developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 1 | From e16f200dc1d2f69efc78c7c55af0d7b410a981f9 Mon Sep 17 00:00:00 2001 |
| 2 | From: Glenn Strauss <gstrauss@gluelogic.com> |
| 3 | Date: Tue, 5 Jul 2022 02:49:50 -0400 |
| 4 | Subject: [PATCH 1/7] mbedtls: TLS/crypto option (initial port) |
| 5 | |
| 6 | Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com> |
| 7 | --- |
| 8 | hostapd/Makefile | 91 + |
| 9 | hostapd/defconfig | 15 +- |
| 10 | src/crypto/crypto_mbedtls.c | 4043 +++++++++++++++++ |
| 11 | src/crypto/tls_mbedtls.c | 3313 ++++++++++++++ |
| 12 | .../build/build-wpa_supplicant-mbedtls.config | 24 + |
| 13 | tests/hwsim/example-hostapd.config | 4 + |
| 14 | tests/hwsim/example-wpa_supplicant.config | 4 + |
| 15 | wpa_supplicant/Makefile | 74 + |
| 16 | wpa_supplicant/defconfig | 6 +- |
| 17 | 9 files changed, 7571 insertions(+), 3 deletions(-) |
| 18 | create mode 100644 src/crypto/crypto_mbedtls.c |
| 19 | create mode 100644 src/crypto/tls_mbedtls.c |
| 20 | create mode 100644 tests/build/build-wpa_supplicant-mbedtls.config |
| 21 | |
| 22 | --- a/hostapd/Makefile |
| 23 | +++ b/hostapd/Makefile |
| 24 | @@ -745,6 +745,40 @@ endif |
| 25 | CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" |
| 26 | endif |
| 27 | |
| 28 | +ifeq ($(CONFIG_TLS), mbedtls) |
| 29 | +ifndef CONFIG_CRYPTO |
| 30 | +CONFIG_CRYPTO=mbedtls |
| 31 | +endif |
| 32 | +ifdef TLS_FUNCS |
| 33 | +OBJS += ../src/crypto/tls_mbedtls.o |
| 34 | +LIBS += -lmbedtls |
| 35 | +ifndef CONFIG_DPP |
| 36 | +LIBS += -lmbedx509 |
| 37 | +endif |
| 38 | +endif |
| 39 | +OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o |
| 40 | +HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o |
| 41 | +SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o |
| 42 | +ifdef NEED_FIPS186_2_PRF |
| 43 | +OBJS += ../src/crypto/fips_prf_internal.o |
| 44 | +SHA1OBJS += ../src/crypto/sha1-internal.o |
| 45 | +endif |
| 46 | +ifeq ($(CONFIG_CRYPTO), mbedtls) |
| 47 | +ifdef CONFIG_DPP |
| 48 | +LIBS += -lmbedx509 |
| 49 | +LIBS_h += -lmbedx509 |
| 50 | +LIBS_n += -lmbedx509 |
| 51 | +LIBS_s += -lmbedx509 |
| 52 | +endif |
| 53 | +LIBS += -lmbedcrypto |
| 54 | +LIBS_h += -lmbedcrypto |
| 55 | +LIBS_n += -lmbedcrypto |
| 56 | +LIBS_s += -lmbedcrypto |
| 57 | +# XXX: create a config option? |
| 58 | +CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 |
| 59 | +endif |
| 60 | +endif |
| 61 | + |
| 62 | ifeq ($(CONFIG_TLS), gnutls) |
| 63 | ifndef CONFIG_CRYPTO |
| 64 | # default to libgcrypt |
| 65 | @@ -924,9 +958,11 @@ endif |
| 66 | |
| 67 | ifneq ($(CONFIG_TLS), openssl) |
| 68 | ifneq ($(CONFIG_TLS), wolfssl) |
| 69 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 70 | AESOBJS += ../src/crypto/aes-wrap.o |
| 71 | endif |
| 72 | endif |
| 73 | +endif |
| 74 | ifdef NEED_AES_EAX |
| 75 | AESOBJS += ../src/crypto/aes-eax.o |
| 76 | NEED_AES_CTR=y |
| 77 | @@ -936,38 +972,48 @@ AESOBJS += ../src/crypto/aes-siv.o |
| 78 | NEED_AES_CTR=y |
| 79 | endif |
| 80 | ifdef NEED_AES_CTR |
| 81 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 82 | AESOBJS += ../src/crypto/aes-ctr.o |
| 83 | endif |
| 84 | +endif |
| 85 | ifdef NEED_AES_ENCBLOCK |
| 86 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 87 | AESOBJS += ../src/crypto/aes-encblock.o |
| 88 | endif |
| 89 | +endif |
| 90 | ifneq ($(CONFIG_TLS), openssl) |
| 91 | ifneq ($(CONFIG_TLS), linux) |
| 92 | ifneq ($(CONFIG_TLS), wolfssl) |
| 93 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 94 | AESOBJS += ../src/crypto/aes-omac1.o |
| 95 | endif |
| 96 | endif |
| 97 | endif |
| 98 | +endif |
| 99 | ifdef NEED_AES_UNWRAP |
| 100 | ifneq ($(CONFIG_TLS), openssl) |
| 101 | ifneq ($(CONFIG_TLS), linux) |
| 102 | ifneq ($(CONFIG_TLS), wolfssl) |
| 103 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 104 | NEED_AES_DEC=y |
| 105 | AESOBJS += ../src/crypto/aes-unwrap.o |
| 106 | endif |
| 107 | endif |
| 108 | endif |
| 109 | endif |
| 110 | +endif |
| 111 | ifdef NEED_AES_CBC |
| 112 | NEED_AES_DEC=y |
| 113 | ifneq ($(CONFIG_TLS), openssl) |
| 114 | ifneq ($(CONFIG_TLS), linux) |
| 115 | ifneq ($(CONFIG_TLS), wolfssl) |
| 116 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 117 | AESOBJS += ../src/crypto/aes-cbc.o |
| 118 | endif |
| 119 | endif |
| 120 | endif |
| 121 | endif |
| 122 | +endif |
| 123 | ifdef NEED_AES_DEC |
| 124 | ifdef CONFIG_INTERNAL_AES |
| 125 | AESOBJS += ../src/crypto/aes-internal-dec.o |
| 126 | @@ -982,12 +1028,16 @@ ifneq ($(CONFIG_TLS), openssl) |
| 127 | ifneq ($(CONFIG_TLS), linux) |
| 128 | ifneq ($(CONFIG_TLS), gnutls) |
| 129 | ifneq ($(CONFIG_TLS), wolfssl) |
| 130 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 131 | SHA1OBJS += ../src/crypto/sha1.o |
| 132 | endif |
| 133 | endif |
| 134 | endif |
| 135 | endif |
| 136 | +endif |
| 137 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 138 | SHA1OBJS += ../src/crypto/sha1-prf.o |
| 139 | +endif |
| 140 | ifdef CONFIG_INTERNAL_SHA1 |
| 141 | SHA1OBJS += ../src/crypto/sha1-internal.o |
| 142 | ifdef NEED_FIPS186_2_PRF |
| 143 | @@ -996,16 +1046,22 @@ endif |
| 144 | endif |
| 145 | ifneq ($(CONFIG_TLS), openssl) |
| 146 | ifneq ($(CONFIG_TLS), wolfssl) |
| 147 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 148 | SHA1OBJS += ../src/crypto/sha1-pbkdf2.o |
| 149 | endif |
| 150 | endif |
| 151 | +endif |
| 152 | ifdef NEED_T_PRF |
| 153 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 154 | SHA1OBJS += ../src/crypto/sha1-tprf.o |
| 155 | endif |
| 156 | +endif |
| 157 | ifdef NEED_TLS_PRF |
| 158 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 159 | SHA1OBJS += ../src/crypto/sha1-tlsprf.o |
| 160 | endif |
| 161 | endif |
| 162 | +endif |
| 163 | |
| 164 | ifdef NEED_SHA1 |
| 165 | OBJS += $(SHA1OBJS) |
| 166 | @@ -1015,11 +1071,13 @@ ifneq ($(CONFIG_TLS), openssl) |
| 167 | ifneq ($(CONFIG_TLS), linux) |
| 168 | ifneq ($(CONFIG_TLS), gnutls) |
| 169 | ifneq ($(CONFIG_TLS), wolfssl) |
| 170 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 171 | OBJS += ../src/crypto/md5.o |
| 172 | endif |
| 173 | endif |
| 174 | endif |
| 175 | endif |
| 176 | +endif |
| 177 | |
| 178 | ifdef NEED_MD5 |
| 179 | ifdef CONFIG_INTERNAL_MD5 |
| 180 | @@ -1058,56 +1116,81 @@ ifneq ($(CONFIG_TLS), openssl) |
| 181 | ifneq ($(CONFIG_TLS), linux) |
| 182 | ifneq ($(CONFIG_TLS), gnutls) |
| 183 | ifneq ($(CONFIG_TLS), wolfssl) |
| 184 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 185 | OBJS += ../src/crypto/sha256.o |
| 186 | endif |
| 187 | endif |
| 188 | endif |
| 189 | endif |
| 190 | +endif |
| 191 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 192 | OBJS += ../src/crypto/sha256-prf.o |
| 193 | +endif |
| 194 | ifdef CONFIG_INTERNAL_SHA256 |
| 195 | OBJS += ../src/crypto/sha256-internal.o |
| 196 | endif |
| 197 | ifdef NEED_TLS_PRF_SHA256 |
| 198 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 199 | OBJS += ../src/crypto/sha256-tlsprf.o |
| 200 | endif |
| 201 | +endif |
| 202 | ifdef NEED_TLS_PRF_SHA384 |
| 203 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 204 | OBJS += ../src/crypto/sha384-tlsprf.o |
| 205 | endif |
| 206 | +endif |
| 207 | ifdef NEED_HMAC_SHA256_KDF |
| 208 | +CFLAGS += -DCONFIG_HMAC_SHA256_KDF |
| 209 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 210 | OBJS += ../src/crypto/sha256-kdf.o |
| 211 | endif |
| 212 | +endif |
| 213 | ifdef NEED_HMAC_SHA384_KDF |
| 214 | +CFLAGS += -DCONFIG_HMAC_SHA384_KDF |
| 215 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 216 | OBJS += ../src/crypto/sha384-kdf.o |
| 217 | endif |
| 218 | +endif |
| 219 | ifdef NEED_HMAC_SHA512_KDF |
| 220 | +CFLAGS += -DCONFIG_HMAC_SHA512_KDF |
| 221 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 222 | OBJS += ../src/crypto/sha512-kdf.o |
| 223 | endif |
| 224 | +endif |
| 225 | ifdef NEED_SHA384 |
| 226 | CFLAGS += -DCONFIG_SHA384 |
| 227 | ifneq ($(CONFIG_TLS), openssl) |
| 228 | ifneq ($(CONFIG_TLS), linux) |
| 229 | ifneq ($(CONFIG_TLS), gnutls) |
| 230 | ifneq ($(CONFIG_TLS), wolfssl) |
| 231 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 232 | OBJS += ../src/crypto/sha384.o |
| 233 | endif |
| 234 | endif |
| 235 | endif |
| 236 | endif |
| 237 | +endif |
| 238 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 239 | OBJS += ../src/crypto/sha384-prf.o |
| 240 | endif |
| 241 | +endif |
| 242 | ifdef NEED_SHA512 |
| 243 | CFLAGS += -DCONFIG_SHA512 |
| 244 | ifneq ($(CONFIG_TLS), openssl) |
| 245 | ifneq ($(CONFIG_TLS), linux) |
| 246 | ifneq ($(CONFIG_TLS), gnutls) |
| 247 | ifneq ($(CONFIG_TLS), wolfssl) |
| 248 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 249 | OBJS += ../src/crypto/sha512.o |
| 250 | endif |
| 251 | endif |
| 252 | endif |
| 253 | endif |
| 254 | +endif |
| 255 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 256 | OBJS += ../src/crypto/sha512-prf.o |
| 257 | endif |
| 258 | +endif |
| 259 | |
| 260 | ifdef CONFIG_INTERNAL_SHA384 |
| 261 | CFLAGS += -DCONFIG_INTERNAL_SHA384 |
| 262 | @@ -1152,11 +1235,13 @@ HOBJS += $(SHA1OBJS) |
| 263 | ifneq ($(CONFIG_TLS), openssl) |
| 264 | ifneq ($(CONFIG_TLS), linux) |
| 265 | ifneq ($(CONFIG_TLS), wolfssl) |
| 266 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 267 | HOBJS += ../src/crypto/md5.o |
| 268 | endif |
| 269 | endif |
| 270 | endif |
| 271 | endif |
| 272 | +endif |
| 273 | |
| 274 | ifdef CONFIG_RADIUS_SERVER |
| 275 | CFLAGS += -DRADIUS_SERVER |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 276 | @@ -1329,7 +1414,9 @@ NOBJS += ../src/utils/trace.o |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 277 | endif |
| 278 | |
| 279 | HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o |
| 280 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 281 | HOBJS += ../src/crypto/aes-encblock.o |
| 282 | +endif |
| 283 | ifdef CONFIG_INTERNAL_AES |
| 284 | HOBJS += ../src/crypto/aes-internal.o |
| 285 | HOBJS += ../src/crypto/aes-internal-enc.o |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 286 | @@ -1352,13 +1439,17 @@ SOBJS += ../src/common/sae.o |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 287 | SOBJS += ../src/common/sae_pk.o |
| 288 | SOBJS += ../src/common/dragonfly.o |
| 289 | SOBJS += $(AESOBJS) |
| 290 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 291 | SOBJS += ../src/crypto/sha256-prf.o |
| 292 | SOBJS += ../src/crypto/sha384-prf.o |
| 293 | SOBJS += ../src/crypto/sha512-prf.o |
| 294 | +endif |
| 295 | SOBJS += ../src/crypto/dh_groups.o |
| 296 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 297 | SOBJS += ../src/crypto/sha256-kdf.o |
| 298 | SOBJS += ../src/crypto/sha384-kdf.o |
| 299 | SOBJS += ../src/crypto/sha512-kdf.o |
| 300 | +endif |
| 301 | |
| 302 | _OBJS_VAR := NOBJS |
| 303 | include ../src/objs.mk |
| 304 | --- a/hostapd/defconfig |
| 305 | +++ b/hostapd/defconfig |
| 306 | @@ -6,9 +6,21 @@ |
| 307 | # just setting VARIABLE=n is not disabling that variable. |
| 308 | # |
| 309 | # This file is included in Makefile, so variables like CFLAGS and LIBS can also |
| 310 | -# be modified from here. In most cass, these lines should use += in order not |
| 311 | +# be modified from here. In most cases, these lines should use += in order not |
| 312 | # to override previous values of the variables. |
| 313 | |
| 314 | + |
| 315 | +# Uncomment following two lines and fix the paths if you have installed TLS |
| 316 | +# libraries in a non-default location |
| 317 | +#CFLAGS += -I/usr/local/openssl/include |
| 318 | +#LIBS += -L/usr/local/openssl/lib |
| 319 | + |
| 320 | +# Some Red Hat versions seem to include kerberos header files from OpenSSL, but |
| 321 | +# the kerberos files are not in the default include path. Following line can be |
| 322 | +# used to fix build issues on such systems (krb5.h not found). |
| 323 | +#CFLAGS += -I/usr/include/kerberos |
| 324 | + |
| 325 | + |
| 326 | # Driver interface for Host AP driver |
| 327 | CONFIG_DRIVER_HOSTAP=y |
| 328 | |
| 329 | @@ -278,6 +290,7 @@ CONFIG_IPV6=y |
| 330 | # openssl = OpenSSL (default) |
| 331 | # gnutls = GnuTLS |
| 332 | # internal = Internal TLSv1 implementation (experimental) |
| 333 | +# mbedtls = mbed TLS |
| 334 | # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental) |
| 335 | # none = Empty template |
| 336 | #CONFIG_TLS=openssl |
| 337 | --- /dev/null |
| 338 | +++ b/src/crypto/crypto_mbedtls.c |
| 339 | @@ -0,0 +1,4043 @@ |
| 340 | +/* |
| 341 | + * crypto wrapper functions for mbed TLS |
| 342 | + * |
| 343 | + * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com> |
| 344 | + * SPDX-License-Identifier: BSD-3-Clause |
| 345 | + */ |
| 346 | + |
| 347 | +#include "utils/includes.h" |
| 348 | +#include "utils/common.h" |
| 349 | + |
| 350 | +#include <mbedtls/version.h> |
| 351 | +#include <mbedtls/entropy.h> |
| 352 | +#include <mbedtls/ctr_drbg.h> |
| 353 | +#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */ |
| 354 | +#include <mbedtls/asn1.h> |
| 355 | +#include <mbedtls/asn1write.h> |
| 356 | +#include <mbedtls/aes.h> |
| 357 | +#include <mbedtls/md.h> |
| 358 | +#include <mbedtls/md5.h> |
| 359 | +#include <mbedtls/sha1.h> |
| 360 | +#include <mbedtls/sha256.h> |
| 361 | +#include <mbedtls/sha512.h> |
| 362 | + |
| 363 | +#ifndef MBEDTLS_PRIVATE |
| 364 | +#define MBEDTLS_PRIVATE(x) x |
| 365 | +#endif |
| 366 | + |
| 367 | +/* hostapd/wpa_supplicant provides forced_memzero(), |
| 368 | + * but prefer mbedtls_platform_zeroize() */ |
| 369 | +#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz) |
| 370 | + |
| 371 | +#ifndef __has_attribute |
| 372 | +#define __has_attribute(x) 0 |
| 373 | +#endif |
| 374 | + |
| 375 | +#ifndef __GNUC_PREREQ |
| 376 | +#define __GNUC_PREREQ(maj,min) 0 |
| 377 | +#endif |
| 378 | + |
| 379 | +#ifndef __attribute_cold__ |
| 380 | +#if __has_attribute(cold) \ |
| 381 | + || __GNUC_PREREQ(4,3) |
| 382 | +#define __attribute_cold__ __attribute__((__cold__)) |
| 383 | +#else |
| 384 | +#define __attribute_cold__ |
| 385 | +#endif |
| 386 | +#endif |
| 387 | + |
| 388 | +#ifndef __attribute_noinline__ |
| 389 | +#if __has_attribute(noinline) \ |
| 390 | + || __GNUC_PREREQ(3,1) |
| 391 | +#define __attribute_noinline__ __attribute__((__noinline__)) |
| 392 | +#else |
| 393 | +#define __attribute_noinline__ |
| 394 | +#endif |
| 395 | +#endif |
| 396 | + |
| 397 | +#include "crypto.h" |
| 398 | +#include "aes_wrap.h" |
| 399 | +#include "aes.h" |
| 400 | +#include "md5.h" |
| 401 | +#include "sha1.h" |
| 402 | +#include "sha256.h" |
| 403 | +#include "sha384.h" |
| 404 | +#include "sha512.h" |
| 405 | + |
| 406 | + |
| 407 | +/* |
| 408 | + * selective code inclusion based on preprocessor defines |
| 409 | + * |
| 410 | + * future: additional code could be wrapped with preprocessor checks if |
| 411 | + * wpa_supplicant/Makefile and hostap/Makefile were more consistent with |
| 412 | + * setting preprocessor defines for named groups of functionality |
| 413 | + */ |
| 414 | + |
| 415 | +#if defined(CONFIG_FIPS) |
| 416 | +#undef MBEDTLS_MD4_C /* omit md4_vector() */ |
| 417 | +#undef MBEDTLS_MD5_C /* omit md5_vector() hmac_md5_vector() hmac_md5() */ |
| 418 | +#undef MBEDTLS_DES_C /* omit des_encrypt() */ |
| 419 | +#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */ |
| 420 | +#define CRYPTO_MBEDTLS_CONFIG_FIPS |
| 421 | +#endif |
| 422 | + |
| 423 | +#if !defined(CONFIG_FIPS) |
| 424 | +#if defined(EAP_PWD) \ |
| 425 | + || defined(EAP_LEAP) || defined(EAP_LEAP_DYNAMIC) \ |
| 426 | + || defined(EAP_TTLS) || defined(EAP_TTLS_DYNAMIC) \ |
| 427 | + || defined(EAP_MSCHAPv2) || defined(EAP_MSCHAPv2_DYNAMIC) \ |
| 428 | + || defined(EAP_SERVER_MSCHAPV2) |
| 429 | +#ifndef MBEDTLS_MD4_C /* (MD4 not in mbedtls 3.x) */ |
| 430 | +#include "md4-internal.c"/* pull in hostap local implementation */ |
| 431 | +#endif /* md4_vector() */ |
| 432 | +#else |
| 433 | +#undef MBEDTLS_MD4_C /* omit md4_vector() */ |
| 434 | +#endif |
| 435 | +#endif |
| 436 | + |
| 437 | +#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_NO_WPA) |
| 438 | +#ifndef MBEDTLS_ARC4_C /* (RC4 not in mbedtls 3.x) */ |
| 439 | +#include "rc4.c" /* pull in hostap local implementation */ |
| 440 | +#endif /* rc4_skip() */ |
| 441 | +#else |
| 442 | +#undef MBEDTLS_ARC4_C /* omit rc4_skip() */ |
| 443 | +#endif |
| 444 | + |
| 445 | +#if defined(CONFIG_MACSEC) \ |
| 446 | + || defined(CONFIG_NO_RADIUS) \ |
| 447 | + || defined(CONFIG_IEEE80211R) \ |
| 448 | + || defined(EAP_SERVER_FAST) \ |
| 449 | + || defined(EAP_SERVER_TEAP) \ |
| 450 | + || !defined(CONFIG_NO_WPA) |
| 451 | + /* aes_wrap() aes_unwrap() */ |
| 452 | +#else |
| 453 | +#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */ |
| 454 | +#endif |
| 455 | + |
| 456 | +#if !defined(CONFIG_SHA256) |
| 457 | +#undef MBEDTLS_SHA256_C |
| 458 | +#endif |
| 459 | + |
| 460 | +#if !defined(CONFIG_SHA384) && !defined(CONFIG_SHA512) |
| 461 | +#undef MBEDTLS_SHA512_C |
| 462 | +#endif |
| 463 | + |
| 464 | +#if defined(CONFIG_HMAC_SHA256_KDF) |
| 465 | +#define CRYPTO_MBEDTLS_HMAC_KDF_SHA256 |
| 466 | +#endif |
| 467 | +#if defined(CONFIG_HMAC_SHA384_KDF) |
| 468 | +#define CRYPTO_MBEDTLS_HMAC_KDF_SHA384 |
| 469 | +#endif |
| 470 | +#if defined(CONFIG_HMAC_SHA512_KDF) |
| 471 | +#define CRYPTO_MBEDTLS_HMAC_KDF_SHA512 |
| 472 | +#endif |
| 473 | + |
| 474 | +#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \ |
| 475 | + || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST) |
| 476 | +#define CRYPTO_MBEDTLS_SHA1_T_PRF |
| 477 | +#endif |
| 478 | + |
| 479 | +#if defined(CONFIG_DES) |
| 480 | +#define CRYPTO_MBEDTLS_DES_ENCRYPT |
| 481 | +#endif /* des_encrypt() */ |
| 482 | + |
| 483 | +#if !defined(CONFIG_NO_PBKDF2) |
| 484 | +#define CRYPTO_MBEDTLS_PBKDF2_SHA1 |
| 485 | +#endif /* pbkdf2_sha1() */ |
| 486 | + |
| 487 | +#if defined(EAP_IKEV2) \ |
| 488 | + || defined(EAP_IKEV2_DYNAMIC) \ |
| 489 | + || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ |
| 490 | +#define CRYPTO_MBEDTLS_CRYPTO_CIPHER |
| 491 | +#endif /* crypto_cipher_*() */ |
| 492 | + |
| 493 | +#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ |
| 494 | +#define CRYPTO_MBEDTLS_CRYPTO_HASH |
| 495 | +#endif /* crypto_hash_*() */ |
| 496 | + |
| 497 | +#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ \ |
| 498 | + || defined(CONFIG_SAE) /* CONFIG_SAE=y */ |
| 499 | +#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM |
| 500 | +#endif /* crypto_bignum_*() */ |
| 501 | + |
| 502 | +#if defined(EAP_PWD) /* CONFIG_EAP_PWD=y */ \ |
| 503 | + || defined(EAP_EKE) /* CONFIG_EAP_EKE=y */ \ |
| 504 | + || defined(EAP_EKE_DYNAMIC) /* CONFIG_EAP_EKE=y */ \ |
| 505 | + || defined(EAP_SERVER_EKE) /* CONFIG_EAP_EKE=y */ \ |
| 506 | + || defined(EAP_IKEV2) /* CONFIG_EAP_IKEV2y */ \ |
| 507 | + || defined(EAP_IKEV2_DYNAMIC)/* CONFIG_EAP_IKEV2=y */ \ |
| 508 | + || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ \ |
| 509 | + || defined(CONFIG_SAE) /* CONFIG_SAE=y */ \ |
| 510 | + || defined(CONFIG_WPS) /* CONFIG_WPS=y */ |
| 511 | +#define CRYPTO_MBEDTLS_CRYPTO_DH |
| 512 | +#if defined(CONFIG_WPS_NFC) |
| 513 | +#define CRYPTO_MBEDTLS_DH5_INIT_FIXED |
| 514 | +#endif /* dh5_init_fixed() */ |
| 515 | +#endif /* crypto_dh_*() */ |
| 516 | + |
| 517 | +#if !defined(CONFIG_NO_WPA) /* CONFIG_NO_WPA= */ |
| 518 | +#define CRYPTO_MBEDTLS_CRYPTO_ECDH |
| 519 | +#endif /* crypto_ecdh_*() */ |
| 520 | + |
| 521 | +#if defined(CONFIG_ECC) |
| 522 | +#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM |
| 523 | +#define CRYPTO_MBEDTLS_CRYPTO_EC |
| 524 | +#endif /* crypto_ec_*() crypto_ec_key_*() */ |
| 525 | + |
| 526 | +#if defined(CONFIG_DPP) /* CONFIG_DPP=y */ |
| 527 | +#define CRYPTO_MBEDTLS_CRYPTO_EC_DPP /* extra for DPP */ |
| 528 | +#define CRYPTO_MBEDTLS_CRYPTO_CSR |
| 529 | +#endif /* crypto_csr_*() */ |
| 530 | + |
| 531 | +#if defined(CONFIG_DPP3) /* CONFIG_DPP3=y */ |
| 532 | +#define CRYPTO_MBEDTLS_CRYPTO_HPKE |
| 533 | +#endif |
| 534 | + |
| 535 | +#if defined(CONFIG_DPP2) /* CONFIG_DPP2=y */ |
| 536 | +#define CRYPTO_MBEDTLS_CRYPTO_PKCS7 |
| 537 | +#endif /* crypto_pkcs7_*() */ |
| 538 | + |
| 539 | +#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \ |
| 540 | + || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA) \ |
| 541 | + || defined(CONFIG_AP) || defined(HOSTAPD) |
| 542 | +/* CONFIG_EAP_SIM=y CONFIG_EAP_AKA=y CONFIG_AP=y HOSTAPD */ |
| 543 | +#if defined(CRYPTO_RSA_OAEP_SHA256) |
| 544 | +#define CRYPTO_MBEDTLS_CRYPTO_RSA |
| 545 | +#endif |
| 546 | +#endif /* crypto_rsa_*() */ |
| 547 | + |
| 548 | + |
| 549 | +static int ctr_drbg_init_state; |
| 550 | +static mbedtls_ctr_drbg_context ctr_drbg; |
| 551 | +static mbedtls_entropy_context entropy; |
| 552 | + |
| 553 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM |
| 554 | +#include <mbedtls/bignum.h> |
| 555 | +static mbedtls_mpi mpi_sw_A; |
| 556 | +#endif |
| 557 | + |
| 558 | +__attribute_cold__ |
| 559 | +__attribute_noinline__ |
| 560 | +static mbedtls_ctr_drbg_context * ctr_drbg_init(void) |
| 561 | +{ |
| 562 | + mbedtls_ctr_drbg_init(&ctr_drbg); |
| 563 | + mbedtls_entropy_init(&entropy); |
| 564 | + if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, |
| 565 | + NULL, 0)) { |
| 566 | + wpa_printf(MSG_ERROR, "Init of random number generator failed"); |
| 567 | + /* XXX: abort? */ |
| 568 | + } |
| 569 | + else |
| 570 | + ctr_drbg_init_state = 1; |
| 571 | + |
| 572 | + return &ctr_drbg; |
| 573 | +} |
| 574 | + |
| 575 | +__attribute_cold__ |
| 576 | +void crypto_unload(void) |
| 577 | +{ |
| 578 | + if (ctr_drbg_init_state) { |
| 579 | + mbedtls_ctr_drbg_free(&ctr_drbg); |
| 580 | + mbedtls_entropy_free(&entropy); |
| 581 | + #ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM |
| 582 | + mbedtls_mpi_free(&mpi_sw_A); |
| 583 | + #endif |
| 584 | + ctr_drbg_init_state = 0; |
| 585 | + } |
| 586 | +} |
| 587 | + |
| 588 | +/* init ctr_drbg on first use |
| 589 | + * crypto_global_init() and crypto_global_deinit() are not available here |
| 590 | + * (available only when CONFIG_TLS=internal, which is not CONFIG_TLS=mbedtls) */ |
| 591 | +mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/ |
| 592 | +inline |
| 593 | +mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void) |
| 594 | +{ |
| 595 | + return ctr_drbg_init_state ? &ctr_drbg : ctr_drbg_init(); |
| 596 | +} |
| 597 | + |
| 598 | +#ifdef CRYPTO_MBEDTLS_CONFIG_FIPS |
| 599 | +int crypto_get_random(void *buf, size_t len) |
| 600 | +{ |
| 601 | + return mbedtls_ctr_drbg_random(crypto_mbedtls_ctr_drbg(),buf,len) ? -1 : 0; |
| 602 | +} |
| 603 | +#endif |
| 604 | + |
| 605 | + |
| 606 | +#if 1 |
| 607 | + |
| 608 | +/* tradeoff: slightly smaller code size here at cost of slight increase |
| 609 | + * in instructions and function calls at runtime versus the expanded |
| 610 | + * per-message-digest code that follows in #else (~0.5 kib .text larger) */ |
| 611 | + |
| 612 | +__attribute_noinline__ |
| 613 | +static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len, |
| 614 | + u8 *mac, mbedtls_md_type_t md_type) |
| 615 | +{ |
| 616 | + mbedtls_md_context_t ctx; |
| 617 | + mbedtls_md_init(&ctx); |
| 618 | + if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){ |
| 619 | + mbedtls_md_free(&ctx); |
| 620 | + return -1; |
| 621 | + } |
| 622 | + mbedtls_md_starts(&ctx); |
| 623 | + for (size_t i = 0; i < num_elem; ++i) |
| 624 | + mbedtls_md_update(&ctx, addr[i], len[i]); |
| 625 | + mbedtls_md_finish(&ctx, mac); |
| 626 | + mbedtls_md_free(&ctx); |
| 627 | + return 0; |
| 628 | +} |
| 629 | + |
| 630 | +#ifdef MBEDTLS_SHA512_C |
| 631 | +int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 632 | +{ |
| 633 | + return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA512); |
| 634 | +} |
| 635 | + |
| 636 | +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 637 | +{ |
| 638 | + return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA384); |
| 639 | +} |
| 640 | +#endif |
| 641 | + |
| 642 | +#ifdef MBEDTLS_SHA256_C |
| 643 | +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 644 | +{ |
| 645 | + return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA256); |
| 646 | +} |
| 647 | +#endif |
| 648 | + |
| 649 | +#ifdef MBEDTLS_SHA1_C |
| 650 | +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 651 | +{ |
| 652 | + return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA1); |
| 653 | +} |
| 654 | +#endif |
| 655 | + |
| 656 | +#ifdef MBEDTLS_MD5_C |
| 657 | +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 658 | +{ |
| 659 | + return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD5); |
| 660 | +} |
| 661 | +#endif |
| 662 | + |
| 663 | +#ifdef MBEDTLS_MD4_C |
| 664 | +#include <mbedtls/md4.h> |
| 665 | +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 666 | +{ |
| 667 | + return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD4); |
| 668 | +} |
| 669 | +#endif |
| 670 | + |
| 671 | +#else /* expanded per-message-digest functions */ |
| 672 | + |
| 673 | +#ifdef MBEDTLS_SHA512_C |
| 674 | +#include <mbedtls/sha512.h> |
| 675 | +__attribute_noinline__ |
| 676 | +static int sha384_512_vector(size_t num_elem, const u8 *addr[], |
| 677 | + const size_t *len, u8 *mac, int is384) |
| 678 | +{ |
| 679 | + struct mbedtls_sha512_context ctx; |
| 680 | + mbedtls_sha512_init(&ctx); |
| 681 | + #if MBEDTLS_VERSION_MAJOR >= 3 |
| 682 | + mbedtls_sha512_starts(&ctx, is384); |
| 683 | + for (size_t i = 0; i < num_elem; ++i) |
| 684 | + mbedtls_sha512_update(&ctx, addr[i], len[i]); |
| 685 | + mbedtls_sha512_finish(&ctx, mac); |
| 686 | + #else |
| 687 | + mbedtls_sha512_starts_ret(&ctx, is384); |
| 688 | + for (size_t i = 0; i < num_elem; ++i) |
| 689 | + mbedtls_sha512_update_ret(&ctx, addr[i], len[i]); |
| 690 | + mbedtls_sha512_finish_ret(&ctx, mac); |
| 691 | + #endif |
| 692 | + mbedtls_sha512_free(&ctx); |
| 693 | + return 0; |
| 694 | +} |
| 695 | + |
| 696 | +int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 697 | +{ |
| 698 | + return sha384_512_vector(num_elem, addr, len, mac, 0); |
| 699 | +} |
| 700 | + |
| 701 | +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 702 | +{ |
| 703 | + return sha384_512_vector(num_elem, addr, len, mac, 1); |
| 704 | +} |
| 705 | +#endif |
| 706 | + |
| 707 | +#ifdef MBEDTLS_SHA256_C |
| 708 | +#include <mbedtls/sha256.h> |
| 709 | +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 710 | +{ |
| 711 | + struct mbedtls_sha256_context ctx; |
| 712 | + mbedtls_sha256_init(&ctx); |
| 713 | + #if MBEDTLS_VERSION_MAJOR >= 3 |
| 714 | + mbedtls_sha256_starts(&ctx, 0); |
| 715 | + for (size_t i = 0; i < num_elem; ++i) |
| 716 | + mbedtls_sha256_update(&ctx, addr[i], len[i]); |
| 717 | + mbedtls_sha256_finish(&ctx, mac); |
| 718 | + #else |
| 719 | + mbedtls_sha256_starts_ret(&ctx, 0); |
| 720 | + for (size_t i = 0; i < num_elem; ++i) |
| 721 | + mbedtls_sha256_update_ret(&ctx, addr[i], len[i]); |
| 722 | + mbedtls_sha256_finish_ret(&ctx, mac); |
| 723 | + #endif |
| 724 | + mbedtls_sha256_free(&ctx); |
| 725 | + return 0; |
| 726 | +} |
| 727 | +#endif |
| 728 | + |
| 729 | +#ifdef MBEDTLS_SHA1_C |
| 730 | +#include <mbedtls/sha1.h> |
| 731 | +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 732 | +{ |
| 733 | + struct mbedtls_sha1_context ctx; |
| 734 | + mbedtls_sha1_init(&ctx); |
| 735 | + #if MBEDTLS_VERSION_MAJOR >= 3 |
| 736 | + mbedtls_sha1_starts(&ctx); |
| 737 | + for (size_t i = 0; i < num_elem; ++i) |
| 738 | + mbedtls_sha1_update(&ctx, addr[i], len[i]); |
| 739 | + mbedtls_sha1_finish(&ctx, mac); |
| 740 | + #else |
| 741 | + mbedtls_sha1_starts_ret(&ctx); |
| 742 | + for (size_t i = 0; i < num_elem; ++i) |
| 743 | + mbedtls_sha1_update_ret(&ctx, addr[i], len[i]); |
| 744 | + mbedtls_sha1_finish_ret(&ctx, mac); |
| 745 | + #endif |
| 746 | + mbedtls_sha1_free(&ctx); |
| 747 | + return 0; |
| 748 | +} |
| 749 | +#endif |
| 750 | + |
| 751 | +#ifdef MBEDTLS_MD5_C |
| 752 | +#include <mbedtls/md5.h> |
| 753 | +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 754 | +{ |
| 755 | + struct mbedtls_md5_context ctx; |
| 756 | + mbedtls_md5_init(&ctx); |
| 757 | + #if MBEDTLS_VERSION_MAJOR >= 3 |
| 758 | + mbedtls_md5_starts(&ctx); |
| 759 | + for (size_t i = 0; i < num_elem; ++i) |
| 760 | + mbedtls_md5_update(&ctx, addr[i], len[i]); |
| 761 | + mbedtls_md5_finish(&ctx, mac); |
| 762 | + #else |
| 763 | + mbedtls_md5_starts_ret(&ctx); |
| 764 | + for (size_t i = 0; i < num_elem; ++i) |
| 765 | + mbedtls_md5_update_ret(&ctx, addr[i], len[i]); |
| 766 | + mbedtls_md5_finish_ret(&ctx, mac); |
| 767 | + #endif |
| 768 | + mbedtls_md5_free(&ctx); |
| 769 | + return 0; |
| 770 | +} |
| 771 | +#endif |
| 772 | + |
| 773 | +#ifdef MBEDTLS_MD4_C |
| 774 | +#include <mbedtls/md4.h> |
| 775 | +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) |
| 776 | +{ |
| 777 | + struct mbedtls_md4_context ctx; |
| 778 | + mbedtls_md4_init(&ctx); |
| 779 | + mbedtls_md4_starts_ret(&ctx); |
| 780 | + for (size_t i = 0; i < num_elem; ++i) |
| 781 | + mbedtls_md4_update_ret(&ctx, addr[i], len[i]); |
| 782 | + mbedtls_md4_finish_ret(&ctx, mac); |
| 783 | + mbedtls_md4_free(&ctx); |
| 784 | + return 0; |
| 785 | +} |
| 786 | +#endif |
| 787 | + |
| 788 | +#endif /* expanded per-message-digest functions */ |
| 789 | + |
| 790 | + |
| 791 | +__attribute_noinline__ |
| 792 | +static int hmac_vector(const u8 *key, size_t key_len, size_t num_elem, |
| 793 | + const u8 *addr[], const size_t *len, u8 *mac, |
| 794 | + mbedtls_md_type_t md_type) |
| 795 | +{ |
| 796 | + mbedtls_md_context_t ctx; |
| 797 | + mbedtls_md_init(&ctx); |
| 798 | + if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){ |
| 799 | + mbedtls_md_free(&ctx); |
| 800 | + return -1; |
| 801 | + } |
| 802 | + mbedtls_md_hmac_starts(&ctx, key, key_len); |
| 803 | + for (size_t i = 0; i < num_elem; ++i) |
| 804 | + mbedtls_md_hmac_update(&ctx, addr[i], len[i]); |
| 805 | + mbedtls_md_hmac_finish(&ctx, mac); |
| 806 | + mbedtls_md_free(&ctx); |
| 807 | + return 0; |
| 808 | +} |
| 809 | + |
| 810 | +#ifdef MBEDTLS_SHA512_C |
| 811 | +int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem, |
| 812 | + const u8 *addr[], const size_t *len, u8 *mac) |
| 813 | +{ |
| 814 | + return hmac_vector(key, key_len, num_elem, addr, len, mac, |
| 815 | + MBEDTLS_MD_SHA512); |
| 816 | +} |
| 817 | + |
| 818 | +int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
| 819 | + u8 *mac) |
| 820 | +{ |
| 821 | + return hmac_vector(key, key_len, 1, &data, &data_len, mac, |
| 822 | + MBEDTLS_MD_SHA512); |
| 823 | +} |
| 824 | + |
| 825 | +int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, |
| 826 | + const u8 *addr[], const size_t *len, u8 *mac) |
| 827 | +{ |
| 828 | + return hmac_vector(key, key_len, num_elem, addr, len, mac, |
| 829 | + MBEDTLS_MD_SHA384); |
| 830 | +} |
| 831 | + |
| 832 | +int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
| 833 | + u8 *mac) |
| 834 | +{ |
| 835 | + return hmac_vector(key, key_len, 1, &data, &data_len, mac, |
| 836 | + MBEDTLS_MD_SHA384); |
| 837 | +} |
| 838 | +#endif |
| 839 | + |
| 840 | +#ifdef MBEDTLS_SHA256_C |
| 841 | +int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, |
| 842 | + const u8 *addr[], const size_t *len, u8 *mac) |
| 843 | +{ |
| 844 | + return hmac_vector(key, key_len, num_elem, addr, len, mac, |
| 845 | + MBEDTLS_MD_SHA256); |
| 846 | +} |
| 847 | + |
| 848 | +int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
| 849 | + u8 *mac) |
| 850 | +{ |
| 851 | + return hmac_vector(key, key_len, 1, &data, &data_len, mac, |
| 852 | + MBEDTLS_MD_SHA256); |
| 853 | +} |
| 854 | +#endif |
| 855 | + |
| 856 | +#ifdef MBEDTLS_SHA1_C |
| 857 | +int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, |
| 858 | + const u8 *addr[], const size_t *len, u8 *mac) |
| 859 | +{ |
| 860 | + return hmac_vector(key, key_len, num_elem, addr, len, mac, |
| 861 | + MBEDTLS_MD_SHA1); |
| 862 | +} |
| 863 | + |
| 864 | +int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
| 865 | + u8 *mac) |
| 866 | +{ |
| 867 | + return hmac_vector(key, key_len, 1, &data, &data_len, mac, |
| 868 | + MBEDTLS_MD_SHA1); |
| 869 | +} |
| 870 | +#endif |
| 871 | + |
| 872 | +#ifdef MBEDTLS_MD5_C |
| 873 | +int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, |
| 874 | + const u8 *addr[], const size_t *len, u8 *mac) |
| 875 | +{ |
| 876 | + return hmac_vector(key, key_len, num_elem, addr, len, mac, |
| 877 | + MBEDTLS_MD_MD5); |
| 878 | +} |
| 879 | + |
| 880 | +int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, |
| 881 | + u8 *mac) |
| 882 | +{ |
| 883 | + return hmac_vector(key, key_len, 1, &data, &data_len, mac, |
| 884 | + MBEDTLS_MD_MD5); |
| 885 | +} |
| 886 | +#endif |
| 887 | + |
| 888 | + |
| 889 | +#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) |
| 890 | + |
| 891 | +#if defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA256) \ |
| 892 | + || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA384) \ |
| 893 | + || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA512) |
| 894 | + |
| 895 | +#include <mbedtls/hkdf.h> |
| 896 | + |
| 897 | +/* sha256-kdf.c sha384-kdf.c sha512-kdf.c */ |
| 898 | + |
| 899 | +/* HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869) */ |
| 900 | +/* HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (RFC 5869) */ |
| 901 | +/* HMAC-SHA512 KDF (RFC 5295) and HKDF-Expand(SHA512) (RFC 5869) */ |
| 902 | +__attribute_noinline__ |
| 903 | +static int hmac_kdf_expand(const u8 *prk, size_t prk_len, |
| 904 | + const char *label, const u8 *info, size_t info_len, |
| 905 | + u8 *okm, size_t okm_len, mbedtls_md_type_t md_type) |
| 906 | +{ |
| 907 | + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); |
| 908 | + #ifdef MBEDTLS_HKDF_C |
| 909 | + if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */ |
| 910 | + return mbedtls_hkdf_expand(md_info, prk, prk_len, info, |
| 911 | + info_len, okm, okm_len) ? -1 : 0; |
| 912 | + #endif |
| 913 | + |
| 914 | + const size_t mac_len = mbedtls_md_get_size(md_info); |
| 915 | + /* okm_len must not exceed 255 times hash len (RFC 5869 Section 2.3) */ |
| 916 | + if (okm_len > ((mac_len << 8) - mac_len)) |
| 917 | + return -1; |
| 918 | + |
| 919 | + mbedtls_md_context_t ctx; |
| 920 | + mbedtls_md_init(&ctx); |
| 921 | + if (mbedtls_md_setup(&ctx, md_info, 1) != 0) { |
| 922 | + mbedtls_md_free(&ctx); |
| 923 | + return -1; |
| 924 | + } |
| 925 | + mbedtls_md_hmac_starts(&ctx, prk, prk_len); |
| 926 | + |
| 927 | + u8 iter = 1; |
| 928 | + const u8 *addr[4] = { okm, (const u8 *)label, info, &iter }; |
| 929 | + size_t len[4] = { 0, label ? os_strlen(label)+1 : 0, info_len, 1 }; |
| 930 | + |
| 931 | + for (; okm_len >= mac_len; okm_len -= mac_len, ++iter) { |
| 932 | + for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) |
| 933 | + mbedtls_md_hmac_update(&ctx, addr[i], len[i]); |
| 934 | + mbedtls_md_hmac_finish(&ctx, okm); |
| 935 | + mbedtls_md_hmac_reset(&ctx); |
| 936 | + addr[0] = okm; |
| 937 | + okm += mac_len; |
| 938 | + len[0] = mac_len; /*(include digest in subsequent rounds)*/ |
| 939 | + } |
| 940 | + |
| 941 | + if (okm_len) { |
| 942 | + u8 hash[MBEDTLS_MD_MAX_SIZE]; |
| 943 | + for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) |
| 944 | + mbedtls_md_hmac_update(&ctx, addr[i], len[i]); |
| 945 | + mbedtls_md_hmac_finish(&ctx, hash); |
| 946 | + os_memcpy(okm, hash, okm_len); |
| 947 | + forced_memzero(hash, mac_len); |
| 948 | + } |
| 949 | + |
| 950 | + mbedtls_md_free(&ctx); |
| 951 | + return 0; |
| 952 | +} |
| 953 | + |
| 954 | +#ifdef MBEDTLS_SHA512_C |
| 955 | +#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA512 |
| 956 | +int hmac_sha512_kdf(const u8 *secret, size_t secret_len, |
| 957 | + const char *label, const u8 *seed, size_t seed_len, |
| 958 | + u8 *out, size_t outlen) |
| 959 | +{ |
| 960 | + return hmac_kdf_expand(secret, secret_len, label, seed, seed_len, |
| 961 | + out, outlen, MBEDTLS_MD_SHA512); |
| 962 | +} |
| 963 | +#endif |
| 964 | + |
| 965 | +#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA384 |
| 966 | +int hmac_sha384_kdf(const u8 *secret, size_t secret_len, |
| 967 | + const char *label, const u8 *seed, size_t seed_len, |
| 968 | + u8 *out, size_t outlen) |
| 969 | +{ |
| 970 | + return hmac_kdf_expand(secret, secret_len, label, seed, seed_len, |
| 971 | + out, outlen, MBEDTLS_MD_SHA384); |
| 972 | +} |
| 973 | +#endif |
| 974 | +#endif |
| 975 | + |
| 976 | +#ifdef MBEDTLS_SHA256_C |
| 977 | +#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA256 |
| 978 | +int hmac_sha256_kdf(const u8 *secret, size_t secret_len, |
| 979 | + const char *label, const u8 *seed, size_t seed_len, |
| 980 | + u8 *out, size_t outlen) |
| 981 | +{ |
| 982 | + return hmac_kdf_expand(secret, secret_len, label, seed, seed_len, |
| 983 | + out, outlen, MBEDTLS_MD_SHA256); |
| 984 | +} |
| 985 | +#endif |
| 986 | +#endif |
| 987 | + |
| 988 | +#endif /* CRYPTO_MBEDTLS_HMAC_KDF_* */ |
| 989 | + |
| 990 | + |
| 991 | +/* sha256-prf.c sha384-prf.c sha512-prf.c */ |
| 992 | + |
| 993 | +/* hmac_prf_bits - IEEE Std 802.11ac-2013, 11.6.1.7.2 Key derivation function */ |
| 994 | +__attribute_noinline__ |
| 995 | +static int hmac_prf_bits(const u8 *key, size_t key_len, const char *label, |
| 996 | + const u8 *data, size_t data_len, u8 *buf, |
| 997 | + size_t buf_len_bits, mbedtls_md_type_t md_type) |
| 998 | +{ |
| 999 | + mbedtls_md_context_t ctx; |
| 1000 | + mbedtls_md_init(&ctx); |
| 1001 | + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); |
| 1002 | + if (mbedtls_md_setup(&ctx, md_info, 1) != 0) { |
| 1003 | + mbedtls_md_free(&ctx); |
| 1004 | + return -1; |
| 1005 | + } |
| 1006 | + mbedtls_md_hmac_starts(&ctx, key, key_len); |
| 1007 | + |
| 1008 | + u16 ctr, n_le = host_to_le16(buf_len_bits); |
| 1009 | + const u8 * const addr[] = { (u8 *)&ctr,(u8 *)label,data,(u8 *)&n_le }; |
| 1010 | + const size_t len[] = { 2, os_strlen(label), data_len, 2 }; |
| 1011 | + const size_t mac_len = mbedtls_md_get_size(md_info); |
| 1012 | + size_t buf_len = (buf_len_bits + 7) / 8; |
| 1013 | + for (ctr = 1; buf_len >= mac_len; buf_len -= mac_len, ++ctr) { |
| 1014 | + #if __BYTE_ORDER == __BIG_ENDIAN |
| 1015 | + ctr = host_to_le16(ctr); |
| 1016 | + #endif |
| 1017 | + for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) |
| 1018 | + mbedtls_md_hmac_update(&ctx, addr[i], len[i]); |
| 1019 | + mbedtls_md_hmac_finish(&ctx, buf); |
| 1020 | + mbedtls_md_hmac_reset(&ctx); |
| 1021 | + buf += mac_len; |
| 1022 | + #if __BYTE_ORDER == __BIG_ENDIAN |
| 1023 | + ctr = le_to_host16(ctr); |
| 1024 | + #endif |
| 1025 | + } |
| 1026 | + |
| 1027 | + if (buf_len) { |
| 1028 | + u8 hash[MBEDTLS_MD_MAX_SIZE]; |
| 1029 | + #if __BYTE_ORDER == __BIG_ENDIAN |
| 1030 | + ctr = host_to_le16(ctr); |
| 1031 | + #endif |
| 1032 | + for (size_t i = 0; i < ARRAY_SIZE(addr); ++i) |
| 1033 | + mbedtls_md_hmac_update(&ctx, addr[i], len[i]); |
| 1034 | + mbedtls_md_hmac_finish(&ctx, hash); |
| 1035 | + os_memcpy(buf, hash, buf_len); |
| 1036 | + buf += buf_len; |
| 1037 | + forced_memzero(hash, mac_len); |
| 1038 | + } |
| 1039 | + |
| 1040 | + /* Mask out unused bits in last octet if it does not use all the bits */ |
| 1041 | + if ((buf_len_bits &= 0x7)) |
| 1042 | + buf[-1] &= (u8)(0xff << (8 - buf_len_bits)); |
| 1043 | + |
| 1044 | + mbedtls_md_free(&ctx); |
| 1045 | + return 0; |
| 1046 | +} |
| 1047 | + |
| 1048 | +#ifdef MBEDTLS_SHA512_C |
| 1049 | +int sha512_prf(const u8 *key, size_t key_len, const char *label, |
| 1050 | + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) |
| 1051 | +{ |
| 1052 | + return hmac_prf_bits(key, key_len, label, data, data_len, buf, |
| 1053 | + buf_len * 8, MBEDTLS_MD_SHA512); |
| 1054 | +} |
| 1055 | + |
| 1056 | +int sha384_prf(const u8 *key, size_t key_len, const char *label, |
| 1057 | + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) |
| 1058 | +{ |
| 1059 | + return hmac_prf_bits(key, key_len, label, data, data_len, buf, |
| 1060 | + buf_len * 8, MBEDTLS_MD_SHA384); |
| 1061 | +} |
| 1062 | +#endif |
| 1063 | + |
| 1064 | +#ifdef MBEDTLS_SHA256_C |
| 1065 | +int sha256_prf(const u8 *key, size_t key_len, const char *label, |
| 1066 | + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) |
| 1067 | +{ |
| 1068 | + return hmac_prf_bits(key, key_len, label, data, data_len, buf, |
| 1069 | + buf_len * 8, MBEDTLS_MD_SHA256); |
| 1070 | +} |
| 1071 | + |
| 1072 | +int sha256_prf_bits(const u8 *key, size_t key_len, const char *label, |
| 1073 | + const u8 *data, size_t data_len, u8 *buf, |
| 1074 | + size_t buf_len_bits) |
| 1075 | +{ |
| 1076 | + return hmac_prf_bits(key, key_len, label, data, data_len, buf, |
| 1077 | + buf_len_bits, MBEDTLS_MD_SHA256); |
| 1078 | +} |
| 1079 | +#endif |
| 1080 | + |
| 1081 | +#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */ |
| 1082 | + |
| 1083 | + |
| 1084 | +#ifdef MBEDTLS_SHA1_C |
| 1085 | + |
| 1086 | +/* sha1-prf.c */ |
| 1087 | + |
| 1088 | +/* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) */ |
| 1089 | + |
| 1090 | +int sha1_prf(const u8 *key, size_t key_len, const char *label, |
| 1091 | + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) |
| 1092 | +{ |
| 1093 | + /*(note: algorithm differs from hmac_prf_bits() */ |
| 1094 | + /*(note: smaller code size instead of expanding hmac_sha1_vector() |
| 1095 | + * as is done in hmac_prf_bits(); not expecting large num of loops) */ |
| 1096 | + u8 counter = 0; |
| 1097 | + const u8 *addr[] = { (u8 *)label, data, &counter }; |
| 1098 | + const size_t len[] = { os_strlen(label)+1, data_len, 1 }; |
| 1099 | + |
| 1100 | + for (; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++counter) { |
| 1101 | + if (hmac_sha1_vector(key, key_len, 3, addr, len, buf)) |
| 1102 | + return -1; |
| 1103 | + buf += SHA1_MAC_LEN; |
| 1104 | + } |
| 1105 | + |
| 1106 | + if (buf_len) { |
| 1107 | + u8 hash[SHA1_MAC_LEN]; |
| 1108 | + if (hmac_sha1_vector(key, key_len, 3, addr, len, hash)) |
| 1109 | + return -1; |
| 1110 | + os_memcpy(buf, hash, buf_len); |
| 1111 | + forced_memzero(hash, sizeof(hash)); |
| 1112 | + } |
| 1113 | + |
| 1114 | + return 0; |
| 1115 | +} |
| 1116 | + |
| 1117 | +#ifdef CRYPTO_MBEDTLS_SHA1_T_PRF |
| 1118 | + |
| 1119 | +/* sha1-tprf.c */ |
| 1120 | + |
| 1121 | +/* sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) (RFC 4851,Section 5.5)*/ |
| 1122 | + |
| 1123 | +int sha1_t_prf(const u8 *key, size_t key_len, const char *label, |
| 1124 | + const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len) |
| 1125 | +{ |
| 1126 | + /*(note: algorithm differs from hmac_prf_bits() and hmac_kdf() above)*/ |
| 1127 | + /*(note: smaller code size instead of expanding hmac_sha1_vector() |
| 1128 | + * as is done in hmac_prf_bits(); not expecting large num of loops) */ |
| 1129 | + u8 ctr; |
| 1130 | + u16 olen = host_to_be16(buf_len); |
| 1131 | + const u8 *addr[] = { buf, (u8 *)label, seed, (u8 *)&olen, &ctr }; |
| 1132 | + size_t len[] = { 0, os_strlen(label)+1, seed_len, 2, 1 }; |
| 1133 | + |
| 1134 | + for (ctr = 1; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++ctr) { |
| 1135 | + if (hmac_sha1_vector(key, key_len, 5, addr, len, buf)) |
| 1136 | + return -1; |
| 1137 | + addr[0] = buf; |
| 1138 | + buf += SHA1_MAC_LEN; |
| 1139 | + len[0] = SHA1_MAC_LEN; /*(include digest in subsequent rounds)*/ |
| 1140 | + } |
| 1141 | + |
| 1142 | + if (buf_len) { |
| 1143 | + u8 hash[SHA1_MAC_LEN]; |
| 1144 | + if (hmac_sha1_vector(key, key_len, 5, addr, len, hash)) |
| 1145 | + return -1; |
| 1146 | + os_memcpy(buf, hash, buf_len); |
| 1147 | + forced_memzero(hash, sizeof(hash)); |
| 1148 | + } |
| 1149 | + |
| 1150 | + return 0; |
| 1151 | +} |
| 1152 | + |
| 1153 | +#endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */ |
| 1154 | + |
| 1155 | +#endif /* MBEDTLS_SHA1_C */ |
| 1156 | + |
| 1157 | + |
| 1158 | +#ifdef CRYPTO_MBEDTLS_DES_ENCRYPT |
| 1159 | +#ifdef MBEDTLS_DES_C |
| 1160 | +#include <mbedtls/des.h> |
| 1161 | +int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) |
| 1162 | +{ |
| 1163 | + u8 pkey[8], next, tmp; |
| 1164 | + int i; |
| 1165 | + |
| 1166 | + /* Add parity bits to the key */ |
| 1167 | + next = 0; |
| 1168 | + for (i = 0; i < 7; i++) { |
| 1169 | + tmp = key[i]; |
| 1170 | + pkey[i] = (tmp >> i) | next | 1; |
| 1171 | + next = tmp << (7 - i); |
| 1172 | + } |
| 1173 | + pkey[i] = next | 1; |
| 1174 | + |
| 1175 | + mbedtls_des_context des; |
| 1176 | + mbedtls_des_init(&des); |
| 1177 | + int ret = mbedtls_des_setkey_enc(&des, pkey) |
| 1178 | + || mbedtls_des_crypt_ecb(&des, clear, cypher) ? -1 : 0; |
| 1179 | + mbedtls_des_free(&des); |
| 1180 | + return ret; |
| 1181 | +} |
| 1182 | +#else |
| 1183 | +#include "des-internal.c"/* pull in hostap local implementation */ |
| 1184 | +#endif |
| 1185 | +#endif |
| 1186 | + |
| 1187 | + |
| 1188 | +#ifdef CRYPTO_MBEDTLS_PBKDF2_SHA1 |
| 1189 | +/* sha1-pbkdf2.c */ |
| 1190 | +#include <mbedtls/pkcs5.h> |
| 1191 | +int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, |
| 1192 | + int iterations, u8 *buf, size_t buflen) |
| 1193 | +{ |
| 1194 | + #if MBEDTLS_VERSION_NUMBER >= 0x03020200 /* mbedtls 3.2.2 */ |
| 1195 | + return mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, |
| 1196 | + (const u8 *)passphrase, os_strlen(passphrase), |
| 1197 | + ssid, ssid_len, iterations, 32, buf) ? -1 : 0; |
| 1198 | + #else |
| 1199 | + const mbedtls_md_info_t *md_info; |
| 1200 | + md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); |
| 1201 | + if (md_info == NULL) |
| 1202 | + return -1; |
| 1203 | + mbedtls_md_context_t ctx; |
| 1204 | + mbedtls_md_init(&ctx); |
| 1205 | + int ret = mbedtls_md_setup(&ctx, md_info, 1) |
| 1206 | + || mbedtls_pkcs5_pbkdf2_hmac(&ctx, |
| 1207 | + (const u8 *)passphrase, os_strlen(passphrase), |
| 1208 | + ssid, ssid_len, iterations, 32, buf) ? -1 : 0; |
| 1209 | + mbedtls_md_free(&ctx); |
| 1210 | + return ret; |
| 1211 | + #endif |
| 1212 | +} |
| 1213 | +#endif |
| 1214 | + |
| 1215 | + |
| 1216 | +/*#include "aes.h"*/ /* prototypes also included in "crypto.h" */ |
| 1217 | + |
| 1218 | +static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode) |
| 1219 | +{ |
| 1220 | + mbedtls_aes_context *aes = os_malloc(sizeof(*aes)); |
| 1221 | + if (!aes) |
| 1222 | + return NULL; |
| 1223 | + |
| 1224 | + mbedtls_aes_init(aes); |
| 1225 | + if ((mode == MBEDTLS_AES_ENCRYPT |
| 1226 | + ? mbedtls_aes_setkey_enc(aes, key, len * 8) |
| 1227 | + : mbedtls_aes_setkey_dec(aes, key, len * 8)) == 0) |
| 1228 | + return aes; |
| 1229 | + |
| 1230 | + mbedtls_aes_free(aes); |
| 1231 | + os_free(aes); |
| 1232 | + return NULL; |
| 1233 | +} |
| 1234 | + |
| 1235 | +void *aes_encrypt_init(const u8 *key, size_t len) |
| 1236 | +{ |
| 1237 | + return aes_crypt_init_mode(key, len, MBEDTLS_AES_ENCRYPT); |
| 1238 | +} |
| 1239 | + |
| 1240 | +int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) |
| 1241 | +{ |
| 1242 | + return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt); |
| 1243 | +} |
| 1244 | + |
| 1245 | +void aes_encrypt_deinit(void *ctx) |
| 1246 | +{ |
| 1247 | + mbedtls_aes_free(ctx); |
| 1248 | + os_free(ctx); |
| 1249 | +} |
| 1250 | + |
| 1251 | +void *aes_decrypt_init(const u8 *key, size_t len) |
| 1252 | +{ |
| 1253 | + return aes_crypt_init_mode(key, len, MBEDTLS_AES_DECRYPT); |
| 1254 | +} |
| 1255 | + |
| 1256 | +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) |
| 1257 | +{ |
| 1258 | + return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, crypt, plain); |
| 1259 | +} |
| 1260 | + |
| 1261 | +void aes_decrypt_deinit(void *ctx) |
| 1262 | +{ |
| 1263 | + mbedtls_aes_free(ctx); |
| 1264 | + os_free(ctx); |
| 1265 | +} |
| 1266 | + |
| 1267 | + |
| 1268 | +#include "aes_wrap.h" |
| 1269 | + |
| 1270 | + |
| 1271 | +#ifdef MBEDTLS_NIST_KW_C |
| 1272 | + |
| 1273 | +#include <mbedtls/nist_kw.h> |
| 1274 | + |
| 1275 | +/* aes-wrap.c */ |
| 1276 | +int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) |
| 1277 | +{ |
| 1278 | + mbedtls_nist_kw_context ctx; |
| 1279 | + mbedtls_nist_kw_init(&ctx); |
| 1280 | + size_t olen; |
| 1281 | + int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, |
| 1282 | + kek, kek_len*8, 1) |
| 1283 | + || mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, plain, n*8, |
| 1284 | + cipher, &olen, (n+1)*8) ? -1 : 0; |
| 1285 | + mbedtls_nist_kw_free(&ctx); |
| 1286 | + return ret; |
| 1287 | +} |
| 1288 | + |
| 1289 | +/* aes-unwrap.c */ |
| 1290 | +int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) |
| 1291 | +{ |
| 1292 | + mbedtls_nist_kw_context ctx; |
| 1293 | + mbedtls_nist_kw_init(&ctx); |
| 1294 | + size_t olen; |
| 1295 | + int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, |
| 1296 | + kek, kek_len*8, 0) |
| 1297 | + || mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, cipher, |
| 1298 | + (n+1)*8, plain, &olen, n*8) ? -1 : 0; |
| 1299 | + mbedtls_nist_kw_free(&ctx); |
| 1300 | + return ret; |
| 1301 | +} |
| 1302 | + |
| 1303 | +#else |
| 1304 | + |
| 1305 | +#ifndef CRYPTO_MBEDTLS_CONFIG_FIPS |
| 1306 | +#include "aes-wrap.c" /* pull in hostap local implementation */ |
| 1307 | +#include "aes-unwrap.c" /* pull in hostap local implementation */ |
| 1308 | +#endif |
| 1309 | + |
| 1310 | +#endif /* MBEDTLS_NIST_KW_C */ |
| 1311 | + |
| 1312 | + |
| 1313 | +#ifdef MBEDTLS_CMAC_C |
| 1314 | + |
| 1315 | +/* aes-omac1.c */ |
| 1316 | + |
| 1317 | +#include <mbedtls/cmac.h> |
| 1318 | + |
| 1319 | +int omac1_aes_vector( |
| 1320 | + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], |
| 1321 | + const size_t *len, u8 *mac) |
| 1322 | +{ |
| 1323 | + mbedtls_cipher_type_t cipher_type; |
| 1324 | + switch (key_len) { |
| 1325 | + case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break; |
| 1326 | + case 24: cipher_type = MBEDTLS_CIPHER_AES_192_ECB; break; |
| 1327 | + case 32: cipher_type = MBEDTLS_CIPHER_AES_256_ECB; break; |
| 1328 | + default: return -1; |
| 1329 | + } |
| 1330 | + const mbedtls_cipher_info_t *cipher_info; |
| 1331 | + cipher_info = mbedtls_cipher_info_from_type(cipher_type); |
| 1332 | + if (cipher_info == NULL) |
| 1333 | + return -1; |
| 1334 | + |
| 1335 | + mbedtls_cipher_context_t ctx; |
| 1336 | + mbedtls_cipher_init(&ctx); |
| 1337 | + int ret = -1; |
| 1338 | + if (mbedtls_cipher_setup(&ctx, cipher_info) == 0 |
| 1339 | + && mbedtls_cipher_cmac_starts(&ctx, key, key_len*8) == 0) { |
| 1340 | + ret = 0; |
| 1341 | + for (size_t i = 0; i < num_elem && ret == 0; ++i) |
| 1342 | + ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]); |
| 1343 | + } |
| 1344 | + if (ret == 0) |
| 1345 | + ret = mbedtls_cipher_cmac_finish(&ctx, mac); |
| 1346 | + mbedtls_cipher_free(&ctx); |
| 1347 | + return ret ? -1 : 0; |
| 1348 | +} |
| 1349 | + |
| 1350 | +int omac1_aes_128_vector(const u8 *key, size_t num_elem, |
| 1351 | + const u8 *addr[], const size_t *len, |
| 1352 | + u8 *mac) |
| 1353 | +{ |
| 1354 | + return omac1_aes_vector(key, 16, num_elem, addr, len, mac); |
| 1355 | +} |
| 1356 | + |
| 1357 | +int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) |
| 1358 | +{ |
| 1359 | + return omac1_aes_vector(key, 16, 1, &data, &data_len, mac); |
| 1360 | +} |
| 1361 | + |
| 1362 | +int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) |
| 1363 | +{ |
| 1364 | + return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); |
| 1365 | +} |
| 1366 | + |
| 1367 | +#else |
| 1368 | + |
| 1369 | +#include "aes-omac1.c" /* pull in hostap local implementation */ |
| 1370 | + |
| 1371 | +#ifndef MBEDTLS_AES_BLOCK_SIZE |
| 1372 | +#define MBEDTLS_AES_BLOCK_SIZE 16 |
| 1373 | +#endif |
| 1374 | + |
| 1375 | +#endif /* MBEDTLS_CMAC_C */ |
| 1376 | + |
| 1377 | + |
| 1378 | +/* These interfaces can be inefficient when used in loops, as the overhead of |
| 1379 | + * initialization each call is large for each block input (e.g. 16 bytes) */ |
| 1380 | + |
| 1381 | + |
| 1382 | +/* aes-encblock.c */ |
| 1383 | +int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) |
| 1384 | +{ |
| 1385 | + mbedtls_aes_context aes; |
| 1386 | + mbedtls_aes_init(&aes); |
| 1387 | + int ret = mbedtls_aes_setkey_enc(&aes, key, 128) |
| 1388 | + || mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out) |
| 1389 | + ? -1 |
| 1390 | + : 0; |
| 1391 | + mbedtls_aes_free(&aes); |
| 1392 | + return ret; |
| 1393 | +} |
| 1394 | + |
| 1395 | + |
| 1396 | +/* aes-ctr.c */ |
| 1397 | +int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce, |
| 1398 | + u8 *data, size_t data_len) |
| 1399 | +{ |
| 1400 | + unsigned char counter[MBEDTLS_AES_BLOCK_SIZE]; |
| 1401 | + unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE]; |
| 1402 | + os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/ |
| 1403 | + |
| 1404 | + mbedtls_aes_context ctx; |
| 1405 | + mbedtls_aes_init(&ctx); |
| 1406 | + size_t nc_off = 0; |
| 1407 | + int ret = mbedtls_aes_setkey_enc(&ctx, key, key_len*8) |
| 1408 | + || mbedtls_aes_crypt_ctr(&ctx, data_len, &nc_off, |
| 1409 | + counter, stream_block, |
| 1410 | + data, data) ? -1 : 0; |
| 1411 | + forced_memzero(stream_block, sizeof(stream_block)); |
| 1412 | + mbedtls_aes_free(&ctx); |
| 1413 | + return ret; |
| 1414 | +} |
| 1415 | + |
| 1416 | +int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, |
| 1417 | + u8 *data, size_t data_len) |
| 1418 | +{ |
| 1419 | + return aes_ctr_encrypt(key, 16, nonce, data, data_len); |
| 1420 | +} |
| 1421 | + |
| 1422 | + |
| 1423 | +/* aes-cbc.c */ |
| 1424 | +static int aes_128_cbc_oper(const u8 *key, const u8 *iv, |
| 1425 | + u8 *data, size_t data_len, int mode) |
| 1426 | +{ |
| 1427 | + unsigned char ivec[MBEDTLS_AES_BLOCK_SIZE]; |
| 1428 | + os_memcpy(ivec, iv, MBEDTLS_AES_BLOCK_SIZE); /*(must be writable)*/ |
| 1429 | + |
| 1430 | + mbedtls_aes_context ctx; |
| 1431 | + mbedtls_aes_init(&ctx); |
| 1432 | + int ret = (mode == MBEDTLS_AES_ENCRYPT |
| 1433 | + ? mbedtls_aes_setkey_enc(&ctx, key, 128) |
| 1434 | + : mbedtls_aes_setkey_dec(&ctx, key, 128)) |
| 1435 | + || mbedtls_aes_crypt_cbc(&ctx, mode, data_len, ivec, data, data); |
| 1436 | + mbedtls_aes_free(&ctx); |
| 1437 | + return ret ? -1 : 0; |
| 1438 | +} |
| 1439 | + |
| 1440 | +int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) |
| 1441 | +{ |
| 1442 | + return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT); |
| 1443 | +} |
| 1444 | + |
| 1445 | +int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) |
| 1446 | +{ |
| 1447 | + return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT); |
| 1448 | +} |
| 1449 | + |
| 1450 | + |
| 1451 | +/* |
| 1452 | + * Much of the following is documented in crypto.h as for CONFIG_TLS=internal |
| 1453 | + * but such comments are not accurate: |
| 1454 | + * |
| 1455 | + * "This function is only used with internal TLSv1 implementation |
| 1456 | + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need |
| 1457 | + * to implement this." |
| 1458 | + */ |
| 1459 | + |
| 1460 | + |
| 1461 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_CIPHER |
| 1462 | + |
| 1463 | +#include <mbedtls/cipher.h> |
| 1464 | + |
| 1465 | +struct crypto_cipher |
| 1466 | +{ |
| 1467 | + mbedtls_cipher_context_t ctx_enc; |
| 1468 | + mbedtls_cipher_context_t ctx_dec; |
| 1469 | +}; |
| 1470 | + |
| 1471 | +struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, |
| 1472 | + const u8 *iv, const u8 *key, |
| 1473 | + size_t key_len) |
| 1474 | +{ |
| 1475 | + /* IKEv2 src/eap_common/ikev2_common.c:ikev2_{encr,decr}_encrypt() |
| 1476 | + * uses one of CRYPTO_CIPHER_ALG_AES or CRYPTO_CIPHER_ALG_3DES */ |
| 1477 | + |
| 1478 | + mbedtls_cipher_type_t cipher_type; |
| 1479 | + size_t iv_len; |
| 1480 | + switch (alg) { |
| 1481 | + #ifdef MBEDTLS_ARC4_C |
| 1482 | + #if 0 |
| 1483 | + case CRYPTO_CIPHER_ALG_RC4: |
| 1484 | + cipher_type = MBEDTLS_CIPHER_ARC4_128; |
| 1485 | + iv_len = 0; |
| 1486 | + break; |
| 1487 | + #endif |
| 1488 | + #endif |
| 1489 | + #ifdef MBEDTLS_AES_C |
| 1490 | + case CRYPTO_CIPHER_ALG_AES: |
| 1491 | + if (key_len == 16) cipher_type = MBEDTLS_CIPHER_AES_128_CTR; |
| 1492 | + if (key_len == 24) cipher_type = MBEDTLS_CIPHER_AES_192_CTR; |
| 1493 | + if (key_len == 32) cipher_type = MBEDTLS_CIPHER_AES_256_CTR; |
| 1494 | + iv_len = 16; |
| 1495 | + break; |
| 1496 | + #endif |
| 1497 | + #ifdef MBEDTLS_DES_C |
| 1498 | + case CRYPTO_CIPHER_ALG_3DES: |
| 1499 | + cipher_type = MBEDTLS_CIPHER_DES_EDE3_CBC; |
| 1500 | + iv_len = 8; |
| 1501 | + break; |
| 1502 | + #if 0 |
| 1503 | + case CRYPTO_CIPHER_ALG_DES: |
| 1504 | + cipher_type = MBEDTLS_CIPHER_DES_CBC; |
| 1505 | + iv_len = 8; |
| 1506 | + break; |
| 1507 | + #endif |
| 1508 | + #endif |
| 1509 | + default: |
| 1510 | + return NULL; |
| 1511 | + } |
| 1512 | + |
| 1513 | + const mbedtls_cipher_info_t *cipher_info; |
| 1514 | + cipher_info = mbedtls_cipher_info_from_type(cipher_type); |
| 1515 | + if (cipher_info == NULL) |
| 1516 | + return NULL; |
| 1517 | + |
| 1518 | + key_len *= 8; /* key_bitlen */ |
| 1519 | + #if 0 /*(were key_bitlen not already available)*/ |
| 1520 | + #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */ |
| 1521 | + key_len = mbedtls_cipher_info_get_key_bitlen(cipher_info); |
| 1522 | + #else |
| 1523 | + key_len = cipher_info->MBEDTLS_PRIVATE(key_bitlen); |
| 1524 | + #endif |
| 1525 | + #endif |
| 1526 | + |
| 1527 | + #if 0 /*(were iv_len not known above, would need MBEDTLS_PRIVATE(iv_size))*/ |
| 1528 | + iv_len = cipher_info->MBEDTLS_PRIVATE(iv_size); |
| 1529 | + #endif |
| 1530 | + |
| 1531 | + struct crypto_cipher *ctx = os_malloc(sizeof(*ctx)); |
| 1532 | + if (!ctx) |
| 1533 | + return NULL; |
| 1534 | + |
| 1535 | + mbedtls_cipher_init(&ctx->ctx_enc); |
| 1536 | + mbedtls_cipher_init(&ctx->ctx_dec); |
| 1537 | + if ( mbedtls_cipher_setup(&ctx->ctx_enc,cipher_info) == 0 |
| 1538 | + && mbedtls_cipher_setup(&ctx->ctx_dec,cipher_info) == 0 |
| 1539 | + && mbedtls_cipher_setkey(&ctx->ctx_enc,key,key_len,MBEDTLS_ENCRYPT) == 0 |
| 1540 | + && mbedtls_cipher_setkey(&ctx->ctx_dec,key,key_len,MBEDTLS_DECRYPT) == 0 |
| 1541 | + && mbedtls_cipher_set_iv(&ctx->ctx_enc,iv,iv_len) == 0 |
| 1542 | + && mbedtls_cipher_set_iv(&ctx->ctx_dec,iv,iv_len) == 0 |
| 1543 | + && mbedtls_cipher_reset(&ctx->ctx_enc) == 0 |
| 1544 | + && mbedtls_cipher_reset(&ctx->ctx_dec) == 0) { |
| 1545 | + return ctx; |
| 1546 | + } |
| 1547 | + |
| 1548 | + mbedtls_cipher_free(&ctx->ctx_enc); |
| 1549 | + mbedtls_cipher_free(&ctx->ctx_dec); |
| 1550 | + os_free(ctx); |
| 1551 | + return NULL; |
| 1552 | +} |
| 1553 | + |
| 1554 | +int crypto_cipher_encrypt(struct crypto_cipher *ctx, |
| 1555 | + const u8 *plain, u8 *crypt, size_t len) |
| 1556 | +{ |
| 1557 | + size_t olen = 0; /*(poor interface above; unknown size of u8 *crypt)*/ |
| 1558 | + return (mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen) |
| 1559 | + || mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen)) ? -1 : 0; |
| 1560 | +} |
| 1561 | + |
| 1562 | +int crypto_cipher_decrypt(struct crypto_cipher *ctx, |
| 1563 | + const u8 *crypt, u8 *plain, size_t len) |
| 1564 | +{ |
| 1565 | + size_t olen = 0; /*(poor interface above; unknown size of u8 *plain)*/ |
| 1566 | + return (mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen) |
| 1567 | + || mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen)) ? -1 : 0; |
| 1568 | +} |
| 1569 | + |
| 1570 | +void crypto_cipher_deinit(struct crypto_cipher *ctx) |
| 1571 | +{ |
| 1572 | + mbedtls_cipher_free(&ctx->ctx_enc); |
| 1573 | + mbedtls_cipher_free(&ctx->ctx_dec); |
| 1574 | + os_free(ctx); |
| 1575 | +} |
| 1576 | + |
| 1577 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_CIPHER */ |
| 1578 | + |
| 1579 | + |
| 1580 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_HASH |
| 1581 | + |
| 1582 | +struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, |
| 1583 | + size_t key_len) |
| 1584 | +{ |
| 1585 | + mbedtls_md_type_t md_type; |
| 1586 | + int is_hmac = 0; |
| 1587 | + |
| 1588 | + switch (alg) { |
| 1589 | + #ifdef MBEDTLS_MD5_C |
| 1590 | + case CRYPTO_HASH_ALG_MD5: |
| 1591 | + md_type = MBEDTLS_MD_MD5; |
| 1592 | + break; |
| 1593 | + #endif |
| 1594 | + #ifdef MBEDTLS_SHA1_C |
| 1595 | + case CRYPTO_HASH_ALG_SHA1: |
| 1596 | + md_type = MBEDTLS_MD_SHA1; |
| 1597 | + break; |
| 1598 | + #endif |
| 1599 | + #ifdef MBEDTLS_MD5_C |
| 1600 | + case CRYPTO_HASH_ALG_HMAC_MD5: |
| 1601 | + md_type = MBEDTLS_MD_MD5; |
| 1602 | + is_hmac = 1; |
| 1603 | + break; |
| 1604 | + #endif |
| 1605 | + #ifdef MBEDTLS_SHA1_C |
| 1606 | + case CRYPTO_HASH_ALG_HMAC_SHA1: |
| 1607 | + md_type = MBEDTLS_MD_SHA1; |
| 1608 | + is_hmac = 1; |
| 1609 | + break; |
| 1610 | + #endif |
| 1611 | + #ifdef MBEDTLS_SHA256_C |
| 1612 | + case CRYPTO_HASH_ALG_SHA256: |
| 1613 | + md_type = MBEDTLS_MD_SHA256; |
| 1614 | + break; |
| 1615 | + case CRYPTO_HASH_ALG_HMAC_SHA256: |
| 1616 | + md_type = MBEDTLS_MD_SHA256; |
| 1617 | + is_hmac = 1; |
| 1618 | + break; |
| 1619 | + #endif |
| 1620 | + #ifdef MBEDTLS_SHA512_C |
| 1621 | + case CRYPTO_HASH_ALG_SHA384: |
| 1622 | + md_type = MBEDTLS_MD_SHA384; |
| 1623 | + break; |
| 1624 | + case CRYPTO_HASH_ALG_SHA512: |
| 1625 | + md_type = MBEDTLS_MD_SHA512; |
| 1626 | + break; |
| 1627 | + #endif |
| 1628 | + default: |
| 1629 | + return NULL; |
| 1630 | + } |
| 1631 | + |
| 1632 | + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type); |
| 1633 | + if (!md_info) |
| 1634 | + return NULL; |
| 1635 | + |
| 1636 | + mbedtls_md_context_t *mctx = os_malloc(sizeof(*mctx)); |
| 1637 | + if (mctx == NULL) |
| 1638 | + return NULL; |
| 1639 | + |
| 1640 | + mbedtls_md_init(mctx); |
| 1641 | + if (mbedtls_md_setup(mctx, md_info, is_hmac) != 0) { |
| 1642 | + os_free(mctx); |
| 1643 | + return NULL; |
| 1644 | + } |
| 1645 | + |
| 1646 | + if (is_hmac) |
| 1647 | + mbedtls_md_hmac_starts(mctx, key, key_len); |
| 1648 | + else |
| 1649 | + mbedtls_md_starts(mctx); |
| 1650 | + return (struct crypto_hash *)((uintptr_t)mctx | is_hmac); |
| 1651 | +} |
| 1652 | + |
| 1653 | +void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) |
| 1654 | +{ |
| 1655 | + mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL); |
| 1656 | + #if 0 |
| 1657 | + /*(mbedtls_md_hmac_update() and mbedtls_md_update() |
| 1658 | + * make same modifications under the hood in mbedtls)*/ |
| 1659 | + if ((uintptr_t)ctx & 1uL) |
| 1660 | + mbedtls_md_hmac_update(mctx, data, len); |
| 1661 | + else |
| 1662 | + #endif |
| 1663 | + mbedtls_md_update(mctx, data, len); |
| 1664 | +} |
| 1665 | + |
| 1666 | +int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) |
| 1667 | +{ |
| 1668 | + mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL); |
| 1669 | + if (mac != NULL && len != NULL) { /*(NULL if caller just freeing context)*/ |
| 1670 | + #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ |
| 1671 | + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(mctx); |
| 1672 | + #else |
| 1673 | + const mbedtls_md_info_t *md_info = mctx->MBEDTLS_PRIVATE(md_info); |
| 1674 | + #endif |
| 1675 | + size_t maclen = mbedtls_md_get_size(md_info); |
| 1676 | + if (*len < maclen) { |
| 1677 | + *len = maclen; |
| 1678 | + /*(note: ctx not freed; can call again with larger *len)*/ |
| 1679 | + return -1; |
| 1680 | + } |
| 1681 | + *len = maclen; |
| 1682 | + if ((uintptr_t)ctx & 1uL) |
| 1683 | + mbedtls_md_hmac_finish(mctx, mac); |
| 1684 | + else |
| 1685 | + mbedtls_md_finish(mctx, mac); |
| 1686 | + } |
| 1687 | + mbedtls_md_free(mctx); |
| 1688 | + os_free(mctx); |
| 1689 | + return 0; |
| 1690 | +} |
| 1691 | + |
| 1692 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_HASH */ |
| 1693 | + |
| 1694 | + |
| 1695 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM |
| 1696 | + |
| 1697 | +#include <mbedtls/bignum.h> |
| 1698 | + |
| 1699 | +/* crypto.h bignum interfaces */ |
| 1700 | + |
| 1701 | +struct crypto_bignum *crypto_bignum_init(void) |
| 1702 | +{ |
| 1703 | + mbedtls_mpi *bn = os_malloc(sizeof(*bn)); |
| 1704 | + if (bn) |
| 1705 | + mbedtls_mpi_init(bn); |
| 1706 | + return (struct crypto_bignum *)bn; |
| 1707 | +} |
| 1708 | + |
| 1709 | +struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len) |
| 1710 | +{ |
| 1711 | + mbedtls_mpi *bn = os_malloc(sizeof(*bn)); |
| 1712 | + if (bn) { |
| 1713 | + mbedtls_mpi_init(bn); |
| 1714 | + if (mbedtls_mpi_read_binary(bn, buf, len) == 0) |
| 1715 | + return (struct crypto_bignum *)bn; |
| 1716 | + } |
| 1717 | + |
| 1718 | + os_free(bn); |
| 1719 | + return NULL; |
| 1720 | +} |
| 1721 | + |
| 1722 | +struct crypto_bignum *crypto_bignum_init_uint(unsigned int val) |
| 1723 | +{ |
| 1724 | + #if 0 /*(hostap use of this interface passes int, not uint)*/ |
| 1725 | + val = host_to_be32(val); |
| 1726 | + return crypto_bignum_init_set((const u8 *)&val, sizeof(val)); |
| 1727 | + #else |
| 1728 | + mbedtls_mpi *bn = os_malloc(sizeof(*bn)); |
| 1729 | + if (bn) { |
| 1730 | + mbedtls_mpi_init(bn); |
| 1731 | + if (mbedtls_mpi_lset(bn, (int)val) == 0) |
| 1732 | + return (struct crypto_bignum *)bn; |
| 1733 | + } |
| 1734 | + |
| 1735 | + os_free(bn); |
| 1736 | + return NULL; |
| 1737 | + #endif |
| 1738 | +} |
| 1739 | + |
| 1740 | +void crypto_bignum_deinit(struct crypto_bignum *n, int clear) |
| 1741 | +{ |
| 1742 | + mbedtls_mpi_free((mbedtls_mpi *)n); |
| 1743 | + os_free(n); |
| 1744 | +} |
| 1745 | + |
| 1746 | +int crypto_bignum_to_bin(const struct crypto_bignum *a, |
| 1747 | + u8 *buf, size_t buflen, size_t padlen) |
| 1748 | +{ |
| 1749 | + size_t n = mbedtls_mpi_size((mbedtls_mpi *)a); |
| 1750 | + if (n < padlen) |
| 1751 | + n = padlen; |
| 1752 | + return n > buflen || mbedtls_mpi_write_binary((mbedtls_mpi *)a, buf, n) |
| 1753 | + ? -1 |
| 1754 | + : (int)(n); |
| 1755 | +} |
| 1756 | + |
| 1757 | +int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) |
| 1758 | +{ |
| 1759 | + /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/ |
| 1760 | + #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */ |
| 1761 | + return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m, |
| 1762 | + mbedtls_ctr_drbg_random, |
| 1763 | + crypto_mbedtls_ctr_drbg()) ? -1 : 0; |
| 1764 | + #else |
| 1765 | + /* (needed by EAP_PWD, SAE, DPP) */ |
| 1766 | + wpa_printf(MSG_ERROR, |
| 1767 | + "mbedtls 2.27.0 or later required for mbedtls_mpi_random()"); |
| 1768 | + return -1; |
| 1769 | + #endif |
| 1770 | +} |
| 1771 | + |
| 1772 | +int crypto_bignum_add(const struct crypto_bignum *a, |
| 1773 | + const struct crypto_bignum *b, |
| 1774 | + struct crypto_bignum *c) |
| 1775 | +{ |
| 1776 | + return mbedtls_mpi_add_mpi((mbedtls_mpi *)c, |
| 1777 | + (const mbedtls_mpi *)a, |
| 1778 | + (const mbedtls_mpi *)b) ? -1 : 0; |
| 1779 | +} |
| 1780 | + |
| 1781 | +int crypto_bignum_mod(const struct crypto_bignum *a, |
| 1782 | + const struct crypto_bignum *b, |
| 1783 | + struct crypto_bignum *c) |
| 1784 | +{ |
| 1785 | + return mbedtls_mpi_mod_mpi((mbedtls_mpi *)c, |
| 1786 | + (const mbedtls_mpi *)a, |
| 1787 | + (const mbedtls_mpi *)b) ? -1 : 0; |
| 1788 | +} |
| 1789 | + |
| 1790 | +int crypto_bignum_exptmod(const struct crypto_bignum *a, |
| 1791 | + const struct crypto_bignum *b, |
| 1792 | + const struct crypto_bignum *c, |
| 1793 | + struct crypto_bignum *d) |
| 1794 | +{ |
| 1795 | + /* (check if input params match d; d is the result) */ |
| 1796 | + /* (a == d) is ok in current mbedtls implementation */ |
| 1797 | + if (b == d || c == d) { /*(not ok; store result in intermediate)*/ |
| 1798 | + mbedtls_mpi R; |
| 1799 | + mbedtls_mpi_init(&R); |
| 1800 | + int rc = mbedtls_mpi_exp_mod(&R, |
| 1801 | + (const mbedtls_mpi *)a, |
| 1802 | + (const mbedtls_mpi *)b, |
| 1803 | + (const mbedtls_mpi *)c, |
| 1804 | + NULL) |
| 1805 | + || mbedtls_mpi_copy((mbedtls_mpi *)d, &R) ? -1 : 0; |
| 1806 | + mbedtls_mpi_free(&R); |
| 1807 | + return rc; |
| 1808 | + } |
| 1809 | + else { |
| 1810 | + return mbedtls_mpi_exp_mod((mbedtls_mpi *)d, |
| 1811 | + (const mbedtls_mpi *)a, |
| 1812 | + (const mbedtls_mpi *)b, |
| 1813 | + (const mbedtls_mpi *)c, |
| 1814 | + NULL) ? -1 : 0; |
| 1815 | + } |
| 1816 | +} |
| 1817 | + |
| 1818 | +int crypto_bignum_inverse(const struct crypto_bignum *a, |
| 1819 | + const struct crypto_bignum *b, |
| 1820 | + struct crypto_bignum *c) |
| 1821 | +{ |
| 1822 | + return mbedtls_mpi_inv_mod((mbedtls_mpi *)c, |
| 1823 | + (const mbedtls_mpi *)a, |
| 1824 | + (const mbedtls_mpi *)b) ? -1 : 0; |
| 1825 | +} |
| 1826 | + |
| 1827 | +int crypto_bignum_sub(const struct crypto_bignum *a, |
| 1828 | + const struct crypto_bignum *b, |
| 1829 | + struct crypto_bignum *c) |
| 1830 | +{ |
| 1831 | + return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c, |
| 1832 | + (const mbedtls_mpi *)a, |
| 1833 | + (const mbedtls_mpi *)b) ? -1 : 0; |
| 1834 | +} |
| 1835 | + |
| 1836 | +int crypto_bignum_div(const struct crypto_bignum *a, |
| 1837 | + const struct crypto_bignum *b, |
| 1838 | + struct crypto_bignum *c) |
| 1839 | +{ |
| 1840 | + /*(most current use of this crypto.h interface has a == c (result), |
| 1841 | + * so store result in an intermediate to avoid overwritten input)*/ |
| 1842 | + mbedtls_mpi R; |
| 1843 | + mbedtls_mpi_init(&R); |
| 1844 | + int rc = mbedtls_mpi_div_mpi(&R, NULL, |
| 1845 | + (const mbedtls_mpi *)a, |
| 1846 | + (const mbedtls_mpi *)b) |
| 1847 | + || mbedtls_mpi_copy((mbedtls_mpi *)c, &R) ? -1 : 0; |
| 1848 | + mbedtls_mpi_free(&R); |
| 1849 | + return rc; |
| 1850 | +} |
| 1851 | + |
| 1852 | +int crypto_bignum_addmod(const struct crypto_bignum *a, |
| 1853 | + const struct crypto_bignum *b, |
| 1854 | + const struct crypto_bignum *c, |
| 1855 | + struct crypto_bignum *d) |
| 1856 | +{ |
| 1857 | + return mbedtls_mpi_add_mpi((mbedtls_mpi *)d, |
| 1858 | + (const mbedtls_mpi *)a, |
| 1859 | + (const mbedtls_mpi *)b) |
| 1860 | + || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, |
| 1861 | + (mbedtls_mpi *)d, |
| 1862 | + (const mbedtls_mpi *)c) ? -1 : 0; |
| 1863 | +} |
| 1864 | + |
| 1865 | +int crypto_bignum_mulmod(const struct crypto_bignum *a, |
| 1866 | + const struct crypto_bignum *b, |
| 1867 | + const struct crypto_bignum *c, |
| 1868 | + struct crypto_bignum *d) |
| 1869 | +{ |
| 1870 | + return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d, |
| 1871 | + (const mbedtls_mpi *)a, |
| 1872 | + (const mbedtls_mpi *)b) |
| 1873 | + || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, |
| 1874 | + (mbedtls_mpi *)d, |
| 1875 | + (const mbedtls_mpi *)c) ? -1 : 0; |
| 1876 | +} |
| 1877 | + |
| 1878 | +int crypto_bignum_sqrmod(const struct crypto_bignum *a, |
| 1879 | + const struct crypto_bignum *b, |
| 1880 | + struct crypto_bignum *c) |
| 1881 | +{ |
| 1882 | + #if 1 |
| 1883 | + return crypto_bignum_mulmod(a, a, b, c); |
| 1884 | + #else |
| 1885 | + mbedtls_mpi bn; |
| 1886 | + mbedtls_mpi_init(&bn); |
| 1887 | + if (mbedtls_mpi_lset(&bn, 2)) /* alt?: mbedtls_mpi_set_bit(&bn, 1) */ |
| 1888 | + return -1; |
| 1889 | + int ret = mbedtls_mpi_exp_mod((mbedtls_mpi *)c, |
| 1890 | + (const mbedtls_mpi *)a, &bn, |
| 1891 | + (const mbedtls_mpi *)b, NULL) ? -1 : 0; |
| 1892 | + mbedtls_mpi_free(&bn); |
| 1893 | + return ret; |
| 1894 | + #endif |
| 1895 | +} |
| 1896 | + |
| 1897 | +int crypto_bignum_rshift(const struct crypto_bignum *a, int n, |
| 1898 | + struct crypto_bignum *r) |
| 1899 | +{ |
| 1900 | + return mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a) |
| 1901 | + || mbedtls_mpi_shift_r((mbedtls_mpi *)r, n) ? -1 : 0; |
| 1902 | +} |
| 1903 | + |
| 1904 | +int crypto_bignum_cmp(const struct crypto_bignum *a, |
| 1905 | + const struct crypto_bignum *b) |
| 1906 | +{ |
| 1907 | + return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, (const mbedtls_mpi *)b); |
| 1908 | +} |
| 1909 | + |
| 1910 | +int crypto_bignum_is_zero(const struct crypto_bignum *a) |
| 1911 | +{ |
| 1912 | + /* XXX: src/common/sae.c:sswu() contains comment: |
| 1913 | + * "TODO: Make sure crypto_bignum_is_zero() is constant time" |
| 1914 | + * Note: mbedtls_mpi_cmp_int() *is not* constant time */ |
| 1915 | + return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0); |
| 1916 | +} |
| 1917 | + |
| 1918 | +int crypto_bignum_is_one(const struct crypto_bignum *a) |
| 1919 | +{ |
| 1920 | + return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0); |
| 1921 | +} |
| 1922 | + |
| 1923 | +int crypto_bignum_is_odd(const struct crypto_bignum *a) |
| 1924 | +{ |
| 1925 | + return mbedtls_mpi_get_bit((const mbedtls_mpi *)a, 0); |
| 1926 | +} |
| 1927 | + |
| 1928 | +#include "utils/const_time.h" |
| 1929 | +int crypto_bignum_legendre(const struct crypto_bignum *a, |
| 1930 | + const struct crypto_bignum *p) |
| 1931 | +{ |
| 1932 | + /* Security Note: |
| 1933 | + * mbedtls_mpi_exp_mod() is not documented to run in constant time, |
| 1934 | + * though mbedtls/library/bignum.c uses constant_time_internal.h funcs. |
| 1935 | + * Compare to crypto_openssl.c:crypto_bignum_legendre() |
| 1936 | + * which uses openssl BN_mod_exp_mont_consttime() |
| 1937 | + * mbedtls/library/ecp.c has further countermeasures to timing attacks, |
| 1938 | + * (but ecp.c funcs are not used here) */ |
| 1939 | + |
| 1940 | + mbedtls_mpi exp, tmp; |
| 1941 | + mbedtls_mpi_init(&exp); |
| 1942 | + mbedtls_mpi_init(&tmp); |
| 1943 | + |
| 1944 | + /* exp = (p-1) / 2 */ |
| 1945 | + int res; |
| 1946 | + if (mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1) == 0 |
| 1947 | + && mbedtls_mpi_shift_r(&exp, 1) == 0 |
| 1948 | + && mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *)a, &exp, |
| 1949 | + (const mbedtls_mpi *)p, NULL) == 0) { |
| 1950 | + /*(modified from crypto_openssl.c:crypto_bignum_legendre())*/ |
| 1951 | + /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need |
| 1952 | + * to use constant time selection to avoid branches here. */ |
| 1953 | + unsigned int mask; |
| 1954 | + res = -1; |
| 1955 | + mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 1) == 0), 1); |
| 1956 | + res = const_time_select_int(mask, 1, res); |
| 1957 | + mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 0) == 0), 1); |
| 1958 | + res = const_time_select_int(mask, 0, res); |
| 1959 | + } else { |
| 1960 | + res = -2; |
| 1961 | + } |
| 1962 | + |
| 1963 | + mbedtls_mpi_free(&tmp); |
| 1964 | + mbedtls_mpi_free(&exp); |
| 1965 | + return res; |
| 1966 | +} |
| 1967 | + |
| 1968 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_BIGNUM */ |
| 1969 | + |
| 1970 | + |
| 1971 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_DH |
| 1972 | + |
| 1973 | +/* crypto_internal-modexp.c */ |
| 1974 | + |
| 1975 | +#include <mbedtls/bignum.h> |
| 1976 | +#include <mbedtls/dhm.h> |
| 1977 | + |
| 1978 | +#if 0 /* crypto_dh_init() and crypto_dh_derive_secret() prefer to use mbedtls */ |
| 1979 | +int crypto_mod_exp(const u8 *base, size_t base_len, |
| 1980 | + const u8 *power, size_t power_len, |
| 1981 | + const u8 *modulus, size_t modulus_len, |
| 1982 | + u8 *result, size_t *result_len) |
| 1983 | +{ |
| 1984 | + mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result; |
| 1985 | + mbedtls_mpi_init(&bn_base); |
| 1986 | + mbedtls_mpi_init(&bn_exp); |
| 1987 | + mbedtls_mpi_init(&bn_modulus); |
| 1988 | + mbedtls_mpi_init(&bn_result); |
| 1989 | + |
| 1990 | + size_t len; |
| 1991 | + int ret = mbedtls_mpi_read_binary(&bn_base, base, base_len) |
| 1992 | + || mbedtls_mpi_read_binary(&bn_exp, power, power_len) |
| 1993 | + || mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len) |
| 1994 | + || mbedtls_mpi_exp_mod(&bn_result,&bn_base,&bn_exp,&bn_modulus,NULL) |
| 1995 | + || (len = mbedtls_mpi_size(&bn_result)) > *result_len |
| 1996 | + || mbedtls_mpi_write_binary(&bn_result, result, (*result_len = len)) |
| 1997 | + ? -1 |
| 1998 | + : 0; |
| 1999 | + |
| 2000 | + mbedtls_mpi_free(&bn_base); |
| 2001 | + mbedtls_mpi_free(&bn_exp); |
| 2002 | + mbedtls_mpi_free(&bn_modulus); |
| 2003 | + mbedtls_mpi_free(&bn_result); |
| 2004 | + return ret; |
| 2005 | +} |
| 2006 | +#endif |
| 2007 | + |
| 2008 | +static int crypto_mbedtls_dh_set_bin_pg(mbedtls_dhm_context *ctx, u8 generator, |
| 2009 | + const u8 *prime, size_t prime_len) |
| 2010 | +{ |
| 2011 | + /*(could set these directly in MBEDTLS_PRIVATE members)*/ |
| 2012 | + mbedtls_mpi P, G; |
| 2013 | + mbedtls_mpi_init(&P); |
| 2014 | + mbedtls_mpi_init(&G); |
| 2015 | + int ret = mbedtls_mpi_lset(&G, generator) |
| 2016 | + || mbedtls_mpi_read_binary(&P, prime, prime_len) |
| 2017 | + || mbedtls_dhm_set_group(ctx, &P, &G); |
| 2018 | + mbedtls_mpi_free(&P); |
| 2019 | + mbedtls_mpi_free(&G); |
| 2020 | + return ret; |
| 2021 | +} |
| 2022 | + |
| 2023 | +__attribute_noinline__ |
| 2024 | +static int crypto_mbedtls_dh_init_public(mbedtls_dhm_context *ctx, u8 generator, |
| 2025 | + const u8 *prime, size_t prime_len, |
| 2026 | + u8 *privkey, u8 *pubkey) |
| 2027 | +{ |
| 2028 | + if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len) |
| 2029 | + || mbedtls_dhm_make_public(ctx, (int)prime_len, pubkey, prime_len, |
| 2030 | + mbedtls_ctr_drbg_random, |
| 2031 | + crypto_mbedtls_ctr_drbg())) |
| 2032 | + return -1; |
| 2033 | + |
| 2034 | + /*(enable later when upstream mbedtls interface changes require)*/ |
| 2035 | + #if 0 && MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 2036 | + mbedtls_mpi X; |
| 2037 | + mbedtls_mpi_init(&X); |
| 2038 | + int ret = mbedtls_dhm_get_value(ctx, MBEDTLS_DHM_PARAM_X, &X) |
| 2039 | + || mbedtls_mpi_write_binary(&X, privkey, prime_len) ? -1 : 0; |
| 2040 | + mbedtls_mpi_free(&X); |
| 2041 | + return ret; |
| 2042 | + #else |
| 2043 | + return mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(X), |
| 2044 | + privkey, prime_len) ? -1 : 0; |
| 2045 | + #endif |
| 2046 | +} |
| 2047 | + |
| 2048 | +int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, |
| 2049 | + u8 *pubkey) |
| 2050 | +{ |
| 2051 | + #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/ |
| 2052 | + size_t pubkey_len, pad; |
| 2053 | + |
| 2054 | + if (os_get_random(privkey, prime_len) < 0) |
| 2055 | + return -1; |
| 2056 | + if (os_memcmp(privkey, prime, prime_len) > 0) { |
| 2057 | + /* Make sure private value is smaller than prime */ |
| 2058 | + privkey[0] = 0; |
| 2059 | + } |
| 2060 | + |
| 2061 | + pubkey_len = prime_len; |
| 2062 | + if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len, |
| 2063 | + pubkey, &pubkey_len) < 0) |
| 2064 | + return -1; |
| 2065 | + if (pubkey_len < prime_len) { |
| 2066 | + pad = prime_len - pubkey_len; |
| 2067 | + os_memmove(pubkey + pad, pubkey, pubkey_len); |
| 2068 | + os_memset(pubkey, 0, pad); |
| 2069 | + } |
| 2070 | + |
| 2071 | + return 0; |
| 2072 | + #else |
| 2073 | + /* Prefer to use mbedtls to derive our public/private key, as doing so |
| 2074 | + * leverages mbedtls to properly format output and to perform blinding*/ |
| 2075 | + mbedtls_dhm_context ctx; |
| 2076 | + mbedtls_dhm_init(&ctx); |
| 2077 | + int ret = crypto_mbedtls_dh_init_public(&ctx, generator, prime, |
| 2078 | + prime_len, privkey, pubkey); |
| 2079 | + mbedtls_dhm_free(&ctx); |
| 2080 | + return ret; |
| 2081 | + #endif |
| 2082 | +} |
| 2083 | + |
| 2084 | +/*(crypto_dh_derive_secret() could be implemented using crypto.h APIs |
| 2085 | + * instead of being reimplemented in each crypto_*.c)*/ |
| 2086 | +int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len, |
| 2087 | + const u8 *order, size_t order_len, |
| 2088 | + const u8 *privkey, size_t privkey_len, |
| 2089 | + const u8 *pubkey, size_t pubkey_len, |
| 2090 | + u8 *secret, size_t *len) |
| 2091 | +{ |
| 2092 | + #if 0 |
| 2093 | + if (pubkey_len > prime_len || |
| 2094 | + (pubkey_len == prime_len && |
| 2095 | + os_memcmp(pubkey, prime, prime_len) >= 0)) |
| 2096 | + return -1; |
| 2097 | + |
| 2098 | + int res = 0; |
| 2099 | + mbedtls_mpi pub; |
| 2100 | + mbedtls_mpi_init(&pub); |
| 2101 | + if (mbedtls_mpi_read_binary(&pub, pubkey, pubkey_len) |
| 2102 | + || mbedtls_mpi_cmp_int(&pub, 1) <= 0) { |
| 2103 | + res = -1; |
| 2104 | + } else if (order) { |
| 2105 | + mbedtls_mpi p, q, tmp; |
| 2106 | + mbedtls_mpi_init(&p); |
| 2107 | + mbedtls_mpi_init(&q); |
| 2108 | + mbedtls_mpi_init(&tmp); |
| 2109 | + |
| 2110 | + /* verify: pubkey^q == 1 mod p */ |
| 2111 | + res = (mbedtls_mpi_read_binary(&p, prime, prime_len) |
| 2112 | + || mbedtls_mpi_read_binary(&q, order, order_len) |
| 2113 | + || mbedtls_mpi_exp_mod(&tmp, &pub, &q, &p, NULL) |
| 2114 | + || mbedtls_mpi_cmp_int(&tmp, 1) != 0); |
| 2115 | + |
| 2116 | + mbedtls_mpi_free(&p); |
| 2117 | + mbedtls_mpi_free(&q); |
| 2118 | + mbedtls_mpi_free(&tmp); |
| 2119 | + } |
| 2120 | + mbedtls_mpi_free(&pub); |
| 2121 | + |
| 2122 | + return (res == 0) |
| 2123 | + ? crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len, |
| 2124 | + prime, prime_len, secret, len) |
| 2125 | + : -1; |
| 2126 | + #else |
| 2127 | + /* Prefer to use mbedtls to derive DH shared secret, as doing so |
| 2128 | + * leverages mbedtls to validate params and to perform blinding. |
| 2129 | + * |
| 2130 | + * Attempt to reconstitute DH context to derive shared secret |
| 2131 | + * (due to limitations of the interface, which ought to pass context). |
| 2132 | + * Force provided G (our private key) into context without validation. |
| 2133 | + * Regenerating GX (our public key) not needed to derive shared secret. |
| 2134 | + */ |
| 2135 | + /*(older compilers might not support VLAs)*/ |
| 2136 | + /*unsigned char buf[2+prime_len+2+1+2+pubkey_len];*/ |
| 2137 | + unsigned char buf[2+MBEDTLS_MPI_MAX_SIZE+2+1+2+MBEDTLS_MPI_MAX_SIZE]; |
| 2138 | + unsigned char *p = buf + 2 + prime_len; |
| 2139 | + if (2+prime_len+2+1+2+pubkey_len > sizeof(buf)) |
| 2140 | + return -1; |
| 2141 | + WPA_PUT_BE16(buf, prime_len); /*(2-byte big-endian size of prime)*/ |
| 2142 | + p[0] = 0; /*(2-byte big-endian size of generator)*/ |
| 2143 | + p[1] = 1; |
| 2144 | + p[2] = generator; |
| 2145 | + WPA_PUT_BE16(p+3, pubkey_len); /*(2-byte big-endian size of pubkey)*/ |
| 2146 | + os_memcpy(p+5, pubkey, pubkey_len); |
| 2147 | + os_memcpy(buf+2, prime, prime_len); |
| 2148 | + |
| 2149 | + mbedtls_dhm_context ctx; |
| 2150 | + mbedtls_dhm_init(&ctx); |
| 2151 | + p = buf; |
| 2152 | + int ret = mbedtls_dhm_read_params(&ctx, &p, p+2+prime_len+5+pubkey_len) |
| 2153 | + || mbedtls_mpi_read_binary(&ctx.MBEDTLS_PRIVATE(X), |
| 2154 | + privkey, privkey_len) |
| 2155 | + || mbedtls_dhm_calc_secret(&ctx, secret, *len, len, |
| 2156 | + mbedtls_ctr_drbg_random, |
| 2157 | + crypto_mbedtls_ctr_drbg()) ? -1 : 0; |
| 2158 | + mbedtls_dhm_free(&ctx); |
| 2159 | + return ret; |
| 2160 | + #endif |
| 2161 | +} |
| 2162 | + |
| 2163 | +/* dh_group5.c */ |
| 2164 | + |
| 2165 | +#include "dh_group5.h" |
| 2166 | + |
| 2167 | +/* RFC3526_PRIME_1536[] and RFC3526_GENERATOR_1536[] from crypto_wolfssl.c */ |
| 2168 | + |
| 2169 | +static const unsigned char RFC3526_PRIME_1536[] = { |
| 2170 | + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2, |
| 2171 | + 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1, |
| 2172 | + 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6, |
| 2173 | + 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, |
| 2174 | + 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, |
| 2175 | + 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, |
| 2176 | + 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9, |
| 2177 | + 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, |
| 2178 | + 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, |
| 2179 | + 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, |
| 2180 | + 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, |
| 2181 | + 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, |
| 2182 | + 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56, |
| 2183 | + 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D, |
| 2184 | + 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08, |
| 2185 | + 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF |
| 2186 | +}; |
| 2187 | + |
| 2188 | +static const unsigned char RFC3526_GENERATOR_1536[] = { |
| 2189 | + 0x02 |
| 2190 | +}; |
| 2191 | + |
| 2192 | +void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) |
| 2193 | +{ |
| 2194 | + const unsigned char * const prime = RFC3526_PRIME_1536; |
| 2195 | + const size_t prime_len = sizeof(RFC3526_PRIME_1536); |
| 2196 | + const u8 generator = *RFC3526_GENERATOR_1536; |
| 2197 | + struct wpabuf *wpubl = NULL, *wpriv = NULL; |
| 2198 | + |
| 2199 | + mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx)); |
| 2200 | + if (ctx == NULL) |
| 2201 | + return NULL; |
| 2202 | + mbedtls_dhm_init(ctx); |
| 2203 | + |
| 2204 | + if ( (wpubl = wpabuf_alloc(prime_len)) |
| 2205 | + && (wpriv = wpabuf_alloc(prime_len)) |
| 2206 | + && crypto_mbedtls_dh_init_public(ctx, generator, prime, prime_len, |
| 2207 | + wpabuf_put(wpriv, prime_len), |
| 2208 | + wpabuf_put(wpubl, prime_len))==0) { |
| 2209 | + wpabuf_free(*publ); |
| 2210 | + wpabuf_clear_free(*priv); |
| 2211 | + *publ = wpubl; |
| 2212 | + *priv = wpriv; |
| 2213 | + return ctx; |
| 2214 | + } |
| 2215 | + |
| 2216 | + wpabuf_clear_free(wpriv); |
| 2217 | + wpabuf_free(wpubl); |
| 2218 | + mbedtls_dhm_free(ctx); |
| 2219 | + os_free(ctx); |
| 2220 | + return NULL; |
| 2221 | +} |
| 2222 | + |
| 2223 | +#ifdef CRYPTO_MBEDTLS_DH5_INIT_FIXED |
| 2224 | +void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ) |
| 2225 | +{ |
| 2226 | + const unsigned char * const prime = RFC3526_PRIME_1536; |
| 2227 | + const size_t prime_len = sizeof(RFC3526_PRIME_1536); |
| 2228 | + const u8 generator = *RFC3526_GENERATOR_1536; |
| 2229 | + |
| 2230 | + mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx)); |
| 2231 | + if (ctx == NULL) |
| 2232 | + return NULL; |
| 2233 | + mbedtls_dhm_init(ctx); |
| 2234 | + |
| 2235 | + if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)==0 |
| 2236 | + #if 0 /*(ignore; not required to derive shared secret)*/ |
| 2237 | + && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(GX), |
| 2238 | + wpabuf_head(publ),wpabuf_len(publ))==0 |
| 2239 | + #endif |
| 2240 | + && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(X), |
| 2241 | + wpabuf_head(priv),wpabuf_len(priv))==0) { |
| 2242 | + return ctx; |
| 2243 | + } |
| 2244 | + |
| 2245 | + mbedtls_dhm_free(ctx); |
| 2246 | + os_free(ctx); |
| 2247 | + return NULL; |
| 2248 | +} |
| 2249 | +#endif |
| 2250 | + |
| 2251 | +struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, |
| 2252 | + const struct wpabuf *own_private) |
| 2253 | +{ |
| 2254 | + /*((mbedtls_dhm_context *)ctx must already contain own_private)*/ |
| 2255 | + /* mbedtls 2.x: prime_len = ctx->len; */ |
| 2256 | + /* mbedtls 3.x: prime_len = mbedtls_dhm_get_len(ctx); */ |
| 2257 | + size_t olen = sizeof(RFC3526_PRIME_1536); /*(sizeof(); prime known)*/ |
| 2258 | + struct wpabuf *buf = wpabuf_alloc(olen); |
| 2259 | + if (buf == NULL) |
| 2260 | + return NULL; |
| 2261 | + if (mbedtls_dhm_read_public((mbedtls_dhm_context *)ctx, |
| 2262 | + wpabuf_head(peer_public), |
| 2263 | + wpabuf_len(peer_public)) == 0 |
| 2264 | + && mbedtls_dhm_calc_secret(ctx, wpabuf_mhead(buf), olen, &olen, |
| 2265 | + mbedtls_ctr_drbg_random, |
| 2266 | + crypto_mbedtls_ctr_drbg()) == 0) { |
| 2267 | + wpabuf_put(buf, olen); |
| 2268 | + return buf; |
| 2269 | + } |
| 2270 | + |
| 2271 | + wpabuf_free(buf); |
| 2272 | + return NULL; |
| 2273 | +} |
| 2274 | + |
| 2275 | +void dh5_free(void *ctx) |
| 2276 | +{ |
| 2277 | + mbedtls_dhm_free(ctx); |
| 2278 | + os_free(ctx); |
| 2279 | +} |
| 2280 | + |
| 2281 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_DH */ |
| 2282 | + |
| 2283 | + |
| 2284 | +#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC) |
| 2285 | + |
| 2286 | +#include <mbedtls/ecp.h> |
| 2287 | + |
| 2288 | +#define CRYPTO_EC_pbits(e) (((mbedtls_ecp_group *)(e))->pbits) |
| 2289 | +#define CRYPTO_EC_plen(e) ((((mbedtls_ecp_group *)(e))->pbits+7)>>3) |
| 2290 | +#define CRYPTO_EC_P(e) (&((mbedtls_ecp_group *)(e))->P) |
| 2291 | +#define CRYPTO_EC_N(e) (&((mbedtls_ecp_group *)(e))->N) |
| 2292 | +#define CRYPTO_EC_A(e) (&((mbedtls_ecp_group *)(e))->A) |
| 2293 | +#define CRYPTO_EC_B(e) (&((mbedtls_ecp_group *)(e))->B) |
| 2294 | +#define CRYPTO_EC_G(e) (&((mbedtls_ecp_group *)(e))->G) |
| 2295 | + |
| 2296 | +static mbedtls_ecp_group_id crypto_mbedtls_ecp_group_id_from_ike_id(int group) |
| 2297 | +{ |
| 2298 | + /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */ |
| 2299 | + switch (group) { |
| 2300 | + #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED |
| 2301 | + case 19: return MBEDTLS_ECP_DP_SECP256R1; |
| 2302 | + #endif |
| 2303 | + #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED |
| 2304 | + case 20: return MBEDTLS_ECP_DP_SECP384R1; |
| 2305 | + #endif |
| 2306 | + #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED |
| 2307 | + case 21: return MBEDTLS_ECP_DP_SECP521R1; |
| 2308 | + #endif |
| 2309 | + #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED |
| 2310 | + case 25: return MBEDTLS_ECP_DP_SECP192R1; |
| 2311 | + #endif |
| 2312 | + #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED |
| 2313 | + case 26: return MBEDTLS_ECP_DP_SECP224R1; |
| 2314 | + #endif |
| 2315 | + #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED |
| 2316 | + case 28: return MBEDTLS_ECP_DP_BP256R1; |
| 2317 | + #endif |
| 2318 | + #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED |
| 2319 | + case 29: return MBEDTLS_ECP_DP_BP384R1; |
| 2320 | + #endif |
| 2321 | + #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED |
| 2322 | + case 30: return MBEDTLS_ECP_DP_BP512R1; |
| 2323 | + #endif |
| 2324 | + #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED |
| 2325 | + case 31: return MBEDTLS_ECP_DP_CURVE25519; |
| 2326 | + #endif |
| 2327 | + #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED |
| 2328 | + case 32: return MBEDTLS_ECP_DP_CURVE448; |
| 2329 | + #endif |
| 2330 | + default: return MBEDTLS_ECP_DP_NONE; |
| 2331 | + } |
| 2332 | +} |
| 2333 | + |
| 2334 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC |
| 2335 | +static int crypto_mbedtls_ike_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id) |
| 2336 | +{ |
| 2337 | + /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */ |
| 2338 | + /*(for crypto_ec_key_group())*/ |
| 2339 | + switch (grp_id) { |
| 2340 | + #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED |
| 2341 | + case MBEDTLS_ECP_DP_SECP256R1: return 19; |
| 2342 | + #endif |
| 2343 | + #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED |
| 2344 | + case MBEDTLS_ECP_DP_SECP384R1: return 20; |
| 2345 | + #endif |
| 2346 | + #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED |
| 2347 | + case MBEDTLS_ECP_DP_SECP521R1: return 21; |
| 2348 | + #endif |
| 2349 | + #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED |
| 2350 | + case MBEDTLS_ECP_DP_SECP192R1: return 25; |
| 2351 | + #endif |
| 2352 | + #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED |
| 2353 | + case MBEDTLS_ECP_DP_SECP224R1: return 26; |
| 2354 | + #endif |
| 2355 | + #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED |
| 2356 | + case MBEDTLS_ECP_DP_BP256R1: return 28; |
| 2357 | + #endif |
| 2358 | + #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED |
| 2359 | + case MBEDTLS_ECP_DP_BP384R1: return 29; |
| 2360 | + #endif |
| 2361 | + #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED |
| 2362 | + case MBEDTLS_ECP_DP_BP512R1: return 30; |
| 2363 | + #endif |
| 2364 | + #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED |
| 2365 | + case MBEDTLS_ECP_DP_CURVE25519: return 31; |
| 2366 | + #endif |
| 2367 | + #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED |
| 2368 | + case MBEDTLS_ECP_DP_CURVE448: return 32; |
| 2369 | + #endif |
| 2370 | + default: return -1; |
| 2371 | + } |
| 2372 | +} |
| 2373 | +#endif |
| 2374 | + |
| 2375 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH || CRYPTO_MBEDTLS_CRYPTO_EC */ |
| 2376 | + |
| 2377 | + |
| 2378 | +#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC_DPP) |
| 2379 | + |
| 2380 | +#include <mbedtls/ecp.h> |
| 2381 | +#include <mbedtls/pk.h> |
| 2382 | + |
| 2383 | +static int crypto_mbedtls_keypair_gen(int group, mbedtls_pk_context *pk) |
| 2384 | +{ |
| 2385 | + mbedtls_ecp_group_id grp_id = |
| 2386 | + crypto_mbedtls_ecp_group_id_from_ike_id(group); |
| 2387 | + if (grp_id == MBEDTLS_ECP_DP_NONE) |
| 2388 | + return -1; |
| 2389 | + const mbedtls_pk_info_t *pk_info = |
| 2390 | + mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); |
| 2391 | + if (pk_info == NULL) |
| 2392 | + return -1; |
| 2393 | + return mbedtls_pk_setup(pk, pk_info) |
| 2394 | + || mbedtls_ecp_gen_key(grp_id, mbedtls_pk_ec(*pk), |
| 2395 | + mbedtls_ctr_drbg_random, |
| 2396 | + crypto_mbedtls_ctr_drbg()) ? -1 : 0; |
| 2397 | +} |
| 2398 | + |
| 2399 | +#endif |
| 2400 | + |
| 2401 | + |
| 2402 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_ECDH |
| 2403 | + |
| 2404 | +#include <mbedtls/ecdh.h> |
| 2405 | +#include <mbedtls/ecdsa.h> |
| 2406 | +#include <mbedtls/ecp.h> |
| 2407 | +#include <mbedtls/pk.h> |
| 2408 | + |
| 2409 | +/* wrap mbedtls_ecdh_context for more future-proof direct access to components |
| 2410 | + * (mbedtls_ecdh_context internal implementation may change between releases) |
| 2411 | + * |
| 2412 | + * If mbedtls_pk_context -- specifically underlying mbedtls_ecp_keypair -- |
| 2413 | + * lifetime were guaranteed to be longer than that of mbedtls_ecdh_context, |
| 2414 | + * then mbedtls_pk_context or mbedtls_ecp_keypair could be stored in crypto_ecdh |
| 2415 | + * (or crypto_ec_key could be stored in crypto_ecdh, and crypto_ec_key could |
| 2416 | + * wrap mbedtls_ecp_keypair and components, to avoid MBEDTLS_PRIVATE access) */ |
| 2417 | +struct crypto_ecdh { |
| 2418 | + mbedtls_ecdh_context ctx; |
| 2419 | + mbedtls_ecp_group grp; |
| 2420 | + mbedtls_ecp_point Q; |
| 2421 | +}; |
| 2422 | + |
| 2423 | +struct crypto_ecdh * crypto_ecdh_init(int group) |
| 2424 | +{ |
| 2425 | + mbedtls_pk_context pk; |
| 2426 | + mbedtls_pk_init(&pk); |
| 2427 | + struct crypto_ecdh *ecdh = crypto_mbedtls_keypair_gen(group, &pk) == 0 |
| 2428 | + ? crypto_ecdh_init2(group, (struct crypto_ec_key *)&pk) |
| 2429 | + : NULL; |
| 2430 | + mbedtls_pk_free(&pk); |
| 2431 | + return ecdh; |
| 2432 | +} |
| 2433 | + |
| 2434 | +struct crypto_ecdh * crypto_ecdh_init2(int group, |
| 2435 | + struct crypto_ec_key *own_key) |
| 2436 | +{ |
| 2437 | + mbedtls_ecp_group_id grp_id = |
| 2438 | + crypto_mbedtls_ecp_group_id_from_ike_id(group); |
| 2439 | + if (grp_id == MBEDTLS_ECP_DP_NONE) |
| 2440 | + return NULL; |
| 2441 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)own_key); |
| 2442 | + struct crypto_ecdh *ecdh = os_malloc(sizeof(*ecdh)); |
| 2443 | + if (ecdh == NULL) |
| 2444 | + return NULL; |
| 2445 | + mbedtls_ecdh_init(&ecdh->ctx); |
| 2446 | + mbedtls_ecp_group_init(&ecdh->grp); |
| 2447 | + mbedtls_ecp_point_init(&ecdh->Q); |
| 2448 | + if (mbedtls_ecdh_setup(&ecdh->ctx, grp_id) == 0 |
| 2449 | + && mbedtls_ecdh_get_params(&ecdh->ctx,ecp_kp,MBEDTLS_ECDH_OURS) == 0) { |
| 2450 | + /* copy grp and Q for later use |
| 2451 | + * (retrieving this info later is more convoluted |
| 2452 | + * even if mbedtls_ecdh_make_public() is considered)*/ |
| 2453 | + #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ |
| 2454 | + mbedtls_mpi d; |
| 2455 | + mbedtls_mpi_init(&d); |
| 2456 | + if (mbedtls_ecp_export(ecp_kp, &ecdh->grp, &d, &ecdh->Q) == 0) { |
| 2457 | + mbedtls_mpi_free(&d); |
| 2458 | + return ecdh; |
| 2459 | + } |
| 2460 | + mbedtls_mpi_free(&d); |
| 2461 | + #else |
| 2462 | + if (mbedtls_ecp_group_load(&ecdh->grp, grp_id) == 0 |
| 2463 | + && mbedtls_ecp_copy(&ecdh->Q, &ecp_kp->MBEDTLS_PRIVATE(Q)) == 0) |
| 2464 | + return ecdh; |
| 2465 | + #endif |
| 2466 | + } |
| 2467 | + |
| 2468 | + mbedtls_ecp_point_free(&ecdh->Q); |
| 2469 | + mbedtls_ecp_group_free(&ecdh->grp); |
| 2470 | + mbedtls_ecdh_free(&ecdh->ctx); |
| 2471 | + os_free(ecdh); |
| 2472 | + return NULL; |
| 2473 | +} |
| 2474 | + |
| 2475 | +struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y) |
| 2476 | +{ |
| 2477 | + mbedtls_ecp_group *grp = &ecdh->grp; |
| 2478 | + size_t len = CRYPTO_EC_plen(grp); |
| 2479 | + #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED |
| 2480 | + /* len */ |
| 2481 | + #endif |
| 2482 | + #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED |
| 2483 | + if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) |
| 2484 | + len = inc_y ? len*2+1 : len+1; |
| 2485 | + #endif |
| 2486 | + struct wpabuf *buf = wpabuf_alloc(len); |
| 2487 | + if (buf == NULL) |
| 2488 | + return NULL; |
| 2489 | + inc_y = inc_y ? MBEDTLS_ECP_PF_UNCOMPRESSED : MBEDTLS_ECP_PF_COMPRESSED; |
| 2490 | + if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &len, |
| 2491 | + wpabuf_mhead_u8(buf), len) == 0) { |
| 2492 | + wpabuf_put(buf, len); |
| 2493 | + return buf; |
| 2494 | + } |
| 2495 | + |
| 2496 | + wpabuf_free(buf); |
| 2497 | + return NULL; |
| 2498 | +} |
| 2499 | + |
| 2500 | +#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) |
| 2501 | +static int crypto_mbedtls_short_weierstrass_derive_y(mbedtls_ecp_group *grp, |
| 2502 | + mbedtls_mpi *bn, |
| 2503 | + int parity_bit) |
| 2504 | +{ |
| 2505 | + /* y^2 = x^3 + ax + b |
| 2506 | + * sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */ |
| 2507 | + mbedtls_mpi *cy2 = (mbedtls_mpi *) |
| 2508 | + crypto_ec_point_compute_y_sqr((struct crypto_ec *)grp, |
| 2509 | + (const struct crypto_bignum *)bn); /*x*/ |
| 2510 | + if (cy2 == NULL) |
| 2511 | + return -1; |
| 2512 | + |
| 2513 | + /*mbedtls_mpi_free(bn);*/ |
| 2514 | + /*(reuse bn to store result (y))*/ |
| 2515 | + |
| 2516 | + mbedtls_mpi exp; |
| 2517 | + mbedtls_mpi_init(&exp); |
| 2518 | + int ret = mbedtls_mpi_get_bit(&grp->P, 0) != 1 /*(p = 3 mod 4)*/ |
| 2519 | + || mbedtls_mpi_get_bit(&grp->P, 1) != 1 /*(p = 3 mod 4)*/ |
| 2520 | + || mbedtls_mpi_add_int(&exp, &grp->P, 1) |
| 2521 | + || mbedtls_mpi_shift_r(&exp, 2) |
| 2522 | + || mbedtls_mpi_exp_mod(bn, cy2, &exp, &grp->P, NULL) |
| 2523 | + || (mbedtls_mpi_get_bit(bn, 0) != parity_bit |
| 2524 | + && mbedtls_mpi_sub_mpi(bn, &grp->P, bn)); |
| 2525 | + mbedtls_mpi_free(&exp); |
| 2526 | + mbedtls_mpi_free(cy2); |
| 2527 | + os_free(cy2); |
| 2528 | + return ret; |
| 2529 | +} |
| 2530 | +#endif |
| 2531 | + |
| 2532 | +struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, |
| 2533 | + const u8 *key, size_t len) |
| 2534 | +{ |
| 2535 | + if (len == 0) /*(invalid peer key)*/ |
| 2536 | + return NULL; |
| 2537 | + |
| 2538 | + mbedtls_ecp_group *grp = &ecdh->grp; |
| 2539 | + |
| 2540 | + #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) |
| 2541 | + if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { |
| 2542 | + /* add header for mbedtls_ecdh_read_public() */ |
| 2543 | + u8 buf[256]; |
| 2544 | + if (sizeof(buf)-1 < len) |
| 2545 | + return NULL; |
| 2546 | + buf[0] = (u8)(len); |
| 2547 | + os_memcpy(buf+1, key, len); |
| 2548 | + |
| 2549 | + if (inc_y) { |
| 2550 | + if (!(len & 1)) { /*(dpp code/tests does not include tag?!?)*/ |
| 2551 | + if (sizeof(buf)-2 < len) |
| 2552 | + return NULL; |
| 2553 | + buf[0] = (u8)(1+len); |
| 2554 | + buf[1] = 0x04; |
| 2555 | + os_memcpy(buf+2, key, len); |
| 2556 | + } |
| 2557 | + len >>= 1; /*(repurpose len to prime_len)*/ |
| 2558 | + } |
| 2559 | + else if (key[0] == 0x02 || key[0] == 0x03) { /* (inc_y == 0) */ |
| 2560 | + --len; /*(repurpose len to prime_len)*/ |
| 2561 | + |
| 2562 | + /* mbedtls_ecp_point_read_binary() does not currently support |
| 2563 | + * MBEDTLS_ECP_PF_COMPRESSED format (buf[1] = 0x02 or 0x03) |
| 2564 | + * (returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) */ |
| 2565 | + |
| 2566 | + /* derive y, amend buf[] with y for UNCOMPRESSED format */ |
| 2567 | + if (sizeof(buf)-2 < len*2 || len == 0) |
| 2568 | + return NULL; |
| 2569 | + buf[0] = (u8)(1+len*2); |
| 2570 | + buf[1] = 0x04; |
| 2571 | + mbedtls_mpi bn; |
| 2572 | + mbedtls_mpi_init(&bn); |
| 2573 | + int ret = mbedtls_mpi_read_binary(&bn, key+1, len) |
| 2574 | + || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn, |
| 2575 | + key[0] & 1) |
| 2576 | + || mbedtls_mpi_write_binary(&bn, buf+2+len, len); |
| 2577 | + mbedtls_mpi_free(&bn); |
| 2578 | + if (ret != 0) |
| 2579 | + return NULL; |
| 2580 | + } |
| 2581 | + |
| 2582 | + if (key[0] == 0) /*(repurpose len to prime_len)*/ |
| 2583 | + len = CRYPTO_EC_plen(grp); |
| 2584 | + |
| 2585 | + if (mbedtls_ecdh_read_public(&ecdh->ctx, buf, buf[0]+1)) |
| 2586 | + return NULL; |
| 2587 | + } |
| 2588 | + #endif |
| 2589 | + #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) |
| 2590 | + if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { |
| 2591 | + if (mbedtls_ecdh_read_public(&ecdh->ctx, key, len)) |
| 2592 | + return NULL; |
| 2593 | + } |
| 2594 | + #endif |
| 2595 | + |
| 2596 | + struct wpabuf *buf = wpabuf_alloc(len); |
| 2597 | + if (buf == NULL) |
| 2598 | + return NULL; |
| 2599 | + |
| 2600 | + if (mbedtls_ecdh_calc_secret(&ecdh->ctx, &len, |
| 2601 | + wpabuf_mhead(buf), len, |
| 2602 | + mbedtls_ctr_drbg_random, |
| 2603 | + crypto_mbedtls_ctr_drbg()) == 0) { |
| 2604 | + wpabuf_put(buf, len); |
| 2605 | + return buf; |
| 2606 | + } |
| 2607 | + |
| 2608 | + wpabuf_clear_free(buf); |
| 2609 | + return NULL; |
| 2610 | +} |
| 2611 | + |
| 2612 | +void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) |
| 2613 | +{ |
| 2614 | + if (ecdh == NULL) |
| 2615 | + return; |
| 2616 | + mbedtls_ecp_point_free(&ecdh->Q); |
| 2617 | + mbedtls_ecp_group_free(&ecdh->grp); |
| 2618 | + mbedtls_ecdh_free(&ecdh->ctx); |
| 2619 | + os_free(ecdh); |
| 2620 | +} |
| 2621 | + |
| 2622 | +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) |
| 2623 | +{ |
| 2624 | + return CRYPTO_EC_plen(&ecdh->grp); |
| 2625 | +} |
| 2626 | + |
| 2627 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH */ |
| 2628 | + |
| 2629 | + |
| 2630 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC |
| 2631 | + |
| 2632 | +#include <mbedtls/ecp.h> |
| 2633 | + |
| 2634 | +struct crypto_ec *crypto_ec_init(int group) |
| 2635 | +{ |
| 2636 | + mbedtls_ecp_group_id grp_id = |
| 2637 | + crypto_mbedtls_ecp_group_id_from_ike_id(group); |
| 2638 | + if (grp_id == MBEDTLS_ECP_DP_NONE) |
| 2639 | + return NULL; |
| 2640 | + mbedtls_ecp_group *e = os_malloc(sizeof(*e)); |
| 2641 | + if (e == NULL) |
| 2642 | + return NULL; |
| 2643 | + mbedtls_ecp_group_init(e); |
| 2644 | + if (mbedtls_ecp_group_load(e, grp_id) == 0) |
| 2645 | + return (struct crypto_ec *)e; |
| 2646 | + |
| 2647 | + mbedtls_ecp_group_free(e); |
| 2648 | + os_free(e); |
| 2649 | + return NULL; |
| 2650 | +} |
| 2651 | + |
| 2652 | +void crypto_ec_deinit(struct crypto_ec *e) |
| 2653 | +{ |
| 2654 | + mbedtls_ecp_group_free((mbedtls_ecp_group *)e); |
| 2655 | + os_free(e); |
| 2656 | +} |
| 2657 | + |
| 2658 | +size_t crypto_ec_prime_len(struct crypto_ec *e) |
| 2659 | +{ |
| 2660 | + return CRYPTO_EC_plen(e); |
| 2661 | +} |
| 2662 | + |
| 2663 | +size_t crypto_ec_prime_len_bits(struct crypto_ec *e) |
| 2664 | +{ |
| 2665 | + return CRYPTO_EC_pbits(e); |
| 2666 | +} |
| 2667 | + |
| 2668 | +size_t crypto_ec_order_len(struct crypto_ec *e) |
| 2669 | +{ |
| 2670 | + return (mbedtls_mpi_bitlen(CRYPTO_EC_N(e)) + 7) / 8; |
| 2671 | +} |
| 2672 | + |
| 2673 | +const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e) |
| 2674 | +{ |
| 2675 | + return (const struct crypto_bignum *)CRYPTO_EC_P(e); |
| 2676 | +} |
| 2677 | + |
| 2678 | +const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e) |
| 2679 | +{ |
| 2680 | + return (const struct crypto_bignum *)CRYPTO_EC_N(e); |
| 2681 | +} |
| 2682 | + |
| 2683 | +const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e) |
| 2684 | +{ |
| 2685 | + static const uint8_t secp256r1_a[] = |
| 2686 | + {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01, |
| 2687 | + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, |
| 2688 | + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff, |
| 2689 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc}; |
| 2690 | + static const uint8_t secp384r1_a[] = |
| 2691 | + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2692 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2693 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2694 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, |
| 2695 | + 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00, |
| 2696 | + 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfc}; |
| 2697 | + static const uint8_t secp521r1_a[] = |
| 2698 | + {0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2699 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2700 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2701 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2702 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2703 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2704 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2705 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2706 | + 0xff,0xfc}; |
| 2707 | + static const uint8_t secp192r1_a[] = |
| 2708 | + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2709 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, |
| 2710 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc}; |
| 2711 | + static const uint8_t secp224r1_a[] = |
| 2712 | + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2713 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe, |
| 2714 | + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, |
| 2715 | + 0xff,0xff,0xff,0xfe}; |
| 2716 | + |
| 2717 | + const uint8_t *bin = NULL; |
| 2718 | + size_t len = 0; |
| 2719 | + |
| 2720 | + /* (mbedtls groups matching supported sswu_curve_param() IKE groups) */ |
| 2721 | + switch (((mbedtls_ecp_group *)e)->id) { |
| 2722 | + #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED |
| 2723 | + case MBEDTLS_ECP_DP_SECP256R1: |
| 2724 | + bin = secp256r1_a; |
| 2725 | + len = sizeof(secp256r1_a); |
| 2726 | + break; |
| 2727 | + #endif |
| 2728 | + #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED |
| 2729 | + case MBEDTLS_ECP_DP_SECP384R1: |
| 2730 | + bin = secp384r1_a; |
| 2731 | + len = sizeof(secp384r1_a); |
| 2732 | + break; |
| 2733 | + #endif |
| 2734 | + #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED |
| 2735 | + case MBEDTLS_ECP_DP_SECP521R1: |
| 2736 | + bin = secp521r1_a; |
| 2737 | + len = sizeof(secp521r1_a); |
| 2738 | + break; |
| 2739 | + #endif |
| 2740 | + #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED |
| 2741 | + case MBEDTLS_ECP_DP_SECP192R1: |
| 2742 | + bin = secp192r1_a; |
| 2743 | + len = sizeof(secp192r1_a); |
| 2744 | + break; |
| 2745 | + #endif |
| 2746 | + #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED |
| 2747 | + case MBEDTLS_ECP_DP_SECP224R1: |
| 2748 | + bin = secp224r1_a; |
| 2749 | + len = sizeof(secp224r1_a); |
| 2750 | + break; |
| 2751 | + #endif |
| 2752 | + #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED |
| 2753 | + case MBEDTLS_ECP_DP_BP256R1: |
| 2754 | + return (const struct crypto_bignum *)CRYPTO_EC_A(e); |
| 2755 | + #endif |
| 2756 | + #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED |
| 2757 | + case MBEDTLS_ECP_DP_BP384R1: |
| 2758 | + return (const struct crypto_bignum *)CRYPTO_EC_A(e); |
| 2759 | + #endif |
| 2760 | + #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED |
| 2761 | + case MBEDTLS_ECP_DP_BP512R1: |
| 2762 | + return (const struct crypto_bignum *)CRYPTO_EC_A(e); |
| 2763 | + #endif |
| 2764 | + #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED |
| 2765 | + case MBEDTLS_ECP_DP_CURVE25519: |
| 2766 | + return (const struct crypto_bignum *)CRYPTO_EC_A(e); |
| 2767 | + #endif |
| 2768 | + #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED |
| 2769 | + case MBEDTLS_ECP_DP_CURVE448: |
| 2770 | + return (const struct crypto_bignum *)CRYPTO_EC_A(e); |
| 2771 | + #endif |
| 2772 | + default: |
| 2773 | + return NULL; |
| 2774 | + } |
| 2775 | + |
| 2776 | + /*(note: not thread-safe; returns file-scoped static storage)*/ |
| 2777 | + if (mbedtls_mpi_read_binary(&mpi_sw_A, bin, len) == 0) |
| 2778 | + return (const struct crypto_bignum *)&mpi_sw_A; |
| 2779 | + return NULL; |
| 2780 | +} |
| 2781 | + |
| 2782 | +const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e) |
| 2783 | +{ |
| 2784 | + return (const struct crypto_bignum *)CRYPTO_EC_B(e); |
| 2785 | +} |
| 2786 | + |
| 2787 | +const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e) |
| 2788 | +{ |
| 2789 | + return (const struct crypto_ec_point *)CRYPTO_EC_G(e); |
| 2790 | +} |
| 2791 | + |
| 2792 | +struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e) |
| 2793 | +{ |
| 2794 | + mbedtls_ecp_point *p = os_malloc(sizeof(*p)); |
| 2795 | + if (p != NULL) |
| 2796 | + mbedtls_ecp_point_init(p); |
| 2797 | + return (struct crypto_ec_point *)p; |
| 2798 | +} |
| 2799 | + |
| 2800 | +void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) |
| 2801 | +{ |
| 2802 | + mbedtls_ecp_point_free((mbedtls_ecp_point *)p); |
| 2803 | + os_free(p); |
| 2804 | +} |
| 2805 | + |
| 2806 | +int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p, |
| 2807 | + struct crypto_bignum *x) |
| 2808 | +{ |
| 2809 | + mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X); |
| 2810 | + return mbedtls_mpi_copy((mbedtls_mpi *)x, px) |
| 2811 | + ? -1 |
| 2812 | + : 0; |
| 2813 | +} |
| 2814 | + |
| 2815 | +int crypto_ec_point_to_bin(struct crypto_ec *e, |
| 2816 | + const struct crypto_ec_point *point, u8 *x, u8 *y) |
| 2817 | +{ |
| 2818 | + /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */ |
| 2819 | + size_t len = CRYPTO_EC_plen(e); |
| 2820 | + if (x) { |
| 2821 | + mbedtls_mpi *px = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X); |
| 2822 | + if (mbedtls_mpi_write_binary(px, x, len)) |
| 2823 | + return -1; |
| 2824 | + } |
| 2825 | + if (y) { |
| 2826 | + #if 0 /*(should not be necessary; py mpi should be in initial state)*/ |
| 2827 | + #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED |
| 2828 | + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) |
| 2829 | + == MBEDTLS_ECP_TYPE_MONTGOMERY) { |
| 2830 | + os_memset(y, 0, len); |
| 2831 | + return 0; |
| 2832 | + } |
| 2833 | + #endif |
| 2834 | + #endif |
| 2835 | + mbedtls_mpi *py = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y); |
| 2836 | + if (mbedtls_mpi_write_binary(py, y, len)) |
| 2837 | + return -1; |
| 2838 | + } |
| 2839 | + return 0; |
| 2840 | +} |
| 2841 | + |
| 2842 | +struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, |
| 2843 | + const u8 *val) |
| 2844 | +{ |
| 2845 | + size_t len = CRYPTO_EC_plen(e); |
| 2846 | + mbedtls_ecp_point *p = os_malloc(sizeof(*p)); |
| 2847 | + u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2]; |
| 2848 | + if (p == NULL) |
| 2849 | + return NULL; |
| 2850 | + mbedtls_ecp_point_init(p); |
| 2851 | + |
| 2852 | + #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED |
| 2853 | + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) |
| 2854 | + == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { |
| 2855 | + #if 0 /* prefer alternative to MBEDTLS_PRIVATE() access */ |
| 2856 | + mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X); |
| 2857 | + mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); |
| 2858 | + mbedtls_mpi *pz = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z); |
| 2859 | + |
| 2860 | + if (mbedtls_mpi_read_binary(px, val, len) == 0 |
| 2861 | + && mbedtls_mpi_read_binary(py, val + len, len) == 0 |
| 2862 | + && mbedtls_mpi_lset(pz, 1) == 0) |
| 2863 | + return (struct crypto_ec_point *)p; |
| 2864 | + #else |
| 2865 | + buf[0] = 0x04; |
| 2866 | + os_memcpy(buf+1, val, len*2); |
| 2867 | + if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p, |
| 2868 | + buf, 1+len*2) == 0) |
| 2869 | + return (struct crypto_ec_point *)p; |
| 2870 | + #endif |
| 2871 | + } |
| 2872 | + #endif |
| 2873 | + #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED |
| 2874 | + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) |
| 2875 | + == MBEDTLS_ECP_TYPE_MONTGOMERY) { |
| 2876 | + /* crypto.h interface documents crypto_ec_point_from_bin() |
| 2877 | + * val is length: prime_len * 2 and is big-endian |
| 2878 | + * (Short Weierstrass is assumed by hostap) |
| 2879 | + * Reverse to little-endian format for Montgomery */ |
| 2880 | + for (unsigned int i = 0; i < len; ++i) |
| 2881 | + buf[i] = val[len-1-i]; |
| 2882 | + if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p, |
| 2883 | + buf, len) == 0) |
| 2884 | + return (struct crypto_ec_point *)p; |
| 2885 | + } |
| 2886 | + #endif |
| 2887 | + |
| 2888 | + mbedtls_ecp_point_free(p); |
| 2889 | + os_free(p); |
| 2890 | + return NULL; |
| 2891 | +} |
| 2892 | + |
| 2893 | +int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, |
| 2894 | + const struct crypto_ec_point *b, |
| 2895 | + struct crypto_ec_point *c) |
| 2896 | +{ |
| 2897 | + /* mbedtls does not provide an mbedtls_ecp_point add function */ |
| 2898 | + mbedtls_mpi one; |
| 2899 | + mbedtls_mpi_init(&one); |
| 2900 | + int ret = mbedtls_mpi_lset(&one, 1) |
| 2901 | + || mbedtls_ecp_muladd( |
| 2902 | + (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)c, |
| 2903 | + &one, (const mbedtls_ecp_point *)a, |
| 2904 | + &one, (const mbedtls_ecp_point *)b) ? -1 : 0; |
| 2905 | + mbedtls_mpi_free(&one); |
| 2906 | + return ret; |
| 2907 | +} |
| 2908 | + |
| 2909 | +int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, |
| 2910 | + const struct crypto_bignum *b, |
| 2911 | + struct crypto_ec_point *res) |
| 2912 | +{ |
| 2913 | + return mbedtls_ecp_mul( |
| 2914 | + (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res, |
| 2915 | + (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p, |
| 2916 | + mbedtls_ctr_drbg_random, crypto_mbedtls_ctr_drbg()) ? -1 : 0; |
| 2917 | +} |
| 2918 | + |
| 2919 | +int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) |
| 2920 | +{ |
| 2921 | + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) |
| 2922 | + == MBEDTLS_ECP_TYPE_MONTGOMERY) { |
| 2923 | + /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */ |
| 2924 | + wpa_printf(MSG_ERROR, |
| 2925 | + "%s not implemented for Montgomery curves",__func__); |
| 2926 | + return -1; |
| 2927 | + } |
| 2928 | + |
| 2929 | + /* mbedtls does not provide an mbedtls_ecp_point invert function */ |
| 2930 | + /* below works for Short Weierstrass; incorrect for Montgomery curves */ |
| 2931 | + mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); |
| 2932 | + return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p) /*point at infinity*/ |
| 2933 | + || mbedtls_mpi_cmp_int(py, 0) == 0 /*point is its own inverse*/ |
| 2934 | + || mbedtls_mpi_sub_abs(py, CRYPTO_EC_P(e), py) == 0 ? 0 : -1; |
| 2935 | +} |
| 2936 | + |
| 2937 | +#ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED |
| 2938 | +static int |
| 2939 | +crypto_ec_point_y_sqr_weierstrass(mbedtls_ecp_group *e, const mbedtls_mpi *x, |
| 2940 | + mbedtls_mpi *y2) |
| 2941 | +{ |
| 2942 | + /* MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS y^2 = x^3 + a x + b */ |
| 2943 | + |
| 2944 | + /* Short Weierstrass elliptic curve group w/o A set treated as A = -3 */ |
| 2945 | + /* Attempt to match mbedtls/library/ecp.c:ecp_check_pubkey_sw() behavior |
| 2946 | + * and elsewhere in mbedtls/library/ecp.c where if A is not set, it is |
| 2947 | + * treated as if A = -3. */ |
| 2948 | + |
| 2949 | + #if 0 |
| 2950 | + /* y^2 = x^3 + ax + b */ |
| 2951 | + mbedtls_mpi *A = &e->A; |
| 2952 | + mbedtls_mpi t, A_neg3; |
| 2953 | + if (&e->A.p == NULL) { |
| 2954 | + mbedtls_mpi_init(&A_neg3); |
| 2955 | + if (mbedtls_mpi_lset(&A_neg3, -3) != 0) { |
| 2956 | + mbedtls_mpi_free(&A_neg3); |
| 2957 | + return -1; |
| 2958 | + } |
| 2959 | + A = &A_neg3; |
| 2960 | + } |
| 2961 | + mbedtls_mpi_init(&t); |
| 2962 | + int ret = /* x^3 */ |
| 2963 | + mbedtls_mpi_lset(&t, 3) |
| 2964 | + || mbedtls_mpi_exp_mod(y2, x, &t, &e->P, NULL) |
| 2965 | + /* ax */ |
| 2966 | + || mbedtls_mpi_mul_mpi(y2, y2, A) |
| 2967 | + || mbedtls_mpi_mod_mpi(&t, &t, &e->P) |
| 2968 | + /* ax + b */ |
| 2969 | + || mbedtls_mpi_add_mpi(&t, &t, &e->B) |
| 2970 | + || mbedtls_mpi_mod_mpi(&t, &t, &e->P) |
| 2971 | + /* x^3 + ax + b */ |
| 2972 | + || mbedtls_mpi_add_mpi(&t, &t, y2) /* ax + b + x^3 */ |
| 2973 | + || mbedtls_mpi_mod_mpi(y2, &t, &e->P); |
| 2974 | + mbedtls_mpi_free(&t); |
| 2975 | + if (A == &A_neg3) |
| 2976 | + mbedtls_mpi_free(&A_neg3); |
| 2977 | + return ret; /* 0: success, non-zero: failure */ |
| 2978 | + #else |
| 2979 | + /* y^2 = x^3 + ax + b = (x^2 + a)x + b */ |
| 2980 | + return /* x^2 */ |
| 2981 | + mbedtls_mpi_mul_mpi(y2, x, x) |
| 2982 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P) |
| 2983 | + /* x^2 + a */ |
| 2984 | + || (e->A.MBEDTLS_PRIVATE(p) |
| 2985 | + ? mbedtls_mpi_add_mpi(y2, y2, &e->A) |
| 2986 | + : mbedtls_mpi_sub_int(y2, y2, 3)) |
| 2987 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P) |
| 2988 | + /* (x^2 + a)x */ |
| 2989 | + || mbedtls_mpi_mul_mpi(y2, y2, x) |
| 2990 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P) |
| 2991 | + /* (x^2 + a)x + b */ |
| 2992 | + || mbedtls_mpi_add_mpi(y2, y2, &e->B) |
| 2993 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P); |
| 2994 | + #endif |
| 2995 | +} |
| 2996 | +#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */ |
| 2997 | + |
| 2998 | +#if 0 /* not used by hostap */ |
| 2999 | +#ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED |
| 3000 | +static int |
| 3001 | +crypto_ec_point_y_sqr_montgomery(mbedtls_ecp_group *e, const mbedtls_mpi *x, |
| 3002 | + mbedtls_mpi *y2) |
| 3003 | +{ |
| 3004 | + /* XXX: !!! must be reviewed and audited for correctness !!! */ |
| 3005 | + |
| 3006 | + /* MBEDTLS_ECP_TYPE_MONTGOMERY y^2 = x^3 + a x^2 + x */ |
| 3007 | + |
| 3008 | + /* y^2 = x^3 + a x^2 + x = (x + a)x^2 + x */ |
| 3009 | + mbedtls_mpi x2; |
| 3010 | + mbedtls_mpi_init(&x2); |
| 3011 | + int ret = /* x^2 */ |
| 3012 | + mbedtls_mpi_mul_mpi(&x2, x, x) |
| 3013 | + || mbedtls_mpi_mod_mpi(&x2, &x2, &e->P) |
| 3014 | + /* x + a */ |
| 3015 | + || mbedtls_mpi_add_mpi(y2, x, &e->A) |
| 3016 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P) |
| 3017 | + /* (x + a)x^2 */ |
| 3018 | + || mbedtls_mpi_mul_mpi(y2, y2, &x2) |
| 3019 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P) |
| 3020 | + /* (x + a)x^2 + x */ |
| 3021 | + || mbedtls_mpi_add_mpi(y2, y2, x) |
| 3022 | + || mbedtls_mpi_mod_mpi(y2, y2, &e->P); |
| 3023 | + mbedtls_mpi_free(&x2); |
| 3024 | + return ret; /* 0: success, non-zero: failure */ |
| 3025 | +} |
| 3026 | +#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */ |
| 3027 | +#endif |
| 3028 | + |
| 3029 | +struct crypto_bignum * |
| 3030 | +crypto_ec_point_compute_y_sqr(struct crypto_ec *e, |
| 3031 | + const struct crypto_bignum *x) |
| 3032 | +{ |
| 3033 | + mbedtls_mpi *y2 = os_malloc(sizeof(*y2)); |
| 3034 | + if (y2 == NULL) |
| 3035 | + return NULL; |
| 3036 | + mbedtls_mpi_init(y2); |
| 3037 | + |
| 3038 | + #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED |
| 3039 | + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) |
| 3040 | + == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS |
| 3041 | + && crypto_ec_point_y_sqr_weierstrass((mbedtls_ecp_group *)e, |
| 3042 | + (const mbedtls_mpi *)x, |
| 3043 | + y2) == 0) |
| 3044 | + return (struct crypto_bignum *)y2; |
| 3045 | + #endif |
| 3046 | + #if 0 /* not used by hostap */ |
| 3047 | + #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED |
| 3048 | + if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e) |
| 3049 | + == MBEDTLS_ECP_TYPE_MONTGOMERY |
| 3050 | + && crypto_ec_point_y_sqr_montgomery((mbedtls_ecp_group *)e, |
| 3051 | + (const mbedtls_mpi *)x, |
| 3052 | + y2) == 0) |
| 3053 | + return (struct crypto_bignum *)y2; |
| 3054 | + #endif |
| 3055 | + #endif |
| 3056 | + |
| 3057 | + mbedtls_mpi_free(y2); |
| 3058 | + os_free(y2); |
| 3059 | + return NULL; |
| 3060 | +} |
| 3061 | + |
| 3062 | +int crypto_ec_point_is_at_infinity(struct crypto_ec *e, |
| 3063 | + const struct crypto_ec_point *p) |
| 3064 | +{ |
| 3065 | + return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p); |
| 3066 | +} |
| 3067 | + |
| 3068 | +int crypto_ec_point_is_on_curve(struct crypto_ec *e, |
| 3069 | + const struct crypto_ec_point *p) |
| 3070 | +{ |
| 3071 | + #if 1 |
| 3072 | + return mbedtls_ecp_check_pubkey((const mbedtls_ecp_group *)e, |
| 3073 | + (const mbedtls_ecp_point *)p) == 0; |
| 3074 | + #else |
| 3075 | + /* compute y^2 mod P and compare to y^2 mod P */ |
| 3076 | + /*(ref: src/eap_common/eap_pwd_common.c:compute_password_element())*/ |
| 3077 | + const mbedtls_mpi *px = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X); |
| 3078 | + mbedtls_mpi *cy2 = (mbedtls_mpi *) |
| 3079 | + crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *)px); |
| 3080 | + if (cy2 == NULL) |
| 3081 | + return 0; |
| 3082 | + |
| 3083 | + mbedtls_mpi y2; |
| 3084 | + mbedtls_mpi_init(&y2); |
| 3085 | + const mbedtls_mpi *py = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); |
| 3086 | + int is_on_curve = mbedtls_mpi_mul_mpi(&y2, py, py) /* y^2 mod P */ |
| 3087 | + || mbedtls_mpi_mod_mpi(&y2, &y2, CRYPTO_EC_P(e)) |
| 3088 | + || mbedtls_mpi_cmp_mpi(&y2, cy2) != 0 ? 0 : 1; |
| 3089 | + |
| 3090 | + mbedtls_mpi_free(&y2); |
| 3091 | + mbedtls_mpi_free(cy2); |
| 3092 | + os_free(cy2); |
| 3093 | + return is_on_curve; |
| 3094 | + #endif |
| 3095 | +} |
| 3096 | + |
| 3097 | +int crypto_ec_point_cmp(const struct crypto_ec *e, |
| 3098 | + const struct crypto_ec_point *a, |
| 3099 | + const struct crypto_ec_point *b) |
| 3100 | +{ |
| 3101 | + return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *)a, |
| 3102 | + (const mbedtls_ecp_point *)b); |
| 3103 | +} |
| 3104 | + |
| 3105 | +#if !defined(CONFIG_NO_STDOUT_DEBUG) |
| 3106 | +void crypto_ec_point_debug_print(const struct crypto_ec *e, |
| 3107 | + const struct crypto_ec_point *p, |
| 3108 | + const char *title) |
| 3109 | +{ |
| 3110 | + u8 x[MBEDTLS_MPI_MAX_SIZE]; |
| 3111 | + u8 y[MBEDTLS_MPI_MAX_SIZE]; |
| 3112 | + size_t len = CRYPTO_EC_plen(e); |
| 3113 | + /* crypto_ec_point_to_bin ought to take (const struct crypto_ec *e) */ |
| 3114 | + struct crypto_ec *ee; |
| 3115 | + *(const struct crypto_ec **)&ee = e; /*(cast away const)*/ |
| 3116 | + if (crypto_ec_point_to_bin(ee, p, x, y) == 0) { |
| 3117 | + if (title) |
| 3118 | + wpa_printf(MSG_DEBUG, "%s", title); |
| 3119 | + wpa_hexdump(MSG_DEBUG, "x:", x, len); |
| 3120 | + wpa_hexdump(MSG_DEBUG, "y:", y, len); |
| 3121 | + } |
| 3122 | +} |
| 3123 | +#endif |
| 3124 | + |
| 3125 | + |
| 3126 | +struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) |
| 3127 | +{ |
| 3128 | + mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); |
| 3129 | + if (ctx == NULL) |
| 3130 | + return NULL; |
| 3131 | + mbedtls_pk_init(ctx); |
| 3132 | + #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 3133 | + if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0) == 0) |
| 3134 | + #else |
| 3135 | + if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0, |
| 3136 | + mbedtls_ctr_drbg_random, |
| 3137 | + crypto_mbedtls_ctr_drbg()) == 0) |
| 3138 | + #endif |
| 3139 | + return (struct crypto_ec_key *)ctx; |
| 3140 | + |
| 3141 | + mbedtls_pk_free(ctx); |
| 3142 | + os_free(ctx); |
| 3143 | + return NULL; |
| 3144 | +} |
| 3145 | + |
| 3146 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE |
| 3147 | +#ifdef CONFIG_MODULE_TESTS |
| 3148 | +/*(for crypto_module_tests.c)*/ |
| 3149 | +struct crypto_ec_key * crypto_ec_key_set_priv(int group, |
| 3150 | + const u8 *raw, size_t raw_len) |
| 3151 | +{ |
| 3152 | + mbedtls_ecp_group_id grp_id = |
| 3153 | + crypto_mbedtls_ecp_group_id_from_ike_id(group); |
| 3154 | + if (grp_id == MBEDTLS_ECP_DP_NONE) |
| 3155 | + return NULL; |
| 3156 | + const mbedtls_pk_info_t *pk_info = |
| 3157 | + mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); |
| 3158 | + if (pk_info == NULL) |
| 3159 | + return NULL; |
| 3160 | + mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); |
| 3161 | + if (ctx == NULL) |
| 3162 | + return NULL; |
| 3163 | + mbedtls_pk_init(ctx); |
| 3164 | + if (mbedtls_pk_setup(ctx, pk_info) == 0 |
| 3165 | + && mbedtls_ecp_read_key(grp_id,mbedtls_pk_ec(*ctx),raw,raw_len) == 0) { |
| 3166 | + return (struct crypto_ec_key *)ctx; |
| 3167 | + } |
| 3168 | + |
| 3169 | + mbedtls_pk_free(ctx); |
| 3170 | + os_free(ctx); |
| 3171 | + return NULL; |
| 3172 | +} |
| 3173 | +#endif |
| 3174 | +#endif |
| 3175 | + |
| 3176 | +#include <mbedtls/error.h> |
| 3177 | +#include <mbedtls/oid.h> |
| 3178 | +static int crypto_mbedtls_pk_parse_subpubkey_compressed(mbedtls_pk_context *ctx, const u8 *der, size_t der_len) |
| 3179 | +{ |
| 3180 | + /* The following is modified from: |
| 3181 | + * mbedtls/library/pkparse.c:mbedtls_pk_parse_subpubkey() |
| 3182 | + * mbedtls/library/pkparse.c:pk_get_pk_alg() |
| 3183 | + * mbedtls/library/pkparse.c:pk_use_ecparams() |
| 3184 | + */ |
| 3185 | + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; |
| 3186 | + const mbedtls_pk_info_t *pk_info; |
| 3187 | + int ret; |
| 3188 | + size_t len; |
| 3189 | + const unsigned char *end = der+der_len; |
| 3190 | + unsigned char *p; |
| 3191 | + *(const unsigned char **)&p = der; |
| 3192 | + |
| 3193 | + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, |
| 3194 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) |
| 3195 | + { |
| 3196 | + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); |
| 3197 | + } |
| 3198 | + |
| 3199 | + end = p + len; |
| 3200 | + |
| 3201 | + /* |
| 3202 | + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 ) |
| 3203 | + return( ret ); |
| 3204 | + */ |
| 3205 | + mbedtls_asn1_buf alg_oid, params; |
| 3206 | + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); |
| 3207 | + if( ( ret = mbedtls_asn1_get_alg( &p, end, &alg_oid, ¶ms ) ) != 0 ) |
| 3208 | + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) ); |
| 3209 | + if( mbedtls_oid_get_pk_alg( &alg_oid, &pk_alg ) != 0 ) |
| 3210 | + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
| 3211 | + |
| 3212 | + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end, &len ) ) != 0 ) |
| 3213 | + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); |
| 3214 | + |
| 3215 | + if( p + len != end ) |
| 3216 | + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, |
| 3217 | + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); |
| 3218 | + |
| 3219 | + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) |
| 3220 | + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); |
| 3221 | + |
| 3222 | + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) |
| 3223 | + return( ret ); |
| 3224 | + |
| 3225 | + /* assume mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx) |
| 3226 | + * has already run with ctx initialized up to pk_get_ecpubkey(), |
| 3227 | + * and pk_get_ecpubkey() has returned MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE |
| 3228 | + * |
| 3229 | + * mbedtls mbedtls_ecp_point_read_binary() |
| 3230 | + * does not handle point in COMPRESSED format |
| 3231 | + * |
| 3232 | + * (validate assumption that algorithm is EC) */ |
| 3233 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx); |
| 3234 | + if (ecp_kp == NULL) |
| 3235 | + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
| 3236 | + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3237 | + mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); |
| 3238 | + mbedtls_ecp_group_id grp_id; |
| 3239 | + |
| 3240 | + |
| 3241 | + /* mbedtls/library/pkparse.c:pk_use_ecparams() */ |
| 3242 | + |
| 3243 | + if( params.tag == MBEDTLS_ASN1_OID ) |
| 3244 | + { |
| 3245 | + if( mbedtls_oid_get_ec_grp( ¶ms, &grp_id ) != 0 ) |
| 3246 | + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); |
| 3247 | + } |
| 3248 | + else |
| 3249 | + { |
| 3250 | +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) |
| 3251 | + /*(large code block not copied from mbedtls; unsupported)*/ |
| 3252 | + #if 0 |
| 3253 | + if( ( ret = pk_group_id_from_specified( ¶ms, &grp_id ) ) != 0 ) |
| 3254 | + return( ret ); |
| 3255 | + #endif |
| 3256 | +#endif |
| 3257 | + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
| 3258 | + } |
| 3259 | + |
| 3260 | + /* |
| 3261 | + * grp may already be initialized; if so, make sure IDs match |
| 3262 | + */ |
| 3263 | + if( ecp_kp_grp->id != MBEDTLS_ECP_DP_NONE && ecp_kp_grp->id != grp_id ) |
| 3264 | + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); |
| 3265 | + |
| 3266 | + if( ( ret = mbedtls_ecp_group_load( ecp_kp_grp, grp_id ) ) != 0 ) |
| 3267 | + return( ret ); |
| 3268 | + |
| 3269 | + |
| 3270 | + /* (validate assumption that EC point is in COMPRESSED format) */ |
| 3271 | + len = CRYPTO_EC_plen(ecp_kp_grp); |
| 3272 | + if( mbedtls_ecp_get_type(ecp_kp_grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS |
| 3273 | + || (end - p) != 1+len |
| 3274 | + || (*p != 0x02 && *p != 0x03) ) |
| 3275 | + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); |
| 3276 | + |
| 3277 | + /* Instead of calling mbedtls/library/pkparse.c:pk_get_ecpubkey() to call |
| 3278 | + * mbedtls_ecp_point_read_binary(), manually parse point into ecp_kp_Q */ |
| 3279 | + mbedtls_mpi *X = &ecp_kp_Q->MBEDTLS_PRIVATE(X); |
| 3280 | + mbedtls_mpi *Y = &ecp_kp_Q->MBEDTLS_PRIVATE(Y); |
| 3281 | + mbedtls_mpi *Z = &ecp_kp_Q->MBEDTLS_PRIVATE(Z); |
| 3282 | + ret = mbedtls_mpi_lset(Z, 1); |
| 3283 | + if (ret != 0) |
| 3284 | + return( ret ); |
| 3285 | + ret = mbedtls_mpi_read_binary(X, p+1, len); |
| 3286 | + if (ret != 0) |
| 3287 | + return( ret ); |
| 3288 | + /* derive Y |
| 3289 | + * (similar derivation of Y in crypto_mbedtls.c:crypto_ecdh_set_peerkey())*/ |
| 3290 | + ret = mbedtls_mpi_copy(Y, X) /*(Y is used as input and output obj below)*/ |
| 3291 | + || crypto_mbedtls_short_weierstrass_derive_y(ecp_kp_grp, Y, (*p & 1)); |
| 3292 | + if (ret != 0) |
| 3293 | + return( ret ); |
| 3294 | + |
| 3295 | + return mbedtls_ecp_check_pubkey( ecp_kp_grp, ecp_kp_Q ); |
| 3296 | +} |
| 3297 | + |
| 3298 | +struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) |
| 3299 | +{ |
| 3300 | + mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); |
| 3301 | + if (ctx == NULL) |
| 3302 | + return NULL; |
| 3303 | + mbedtls_pk_init(ctx); |
| 3304 | + /*int rc = mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx);*/ |
| 3305 | + int rc = mbedtls_pk_parse_public_key(ctx, der, der_len); |
| 3306 | + if (rc == 0) |
| 3307 | + return (struct crypto_ec_key *)ctx; |
| 3308 | + else if (rc == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) { |
| 3309 | + /* mbedtls mbedtls_ecp_point_read_binary() |
| 3310 | + * does not handle point in COMPRESSED format; parse internally */ |
| 3311 | + rc = crypto_mbedtls_pk_parse_subpubkey_compressed(ctx,der,der_len); |
| 3312 | + if (rc == 0) |
| 3313 | + return (struct crypto_ec_key *)ctx; |
| 3314 | + } |
| 3315 | + |
| 3316 | + mbedtls_pk_free(ctx); |
| 3317 | + os_free(ctx); |
| 3318 | + return NULL; |
| 3319 | +} |
| 3320 | + |
| 3321 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP |
| 3322 | + |
| 3323 | +static struct crypto_ec_key * |
| 3324 | +crypto_ec_key_set_pub_point_for_group(mbedtls_ecp_group_id grp_id, |
| 3325 | + const mbedtls_ecp_point *pub, |
| 3326 | + const u8 *buf, size_t len) |
| 3327 | +{ |
| 3328 | + const mbedtls_pk_info_t *pk_info = |
| 3329 | + mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY); |
| 3330 | + if (pk_info == NULL) |
| 3331 | + return NULL; |
| 3332 | + mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); |
| 3333 | + if (ctx == NULL) |
| 3334 | + return NULL; |
| 3335 | + mbedtls_pk_init(ctx); |
| 3336 | + if (mbedtls_pk_setup(ctx, pk_info) == 0) { |
| 3337 | + /* (Is private key generation necessary for callers?) |
| 3338 | + * alt: gen key then overwrite Q |
| 3339 | + * mbedtls_ecp_gen_key(grp_id, ecp_kp, |
| 3340 | + * mbedtls_ctr_drbg_random, |
| 3341 | + * crypto_mbedtls_ctr_drbg()) == 0 |
| 3342 | + */ |
| 3343 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx); |
| 3344 | + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3345 | + mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); |
| 3346 | + mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d); |
| 3347 | + if (mbedtls_ecp_group_load(ecp_kp_grp, grp_id) == 0 |
| 3348 | + && (pub |
| 3349 | + ? mbedtls_ecp_copy(ecp_kp_Q, pub) == 0 |
| 3350 | + : mbedtls_ecp_point_read_binary(ecp_kp_grp, ecp_kp_Q, |
| 3351 | + buf, len) == 0) |
| 3352 | + && mbedtls_ecp_gen_privkey(ecp_kp_grp, ecp_kp_d, |
| 3353 | + mbedtls_ctr_drbg_random, |
| 3354 | + crypto_mbedtls_ctr_drbg()) == 0){ |
| 3355 | + return (struct crypto_ec_key *)ctx; |
| 3356 | + } |
| 3357 | + } |
| 3358 | + |
| 3359 | + mbedtls_pk_free(ctx); |
| 3360 | + os_free(ctx); |
| 3361 | + return NULL; |
| 3362 | +} |
| 3363 | + |
| 3364 | +struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x, |
| 3365 | + const u8 *y, size_t len) |
| 3366 | +{ |
| 3367 | + mbedtls_ecp_group_id grp_id = |
| 3368 | + crypto_mbedtls_ecp_group_id_from_ike_id(group); |
| 3369 | + if (grp_id == MBEDTLS_ECP_DP_NONE) |
| 3370 | + return NULL; |
| 3371 | + if (len > MBEDTLS_MPI_MAX_SIZE) |
| 3372 | + return NULL; |
| 3373 | + u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2]; |
| 3374 | + buf[0] = 0x04; /* assume x,y for Short Weierstrass */ |
| 3375 | + os_memcpy(buf+1, x, len); |
| 3376 | + os_memcpy(buf+1+len, y, len); |
| 3377 | + |
| 3378 | + return crypto_ec_key_set_pub_point_for_group(grp_id,NULL,buf,1+len*2); |
| 3379 | +} |
| 3380 | + |
| 3381 | +struct crypto_ec_key * |
| 3382 | +crypto_ec_key_set_pub_point(struct crypto_ec *e, |
| 3383 | + const struct crypto_ec_point *pub) |
| 3384 | +{ |
| 3385 | + mbedtls_ecp_group_id grp_id = ((mbedtls_ecp_group *)e)->id; |
| 3386 | + mbedtls_ecp_point *p = (mbedtls_ecp_point *)pub; |
| 3387 | + return crypto_ec_key_set_pub_point_for_group(grp_id, p, NULL, 0); |
| 3388 | +} |
| 3389 | + |
| 3390 | + |
| 3391 | +struct crypto_ec_key * crypto_ec_key_gen(int group) |
| 3392 | +{ |
| 3393 | + mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); |
| 3394 | + if (ctx == NULL) |
| 3395 | + return NULL; |
| 3396 | + mbedtls_pk_init(ctx); |
| 3397 | + if (crypto_mbedtls_keypair_gen(group, ctx) == 0) |
| 3398 | + return (struct crypto_ec_key *)ctx; |
| 3399 | + mbedtls_pk_free(ctx); |
| 3400 | + os_free(ctx); |
| 3401 | + return NULL; |
| 3402 | +} |
| 3403 | + |
| 3404 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ |
| 3405 | + |
| 3406 | +void crypto_ec_key_deinit(struct crypto_ec_key *key) |
| 3407 | +{ |
| 3408 | + mbedtls_pk_free((mbedtls_pk_context *)key); |
| 3409 | + os_free(key); |
| 3410 | +} |
| 3411 | + |
| 3412 | +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) |
| 3413 | +{ |
| 3414 | + /* (similar to crypto_ec_key_get_pubkey_point(), |
| 3415 | + * but compressed point format and ASN.1 DER wrapping)*/ |
| 3416 | +#ifndef MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/ |
| 3417 | +#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES ) |
| 3418 | +#endif |
| 3419 | + unsigned char buf[MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES]; |
| 3420 | + int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key, |
| 3421 | + buf, sizeof(buf)); |
| 3422 | + if (len < 0) |
| 3423 | + return NULL; |
| 3424 | + /* Note: data is written at the end of the buffer! Use the |
| 3425 | + * return value to determine where you should start |
| 3426 | + * using the buffer */ |
| 3427 | + unsigned char *p = buf+sizeof(buf)-len; |
| 3428 | + |
| 3429 | + #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED |
| 3430 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3431 | + if (ecp_kp == NULL) |
| 3432 | + return NULL; |
| 3433 | + mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3434 | + /* Note: sae_pk.c expects pubkey point in compressed format, |
| 3435 | + * but mbedtls_pk_write_pubkey_der() writes uncompressed format. |
| 3436 | + * Manually translate format and update lengths in DER format */ |
| 3437 | + if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) { |
| 3438 | + unsigned char *end = buf+sizeof(buf); |
| 3439 | + size_t n; |
| 3440 | + /* SubjectPublicKeyInfo SEQUENCE */ |
| 3441 | + mbedtls_asn1_get_tag(&p, end, &n, |
| 3442 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3443 | + /* algorithm AlgorithmIdentifier */ |
| 3444 | + unsigned char *a = p; |
| 3445 | + size_t alen; |
| 3446 | + mbedtls_asn1_get_tag(&p, end, &alen, |
| 3447 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3448 | + p += alen; |
| 3449 | + alen = (size_t)(p - a); |
| 3450 | + /* subjectPublicKey BIT STRING */ |
| 3451 | + mbedtls_asn1_get_tag(&p, end, &n, MBEDTLS_ASN1_BIT_STRING); |
| 3452 | + /* rewrite into compressed point format and rebuild ASN.1 */ |
| 3453 | + p[1] = (buf[sizeof(buf)-1] & 1) ? 0x03 : 0x02; |
| 3454 | + n = 1 + 1 + (n-2)/2; |
| 3455 | + len = mbedtls_asn1_write_len(&p, buf, n) + (int)n; |
| 3456 | + len += mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_BIT_STRING); |
| 3457 | + os_memmove(p-alen, a, alen); |
| 3458 | + len += alen; |
| 3459 | + p -= alen; |
| 3460 | + len += mbedtls_asn1_write_len(&p, buf, (size_t)len); |
| 3461 | + len += mbedtls_asn1_write_tag(&p, buf, |
| 3462 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3463 | + } |
| 3464 | + #endif |
| 3465 | + return wpabuf_alloc_copy(p, (size_t)len); |
| 3466 | +} |
| 3467 | + |
| 3468 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP |
| 3469 | + |
| 3470 | +struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key, |
| 3471 | + bool include_pub) |
| 3472 | +{ |
| 3473 | +#ifndef MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/ |
| 3474 | +#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES ) |
| 3475 | +#endif |
| 3476 | + unsigned char priv[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES]; |
| 3477 | + int privlen = mbedtls_pk_write_key_der((mbedtls_pk_context *)key, |
| 3478 | + priv, sizeof(priv)); |
| 3479 | + if (privlen < 0) |
| 3480 | + return NULL; |
| 3481 | + |
| 3482 | + struct wpabuf *wbuf; |
| 3483 | + |
| 3484 | + /* Note: data is written at the end of the buffer! Use the |
| 3485 | + * return value to determine where you should start |
| 3486 | + * using the buffer */ |
| 3487 | + /* mbedtls_pk_write_key_der() includes publicKey in DER */ |
| 3488 | + if (include_pub) |
| 3489 | + wbuf = wpabuf_alloc_copy(priv+sizeof(priv)-privlen, privlen); |
| 3490 | + else { |
| 3491 | + /* calculate publicKey offset and skip from end of buffer */ |
| 3492 | + unsigned char *p = priv+sizeof(priv)-privlen; |
| 3493 | + unsigned char *end = priv+sizeof(priv); |
| 3494 | + size_t len; |
| 3495 | + /* ECPrivateKey SEQUENCE */ |
| 3496 | + mbedtls_asn1_get_tag(&p, end, &len, |
| 3497 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3498 | + /* version INTEGER */ |
| 3499 | + unsigned char *v = p; |
| 3500 | + mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); |
| 3501 | + p += len; |
| 3502 | + /* privateKey OCTET STRING */ |
| 3503 | + mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); |
| 3504 | + p += len; |
| 3505 | + /* parameters ECParameters */ |
| 3506 | + mbedtls_asn1_get_tag(&p, end, &len, |
| 3507 | + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED); |
| 3508 | + p += len; |
| 3509 | + |
| 3510 | + /* write new SEQUENCE header (we know that it fits in priv[]) */ |
| 3511 | + len = (size_t)(p - v); |
| 3512 | + p = v; |
| 3513 | + len += mbedtls_asn1_write_len(&p, priv, len); |
| 3514 | + len += mbedtls_asn1_write_tag(&p, priv, |
| 3515 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3516 | + wbuf = wpabuf_alloc_copy(p, len); |
| 3517 | + } |
| 3518 | + |
| 3519 | + forced_memzero(priv, sizeof(priv)); |
| 3520 | + return wbuf; |
| 3521 | +} |
| 3522 | + |
| 3523 | +struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key, |
| 3524 | + int prefix) |
| 3525 | +{ |
| 3526 | + /*(similarities to crypto_ecdh_get_pubkey(), but different struct)*/ |
| 3527 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3528 | + if (ecp_kp == NULL) |
| 3529 | + return NULL; |
| 3530 | + mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3531 | + size_t len = CRYPTO_EC_plen(grp); |
| 3532 | + #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED |
| 3533 | + /* len */ |
| 3534 | + #endif |
| 3535 | + #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED |
| 3536 | + if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) |
| 3537 | + len = len*2+1; |
| 3538 | + #endif |
| 3539 | + struct wpabuf *buf = wpabuf_alloc(len); |
| 3540 | + if (buf == NULL) |
| 3541 | + return NULL; |
| 3542 | + mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); |
| 3543 | + if (mbedtls_ecp_point_write_binary(grp, ecp_kp_Q, |
| 3544 | + MBEDTLS_ECP_PF_UNCOMPRESSED, &len, |
| 3545 | + wpabuf_mhead_u8(buf), len) == 0) { |
| 3546 | + if (!prefix) /* Remove 0x04 prefix if requested */ |
| 3547 | + os_memmove(wpabuf_mhead(buf),wpabuf_mhead(buf)+1,--len); |
| 3548 | + wpabuf_put(buf, len); |
| 3549 | + return buf; |
| 3550 | + } |
| 3551 | + |
| 3552 | + wpabuf_free(buf); |
| 3553 | + return NULL; |
| 3554 | +} |
| 3555 | + |
| 3556 | +struct crypto_ec_point * |
| 3557 | +crypto_ec_key_get_public_key(struct crypto_ec_key *key) |
| 3558 | +{ |
| 3559 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3560 | + if (ecp_kp == NULL) |
| 3561 | + return NULL; |
| 3562 | + mbedtls_ecp_point *p = os_malloc(sizeof(*p)); |
| 3563 | + if (p != NULL) { |
| 3564 | + /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/ |
| 3565 | + mbedtls_ecp_point_init(p); |
| 3566 | + mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); |
| 3567 | + if (mbedtls_ecp_copy(p, ecp_kp_Q)) { |
| 3568 | + mbedtls_ecp_point_free(p); |
| 3569 | + os_free(p); |
| 3570 | + p = NULL; |
| 3571 | + } |
| 3572 | + } |
| 3573 | + return (struct crypto_ec_point *)p; |
| 3574 | +} |
| 3575 | + |
| 3576 | +struct crypto_bignum * |
| 3577 | +crypto_ec_key_get_private_key(struct crypto_ec_key *key) |
| 3578 | +{ |
| 3579 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3580 | + if (ecp_kp == NULL) |
| 3581 | + return NULL; |
| 3582 | + mbedtls_mpi *bn = os_malloc(sizeof(*bn)); |
| 3583 | + if (bn) { |
| 3584 | + /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/ |
| 3585 | + mbedtls_mpi_init(bn); |
| 3586 | + mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d); |
| 3587 | + if (mbedtls_mpi_copy(bn, ecp_kp_d)) { |
| 3588 | + mbedtls_mpi_free(bn); |
| 3589 | + os_free(bn); |
| 3590 | + bn = NULL; |
| 3591 | + } |
| 3592 | + } |
| 3593 | + return (struct crypto_bignum *)bn; |
| 3594 | +} |
| 3595 | + |
| 3596 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ |
| 3597 | + |
| 3598 | +static mbedtls_md_type_t crypto_ec_key_sign_md(size_t len) |
| 3599 | +{ |
| 3600 | + /* get mbedtls_md_type_t from length of hash data to be signed */ |
| 3601 | + switch (len) { |
| 3602 | + case 64: return MBEDTLS_MD_SHA512; |
| 3603 | + case 48: return MBEDTLS_MD_SHA384; |
| 3604 | + case 32: return MBEDTLS_MD_SHA256; |
| 3605 | + case 20: return MBEDTLS_MD_SHA1; |
| 3606 | + case 16: return MBEDTLS_MD_MD5; |
| 3607 | + default: return MBEDTLS_MD_NONE; |
| 3608 | + } |
| 3609 | +} |
| 3610 | + |
| 3611 | +struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, |
| 3612 | + size_t len) |
| 3613 | +{ |
| 3614 | + #ifndef MBEDTLS_PK_SIGNATURE_MAX_SIZE /*(defined since mbedtls 2.20.0)*/ |
| 3615 | + #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE |
| 3616 | + #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN |
| 3617 | + #else |
| 3618 | + #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE |
| 3619 | + #endif |
| 3620 | + #endif |
| 3621 | + size_t sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE; |
| 3622 | + struct wpabuf *buf = wpabuf_alloc(sig_len); |
| 3623 | + if (buf == NULL) |
| 3624 | + return NULL; |
| 3625 | + if (mbedtls_pk_sign((mbedtls_pk_context *)key, |
| 3626 | + crypto_ec_key_sign_md(len), data, len, |
| 3627 | + wpabuf_mhead_u8(buf), |
| 3628 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 3629 | + sig_len, |
| 3630 | + #endif |
| 3631 | + &sig_len, |
| 3632 | + mbedtls_ctr_drbg_random, |
| 3633 | + crypto_mbedtls_ctr_drbg()) == 0) { |
| 3634 | + wpabuf_put(buf, sig_len); |
| 3635 | + return buf; |
| 3636 | + } |
| 3637 | + |
| 3638 | + wpabuf_free(buf); |
| 3639 | + return NULL; |
| 3640 | +} |
| 3641 | + |
| 3642 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP |
| 3643 | +struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key, |
| 3644 | + const u8 *data, size_t len) |
| 3645 | +{ |
| 3646 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3647 | + if (ecp_kp == NULL) |
| 3648 | + return NULL; |
| 3649 | + |
| 3650 | + size_t sig_len = MBEDTLS_ECDSA_MAX_LEN; |
| 3651 | + u8 buf[MBEDTLS_ECDSA_MAX_LEN]; |
| 3652 | + if (mbedtls_ecdsa_write_signature(ecp_kp, crypto_ec_key_sign_md(len), |
| 3653 | + data, len, buf, |
| 3654 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 3655 | + sig_len, |
| 3656 | + #endif |
| 3657 | + &sig_len, |
| 3658 | + mbedtls_ctr_drbg_random, |
| 3659 | + crypto_mbedtls_ctr_drbg())) { |
| 3660 | + return NULL; |
| 3661 | + } |
| 3662 | + |
| 3663 | + /*(mbedtls_ecdsa_write_signature() writes signature in ASN.1)*/ |
| 3664 | + /* parse ASN.1 to get r and s and lengths */ |
| 3665 | + u8 *p = buf, *r, *s; |
| 3666 | + u8 *end = p + sig_len; |
| 3667 | + size_t rlen, slen; |
| 3668 | + mbedtls_asn1_get_tag(&p, end, &rlen, |
| 3669 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3670 | + mbedtls_asn1_get_tag(&p, end, &rlen, MBEDTLS_ASN1_INTEGER); |
| 3671 | + r = p; |
| 3672 | + p += rlen; |
| 3673 | + mbedtls_asn1_get_tag(&p, end, &slen, MBEDTLS_ASN1_INTEGER); |
| 3674 | + s = p; |
| 3675 | + |
| 3676 | + /* write raw r and s into out |
| 3677 | + * (including removal of leading 0 if added for ASN.1 integer) |
| 3678 | + * note: DPP caller expects raw r, s each padded to prime len */ |
| 3679 | + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3680 | + size_t plen = CRYPTO_EC_plen(ecp_kp_grp); |
| 3681 | + if (rlen > plen) { |
| 3682 | + r += (rlen - plen); |
| 3683 | + rlen = plen; |
| 3684 | + } |
| 3685 | + if (slen > plen) { |
| 3686 | + s += (slen - plen); |
| 3687 | + slen = plen; |
| 3688 | + } |
| 3689 | + struct wpabuf *out = wpabuf_alloc(plen*2); |
| 3690 | + if (out) { |
| 3691 | + wpabuf_put(out, plen*2); |
| 3692 | + p = wpabuf_mhead_u8(out); |
| 3693 | + os_memset(p, 0, plen*2); |
| 3694 | + os_memcpy(p+plen*1-rlen, r, rlen); |
| 3695 | + os_memcpy(p+plen*2-slen, s, slen); |
| 3696 | + } |
| 3697 | + return out; |
| 3698 | +} |
| 3699 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ |
| 3700 | + |
| 3701 | +int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, |
| 3702 | + size_t len, const u8 *sig, size_t sig_len) |
| 3703 | +{ |
| 3704 | + switch (mbedtls_pk_verify((mbedtls_pk_context *)key, |
| 3705 | + crypto_ec_key_sign_md(len), data, len, |
| 3706 | + sig, sig_len)) { |
| 3707 | + case 0: |
| 3708 | + /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */ |
| 3709 | + return 1; |
| 3710 | + case MBEDTLS_ERR_ECP_VERIFY_FAILED: |
| 3711 | + return 0; |
| 3712 | + default: |
| 3713 | + return -1; |
| 3714 | + } |
| 3715 | +} |
| 3716 | + |
| 3717 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP |
| 3718 | +int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key, |
| 3719 | + const u8 *data, size_t len, |
| 3720 | + const u8 *r, size_t r_len, |
| 3721 | + const u8 *s, size_t s_len) |
| 3722 | +{ |
| 3723 | + /* reimplement mbedtls_ecdsa_read_signature() without encoding r and s |
| 3724 | + * into ASN.1 just for mbedtls_ecdsa_read_signature() to decode ASN.1 */ |
| 3725 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3726 | + if (ecp_kp == NULL) |
| 3727 | + return -1; |
| 3728 | + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3729 | + mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q); |
| 3730 | + |
| 3731 | + mbedtls_mpi mpi_r; |
| 3732 | + mbedtls_mpi mpi_s; |
| 3733 | + mbedtls_mpi_init(&mpi_r); |
| 3734 | + mbedtls_mpi_init(&mpi_s); |
| 3735 | + int ret = mbedtls_mpi_read_binary(&mpi_r, r, r_len) |
| 3736 | + || mbedtls_mpi_read_binary(&mpi_s, s, s_len) ? -1 : 0; |
| 3737 | + if (ret == 0) { |
| 3738 | + ret = mbedtls_ecdsa_verify(ecp_kp_grp, data, len, |
| 3739 | + ecp_kp_Q, &mpi_r, &mpi_s); |
| 3740 | + ret = ret ? ret == MBEDTLS_ERR_ECP_BAD_INPUT_DATA ? 0 : -1 : 1; |
| 3741 | + } |
| 3742 | + mbedtls_mpi_free(&mpi_r); |
| 3743 | + mbedtls_mpi_free(&mpi_s); |
| 3744 | + return ret; |
| 3745 | +} |
| 3746 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ |
| 3747 | + |
| 3748 | +int crypto_ec_key_group(struct crypto_ec_key *key) |
| 3749 | +{ |
| 3750 | + mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key); |
| 3751 | + if (ecp_kp == NULL) |
| 3752 | + return -1; |
| 3753 | + mbedtls_ecp_group *ecp_group = &ecp_kp->MBEDTLS_PRIVATE(grp); |
| 3754 | + return crypto_mbedtls_ike_id_from_ecp_group_id(ecp_group->id); |
| 3755 | +} |
| 3756 | + |
| 3757 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP |
| 3758 | + |
| 3759 | +int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2) |
| 3760 | +{ |
| 3761 | +#if 0 /*(DPP is passing two public keys; unable to use pk_check_pair())*/ |
| 3762 | + #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 3763 | + return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1, |
| 3764 | + (const mbedtls_pk_context *)key2) ? -1 : 0; |
| 3765 | + #else |
| 3766 | + return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1, |
| 3767 | + (const mbedtls_pk_context *)key2, |
| 3768 | + mbedtls_ctr_drbg_random, |
| 3769 | + crypto_mbedtls_ctr_drbg()) ? -1 : 0; |
| 3770 | + #endif |
| 3771 | +#else |
| 3772 | + mbedtls_ecp_keypair *ecp_kp1=mbedtls_pk_ec(*(mbedtls_pk_context *)key1); |
| 3773 | + mbedtls_ecp_keypair *ecp_kp2=mbedtls_pk_ec(*(mbedtls_pk_context *)key2); |
| 3774 | + if (ecp_kp1 == NULL || ecp_kp2 == NULL) |
| 3775 | + return -1; |
| 3776 | + mbedtls_ecp_group *ecp_kp1_grp = &ecp_kp1->MBEDTLS_PRIVATE(grp); |
| 3777 | + mbedtls_ecp_group *ecp_kp2_grp = &ecp_kp2->MBEDTLS_PRIVATE(grp); |
| 3778 | + mbedtls_ecp_point *ecp_kp1_Q = &ecp_kp1->MBEDTLS_PRIVATE(Q); |
| 3779 | + mbedtls_ecp_point *ecp_kp2_Q = &ecp_kp2->MBEDTLS_PRIVATE(Q); |
| 3780 | + return ecp_kp1_grp->id != ecp_kp2_grp->id |
| 3781 | + || mbedtls_ecp_point_cmp(ecp_kp1_Q, ecp_kp2_Q) ? -1 : 0; |
| 3782 | +#endif |
| 3783 | +} |
| 3784 | + |
| 3785 | +void crypto_ec_key_debug_print(const struct crypto_ec_key *key, |
| 3786 | + const char *title) |
| 3787 | +{ |
| 3788 | + /* TBD: what info is desirable here and in what human readable format?*/ |
| 3789 | + /*(crypto_openssl.c prints a human-readably public key and attributes)*/ |
| 3790 | + #if 0 |
| 3791 | + struct mbedtls_pk_debug_item debug_item; |
| 3792 | + if (mbedtls_pk_debug((const mbedtls_pk_context *)key, &debug_item)) |
| 3793 | + return; |
| 3794 | + /* ... */ |
| 3795 | + #endif |
| 3796 | + wpa_printf(MSG_DEBUG, "%s: %s not implemented", title, __func__); |
| 3797 | +} |
| 3798 | + |
| 3799 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */ |
| 3800 | + |
| 3801 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_EC */ |
| 3802 | + |
| 3803 | + |
| 3804 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_CSR |
| 3805 | + |
| 3806 | +#include <mbedtls/x509_csr.h> |
| 3807 | +#include <mbedtls/oid.h> |
| 3808 | + |
| 3809 | +struct crypto_csr * crypto_csr_init(void) |
| 3810 | +{ |
| 3811 | + mbedtls_x509write_csr *csr = os_malloc(sizeof(*csr)); |
| 3812 | + if (csr != NULL) |
| 3813 | + mbedtls_x509write_csr_init(csr); |
| 3814 | + return (struct crypto_csr *)csr; |
| 3815 | +} |
| 3816 | + |
| 3817 | +struct crypto_csr * crypto_csr_verify(const struct wpabuf *req) |
| 3818 | +{ |
| 3819 | + /* future: look for alternatives to MBEDTLS_PRIVATE() access */ |
| 3820 | + |
| 3821 | + /* sole caller src/common/dpp_crypto.c:dpp_validate_csr() |
| 3822 | + * uses (mbedtls_x509_csr *) to obtain CSR_ATTR_CHALLENGE_PASSWORD |
| 3823 | + * so allocate different object (mbedtls_x509_csr *) and special-case |
| 3824 | + * object when used in crypto_csr_get_attribute() and when free()d in |
| 3825 | + * crypto_csr_deinit(). */ |
| 3826 | + |
| 3827 | + mbedtls_x509_csr *csr = os_malloc(sizeof(*csr)); |
| 3828 | + if (csr == NULL) |
| 3829 | + return NULL; |
| 3830 | + mbedtls_x509_csr_init(csr); |
| 3831 | + const mbedtls_md_info_t *md_info; |
| 3832 | + unsigned char digest[MBEDTLS_MD_MAX_SIZE]; |
| 3833 | + if (mbedtls_x509_csr_parse_der(csr,wpabuf_head(req),wpabuf_len(req))==0 |
| 3834 | + && (md_info=mbedtls_md_info_from_type(csr->MBEDTLS_PRIVATE(sig_md))) |
| 3835 | + != NULL |
| 3836 | + && mbedtls_md(md_info, csr->cri.p, csr->cri.len, digest) == 0) { |
| 3837 | + switch (mbedtls_pk_verify(&csr->pk,csr->MBEDTLS_PRIVATE(sig_md), |
| 3838 | + digest, mbedtls_md_get_size(md_info), |
| 3839 | + csr->MBEDTLS_PRIVATE(sig).p, |
| 3840 | + csr->MBEDTLS_PRIVATE(sig).len)) { |
| 3841 | + case 0: |
| 3842 | + /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */ |
| 3843 | + return (struct crypto_csr *)((uintptr_t)csr | 1uL); |
| 3844 | + default: |
| 3845 | + break; |
| 3846 | + } |
| 3847 | + } |
| 3848 | + |
| 3849 | + mbedtls_x509_csr_free(csr); |
| 3850 | + os_free(csr); |
| 3851 | + return NULL; |
| 3852 | +} |
| 3853 | + |
| 3854 | +void crypto_csr_deinit(struct crypto_csr *csr) |
| 3855 | +{ |
| 3856 | + if ((uintptr_t)csr & 1uL) { |
| 3857 | + csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL); |
| 3858 | + mbedtls_x509_csr_free((mbedtls_x509_csr *)csr); |
| 3859 | + } |
| 3860 | + else |
| 3861 | + mbedtls_x509write_csr_free((mbedtls_x509write_csr *)csr); |
| 3862 | + os_free(csr); |
| 3863 | +} |
| 3864 | + |
| 3865 | +int crypto_csr_set_ec_public_key(struct crypto_csr *csr, |
| 3866 | + struct crypto_ec_key *key) |
| 3867 | +{ |
| 3868 | + mbedtls_x509write_csr_set_key((mbedtls_x509write_csr *)csr, |
| 3869 | + (mbedtls_pk_context *)key); |
| 3870 | + return 0; |
| 3871 | +} |
| 3872 | + |
| 3873 | +int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type, |
| 3874 | + const char *name) |
| 3875 | +{ |
| 3876 | + /* specialized for src/common/dpp_crypto.c */ |
| 3877 | + |
| 3878 | + /* sole caller src/common/dpp_crypto.c:dpp_build_csr() |
| 3879 | + * calls this function only once, using type == CSR_NAME_CN |
| 3880 | + * (If called more than once, this code would need to append |
| 3881 | + * components to the subject name, which we could do by |
| 3882 | + * appending to (mbedtls_x509write_csr *) private member |
| 3883 | + * mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject)) */ |
| 3884 | + |
| 3885 | + const char *label; |
| 3886 | + switch (type) { |
| 3887 | + case CSR_NAME_CN: label = "CN="; break; |
| 3888 | + case CSR_NAME_SN: label = "SN="; break; |
| 3889 | + case CSR_NAME_C: label = "C="; break; |
| 3890 | + case CSR_NAME_O: label = "O="; break; |
| 3891 | + case CSR_NAME_OU: label = "OU="; break; |
| 3892 | + default: return -1; |
| 3893 | + } |
| 3894 | + |
| 3895 | + size_t len = strlen(name); |
| 3896 | + struct wpabuf *buf = wpabuf_alloc(3+len+1); |
| 3897 | + if (buf == NULL) |
| 3898 | + return -1; |
| 3899 | + wpabuf_put_data(buf, label, strlen(label)); |
| 3900 | + wpabuf_put_data(buf, name, len+1); /*(include trailing '\0')*/ |
| 3901 | + /* Note: 'name' provided is set as given and should be backslash-escaped |
| 3902 | + * by caller when necessary, e.g. literal ',' which are not separating |
| 3903 | + * components should be backslash-escaped */ |
| 3904 | + |
| 3905 | + int ret = |
| 3906 | + mbedtls_x509write_csr_set_subject_name((mbedtls_x509write_csr *)csr, |
| 3907 | + wpabuf_head(buf)) ? -1 : 0; |
| 3908 | + wpabuf_free(buf); |
| 3909 | + return ret; |
| 3910 | +} |
| 3911 | + |
| 3912 | +/* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */ |
| 3913 | +static const char OBJ_pkcs9_challengePassword[] = MBEDTLS_OID_PKCS9 "\x07"; |
| 3914 | + |
| 3915 | +int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr, |
| 3916 | + int attr_type, const u8 *value, size_t len) |
| 3917 | +{ |
| 3918 | + /* specialized for src/common/dpp_crypto.c */ |
| 3919 | + /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes |
| 3920 | + * attr == CSR_ATTR_CHALLENGE_PASSWORD |
| 3921 | + * attr_type == ASN1_TAG_UTF8STRING */ |
| 3922 | + |
| 3923 | + const char *oid; |
| 3924 | + size_t oid_len; |
| 3925 | + switch (attr) { |
| 3926 | + case CSR_ATTR_CHALLENGE_PASSWORD: |
| 3927 | + oid = OBJ_pkcs9_challengePassword; |
| 3928 | + oid_len = sizeof(OBJ_pkcs9_challengePassword)-1; |
| 3929 | + break; |
| 3930 | + default: |
| 3931 | + return -1; |
| 3932 | + } |
| 3933 | + |
| 3934 | + #if 0 /*(incorrect; sets an extension, not an attribute)*/ |
| 3935 | + return mbedtls_x509write_csr_set_extension((mbedtls_x509write_csr *)csr, |
| 3936 | + oid, oid_len, |
| 3937 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 3938 | + 0, /*(critical flag)*/ |
| 3939 | + #endif |
| 3940 | + value, len) ? -1 : 0; |
| 3941 | + #else |
| 3942 | + (void)oid; |
| 3943 | + (void)oid_len; |
| 3944 | + #endif |
| 3945 | + |
| 3946 | + /* mbedtls does not currently provide way to set an attribute in a CSR: |
| 3947 | + * https://github.com/Mbed-TLS/mbedtls/issues/4886 */ |
| 3948 | + wpa_printf(MSG_ERROR, |
| 3949 | + "mbedtls does not currently support setting challengePassword " |
| 3950 | + "attribute in CSR"); |
| 3951 | + return -1; |
| 3952 | +} |
| 3953 | + |
| 3954 | +const u8 * mbedtls_x509_csr_attr_oid_value(mbedtls_x509_csr *csr, |
| 3955 | + const char *oid, size_t oid_len, |
| 3956 | + size_t *vlen, int *vtype) |
| 3957 | +{ |
| 3958 | + /* Note: mbedtls_x509_csr_parse_der() has parsed and validated CSR, |
| 3959 | + * so validation checks are not repeated here |
| 3960 | + * |
| 3961 | + * It would be nicer if (mbedtls_x509_csr *) had an mbedtls_x509_buf of |
| 3962 | + * Attributes (or at least a pointer) since mbedtls_x509_csr_parse_der() |
| 3963 | + * already parsed the rest of CertificationRequestInfo, some of which is |
| 3964 | + * repeated here to step to Attributes. Since csr->subject_raw.p points |
| 3965 | + * into csr->cri.p, which points into csr->raw.p, step over version and |
| 3966 | + * subject of CertificationRequestInfo (SEQUENCE) */ |
| 3967 | + unsigned char *p = csr->subject_raw.p + csr->subject_raw.len; |
| 3968 | + unsigned char *end = csr->cri.p + csr->cri.len, *ext; |
| 3969 | + size_t len; |
| 3970 | + |
| 3971 | + /* step over SubjectPublicKeyInfo */ |
| 3972 | + mbedtls_asn1_get_tag(&p, end, &len, |
| 3973 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); |
| 3974 | + p += len; |
| 3975 | + |
| 3976 | + /* Attributes |
| 3977 | + * { ATTRIBUTE:IOSet } ::= SET OF { SEQUENCE { OID, value } } |
| 3978 | + */ |
| 3979 | + if (mbedtls_asn1_get_tag(&p, end, &len, |
| 3980 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) { |
| 3981 | + return NULL; |
| 3982 | + } |
| 3983 | + while (p < end) { |
| 3984 | + if (mbedtls_asn1_get_tag(&p, end, &len, |
| 3985 | + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) { |
| 3986 | + return NULL; |
| 3987 | + } |
| 3988 | + ext = p; |
| 3989 | + p += len; |
| 3990 | + |
| 3991 | + if (mbedtls_asn1_get_tag(&ext,end,&len,MBEDTLS_ASN1_OID) != 0) |
| 3992 | + return NULL; |
| 3993 | + if (oid_len != len || 0 != memcmp(ext, oid, oid_len)) |
| 3994 | + continue; |
| 3995 | + |
| 3996 | + /* found oid; return value */ |
| 3997 | + *vtype = *ext++; /* tag */ |
| 3998 | + return (mbedtls_asn1_get_len(&ext,end,vlen) == 0) ? ext : NULL; |
| 3999 | + } |
| 4000 | + |
| 4001 | + return NULL; |
| 4002 | +} |
| 4003 | + |
| 4004 | +const u8 * crypto_csr_get_attribute(struct crypto_csr *csr, |
| 4005 | + enum crypto_csr_attr attr, |
| 4006 | + size_t *len, int *type) |
| 4007 | +{ |
| 4008 | + /* specialized for src/common/dpp_crypto.c */ |
| 4009 | + /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes |
| 4010 | + * attr == CSR_ATTR_CHALLENGE_PASSWORD */ |
| 4011 | + |
| 4012 | + const char *oid; |
| 4013 | + size_t oid_len; |
| 4014 | + switch (attr) { |
| 4015 | + case CSR_ATTR_CHALLENGE_PASSWORD: |
| 4016 | + oid = OBJ_pkcs9_challengePassword; |
| 4017 | + oid_len = sizeof(OBJ_pkcs9_challengePassword)-1; |
| 4018 | + break; |
| 4019 | + default: |
| 4020 | + return NULL; |
| 4021 | + } |
| 4022 | + |
| 4023 | + /* see crypto_csr_verify(); expecting (mbedtls_x509_csr *) tagged |=1 */ |
| 4024 | + if (!((uintptr_t)csr & 1uL)) |
| 4025 | + return NULL; |
| 4026 | + csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL); |
| 4027 | + |
| 4028 | + return mbedtls_x509_csr_attr_oid_value((mbedtls_x509_csr *)csr, |
| 4029 | + oid, oid_len, len, type); |
| 4030 | +} |
| 4031 | + |
| 4032 | +struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, |
| 4033 | + struct crypto_ec_key *key, |
| 4034 | + enum crypto_hash_alg algo) |
| 4035 | +{ |
| 4036 | + mbedtls_md_type_t sig_md; |
| 4037 | + switch (algo) { |
| 4038 | + #ifdef MBEDTLS_SHA256_C |
| 4039 | + case CRYPTO_HASH_ALG_SHA256: sig_md = MBEDTLS_MD_SHA256; break; |
| 4040 | + #endif |
| 4041 | + #ifdef MBEDTLS_SHA512_C |
| 4042 | + case CRYPTO_HASH_ALG_SHA384: sig_md = MBEDTLS_MD_SHA384; break; |
| 4043 | + case CRYPTO_HASH_ALG_SHA512: sig_md = MBEDTLS_MD_SHA512; break; |
| 4044 | + #endif |
| 4045 | + default: |
| 4046 | + return NULL; |
| 4047 | + } |
| 4048 | + mbedtls_x509write_csr_set_md_alg((mbedtls_x509write_csr *)csr, sig_md); |
| 4049 | + |
| 4050 | + #if 0 |
| 4051 | + unsigned char key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
| 4052 | + | MBEDTLS_X509_KU_KEY_CERT_SIGN; |
| 4053 | + if (mbedtls_x509write_csr_set_key_usage((mbedtls_x509write_csr *)csr, |
| 4054 | + key_usage)) |
| 4055 | + return NULL; |
| 4056 | + #endif |
| 4057 | + |
| 4058 | + #if 0 |
| 4059 | + unsigned char ns_cert_type = MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT |
| 4060 | + | MBEDTLS_X509_NS_CERT_TYPE_EMAIL; |
| 4061 | + if (mbedtls_x509write_csr_set_ns_cert_type((mbedtls_x509write_csr *)csr, |
| 4062 | + ns_cert_type)) |
| 4063 | + return NULL; |
| 4064 | + #endif |
| 4065 | + |
| 4066 | + #if 0 |
| 4067 | + /* mbedtls does not currently provide way to set an attribute in a CSR: |
| 4068 | + * https://github.com/Mbed-TLS/mbedtls/issues/4886 |
| 4069 | + * XXX: hwsim dpp_enterprise test fails due to this limitation. |
| 4070 | + * |
| 4071 | + * Current usage of this function is solely by dpp_build_csr(), |
| 4072 | + * so as a kludge, might consider custom (struct crypto_csr *) |
| 4073 | + * containing (mbedtls_x509write_csr *) and a list of attributes |
| 4074 | + * (i.e. challengePassword). Might have to totally reimplement |
| 4075 | + * mbedtls_x509write_csr_der(); underlying x509write_csr_der_internal() |
| 4076 | + * handles signing the CSR. (This is more work that appending an |
| 4077 | + * Attributes section to end of CSR and adjusting ASN.1 length of CSR.) |
| 4078 | + */ |
| 4079 | + #endif |
| 4080 | + |
| 4081 | + unsigned char buf[4096]; /* XXX: large enough? too large? */ |
| 4082 | + int len = mbedtls_x509write_csr_der((mbedtls_x509write_csr *)csr, |
| 4083 | + buf, sizeof(buf), |
| 4084 | + mbedtls_ctr_drbg_random, |
| 4085 | + crypto_mbedtls_ctr_drbg()); |
| 4086 | + if (len < 0) |
| 4087 | + return NULL; |
| 4088 | + /* Note: data is written at the end of the buffer! Use the |
| 4089 | + * return value to determine where you should start |
| 4090 | + * using the buffer */ |
| 4091 | + return wpabuf_alloc_copy(buf+sizeof(buf)-len, (size_t)len); |
| 4092 | +} |
| 4093 | + |
| 4094 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_CSR */ |
| 4095 | + |
| 4096 | + |
| 4097 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_PKCS7 |
| 4098 | + |
| 4099 | +#if 0 |
| 4100 | +#include <mbedtls/pkcs7.h> /* PKCS7 is not currently supported in mbedtls */ |
| 4101 | +#include <mbedtls/pem.h> |
| 4102 | +#endif |
| 4103 | + |
| 4104 | +struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7) |
| 4105 | +{ |
| 4106 | + /* PKCS7 is not currently supported in mbedtls */ |
| 4107 | + return NULL; |
| 4108 | + |
| 4109 | +#if 0 |
| 4110 | + /* https://github.com/naynajain/mbedtls-1 branch: development-pkcs7 |
| 4111 | + * (??? potential future contribution to mbedtls ???) */ |
| 4112 | + |
| 4113 | + /* Note: PKCS7 signature *is not* verified by this function. |
| 4114 | + * The function interface does not provide for passing a certificate */ |
| 4115 | + |
| 4116 | + mbedtls_pkcs7 mpkcs7; |
| 4117 | + mbedtls_pkcs7_init(&mpkcs7); |
| 4118 | + int pkcs7_type = mbedtls_pkcs7_parse_der(wpabuf_head(pkcs7), |
| 4119 | + wpabuf_len(pkcs7), |
| 4120 | + &mpkcs7); |
| 4121 | + wpabuf *buf = NULL; |
| 4122 | + do { |
| 4123 | + if (pkcs7_type < 0) |
| 4124 | + break; |
| 4125 | + |
| 4126 | + /* src/common/dpp.c:dpp_parse_cred_dot1x() interested in certs |
| 4127 | + * for wpa_supplicant/dpp_supplicant.c:wpas_dpp_add_network() |
| 4128 | + * (? are adding certificate headers and footers desired ?) */ |
| 4129 | + |
| 4130 | + /* development-pkcs7 branch does not currently provide |
| 4131 | + * additional interfaces to retrieve the parsed data */ |
| 4132 | + |
| 4133 | + mbedtls_x509_crt *certs = |
| 4134 | + &mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(certs); |
| 4135 | + int ncerts = |
| 4136 | + mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(no_of_certs); |
| 4137 | + |
| 4138 | + /* allocate buffer for PEM (base64-encoded DER) |
| 4139 | + * plus header, footer, newlines, and some extra */ |
| 4140 | + buf = wpabuf_alloc((wpabuf_len(pkcs7)+2)/3*4 + ncerts*64); |
| 4141 | + if (buf == NULL) |
| 4142 | + break; |
| 4143 | + |
| 4144 | + #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n" |
| 4145 | + #define PEM_END_CRT "-----END CERTIFICATE-----\n" |
| 4146 | + size_t olen; |
| 4147 | + for (int i = 0; i < ncerts; ++i) { |
| 4148 | + int ret = mbedtls_pem_write_buffer( |
| 4149 | + PEM_BEGIN_CRT, PEM_END_CRT, |
| 4150 | + certs[i].raw.p, certs[i].raw.len, |
| 4151 | + wpabuf_mhead(buf, 0), wpabuf_tailroom(buf), |
| 4152 | + &olen)); |
| 4153 | + if (ret == 0) |
| 4154 | + wpabuf_put(buf, olen); |
| 4155 | + } else { |
| 4156 | + if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) |
| 4157 | + ret = wpabuf_resize( |
| 4158 | + &buf,olen-wpabuf_tailroom(buf)); |
| 4159 | + if (ret == 0) { |
| 4160 | + --i;/*(adjust loop iterator for retry)*/ |
| 4161 | + continue; |
| 4162 | + } |
| 4163 | + wpabuf_free(buf); |
| 4164 | + buf = NULL; |
| 4165 | + break; |
| 4166 | + } |
| 4167 | + } |
| 4168 | + } while (0); |
| 4169 | + |
| 4170 | + mbedtls_pkcs7_free(&mpkcs7); |
| 4171 | + return buf; |
| 4172 | +#endif |
| 4173 | +} |
| 4174 | + |
| 4175 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_PKCS7 */ |
| 4176 | + |
| 4177 | + |
| 4178 | +#ifdef MBEDTLS_ARC4_C |
| 4179 | +#include <mbedtls/arc4.h> |
| 4180 | +int rc4_skip(const u8 *key, size_t keylen, size_t skip, |
| 4181 | + u8 *data, size_t data_len) |
| 4182 | +{ |
| 4183 | + mbedtls_arc4_context ctx; |
| 4184 | + mbedtls_arc4_init(&ctx); |
| 4185 | + mbedtls_arc4_setup(&ctx, key, keylen); |
| 4186 | + |
| 4187 | + if (skip) { |
| 4188 | + /*(prefer [16] on ancient hardware with smaller cache lines)*/ |
| 4189 | + unsigned char skip_buf[64]; /*('skip' is generally small)*/ |
| 4190 | + /*os_memset(skip_buf, 0, sizeof(skip_buf));*/ /*(necessary?)*/ |
| 4191 | + size_t len; |
| 4192 | + do { |
| 4193 | + len = skip > sizeof(skip_buf) ? sizeof(skip_buf) : skip; |
| 4194 | + mbedtls_arc4_crypt(&ctx, len, skip_buf, skip_buf); |
| 4195 | + } while ((skip -= len)); |
| 4196 | + } |
| 4197 | + |
| 4198 | + int ret = mbedtls_arc4_crypt(&ctx, data_len, data, data); |
| 4199 | + mbedtls_arc4_free(&ctx); |
| 4200 | + return ret; |
| 4201 | +} |
| 4202 | +#endif |
| 4203 | + |
| 4204 | + |
| 4205 | +/* duplicated in tls_mbedtls.c:tls_mbedtls_readfile()*/ |
| 4206 | +__attribute_noinline__ |
| 4207 | +static int crypto_mbedtls_readfile(const char *path, u8 **buf, size_t *n) |
| 4208 | +{ |
| 4209 | + #if 0 /* #ifdef MBEDTLS_FS_IO */ |
| 4210 | + /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/ |
| 4211 | + if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) { |
| 4212 | + wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path); |
| 4213 | + return -1; |
| 4214 | + } |
| 4215 | + #else |
| 4216 | + /*(use os_readfile() so that we can use os_free() |
| 4217 | + *(if we use mbedtls_pk_load_file() above, macros prevent calling free() |
| 4218 | + * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free() |
| 4219 | + * on buf aborts in tests if buf not allocated via os_malloc())*/ |
| 4220 | + *buf = (u8 *)os_readfile(path, n); |
| 4221 | + if (!*buf) { |
| 4222 | + wpa_printf(MSG_ERROR, "error: os_readfile %s", path); |
| 4223 | + return -1; |
| 4224 | + } |
| 4225 | + u8 *buf0 = os_realloc(*buf, *n+1); |
| 4226 | + if (!buf0) { |
| 4227 | + bin_clear_free(*buf, *n); |
| 4228 | + *buf = NULL; |
| 4229 | + return -1; |
| 4230 | + } |
| 4231 | + buf0[(*n)++] = '\0'; |
| 4232 | + *buf = buf0; |
| 4233 | + #endif |
| 4234 | + return 0; |
| 4235 | +} |
| 4236 | + |
| 4237 | + |
| 4238 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_RSA |
| 4239 | +#ifdef MBEDTLS_RSA_C |
| 4240 | + |
| 4241 | +#include <mbedtls/pk.h> |
| 4242 | +#include <mbedtls/rsa.h> |
| 4243 | + |
| 4244 | +struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key) |
| 4245 | +{ |
| 4246 | + /* mbedtls_pk_parse_keyfile() and mbedtls_pk_parse_public_keyfile() |
| 4247 | + * require #ifdef MBEDTLS_FS_IO in mbedtls library. Prefer to use |
| 4248 | + * crypto_mbedtls_readfile(), which wraps os_readfile() */ |
| 4249 | + u8 *data; |
| 4250 | + size_t len; |
| 4251 | + if (crypto_mbedtls_readfile(file, &data, &len) != 0) |
| 4252 | + return NULL; |
| 4253 | + |
| 4254 | + mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx)); |
| 4255 | + if (ctx == NULL) { |
| 4256 | + bin_clear_free(data, len); |
| 4257 | + return NULL; |
| 4258 | + } |
| 4259 | + mbedtls_pk_init(ctx); |
| 4260 | + |
| 4261 | + int rc; |
| 4262 | + rc = (private_key |
| 4263 | + ? mbedtls_pk_parse_key(ctx, data, len, NULL, 0 |
| 4264 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 4265 | + ,mbedtls_ctr_drbg_random, |
| 4266 | + crypto_mbedtls_ctr_drbg() |
| 4267 | + #endif |
| 4268 | + ) |
| 4269 | + : mbedtls_pk_parse_public_key(ctx, data, len)) == 0 |
| 4270 | + && mbedtls_pk_can_do(ctx, MBEDTLS_PK_RSA); |
| 4271 | + |
| 4272 | + bin_clear_free(data, len); |
| 4273 | + |
| 4274 | + if (rc) { |
| 4275 | + /* use MBEDTLS_RSA_PKCS_V21 padding for RSAES-OAEP */ |
| 4276 | + /* use MBEDTLS_MD_SHA256 for these hostap interfaces */ |
| 4277 | + #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 4278 | + /*(no return value in mbedtls 2.x)*/ |
| 4279 | + mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx), |
| 4280 | + MBEDTLS_RSA_PKCS_V21, |
| 4281 | + MBEDTLS_MD_SHA256); |
| 4282 | + #else |
| 4283 | + if (mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx), |
| 4284 | + MBEDTLS_RSA_PKCS_V21, |
| 4285 | + MBEDTLS_MD_SHA256) == 0) |
| 4286 | + #endif |
| 4287 | + return (struct crypto_rsa_key *)ctx; |
| 4288 | + } |
| 4289 | + |
| 4290 | + mbedtls_pk_free(ctx); |
| 4291 | + os_free(ctx); |
| 4292 | + return NULL; |
| 4293 | +} |
| 4294 | + |
| 4295 | +struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key, |
| 4296 | + const struct wpabuf *in) |
| 4297 | +{ |
| 4298 | + mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key); |
| 4299 | + size_t olen = mbedtls_rsa_get_len(pk_rsa); |
| 4300 | + struct wpabuf *buf = wpabuf_alloc(olen); |
| 4301 | + if (buf == NULL) |
| 4302 | + return NULL; |
| 4303 | + |
| 4304 | + /* mbedtls_pk_encrypt() takes a few more hops to get to same func */ |
| 4305 | + if (mbedtls_rsa_rsaes_oaep_encrypt(pk_rsa, |
| 4306 | + mbedtls_ctr_drbg_random, |
| 4307 | + crypto_mbedtls_ctr_drbg(), |
| 4308 | + #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 4309 | + MBEDTLS_RSA_PRIVATE, |
| 4310 | + #endif |
| 4311 | + NULL, 0, |
| 4312 | + wpabuf_len(in), wpabuf_head(in), |
| 4313 | + wpabuf_put(buf, olen)) == 0) { |
| 4314 | + return buf; |
| 4315 | + } |
| 4316 | + |
| 4317 | + wpabuf_clear_free(buf); |
| 4318 | + return NULL; |
| 4319 | +} |
| 4320 | + |
| 4321 | +struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key, |
| 4322 | + const struct wpabuf *in) |
| 4323 | +{ |
| 4324 | + mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key); |
| 4325 | + size_t olen = mbedtls_rsa_get_len(pk_rsa); |
| 4326 | + struct wpabuf *buf = wpabuf_alloc(olen); |
| 4327 | + if (buf == NULL) |
| 4328 | + return NULL; |
| 4329 | + |
| 4330 | + /* mbedtls_pk_decrypt() takes a few more hops to get to same func */ |
| 4331 | + if (mbedtls_rsa_rsaes_oaep_decrypt(pk_rsa, |
| 4332 | + mbedtls_ctr_drbg_random, |
| 4333 | + crypto_mbedtls_ctr_drbg(), |
| 4334 | + #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 4335 | + MBEDTLS_RSA_PUBLIC, |
| 4336 | + #endif |
| 4337 | + NULL, 0, &olen, wpabuf_head(in), |
| 4338 | + wpabuf_mhead(buf), olen) == 0) { |
| 4339 | + wpabuf_put(buf, olen); |
| 4340 | + return buf; |
| 4341 | + } |
| 4342 | + |
| 4343 | + wpabuf_clear_free(buf); |
| 4344 | + return NULL; |
| 4345 | +} |
| 4346 | + |
| 4347 | +void crypto_rsa_key_free(struct crypto_rsa_key *key) |
| 4348 | +{ |
| 4349 | + mbedtls_pk_free((mbedtls_pk_context *)key); |
| 4350 | + os_free(key); |
| 4351 | +} |
| 4352 | + |
| 4353 | +#endif /* MBEDTLS_RSA_C */ |
| 4354 | +#endif /* CRYPTO_MBEDTLS_CRYPTO_RSA */ |
| 4355 | + |
| 4356 | +#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE |
| 4357 | + |
| 4358 | +struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id, |
| 4359 | + enum hpke_kdf_id kdf_id, |
| 4360 | + enum hpke_aead_id aead_id, |
| 4361 | + struct crypto_ec_key *peer_pub, |
| 4362 | + const u8 *info, size_t info_len, |
| 4363 | + const u8 *aad, size_t aad_len, |
| 4364 | + const u8 *pt, size_t pt_len) |
| 4365 | +{ |
| 4366 | + /* not yet implemented */ |
| 4367 | + return NULL; |
| 4368 | +} |
| 4369 | + |
| 4370 | +struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id, |
| 4371 | + enum hpke_kdf_id kdf_id, |
| 4372 | + enum hpke_aead_id aead_id, |
| 4373 | + struct crypto_ec_key *own_priv, |
| 4374 | + const u8 *info, size_t info_len, |
| 4375 | + const u8 *aad, size_t aad_len, |
| 4376 | + const u8 *enc_ct, size_t enc_ct_len) |
| 4377 | +{ |
| 4378 | + /* not yet implemented */ |
| 4379 | + return NULL; |
| 4380 | +} |
| 4381 | + |
| 4382 | +#endif |
| 4383 | --- /dev/null |
| 4384 | +++ b/src/crypto/tls_mbedtls.c |
| 4385 | @@ -0,0 +1,3313 @@ |
| 4386 | +/* |
| 4387 | + * SSL/TLS interface functions for mbed TLS |
| 4388 | + * |
| 4389 | + * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com> |
| 4390 | + * SPDX-License-Identifier: BSD-3-Clause |
| 4391 | + * |
| 4392 | + * This software may be distributed under the terms of the BSD license. |
| 4393 | + * See README for more details. |
| 4394 | + * |
| 4395 | + * template: src/crypto/tls_none.c |
| 4396 | + * reference: src/crypto/tls_*.c |
| 4397 | + * |
| 4398 | + * Known Limitations: |
| 4399 | + * - no TLSv1.3 (not available in mbedtls 2.x; experimental in mbedtls 3.x) |
| 4400 | + * - no OCSP (not yet available in mbedtls) |
| 4401 | + * - mbedtls does not support all certificate encodings used by hwsim tests |
| 4402 | + * PCKS#5 v1.5 |
| 4403 | + * PCKS#12 |
| 4404 | + * DH DSA |
| 4405 | + * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c |
| 4406 | + * - mbedtls does not currently provide way to set an attribute in a CSR |
| 4407 | + * https://github.com/Mbed-TLS/mbedtls/issues/4886 |
| 4408 | + * so tests/hwsim dpp_enterprise tests fail |
| 4409 | + * - DPP2 not supported |
| 4410 | + * PKCS#7 parsing is not supported in mbedtls |
| 4411 | + * See crypto_mbedtls.c:crypto_pkcs7_get_certificates() comments |
| 4412 | + * - DPP3 not supported |
| 4413 | + * hpke_base_seal() and hpke_base_seal() not implemented in crypto_mbedtls.c |
| 4414 | + * |
| 4415 | + * Status: |
| 4416 | + * - code written to be compatible with mbedtls 2.x and mbedtls 3.x |
| 4417 | + * (currently requires mbedtls >= 2.27.0 for mbedtls_mpi_random()) |
| 4418 | + * (currently requires mbedtls >= 2.18.0 for mbedtls_ssl_tls_prf()) |
| 4419 | + * - builds with tests/build/build-wpa_supplicant-mbedtls.config |
| 4420 | + * - passes all tests/ crypto module tests (incomplete coverage) |
| 4421 | + * ($ cd tests; make clean; make -j 4 run-tests CONFIG_TLS=mbedtls) |
| 4422 | + * - passes almost all tests/hwsim tests |
| 4423 | + * (hwsim tests skipped for missing features) |
| 4424 | + * |
| 4425 | + * RFE: |
| 4426 | + * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c |
| 4427 | + * - client/server session resumption, and/or save client session ticket |
| 4428 | + */ |
| 4429 | + |
| 4430 | +#include "includes.h" |
| 4431 | +#include "common.h" |
| 4432 | + |
| 4433 | +#include <mbedtls/version.h> |
| 4434 | +#include <mbedtls/ctr_drbg.h> |
| 4435 | +#include <mbedtls/error.h> |
| 4436 | +#include <mbedtls/oid.h> |
| 4437 | +#include <mbedtls/pem.h> |
| 4438 | +#include <mbedtls/platform.h> /* mbedtls_calloc() mbedtls_free() */ |
| 4439 | +#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */ |
| 4440 | +#include <mbedtls/ssl.h> |
| 4441 | +#include <mbedtls/ssl_ticket.h> |
| 4442 | +#include <mbedtls/x509.h> |
| 4443 | +#include <mbedtls/x509_crt.h> |
| 4444 | + |
| 4445 | +#if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.4.0 */ |
| 4446 | +#include <mbedtls/net_sockets.h> |
| 4447 | +#else |
| 4448 | +#include <mbedtls/net.h> |
| 4449 | +#endif |
| 4450 | + |
| 4451 | +#ifndef MBEDTLS_PRIVATE |
| 4452 | +#define MBEDTLS_PRIVATE(x) x |
| 4453 | +#endif |
| 4454 | + |
| 4455 | +#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */ |
| 4456 | +#define mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl) \ |
| 4457 | + ((ssl)->MBEDTLS_PRIVATE(session) \ |
| 4458 | + ?(ssl)->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(ciphersuite) \ |
| 4459 | + : 0) |
| 4460 | +#define mbedtls_ssl_ciphersuite_get_name(info) \ |
| 4461 | + (info)->MBEDTLS_PRIVATE(name) |
| 4462 | +#endif |
| 4463 | + |
| 4464 | +#include "crypto.h" /* sha256_vector() */ |
| 4465 | +#include "tls.h" |
| 4466 | + |
| 4467 | +#ifndef SHA256_DIGEST_LENGTH |
| 4468 | +#define SHA256_DIGEST_LENGTH 32 |
| 4469 | +#endif |
| 4470 | + |
| 4471 | +#ifndef MBEDTLS_EXPKEY_FIXED_SECRET_LEN |
| 4472 | +#define MBEDTLS_EXPKEY_FIXED_SECRET_LEN 48 |
| 4473 | +#endif |
| 4474 | + |
| 4475 | +#ifndef MBEDTLS_EXPKEY_RAND_LEN |
| 4476 | +#define MBEDTLS_EXPKEY_RAND_LEN 32 |
| 4477 | +#endif |
| 4478 | + |
| 4479 | +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 4480 | +static mbedtls_ssl_export_keys_t tls_connection_export_keys_cb; |
| 4481 | +#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 4482 | +static mbedtls_ssl_export_keys_ext_t tls_connection_export_keys_cb; |
| 4483 | +#else /*(not implemented; return error)*/ |
| 4484 | +#define mbedtls_ssl_tls_prf(a,b,c,d,e,f,g,h) (-1) |
| 4485 | +typedef mbedtls_tls_prf_types int; |
| 4486 | +#endif |
| 4487 | + |
| 4488 | + |
| 4489 | +/* hostapd/wpa_supplicant provides forced_memzero(), |
| 4490 | + * but prefer mbedtls_platform_zeroize() */ |
| 4491 | +#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz) |
| 4492 | + |
| 4493 | + |
| 4494 | +#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \ |
| 4495 | + || defined(EAP_TEAP) || defined(EAP_SERVER_TEAP) |
| 4496 | +#ifdef MBEDTLS_SSL_SESSION_TICKETS |
| 4497 | +#ifdef MBEDTLS_SSL_TICKET_C |
| 4498 | +#define TLS_MBEDTLS_SESSION_TICKETS |
| 4499 | +#if defined(EAP_TEAP) || defined(EAP_SERVER_TEAP) |
| 4500 | +#define TLS_MBEDTLS_EAP_TEAP |
| 4501 | +#endif |
| 4502 | +#if !defined(CONFIG_FIPS) /* EAP-FAST keys cannot be exported in FIPS mode */ |
| 4503 | +#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) |
| 4504 | +#define TLS_MBEDTLS_EAP_FAST |
| 4505 | +#endif |
| 4506 | +#endif |
| 4507 | +#endif |
| 4508 | +#endif |
| 4509 | +#endif |
| 4510 | + |
| 4511 | + |
| 4512 | +struct tls_conf { |
| 4513 | + mbedtls_ssl_config conf; |
| 4514 | + |
| 4515 | + unsigned int verify_peer:1; |
| 4516 | + unsigned int verify_depth0_only:1; |
| 4517 | + unsigned int check_crl:2; /*(needs :2 bits for 0, 1, 2)*/ |
| 4518 | + unsigned int check_crl_strict:1; /*(needs :1 bit for 0, 1)*/ |
| 4519 | + unsigned int ca_cert_probe:1; |
| 4520 | + unsigned int has_ca_cert:1; |
| 4521 | + unsigned int has_client_cert:1; |
| 4522 | + unsigned int has_private_key:1; |
| 4523 | + unsigned int suiteb128:1; |
| 4524 | + unsigned int suiteb192:1; |
| 4525 | + mbedtls_x509_crl *crl; |
| 4526 | + mbedtls_x509_crt ca_cert; |
| 4527 | + mbedtls_x509_crt client_cert; |
| 4528 | + mbedtls_pk_context private_key; |
| 4529 | + |
| 4530 | + uint32_t refcnt; |
| 4531 | + |
| 4532 | + unsigned int flags; |
| 4533 | + char *subject_match; |
| 4534 | + char *altsubject_match; |
| 4535 | + char *suffix_match; |
| 4536 | + char *domain_match; |
| 4537 | + char *check_cert_subject; |
| 4538 | + u8 ca_cert_hash[SHA256_DIGEST_LENGTH]; |
| 4539 | + |
| 4540 | + int *ciphersuites; /* list of ciphersuite ids for mbedtls_ssl_config */ |
| 4541 | +#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */ |
| 4542 | + mbedtls_ecp_group_id *curves; |
| 4543 | +#else |
| 4544 | + uint16_t *curves; /* list of curve ids for mbedtls_ssl_config */ |
| 4545 | +#endif |
| 4546 | +}; |
| 4547 | + |
| 4548 | + |
| 4549 | +struct tls_global { |
| 4550 | + struct tls_conf *tls_conf; |
| 4551 | + char *ocsp_stapling_response; |
| 4552 | + mbedtls_ctr_drbg_context *ctr_drbg; /*(see crypto_mbedtls.c)*/ |
| 4553 | + #ifdef MBEDTLS_SSL_SESSION_TICKETS |
| 4554 | + mbedtls_ssl_ticket_context ticket_ctx; |
| 4555 | + #endif |
| 4556 | + char *ca_cert_file; |
| 4557 | + struct os_reltime crl_reload_previous; |
| 4558 | + unsigned int crl_reload_interval; |
| 4559 | + uint32_t refcnt; |
| 4560 | + struct tls_config init_conf; |
| 4561 | +}; |
| 4562 | + |
| 4563 | +static struct tls_global tls_ctx_global; |
| 4564 | + |
| 4565 | + |
| 4566 | +struct tls_connection { |
| 4567 | + struct tls_conf *tls_conf; |
| 4568 | + struct wpabuf *push_buf; |
| 4569 | + struct wpabuf *pull_buf; |
| 4570 | + size_t pull_buf_offset; |
| 4571 | + |
| 4572 | + unsigned int established:1; |
| 4573 | + unsigned int resumed:1; |
| 4574 | + unsigned int verify_peer:1; |
| 4575 | + unsigned int is_server:1; |
| 4576 | + |
| 4577 | + mbedtls_ssl_context ssl; |
| 4578 | + |
| 4579 | + mbedtls_tls_prf_types tls_prf_type; |
| 4580 | + size_t expkey_keyblock_size; |
| 4581 | + size_t expkey_secret_len; |
| 4582 | + #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 4583 | + unsigned char expkey_secret[MBEDTLS_EXPKEY_FIXED_SECRET_LEN]; |
| 4584 | + #else |
| 4585 | + unsigned char expkey_secret[MBEDTLS_MD_MAX_SIZE]; |
| 4586 | + #endif |
| 4587 | + unsigned char expkey_randbytes[MBEDTLS_EXPKEY_RAND_LEN*2]; |
| 4588 | + |
| 4589 | + int read_alerts, write_alerts, failed; |
| 4590 | + |
| 4591 | + #ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 4592 | + tls_session_ticket_cb session_ticket_cb; |
| 4593 | + void *session_ticket_cb_ctx; |
| 4594 | + unsigned char *clienthello_session_ticket; |
| 4595 | + size_t clienthello_session_ticket_len; |
| 4596 | + #endif |
| 4597 | + char *peer_subject; /* peer subject info for authenticated peer */ |
| 4598 | + struct wpabuf *success_data; |
| 4599 | +}; |
| 4600 | + |
| 4601 | + |
| 4602 | +#ifndef __has_attribute |
| 4603 | +#define __has_attribute(x) 0 |
| 4604 | +#endif |
| 4605 | + |
| 4606 | +#ifndef __GNUC_PREREQ |
| 4607 | +#define __GNUC_PREREQ(maj,min) 0 |
| 4608 | +#endif |
| 4609 | + |
| 4610 | +#ifndef __attribute_cold__ |
| 4611 | +#if __has_attribute(cold) \ |
| 4612 | + || __GNUC_PREREQ(4,3) |
| 4613 | +#define __attribute_cold__ __attribute__((__cold__)) |
| 4614 | +#else |
| 4615 | +#define __attribute_cold__ |
| 4616 | +#endif |
| 4617 | +#endif |
| 4618 | + |
| 4619 | +#ifndef __attribute_noinline__ |
| 4620 | +#if __has_attribute(noinline) \ |
| 4621 | + || __GNUC_PREREQ(3,1) |
| 4622 | +#define __attribute_noinline__ __attribute__((__noinline__)) |
| 4623 | +#else |
| 4624 | +#define __attribute_noinline__ |
| 4625 | +#endif |
| 4626 | +#endif |
| 4627 | + |
| 4628 | + |
| 4629 | +__attribute_cold__ |
| 4630 | +__attribute_noinline__ |
| 4631 | +static void emsg(int level, const char * const msg) |
| 4632 | +{ |
| 4633 | + wpa_printf(level, "MTLS: %s", msg); |
| 4634 | +} |
| 4635 | + |
| 4636 | + |
| 4637 | +__attribute_cold__ |
| 4638 | +__attribute_noinline__ |
| 4639 | +static void emsgrc(int level, const char * const msg, int rc) |
| 4640 | +{ |
| 4641 | + #ifdef MBEDTLS_ERROR_C |
| 4642 | + /* error logging convenience function that decodes mbedtls result codes */ |
| 4643 | + char buf[256]; |
| 4644 | + mbedtls_strerror(rc, buf, sizeof(buf)); |
| 4645 | + wpa_printf(level, "MTLS: %s: %s (-0x%04x)", msg, buf, -rc); |
| 4646 | + #else |
| 4647 | + wpa_printf(level, "MTLS: %s: (-0x%04x)", msg, -rc); |
| 4648 | + #endif |
| 4649 | +} |
| 4650 | + |
| 4651 | + |
| 4652 | +#define elog(rc, msg) emsgrc(MSG_ERROR, (msg), (rc)) |
| 4653 | +#define ilog(rc, msg) emsgrc(MSG_INFO, (msg), (rc)) |
| 4654 | + |
| 4655 | + |
| 4656 | +struct tls_conf * tls_conf_init(void *tls_ctx) |
| 4657 | +{ |
| 4658 | + struct tls_conf *tls_conf = os_zalloc(sizeof(*tls_conf)); |
| 4659 | + if (tls_conf == NULL) |
| 4660 | + return NULL; |
| 4661 | + tls_conf->refcnt = 1; |
| 4662 | + |
| 4663 | + mbedtls_ssl_config_init(&tls_conf->conf); |
| 4664 | + mbedtls_ssl_conf_rng(&tls_conf->conf, |
| 4665 | + mbedtls_ctr_drbg_random, tls_ctx_global.ctr_drbg); |
| 4666 | + mbedtls_x509_crt_init(&tls_conf->ca_cert); |
| 4667 | + mbedtls_x509_crt_init(&tls_conf->client_cert); |
| 4668 | + mbedtls_pk_init(&tls_conf->private_key); |
| 4669 | + |
| 4670 | + return tls_conf; |
| 4671 | +} |
| 4672 | + |
| 4673 | + |
| 4674 | +void tls_conf_deinit(struct tls_conf *tls_conf) |
| 4675 | +{ |
| 4676 | + if (tls_conf == NULL || --tls_conf->refcnt != 0) |
| 4677 | + return; |
| 4678 | + |
| 4679 | + mbedtls_x509_crt_free(&tls_conf->ca_cert); |
| 4680 | + mbedtls_x509_crt_free(&tls_conf->client_cert); |
| 4681 | + if (tls_conf->crl) { |
| 4682 | + mbedtls_x509_crl_free(tls_conf->crl); |
| 4683 | + os_free(tls_conf->crl); |
| 4684 | + } |
| 4685 | + mbedtls_pk_free(&tls_conf->private_key); |
| 4686 | + mbedtls_ssl_config_free(&tls_conf->conf); |
| 4687 | + os_free(tls_conf->curves); |
| 4688 | + os_free(tls_conf->ciphersuites); |
| 4689 | + os_free(tls_conf->subject_match); |
| 4690 | + os_free(tls_conf->altsubject_match); |
| 4691 | + os_free(tls_conf->suffix_match); |
| 4692 | + os_free(tls_conf->domain_match); |
| 4693 | + os_free(tls_conf->check_cert_subject); |
| 4694 | + os_free(tls_conf); |
| 4695 | +} |
| 4696 | + |
| 4697 | + |
| 4698 | +mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/ |
| 4699 | + |
| 4700 | +__attribute_cold__ |
| 4701 | +void * tls_init(const struct tls_config *conf) |
| 4702 | +{ |
| 4703 | + /* RFE: review struct tls_config *conf (different from tls_conf) */ |
| 4704 | + |
| 4705 | + if (++tls_ctx_global.refcnt > 1) |
| 4706 | + return &tls_ctx_global; |
| 4707 | + |
| 4708 | + tls_ctx_global.ctr_drbg = crypto_mbedtls_ctr_drbg(); |
| 4709 | + #ifdef MBEDTLS_SSL_SESSION_TICKETS |
| 4710 | + mbedtls_ssl_ticket_init(&tls_ctx_global.ticket_ctx); |
| 4711 | + mbedtls_ssl_ticket_setup(&tls_ctx_global.ticket_ctx, |
| 4712 | + mbedtls_ctr_drbg_random, |
| 4713 | + tls_ctx_global.ctr_drbg, |
| 4714 | + MBEDTLS_CIPHER_AES_256_GCM, |
| 4715 | + 43200); /* ticket timeout: 12 hours */ |
| 4716 | + #endif |
| 4717 | + /* copy struct for future use */ |
| 4718 | + tls_ctx_global.init_conf = *conf; |
| 4719 | + if (conf->openssl_ciphers) |
| 4720 | + tls_ctx_global.init_conf.openssl_ciphers = |
| 4721 | + os_strdup(conf->openssl_ciphers); |
| 4722 | + |
| 4723 | + tls_ctx_global.crl_reload_interval = conf->crl_reload_interval; |
| 4724 | + os_get_reltime(&tls_ctx_global.crl_reload_previous); |
| 4725 | + |
| 4726 | + return &tls_ctx_global; |
| 4727 | +} |
| 4728 | + |
| 4729 | + |
| 4730 | +__attribute_cold__ |
| 4731 | +void tls_deinit(void *tls_ctx) |
| 4732 | +{ |
| 4733 | + if (tls_ctx == NULL || --tls_ctx_global.refcnt != 0) |
| 4734 | + return; |
| 4735 | + |
| 4736 | + tls_conf_deinit(tls_ctx_global.tls_conf); |
| 4737 | + os_free(tls_ctx_global.ca_cert_file); |
| 4738 | + os_free(tls_ctx_global.ocsp_stapling_response); |
| 4739 | + char *openssl_ciphers; /*(allocated in tls_init())*/ |
| 4740 | + *(const char **)&openssl_ciphers = |
| 4741 | + tls_ctx_global.init_conf.openssl_ciphers; |
| 4742 | + os_free(openssl_ciphers); |
| 4743 | + #ifdef MBEDTLS_SSL_SESSION_TICKETS |
| 4744 | + mbedtls_ssl_ticket_free(&tls_ctx_global.ticket_ctx); |
| 4745 | + #endif |
| 4746 | + os_memset(&tls_ctx_global, 0, sizeof(tls_ctx_global)); |
| 4747 | +} |
| 4748 | + |
| 4749 | + |
| 4750 | +int tls_get_errors(void *tls_ctx) |
| 4751 | +{ |
| 4752 | + return 0; |
| 4753 | +} |
| 4754 | + |
| 4755 | + |
| 4756 | +static void tls_connection_deinit_expkey(struct tls_connection *conn) |
| 4757 | +{ |
| 4758 | + conn->tls_prf_type = 0; /* MBEDTLS_SSL_TLS_PRF_NONE; */ |
| 4759 | + conn->expkey_keyblock_size = 0; |
| 4760 | + conn->expkey_secret_len = 0; |
| 4761 | + forced_memzero(conn->expkey_secret, sizeof(conn->expkey_secret)); |
| 4762 | + forced_memzero(conn->expkey_randbytes, sizeof(conn->expkey_randbytes)); |
| 4763 | +} |
| 4764 | + |
| 4765 | + |
| 4766 | +#ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 4767 | +void tls_connection_deinit_clienthello_session_ticket(struct tls_connection *conn) |
| 4768 | +{ |
| 4769 | + if (conn->clienthello_session_ticket) { |
| 4770 | + mbedtls_platform_zeroize(conn->clienthello_session_ticket, |
| 4771 | + conn->clienthello_session_ticket_len); |
| 4772 | + mbedtls_free(conn->clienthello_session_ticket); |
| 4773 | + conn->clienthello_session_ticket = NULL; |
| 4774 | + conn->clienthello_session_ticket_len = 0; |
| 4775 | + } |
| 4776 | +} |
| 4777 | +#endif |
| 4778 | + |
| 4779 | + |
| 4780 | +void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) |
| 4781 | +{ |
| 4782 | + if (conn == NULL) |
| 4783 | + return; |
| 4784 | + |
| 4785 | + #if 0 /*(good intention, but never sent since we destroy self below)*/ |
| 4786 | + if (conn->established) |
| 4787 | + mbedtls_ssl_close_notify(&conn->ssl); |
| 4788 | + #endif |
| 4789 | + |
| 4790 | + if (conn->tls_prf_type) |
| 4791 | + tls_connection_deinit_expkey(conn); |
| 4792 | + |
| 4793 | + #ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 4794 | + if (conn->clienthello_session_ticket) |
| 4795 | + tls_connection_deinit_clienthello_session_ticket(conn); |
| 4796 | + #endif |
| 4797 | + |
| 4798 | + os_free(conn->peer_subject); |
| 4799 | + wpabuf_free(conn->success_data); |
| 4800 | + wpabuf_free(conn->push_buf); |
| 4801 | + wpabuf_free(conn->pull_buf); |
| 4802 | + mbedtls_ssl_free(&conn->ssl); |
| 4803 | + tls_conf_deinit(conn->tls_conf); |
| 4804 | + os_free(conn); |
| 4805 | +} |
| 4806 | + |
| 4807 | + |
| 4808 | +static void tls_mbedtls_refresh_crl(void); |
| 4809 | +static int tls_mbedtls_ssl_setup(struct tls_connection *conn); |
| 4810 | + |
| 4811 | +struct tls_connection * tls_connection_init(void *tls_ctx) |
| 4812 | +{ |
| 4813 | + struct tls_connection *conn = os_zalloc(sizeof(*conn)); |
| 4814 | + if (conn == NULL) |
| 4815 | + return NULL; |
| 4816 | + |
| 4817 | + mbedtls_ssl_init(&conn->ssl); |
| 4818 | + |
| 4819 | + conn->tls_conf = tls_ctx_global.tls_conf; /*(inherit global conf, if set)*/ |
| 4820 | + if (conn->tls_conf) { |
| 4821 | + ++conn->tls_conf->refcnt; |
| 4822 | + /* check for CRL refresh if inheriting from global config */ |
| 4823 | + tls_mbedtls_refresh_crl(); |
| 4824 | + |
| 4825 | + conn->verify_peer = conn->tls_conf->verify_peer; |
| 4826 | + if (tls_mbedtls_ssl_setup(conn) != 0) { |
| 4827 | + tls_connection_deinit(&tls_ctx_global, conn); |
| 4828 | + return NULL; |
| 4829 | + } |
| 4830 | + } |
| 4831 | + |
| 4832 | + return conn; |
| 4833 | +} |
| 4834 | + |
| 4835 | + |
| 4836 | +int tls_connection_established(void *tls_ctx, struct tls_connection *conn) |
| 4837 | +{ |
| 4838 | + return conn ? conn->established : 0; |
| 4839 | +} |
| 4840 | + |
| 4841 | + |
| 4842 | +__attribute_noinline__ |
| 4843 | +char * tls_mbedtls_peer_serial_num(const mbedtls_x509_crt *crt, char *serial_num, size_t len) |
| 4844 | +{ |
| 4845 | + /* mbedtls_x509_serial_gets() inefficiently formats to hex separated by |
| 4846 | + * colons, so generate the hex serial number here. The func |
| 4847 | + * wpa_snprintf_hex_uppercase() is similarly inefficient. */ |
| 4848 | + size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */ |
| 4849 | + while (i < crt->serial.len && crt->serial.p[i] == 0) ++i; |
| 4850 | + if (i == crt->serial.len) --i; |
| 4851 | + |
| 4852 | + const unsigned char *s = crt->serial.p + i; |
| 4853 | + const size_t e = (crt->serial.len - i) * 2; |
| 4854 | + if (e >= len) |
| 4855 | + return NULL; |
| 4856 | + #if 0 |
| 4857 | + wpa_snprintf_hex_uppercase(serial_num, len, s, crt->serial.len-i); |
| 4858 | + #else |
| 4859 | + for (i = 0; i < e; i+=2, ++s) { |
| 4860 | + serial_num[i+0] = "0123456789ABCDEF"[(*s >> 4)]; |
| 4861 | + serial_num[i+1] = "0123456789ABCDEF"[(*s & 0xF)]; |
| 4862 | + } |
| 4863 | + serial_num[e] = '\0'; |
| 4864 | + #endif |
| 4865 | + return serial_num; |
| 4866 | +} |
| 4867 | + |
| 4868 | + |
| 4869 | +char * tls_connection_peer_serial_num(void *tls_ctx, |
| 4870 | + struct tls_connection *conn) |
| 4871 | +{ |
| 4872 | + const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&conn->ssl); |
| 4873 | + if (crt == NULL) |
| 4874 | + return NULL; |
| 4875 | + size_t len = crt->serial.len * 2 + 1; |
| 4876 | + char *serial_num = os_malloc(len); |
| 4877 | + if (!serial_num) |
| 4878 | + return NULL; |
| 4879 | + return tls_mbedtls_peer_serial_num(crt, serial_num, len); |
| 4880 | +} |
| 4881 | + |
| 4882 | + |
| 4883 | +static void tls_pull_buf_reset(struct tls_connection *conn); |
| 4884 | + |
| 4885 | +int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) |
| 4886 | +{ |
| 4887 | + /* Note: this function called from eap_peer_tls_reauth_init() |
| 4888 | + * for session resumption, not for connection shutdown */ |
| 4889 | + |
| 4890 | + if (conn == NULL) |
| 4891 | + return -1; |
| 4892 | + |
| 4893 | + tls_pull_buf_reset(conn); |
| 4894 | + wpabuf_free(conn->push_buf); |
| 4895 | + conn->push_buf = NULL; |
| 4896 | + conn->established = 0; |
| 4897 | + conn->resumed = 0; |
| 4898 | + if (conn->tls_prf_type) |
| 4899 | + tls_connection_deinit_expkey(conn); |
| 4900 | + |
| 4901 | + /* RFE: prepare for session resumption? (see doc in crypto/tls.h) */ |
| 4902 | + |
| 4903 | + return mbedtls_ssl_session_reset(&conn->ssl); |
| 4904 | +} |
| 4905 | + |
| 4906 | + |
| 4907 | +static int tls_wpabuf_resize_put_data(struct wpabuf **buf, |
| 4908 | + const unsigned char *data, size_t dlen) |
| 4909 | +{ |
| 4910 | + if (wpabuf_resize(buf, dlen) < 0) |
| 4911 | + return 0; |
| 4912 | + wpabuf_put_data(*buf, data, dlen); |
| 4913 | + return 1; |
| 4914 | +} |
| 4915 | + |
| 4916 | + |
| 4917 | +static int tls_pull_buf_append(struct tls_connection *conn, |
| 4918 | + const struct wpabuf *in_data) |
| 4919 | +{ |
| 4920 | + /*(interface does not lend itself to move semantics)*/ |
| 4921 | + return tls_wpabuf_resize_put_data(&conn->pull_buf, |
| 4922 | + wpabuf_head(in_data), |
| 4923 | + wpabuf_len(in_data)); |
| 4924 | +} |
| 4925 | + |
| 4926 | + |
| 4927 | +static void tls_pull_buf_reset(struct tls_connection *conn) |
| 4928 | +{ |
| 4929 | + /*(future: might consider reusing conn->pull_buf)*/ |
| 4930 | + wpabuf_free(conn->pull_buf); |
| 4931 | + conn->pull_buf = NULL; |
| 4932 | + conn->pull_buf_offset = 0; |
| 4933 | +} |
| 4934 | + |
| 4935 | + |
| 4936 | +__attribute_cold__ |
| 4937 | +static void tls_pull_buf_discard(struct tls_connection *conn, const char *func) |
| 4938 | +{ |
| 4939 | + size_t discard = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset; |
| 4940 | + if (discard) |
| 4941 | + wpa_printf(MSG_DEBUG, |
| 4942 | + "%s - %zu bytes remaining in pull_buf; discarding", |
| 4943 | + func, discard); |
| 4944 | + tls_pull_buf_reset(conn); |
| 4945 | +} |
| 4946 | + |
| 4947 | + |
| 4948 | +static int tls_pull_func(void *ptr, unsigned char *buf, size_t len) |
| 4949 | +{ |
| 4950 | + struct tls_connection *conn = (struct tls_connection *) ptr; |
| 4951 | + if (conn->pull_buf == NULL) |
| 4952 | + return MBEDTLS_ERR_SSL_WANT_READ; |
| 4953 | + const size_t dlen = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset; |
| 4954 | + if (dlen == 0) |
| 4955 | + return MBEDTLS_ERR_SSL_WANT_READ; |
| 4956 | + |
| 4957 | + if (len > dlen) |
| 4958 | + len = dlen; |
| 4959 | + os_memcpy(buf, wpabuf_head(conn->pull_buf)+conn->pull_buf_offset, len); |
| 4960 | + |
| 4961 | + if (len == dlen) { |
| 4962 | + tls_pull_buf_reset(conn); |
| 4963 | + /*wpa_printf(MSG_DEBUG, "%s - emptied pull_buf", __func__);*/ |
| 4964 | + } |
| 4965 | + else { |
| 4966 | + conn->pull_buf_offset += len; |
| 4967 | + /*wpa_printf(MSG_DEBUG, "%s - %zu bytes remaining in pull_buf", |
| 4968 | + __func__, dlen - len);*/ |
| 4969 | + } |
| 4970 | + return (int)len; |
| 4971 | +} |
| 4972 | + |
| 4973 | + |
| 4974 | +static int tls_push_func(void *ptr, const unsigned char *buf, size_t len) |
| 4975 | +{ |
| 4976 | + struct tls_connection *conn = (struct tls_connection *) ptr; |
| 4977 | + return tls_wpabuf_resize_put_data(&conn->push_buf, buf, len) |
| 4978 | + ? (int)len |
| 4979 | + : MBEDTLS_ERR_SSL_ALLOC_FAILED; |
| 4980 | +} |
| 4981 | + |
| 4982 | + |
| 4983 | +static int |
| 4984 | +tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags); |
| 4985 | + |
| 4986 | + |
| 4987 | +static int tls_mbedtls_ssl_setup(struct tls_connection *conn) |
| 4988 | +{ |
| 4989 | + #if 0 |
| 4990 | + /* mbedtls_ssl_setup() must be called only once */ |
| 4991 | + /* If this func might be called multiple times (e.g. via set_params), |
| 4992 | + * then we should set a flag in conn that ssl was initialized */ |
| 4993 | + if (conn->ssl_is_init) { |
| 4994 | + mbedtls_ssl_free(&conn->ssl); |
| 4995 | + mbedtls_ssl_init(&conn->ssl); |
| 4996 | + } |
| 4997 | + #endif |
| 4998 | + |
| 4999 | + int ret = mbedtls_ssl_setup(&conn->ssl, &conn->tls_conf->conf); |
| 5000 | + if (ret != 0) { |
| 5001 | + elog(ret, "mbedtls_ssl_setup"); |
| 5002 | + return -1; |
| 5003 | + } |
| 5004 | + |
| 5005 | + mbedtls_ssl_set_bio(&conn->ssl, conn, tls_push_func, tls_pull_func, NULL); |
| 5006 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 5007 | + mbedtls_ssl_set_export_keys_cb( |
| 5008 | + &conn->ssl, tls_connection_export_keys_cb, conn); |
| 5009 | + #elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 5010 | + mbedtls_ssl_conf_export_keys_ext_cb( |
| 5011 | + &conn->tls_conf->conf, tls_connection_export_keys_cb, conn); |
| 5012 | + #endif |
| 5013 | + if (conn->verify_peer) |
| 5014 | + mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn); |
| 5015 | + |
| 5016 | + return 0; |
| 5017 | +} |
| 5018 | + |
| 5019 | + |
| 5020 | +static int tls_mbedtls_data_is_pem(const u8 *data) |
| 5021 | +{ |
| 5022 | + return (NULL != os_strstr((char *)data, "-----")); |
| 5023 | +} |
| 5024 | + |
| 5025 | + |
| 5026 | +static void tls_mbedtls_set_allowed_tls_vers(struct tls_conf *tls_conf, |
| 5027 | + mbedtls_ssl_config *conf) |
| 5028 | +{ |
| 5029 | + #if !defined(MBEDTLS_SSL_PROTO_TLS1_3) |
| 5030 | + tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_3; |
| 5031 | + #endif |
| 5032 | + |
| 5033 | + /* unconditionally require TLSv1.2+ for TLS_CONN_SUITEB */ |
| 5034 | + if (tls_conf->flags & TLS_CONN_SUITEB) { |
| 5035 | + tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_0; |
| 5036 | + tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_1; |
| 5037 | + } |
| 5038 | + |
| 5039 | + const unsigned int flags = tls_conf->flags; |
| 5040 | + |
| 5041 | + /* attempt to map flags to min and max TLS protocol version */ |
| 5042 | + |
| 5043 | + int min = (flags & TLS_CONN_DISABLE_TLSv1_0) |
| 5044 | + ? (flags & TLS_CONN_DISABLE_TLSv1_1) |
| 5045 | + ? (flags & TLS_CONN_DISABLE_TLSv1_2) |
| 5046 | + ? (flags & TLS_CONN_DISABLE_TLSv1_3) |
| 5047 | + ? 4 |
| 5048 | + : 3 |
| 5049 | + : 2 |
| 5050 | + : 1 |
| 5051 | + : 0; |
| 5052 | + |
| 5053 | + int max = (flags & TLS_CONN_DISABLE_TLSv1_3) |
| 5054 | + ? (flags & TLS_CONN_DISABLE_TLSv1_2) |
| 5055 | + ? (flags & TLS_CONN_DISABLE_TLSv1_1) |
| 5056 | + ? (flags & TLS_CONN_DISABLE_TLSv1_0) |
| 5057 | + ? -1 |
| 5058 | + : 0 |
| 5059 | + : 1 |
| 5060 | + : 2 |
| 5061 | + : 3; |
| 5062 | + |
| 5063 | + if ((flags & TLS_CONN_ENABLE_TLSv1_2) && min > 2) min = 2; |
| 5064 | + if ((flags & TLS_CONN_ENABLE_TLSv1_1) && min > 1) min = 1; |
| 5065 | + if ((flags & TLS_CONN_ENABLE_TLSv1_0) && min > 0) min = 0; |
| 5066 | + if (max < min) { |
| 5067 | + emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring"); |
| 5068 | + return; |
| 5069 | + } |
| 5070 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 5071 | + /* mbed TLS 3.0.0 removes support for protocols < TLSv1.2 */ |
| 5072 | + if (min < 2 || max < 2) { |
| 5073 | + emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring"); |
| 5074 | + if (min < 2) min = 2; |
| 5075 | + if (max < 2) max = 2; |
| 5076 | + } |
| 5077 | + #endif |
| 5078 | + |
| 5079 | + #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ |
| 5080 | + /* MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303 *//*!< (D)TLS 1.2 */ |
| 5081 | + /* MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304 *//*!< (D)TLS 1.3 */ |
| 5082 | + min = (min == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3; |
| 5083 | + max = (max == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3; |
| 5084 | + mbedtls_ssl_conf_min_tls_version(conf, min); |
| 5085 | + mbedtls_ssl_conf_max_tls_version(conf, max); |
| 5086 | + #else |
| 5087 | + #ifndef MBEDTLS_SSL_MINOR_VERSION_4 |
| 5088 | + if (min == 3) min = 2; |
| 5089 | + if (max == 3) max = 2; |
| 5090 | + #endif |
| 5091 | + /* MBEDTLS_SSL_MINOR_VERSION_0 0 *//*!< SSL v3.0 */ |
| 5092 | + /* MBEDTLS_SSL_MINOR_VERSION_1 1 *//*!< TLS v1.0 */ |
| 5093 | + /* MBEDTLS_SSL_MINOR_VERSION_2 2 *//*!< TLS v1.1 */ |
| 5094 | + /* MBEDTLS_SSL_MINOR_VERSION_3 3 *//*!< TLS v1.2 */ |
| 5095 | + /* MBEDTLS_SSL_MINOR_VERSION_4 4 *//*!< TLS v1.3 */ |
| 5096 | + mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, min+1); |
| 5097 | + mbedtls_ssl_conf_max_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, max+1); |
| 5098 | + #endif |
| 5099 | +} |
| 5100 | + |
| 5101 | + |
| 5102 | +__attribute_noinline__ |
| 5103 | +static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n); |
| 5104 | + |
| 5105 | + |
| 5106 | +static int |
| 5107 | +tls_mbedtls_set_dhparams(struct tls_conf *tls_conf, const char *dh_file) |
| 5108 | +{ |
| 5109 | + size_t len; |
| 5110 | + u8 *data; |
| 5111 | + if (tls_mbedtls_readfile(dh_file, &data, &len)) |
| 5112 | + return 0; |
| 5113 | + |
| 5114 | + /* parse only if DH parameters if in PEM format */ |
| 5115 | + if (tls_mbedtls_data_is_pem(data) |
| 5116 | + && NULL == os_strstr((char *)data, "-----BEGIN DH PARAMETERS-----")) { |
| 5117 | + if (os_strstr((char *)data, "-----BEGIN DSA PARAMETERS-----")) |
| 5118 | + wpa_printf(MSG_WARNING, "DSA parameters not handled (%s)", dh_file); |
| 5119 | + else |
| 5120 | + wpa_printf(MSG_WARNING, "unexpected DH param content (%s)",dh_file); |
| 5121 | + forced_memzero(data, len); |
| 5122 | + os_free(data); |
| 5123 | + return 0; |
| 5124 | + } |
| 5125 | + |
| 5126 | + /* mbedtls_dhm_parse_dhm() expects "-----BEGIN DH PARAMETERS-----" if PEM */ |
| 5127 | + mbedtls_dhm_context dhm; |
| 5128 | + mbedtls_dhm_init(&dhm); |
| 5129 | + int rc = mbedtls_dhm_parse_dhm(&dhm, data, len); |
| 5130 | + if (0 == rc) |
| 5131 | + rc = mbedtls_ssl_conf_dh_param_ctx(&tls_conf->conf, &dhm); |
| 5132 | + if (0 != rc) |
| 5133 | + elog(rc, dh_file); |
| 5134 | + mbedtls_dhm_free(&dhm); |
| 5135 | + |
| 5136 | + forced_memzero(data, len); |
| 5137 | + os_free(data); |
| 5138 | + return (0 == rc); |
| 5139 | +} |
| 5140 | + |
| 5141 | + |
| 5142 | +/* reference: lighttpd src/mod_mbedtls.c:mod_mbedtls_ssl_append_curve() |
| 5143 | + * (same author: gstrauss@gluelogic.com; same license: BSD-3-Clause) */ |
| 5144 | +#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */ |
| 5145 | +static int |
| 5146 | +tls_mbedtls_append_curve (mbedtls_ecp_group_id *ids, int nids, int idsz, const mbedtls_ecp_group_id id) |
| 5147 | +{ |
| 5148 | + if (1 >= idsz - (nids + 1)) { |
| 5149 | + emsg(MSG_ERROR, "error: too many curves during list expand"); |
| 5150 | + return -1; |
| 5151 | + } |
| 5152 | + ids[++nids] = id; |
| 5153 | + return nids; |
| 5154 | +} |
| 5155 | + |
| 5156 | + |
| 5157 | +static int |
| 5158 | +tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist) |
| 5159 | +{ |
| 5160 | + mbedtls_ecp_group_id ids[512]; |
| 5161 | + int nids = -1; |
| 5162 | + const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1); |
| 5163 | + const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list(); |
| 5164 | + |
| 5165 | + for (const char *e = curvelist-1; e; ) { |
| 5166 | + const char * const n = e+1; |
| 5167 | + e = os_strchr(n, ':'); |
| 5168 | + size_t len = e ? (size_t)(e - n) : os_strlen(n); |
| 5169 | + mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE; |
| 5170 | + switch (len) { |
| 5171 | + case 5: |
| 5172 | + if (0 == os_memcmp("P-521", n, 5)) |
| 5173 | + grp_id = MBEDTLS_ECP_DP_SECP521R1; |
| 5174 | + else if (0 == os_memcmp("P-384", n, 5)) |
| 5175 | + grp_id = MBEDTLS_ECP_DP_SECP384R1; |
| 5176 | + else if (0 == os_memcmp("P-256", n, 5)) |
| 5177 | + grp_id = MBEDTLS_ECP_DP_SECP256R1; |
| 5178 | + break; |
| 5179 | + case 6: |
| 5180 | + if (0 == os_memcmp("BP-521", n, 6)) |
| 5181 | + grp_id = MBEDTLS_ECP_DP_BP512R1; |
| 5182 | + else if (0 == os_memcmp("BP-384", n, 6)) |
| 5183 | + grp_id = MBEDTLS_ECP_DP_BP384R1; |
| 5184 | + else if (0 == os_memcmp("BP-256", n, 6)) |
| 5185 | + grp_id = MBEDTLS_ECP_DP_BP256R1; |
| 5186 | + break; |
| 5187 | + default: |
| 5188 | + break; |
| 5189 | + } |
| 5190 | + if (grp_id != MBEDTLS_ECP_DP_NONE) { |
| 5191 | + nids = tls_mbedtls_append_curve(ids, nids, idsz, grp_id); |
| 5192 | + if (-1 == nids) return 0; |
| 5193 | + continue; |
| 5194 | + } |
| 5195 | + /* similar to mbedtls_ecp_curve_info_from_name() */ |
| 5196 | + const mbedtls_ecp_curve_info *info; |
| 5197 | + for (info = curve_info; info->grp_id != MBEDTLS_ECP_DP_NONE; ++info) { |
| 5198 | + if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0') |
| 5199 | + break; |
| 5200 | + } |
| 5201 | + if (info->grp_id == MBEDTLS_ECP_DP_NONE) { |
| 5202 | + wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n); |
| 5203 | + return 0; |
| 5204 | + } |
| 5205 | + |
| 5206 | + nids = tls_mbedtls_append_curve(ids, nids, idsz, info->grp_id); |
| 5207 | + if (-1 == nids) return 0; |
| 5208 | + } |
| 5209 | + |
| 5210 | + /* mod_openssl configures "prime256v1" if curve list not specified, |
| 5211 | + * but mbedtls provides a list of supported curves if not explicitly set */ |
| 5212 | + if (-1 == nids) return 1; /* empty list; no-op */ |
| 5213 | + |
| 5214 | + ids[++nids] = MBEDTLS_ECP_DP_NONE; /* terminate list */ |
| 5215 | + ++nids; |
| 5216 | + |
| 5217 | + /* curves list must be persistent for lifetime of mbedtls_ssl_config */ |
| 5218 | + tls_conf->curves = os_malloc(nids * sizeof(mbedtls_ecp_group_id)); |
| 5219 | + if (tls_conf->curves == NULL) |
| 5220 | + return 0; |
| 5221 | + os_memcpy(tls_conf->curves, ids, nids * sizeof(mbedtls_ecp_group_id)); |
| 5222 | + |
| 5223 | + mbedtls_ssl_conf_curves(&tls_conf->conf, tls_conf->curves); |
| 5224 | + return 1; |
| 5225 | +} |
| 5226 | +#else |
| 5227 | +static int |
| 5228 | +tls_mbedtls_append_curve (uint16_t *ids, int nids, int idsz, const uint16_t id) |
| 5229 | +{ |
| 5230 | + if (1 >= idsz - (nids + 1)) { |
| 5231 | + emsg(MSG_ERROR, "error: too many curves during list expand"); |
| 5232 | + return -1; |
| 5233 | + } |
| 5234 | + ids[++nids] = id; |
| 5235 | + return nids; |
| 5236 | +} |
| 5237 | + |
| 5238 | + |
| 5239 | +static int |
| 5240 | +tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist) |
| 5241 | +{ |
| 5242 | + /* TLS Supported Groups (renamed from "EC Named Curve Registry") |
| 5243 | + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 |
| 5244 | + */ |
| 5245 | + uint16_t ids[512]; |
| 5246 | + int nids = -1; |
| 5247 | + const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1); |
| 5248 | + const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list(); |
| 5249 | + |
| 5250 | + for (const char *e = curvelist-1; e; ) { |
| 5251 | + const char * const n = e+1; |
| 5252 | + e = os_strchr(n, ':'); |
| 5253 | + size_t len = e ? (size_t)(e - n) : os_strlen(n); |
| 5254 | + uint16_t tls_id = 0; |
| 5255 | + switch (len) { |
| 5256 | + case 5: |
| 5257 | + if (0 == os_memcmp("P-521", n, 5)) |
| 5258 | + tls_id = 25; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP521R1 */ |
| 5259 | + else if (0 == os_memcmp("P-384", n, 5)) |
| 5260 | + tls_id = 24; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP384R1 */ |
| 5261 | + else if (0 == os_memcmp("P-256", n, 5)) |
| 5262 | + tls_id = 23; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP256R1 */ |
| 5263 | + break; |
| 5264 | + case 6: |
| 5265 | + if (0 == os_memcmp("BP-521", n, 6)) |
| 5266 | + tls_id = 28; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP512R1 */ |
| 5267 | + else if (0 == os_memcmp("BP-384", n, 6)) |
| 5268 | + tls_id = 27; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP384R1 */ |
| 5269 | + else if (0 == os_memcmp("BP-256", n, 6)) |
| 5270 | + tls_id = 26; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP256R1 */ |
| 5271 | + break; |
| 5272 | + default: |
| 5273 | + break; |
| 5274 | + } |
| 5275 | + if (tls_id != 0) { |
| 5276 | + nids = tls_mbedtls_append_curve(ids, nids, idsz, tls_id); |
| 5277 | + if (-1 == nids) return 0; |
| 5278 | + continue; |
| 5279 | + } |
| 5280 | + /* similar to mbedtls_ecp_curve_info_from_name() */ |
| 5281 | + const mbedtls_ecp_curve_info *info; |
| 5282 | + for (info = curve_info; info->tls_id != 0; ++info) { |
| 5283 | + if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0') |
| 5284 | + break; |
| 5285 | + } |
| 5286 | + if (info->tls_id == 0) { |
| 5287 | + wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n); |
| 5288 | + return 0; |
| 5289 | + } |
| 5290 | + |
| 5291 | + nids = tls_mbedtls_append_curve(ids, nids, idsz, info->tls_id); |
| 5292 | + if (-1 == nids) return 0; |
| 5293 | + } |
| 5294 | + |
| 5295 | + /* mod_openssl configures "prime256v1" if curve list not specified, |
| 5296 | + * but mbedtls provides a list of supported curves if not explicitly set */ |
| 5297 | + if (-1 == nids) return 1; /* empty list; no-op */ |
| 5298 | + |
| 5299 | + ids[++nids] = 0; /* terminate list */ |
| 5300 | + ++nids; |
| 5301 | + |
| 5302 | + /* curves list must be persistent for lifetime of mbedtls_ssl_config */ |
| 5303 | + tls_conf->curves = os_malloc(nids * sizeof(uint16_t)); |
| 5304 | + if (tls_conf->curves == NULL) |
| 5305 | + return 0; |
| 5306 | + os_memcpy(tls_conf->curves, ids, nids * sizeof(uint16_t)); |
| 5307 | + |
| 5308 | + mbedtls_ssl_conf_groups(&tls_conf->conf, tls_conf->curves); |
| 5309 | + return 1; |
| 5310 | +} |
| 5311 | +#endif /* MBEDTLS_VERSION_NUMBER >= 0x03010000 */ /* mbedtls 3.1.0 */ |
| 5312 | + |
| 5313 | + |
| 5314 | +/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */ |
| 5315 | +static const int suite_AES_256_ephemeral[] = { |
| 5316 | + /* All AES-256 ephemeral suites */ |
| 5317 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
| 5318 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, |
| 5319 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, |
| 5320 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, |
| 5321 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, |
| 5322 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, |
| 5323 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, |
| 5324 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, |
| 5325 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, |
| 5326 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, |
| 5327 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, |
| 5328 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, |
| 5329 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8 |
| 5330 | +}; |
| 5331 | + |
| 5332 | +/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */ |
| 5333 | +static const int suite_AES_128_ephemeral[] = { |
| 5334 | + /* All AES-128 ephemeral suites */ |
| 5335 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
| 5336 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, |
| 5337 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, |
| 5338 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, |
| 5339 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, |
| 5340 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, |
| 5341 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, |
| 5342 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, |
| 5343 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, |
| 5344 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, |
| 5345 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, |
| 5346 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, |
| 5347 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8 |
| 5348 | +}; |
| 5349 | + |
| 5350 | +/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */ |
| 5351 | +/* HIGH cipher list (mapped from openssl list to mbedtls) */ |
| 5352 | +static const int suite_HIGH[] = { |
| 5353 | + MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
| 5354 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, |
| 5355 | + MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, |
| 5356 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
| 5357 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, |
| 5358 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, |
| 5359 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, |
| 5360 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, |
| 5361 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, |
| 5362 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, |
| 5363 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, |
| 5364 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, |
| 5365 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, |
| 5366 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, |
| 5367 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8, |
| 5368 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8, |
| 5369 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384, |
| 5370 | + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384, |
| 5371 | + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, |
| 5372 | + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, |
| 5373 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384, |
| 5374 | + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384, |
| 5375 | + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384, |
| 5376 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
| 5377 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, |
| 5378 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, |
| 5379 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, |
| 5380 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, |
| 5381 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, |
| 5382 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, |
| 5383 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, |
| 5384 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, |
| 5385 | + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, |
| 5386 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, |
| 5387 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8, |
| 5388 | + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, |
| 5389 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256, |
| 5390 | + MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
| 5391 | + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
| 5392 | + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, |
| 5393 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256, |
| 5394 | + MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256, |
| 5395 | + MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256, |
| 5396 | + MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, |
| 5397 | + MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, |
| 5398 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, |
| 5399 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, |
| 5400 | + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, |
| 5401 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, |
| 5402 | + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, |
| 5403 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, |
| 5404 | + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
| 5405 | + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
| 5406 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, |
| 5407 | + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384, |
| 5408 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, |
| 5409 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, |
| 5410 | + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, |
| 5411 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, |
| 5412 | + MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, |
| 5413 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, |
| 5414 | + MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
| 5415 | + MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
| 5416 | + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, |
| 5417 | + MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256, |
| 5418 | + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, |
| 5419 | + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, |
| 5420 | + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, |
| 5421 | + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, |
| 5422 | + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, |
| 5423 | + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256, |
| 5424 | + MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, |
| 5425 | + MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384, |
| 5426 | + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, |
| 5427 | + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, |
| 5428 | + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, |
| 5429 | + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, |
| 5430 | + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, |
| 5431 | + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, |
| 5432 | + MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, |
| 5433 | + MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256, |
| 5434 | + MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256, |
| 5435 | + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, |
| 5436 | + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, |
| 5437 | + MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA, |
| 5438 | + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
| 5439 | + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384, |
| 5440 | + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, |
| 5441 | + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, |
| 5442 | + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, |
| 5443 | + MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
| 5444 | + MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256, |
| 5445 | + MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, |
| 5446 | + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, |
| 5447 | + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, |
| 5448 | + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, |
| 5449 | + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, |
| 5450 | + MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, |
| 5451 | + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, |
| 5452 | + MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384, |
| 5453 | + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, |
| 5454 | + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, |
| 5455 | + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, |
| 5456 | + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, |
| 5457 | + MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, |
| 5458 | + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, |
| 5459 | + MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 |
| 5460 | +}; |
| 5461 | + |
| 5462 | + |
| 5463 | +__attribute_noinline__ |
| 5464 | +static int |
| 5465 | +tls_mbedtls_append_ciphersuite (int *ids, int nids, int idsz, const int *x, int xsz) |
| 5466 | +{ |
| 5467 | + if (xsz >= idsz - (nids + 1)) { |
| 5468 | + emsg(MSG_ERROR, "error: too many ciphers during list expand"); |
| 5469 | + return -1; |
| 5470 | + } |
| 5471 | + |
| 5472 | + for (int i = 0; i < xsz; ++i) |
| 5473 | + ids[++nids] = x[i]; |
| 5474 | + |
| 5475 | + return nids; |
| 5476 | +} |
| 5477 | + |
| 5478 | + |
| 5479 | +static int |
| 5480 | +tls_mbedtls_translate_ciphername(int id, char *buf, size_t buflen) |
| 5481 | +{ |
| 5482 | + const mbedtls_ssl_ciphersuite_t *info = |
| 5483 | + mbedtls_ssl_ciphersuite_from_id(id); |
| 5484 | + if (info == NULL) |
| 5485 | + return 0; |
| 5486 | + const char *name = mbedtls_ssl_ciphersuite_get_name(info); |
| 5487 | + const size_t len = os_strlen(name); |
| 5488 | + if (len == 7 && 0 == os_memcmp(name, "unknown", 7)) |
| 5489 | + return 0; |
| 5490 | + if (len >= buflen) |
| 5491 | + return 0; |
| 5492 | + os_strlcpy(buf, name, buflen); |
| 5493 | + |
| 5494 | + /* attempt to translate mbedtls string to openssl string |
| 5495 | + * (some heuristics; incomplete) */ |
| 5496 | + size_t i = 0, j = 0; |
| 5497 | + if (buf[0] == 'T') { |
| 5498 | + if (os_strncmp(buf, "TLS1-3-", 7) == 0) { |
| 5499 | + buf[3] = '-'; |
| 5500 | + j = 4; /* remove "1-3" from "TLS1-3-" prefix */ |
| 5501 | + i = 7; |
| 5502 | + } |
| 5503 | + else if (os_strncmp(buf, "TLS-", 4) == 0) |
| 5504 | + i = 4; /* remove "TLS-" prefix */ |
| 5505 | + } |
| 5506 | + for (; buf[i]; ++i) { |
| 5507 | + if (buf[i] == '-') { |
| 5508 | + if (i >= 3) { |
| 5509 | + if (0 == os_memcmp(buf+i-3, "AES", 3)) |
| 5510 | + continue; /* "AES-" -> "AES" */ |
| 5511 | + } |
| 5512 | + if (i >= 4) { |
| 5513 | + if (0 == os_memcmp(buf+i-4, "WITH", 4)) { |
| 5514 | + j -= 4; /* remove "WITH-" */ |
| 5515 | + continue; |
| 5516 | + } |
| 5517 | + } |
| 5518 | + } |
| 5519 | + buf[j++] = buf[i]; |
| 5520 | + } |
| 5521 | + buf[j] = '\0'; |
| 5522 | + |
| 5523 | + return j; |
| 5524 | +} |
| 5525 | + |
| 5526 | + |
| 5527 | +__attribute_noinline__ |
| 5528 | +static int |
| 5529 | +tls_mbedtls_set_ciphersuites(struct tls_conf *tls_conf, int *ids, int nids) |
| 5530 | +{ |
| 5531 | + /* ciphersuites list must be persistent for lifetime of mbedtls_ssl_config*/ |
| 5532 | + os_free(tls_conf->ciphersuites); |
| 5533 | + tls_conf->ciphersuites = os_malloc(nids * sizeof(int)); |
| 5534 | + if (tls_conf->ciphersuites == NULL) |
| 5535 | + return 0; |
| 5536 | + os_memcpy(tls_conf->ciphersuites, ids, nids * sizeof(int)); |
| 5537 | + mbedtls_ssl_conf_ciphersuites(&tls_conf->conf, tls_conf->ciphersuites); |
| 5538 | + return 1; |
| 5539 | +} |
| 5540 | + |
| 5541 | + |
| 5542 | +static int |
| 5543 | +tls_mbedtls_set_ciphers(struct tls_conf *tls_conf, const char *ciphers) |
| 5544 | +{ |
| 5545 | + char buf[64]; |
| 5546 | + int ids[512]; |
| 5547 | + int nids = -1; |
| 5548 | + const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1); |
| 5549 | + const char *next; |
| 5550 | + size_t blen, clen; |
| 5551 | + do { |
| 5552 | + next = os_strchr(ciphers, ':'); |
| 5553 | + clen = next ? (size_t)(next - ciphers) : os_strlen(ciphers); |
| 5554 | + if (!clen) |
| 5555 | + continue; |
| 5556 | + |
| 5557 | + /* special-case a select set of openssl group names for hwsim tests */ |
| 5558 | + /* (review; remove excess code if tests are not run for non-OpenSSL?) */ |
| 5559 | + if (clen == 9 && os_memcmp(ciphers, "SUITEB192", 9) == 0) { |
| 5560 | + static int ssl_preset_suiteb192_ciphersuites[] = { |
| 5561 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, |
| 5562 | + 0 |
| 5563 | + }; |
| 5564 | + return tls_mbedtls_set_ciphersuites(tls_conf, |
| 5565 | + ssl_preset_suiteb192_ciphersuites, |
| 5566 | + 2); |
| 5567 | + } |
| 5568 | + if (clen == 9 && os_memcmp(ciphers, "SUITEB128", 9) == 0) { |
| 5569 | + static int ssl_preset_suiteb128_ciphersuites[] = { |
| 5570 | + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, |
| 5571 | + 0 |
| 5572 | + }; |
| 5573 | + return tls_mbedtls_set_ciphersuites(tls_conf, |
| 5574 | + ssl_preset_suiteb128_ciphersuites, |
| 5575 | + 2); |
| 5576 | + } |
| 5577 | + if (clen == 7 && os_memcmp(ciphers, "DEFAULT", 7) == 0) |
| 5578 | + continue; |
| 5579 | + if (clen == 6 && os_memcmp(ciphers, "AES128", 6) == 0) { |
| 5580 | + nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, |
| 5581 | + suite_AES_128_ephemeral, |
| 5582 | + (int)ARRAY_SIZE(suite_AES_128_ephemeral)); |
| 5583 | + if (nids == -1) |
| 5584 | + return 0; |
| 5585 | + continue; |
| 5586 | + } |
| 5587 | + if (clen == 6 && os_memcmp(ciphers, "AES256", 6) == 0) { |
| 5588 | + nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, |
| 5589 | + suite_AES_256_ephemeral, |
| 5590 | + (int)ARRAY_SIZE(suite_AES_256_ephemeral)); |
| 5591 | + if (nids == -1) |
| 5592 | + return 0; |
| 5593 | + continue; |
| 5594 | + } |
| 5595 | + if (clen == 4 && os_memcmp(ciphers, "HIGH", 4) == 0) { |
| 5596 | + nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, suite_HIGH, |
| 5597 | + (int)ARRAY_SIZE(suite_HIGH)); |
| 5598 | + if (nids == -1) |
| 5599 | + return 0; |
| 5600 | + continue; |
| 5601 | + } |
| 5602 | + /* ignore anonymous cipher group names (?not supported by mbedtls?) */ |
| 5603 | + if (clen == 4 && os_memcmp(ciphers, "!ADH", 4) == 0) |
| 5604 | + continue; |
| 5605 | + if (clen == 6 && os_memcmp(ciphers, "-aECDH", 6) == 0) |
| 5606 | + continue; |
| 5607 | + if (clen == 7 && os_memcmp(ciphers, "-aECDSA", 7) == 0) |
| 5608 | + continue; |
| 5609 | + |
| 5610 | + /* attempt to match mbedtls cipher names |
| 5611 | + * nb: does not support openssl group names or list manipulation syntax |
| 5612 | + * (alt: could copy almost 1200 lines (!!!) of lighttpd mod_mbedtls.c |
| 5613 | + * mod_mbedtls_ssl_conf_ciphersuites() to translate strings) |
| 5614 | + * note: not efficient to rewrite list for each ciphers entry, |
| 5615 | + * but this code is expected to run only at startup |
| 5616 | + */ |
| 5617 | + const int *list = mbedtls_ssl_list_ciphersuites(); |
| 5618 | + for (; *list; ++list) { |
| 5619 | + blen = tls_mbedtls_translate_ciphername(*list,buf,sizeof(buf)); |
| 5620 | + if (!blen) |
| 5621 | + continue; |
| 5622 | + |
| 5623 | + /* matching heuristics additional to translate_ciphername above */ |
| 5624 | + if (blen == clen+4) { |
| 5625 | + char *cbc = os_strstr(buf, "CBC-"); |
| 5626 | + if (cbc) { |
| 5627 | + os_memmove(cbc, cbc+4, blen-(cbc+4-buf)+1); /*(w/ '\0')*/ |
| 5628 | + blen -= 4; |
| 5629 | + } |
| 5630 | + } |
| 5631 | + if (blen >= clen && os_memcmp(ciphers, buf, clen) == 0 |
| 5632 | + && (blen == clen |
| 5633 | + || (blen == clen+7 && os_memcmp(buf+clen, "-SHA256", 7)))) { |
| 5634 | + if (1 >= idsz - (nids + 1)) { |
| 5635 | + emsg(MSG_ERROR, |
| 5636 | + "error: too many ciphers during list expand"); |
| 5637 | + return 0; |
| 5638 | + } |
| 5639 | + ids[++nids] = *list; |
| 5640 | + break; |
| 5641 | + } |
| 5642 | + } |
| 5643 | + if (*list == 0) { |
| 5644 | + wpa_printf(MSG_ERROR, |
| 5645 | + "MTLS: unrecognized cipher: %.*s", (int)clen, ciphers); |
| 5646 | + return 0; |
| 5647 | + } |
| 5648 | + } while ((ciphers = next ? next+1 : NULL)); |
| 5649 | + |
| 5650 | + if (-1 == nids) return 1; /* empty list; no-op */ |
| 5651 | + |
| 5652 | + ids[++nids] = 0; /* terminate list */ |
| 5653 | + ++nids; |
| 5654 | + |
| 5655 | + return tls_mbedtls_set_ciphersuites(tls_conf, ids, nids); |
| 5656 | +} |
| 5657 | + |
| 5658 | + |
| 5659 | +__attribute_noinline__ |
| 5660 | +static int tls_mbedtls_set_item(char **config_item, const char *item) |
| 5661 | +{ |
| 5662 | + os_free(*config_item); |
| 5663 | + *config_item = NULL; |
| 5664 | + return item ? (*config_item = os_strdup(item)) != NULL : 1; |
| 5665 | +} |
| 5666 | + |
| 5667 | + |
| 5668 | +static int tls_connection_set_subject_match(struct tls_conf *tls_conf, |
| 5669 | + const struct tls_connection_params *params) |
| 5670 | +{ |
| 5671 | + int rc = 1; |
| 5672 | + rc &= tls_mbedtls_set_item(&tls_conf->subject_match, |
| 5673 | + params->subject_match); |
| 5674 | + rc &= tls_mbedtls_set_item(&tls_conf->altsubject_match, |
| 5675 | + params->altsubject_match); |
| 5676 | + rc &= tls_mbedtls_set_item(&tls_conf->suffix_match, |
| 5677 | + params->suffix_match); |
| 5678 | + rc &= tls_mbedtls_set_item(&tls_conf->domain_match, |
| 5679 | + params->domain_match); |
| 5680 | + rc &= tls_mbedtls_set_item(&tls_conf->check_cert_subject, |
| 5681 | + params->check_cert_subject); |
| 5682 | + return rc; |
| 5683 | +} |
| 5684 | + |
| 5685 | + |
| 5686 | +/* duplicated in crypto_mbedtls.c:crypto_mbedtls_readfile()*/ |
| 5687 | +__attribute_noinline__ |
| 5688 | +static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n) |
| 5689 | +{ |
| 5690 | + #if 0 /* #ifdef MBEDTLS_FS_IO */ |
| 5691 | + /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/ |
| 5692 | + if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) { |
| 5693 | + wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path); |
| 5694 | + return -1; |
| 5695 | + } |
| 5696 | + #else |
| 5697 | + /*(use os_readfile() so that we can use os_free() |
| 5698 | + *(if we use mbedtls_pk_load_file() above, macros prevent calling free() |
| 5699 | + * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free() |
| 5700 | + * on buf aborts in tests if buf not allocated via os_malloc())*/ |
| 5701 | + *buf = (u8 *)os_readfile(path, n); |
| 5702 | + if (!*buf) { |
| 5703 | + wpa_printf(MSG_ERROR, "error: os_readfile %s", path); |
| 5704 | + return -1; |
| 5705 | + } |
| 5706 | + u8 *buf0 = os_realloc(*buf, *n+1); |
| 5707 | + if (!buf0) { |
| 5708 | + bin_clear_free(*buf, *n); |
| 5709 | + *buf = NULL; |
| 5710 | + return -1; |
| 5711 | + } |
| 5712 | + buf0[(*n)++] = '\0'; |
| 5713 | + *buf = buf0; |
| 5714 | + #endif |
| 5715 | + return 0; |
| 5716 | +} |
| 5717 | + |
| 5718 | + |
| 5719 | +static int tls_mbedtls_set_crl(struct tls_conf *tls_conf, const u8 *data, size_t len) |
| 5720 | +{ |
| 5721 | + /* do not use mbedtls_x509_crl_parse() on PEM unless it contains CRL */ |
| 5722 | + if (len && data[len-1] == '\0' |
| 5723 | + && NULL == os_strstr((const char *)data,"-----BEGIN X509 CRL-----") |
| 5724 | + && tls_mbedtls_data_is_pem(data)) |
| 5725 | + return 0; |
| 5726 | + |
| 5727 | + mbedtls_x509_crl crl; |
| 5728 | + mbedtls_x509_crl_init(&crl); |
| 5729 | + int rc = mbedtls_x509_crl_parse(&crl, data, len); |
| 5730 | + if (rc < 0) { |
| 5731 | + mbedtls_x509_crl_free(&crl); |
| 5732 | + return rc == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ? 0 : rc; |
| 5733 | + } |
| 5734 | + |
| 5735 | + mbedtls_x509_crl *crl_new = os_malloc(sizeof(crl)); |
| 5736 | + if (crl_new == NULL) { |
| 5737 | + mbedtls_x509_crl_free(&crl); |
| 5738 | + return MBEDTLS_ERR_X509_ALLOC_FAILED; |
| 5739 | + } |
| 5740 | + os_memcpy(crl_new, &crl, sizeof(crl)); |
| 5741 | + |
| 5742 | + mbedtls_x509_crl *crl_old = tls_conf->crl; |
| 5743 | + tls_conf->crl = crl_new; |
| 5744 | + if (crl_old) { |
| 5745 | + mbedtls_x509_crl_free(crl_old); |
| 5746 | + os_free(crl_old); |
| 5747 | + } |
| 5748 | + return 0; |
| 5749 | +} |
| 5750 | + |
| 5751 | + |
| 5752 | +static int tls_mbedtls_set_ca(struct tls_conf *tls_conf, u8 *data, size_t len) |
| 5753 | +{ |
| 5754 | + /* load crt struct onto stack and then copy into tls_conf in |
| 5755 | + * order to preserve existing tls_conf value if error occurs |
| 5756 | + * |
| 5757 | + * hostapd is not threaded, or else should allocate memory and swap in |
| 5758 | + * pointer reduce race condition. (If threaded, would also need to |
| 5759 | + * keep reference count of use to avoid freeing while still in use.) */ |
| 5760 | + |
| 5761 | + mbedtls_x509_crt crt; |
| 5762 | + mbedtls_x509_crt_init(&crt); |
| 5763 | + int rc = mbedtls_x509_crt_parse(&crt, data, len); |
| 5764 | + if (rc < 0) { |
| 5765 | + mbedtls_x509_crt_free(&crt); |
| 5766 | + return rc; |
| 5767 | + } |
| 5768 | + |
| 5769 | + mbedtls_x509_crt_free(&tls_conf->ca_cert); |
| 5770 | + os_memcpy(&tls_conf->ca_cert, &crt, sizeof(crt)); |
| 5771 | + return 0; |
| 5772 | +} |
| 5773 | + |
| 5774 | + |
| 5775 | +static int tls_mbedtls_set_ca_and_crl(struct tls_conf *tls_conf, const char *ca_cert_file) |
| 5776 | +{ |
| 5777 | + size_t len; |
| 5778 | + u8 *data; |
| 5779 | + if (tls_mbedtls_readfile(ca_cert_file, &data, &len)) |
| 5780 | + return -1; |
| 5781 | + |
| 5782 | + int rc; |
| 5783 | + if (0 == (rc = tls_mbedtls_set_ca(tls_conf, data, len)) |
| 5784 | + && (!tls_mbedtls_data_is_pem(data) /*skip parse for CRL if not PEM*/ |
| 5785 | + || 0 == (rc = tls_mbedtls_set_crl(tls_conf, data, len)))) { |
| 5786 | + mbedtls_ssl_conf_ca_chain(&tls_conf->conf, |
| 5787 | + &tls_conf->ca_cert, |
| 5788 | + tls_conf->crl); |
| 5789 | + } |
| 5790 | + else { |
| 5791 | + elog(rc, __func__); |
| 5792 | + emsg(MSG_ERROR, ca_cert_file); |
| 5793 | + } |
| 5794 | + |
| 5795 | + forced_memzero(data, len); |
| 5796 | + os_free(data); |
| 5797 | + return rc; |
| 5798 | +} |
| 5799 | + |
| 5800 | + |
| 5801 | +static void tls_mbedtls_refresh_crl(void) |
| 5802 | +{ |
| 5803 | + /* check for CRL refresh |
| 5804 | + * continue even if error occurs; continue with previous cert, CRL */ |
| 5805 | + unsigned int crl_reload_interval = tls_ctx_global.crl_reload_interval; |
| 5806 | + const char *ca_cert_file = tls_ctx_global.ca_cert_file; |
| 5807 | + if (!crl_reload_interval || !ca_cert_file) |
| 5808 | + return; |
| 5809 | + |
| 5810 | + struct os_reltime *previous = &tls_ctx_global.crl_reload_previous; |
| 5811 | + struct os_reltime now; |
| 5812 | + if (os_get_reltime(&now) != 0 |
| 5813 | + || !os_reltime_expired(&now, previous, crl_reload_interval)) |
| 5814 | + return; |
| 5815 | + |
| 5816 | + /* Note: modifying global state is not thread-safe |
| 5817 | + * if in use by existing connections |
| 5818 | + * |
| 5819 | + * src/utils/os.h does not provide a portable stat() |
| 5820 | + * or else it would be a good idea to check mtime and size, |
| 5821 | + * and avoid reloading if file has not changed */ |
| 5822 | + |
| 5823 | + if (tls_mbedtls_set_ca_and_crl(tls_ctx_global.tls_conf, ca_cert_file) == 0) |
| 5824 | + *previous = now; |
| 5825 | +} |
| 5826 | + |
| 5827 | + |
| 5828 | +static int tls_mbedtls_set_ca_cert(struct tls_conf *tls_conf, |
| 5829 | + const struct tls_connection_params *params) |
| 5830 | +{ |
| 5831 | + if (params->ca_cert) { |
| 5832 | + if (os_strncmp(params->ca_cert, "probe://", 8) == 0) { |
| 5833 | + tls_conf->ca_cert_probe = 1; |
| 5834 | + tls_conf->has_ca_cert = 1; |
| 5835 | + return 0; |
| 5836 | + } |
| 5837 | + |
| 5838 | + if (os_strncmp(params->ca_cert, "hash://", 7) == 0) { |
| 5839 | + const char *pos = params->ca_cert + 7; |
| 5840 | + if (os_strncmp(pos, "server/sha256/", 14) != 0) { |
| 5841 | + emsg(MSG_ERROR, "unsupported ca_cert hash value"); |
| 5842 | + return -1; |
| 5843 | + } |
| 5844 | + pos += 14; |
| 5845 | + if (os_strlen(pos) != SHA256_DIGEST_LENGTH*2) { |
| 5846 | + emsg(MSG_ERROR, "unexpected ca_cert hash length"); |
| 5847 | + return -1; |
| 5848 | + } |
| 5849 | + if (hexstr2bin(pos, tls_conf->ca_cert_hash, |
| 5850 | + SHA256_DIGEST_LENGTH) < 0) { |
| 5851 | + emsg(MSG_ERROR, "invalid ca_cert hash value"); |
| 5852 | + return -1; |
| 5853 | + } |
| 5854 | + emsg(MSG_DEBUG, "checking only server certificate match"); |
| 5855 | + tls_conf->verify_depth0_only = 1; |
| 5856 | + tls_conf->has_ca_cert = 1; |
| 5857 | + return 0; |
| 5858 | + } |
| 5859 | + |
| 5860 | + if (tls_mbedtls_set_ca_and_crl(tls_conf, params->ca_cert) != 0) |
| 5861 | + return -1; |
| 5862 | + } |
| 5863 | + if (params->ca_cert_blob) { |
| 5864 | + size_t len = params->ca_cert_blob_len; |
| 5865 | + int is_pem = tls_mbedtls_data_is_pem(params->ca_cert_blob); |
| 5866 | + if (len && params->ca_cert_blob[len-1] != '\0' && is_pem) |
| 5867 | + ++len; /*(include '\0' in len for PEM)*/ |
| 5868 | + int ret = mbedtls_x509_crt_parse(&tls_conf->ca_cert, |
| 5869 | + params->ca_cert_blob, len); |
| 5870 | + if (ret != 0) { |
| 5871 | + elog(ret, "mbedtls_x509_crt_parse"); |
| 5872 | + return -1; |
| 5873 | + } |
| 5874 | + if (is_pem) { /*(ca_cert_blob in DER format contains ca cert only)*/ |
| 5875 | + ret = tls_mbedtls_set_crl(tls_conf, params->ca_cert_blob, len); |
| 5876 | + if (ret != 0) { |
| 5877 | + elog(ret, "mbedtls_x509_crl_parse"); |
| 5878 | + return -1; |
| 5879 | + } |
| 5880 | + } |
| 5881 | + } |
| 5882 | + |
| 5883 | + if (mbedtls_x509_time_is_future(&tls_conf->ca_cert.valid_from) |
| 5884 | + || mbedtls_x509_time_is_past(&tls_conf->ca_cert.valid_to)) { |
| 5885 | + emsg(MSG_WARNING, "ca_cert expired or not yet valid"); |
| 5886 | + if (params->ca_cert) |
| 5887 | + emsg(MSG_WARNING, params->ca_cert); |
| 5888 | + } |
| 5889 | + |
| 5890 | + tls_conf->has_ca_cert = 1; |
| 5891 | + return 0; |
| 5892 | +} |
| 5893 | + |
| 5894 | + |
| 5895 | +static int tls_mbedtls_set_certs(struct tls_conf *tls_conf, |
| 5896 | + const struct tls_connection_params *params) |
| 5897 | +{ |
| 5898 | + int ret; |
| 5899 | + |
| 5900 | + if (params->ca_cert || params->ca_cert_blob) { |
| 5901 | + if (tls_mbedtls_set_ca_cert(tls_conf, params) != 0) |
| 5902 | + return -1; |
| 5903 | + } |
| 5904 | + else if (params->ca_path) { |
| 5905 | + emsg(MSG_INFO, "ca_path support not implemented"); |
| 5906 | + return -1; |
| 5907 | + } |
| 5908 | + |
| 5909 | + if (!tls_conf->has_ca_cert) |
| 5910 | + mbedtls_ssl_conf_authmode(&tls_conf->conf, MBEDTLS_SSL_VERIFY_NONE); |
| 5911 | + else { |
| 5912 | + /* Initial setting: REQUIRED for client, OPTIONAL for server |
| 5913 | + * (see also tls_connection_set_verify()) */ |
| 5914 | + tls_conf->verify_peer = (tls_ctx_global.tls_conf == NULL); |
| 5915 | + int authmode = tls_conf->verify_peer |
| 5916 | + ? MBEDTLS_SSL_VERIFY_REQUIRED |
| 5917 | + : MBEDTLS_SSL_VERIFY_OPTIONAL; |
| 5918 | + mbedtls_ssl_conf_authmode(&tls_conf->conf, authmode); |
| 5919 | + mbedtls_ssl_conf_ca_chain(&tls_conf->conf, |
| 5920 | + &tls_conf->ca_cert, |
| 5921 | + tls_conf->crl); |
| 5922 | + |
| 5923 | + if (!tls_connection_set_subject_match(tls_conf, params)) |
| 5924 | + return -1; |
| 5925 | + } |
| 5926 | + |
| 5927 | + if (params->client_cert2) /*(yes, server_cert2 in msg below)*/ |
| 5928 | + emsg(MSG_INFO, "server_cert2 support not implemented"); |
| 5929 | + |
| 5930 | + if (params->client_cert) { |
| 5931 | + size_t len; |
| 5932 | + u8 *data; |
| 5933 | + if (tls_mbedtls_readfile(params->client_cert, &data, &len)) |
| 5934 | + return -1; |
| 5935 | + ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, data, len); |
| 5936 | + forced_memzero(data, len); |
| 5937 | + os_free(data); |
| 5938 | + } |
| 5939 | + if (params->client_cert_blob) { |
| 5940 | + size_t len = params->client_cert_blob_len; |
| 5941 | + if (len && params->client_cert_blob[len-1] != '\0' |
| 5942 | + && tls_mbedtls_data_is_pem(params->client_cert_blob)) |
| 5943 | + ++len; /*(include '\0' in len for PEM)*/ |
| 5944 | + ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, |
| 5945 | + params->client_cert_blob, len); |
| 5946 | + } |
| 5947 | + if (params->client_cert || params->client_cert_blob) { |
| 5948 | + if (ret < 0) { |
| 5949 | + elog(ret, "mbedtls_x509_crt_parse"); |
| 5950 | + if (params->client_cert) |
| 5951 | + emsg(MSG_ERROR, params->client_cert); |
| 5952 | + return -1; |
| 5953 | + } |
| 5954 | + if (mbedtls_x509_time_is_future(&tls_conf->client_cert.valid_from) |
| 5955 | + || mbedtls_x509_time_is_past(&tls_conf->client_cert.valid_to)) { |
| 5956 | + emsg(MSG_WARNING, "cert expired or not yet valid"); |
| 5957 | + if (params->client_cert) |
| 5958 | + emsg(MSG_WARNING, params->client_cert); |
| 5959 | + } |
| 5960 | + tls_conf->has_client_cert = 1; |
| 5961 | + } |
| 5962 | + |
| 5963 | + if (params->private_key || params->private_key_blob) { |
| 5964 | + size_t len = params->private_key_blob_len; |
| 5965 | + u8 *data; |
| 5966 | + *(const u8 **)&data = params->private_key_blob; |
| 5967 | + if (len && data[len-1] != '\0' && tls_mbedtls_data_is_pem(data)) |
| 5968 | + ++len; /*(include '\0' in len for PEM)*/ |
| 5969 | + if (params->private_key |
| 5970 | + && tls_mbedtls_readfile(params->private_key, &data, &len)) { |
| 5971 | + return -1; |
| 5972 | + } |
| 5973 | + const char *pwd = params->private_key_passwd; |
| 5974 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 5975 | + ret = mbedtls_pk_parse_key(&tls_conf->private_key, |
| 5976 | + data, len, |
| 5977 | + (const unsigned char *)pwd, |
| 5978 | + pwd ? os_strlen(pwd) : 0, |
| 5979 | + mbedtls_ctr_drbg_random, |
| 5980 | + tls_ctx_global.ctr_drbg); |
| 5981 | + #else |
| 5982 | + ret = mbedtls_pk_parse_key(&tls_conf->private_key, |
| 5983 | + data, len, |
| 5984 | + (const unsigned char *)pwd, |
| 5985 | + pwd ? os_strlen(pwd) : 0); |
| 5986 | + #endif |
| 5987 | + if (params->private_key) { |
| 5988 | + forced_memzero(data, len); |
| 5989 | + os_free(data); |
| 5990 | + } |
| 5991 | + if (ret < 0) { |
| 5992 | + elog(ret, "mbedtls_pk_parse_key"); |
| 5993 | + return -1; |
| 5994 | + } |
| 5995 | + tls_conf->has_private_key = 1; |
| 5996 | + } |
| 5997 | + |
| 5998 | + if (tls_conf->has_client_cert && tls_conf->has_private_key) { |
| 5999 | + ret = mbedtls_ssl_conf_own_cert( |
| 6000 | + &tls_conf->conf, &tls_conf->client_cert, &tls_conf->private_key); |
| 6001 | + if (ret < 0) { |
| 6002 | + elog(ret, "mbedtls_ssl_conf_own_cert"); |
| 6003 | + return -1; |
| 6004 | + } |
| 6005 | + } |
| 6006 | + |
| 6007 | + return 0; |
| 6008 | +} |
| 6009 | + |
| 6010 | + |
| 6011 | +/* mbedtls_x509_crt_profile_suiteb plus rsa_min_bitlen 2048 */ |
| 6012 | +/* (reference: see also mbedtls_x509_crt_profile_next) */ |
| 6013 | +/* ??? should permit SHA-512, too, and additional curves ??? */ |
| 6014 | +static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb128 = |
| 6015 | +{ |
| 6016 | + /* Only SHA-256 and 384 */ |
| 6017 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | |
| 6018 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), |
| 6019 | + /* Only ECDSA */ |
| 6020 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | |
| 6021 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), |
| 6022 | +#if defined(MBEDTLS_ECP_C) |
| 6023 | + /* Only NIST P-256 and P-384 */ |
| 6024 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | |
| 6025 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), |
| 6026 | +#else |
| 6027 | + 0, |
| 6028 | +#endif |
| 6029 | + 2048, |
| 6030 | +}; |
| 6031 | + |
| 6032 | + |
| 6033 | +/* stricter than mbedtls_x509_crt_profile_suiteb */ |
| 6034 | +/* (reference: see also mbedtls_x509_crt_profile_next) */ |
| 6035 | +/* ??? should permit SHA-512, too, and additional curves ??? */ |
| 6036 | +static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192 = |
| 6037 | +{ |
| 6038 | + /* Only SHA-384 */ |
| 6039 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), |
| 6040 | + /* Only ECDSA */ |
| 6041 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | |
| 6042 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), |
| 6043 | +#if defined(MBEDTLS_ECP_C) |
| 6044 | + /* Only NIST P-384 */ |
| 6045 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), |
| 6046 | +#else |
| 6047 | + 0, |
| 6048 | +#endif |
| 6049 | + 3072, |
| 6050 | +}; |
| 6051 | + |
| 6052 | + |
| 6053 | +/* stricter than mbedtls_x509_crt_profile_suiteb except allow any PK alg */ |
| 6054 | +/* (reference: see also mbedtls_x509_crt_profile_next) */ |
| 6055 | +/* ??? should permit SHA-512, too, and additional curves ??? */ |
| 6056 | +static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192_anypk = |
| 6057 | +{ |
| 6058 | + /* Only SHA-384 */ |
| 6059 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), |
| 6060 | + 0xFFFFFFF, /* Any PK alg */ |
| 6061 | +#if defined(MBEDTLS_ECP_C) |
| 6062 | + /* Only NIST P-384 */ |
| 6063 | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), |
| 6064 | +#else |
| 6065 | + 0, |
| 6066 | +#endif |
| 6067 | + 3072, |
| 6068 | +}; |
| 6069 | + |
| 6070 | + |
| 6071 | +static int tls_mbedtls_set_params(struct tls_conf *tls_conf, |
| 6072 | + const struct tls_connection_params *params) |
| 6073 | +{ |
| 6074 | + tls_conf->flags = params->flags; |
| 6075 | + |
| 6076 | + if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP_ALL) { |
| 6077 | + emsg(MSG_INFO, "ocsp=3 not supported"); |
| 6078 | + return -1; |
| 6079 | + } |
| 6080 | + |
| 6081 | + if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP) { |
| 6082 | + emsg(MSG_INFO, "ocsp not supported"); |
| 6083 | + return -1; |
| 6084 | + } |
| 6085 | + |
| 6086 | + int suiteb128 = 0; |
| 6087 | + int suiteb192 = 0; |
| 6088 | + if (params->openssl_ciphers) { |
| 6089 | + if (os_strcmp(params->openssl_ciphers, "SUITEB192") == 0) { |
| 6090 | + suiteb192 = 1; |
| 6091 | + tls_conf->flags |= TLS_CONN_SUITEB; |
| 6092 | + } |
| 6093 | + if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) { |
| 6094 | + suiteb128 = 1; |
| 6095 | + tls_conf->flags |= TLS_CONN_SUITEB; |
| 6096 | + } |
| 6097 | + } |
| 6098 | + |
| 6099 | + int ret = mbedtls_ssl_config_defaults( |
| 6100 | + &tls_conf->conf, tls_ctx_global.tls_conf ? MBEDTLS_SSL_IS_SERVER |
| 6101 | + : MBEDTLS_SSL_IS_CLIENT, |
| 6102 | + MBEDTLS_SSL_TRANSPORT_STREAM, |
| 6103 | + (tls_conf->flags & TLS_CONN_SUITEB) ? MBEDTLS_SSL_PRESET_SUITEB |
| 6104 | + : MBEDTLS_SSL_PRESET_DEFAULT); |
| 6105 | + if (ret != 0) { |
| 6106 | + elog(ret, "mbedtls_ssl_config_defaults"); |
| 6107 | + return -1; |
| 6108 | + } |
| 6109 | + |
| 6110 | + if (suiteb128) { |
| 6111 | + mbedtls_ssl_conf_cert_profile(&tls_conf->conf, |
| 6112 | + &tls_mbedtls_crt_profile_suiteb128); |
| 6113 | + mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 2048); |
| 6114 | + } |
| 6115 | + else if (suiteb192) { |
| 6116 | + mbedtls_ssl_conf_cert_profile(&tls_conf->conf, |
| 6117 | + &tls_mbedtls_crt_profile_suiteb192); |
| 6118 | + mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072); |
| 6119 | + } |
| 6120 | + else if (tls_conf->flags & TLS_CONN_SUITEB) { |
| 6121 | + /* treat as suiteb192 while allowing any PK algorithm */ |
| 6122 | + mbedtls_ssl_conf_cert_profile(&tls_conf->conf, |
| 6123 | + &tls_mbedtls_crt_profile_suiteb192_anypk); |
| 6124 | + mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072); |
| 6125 | + } |
| 6126 | + |
| 6127 | + tls_mbedtls_set_allowed_tls_vers(tls_conf, &tls_conf->conf); |
| 6128 | + ret = tls_mbedtls_set_certs(tls_conf, params); |
| 6129 | + if (ret != 0) |
| 6130 | + return -1; |
| 6131 | + |
| 6132 | + if (params->dh_file |
| 6133 | + && !tls_mbedtls_set_dhparams(tls_conf, params->dh_file)) { |
| 6134 | + return -1; |
| 6135 | + } |
| 6136 | + |
| 6137 | + if (params->openssl_ecdh_curves |
| 6138 | + && !tls_mbedtls_set_curves(tls_conf, params->openssl_ecdh_curves)) { |
| 6139 | + return -1; |
| 6140 | + } |
| 6141 | + |
| 6142 | + if (params->openssl_ciphers) { |
| 6143 | + if (!tls_mbedtls_set_ciphers(tls_conf, params->openssl_ciphers)) |
| 6144 | + return -1; |
| 6145 | + } |
| 6146 | + else if (tls_conf->flags & TLS_CONN_SUITEB) { |
| 6147 | + /* special-case a select set of ciphers for hwsim tests */ |
| 6148 | + if (!tls_mbedtls_set_ciphers(tls_conf, |
| 6149 | + (tls_conf->flags & TLS_CONN_SUITEB_NO_ECDH) |
| 6150 | + ? "DHE-RSA-AES256-GCM-SHA384" |
| 6151 | + : "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384")) |
| 6152 | + return -1; |
| 6153 | + } |
| 6154 | + |
| 6155 | + return 0; |
| 6156 | +} |
| 6157 | + |
| 6158 | + |
| 6159 | +int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, |
| 6160 | + const struct tls_connection_params *params) |
| 6161 | +{ |
| 6162 | + if (conn == NULL || params == NULL) |
| 6163 | + return -1; |
| 6164 | + |
| 6165 | + tls_conf_deinit(conn->tls_conf); |
| 6166 | + struct tls_conf *tls_conf = conn->tls_conf = tls_conf_init(tls_ctx); |
| 6167 | + if (tls_conf == NULL) |
| 6168 | + return -1; |
| 6169 | + |
| 6170 | + if (tls_ctx_global.tls_conf) { |
| 6171 | + tls_conf->check_crl = tls_ctx_global.tls_conf->check_crl; |
| 6172 | + tls_conf->check_crl_strict = tls_ctx_global.tls_conf->check_crl_strict; |
| 6173 | + /*(tls_openssl.c inherits check_cert_subject from global conf)*/ |
| 6174 | + if (tls_ctx_global.tls_conf->check_cert_subject) { |
| 6175 | + tls_conf->check_cert_subject = |
| 6176 | + os_strdup(tls_ctx_global.tls_conf->check_cert_subject); |
| 6177 | + if (tls_conf->check_cert_subject == NULL) |
| 6178 | + return -1; |
| 6179 | + } |
| 6180 | + } |
| 6181 | + |
| 6182 | + if (tls_mbedtls_set_params(tls_conf, params) != 0) |
| 6183 | + return -1; |
| 6184 | + conn->verify_peer = tls_conf->verify_peer; |
| 6185 | + |
| 6186 | + return tls_mbedtls_ssl_setup(conn); |
| 6187 | +} |
| 6188 | + |
| 6189 | + |
| 6190 | +#ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 6191 | + |
| 6192 | +static int tls_mbedtls_clienthello_session_ticket_prep (struct tls_connection *conn, |
| 6193 | + const u8 *data, size_t len) |
| 6194 | +{ |
| 6195 | + if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET) |
| 6196 | + return -1; |
| 6197 | + if (conn->clienthello_session_ticket) |
| 6198 | + tls_connection_deinit_clienthello_session_ticket(conn); |
| 6199 | + if (len) { |
| 6200 | + conn->clienthello_session_ticket = mbedtls_calloc(1, len); |
| 6201 | + if (conn->clienthello_session_ticket == NULL) |
| 6202 | + return -1; |
| 6203 | + conn->clienthello_session_ticket_len = len; |
| 6204 | + os_memcpy(conn->clienthello_session_ticket, data, len); |
| 6205 | + } |
| 6206 | + return 0; |
| 6207 | +} |
| 6208 | + |
| 6209 | + |
| 6210 | +static void tls_mbedtls_clienthello_session_ticket_set (struct tls_connection *conn) |
| 6211 | +{ |
| 6212 | + mbedtls_ssl_session *sess = conn->ssl.MBEDTLS_PRIVATE(session_negotiate); |
| 6213 | + if (sess->MBEDTLS_PRIVATE(ticket)) { |
| 6214 | + mbedtls_platform_zeroize(sess->MBEDTLS_PRIVATE(ticket), |
| 6215 | + sess->MBEDTLS_PRIVATE(ticket_len)); |
| 6216 | + mbedtls_free(sess->MBEDTLS_PRIVATE(ticket)); |
| 6217 | + } |
| 6218 | + sess->MBEDTLS_PRIVATE(ticket) = conn->clienthello_session_ticket; |
| 6219 | + sess->MBEDTLS_PRIVATE(ticket_len) = conn->clienthello_session_ticket_len; |
| 6220 | + sess->MBEDTLS_PRIVATE(ticket_lifetime) = 86400;/* XXX: can hint be 0? */ |
| 6221 | + |
| 6222 | + conn->clienthello_session_ticket = NULL; |
| 6223 | + conn->clienthello_session_ticket_len = 0; |
| 6224 | +} |
| 6225 | + |
| 6226 | + |
| 6227 | +static int tls_mbedtls_ssl_ticket_write(void *p_ticket, |
| 6228 | + const mbedtls_ssl_session *session, |
| 6229 | + unsigned char *start, |
| 6230 | + const unsigned char *end, |
| 6231 | + size_t *tlen, |
| 6232 | + uint32_t *lifetime) |
| 6233 | +{ |
| 6234 | + struct tls_connection *conn = p_ticket; |
| 6235 | + if (conn && conn->session_ticket_cb) { |
| 6236 | + /* see tls_mbedtls_clienthello_session_ticket_prep() */ |
| 6237 | + /* see tls_mbedtls_clienthello_session_ticket_set() */ |
| 6238 | + return 0; |
| 6239 | + } |
| 6240 | + |
| 6241 | + return mbedtls_ssl_ticket_write(&tls_ctx_global.ticket_ctx, |
| 6242 | + session, start, end, tlen, lifetime); |
| 6243 | +} |
| 6244 | + |
| 6245 | + |
| 6246 | +static int tls_mbedtls_ssl_ticket_parse(void *p_ticket, |
| 6247 | + mbedtls_ssl_session *session, |
| 6248 | + unsigned char *buf, |
| 6249 | + size_t len) |
| 6250 | +{ |
| 6251 | + /* XXX: TODO: not implemented in client; |
| 6252 | + * mbedtls_ssl_conf_session_tickets_cb() callbacks only for TLS server*/ |
| 6253 | + |
| 6254 | + if (len == 0) |
| 6255 | + return MBEDTLS_ERR_SSL_BAD_INPUT_DATA; |
| 6256 | + |
| 6257 | + struct tls_connection *conn = p_ticket; |
| 6258 | + if (conn && conn->session_ticket_cb) { |
| 6259 | + /* XXX: have random and secret been initialized yet? |
| 6260 | + * or must keys first be exported? |
| 6261 | + * EAP-FAST uses all args, EAP-TEAP only uses secret */ |
| 6262 | + struct tls_random data; |
| 6263 | + if (tls_connection_get_random(NULL, conn, &data) != 0) |
| 6264 | + return MBEDTLS_ERR_SSL_INTERNAL_ERROR; |
| 6265 | + int ret = |
| 6266 | + conn->session_ticket_cb(conn->session_ticket_cb_ctx, |
| 6267 | + buf, len, |
| 6268 | + data.client_random, |
| 6269 | + data.server_random, |
| 6270 | + conn->expkey_secret); |
| 6271 | + if (ret == 1) { |
| 6272 | + conn->resumed = 1; |
| 6273 | + return 0; |
| 6274 | + } |
| 6275 | + emsg(MSG_ERROR, "EAP session ticket ext not implemented"); |
| 6276 | + return MBEDTLS_ERR_SSL_INVALID_MAC; |
| 6277 | + /*(non-zero return used for mbedtls debug logging)*/ |
| 6278 | + } |
| 6279 | + |
| 6280 | + /* XXX: TODO always use tls_mbedtls_ssl_ticket_parse() for callback? */ |
| 6281 | + int rc = mbedtls_ssl_ticket_parse(&tls_ctx_global.ticket_ctx, |
| 6282 | + session, buf, len); |
| 6283 | + if (conn) |
| 6284 | + conn->resumed = (rc == 0); |
| 6285 | + return rc; |
| 6286 | +} |
| 6287 | + |
| 6288 | +#endif /* TLS_MBEDTLS_SESSION_TICKETS */ |
| 6289 | + |
| 6290 | + |
| 6291 | +__attribute_cold__ |
| 6292 | +int tls_global_set_params(void *tls_ctx, |
| 6293 | + const struct tls_connection_params *params) |
| 6294 | +{ |
| 6295 | + /* XXX: why might global_set_params be called more than once? */ |
| 6296 | + if (tls_ctx_global.tls_conf) |
| 6297 | + tls_conf_deinit(tls_ctx_global.tls_conf); |
| 6298 | + tls_ctx_global.tls_conf = tls_conf_init(tls_ctx); |
| 6299 | + if (tls_ctx_global.tls_conf == NULL) |
| 6300 | + return -1; |
| 6301 | + |
| 6302 | + #ifdef MBEDTLS_SSL_SESSION_TICKETS |
| 6303 | + #ifdef MBEDTLS_SSL_TICKET_C |
| 6304 | + if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET)) |
| 6305 | + #ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 6306 | + mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf, |
| 6307 | + tls_mbedtls_ssl_ticket_write, |
| 6308 | + tls_mbedtls_ssl_ticket_parse, |
| 6309 | + NULL); |
| 6310 | + #else |
| 6311 | + mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf, |
| 6312 | + mbedtls_ssl_ticket_write, |
| 6313 | + mbedtls_ssl_ticket_parse, |
| 6314 | + &tls_ctx_global.ticket_ctx); |
| 6315 | + #endif |
| 6316 | + #endif |
| 6317 | + #endif |
| 6318 | + |
| 6319 | + os_free(tls_ctx_global.ocsp_stapling_response); |
| 6320 | + tls_ctx_global.ocsp_stapling_response = NULL; |
| 6321 | + if (params->ocsp_stapling_response) |
| 6322 | + tls_ctx_global.ocsp_stapling_response = |
| 6323 | + os_strdup(params->ocsp_stapling_response); |
| 6324 | + |
| 6325 | + os_free(tls_ctx_global.ca_cert_file); |
| 6326 | + tls_ctx_global.ca_cert_file = NULL; |
| 6327 | + if (params->ca_cert) |
| 6328 | + tls_ctx_global.ca_cert_file = os_strdup(params->ca_cert); |
| 6329 | + return tls_mbedtls_set_params(tls_ctx_global.tls_conf, params); |
| 6330 | +} |
| 6331 | + |
| 6332 | + |
| 6333 | +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) |
| 6334 | +{ |
| 6335 | + tls_ctx_global.tls_conf->check_crl = check_crl; |
| 6336 | + tls_ctx_global.tls_conf->check_crl_strict = strict; /*(time checks)*/ |
| 6337 | + return 0; |
| 6338 | +} |
| 6339 | + |
| 6340 | + |
| 6341 | +int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, |
| 6342 | + int verify_peer, unsigned int flags, |
| 6343 | + const u8 *session_ctx, size_t session_ctx_len) |
| 6344 | +{ |
| 6345 | + /*(EAP server-side calls this from eap_server_tls_ssl_init())*/ |
| 6346 | + if (conn == NULL) |
| 6347 | + return -1; |
| 6348 | + |
| 6349 | + conn->tls_conf->flags |= flags;/* TODO: reprocess flags, if necessary */ |
| 6350 | + |
| 6351 | + int authmode; |
| 6352 | + switch (verify_peer) { |
| 6353 | + case 2: authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; break;/*(eap_teap_init())*/ |
| 6354 | + case 1: authmode = MBEDTLS_SSL_VERIFY_REQUIRED; break; |
| 6355 | + default: authmode = MBEDTLS_SSL_VERIFY_NONE; break; |
| 6356 | + } |
| 6357 | + mbedtls_ssl_set_hs_authmode(&conn->ssl, authmode); |
| 6358 | + |
| 6359 | + if ((conn->verify_peer = (authmode != MBEDTLS_SSL_VERIFY_NONE))) |
| 6360 | + mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn); |
| 6361 | + else |
| 6362 | + mbedtls_ssl_set_verify(&conn->ssl, NULL, NULL); |
| 6363 | + |
| 6364 | + return 0; |
| 6365 | +} |
| 6366 | + |
| 6367 | + |
| 6368 | +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 6369 | +static void tls_connection_export_keys_cb( |
| 6370 | + void *p_expkey, mbedtls_ssl_key_export_type secret_type, |
| 6371 | + const unsigned char *secret, size_t secret_len, |
| 6372 | + const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN], |
| 6373 | + const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN], |
| 6374 | + mbedtls_tls_prf_types tls_prf_type) |
| 6375 | +{ |
| 6376 | + struct tls_connection *conn = p_expkey; |
| 6377 | + conn->tls_prf_type = tls_prf_type; |
| 6378 | + if (!tls_prf_type) |
| 6379 | + return; |
| 6380 | + if (secret_len > sizeof(conn->expkey_secret)) { |
| 6381 | + emsg(MSG_ERROR, "tls_connection_export_keys_cb secret too long"); |
| 6382 | + conn->tls_prf_type = MBEDTLS_SSL_TLS_PRF_NONE; /* 0 */ |
| 6383 | + return; |
| 6384 | + } |
| 6385 | + conn->expkey_secret_len = secret_len; |
| 6386 | + os_memcpy(conn->expkey_secret, secret, secret_len); |
| 6387 | + os_memcpy(conn->expkey_randbytes, |
| 6388 | + client_random, MBEDTLS_EXPKEY_RAND_LEN); |
| 6389 | + os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN, |
| 6390 | + server_random, MBEDTLS_EXPKEY_RAND_LEN); |
| 6391 | +} |
| 6392 | +#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 6393 | +static int tls_connection_export_keys_cb( |
| 6394 | + void *p_expkey, |
| 6395 | + const unsigned char *ms, |
| 6396 | + const unsigned char *kb, |
| 6397 | + size_t maclen, |
| 6398 | + size_t keylen, |
| 6399 | + size_t ivlen, |
| 6400 | + const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN], |
| 6401 | + const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN], |
| 6402 | + mbedtls_tls_prf_types tls_prf_type ) |
| 6403 | +{ |
| 6404 | + struct tls_connection *conn = p_expkey; |
| 6405 | + conn->tls_prf_type = tls_prf_type; |
| 6406 | + if (!tls_prf_type) |
| 6407 | + return -1; /*(return value ignored by mbedtls)*/ |
| 6408 | + conn->expkey_keyblock_size = maclen + keylen + ivlen; |
| 6409 | + conn->expkey_secret_len = MBEDTLS_EXPKEY_FIXED_SECRET_LEN; |
| 6410 | + os_memcpy(conn->expkey_secret, ms, MBEDTLS_EXPKEY_FIXED_SECRET_LEN); |
| 6411 | + os_memcpy(conn->expkey_randbytes, |
| 6412 | + client_random, MBEDTLS_EXPKEY_RAND_LEN); |
| 6413 | + os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN, |
| 6414 | + server_random, MBEDTLS_EXPKEY_RAND_LEN); |
| 6415 | + return 0; |
| 6416 | +} |
| 6417 | +#endif |
| 6418 | + |
| 6419 | + |
| 6420 | +int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn, |
| 6421 | + struct tls_random *data) |
| 6422 | +{ |
| 6423 | + if (!conn || !conn->tls_prf_type) |
| 6424 | + return -1; |
| 6425 | + data->client_random = conn->expkey_randbytes; |
| 6426 | + data->client_random_len = MBEDTLS_EXPKEY_RAND_LEN; |
| 6427 | + data->server_random = conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN; |
| 6428 | + data->server_random_len = MBEDTLS_EXPKEY_RAND_LEN; |
| 6429 | + return 0; |
| 6430 | +} |
| 6431 | + |
| 6432 | + |
| 6433 | +int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn, |
| 6434 | + const char *label, const u8 *context, |
| 6435 | + size_t context_len, u8 *out, size_t out_len) |
| 6436 | +{ |
| 6437 | + /* (EAP-PEAP EAP-TLS EAP-TTLS) */ |
| 6438 | + #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 6439 | + return (conn && conn->established && conn->tls_prf_type) |
| 6440 | + ? mbedtls_ssl_tls_prf(conn->tls_prf_type, |
| 6441 | + conn->expkey_secret, conn->expkey_secret_len, label, |
| 6442 | + conn->expkey_randbytes, |
| 6443 | + sizeof(conn->expkey_randbytes), out, out_len) |
| 6444 | + : -1; |
| 6445 | + #else |
| 6446 | + /* not implemented here for mbedtls < 2.18.0 */ |
| 6447 | + return -1; |
| 6448 | + #endif |
| 6449 | +} |
| 6450 | + |
| 6451 | + |
| 6452 | +#ifdef TLS_MBEDTLS_EAP_FAST |
| 6453 | + |
| 6454 | +#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 6455 | +/* keyblock size info is not exposed in mbed TLS 3.0.0 */ |
| 6456 | +/* extracted from mbedtls library/ssl_tls.c:ssl_tls12_populate_transform() */ |
| 6457 | +#include <mbedtls/ssl_ciphersuites.h> |
| 6458 | +#include <mbedtls/cipher.h> |
| 6459 | +static size_t tls_mbedtls_ssl_keyblock_size (mbedtls_ssl_context *ssl) |
| 6460 | +{ |
| 6461 | + #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* XXX: (not extracted for PSA crypto) */ |
| 6462 | + #if defined(MBEDTLS_SSL_PROTO_TLS1_3) |
| 6463 | + if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) |
| 6464 | + return 0; /* (calculation not extracted) */ |
| 6465 | + #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ |
| 6466 | + |
| 6467 | + int ciphersuite = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl); |
| 6468 | + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = |
| 6469 | + mbedtls_ssl_ciphersuite_from_id(ciphersuite); |
| 6470 | + if (ciphersuite_info == NULL) |
| 6471 | + return 0; |
| 6472 | + |
| 6473 | + const mbedtls_cipher_info_t *cipher_info = |
| 6474 | + mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher)); |
| 6475 | + if (cipher_info == NULL) |
| 6476 | + return 0; |
| 6477 | + |
| 6478 | + #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */ |
| 6479 | + size_t keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8; |
| 6480 | + mbedtls_cipher_mode_t mode = mbedtls_cipher_info_get_mode(cipher_info); |
| 6481 | + #else |
| 6482 | + size_t keylen = cipher_info->MBEDTLS_PRIVATE(key_bitlen) / 8; |
| 6483 | + mbedtls_cipher_mode_t mode = cipher_info->MBEDTLS_PRIVATE(mode); |
| 6484 | + #endif |
| 6485 | + #if defined(MBEDTLS_GCM_C) || \ |
| 6486 | + defined(MBEDTLS_CCM_C) || \ |
| 6487 | + defined(MBEDTLS_CHACHAPOLY_C) |
| 6488 | + if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM) |
| 6489 | + return keylen + 4; |
| 6490 | + else if (mode == MBEDTLS_MODE_CHACHAPOLY) |
| 6491 | + return keylen + 12; |
| 6492 | + else |
| 6493 | + #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */ |
| 6494 | + #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) |
| 6495 | + { |
| 6496 | + const mbedtls_md_info_t *md_info = |
| 6497 | + mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac)); |
| 6498 | + if (md_info == NULL) |
| 6499 | + return 0; |
| 6500 | + size_t mac_key_len = mbedtls_md_get_size(md_info); |
| 6501 | + size_t ivlen = mbedtls_cipher_info_get_iv_size(cipher_info); |
| 6502 | + return keylen + mac_key_len + ivlen; |
| 6503 | + } |
| 6504 | + #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */ |
| 6505 | + #endif /* !MBEDTLS_USE_PSA_CRYPTO *//* (not extracted for PSA crypto) */ |
| 6506 | + return 0; |
| 6507 | +} |
| 6508 | +#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 *//* mbedtls 3.0.0 */ |
| 6509 | + |
| 6510 | + |
| 6511 | +int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn, |
| 6512 | + u8 *out, size_t out_len) |
| 6513 | +{ |
| 6514 | + /* XXX: has export keys callback been run? */ |
| 6515 | + if (!conn || !conn->tls_prf_type) |
| 6516 | + return -1; |
| 6517 | + |
| 6518 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 6519 | + conn->expkey_keyblock_size = tls_mbedtls_ssl_keyblock_size(&conn->ssl); |
| 6520 | + if (conn->expkey_keyblock_size == 0) |
| 6521 | + return -1; |
| 6522 | + #endif |
| 6523 | + size_t skip = conn->expkey_keyblock_size * 2; |
| 6524 | + unsigned char *tmp_out = os_malloc(skip + out_len); |
| 6525 | + if (!tmp_out) |
| 6526 | + return -1; |
| 6527 | + |
| 6528 | + /* server_random and then client_random */ |
| 6529 | + unsigned char seed[MBEDTLS_EXPKEY_RAND_LEN*2]; |
| 6530 | + os_memcpy(seed, conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN, |
| 6531 | + MBEDTLS_EXPKEY_RAND_LEN); |
| 6532 | + os_memcpy(seed + MBEDTLS_EXPKEY_RAND_LEN, conn->expkey_randbytes, |
| 6533 | + MBEDTLS_EXPKEY_RAND_LEN); |
| 6534 | + |
| 6535 | + #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 6536 | + int ret = mbedtls_ssl_tls_prf(conn->tls_prf_type, |
| 6537 | + conn->expkey_secret, conn->expkey_secret_len, |
| 6538 | + "key expansion", seed, sizeof(seed), |
| 6539 | + tmp_out, skip + out_len); |
| 6540 | + if (ret == 0) |
| 6541 | + os_memcpy(out, tmp_out + skip, out_len); |
| 6542 | + #else |
| 6543 | + int ret = -1; /*(not reached if not impl; return -1 at top of func)*/ |
| 6544 | + #endif |
| 6545 | + |
| 6546 | + bin_clear_free(tmp_out, skip + out_len); |
| 6547 | + forced_memzero(seed, sizeof(seed)); |
| 6548 | + return ret; |
| 6549 | +} |
| 6550 | + |
| 6551 | +#endif /* TLS_MBEDTLS_EAP_FAST */ |
| 6552 | + |
| 6553 | + |
| 6554 | +__attribute_cold__ |
| 6555 | +static void tls_mbedtls_suiteb_handshake_alert (struct tls_connection *conn) |
| 6556 | +{ |
| 6557 | + /* tests/hwsim/test_suite_b.py test_suite_b_192_rsa_insufficient_dh */ |
| 6558 | + if (!(conn->tls_conf->flags & TLS_CONN_SUITEB)) |
| 6559 | + return; |
| 6560 | + if (tls_ctx_global.tls_conf) /*(is server; want issue event on client)*/ |
| 6561 | + return; |
| 6562 | + #if 0 |
| 6563 | + /*(info not available on client; |
| 6564 | + * mbed TLS library enforces dhm min bitlen in ServerKeyExchange)*/ |
| 6565 | + if (MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 == |
| 6566 | + #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */ |
| 6567 | + mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl) |
| 6568 | + #else |
| 6569 | + mbedtls_ssl_get_ciphersuite_id( |
| 6570 | + mbedtls_ssl_get_ciphersuite(&conn->ssl)) |
| 6571 | + #endif |
| 6572 | + && mbedtls_mpi_size(&conn->tls_conf->conf.MBEDTLS_PRIVATE(dhm_P)) |
| 6573 | + < 384 /*(3072/8)*/) |
| 6574 | + #endif |
| 6575 | + { |
| 6576 | + struct tls_config *init_conf = &tls_ctx_global.init_conf; |
| 6577 | + if (init_conf->event_cb) { |
| 6578 | + union tls_event_data ev; |
| 6579 | + os_memset(&ev, 0, sizeof(ev)); |
| 6580 | + ev.alert.is_local = 1; |
| 6581 | + ev.alert.type = "fatal"; |
| 6582 | + /*"internal error" string for tests/hwsim/test_suiteb.py */ |
| 6583 | + ev.alert.description = "internal error: handshake failure"; |
| 6584 | + /*ev.alert.description = "insufficient security";*/ |
| 6585 | + init_conf->event_cb(init_conf->cb_ctx, TLS_ALERT, &ev); |
| 6586 | + } |
| 6587 | + } |
| 6588 | +} |
| 6589 | + |
| 6590 | + |
| 6591 | +struct wpabuf * tls_connection_handshake(void *tls_ctx, |
| 6592 | + struct tls_connection *conn, |
| 6593 | + const struct wpabuf *in_data, |
| 6594 | + struct wpabuf **appl_data) |
| 6595 | +{ |
| 6596 | + if (appl_data) |
| 6597 | + *appl_data = NULL; |
| 6598 | + |
| 6599 | + if (in_data && wpabuf_len(in_data)) { |
| 6600 | + /*(unsure why tls_gnutls.c discards buffer contents; skip here)*/ |
| 6601 | + if (conn->pull_buf && 0) /* disable; appears unwise */ |
| 6602 | + tls_pull_buf_discard(conn, __func__); |
| 6603 | + if (!tls_pull_buf_append(conn, in_data)) |
| 6604 | + return NULL; |
| 6605 | + } |
| 6606 | + |
| 6607 | + if (conn->tls_conf == NULL) { |
| 6608 | + struct tls_connection_params params; |
| 6609 | + os_memset(¶ms, 0, sizeof(params)); |
| 6610 | + params.openssl_ciphers = |
| 6611 | + tls_ctx_global.init_conf.openssl_ciphers; |
| 6612 | + params.flags = tls_ctx_global.tls_conf->flags; |
| 6613 | + if (tls_connection_set_params(tls_ctx, conn, ¶ms) != 0) |
| 6614 | + return NULL; |
| 6615 | + } |
| 6616 | + |
| 6617 | + if (conn->verify_peer) /*(call here might be redundant; nbd)*/ |
| 6618 | + mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn); |
| 6619 | + |
| 6620 | + #ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 6621 | + if (conn->clienthello_session_ticket) |
| 6622 | + /*(starting handshake for EAP-FAST and EAP-TEAP)*/ |
| 6623 | + tls_mbedtls_clienthello_session_ticket_set(conn); |
| 6624 | + |
| 6625 | + /* (not thread-safe due to need to set userdata 'conn' for callback) */ |
| 6626 | + /* (unable to use mbedtls_ssl_set_user_data_p() with mbedtls 3.2.0+ |
| 6627 | + * since ticket write and parse callbacks take (mbedtls_ssl_session *) |
| 6628 | + * param instead of (mbedtls_ssl_context *) param) */ |
| 6629 | + if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET) |
| 6630 | + mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf, |
| 6631 | + NULL, NULL, NULL); |
| 6632 | + else |
| 6633 | + mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf, |
| 6634 | + tls_mbedtls_ssl_ticket_write, |
| 6635 | + tls_mbedtls_ssl_ticket_parse, |
| 6636 | + conn); |
| 6637 | + #endif |
| 6638 | + |
| 6639 | + #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */ |
| 6640 | + int ret = mbedtls_ssl_handshake(&conn->ssl); |
| 6641 | + #else |
| 6642 | + int ret = 0; |
| 6643 | + while (conn->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { |
| 6644 | + ret = mbedtls_ssl_handshake_step(&conn->ssl); |
| 6645 | + if (ret != 0) |
| 6646 | + break; |
| 6647 | + } |
| 6648 | + #endif |
| 6649 | + |
| 6650 | + #ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 6651 | + mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf, |
| 6652 | + tls_mbedtls_ssl_ticket_write, |
| 6653 | + tls_mbedtls_ssl_ticket_parse, |
| 6654 | + NULL); |
| 6655 | + #endif |
| 6656 | + |
| 6657 | + switch (ret) { |
| 6658 | + case 0: |
| 6659 | + conn->established = 1; |
| 6660 | + if (conn->push_buf == NULL) |
| 6661 | + /* Need to return something to get final TLS ACK. */ |
| 6662 | + conn->push_buf = wpabuf_alloc(0); |
| 6663 | + |
| 6664 | + if (appl_data /*&& conn->pull_buf && wpabuf_len(conn->pull_buf)*/) |
| 6665 | + *appl_data = NULL; /* RFE: check for application data */ |
| 6666 | + break; |
| 6667 | + case MBEDTLS_ERR_SSL_WANT_WRITE: |
| 6668 | + case MBEDTLS_ERR_SSL_WANT_READ: |
| 6669 | + case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: |
| 6670 | + case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: |
| 6671 | + if (tls_ctx_global.tls_conf /*(is server)*/ |
| 6672 | + && conn->established && conn->push_buf == NULL) |
| 6673 | + /* Need to return something to trigger completion of EAP-TLS. */ |
| 6674 | + conn->push_buf = wpabuf_alloc(0); |
| 6675 | + break; |
| 6676 | + default: |
| 6677 | + ++conn->failed; |
| 6678 | + switch (ret) { |
| 6679 | + case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: |
| 6680 | + case MBEDTLS_ERR_NET_CONN_RESET: |
| 6681 | + case MBEDTLS_ERR_NET_SEND_FAILED: |
| 6682 | + ++conn->write_alerts; |
| 6683 | + break; |
| 6684 | + #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */ |
| 6685 | + case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE: |
| 6686 | + #else |
| 6687 | + case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE: |
| 6688 | + #endif |
| 6689 | + tls_mbedtls_suiteb_handshake_alert(conn); |
| 6690 | + /* fall through */ |
| 6691 | + case MBEDTLS_ERR_NET_RECV_FAILED: |
| 6692 | + case MBEDTLS_ERR_SSL_CONN_EOF: |
| 6693 | + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: |
| 6694 | + case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: |
| 6695 | + ++conn->read_alerts; |
| 6696 | + break; |
| 6697 | + default: |
| 6698 | + break; |
| 6699 | + } |
| 6700 | + |
| 6701 | + ilog(ret, "mbedtls_ssl_handshake"); |
| 6702 | + break; |
| 6703 | + } |
| 6704 | + |
| 6705 | + struct wpabuf *out_data = conn->push_buf; |
| 6706 | + conn->push_buf = NULL; |
| 6707 | + return out_data; |
| 6708 | +} |
| 6709 | + |
| 6710 | + |
| 6711 | +struct wpabuf * tls_connection_server_handshake(void *tls_ctx, |
| 6712 | + struct tls_connection *conn, |
| 6713 | + const struct wpabuf *in_data, |
| 6714 | + struct wpabuf **appl_data) |
| 6715 | +{ |
| 6716 | + conn->is_server = 1; |
| 6717 | + return tls_connection_handshake(tls_ctx, conn, in_data, appl_data); |
| 6718 | +} |
| 6719 | + |
| 6720 | + |
| 6721 | +struct wpabuf * tls_connection_encrypt(void *tls_ctx, |
| 6722 | + struct tls_connection *conn, |
| 6723 | + const struct wpabuf *in_data) |
| 6724 | +{ |
| 6725 | + int res = mbedtls_ssl_write(&conn->ssl, |
| 6726 | + wpabuf_head_u8(in_data), wpabuf_len(in_data)); |
| 6727 | + if (res < 0) { |
| 6728 | + elog(res, "mbedtls_ssl_write"); |
| 6729 | + return NULL; |
| 6730 | + } |
| 6731 | + |
| 6732 | + struct wpabuf *buf = conn->push_buf; |
| 6733 | + conn->push_buf = NULL; |
| 6734 | + return buf; |
| 6735 | +} |
| 6736 | + |
| 6737 | + |
| 6738 | +struct wpabuf * tls_connection_decrypt(void *tls_ctx, |
| 6739 | + struct tls_connection *conn, |
| 6740 | + const struct wpabuf *in_data) |
| 6741 | +{ |
| 6742 | + int res; |
| 6743 | + struct wpabuf *out; |
| 6744 | + |
| 6745 | + /*assert(in_data != NULL);*/ |
| 6746 | + if (!tls_pull_buf_append(conn, in_data)) |
| 6747 | + return NULL; |
| 6748 | + |
| 6749 | + #if defined(MBEDTLS_ZLIB_SUPPORT) /* removed in mbedtls 3.x */ |
| 6750 | + /* Add extra buffer space to handle the possibility of decrypted |
| 6751 | + * data being longer than input data due to TLS compression. */ |
| 6752 | + out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3); |
| 6753 | + #else /* TLS compression is disabled in mbedtls 3.x */ |
| 6754 | + out = wpabuf_alloc(wpabuf_len(in_data)); |
| 6755 | + #endif |
| 6756 | + if (out == NULL) |
| 6757 | + return NULL; |
| 6758 | + |
| 6759 | + res = mbedtls_ssl_read(&conn->ssl, wpabuf_mhead(out), wpabuf_size(out)); |
| 6760 | + if (res < 0) { |
| 6761 | + #if 1 /*(seems like a different error if wpabuf_len(in_data) == 0)*/ |
| 6762 | + if (res == MBEDTLS_ERR_SSL_WANT_READ) |
| 6763 | + return out; |
| 6764 | + #endif |
| 6765 | + elog(res, "mbedtls_ssl_read"); |
| 6766 | + wpabuf_free(out); |
| 6767 | + return NULL; |
| 6768 | + } |
| 6769 | + wpabuf_put(out, res); |
| 6770 | + |
| 6771 | + return out; |
| 6772 | +} |
| 6773 | + |
| 6774 | + |
| 6775 | +int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) |
| 6776 | +{ |
| 6777 | + /* XXX: might need to detect if session resumed from TLS session ticket |
| 6778 | + * even if not special session ticket handling for EAP-FAST, EAP-TEAP */ |
| 6779 | + /* (?ssl->handshake->resume during session ticket validation?) */ |
| 6780 | + return conn && conn->resumed; |
| 6781 | +} |
| 6782 | + |
| 6783 | + |
| 6784 | +#ifdef TLS_MBEDTLS_EAP_FAST |
| 6785 | +int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, |
| 6786 | + u8 *ciphers) |
| 6787 | +{ |
| 6788 | + /* ciphers is list of TLS_CIPHER_* from hostap/src/crypto/tls.h */ |
| 6789 | + int ids[7]; |
| 6790 | + const int idsz = (int)sizeof(ids); |
| 6791 | + int nids = -1, id; |
| 6792 | + for ( ; *ciphers != TLS_CIPHER_NONE; ++ciphers) { |
| 6793 | + switch (*ciphers) { |
| 6794 | + case TLS_CIPHER_RC4_SHA: |
| 6795 | + #ifdef MBEDTLS_TLS_RSA_WITH_RC4_128_SHA |
| 6796 | + id = MBEDTLS_TLS_RSA_WITH_RC4_128_SHA; |
| 6797 | + break; |
| 6798 | + #else |
| 6799 | + continue; /*(not supported in mbedtls 3.x; ignore)*/ |
| 6800 | + #endif |
| 6801 | + case TLS_CIPHER_AES128_SHA: |
| 6802 | + id = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA; |
| 6803 | + break; |
| 6804 | + case TLS_CIPHER_RSA_DHE_AES128_SHA: |
| 6805 | + id = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA; |
| 6806 | + break; |
| 6807 | + case TLS_CIPHER_ANON_DH_AES128_SHA: |
| 6808 | + continue; /*(not supported in mbedtls; ignore)*/ |
| 6809 | + case TLS_CIPHER_RSA_DHE_AES256_SHA: |
| 6810 | + id = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA; |
| 6811 | + break; |
| 6812 | + case TLS_CIPHER_AES256_SHA: |
| 6813 | + id = MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA; |
| 6814 | + break; |
| 6815 | + default: |
| 6816 | + return -1; /* should not happen */ |
| 6817 | + } |
| 6818 | + if (++nids == idsz) |
| 6819 | + return -1; /* should not happen */ |
| 6820 | + ids[nids] = id; |
| 6821 | + } |
| 6822 | + if (nids < 0) |
| 6823 | + return 0; /* nothing to do */ |
| 6824 | + if (++nids == idsz) |
| 6825 | + return -1; /* should not happen */ |
| 6826 | + ids[nids] = 0; /* terminate list */ |
| 6827 | + ++nids; |
| 6828 | + |
| 6829 | + return tls_mbedtls_set_ciphersuites(conn->tls_conf, ids, nids) ? 0 : -1; |
| 6830 | +} |
| 6831 | +#endif |
| 6832 | + |
| 6833 | + |
| 6834 | +int tls_get_version(void *ssl_ctx, struct tls_connection *conn, |
| 6835 | + char *buf, size_t buflen) |
| 6836 | +{ |
| 6837 | + if (conn == NULL) |
| 6838 | + return -1; |
| 6839 | + os_strlcpy(buf, mbedtls_ssl_get_version(&conn->ssl), buflen); |
| 6840 | + return buf[0] != 'u' ? 0 : -1; /*(-1 if "unknown")*/ |
| 6841 | +} |
| 6842 | + |
| 6843 | + |
| 6844 | +#ifdef TLS_MBEDTLS_EAP_TEAP |
| 6845 | +u16 tls_connection_get_cipher_suite(struct tls_connection *conn) |
| 6846 | +{ |
| 6847 | + if (conn == NULL) |
| 6848 | + return 0; |
| 6849 | + return (u16)mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl); |
| 6850 | +} |
| 6851 | +#endif |
| 6852 | + |
| 6853 | + |
| 6854 | +int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, |
| 6855 | + char *buf, size_t buflen) |
| 6856 | +{ |
| 6857 | + if (conn == NULL) |
| 6858 | + return -1; |
| 6859 | + const int id = mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl); |
| 6860 | + return tls_mbedtls_translate_ciphername(id, buf, buflen) ? 0 : -1; |
| 6861 | +} |
| 6862 | + |
| 6863 | + |
| 6864 | +#ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 6865 | + |
| 6866 | +int tls_connection_enable_workaround(void *tls_ctx, |
| 6867 | + struct tls_connection *conn) |
| 6868 | +{ |
| 6869 | + /* (see comment in src/eap_peer/eap_fast.c:eap_fast_init()) */ |
| 6870 | + /* XXX: is there a relevant setting for this in mbed TLS? */ |
| 6871 | + /* (do we even care that much about older CBC ciphers?) */ |
| 6872 | + return 0; |
| 6873 | +} |
| 6874 | + |
| 6875 | + |
| 6876 | +int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, |
| 6877 | + int ext_type, const u8 *data, |
| 6878 | + size_t data_len) |
| 6879 | +{ |
| 6880 | + /* (EAP-FAST and EAP-TEAP) */ |
| 6881 | + if (ext_type == MBEDTLS_TLS_EXT_SESSION_TICKET) /*(ext_type == 35)*/ |
| 6882 | + return tls_mbedtls_clienthello_session_ticket_prep(conn, data, |
| 6883 | + data_len); |
| 6884 | + |
| 6885 | + return -1; |
| 6886 | +} |
| 6887 | + |
| 6888 | +#endif /* TLS_MBEDTLS_SESSION_TICKETS */ |
| 6889 | + |
| 6890 | + |
| 6891 | +int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) |
| 6892 | +{ |
| 6893 | + return conn ? conn->failed : -1; |
| 6894 | +} |
| 6895 | + |
| 6896 | + |
| 6897 | +int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) |
| 6898 | +{ |
| 6899 | + return conn ? conn->read_alerts : -1; |
| 6900 | +} |
| 6901 | + |
| 6902 | + |
| 6903 | +int tls_connection_get_write_alerts(void *tls_ctx, |
| 6904 | + struct tls_connection *conn) |
| 6905 | +{ |
| 6906 | + return conn ? conn->write_alerts : -1; |
| 6907 | +} |
| 6908 | + |
| 6909 | + |
| 6910 | +#ifdef TLS_MBEDTLS_SESSION_TICKETS |
| 6911 | +int tls_connection_set_session_ticket_cb( |
| 6912 | + void *tls_ctx, struct tls_connection *conn, |
| 6913 | + tls_session_ticket_cb cb, void *ctx) |
| 6914 | +{ |
| 6915 | + if (!(conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)) { |
| 6916 | + /* (EAP-FAST and EAP-TEAP) */ |
| 6917 | + conn->session_ticket_cb = cb; |
| 6918 | + conn->session_ticket_cb_ctx = ctx; |
| 6919 | + return 0; |
| 6920 | + } |
| 6921 | + return -1; |
| 6922 | +} |
| 6923 | +#endif |
| 6924 | + |
| 6925 | + |
| 6926 | +int tls_get_library_version(char *buf, size_t buf_len) |
| 6927 | +{ |
| 6928 | + #ifndef MBEDTLS_VERSION_C |
| 6929 | + const char * const ver = "n/a"; |
| 6930 | + #else |
| 6931 | + char ver[9]; |
| 6932 | + mbedtls_version_get_string(ver); |
| 6933 | + #endif |
| 6934 | + return os_snprintf(buf, buf_len, |
| 6935 | + "mbed TLS build=" MBEDTLS_VERSION_STRING " run=%s", ver); |
| 6936 | +} |
| 6937 | + |
| 6938 | + |
| 6939 | +void tls_connection_set_success_data(struct tls_connection *conn, |
| 6940 | + struct wpabuf *data) |
| 6941 | +{ |
| 6942 | + wpabuf_free(conn->success_data); |
| 6943 | + conn->success_data = data; |
| 6944 | +} |
| 6945 | + |
| 6946 | + |
| 6947 | +void tls_connection_set_success_data_resumed(struct tls_connection *conn) |
| 6948 | +{ |
| 6949 | +} |
| 6950 | + |
| 6951 | + |
| 6952 | +const struct wpabuf * |
| 6953 | +tls_connection_get_success_data(struct tls_connection *conn) |
| 6954 | +{ |
| 6955 | + return conn->success_data; |
| 6956 | +} |
| 6957 | + |
| 6958 | + |
| 6959 | +void tls_connection_remove_session(struct tls_connection *conn) |
| 6960 | +{ |
| 6961 | +} |
| 6962 | + |
| 6963 | + |
| 6964 | +#ifdef TLS_MBEDTLS_EAP_TEAP |
| 6965 | +int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len) |
| 6966 | +{ |
| 6967 | + #if defined(MBEDTLS_SSL_RENEGOTIATION) /* XXX: renegotiation or resumption? */ |
| 6968 | + /* data from TLS handshake Finished message */ |
| 6969 | + size_t verify_len = conn->ssl.MBEDTLS_PRIVATE(verify_data_len); |
| 6970 | + char *verify_data = (conn->is_server ^ conn->resumed) |
| 6971 | + ? conn->ssl.MBEDTLS_PRIVATE(peer_verify_data) |
| 6972 | + : conn->ssl.MBEDTLS_PRIVATE(own_verify_data); |
| 6973 | + if (verify_len && verify_len <= max_len) { |
| 6974 | + os_memcpy(buf, verify_data, verify_len); |
| 6975 | + return (int)verify_len; |
| 6976 | + } |
| 6977 | + #endif |
| 6978 | + return -1; |
| 6979 | +} |
| 6980 | +#endif |
| 6981 | + |
| 6982 | + |
| 6983 | +__attribute_noinline__ |
| 6984 | +static void tls_mbedtls_set_peer_subject(struct tls_connection *conn, const mbedtls_x509_crt *crt) |
| 6985 | +{ |
| 6986 | + if (conn->peer_subject) |
| 6987 | + return; |
| 6988 | + char buf[MBEDTLS_X509_MAX_DN_NAME_SIZE*2]; |
| 6989 | + int buflen = mbedtls_x509_dn_gets(buf, sizeof(buf), &crt->subject); |
| 6990 | + if (buflen >= 0 && (conn->peer_subject = os_malloc((size_t)buflen+1))) |
| 6991 | + os_memcpy(conn->peer_subject, buf, (size_t)buflen+1); |
| 6992 | +} |
| 6993 | + |
| 6994 | + |
| 6995 | +#ifdef TLS_MBEDTLS_EAP_TEAP |
| 6996 | +const char * tls_connection_get_peer_subject(struct tls_connection *conn) |
| 6997 | +{ |
| 6998 | + if (!conn) |
| 6999 | + return NULL; |
| 7000 | + if (!conn->peer_subject) { /*(if not set during cert verify)*/ |
| 7001 | + const mbedtls_x509_crt *peer_cert = |
| 7002 | + mbedtls_ssl_get_peer_cert(&conn->ssl); |
| 7003 | + if (peer_cert) |
| 7004 | + tls_mbedtls_set_peer_subject(conn, peer_cert); |
| 7005 | + } |
| 7006 | + return conn->peer_subject; |
| 7007 | +} |
| 7008 | +#endif |
| 7009 | + |
| 7010 | + |
| 7011 | +#ifdef TLS_MBEDTLS_EAP_TEAP |
| 7012 | +bool tls_connection_get_own_cert_used(struct tls_connection *conn) |
| 7013 | +{ |
| 7014 | + /* XXX: availability of cert does not necessary mean that client |
| 7015 | + * received certificate request from server and then sent cert. |
| 7016 | + * ? step handshake in tls_connection_handshake() looking for |
| 7017 | + * MBEDTLS_SSL_CERTIFICATE_REQUEST ? */ |
| 7018 | + const struct tls_conf * const tls_conf = conn->tls_conf; |
| 7019 | + return (tls_conf->has_client_cert && tls_conf->has_private_key); |
| 7020 | +} |
| 7021 | +#endif |
| 7022 | + |
| 7023 | + |
| 7024 | +#if defined(CONFIG_FIPS) |
| 7025 | +#define TLS_MBEDTLS_CONFIG_FIPS |
| 7026 | +#endif |
| 7027 | + |
| 7028 | +#if defined(CONFIG_SHA256) |
| 7029 | +#define TLS_MBEDTLS_TLS_PRF_SHA256 |
| 7030 | +#endif |
| 7031 | + |
| 7032 | +#if defined(CONFIG_SHA384) |
| 7033 | +#define TLS_MBEDTLS_TLS_PRF_SHA384 |
| 7034 | +#endif |
| 7035 | + |
| 7036 | + |
| 7037 | +#ifndef TLS_MBEDTLS_CONFIG_FIPS |
| 7038 | +#if defined(CONFIG_MODULE_TESTS) |
| 7039 | +/* unused with CONFIG_TLS=mbedtls except in crypto_module_tests.c */ |
| 7040 | +#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ \ |
| 7041 | + && MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */ |
| 7042 | +/* sha1-tlsprf.c */ |
| 7043 | +#include "sha1.h" |
| 7044 | +int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label, |
| 7045 | + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) |
| 7046 | +{ |
| 7047 | + return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1, |
| 7048 | + secret, secret_len, label, |
| 7049 | + seed, seed_len, out, outlen) ? -1 : 0; |
| 7050 | +} |
| 7051 | +#else |
| 7052 | +#include "sha1-tlsprf.c" /* pull in hostap local implementation */ |
| 7053 | +#endif |
| 7054 | +#endif |
| 7055 | +#endif |
| 7056 | + |
| 7057 | +#ifdef TLS_MBEDTLS_TLS_PRF_SHA256 |
| 7058 | +/* sha256-tlsprf.c */ |
| 7059 | +#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 7060 | +#include "sha256.h" |
| 7061 | +int tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label, |
| 7062 | + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) |
| 7063 | +{ |
| 7064 | + return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA256, |
| 7065 | + secret, secret_len, label, |
| 7066 | + seed, seed_len, out, outlen) ? -1 : 0; |
| 7067 | +} |
| 7068 | +#else |
| 7069 | +#include "sha256-tlsprf.c" /* pull in hostap local implementation */ |
| 7070 | +#endif |
| 7071 | +#endif |
| 7072 | + |
| 7073 | +#ifdef TLS_MBEDTLS_TLS_PRF_SHA384 |
| 7074 | +/* sha384-tlsprf.c */ |
| 7075 | +#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ |
| 7076 | +#include "sha384.h" |
| 7077 | +int tls_prf_sha384(const u8 *secret, size_t secret_len, const char *label, |
| 7078 | + const u8 *seed, size_t seed_len, u8 *out, size_t outlen) |
| 7079 | +{ |
| 7080 | + return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA384, |
| 7081 | + secret, secret_len, label, |
| 7082 | + seed, seed_len, out, outlen) ? -1 : 0; |
| 7083 | +} |
| 7084 | +#else |
| 7085 | +#include "sha384-tlsprf.c" /* pull in hostap local implementation */ |
| 7086 | +#endif |
| 7087 | +#endif |
| 7088 | + |
| 7089 | + |
| 7090 | +#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */ |
| 7091 | +#define mbedtls_x509_crt_has_ext_type(crt, ext_type) \ |
| 7092 | + ((crt)->MBEDTLS_PRIVATE(ext_types) & (ext_type)) |
| 7093 | +#endif |
| 7094 | + |
| 7095 | +struct mlist { const char *p; size_t n; }; |
| 7096 | + |
| 7097 | + |
| 7098 | +static int |
| 7099 | +tls_mbedtls_match_altsubject(mbedtls_x509_crt *crt, const char *match) |
| 7100 | +{ |
| 7101 | + /* RFE: this could be pre-parsed into structured data at config time */ |
| 7102 | + struct mlist list[256]; /*(much larger than expected)*/ |
| 7103 | + int nlist = 0; |
| 7104 | + if ( os_strncmp(match, "EMAIL:", 6) != 0 |
| 7105 | + && os_strncmp(match, "DNS:", 4) != 0 |
| 7106 | + && os_strncmp(match, "URI:", 4) != 0 ) { |
| 7107 | + wpa_printf(MSG_INFO, "MTLS: Invalid altSubjectName match '%s'", match); |
| 7108 | + return 0; |
| 7109 | + } |
| 7110 | + for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") { |
| 7111 | + do { } while ((tok = os_strchr(s, ';')) |
| 7112 | + && os_strncmp(tok+1, "EMAIL:", 6) != 0 |
| 7113 | + && os_strncmp(tok+1, "DNS:", 4) != 0 |
| 7114 | + && os_strncmp(tok+1, "URI:", 4) != 0); |
| 7115 | + list[nlist].p = s; |
| 7116 | + list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s); |
| 7117 | + if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) { |
| 7118 | + wpa_printf(MSG_INFO, "MTLS: excessive altSubjectName match '%s'", |
| 7119 | + match); |
| 7120 | + break; /* truncate huge list and continue */ |
| 7121 | + } |
| 7122 | + } |
| 7123 | + |
| 7124 | + if (!mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) |
| 7125 | + return 0; |
| 7126 | + |
| 7127 | + const mbedtls_x509_sequence *cur = &crt->subject_alt_names; |
| 7128 | + for (; cur != NULL; cur = cur->next) { |
| 7129 | + const unsigned char san_type = (unsigned char)cur->buf.tag |
| 7130 | + & MBEDTLS_ASN1_TAG_VALUE_MASK; |
| 7131 | + char t; |
| 7132 | + size_t step = 4; |
| 7133 | + switch (san_type) { /* "EMAIL:" or "DNS:" or "URI:" */ |
| 7134 | + case MBEDTLS_X509_SAN_RFC822_NAME: step = 6; t = 'E'; break; |
| 7135 | + case MBEDTLS_X509_SAN_DNS_NAME: t = 'D'; break; |
| 7136 | + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: t = 'U'; break; |
| 7137 | + default: continue; |
| 7138 | + } |
| 7139 | + |
| 7140 | + for (int i = 0; i < nlist; ++i) { |
| 7141 | + /* step over "EMAIL:" or "DNS:" or "URI:" in list[i].p */ |
| 7142 | + /* Note: v is not '\0'-terminated, but is a known length vlen, |
| 7143 | + * so okay to pass to os_strncasecmp() even though not z-string */ |
| 7144 | + if (cur->buf.len == list[i].n - step && t == *list[i].p |
| 7145 | + && 0 == os_strncasecmp((char *)cur->buf.p, |
| 7146 | + list[i].p+step, cur->buf.len)) { |
| 7147 | + return 1; /* match */ |
| 7148 | + } |
| 7149 | + } |
| 7150 | + } |
| 7151 | + return 0; /* no match */ |
| 7152 | +} |
| 7153 | + |
| 7154 | + |
| 7155 | +static int |
| 7156 | +tls_mbedtls_match_suffix(const char *v, size_t vlen, |
| 7157 | + const struct mlist *list, int nlist, int full) |
| 7158 | +{ |
| 7159 | + /* Note: v is not '\0'-terminated, but is a known length vlen, |
| 7160 | + * so okay to pass to os_strncasecmp() even though not z-string */ |
| 7161 | + for (int i = 0; i < nlist; ++i) { |
| 7162 | + size_t n = list[i].n; |
| 7163 | + if ((n == vlen || (n < vlen && v[vlen-n-1] == '.' && !full)) |
| 7164 | + && 0 == os_strncasecmp(v+vlen-n, list[i].p, n)) |
| 7165 | + return 1; /* match */ |
| 7166 | + } |
| 7167 | + return 0; /* no match */ |
| 7168 | +} |
| 7169 | + |
| 7170 | + |
| 7171 | +static int |
| 7172 | +tls_mbedtls_match_suffixes(mbedtls_x509_crt *crt, const char *match, int full) |
| 7173 | +{ |
| 7174 | + /* RFE: this could be pre-parsed into structured data at config time */ |
| 7175 | + struct mlist list[256]; /*(much larger than expected)*/ |
| 7176 | + int nlist = 0; |
| 7177 | + for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") { |
| 7178 | + tok = os_strchr(s, ';'); |
| 7179 | + list[nlist].p = s; |
| 7180 | + list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s); |
| 7181 | + if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) { |
| 7182 | + wpa_printf(MSG_INFO, "MTLS: excessive suffix match '%s'", match); |
| 7183 | + break; /* truncate huge list and continue */ |
| 7184 | + } |
| 7185 | + } |
| 7186 | + |
| 7187 | + /* check subjectAltNames */ |
| 7188 | + if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) { |
| 7189 | + const mbedtls_x509_sequence *cur = &crt->subject_alt_names; |
| 7190 | + for (; cur != NULL; cur = cur->next) { |
| 7191 | + const unsigned char san_type = (unsigned char)cur->buf.tag |
| 7192 | + & MBEDTLS_ASN1_TAG_VALUE_MASK; |
| 7193 | + if (san_type == MBEDTLS_X509_SAN_DNS_NAME |
| 7194 | + && tls_mbedtls_match_suffix((char *)cur->buf.p, |
| 7195 | + cur->buf.len, |
| 7196 | + list, nlist, full)) { |
| 7197 | + return 1; /* match */ |
| 7198 | + } |
| 7199 | + } |
| 7200 | + } |
| 7201 | + |
| 7202 | + /* check subject CN */ |
| 7203 | + const mbedtls_x509_name *name = &crt->subject; |
| 7204 | + for (; name != NULL; name = name->next) { |
| 7205 | + if (name->oid.p && MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0) |
| 7206 | + break; |
| 7207 | + } |
| 7208 | + if (name && tls_mbedtls_match_suffix((char *)name->val.p, name->val.len, |
| 7209 | + list, nlist, full)) { |
| 7210 | + return 1; /* match */ |
| 7211 | + } |
| 7212 | + |
| 7213 | + return 0; /* no match */ |
| 7214 | +} |
| 7215 | + |
| 7216 | + |
| 7217 | +static int |
| 7218 | +tls_mbedtls_match_dn_field(mbedtls_x509_crt *crt, const char *match) |
| 7219 | +{ |
| 7220 | + /* RFE: this could be pre-parsed into structured data at config time */ |
| 7221 | + struct mlistoid { const char *p; size_t n; |
| 7222 | + const char *oid; size_t olen; |
| 7223 | + int prefix; }; |
| 7224 | + struct mlistoid list[32]; /*(much larger than expected)*/ |
| 7225 | + int nlist = 0; |
| 7226 | + for (const char *s = match, *tok, *e; *s; s = tok ? tok+1 : "") { |
| 7227 | + tok = os_strchr(s, '/'); |
| 7228 | + list[nlist].oid = NULL; |
| 7229 | + list[nlist].olen = 0; |
| 7230 | + list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s); |
| 7231 | + e = memchr(s, '=', list[nlist].n); |
| 7232 | + if (e == NULL) { |
| 7233 | + if (list[nlist].n == 0) |
| 7234 | + continue; /* skip consecutive, repeated '/' */ |
| 7235 | + if (list[nlist].n == 1 && *s == '*') { |
| 7236 | + /* special-case "*" to match any OID and value */ |
| 7237 | + s = e = "=*"; |
| 7238 | + list[nlist].n = 2; |
| 7239 | + list[nlist].oid = ""; |
| 7240 | + } |
| 7241 | + else { |
| 7242 | + wpa_printf(MSG_INFO, |
| 7243 | + "MTLS: invalid check_cert_subject '%s' missing '='", |
| 7244 | + match); |
| 7245 | + return 0; |
| 7246 | + } |
| 7247 | + } |
| 7248 | + switch (e - s) { |
| 7249 | + case 1: |
| 7250 | + if (*s == 'C') { |
| 7251 | + list[nlist].oid = MBEDTLS_OID_AT_COUNTRY; |
| 7252 | + list[nlist].olen = sizeof(MBEDTLS_OID_AT_COUNTRY)-1; |
| 7253 | + } |
| 7254 | + else if (*s == 'L') { |
| 7255 | + list[nlist].oid = MBEDTLS_OID_AT_LOCALITY; |
| 7256 | + list[nlist].olen = sizeof(MBEDTLS_OID_AT_LOCALITY)-1; |
| 7257 | + } |
| 7258 | + else if (*s == 'O') { |
| 7259 | + list[nlist].oid = MBEDTLS_OID_AT_ORGANIZATION; |
| 7260 | + list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORGANIZATION)-1; |
| 7261 | + } |
| 7262 | + break; |
| 7263 | + case 2: |
| 7264 | + if (s[0] == 'C' && s[1] == 'N') { |
| 7265 | + list[nlist].oid = MBEDTLS_OID_AT_CN; |
| 7266 | + list[nlist].olen = sizeof(MBEDTLS_OID_AT_CN)-1; |
| 7267 | + } |
| 7268 | + else if (s[0] == 'S' && s[1] == 'T') { |
| 7269 | + list[nlist].oid = MBEDTLS_OID_AT_STATE; |
| 7270 | + list[nlist].olen = sizeof(MBEDTLS_OID_AT_STATE)-1; |
| 7271 | + } |
| 7272 | + else if (s[0] == 'O' && s[1] == 'U') { |
| 7273 | + list[nlist].oid = MBEDTLS_OID_AT_ORG_UNIT; |
| 7274 | + list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORG_UNIT)-1; |
| 7275 | + } |
| 7276 | + break; |
| 7277 | + case 12: |
| 7278 | + if (os_memcmp(s, "emailAddress", 12) == 0) { |
| 7279 | + list[nlist].oid = MBEDTLS_OID_PKCS9_EMAIL; |
| 7280 | + list[nlist].olen = sizeof(MBEDTLS_OID_PKCS9_EMAIL)-1; |
| 7281 | + } |
| 7282 | + break; |
| 7283 | + default: |
| 7284 | + break; |
| 7285 | + } |
| 7286 | + if (list[nlist].oid == NULL) { |
| 7287 | + wpa_printf(MSG_INFO, |
| 7288 | + "MTLS: Unknown field in check_cert_subject '%s'", |
| 7289 | + match); |
| 7290 | + return 0; |
| 7291 | + } |
| 7292 | + list[nlist].n -= (size_t)(++e - s); |
| 7293 | + list[nlist].p = e; |
| 7294 | + if (list[nlist].n && e[list[nlist].n-1] == '*') { |
| 7295 | + --list[nlist].n; |
| 7296 | + list[nlist].prefix = 1; |
| 7297 | + } |
| 7298 | + /*(could easily add support for suffix matches if value begins with '*', |
| 7299 | + * but suffix match is not currently supported by other TLS modules)*/ |
| 7300 | + |
| 7301 | + if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) { |
| 7302 | + wpa_printf(MSG_INFO, |
| 7303 | + "MTLS: excessive check_cert_subject match '%s'", |
| 7304 | + match); |
| 7305 | + break; /* truncate huge list and continue */ |
| 7306 | + } |
| 7307 | + } |
| 7308 | + |
| 7309 | + /* each component in match string must match cert Subject in order listed |
| 7310 | + * The behavior below preserves ordering but is slightly different than |
| 7311 | + * the grossly inefficient contortions implemented in tls_openssl.c */ |
| 7312 | + const mbedtls_x509_name *name = &crt->subject; |
| 7313 | + for (int i = 0; i < nlist; ++i) { |
| 7314 | + int found = 0; |
| 7315 | + for (; name != NULL && !found; name = name->next) { |
| 7316 | + if (!name->oid.p) |
| 7317 | + continue; |
| 7318 | + /* special-case "*" to match any OID and value */ |
| 7319 | + if (list[i].olen == 0) { |
| 7320 | + found = 1; |
| 7321 | + continue; |
| 7322 | + } |
| 7323 | + /* perform equalent of !MBEDTLS_OID_CMP() with oid ptr and len */ |
| 7324 | + if (list[i].olen != name->oid.len |
| 7325 | + || os_memcmp(list[i].oid, name->oid.p, name->oid.len) != 0) |
| 7326 | + continue; |
| 7327 | + /* Note: v is not '\0'-terminated, but is a known length vlen, |
| 7328 | + * so okay to pass to os_strncasecmp() even though not z-string */ |
| 7329 | + if ((list[i].prefix |
| 7330 | + ? list[i].n <= name->val.len /* prefix match */ |
| 7331 | + : list[i].n == name->val.len) /* full match */ |
| 7332 | + && 0 == os_strncasecmp((char *)name->val.p, |
| 7333 | + list[i].p, list[i].n)) { |
| 7334 | + found = 1; |
| 7335 | + continue; |
| 7336 | + } |
| 7337 | + } |
| 7338 | + if (!found) |
| 7339 | + return 0; /* no match */ |
| 7340 | + } |
| 7341 | + return 1; /* match */ |
| 7342 | +} |
| 7343 | + |
| 7344 | + |
| 7345 | +__attribute_cold__ |
| 7346 | +static void |
| 7347 | +tls_mbedtls_verify_fail_event (mbedtls_x509_crt *crt, int depth, |
| 7348 | + const char *errmsg, enum tls_fail_reason reason) |
| 7349 | +{ |
| 7350 | + struct tls_config *init_conf = &tls_ctx_global.init_conf; |
| 7351 | + if (init_conf->event_cb == NULL) |
| 7352 | + return; |
| 7353 | + |
| 7354 | + struct wpabuf *certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len); |
| 7355 | + char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2]; |
| 7356 | + if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0) |
| 7357 | + subject[0] = '\0'; |
| 7358 | + union tls_event_data ev; |
| 7359 | + os_memset(&ev, 0, sizeof(ev)); |
| 7360 | + ev.cert_fail.reason = reason; |
| 7361 | + ev.cert_fail.depth = depth; |
| 7362 | + ev.cert_fail.subject = subject; |
| 7363 | + ev.cert_fail.reason_txt = errmsg; |
| 7364 | + ev.cert_fail.cert = certbuf; |
| 7365 | + |
| 7366 | + init_conf->event_cb(init_conf->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev); |
| 7367 | + |
| 7368 | + wpabuf_free(certbuf); |
| 7369 | +} |
| 7370 | + |
| 7371 | + |
| 7372 | +__attribute_noinline__ |
| 7373 | +static void |
| 7374 | +tls_mbedtls_verify_cert_event (struct tls_connection *conn, |
| 7375 | + mbedtls_x509_crt *crt, int depth) |
| 7376 | +{ |
| 7377 | + struct tls_config *init_conf = &tls_ctx_global.init_conf; |
| 7378 | + if (init_conf->event_cb == NULL) |
| 7379 | + return; |
| 7380 | + |
| 7381 | + struct wpabuf *certbuf = NULL; |
| 7382 | + union tls_event_data ev; |
| 7383 | + os_memset(&ev, 0, sizeof(ev)); |
| 7384 | + |
| 7385 | + #ifdef MBEDTLS_SHA256_C |
| 7386 | + u8 hash[SHA256_DIGEST_LENGTH]; |
| 7387 | + const u8 *addr[] = { (u8 *)crt->raw.p }; |
| 7388 | + if (sha256_vector(1, addr, &crt->raw.len, hash) == 0) { |
| 7389 | + ev.peer_cert.hash = hash; |
| 7390 | + ev.peer_cert.hash_len = sizeof(hash); |
| 7391 | + } |
| 7392 | + #endif |
| 7393 | + ev.peer_cert.depth = depth; |
| 7394 | + char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2]; |
| 7395 | + if (depth == 0) |
| 7396 | + ev.peer_cert.subject = conn->peer_subject; |
| 7397 | + if (ev.peer_cert.subject == NULL) { |
| 7398 | + ev.peer_cert.subject = subject; |
| 7399 | + if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0) |
| 7400 | + subject[0] = '\0'; |
| 7401 | + } |
| 7402 | + |
| 7403 | + char serial_num[128+1]; |
| 7404 | + ev.peer_cert.serial_num = |
| 7405 | + tls_mbedtls_peer_serial_num(crt, serial_num, sizeof(serial_num)); |
| 7406 | + |
| 7407 | + const mbedtls_x509_sequence *cur; |
| 7408 | + |
| 7409 | + cur = NULL; |
| 7410 | + if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) |
| 7411 | + cur = &crt->subject_alt_names; |
| 7412 | + for (; cur != NULL; cur = cur->next) { |
| 7413 | + const unsigned char san_type = (unsigned char)cur->buf.tag |
| 7414 | + & MBEDTLS_ASN1_TAG_VALUE_MASK; |
| 7415 | + size_t prelen = 4; |
| 7416 | + const char *pre; |
| 7417 | + switch (san_type) { |
| 7418 | + case MBEDTLS_X509_SAN_RFC822_NAME: prelen = 6; pre = "EMAIL:";break; |
| 7419 | + case MBEDTLS_X509_SAN_DNS_NAME: pre = "DNS:"; break; |
| 7420 | + case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: pre = "URI:"; break; |
| 7421 | + default: continue; |
| 7422 | + } |
| 7423 | + |
| 7424 | + char *pos = os_malloc(prelen + cur->buf.len + 1); |
| 7425 | + if (pos == NULL) |
| 7426 | + break; |
| 7427 | + ev.peer_cert.altsubject[ev.peer_cert.num_altsubject] = pos; |
| 7428 | + os_memcpy(pos, pre, prelen); |
| 7429 | + /* data should be properly backslash-escaped if needed, |
| 7430 | + * so code below does not re-escape, but does replace CTLs */ |
| 7431 | + /*os_memcpy(pos+prelen, cur->buf.p, cur->buf.len);*/ |
| 7432 | + /*pos[prelen+cur->buf.len] = '\0';*/ |
| 7433 | + pos += prelen; |
| 7434 | + for (size_t i = 0; i < cur->buf.len; ++i) { |
| 7435 | + unsigned char c = cur->buf.p[i]; |
| 7436 | + *pos++ = (c >= 32 && c != 127) ? c : '?'; |
| 7437 | + } |
| 7438 | + *pos = '\0'; |
| 7439 | + |
| 7440 | + if (++ev.peer_cert.num_altsubject == TLS_MAX_ALT_SUBJECT) |
| 7441 | + break; |
| 7442 | + } |
| 7443 | + |
| 7444 | + cur = NULL; |
| 7445 | + if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_CERTIFICATE_POLICIES)) |
| 7446 | + cur = &crt->certificate_policies; |
| 7447 | + for (; cur != NULL; cur = cur->next) { |
| 7448 | + if (cur->buf.len != 11) /* len of OID_TOD_STRICT or OID_TOD_TOFU */ |
| 7449 | + continue; |
| 7450 | + /* TOD-STRICT "1.3.6.1.4.1.40808.1.3.1" */ |
| 7451 | + /* TOD-TOFU "1.3.6.1.4.1.40808.1.3.2" */ |
| 7452 | + #define OID_TOD_STRICT "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x01" |
| 7453 | + #define OID_TOD_TOFU "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x02" |
| 7454 | + if (os_memcmp(cur->buf.p, |
| 7455 | + OID_TOD_STRICT, sizeof(OID_TOD_STRICT)-1) == 0) { |
| 7456 | + ev.peer_cert.tod = 1; /* TOD-STRICT */ |
| 7457 | + break; |
| 7458 | + } |
| 7459 | + if (os_memcmp(cur->buf.p, |
| 7460 | + OID_TOD_TOFU, sizeof(OID_TOD_TOFU)-1) == 0) { |
| 7461 | + ev.peer_cert.tod = 2; /* TOD-TOFU */ |
| 7462 | + break; |
| 7463 | + } |
| 7464 | + } |
| 7465 | + |
| 7466 | + struct tls_conf *tls_conf = conn->tls_conf; |
| 7467 | + if (tls_conf->ca_cert_probe || (tls_conf->flags & TLS_CONN_EXT_CERT_CHECK) |
| 7468 | + || init_conf->cert_in_cb) { |
| 7469 | + certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len); |
| 7470 | + ev.peer_cert.cert = certbuf; |
| 7471 | + } |
| 7472 | + |
| 7473 | + init_conf->event_cb(init_conf->cb_ctx, TLS_PEER_CERTIFICATE, &ev); |
| 7474 | + |
| 7475 | + wpabuf_free(certbuf); |
| 7476 | + char **altsubject; |
| 7477 | + *(const char ***)&altsubject = ev.peer_cert.altsubject; |
| 7478 | + for (size_t i = 0; i < ev.peer_cert.num_altsubject; ++i) |
| 7479 | + os_free(altsubject[i]); |
| 7480 | +} |
| 7481 | + |
| 7482 | + |
| 7483 | +static int |
| 7484 | +tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags) |
| 7485 | +{ |
| 7486 | + /* XXX: N.B. verify code not carefully tested besides hwsim tests |
| 7487 | + * |
| 7488 | + * RFE: mbedtls_x509_crt_verify_info() and enhance log trace messages |
| 7489 | + * RFE: review and add support for additional TLS_CONN_* flags |
| 7490 | + * not handling OCSP (not available in mbedtls) |
| 7491 | + * ... */ |
| 7492 | + |
| 7493 | + struct tls_connection *conn = (struct tls_connection *)arg; |
| 7494 | + struct tls_conf *tls_conf = conn->tls_conf; |
| 7495 | + uint32_t flags_in = *flags; |
| 7496 | + |
| 7497 | + if (depth > 8) { /*(depth 8 picked as arbitrary limit)*/ |
| 7498 | + emsg(MSG_WARNING, "client cert chain too long"); |
| 7499 | + *flags |= MBEDTLS_X509_BADCERT_OTHER; /* cert chain too long */ |
| 7500 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7501 | + "client cert chain too long", |
| 7502 | + TLS_FAIL_BAD_CERTIFICATE); |
| 7503 | + } |
| 7504 | + else if (tls_conf->verify_depth0_only) { |
| 7505 | + if (depth > 0) |
| 7506 | + *flags = 0; |
| 7507 | + else { |
| 7508 | + #ifdef MBEDTLS_SHA256_C |
| 7509 | + u8 hash[SHA256_DIGEST_LENGTH]; |
| 7510 | + const u8 *addr[] = { (u8 *)crt->raw.p }; |
| 7511 | + if (sha256_vector(1, addr, &crt->raw.len, hash) < 0 |
| 7512 | + || os_memcmp(tls_conf->ca_cert_hash, hash, sizeof(hash)) != 0) { |
| 7513 | + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; |
| 7514 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7515 | + "cert hash mismatch", |
| 7516 | + TLS_FAIL_UNTRUSTED); |
| 7517 | + } |
| 7518 | + else /* hash matches; ignore other issues *except* if revoked)*/ |
| 7519 | + *flags &= MBEDTLS_X509_BADCERT_REVOKED; |
| 7520 | + #endif |
| 7521 | + } |
| 7522 | + } |
| 7523 | + else if (depth == 0) { |
| 7524 | + if (!conn->peer_subject) |
| 7525 | + tls_mbedtls_set_peer_subject(conn, crt); |
| 7526 | + /*(use same labels to tls_mbedtls_verify_fail_event() as used in |
| 7527 | + * other TLS modules so that hwsim tests find exact string match)*/ |
| 7528 | + if (!conn->peer_subject) { /* error copying subject string */ |
| 7529 | + *flags |= MBEDTLS_X509_BADCERT_OTHER; |
| 7530 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7531 | + "internal error", |
| 7532 | + TLS_FAIL_UNSPECIFIED); |
| 7533 | + } |
| 7534 | + /*(use os_strstr() for subject match as is done in tls_mbedtls.c |
| 7535 | + * to follow the same behavior, even though a suffix match would |
| 7536 | + * make more sense. Also, note that strstr match does not |
| 7537 | + * normalize whitespace (between components) for comparison)*/ |
| 7538 | + else if (tls_conf->subject_match |
| 7539 | + && os_strstr(conn->peer_subject, |
| 7540 | + tls_conf->subject_match) == NULL) { |
| 7541 | + wpa_printf(MSG_WARNING, |
| 7542 | + "MTLS: Subject '%s' did not match with '%s'", |
| 7543 | + conn->peer_subject, tls_conf->subject_match); |
| 7544 | + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
| 7545 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7546 | + "Subject mismatch", |
| 7547 | + TLS_FAIL_SUBJECT_MISMATCH); |
| 7548 | + } |
| 7549 | + if (tls_conf->altsubject_match |
| 7550 | + && !tls_mbedtls_match_altsubject(crt, tls_conf->altsubject_match)) { |
| 7551 | + wpa_printf(MSG_WARNING, |
| 7552 | + "MTLS: altSubjectName match '%s' not found", |
| 7553 | + tls_conf->altsubject_match); |
| 7554 | + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
| 7555 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7556 | + "AltSubject mismatch", |
| 7557 | + TLS_FAIL_ALTSUBJECT_MISMATCH); |
| 7558 | + } |
| 7559 | + if (tls_conf->suffix_match |
| 7560 | + && !tls_mbedtls_match_suffixes(crt, tls_conf->suffix_match, 0)) { |
| 7561 | + wpa_printf(MSG_WARNING, |
| 7562 | + "MTLS: Domain suffix match '%s' not found", |
| 7563 | + tls_conf->suffix_match); |
| 7564 | + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
| 7565 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7566 | + "Domain suffix mismatch", |
| 7567 | + TLS_FAIL_DOMAIN_SUFFIX_MISMATCH); |
| 7568 | + } |
| 7569 | + if (tls_conf->domain_match |
| 7570 | + && !tls_mbedtls_match_suffixes(crt, tls_conf->domain_match, 1)) { |
| 7571 | + wpa_printf(MSG_WARNING, |
| 7572 | + "MTLS: Domain match '%s' not found", |
| 7573 | + tls_conf->domain_match); |
| 7574 | + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
| 7575 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7576 | + "Domain mismatch", |
| 7577 | + TLS_FAIL_DOMAIN_MISMATCH); |
| 7578 | + } |
| 7579 | + if (tls_conf->check_cert_subject |
| 7580 | + && !tls_mbedtls_match_dn_field(crt, tls_conf->check_cert_subject)) { |
| 7581 | + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; |
| 7582 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7583 | + "Distinguished Name", |
| 7584 | + TLS_FAIL_DN_MISMATCH); |
| 7585 | + } |
| 7586 | + if (tls_conf->flags & TLS_CONN_SUITEB) { |
| 7587 | + /* check RSA modulus size (public key bitlen) */ |
| 7588 | + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&crt->pk); |
| 7589 | + if ((pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS) |
| 7590 | + && mbedtls_pk_get_bitlen(&crt->pk) < 3072) { |
| 7591 | + /* hwsim suite_b RSA tests expect 3072 |
| 7592 | + * suite_b_192_rsa_ecdhe_radius_rsa2048_client |
| 7593 | + * suite_b_192_rsa_dhe_radius_rsa2048_client */ |
| 7594 | + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; |
| 7595 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7596 | + "Insufficient RSA modulus size", |
| 7597 | + TLS_FAIL_INSUFFICIENT_KEY_LEN); |
| 7598 | + } |
| 7599 | + } |
| 7600 | + if (tls_conf->check_crl && tls_conf->crl == NULL) { |
| 7601 | + /* see tests/hwsim test_ap_eap.py ap_wpa2_eap_tls_check_crl */ |
| 7602 | + emsg(MSG_WARNING, "check_crl set but no CRL loaded; reject all?"); |
| 7603 | + *flags |= MBEDTLS_X509_BADCERT_OTHER; |
| 7604 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7605 | + "check_crl set but no CRL loaded; " |
| 7606 | + "reject all?", |
| 7607 | + TLS_FAIL_BAD_CERTIFICATE); |
| 7608 | + } |
| 7609 | + } |
| 7610 | + else { |
| 7611 | + if (tls_conf->check_crl != 2) /* 2 == verify CRLs for all certs */ |
| 7612 | + *flags &= ~MBEDTLS_X509_BADCERT_REVOKED; |
| 7613 | + } |
| 7614 | + |
| 7615 | + if (!tls_conf->check_crl_strict) { |
| 7616 | + *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED; |
| 7617 | + *flags &= ~MBEDTLS_X509_BADCRL_FUTURE; |
| 7618 | + } |
| 7619 | + |
| 7620 | + if (tls_conf->flags & TLS_CONN_DISABLE_TIME_CHECKS) { |
| 7621 | + *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED; |
| 7622 | + *flags &= ~MBEDTLS_X509_BADCERT_FUTURE; |
| 7623 | + } |
| 7624 | + |
| 7625 | + tls_mbedtls_verify_cert_event(conn, crt, depth); |
| 7626 | + |
| 7627 | + if (*flags) { |
| 7628 | + if (*flags & (MBEDTLS_X509_BADCERT_NOT_TRUSTED |
| 7629 | + |MBEDTLS_X509_BADCERT_CN_MISMATCH |
| 7630 | + |MBEDTLS_X509_BADCERT_REVOKED)) { |
| 7631 | + emsg(MSG_WARNING, "client cert not trusted"); |
| 7632 | + } |
| 7633 | + /* report event if flags set but no additional flags set above */ |
| 7634 | + /* (could translate flags to more detailed TLS_FAIL_* if needed) */ |
| 7635 | + if (!(*flags & ~flags_in)) { |
| 7636 | + enum tls_fail_reason reason = TLS_FAIL_UNSPECIFIED; |
| 7637 | + const char *errmsg = "cert verify fail unspecified"; |
| 7638 | + if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) { |
| 7639 | + reason = TLS_FAIL_UNTRUSTED; |
| 7640 | + errmsg = "certificate not trusted"; |
| 7641 | + } |
| 7642 | + if (*flags & MBEDTLS_X509_BADCERT_REVOKED) { |
| 7643 | + reason = TLS_FAIL_REVOKED; |
| 7644 | + errmsg = "certificate has been revoked"; |
| 7645 | + } |
| 7646 | + if (*flags & MBEDTLS_X509_BADCERT_FUTURE) { |
| 7647 | + reason = TLS_FAIL_NOT_YET_VALID; |
| 7648 | + errmsg = "certificate not yet valid"; |
| 7649 | + } |
| 7650 | + if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) { |
| 7651 | + reason = TLS_FAIL_EXPIRED; |
| 7652 | + errmsg = "certificate has expired"; |
| 7653 | + } |
| 7654 | + if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) { |
| 7655 | + reason = TLS_FAIL_BAD_CERTIFICATE; |
| 7656 | + errmsg = "certificate uses insecure algorithm"; |
| 7657 | + } |
| 7658 | + tls_mbedtls_verify_fail_event(crt, depth, errmsg, reason); |
| 7659 | + } |
| 7660 | + #if 0 |
| 7661 | + /* ??? send (again) cert events for all certs in chain ??? |
| 7662 | + * (should already have been called for greater depths) */ |
| 7663 | + /* tls_openssl.c:tls_verify_cb() sends cert events for all certs |
| 7664 | + * in chain if certificate validation fails, but sends all events |
| 7665 | + * with depth set to 0 (might be a bug) */ |
| 7666 | + if (depth > 0) { |
| 7667 | + int pdepth = depth + 1; |
| 7668 | + for (mbedtls_x509_crt *pcrt; (pcrt = crt->next); ++pdepth) { |
| 7669 | + tls_mbedtls_verify_cert_event(conn, pcrt, pdepth); |
| 7670 | + } |
| 7671 | + } |
| 7672 | + #endif |
| 7673 | + /*(do not preserve subject if verification failed but was optional)*/ |
| 7674 | + if (depth == 0 && conn->peer_subject) { |
| 7675 | + os_free(conn->peer_subject); |
| 7676 | + conn->peer_subject = NULL; |
| 7677 | + } |
| 7678 | + } |
| 7679 | + else if (depth == 0) { |
| 7680 | + struct tls_config *init_conf = &tls_ctx_global.init_conf; |
| 7681 | + if (tls_conf->ca_cert_probe) { |
| 7682 | + /* reject server certificate on probe-only run */ |
| 7683 | + *flags |= MBEDTLS_X509_BADCERT_OTHER; |
| 7684 | + tls_mbedtls_verify_fail_event(crt, depth, |
| 7685 | + "server chain probe", |
| 7686 | + TLS_FAIL_SERVER_CHAIN_PROBE); |
| 7687 | + } |
| 7688 | + else if (init_conf->event_cb) { |
| 7689 | + /* ??? send event as soon as depth == 0 is verified ??? |
| 7690 | + * What about rest of chain? |
| 7691 | + * Follows tls_mbedtls.c behavior: */ |
| 7692 | + init_conf->event_cb(init_conf->cb_ctx, |
| 7693 | + TLS_CERT_CHAIN_SUCCESS, NULL); |
| 7694 | + } |
| 7695 | + } |
| 7696 | + |
| 7697 | + return 0; |
| 7698 | +} |
| 7699 | --- /dev/null |
| 7700 | +++ b/tests/build/build-wpa_supplicant-mbedtls.config |
| 7701 | @@ -0,0 +1,24 @@ |
| 7702 | +CONFIG_TLS=mbedtls |
| 7703 | + |
| 7704 | +CONFIG_WPS=y |
| 7705 | +CONFIG_EAP_TLS=y |
| 7706 | +CONFIG_EAP_MSCHAPV2=y |
| 7707 | + |
| 7708 | +CONFIG_EAP_PSK=y |
| 7709 | +CONFIG_EAP_GPSK=y |
| 7710 | +CONFIG_EAP_AKA=y |
| 7711 | +CONFIG_EAP_SIM=y |
| 7712 | +CONFIG_EAP_SAKE=y |
| 7713 | +CONFIG_EAP_PAX=y |
| 7714 | +CONFIG_EAP_FAST=y |
| 7715 | +CONFIG_EAP_IKEV2=y |
| 7716 | + |
| 7717 | +CONFIG_SAE=y |
| 7718 | +CONFIG_FILS=y |
| 7719 | +CONFIG_FILS_SK_PFS=y |
| 7720 | +CONFIG_OWE=y |
| 7721 | +CONFIG_DPP=y |
| 7722 | +CONFIG_SUITEB=y |
| 7723 | +CONFIG_SUITEB192=y |
| 7724 | + |
| 7725 | +CFLAGS += -Werror |
| 7726 | --- a/tests/hwsim/example-hostapd.config |
| 7727 | +++ b/tests/hwsim/example-hostapd.config |
| 7728 | @@ -4,6 +4,7 @@ CONFIG_DRIVER_NONE=y |
| 7729 | CONFIG_DRIVER_NL80211=y |
| 7730 | CONFIG_RSN_PREAUTH=y |
| 7731 | |
| 7732 | +#CONFIG_TLS=mbedtls |
| 7733 | #CONFIG_TLS=internal |
| 7734 | #CONFIG_INTERNAL_LIBTOMMATH=y |
| 7735 | #CONFIG_INTERNAL_LIBTOMMATH_FAST=y |
| 7736 | @@ -39,6 +40,9 @@ endif |
| 7737 | ifeq ($(CONFIG_TLS), wolfssl) |
| 7738 | CONFIG_EAP_PWD=y |
| 7739 | endif |
| 7740 | +ifeq ($(CONFIG_TLS), mbedtls) |
| 7741 | +CONFIG_EAP_PWD=y |
| 7742 | +endif |
| 7743 | CONFIG_EAP_EKE=y |
| 7744 | CONFIG_PKCS12=y |
| 7745 | CONFIG_RADIUS_SERVER=y |
| 7746 | --- a/tests/hwsim/example-wpa_supplicant.config |
| 7747 | +++ b/tests/hwsim/example-wpa_supplicant.config |
| 7748 | @@ -2,6 +2,7 @@ |
| 7749 | |
| 7750 | CONFIG_TLS=openssl |
| 7751 | #CONFIG_TLS=wolfssl |
| 7752 | +#CONFIG_TLS=mbedtls |
| 7753 | #CONFIG_TLS=internal |
| 7754 | #CONFIG_INTERNAL_LIBTOMMATH=y |
| 7755 | #CONFIG_INTERNAL_LIBTOMMATH_FAST=y |
| 7756 | @@ -41,6 +42,9 @@ endif |
| 7757 | ifeq ($(CONFIG_TLS), wolfssl) |
| 7758 | CONFIG_EAP_PWD=y |
| 7759 | endif |
| 7760 | +ifeq ($(CONFIG_TLS), mbedtls) |
| 7761 | +CONFIG_EAP_PWD=y |
| 7762 | +endif |
| 7763 | |
| 7764 | CONFIG_USIM_SIMULATOR=y |
| 7765 | CONFIG_SIM_SIMULATOR=y |
| 7766 | --- a/wpa_supplicant/Makefile |
| 7767 | +++ b/wpa_supplicant/Makefile |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7768 | @@ -1163,6 +1163,29 @@ endif |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7769 | CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" |
| 7770 | endif |
| 7771 | |
| 7772 | +ifeq ($(CONFIG_TLS), mbedtls) |
| 7773 | +ifndef CONFIG_CRYPTO |
| 7774 | +CONFIG_CRYPTO=mbedtls |
| 7775 | +endif |
| 7776 | +ifdef TLS_FUNCS |
| 7777 | +OBJS += ../src/crypto/tls_mbedtls.o |
| 7778 | +LIBS += -lmbedtls -lmbedx509 |
| 7779 | +endif |
| 7780 | +OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o |
| 7781 | +OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o |
| 7782 | +OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o |
| 7783 | +ifdef NEED_FIPS186_2_PRF |
| 7784 | +OBJS += ../src/crypto/fips_prf_internal.o |
| 7785 | +SHA1OBJS += ../src/crypto/sha1-internal.o |
| 7786 | +endif |
| 7787 | +ifeq ($(CONFIG_CRYPTO), mbedtls) |
| 7788 | +LIBS += -lmbedcrypto |
| 7789 | +LIBS_p += -lmbedcrypto |
| 7790 | +# XXX: create a config option? |
| 7791 | +CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 |
| 7792 | +endif |
| 7793 | +endif |
| 7794 | + |
| 7795 | ifeq ($(CONFIG_TLS), gnutls) |
| 7796 | ifndef CONFIG_CRYPTO |
| 7797 | # default to libgcrypt |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7798 | @@ -1355,9 +1378,11 @@ endif |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7799 | |
| 7800 | ifneq ($(CONFIG_TLS), openssl) |
| 7801 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7802 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7803 | NEED_INTERNAL_AES_WRAP=y |
| 7804 | endif |
| 7805 | endif |
| 7806 | +endif |
| 7807 | ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP |
| 7808 | # Seems to be needed at least with BoringSSL |
| 7809 | NEED_INTERNAL_AES_WRAP=y |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7810 | @@ -1371,9 +1396,11 @@ endif |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7811 | |
| 7812 | ifdef NEED_INTERNAL_AES_WRAP |
| 7813 | ifneq ($(CONFIG_TLS), linux) |
| 7814 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7815 | AESOBJS += ../src/crypto/aes-unwrap.o |
| 7816 | endif |
| 7817 | endif |
| 7818 | +endif |
| 7819 | ifdef NEED_AES_EAX |
| 7820 | AESOBJS += ../src/crypto/aes-eax.o |
| 7821 | NEED_AES_CTR=y |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7822 | @@ -1383,35 +1410,45 @@ AESOBJS += ../src/crypto/aes-siv.o |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7823 | NEED_AES_CTR=y |
| 7824 | endif |
| 7825 | ifdef NEED_AES_CTR |
| 7826 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7827 | AESOBJS += ../src/crypto/aes-ctr.o |
| 7828 | endif |
| 7829 | +endif |
| 7830 | ifdef NEED_AES_ENCBLOCK |
| 7831 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7832 | AESOBJS += ../src/crypto/aes-encblock.o |
| 7833 | endif |
| 7834 | +endif |
| 7835 | NEED_AES_ENC=y |
| 7836 | ifneq ($(CONFIG_TLS), openssl) |
| 7837 | ifneq ($(CONFIG_TLS), linux) |
| 7838 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7839 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7840 | AESOBJS += ../src/crypto/aes-omac1.o |
| 7841 | endif |
| 7842 | endif |
| 7843 | endif |
| 7844 | +endif |
| 7845 | ifdef NEED_AES_WRAP |
| 7846 | NEED_AES_ENC=y |
| 7847 | ifdef NEED_INTERNAL_AES_WRAP |
| 7848 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7849 | AESOBJS += ../src/crypto/aes-wrap.o |
| 7850 | endif |
| 7851 | endif |
| 7852 | +endif |
| 7853 | ifdef NEED_AES_CBC |
| 7854 | NEED_AES_ENC=y |
| 7855 | ifneq ($(CONFIG_TLS), openssl) |
| 7856 | ifneq ($(CONFIG_TLS), linux) |
| 7857 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7858 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7859 | AESOBJS += ../src/crypto/aes-cbc.o |
| 7860 | endif |
| 7861 | endif |
| 7862 | endif |
| 7863 | endif |
| 7864 | +endif |
| 7865 | ifdef NEED_AES_ENC |
| 7866 | ifdef CONFIG_INTERNAL_AES |
| 7867 | AESOBJS += ../src/crypto/aes-internal-enc.o |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7868 | @@ -1426,12 +1463,16 @@ ifneq ($(CONFIG_TLS), openssl) |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7869 | ifneq ($(CONFIG_TLS), linux) |
| 7870 | ifneq ($(CONFIG_TLS), gnutls) |
| 7871 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7872 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7873 | SHA1OBJS += ../src/crypto/sha1.o |
| 7874 | endif |
| 7875 | endif |
| 7876 | endif |
| 7877 | endif |
| 7878 | +endif |
| 7879 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7880 | SHA1OBJS += ../src/crypto/sha1-prf.o |
| 7881 | +endif |
| 7882 | ifdef CONFIG_INTERNAL_SHA1 |
| 7883 | SHA1OBJS += ../src/crypto/sha1-internal.o |
| 7884 | ifdef NEED_FIPS186_2_PRF |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7885 | @@ -1443,29 +1484,37 @@ CFLAGS += -DCONFIG_NO_PBKDF2 |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7886 | else |
| 7887 | ifneq ($(CONFIG_TLS), openssl) |
| 7888 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7889 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7890 | SHA1OBJS += ../src/crypto/sha1-pbkdf2.o |
| 7891 | endif |
| 7892 | endif |
| 7893 | endif |
| 7894 | +endif |
| 7895 | ifdef NEED_T_PRF |
| 7896 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7897 | SHA1OBJS += ../src/crypto/sha1-tprf.o |
| 7898 | endif |
| 7899 | +endif |
| 7900 | ifdef NEED_TLS_PRF |
| 7901 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7902 | SHA1OBJS += ../src/crypto/sha1-tlsprf.o |
| 7903 | endif |
| 7904 | endif |
| 7905 | +endif |
| 7906 | |
| 7907 | ifndef CONFIG_FIPS |
| 7908 | ifneq ($(CONFIG_TLS), openssl) |
| 7909 | ifneq ($(CONFIG_TLS), linux) |
| 7910 | ifneq ($(CONFIG_TLS), gnutls) |
| 7911 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7912 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7913 | MD5OBJS += ../src/crypto/md5.o |
| 7914 | endif |
| 7915 | endif |
| 7916 | endif |
| 7917 | endif |
| 7918 | endif |
| 7919 | +endif |
| 7920 | ifdef NEED_MD5 |
| 7921 | ifdef CONFIG_INTERNAL_MD5 |
| 7922 | MD5OBJS += ../src/crypto/md5-internal.o |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7923 | @@ -1520,12 +1569,17 @@ ifneq ($(CONFIG_TLS), openssl) |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7924 | ifneq ($(CONFIG_TLS), linux) |
| 7925 | ifneq ($(CONFIG_TLS), gnutls) |
| 7926 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7927 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7928 | SHA256OBJS += ../src/crypto/sha256.o |
| 7929 | endif |
| 7930 | endif |
| 7931 | endif |
| 7932 | endif |
| 7933 | +endif |
| 7934 | + |
| 7935 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7936 | SHA256OBJS += ../src/crypto/sha256-prf.o |
| 7937 | +endif |
| 7938 | ifdef CONFIG_INTERNAL_SHA256 |
| 7939 | SHA256OBJS += ../src/crypto/sha256-internal.o |
| 7940 | endif |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 7941 | @@ -1538,50 +1592,68 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512 |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 7942 | SHA256OBJS += ../src/crypto/sha512-internal.o |
| 7943 | endif |
| 7944 | ifdef NEED_TLS_PRF_SHA256 |
| 7945 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7946 | SHA256OBJS += ../src/crypto/sha256-tlsprf.o |
| 7947 | endif |
| 7948 | +endif |
| 7949 | ifdef NEED_TLS_PRF_SHA384 |
| 7950 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7951 | SHA256OBJS += ../src/crypto/sha384-tlsprf.o |
| 7952 | endif |
| 7953 | +endif |
| 7954 | ifdef NEED_HMAC_SHA256_KDF |
| 7955 | CFLAGS += -DCONFIG_HMAC_SHA256_KDF |
| 7956 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7957 | OBJS += ../src/crypto/sha256-kdf.o |
| 7958 | endif |
| 7959 | +endif |
| 7960 | ifdef NEED_HMAC_SHA384_KDF |
| 7961 | CFLAGS += -DCONFIG_HMAC_SHA384_KDF |
| 7962 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7963 | OBJS += ../src/crypto/sha384-kdf.o |
| 7964 | endif |
| 7965 | +endif |
| 7966 | ifdef NEED_HMAC_SHA512_KDF |
| 7967 | CFLAGS += -DCONFIG_HMAC_SHA512_KDF |
| 7968 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7969 | OBJS += ../src/crypto/sha512-kdf.o |
| 7970 | endif |
| 7971 | +endif |
| 7972 | OBJS += $(SHA256OBJS) |
| 7973 | ifdef NEED_SHA384 |
| 7974 | ifneq ($(CONFIG_TLS), openssl) |
| 7975 | ifneq ($(CONFIG_TLS), linux) |
| 7976 | ifneq ($(CONFIG_TLS), gnutls) |
| 7977 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7978 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7979 | OBJS += ../src/crypto/sha384.o |
| 7980 | endif |
| 7981 | endif |
| 7982 | endif |
| 7983 | endif |
| 7984 | +endif |
| 7985 | CFLAGS += -DCONFIG_SHA384 |
| 7986 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7987 | OBJS += ../src/crypto/sha384-prf.o |
| 7988 | endif |
| 7989 | +endif |
| 7990 | ifdef NEED_SHA512 |
| 7991 | ifneq ($(CONFIG_TLS), openssl) |
| 7992 | ifneq ($(CONFIG_TLS), linux) |
| 7993 | ifneq ($(CONFIG_TLS), gnutls) |
| 7994 | ifneq ($(CONFIG_TLS), wolfssl) |
| 7995 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 7996 | OBJS += ../src/crypto/sha512.o |
| 7997 | endif |
| 7998 | endif |
| 7999 | endif |
| 8000 | endif |
| 8001 | +endif |
| 8002 | CFLAGS += -DCONFIG_SHA512 |
| 8003 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 8004 | OBJS += ../src/crypto/sha512-prf.o |
| 8005 | endif |
| 8006 | +endif |
| 8007 | |
| 8008 | ifdef NEED_ASN1 |
| 8009 | OBJS += ../src/tls/asn1.o |
developer | 5e0a8d7 | 2023-05-12 18:58:17 +0800 | [diff] [blame] | 8010 | @@ -1756,10 +1828,12 @@ ifdef CONFIG_FIPS |
developer | f2e3f56 | 2022-12-26 19:41:22 +0800 | [diff] [blame] | 8011 | CFLAGS += -DCONFIG_FIPS |
| 8012 | ifneq ($(CONFIG_TLS), openssl) |
| 8013 | ifneq ($(CONFIG_TLS), wolfssl) |
| 8014 | +ifneq ($(CONFIG_TLS), mbedtls) |
| 8015 | $(error CONFIG_FIPS=y requires CONFIG_TLS=openssl) |
| 8016 | endif |
| 8017 | endif |
| 8018 | endif |
| 8019 | +endif |
| 8020 | |
| 8021 | OBJS += $(SHA1OBJS) $(DESOBJS) |
| 8022 | |
| 8023 | --- a/wpa_supplicant/defconfig |
| 8024 | +++ b/wpa_supplicant/defconfig |
| 8025 | @@ -10,8 +10,8 @@ |
| 8026 | # to override previous values of the variables. |
| 8027 | |
| 8028 | |
| 8029 | -# Uncomment following two lines and fix the paths if you have installed OpenSSL |
| 8030 | -# or GnuTLS in non-default location |
| 8031 | +# Uncomment following two lines and fix the paths if you have installed TLS |
| 8032 | +# libraries in a non-default location |
| 8033 | #CFLAGS += -I/usr/local/openssl/include |
| 8034 | #LIBS += -L/usr/local/openssl/lib |
| 8035 | |
| 8036 | @@ -20,6 +20,7 @@ |
| 8037 | # used to fix build issues on such systems (krb5.h not found). |
| 8038 | #CFLAGS += -I/usr/include/kerberos |
| 8039 | |
| 8040 | + |
| 8041 | # Driver interface for generic Linux wireless extensions |
| 8042 | # Note: WEXT is deprecated in the current Linux kernel version and no new |
| 8043 | # functionality is added to it. nl80211-based interface is the new |
| 8044 | @@ -326,6 +327,7 @@ CONFIG_BACKEND=file |
| 8045 | # openssl = OpenSSL (default) |
| 8046 | # gnutls = GnuTLS |
| 8047 | # internal = Internal TLSv1 implementation (experimental) |
| 8048 | +# mbedtls = mbed TLS |
| 8049 | # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental) |
| 8050 | # none = Empty template |
| 8051 | #CONFIG_TLS=openssl |