From: Krishna <krishna.t@xxxxxxxxxxxxx> This is ideal for low footprint embedded systems, the patch adds support for STA mode, the support is minimal, only mandatory stuff is added * DH group19 only for SAE * OWE, DPP and PASN are not supported as ECDH support is yet to be added. * EAP-TEAP is not supported yet This implementation is based on work of ESP team [1], with below changes * decouple from esp_wifi * avoid any changes to core wpa_supplicant (esp. for WPA3) * port to 3.1.0 mbedtls Tested WPA2/WPA3 associations personal/enterprise. Also, add a configuration file with mbedtls for build tests. Code auto-formatted using wpa_supplicant/binder/.clang-format. [1] - https://github.com/espressif/esp-idf/tree/master/components/wpa_supplicant Signed-off-by: Krishna <krishna.t@xxxxxxxxxxxxx> --- hostapd/defconfig | 1 + src/crypto/crypto.h | 2 + src/crypto/crypto_mbedtls-bignum.c | 310 +++++ src/crypto/crypto_mbedtls-ec.c | 935 +++++++++++++ src/crypto/crypto_mbedtls.c | 910 +++++++++++++ src/crypto/tls_mbedtls.c | 1181 +++++++++++++++++ .../build-wpa_supplicant-mbedtls-3.1.0.config | 29 + tests/build/run-build-tests.sh | 7 +- tests/hwsim/test_suite_b.py | 2 +- wpa_supplicant/Makefile | 83 +- wpa_supplicant/defconfig | 1 + 11 files changed, 3454 insertions(+), 7 deletions(-) create mode 100644 src/crypto/crypto_mbedtls-bignum.c create mode 100644 src/crypto/crypto_mbedtls-ec.c create mode 100644 src/crypto/crypto_mbedtls.c create mode 100644 src/crypto/tls_mbedtls.c create mode 100644 tests/build/build-wpa_supplicant-mbedtls-3.1.0.config diff --git a/hostapd/defconfig b/hostapd/defconfig index 666447e4a..fd139eb93 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -269,6 +269,7 @@ CONFIG_IPV6=y # gnutls = GnuTLS # internal = Internal TLSv1 implementation (experimental) # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental) +# mbedtls = Mbed TLS # none = Empty template #CONFIG_TLS=openssl diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index eb600699d..4384fa67a 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -756,6 +756,8 @@ size_t crypto_ec_prime_len(struct crypto_ec *e); */ size_t crypto_ec_prime_len_bits(struct crypto_ec *e); +int crypto_bignum_bits(const struct crypto_bignum *a); + /** * crypto_ec_order_len - Get length of the order in octets * @e: EC context from crypto_ec_init() diff --git a/src/crypto/crypto_mbedtls-bignum.c b/src/crypto/crypto_mbedtls-bignum.c new file mode 100644 index 000000000..e9087b62b --- /dev/null +++ b/src/crypto/crypto_mbedtls-bignum.c @@ -0,0 +1,310 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto.h" +#include "random.h" +#include "sha256.h" +#include "mbedtls/pk.h" +#include "mbedtls/ctr_drbg.h" + +static int f_rng(void *p_rng, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} + +struct crypto_bignum *crypto_bignum_init(void) +{ + + mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi)); + if (bn == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate BN\n", __func__); + return NULL; + } + + mbedtls_mpi_init(bn); + + return (struct crypto_bignum *)bn; +} + +struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len) +{ + int ret = 0; + mbedtls_mpi *bn = os_zalloc(sizeof(mbedtls_mpi)); + if (bn == NULL) { + return NULL; + } + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(bn, buf, len)); + return (struct crypto_bignum *)bn; + +cleanup: + os_free(bn); + return NULL; +} + +int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) +{ + return mbedtls_mpi_random( + (mbedtls_mpi *)r, 0, (mbedtls_mpi *)m, f_rng, NULL); +} + +struct crypto_bignum *crypto_bignum_init_uint(unsigned int val) +{ + return crypto_bignum_init_set((const u8 *)&val, sizeof(val)); +} + +void crypto_bignum_deinit(struct crypto_bignum *n, int clear) +{ + mbedtls_mpi_free((mbedtls_mpi *)n); + os_free((mbedtls_mpi *)n); +} + +int crypto_bignum_to_bin( + const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen) +{ + int num_bytes, offset; + int ret; + + if (padlen > buflen) { + return -1; + } + + num_bytes = mbedtls_mpi_size((mbedtls_mpi *)a); + + if ((size_t)num_bytes > buflen) { + return -1; + } + if (padlen > (size_t)num_bytes) { + offset = padlen - num_bytes; + } else { + offset = 0; + } + + os_memset(buf, 0, offset); + MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary( + (mbedtls_mpi *)a, buf + offset, + mbedtls_mpi_size((mbedtls_mpi *)a))); + + return num_bytes + offset; +cleanup: + return ret; +} + +int crypto_bignum_add( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_add_mpi( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_mod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_mod_mpi( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_exptmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + const struct crypto_bignum *c, struct crypto_bignum *d) +{ + return mbedtls_mpi_exp_mod( + (mbedtls_mpi *)d, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b, (const mbedtls_mpi *)c, NULL) + ? -1 + : 0; +} + +int crypto_bignum_inverse( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_inv_mod( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_sub( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_sub_mpi( + (mbedtls_mpi *)c, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_div( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_div_mpi( + (mbedtls_mpi *)c, NULL, (const mbedtls_mpi *)a, + (const mbedtls_mpi *)b) + ? -1 + : 0; +} + +int crypto_bignum_mulmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + const struct crypto_bignum *c, struct crypto_bignum *d) +{ + int res; + + mbedtls_mpi temp; + mbedtls_mpi_init(&temp); + + res = mbedtls_mpi_mul_mpi( + &temp, (const mbedtls_mpi *)a, (const mbedtls_mpi *)b); + if (res) { + return -1; + } + + res = mbedtls_mpi_mod_mpi((mbedtls_mpi *)d, &temp, (mbedtls_mpi *)c); + mbedtls_mpi_free(&temp); +# + return res ? -1 : 0; +} + +int crypto_bignum_cmp( + const struct crypto_bignum *a, const struct crypto_bignum *b) +{ + return mbedtls_mpi_cmp_mpi( + (const mbedtls_mpi *)a, (const mbedtls_mpi *)b); +} + +int crypto_bignum_bits(const struct crypto_bignum *a) +{ + return mbedtls_mpi_bitlen((const mbedtls_mpi *)a); +} + +int crypto_bignum_is_zero(const struct crypto_bignum *a) +{ + return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0); +} + +int crypto_bignum_is_one(const struct crypto_bignum *a) +{ + return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0); +} + +int crypto_bignum_sqrmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + struct crypto_bignum *c) +{ + return mbedtls_mpi_exp_mod( + (mbedtls_mpi *)c, (mbedtls_mpi *)a, (mbedtls_mpi *)a, + (mbedtls_mpi *)b, NULL); +} + +int crypto_bignum_rshift( + const struct crypto_bignum *a, int n, struct crypto_bignum *r) +{ + + if (mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)) { + return -1; + } + return mbedtls_mpi_shift_r((mbedtls_mpi *)&r, n); +} + +int crypto_bignum_legendre( + const struct crypto_bignum *a, const struct crypto_bignum *p) +{ + mbedtls_mpi exp, tmp; + int res = -2, ret; + + mbedtls_mpi_init(&exp); + mbedtls_mpi_init(&tmp); + + /* exp = (p-1) / 2 */ + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&exp, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &tmp, (const mbedtls_mpi *)a, &exp, (const mbedtls_mpi *)p, NULL)); + + if (mbedtls_mpi_cmp_int(&tmp, 1) == 0) { + res = 1; + } else if ( + mbedtls_mpi_cmp_int(&tmp, 0) == 0 + /* The below check is workaround for the case where HW + * does not behave properly for X ^ A mod M when X is + * power of M. Instead of returning value 0, value M is + * returned.*/ + || mbedtls_mpi_cmp_mpi(&tmp, (const mbedtls_mpi *)p) == 0) { + res = 0; + } else { + res = -1; + } + +cleanup: + mbedtls_mpi_free(&tmp); + mbedtls_mpi_free(&exp); + return res; +} + +int crypto_bignum_to_string( + const struct crypto_bignum *a, u8 *buf, size_t buflen, size_t padlen) +{ + int num_bytes, offset; + size_t outlen; + + if (padlen > buflen) { + return -1; + } + + num_bytes = mbedtls_mpi_size((mbedtls_mpi *)a); + + if (padlen > (size_t)num_bytes) { + offset = padlen - num_bytes; + } else { + offset = 0; + } + + os_memset(buf, 0, offset); + mbedtls_mpi_write_string( + (mbedtls_mpi *)a, 16, (char *)(buf + offset), + mbedtls_mpi_size((mbedtls_mpi *)a), &outlen); + + return outlen; +} + +int crypto_bignum_addmod( + const struct crypto_bignum *a, const struct crypto_bignum *b, + const struct crypto_bignum *c, struct crypto_bignum *d) +{ + struct crypto_bignum *tmp = crypto_bignum_init(); + int ret = -1; + + if (mbedtls_mpi_add_mpi( + (mbedtls_mpi *)tmp, (const mbedtls_mpi *)b, + (const mbedtls_mpi *)c) < 0) + goto fail; + + if (mbedtls_mpi_mod_mpi( + (mbedtls_mpi *)a, (const mbedtls_mpi *)tmp, + (const mbedtls_mpi *)d) < 0) + goto fail; + + ret = 0; +fail: + crypto_bignum_deinit(tmp, 0); + return ret; +} + +void crypto_free_buffer(unsigned char *buf) { os_free(buf); } diff --git a/src/crypto/crypto_mbedtls-ec.c b/src/crypto/crypto_mbedtls-ec.c new file mode 100644 index 000000000..3c61808f6 --- /dev/null +++ b/src/crypto/crypto_mbedtls-ec.c @@ -0,0 +1,935 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto.h" +#include "sha256.h" +#include "crypto/random.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include "mbedtls/pk.h" +#include "mbedtls/ecdh.h" +#include "mbedtls/sha256.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/error.h" +#include "mbedtls/oid.h" +#define IANA_SECP256R1 19 +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES + +#ifdef CONFIG_ECC +static int f_rng(void *p_rng, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} +struct crypto_ec +{ + mbedtls_ecp_group group; +}; + +int crypto_rng_wrapper(void *ctx, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} + +const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.A; +} + +const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.B; +} + +size_t crypto_ec_order_len(struct crypto_ec *e) +{ + return (mbedtls_mpi_bitlen(&e->group.N) + 7) / 8; +} + +struct crypto_ec *crypto_ec_init(int group) +{ + struct crypto_ec *e; + + mbedtls_ecp_group_id grp_id; + + /* IANA registry to mbedtls internal mapping*/ + switch (group) { + case IANA_SECP256R1: + /* For now just support NIST-P256. + * This is of type "short Weierstrass". + */ + grp_id = MBEDTLS_ECP_DP_SECP256R1; + break; + default: + return NULL; + } + e = os_zalloc(sizeof(*e)); + if (e == NULL) { + return NULL; + } + + mbedtls_ecp_group_init(&e->group); + + if (mbedtls_ecp_group_load(&e->group, grp_id)) { + crypto_ec_deinit(e); + e = NULL; + } + + return e; +} + +void crypto_ec_deinit(struct crypto_ec *e) +{ + if (e == NULL) { + return; + } + + mbedtls_ecp_group_free(&e->group); + os_free(e); +} + +struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e) +{ + mbedtls_ecp_point *pt; + if (e == NULL) { + return NULL; + } + + pt = os_zalloc(sizeof(mbedtls_ecp_point)); + + if (pt == NULL) { + return NULL; + } + + mbedtls_ecp_point_init(pt); + + return (struct crypto_ec_point *)pt; +} + +size_t crypto_ec_prime_len(struct crypto_ec *e) +{ + return mbedtls_mpi_size(&e->group.P); +} + +size_t crypto_ec_prime_len_bits(struct crypto_ec *e) +{ + return mbedtls_mpi_bitlen(&e->group.P); +} +struct crypto_ec_group *crypto_ec_get_group_byname(const char *name) +{ + struct crypto_ec *e; + const mbedtls_ecp_curve_info *curve = + mbedtls_ecp_curve_info_from_name(name); + + e = os_zalloc(sizeof(*e)); + if (e == NULL) { + return NULL; + } + + mbedtls_ecp_group_init(&e->group); + + if (mbedtls_ecp_group_load(&e->group, curve->MBEDTLS_PRIVATE(grp_id))) { + crypto_ec_deinit(e); + e = NULL; + } + + return (struct crypto_ec_group *)&e->group; +} + +const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.P; +} + +const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e) +{ + return (const struct crypto_bignum *)&e->group.N; +} + +void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear) +{ + mbedtls_ecp_point_free((mbedtls_ecp_point *)p); + os_free(p); +} + +int crypto_ec_point_to_bin( + struct crypto_ec *e, const struct crypto_ec_point *point, u8 *x, u8 *y) +{ + int len = mbedtls_mpi_size(&e->group.P); + + if (x) { + if (crypto_bignum_to_bin( + (struct crypto_bignum *)&((mbedtls_ecp_point *)point) + ->MBEDTLS_PRIVATE(X), + x, len, len) < 0) { + return -1; + } + } + + if (y) { + if (crypto_bignum_to_bin( + (struct crypto_bignum *)&((mbedtls_ecp_point *)point) + ->MBEDTLS_PRIVATE(Y), + y, len, len) < 0) { + return -1; + } + } + + return 0; +} + +int crypto_ec_get_affine_coordinates( + struct crypto_ec *e, struct crypto_ec_point *pt, struct crypto_bignum *x, + struct crypto_bignum *y) +{ + int ret = -1; + mbedtls_ecp_point *point = (mbedtls_ecp_point *)pt; + + if (!mbedtls_ecp_is_zero(point) && + (mbedtls_mpi_cmp_int(&point->MBEDTLS_PRIVATE(Z), 1) == 0)) { + // Affine coordinates mean that z should be 1, + wpa_printf(MSG_ERROR, "Z coordinate is neither 0 or 1"); + return -1; + } + + if (x) { + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + (mbedtls_mpi *)x, + &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X))); + } + if (y) { + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + (mbedtls_mpi *)y, + &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y))); + } + return 0; +cleanup: + return ret; +} + +int crypto_ec_point_x( + struct crypto_ec *e, const struct crypto_ec_point *p, + struct crypto_bignum *x) +{ + int ret; + + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + (mbedtls_mpi *)x, &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X))); + + return 0; +cleanup: + return ret; +} + +struct crypto_ec_point * +crypto_ec_point_from_bin(struct crypto_ec *e, const u8 *val) +{ + mbedtls_ecp_point *pt; + int len, ret; + + if (e == NULL) { + return NULL; + } + + len = mbedtls_mpi_size(&e->group.P); + + pt = os_zalloc(sizeof(mbedtls_ecp_point)); + if (!pt) { + return NULL; + } + mbedtls_ecp_point_init(pt); + + MBEDTLS_MPI_CHK( + mbedtls_mpi_read_binary(&pt->MBEDTLS_PRIVATE(X), val, len)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_read_binary(&pt->MBEDTLS_PRIVATE(Y), val + len, len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset((&pt->MBEDTLS_PRIVATE(Z)), 1)); + + return (struct crypto_ec_point *)pt; + +cleanup: + mbedtls_ecp_point_free(pt); + os_free(pt); + return NULL; +} + +int crypto_ec_point_add( + struct crypto_ec *e, const struct crypto_ec_point *a, + const struct crypto_ec_point *b, struct crypto_ec_point *c) +{ + int ret; + mbedtls_mpi one; + + mbedtls_mpi_init(&one); + + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&one, 1)); + MBEDTLS_MPI_CHK(mbedtls_ecp_muladd( + &e->group, (mbedtls_ecp_point *)c, &one, + (const mbedtls_ecp_point *)a, &one, (const mbedtls_ecp_point *)b)); + +cleanup: + mbedtls_mpi_free(&one); + return ret ? -1 : 0; +} + +int crypto_ec_point_mul( + struct crypto_ec *e, const struct crypto_ec_point *p, + const struct crypto_bignum *b, struct crypto_ec_point *res) +{ + int ret; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + MBEDTLS_MPI_CHK(mbedtls_ctr_drbg_seed( + &ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)); + + MBEDTLS_MPI_CHK(mbedtls_ecp_mul( + &e->group, (mbedtls_ecp_point *)res, (const mbedtls_mpi *)b, + (const mbedtls_ecp_point *)p, mbedtls_ctr_drbg_random, &ctr_drbg)); +cleanup: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return ret ? -1 : 0; +} + +/* Currently mbedtls does not have any function for inverse + * This function calculates inverse of a point. + * Set R = -P + */ +static int ecp_opp( + const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P) +{ + int ret = 0; + + /* Copy */ + if (R != P) { + MBEDTLS_MPI_CHK(mbedtls_ecp_copy(R, P)); + } + + /* In-place opposite */ + if (mbedtls_mpi_cmp_int(&R->MBEDTLS_PRIVATE(Y), 0) != 0) { + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi( + &R->MBEDTLS_PRIVATE(Y), &grp->P, &R->MBEDTLS_PRIVATE(Y))); + } + +cleanup: + return (ret); +} + +int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p) +{ + return ecp_opp( + &e->group, (mbedtls_ecp_point *)p, (mbedtls_ecp_point *)p) + ? -1 + : 0; +} + +int crypto_ec_point_solve_y_coord( + struct crypto_ec *e, struct crypto_ec_point *p, + const struct crypto_bignum *x, int y_bit) +{ + mbedtls_mpi temp; + mbedtls_mpi *y_sqr, *y; + mbedtls_mpi_init(&temp); + int ret = 0; + + y = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y); + + /* Faster way to find sqrt + * Works only with curves having prime p + * such that p ≡ 3 (mod 4) + * y_ = (y2 ^ ((p+1)/4)) mod p + * + * if LSB of both x and y are same: y = y_ + * else y = p - y_ + * y_bit is LSB of x + */ + y_bit = (y_bit != 0); + + y_sqr = (mbedtls_mpi *)crypto_ec_point_compute_y_sqr(e, x); + + if (y_sqr) { + + MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&temp, &e->group.P, 1)); + MBEDTLS_MPI_CHK(mbedtls_mpi_div_int(&temp, NULL, &temp, 4)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_exp_mod(y, y_sqr, &temp, &e->group.P, NULL)); + + if (y_bit != mbedtls_mpi_get_bit(y, 0)) + MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(y, &e->group.P, y)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_copy( + &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X), + (const mbedtls_mpi *)x)); + MBEDTLS_MPI_CHK(mbedtls_mpi_lset( + &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z), 1)); + } else { + ret = 1; + } +cleanup: + mbedtls_mpi_free(&temp); + mbedtls_mpi_free(y_sqr); + os_free(y_sqr); + return ret ? -1 : 0; +} + +int crypto_get_order(struct crypto_ec_group *group, struct crypto_bignum *x) +{ + return mbedtls_mpi_copy( + (mbedtls_mpi *)x, &((mbedtls_ecp_group *)group)->N); +} + +struct crypto_bignum *crypto_ec_point_compute_y_sqr( + struct crypto_ec *e, const struct crypto_bignum *x) +{ + mbedtls_mpi temp, temp2, num; + int ret = 0; + + mbedtls_mpi *y_sqr = os_zalloc(sizeof(mbedtls_mpi)); + if (y_sqr == NULL) { + return NULL; + } + + mbedtls_mpi_init(&temp); + mbedtls_mpi_init(&temp2); + mbedtls_mpi_init(&num); + mbedtls_mpi_init(y_sqr); + + /* y^2 = x^3 + ax + b mod P*/ + /* mbedtls does not have mod-add or mod-mul apis. + * + */ + + /* Calculate x^3 mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&num, 3)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &temp, (const mbedtls_mpi *)x, &num, &e->group.P, NULL)); + + /* Calculate ax mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&num, -3)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_mul_mpi(&temp2, (const mbedtls_mpi *)x, &num)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P)); + + /* Calculate ax + b mod P. Note that b is already < P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &e->group.B)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&temp2, &temp2, &e->group.P)); + + /* Calculate x^3 + ax + b mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&temp2, &temp2, &temp)); + MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(y_sqr, &temp2, &e->group.P)); + +cleanup: + mbedtls_mpi_free(&temp); + mbedtls_mpi_free(&temp2); + mbedtls_mpi_free(&num); + if (ret) { + mbedtls_mpi_free(y_sqr); + os_free(y_sqr); + return NULL; + } else { + return (struct crypto_bignum *)y_sqr; + } +} + +int crypto_ec_point_is_at_infinity( + struct crypto_ec *e, const struct crypto_ec_point *p) +{ + return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p); +} + +int crypto_ec_point_is_on_curve( + struct crypto_ec *e, const struct crypto_ec_point *p) +{ + mbedtls_mpi y_sqr_lhs, *y_sqr_rhs = NULL, two; + int ret = 0, on_curve = 0; + + mbedtls_mpi_init(&y_sqr_lhs); + mbedtls_mpi_init(&two); + + /* Calculate y^2 mod P*/ + MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&two, 2)); + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &y_sqr_lhs, &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y), + &two, &e->group.P, NULL)); + + y_sqr_rhs = (mbedtls_mpi *)crypto_ec_point_compute_y_sqr( + e, (const struct crypto_bignum *)&((const mbedtls_ecp_point *)p) + ->MBEDTLS_PRIVATE(X)); + + if (y_sqr_rhs && (mbedtls_mpi_cmp_mpi(y_sqr_rhs, &y_sqr_lhs) == 0)) { + on_curve = 1; + } + +cleanup: + mbedtls_mpi_free(&y_sqr_lhs); + mbedtls_mpi_free(&two); + mbedtls_mpi_free(y_sqr_rhs); + os_free(y_sqr_rhs); + return (ret == 0) && (on_curve == 1); +} + +int crypto_ec_point_cmp( + const struct crypto_ec *e, const struct crypto_ec_point *a, + const struct crypto_ec_point *b) +{ + return mbedtls_ecp_point_cmp( + (const mbedtls_ecp_point *)a, (const mbedtls_ecp_point *)b); +} + +void crypto_debug_print_point( + const char *title, struct crypto_ec *e, const struct crypto_ec_point *point) +{ + u8 x[32], y[32]; + + if (crypto_ec_point_to_bin(e, point, x, y) < 0) { + wpa_printf(MSG_ERROR, "error: failed to get corrdinates\n"); + return; + } + + wpa_hexdump(MSG_ERROR, "x:", x, 32); + wpa_hexdump(MSG_ERROR, "y:", y, 32); +} + +static struct crypto_key *crypto_alloc_key(void) +{ + mbedtls_pk_context *key = os_malloc(sizeof(*key)); + + if (!key) { + wpa_printf( + MSG_ERROR, "%s: memory allocation failed\n", __func__); + return NULL; + } + mbedtls_pk_init(key); + + return (struct crypto_key *)key; +} + +void crypto_ec_free_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + mbedtls_pk_free(pkey); + os_free(key); +} + +struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + + return (struct crypto_ec_point *)&mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE( + Q); +} + +int crypto_ec_get_priv_key_der( + struct crypto_key *key, unsigned char **key_data, int *key_len) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + char der_data[ECP_PRV_DER_MAX_BYTES]; + + *key_len = mbedtls_pk_write_key_der( + pkey, (unsigned char *)der_data, ECP_PRV_DER_MAX_BYTES); + if (*key_len <= 0) + return -1; + + *key_data = os_malloc(*key_len); + + if (!*key_data) { + wpa_printf(MSG_ERROR, "memory allocation failed\n"); + return -1; + } + os_memcpy(*key_data, der_data, *key_len); + + return 0; +} + +struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + + return (struct crypto_ec_group *)&( + mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(grp)); +} + +struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + + return ((struct crypto_bignum *)&( + mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(d))); +} + +int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) +{ + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE + 10]; /* tag, length + MPI */ + unsigned char *c = buf + sizeof(buf); + int pk_len = 0; + + memset(buf, 0, sizeof(buf)); + pk_len = mbedtls_pk_write_pubkey(&c, buf, pkey); + + if (pk_len < 0) + return -1; + + if (len == 0) + return pk_len; + + os_memcpy(key_buf, buf + MBEDTLS_MPI_MAX_SIZE + 10 - pk_len, pk_len); + + return pk_len; +} + +int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf) +{ + unsigned char output_buf[1600] = {0}; + int len = mbedtls_pk_write_pubkey_der( + (mbedtls_pk_context *)key, output_buf, 1600); + if (len <= 0) + return 0; + + *key_buf = os_malloc(len); + if (!*key_buf) { + return 0; + } + os_memcpy(*key_buf, output_buf + 1600 - len, len); + + return len; +} + +struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len) +{ + int ret; + mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); + + if (!kctx) { + wpa_printf(MSG_ERROR, "memory allocation failed\n"); + return NULL; + } + ret = mbedtls_pk_parse_key( + kctx, privkey, privkey_len, NULL, 0, f_rng, NULL); + + if (ret < 0) { + // crypto_print_error_string(ret); + goto fail; + } + + return (struct crypto_key *)kctx; + +fail: + mbedtls_pk_free(kctx); + os_free(kctx); + return NULL; +} + +unsigned int crypto_ec_get_mbedtls_to_nist_group_id(int id) +{ + unsigned int nist_grpid = 0; + switch (id) { + case MBEDTLS_ECP_DP_SECP256R1: + nist_grpid = 19; + break; + case MBEDTLS_ECP_DP_SECP384R1: + nist_grpid = 20; + break; + case MBEDTLS_ECP_DP_SECP521R1: + nist_grpid = 21; + break; + case MBEDTLS_ECP_DP_BP256R1: + nist_grpid = 28; + break; + case MBEDTLS_ECP_DP_BP384R1: + nist_grpid = 29; + break; + case MBEDTLS_ECP_DP_BP512R1: + nist_grpid = 30; + break; + default: + break; + } + + return nist_grpid; +} + +int crypto_ec_get_curve_id(const struct crypto_ec_group *group) +{ + mbedtls_ecp_group *grp = (mbedtls_ecp_group *)group; + return (crypto_ec_get_mbedtls_to_nist_group_id(grp->id)); +} + +int crypto_ecdh( + struct crypto_key *key_own, struct crypto_key *key_peer, u8 *secret, + size_t *secret_len) +{ + mbedtls_ecdh_context *ctx; + mbedtls_pk_context *own = (mbedtls_pk_context *)key_own; + mbedtls_pk_context *peer = (mbedtls_pk_context *)key_peer; + + int ret = -1; + + *secret_len = 0; + ctx = os_malloc(sizeof(*ctx)); + if (!ctx) { + wpa_printf( + MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", __func__); + return -1; + } + + mbedtls_ecdh_init(ctx); + /* No need to setup, done through mbedtls_ecdh_get_params */ + + /* set params from our key */ + if (mbedtls_ecdh_get_params( + ctx, mbedtls_pk_ec(*own), MBEDTLS_ECDH_OURS) < 0) { + wpa_printf(MSG_ERROR, "failed to set our ecdh params\n"); + goto fail; + } + +#ifndef DPP_MAX_SHARED_SECRET_LEN +#define DPP_MAX_SHARED_SECRET_LEN 66 +#endif + /* set params from peers key */ + if (mbedtls_ecdh_get_params( + ctx, mbedtls_pk_ec(*peer), MBEDTLS_ECDH_THEIRS) < 0) { + wpa_printf(MSG_ERROR, "failed to set peer's ecdh params\n"); + goto fail; + } + + if (mbedtls_ecdh_calc_secret( + ctx, secret_len, secret, DPP_MAX_SHARED_SECRET_LEN, NULL, + NULL) < 0) { + wpa_printf(MSG_ERROR, "failed to calculate secret\n"); + goto fail; + } + + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + wpa_printf( + MSG_ERROR, "secret len=%ld is too big\n", *secret_len); + goto fail; + } + + ret = 0; + +fail: + mbedtls_ecdh_free(ctx); + os_free(ctx); + return ret; +} + +void crypto_debug_print_ec_key(const char *title, struct crypto_key *key) +{ +#ifdef DEBUG_PRINT + mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; + mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(*pkey); + u8 x[32], y[32], d[32]; + wpa_printf( + MSG_ERROR, "curve: %s\n", + mbedtls_ecp_curve_info_from_grp_id(ecp->grp.id)->name); + int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime( + (struct crypto_ec *)crypto_ec_get_group_from_key(key))); + + wpa_printf(MSG_ERROR, "prime len is %d\n", len); + crypto_ec_point_to_bin( + (struct crypto_ec *)crypto_ec_get_group_from_key(key), + crypto_ec_get_public_key(key), x, y); + crypto_bignum_to_bin(crypto_ec_get_private_key(key), d, len, len); + wpa_hexdump(MSG_ERROR, "Q_x:", x, 32); + wpa_hexdump(MSG_ERROR, "Q_y:", y, 32); + wpa_hexdump(MSG_ERROR, "d: ", d, 32); +#endif +} + +struct crypto_key * +crypto_ec_parse_subpub_key(const unsigned char *p, size_t len) +{ + int ret; + mbedtls_pk_context *pkey = (mbedtls_pk_context *)crypto_alloc_key(); + ret = mbedtls_pk_parse_subpubkey((unsigned char **)&p, p + len, pkey); + + if (ret < 0) { + os_free(pkey); + return NULL; + } + + return (struct crypto_key *)pkey; +} + +int crypto_is_ec_key(struct crypto_key *key) +{ + int ret = + mbedtls_pk_can_do((mbedtls_pk_context *)key, MBEDTLS_PK_ECKEY); + return ret; +} + +struct crypto_key *crypto_ec_gen_keypair(u16 ike_group) +{ + mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); + + if (!kctx) { + wpa_printf( + MSG_ERROR, "%s: memory allocation failed\n", __func__); + return NULL; + } + + if (mbedtls_pk_setup( + kctx, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)) != 0) + goto fail; + + mbedtls_ecp_gen_key( + MBEDTLS_ECP_DP_SECP256R1, + mbedtls_pk_ec(*kctx), // get this from argument + crypto_rng_wrapper, NULL); + + return (struct crypto_key *)kctx; +fail: + mbedtls_pk_free(kctx); + os_free(kctx); + return NULL; +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( + unsigned char **p, unsigned char *start, mbedtls_ecp_keypair *ec) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if ((ret = mbedtls_oid_get_oid_by_ec_grp( + ec->MBEDTLS_PRIVATE(grp).id, &oid, &oid_len)) != 0) + return (ret); + + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); + + return ((int)len); +} + +static int pk_write_ec_pubkey_formatted( + unsigned char **p, unsigned char *start, mbedtls_ecp_keypair *ec, + int format) +{ + int ret; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if ((ret = mbedtls_ecp_point_write_binary( + &ec->MBEDTLS_PRIVATE(grp), &ec->MBEDTLS_PRIVATE(Q), format, + &len, buf, sizeof(buf))) != 0) { + return (ret); + } + + if (*p < start || (size_t)(*p - start) < len) + return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); + + *p -= len; + memcpy(*p, buf, len); + + return ((int)len); +} + +int mbedtls_pk_write_pubkey_formatted( + unsigned char **p, unsigned char *start, const mbedtls_pk_context *key, + int format) +{ + int ret; + size_t len = 0; + + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) + MBEDTLS_ASN1_CHK_ADD( + len, pk_write_ec_pubkey_formatted( + p, start, mbedtls_pk_ec(*key), format)); + else + return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); + + return ((int)len); +} + +int crypto_pk_write_formatted_pubkey_der( + mbedtls_pk_context *key, unsigned char *buf, size_t size, int format) +{ + int ret; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + if (size == 0) + return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_pk_write_pubkey_formatted(&c, buf, key, format)); + + if (c - buf < 1) + return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING)); + + if ((ret = mbedtls_oid_get_oid_by_pk_alg( + mbedtls_pk_get_type(key), &oid, &oid_len)) != 0) { + return (ret); + } + + if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) { + MBEDTLS_ASN1_CHK_ADD( + par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key))); + } + + MBEDTLS_ASN1_CHK_ADD( + len, mbedtls_asn1_write_algorithm_identifier( + &c, buf, oid, oid_len, par_len)); + + MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len)); + MBEDTLS_ASN1_CHK_ADD( + len, + mbedtls_asn1_write_tag( + &c, buf, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); + + return ((int)len); +} + +int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf) +{ + unsigned char output_buf[1600] = {0}; + int len = crypto_pk_write_formatted_pubkey_der( + (mbedtls_pk_context *)key, output_buf, 1600, 1); + if (len <= 0) + return 0; + + *key_buf = os_malloc(len); + if (!*key_buf) { + wpa_printf( + MSG_ERROR, "%s: memory allocation failed\n", __func__); + return 0; + } + os_memcpy(*key_buf, output_buf + 1600 - len, len); + + return len; +} +#endif /* CONFIG_ECC */ diff --git a/src/crypto/crypto_mbedtls.c b/src/crypto/crypto_mbedtls.c new file mode 100644 index 000000000..1fa235dea --- /dev/null +++ b/src/crypto/crypto_mbedtls.c @@ -0,0 +1,910 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "crypto.h" +#include "random.h" +#include "sha256.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/aes.h" +#include "mbedtls/bignum.h" +#include "mbedtls/pkcs5.h" +#include "mbedtls/cmac.h" +#include "mbedtls/nist_kw.h" +#include "mbedtls/des.h" +#include "mbedtls/ccm.h" +#ifdef MBEDTLS_ARC4_C +#include "mbedtls/arc4.h" +#endif + +#include "common.h" +#include "utils/wpabuf.h" +#include "dh_group5.h" +#include "sha1.h" +#include "sha256.h" +#include "md5.h" +#include "aes_wrap.h" +#include "crypto.h" + +static int digest_vector( + mbedtls_md_type_t md_type, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + size_t i; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init(&md_ctx); + + md_info = mbedtls_md_info_from_type(md_type); + if (!md_info) { + wpa_printf(MSG_ERROR, "mbedtls_md_info_from_type() failed"); + return -1; + } + + ret = mbedtls_md_setup(&md_ctx, md_info, 0); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_md_setup() returned error"); + goto cleanup; + } + + ret = mbedtls_md_starts(&md_ctx); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_md_starts returned error"); + goto cleanup; + } + + for (i = 0; i < num_elem; i++) { + ret = mbedtls_md_update(&md_ctx, addr[i], len[i]); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_md_update ret=%d", ret); + goto cleanup; + } + } + + ret = mbedtls_md_finish(&md_ctx, mac); +cleanup: + mbedtls_md_free(&md_ctx); + + return ret; +} + +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_SHA256, num_elem, addr, len, mac); +} + +int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_SHA384, num_elem, addr, len, mac); +} + +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_SHA1, num_elem, addr, len, mac); +} + +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_MD5, num_elem, addr, len, mac); +} + +#ifdef MBEDTLS_MD4_C +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return digest_vector(MBEDTLS_MD_MD4, num_elem, addr, len, mac); +} +#endif + +struct crypto_hash +{ + mbedtls_md_context_t ctx; +}; + +struct crypto_hash * +crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, size_t key_len) +{ + struct crypto_hash *ctx; + mbedtls_md_type_t md_type; + const mbedtls_md_info_t *md_info; + int ret; + + switch (alg) { + case CRYPTO_HASH_ALG_HMAC_MD5: + md_type = MBEDTLS_MD_MD5; + break; + case CRYPTO_HASH_ALG_HMAC_SHA1: + md_type = MBEDTLS_MD_SHA1; + break; + case CRYPTO_HASH_ALG_HMAC_SHA256: + md_type = MBEDTLS_MD_SHA256; + break; + default: + return NULL; + } + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + return NULL; + } + + mbedtls_md_init(&ctx->ctx); + md_info = mbedtls_md_info_from_type(md_type); + if (!md_info) { + os_free(ctx); + return NULL; + } + ret = mbedtls_md_setup(&ctx->ctx, md_info, 1); + if (ret != 0) { + os_free(ctx); + return NULL; + } + mbedtls_md_hmac_starts(&ctx->ctx, key, key_len); + + return ctx; +} + +void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len) +{ + if (ctx == NULL) { + return; + } + mbedtls_md_hmac_update(&ctx->ctx, data, len); +} + +int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) +{ + if (ctx == NULL) { + return -2; + } + + if (mac == NULL || len == NULL) { + mbedtls_md_free(&ctx->ctx); + bin_clear_free(ctx, sizeof(*ctx)); + return 0; + } + mbedtls_md_hmac_finish(&ctx->ctx, mac); + mbedtls_md_free(&ctx->ctx); + bin_clear_free(ctx, sizeof(*ctx)); + + return 0; +} + +static int hmac_vector( + mbedtls_md_type_t md_type, const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + size_t i; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + int ret; + + mbedtls_md_init(&md_ctx); + + md_info = mbedtls_md_info_from_type(md_type); + if (!md_info) { + return -1; + } + + ret = mbedtls_md_setup(&md_ctx, md_info, 1); + if (ret != 0) { + return (ret); + } + + mbedtls_md_hmac_starts(&md_ctx, key, key_len); + + for (i = 0; i < num_elem; i++) { + mbedtls_md_hmac_update(&md_ctx, addr[i], len[i]); + } + + mbedtls_md_hmac_finish(&md_ctx, mac); + + mbedtls_md_free(&md_ctx); + + return 0; +} + +int hmac_sha384_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_SHA384, key, key_len, num_elem, addr, len, mac); +} + +int hmac_sha384( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_sha384_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_sha256_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_SHA256, key, key_len, num_elem, addr, len, mac); +} + +int hmac_sha256( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_md5_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_MD5, key, key_len, num_elem, addr, len, mac); +} + +int hmac_md5( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_sha1_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return hmac_vector( + MBEDTLS_MD_SHA1, key, key_len, num_elem, addr, len, mac); +} + +int hmac_sha1( + const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) +{ + return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); +} + +static void *aes_crypt_init(int mode, const u8 *key, size_t len) +{ + int ret = -1; + mbedtls_aes_context *aes = os_malloc(sizeof(*aes)); + if (!aes) { + return NULL; + } + mbedtls_aes_init(aes); + + if (mode == MBEDTLS_AES_ENCRYPT) { + ret = mbedtls_aes_setkey_enc(aes, key, len * 8); + } else if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_setkey_dec(aes, key, len * 8); + } + if (ret < 0) { + mbedtls_aes_free(aes); + os_free(aes); + wpa_printf( + MSG_ERROR, + "%s: mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec failed", + __func__); + return NULL; + } + + return (void *)aes; +} + +static int aes_crypt(void *ctx, int mode, const u8 *in, u8 *out) +{ + return mbedtls_aes_crypt_ecb((mbedtls_aes_context *)ctx, mode, in, out); +} + +static void aes_crypt_deinit(void *ctx) +{ + mbedtls_aes_free((mbedtls_aes_context *)ctx); + os_free(ctx); +} + +void *aes_encrypt_init(const u8 *key, size_t len) +{ + return aes_crypt_init(MBEDTLS_AES_ENCRYPT, key, len); +} + +int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ + return aes_crypt(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt); +} + +void aes_encrypt_deinit(void *ctx) { return aes_crypt_deinit(ctx); } + +void *aes_decrypt_init(const u8 *key, size_t len) +{ + return aes_crypt_init(MBEDTLS_AES_DECRYPT, key, len); +} + +int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +{ + return aes_crypt(ctx, MBEDTLS_AES_DECRYPT, crypt, plain); +} + +void aes_decrypt_deinit(void *ctx) { return aes_crypt_deinit(ctx); } + +int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + u8 cbc[MBEDTLS_AES_BLOCK_SIZE]; + + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_enc(&ctx, key, 128); + if (ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + os_memcpy(cbc, iv, MBEDTLS_AES_BLOCK_SIZE); + ret = mbedtls_aes_crypt_cbc( + &ctx, MBEDTLS_AES_ENCRYPT, data_len, cbc, data, data); + mbedtls_aes_free(&ctx); + + return ret; +} + +int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) +{ + int ret = 0; + mbedtls_aes_context ctx; + u8 cbc[MBEDTLS_AES_BLOCK_SIZE]; + + mbedtls_aes_init(&ctx); + + ret = mbedtls_aes_setkey_dec(&ctx, key, 128); + if (ret < 0) { + mbedtls_aes_free(&ctx); + return ret; + } + + os_memcpy(cbc, iv, MBEDTLS_AES_BLOCK_SIZE); + ret = mbedtls_aes_crypt_cbc( + &ctx, MBEDTLS_AES_DECRYPT, data_len, cbc, data, data); + mbedtls_aes_free(&ctx); + + return ret; +} + +struct crypto_cipher +{ + mbedtls_cipher_context_t ctx_enc; + mbedtls_cipher_context_t ctx_dec; +}; + +static int crypto_init_cipher_ctx( + mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info, + const u8 *iv, const u8 *key, mbedtls_operation_t operation) +{ + mbedtls_cipher_init(ctx); + int ret; + + ret = mbedtls_cipher_setup(ctx, cipher_info); + if (ret != 0) { + return -1; + } + + if (mbedtls_cipher_setkey( + ctx, key, cipher_info->MBEDTLS_PRIVATE(key_bitlen), + operation) != 0) { + wpa_printf(MSG_ERROR, "mbedtls_cipher_setkey returned error"); + return -1; + } + if (mbedtls_cipher_set_iv( + ctx, iv, cipher_info->MBEDTLS_PRIVATE(iv_size)) != 0) { + wpa_printf(MSG_ERROR, "mbedtls_cipher_set_iv returned error"); + return -1; + } + if (mbedtls_cipher_reset(ctx) != 0) { + wpa_printf(MSG_ERROR, "mbedtls_cipher_reset() returned error"); + return -1; + } + + return 0; +} + +static mbedtls_cipher_type_t +alg_to_mbedtls_cipher(enum crypto_cipher_alg alg, size_t key_len) +{ + switch (alg) { +#ifdef MBEDTLS_ARC4_C + case CRYPTO_CIPHER_ALG_RC4: + return MBEDTLS_CIPHER_ARC4_128; +#endif + case CRYPTO_CIPHER_ALG_AES: + if (key_len == 16) { + return MBEDTLS_CIPHER_AES_128_CBC; + } + if (key_len == 24) { + return MBEDTLS_CIPHER_AES_192_CBC; + } + if (key_len == 32) { + return MBEDTLS_CIPHER_AES_256_CBC; + } + break; +#ifdef MBEDTLS_DES_C + case CRYPTO_CIPHER_ALG_3DES: + return MBEDTLS_CIPHER_DES_EDE3_CBC; + case CRYPTO_CIPHER_ALG_DES: + return MBEDTLS_CIPHER_DES_CBC; +#endif + default: + break; + } + + return MBEDTLS_CIPHER_NONE; +} + +struct crypto_cipher *crypto_cipher_init( + enum crypto_cipher_alg alg, const u8 *iv, const u8 *key, size_t key_len) +{ + struct crypto_cipher *ctx; + mbedtls_cipher_type_t cipher_type; + const mbedtls_cipher_info_t *cipher_info; + + ctx = (struct crypto_cipher *)os_zalloc(sizeof(*ctx)); + if (!ctx) { + return NULL; + } + + cipher_type = alg_to_mbedtls_cipher(alg, key_len); + if (cipher_type == MBEDTLS_CIPHER_NONE) { + goto cleanup; + } + + cipher_info = mbedtls_cipher_info_from_type(cipher_type); + if (cipher_info == NULL) { + goto cleanup; + } + + /* Init both ctx encryption/decryption */ + if (crypto_init_cipher_ctx( + &ctx->ctx_enc, cipher_info, iv, key, MBEDTLS_ENCRYPT) < 0) { + goto cleanup; + } + + if (crypto_init_cipher_ctx( + &ctx->ctx_dec, cipher_info, iv, key, MBEDTLS_DECRYPT) < 0) { + goto cleanup; + } + + return ctx; + +cleanup: + os_free(ctx); + return NULL; +} + +int crypto_cipher_encrypt( + struct crypto_cipher *ctx, const u8 *plain, u8 *crypt, size_t len) +{ + int ret; + size_t olen = 1200; + + ret = mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen); + if (ret != 0) { + return -1; + } + + ret = mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen); + if (ret != 0) { + return -1; + } + + return 0; +} + +int crypto_cipher_decrypt( + struct crypto_cipher *ctx, const u8 *crypt, u8 *plain, size_t len) +{ + int ret; + size_t olen = 1200; + + ret = mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen); + if (ret != 0) { + return -1; + } + + ret = mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen); + if (ret != 0) { + return -1; + } + + return 0; +} + +void crypto_cipher_deinit(struct crypto_cipher *ctx) +{ + mbedtls_cipher_free(&ctx->ctx_enc); + mbedtls_cipher_free(&ctx->ctx_dec); + os_free(ctx); +} + +int aes_ctr_encrypt( + const u8 *key, size_t key_len, const u8 *nonce, u8 *data, size_t data_len) +{ + int ret; + mbedtls_aes_context ctx; + uint8_t stream_block[MBEDTLS_AES_BLOCK_SIZE]; + size_t offset = 0; + + mbedtls_aes_init(&ctx); + ret = mbedtls_aes_setkey_enc(&ctx, key, key_len * 8); + if (ret < 0) { + goto cleanup; + } + ret = mbedtls_aes_crypt_ctr( + &ctx, data_len, &offset, (u8 *)nonce, stream_block, data, data); +cleanup: + mbedtls_aes_free(&ctx); + return ret; +} + +int aes_128_ctr_encrypt( + const u8 *key, const u8 *nonce, u8 *data, size_t data_len) +{ + return aes_ctr_encrypt(key, 16, nonce, data, data_len); +} + +#ifdef MBEDTLS_NIST_KW_C +int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) +{ + mbedtls_nist_kw_context ctx; + size_t olen; + int ret = 0; + mbedtls_nist_kw_init(&ctx); + + ret = mbedtls_nist_kw_setkey( + &ctx, MBEDTLS_CIPHER_ID_AES, kek, kek_len * 8, 1); + if (ret != 0) { + return ret; + } + + ret = mbedtls_nist_kw_wrap( + &ctx, MBEDTLS_KW_MODE_KW, plain, n * 8, cipher, &olen, (n + 1) * 8); + + mbedtls_nist_kw_free(&ctx); + return ret; +} + +int aes_unwrap( + const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain) +{ + mbedtls_nist_kw_context ctx; + size_t olen; + int ret = 0; + mbedtls_nist_kw_init(&ctx); + + ret = mbedtls_nist_kw_setkey( + &ctx, MBEDTLS_CIPHER_ID_AES, kek, kek_len * 8, 0); + if (ret != 0) { + return ret; + } + + ret = mbedtls_nist_kw_unwrap( + &ctx, MBEDTLS_KW_MODE_KW, cipher, (n + 1) * 8, plain, &olen, + (n * 8)); + + mbedtls_nist_kw_free(&ctx); + return ret; +} +#endif + +int crypto_mod_exp( + const uint8_t *base, size_t base_len, const uint8_t *power, + size_t power_len, const uint8_t *modulus, size_t modulus_len, + uint8_t *result, size_t *result_len) +{ + mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result, bn_rinv; + int ret = 0; + + mbedtls_mpi_init(&bn_base); + mbedtls_mpi_init(&bn_exp); + mbedtls_mpi_init(&bn_modulus); + mbedtls_mpi_init(&bn_result); + mbedtls_mpi_init(&bn_rinv); + + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&bn_base, base, base_len)); + MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&bn_exp, power, power_len)); + MBEDTLS_MPI_CHK( + mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len)); + + MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod( + &bn_result, &bn_base, &bn_exp, &bn_modulus, &bn_rinv)); + + ret = mbedtls_mpi_write_binary(&bn_result, result, *result_len); + +cleanup: + mbedtls_mpi_free(&bn_base); + mbedtls_mpi_free(&bn_exp); + mbedtls_mpi_free(&bn_modulus); + mbedtls_mpi_free(&bn_result); + mbedtls_mpi_free(&bn_rinv); + + return ret; +} + +int pbkdf2_sha1( + const char *passphrase, const u8 *ssid, size_t ssid_len, int iterations, + u8 *buf, size_t buflen) +{ + + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret; + + mbedtls_md_init(&sha1_ctx); + + info_sha1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); + if (info_sha1 == NULL) { + ret = -1; + goto cleanup; + } + + if ((ret = mbedtls_md_setup(&sha1_ctx, info_sha1, 1)) != 0) { + ret = -1; + goto cleanup; + } + + ret = mbedtls_pkcs5_pbkdf2_hmac( + &sha1_ctx, (const u8 *)passphrase, os_strlen(passphrase), ssid, + ssid_len, iterations, 32, buf); + if (ret != 0) { + ret = -1; + goto cleanup; + } + +cleanup: + mbedtls_md_free(&sha1_ctx); + return ret; +} + +#ifdef MBEDTLS_DES_C +int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) +{ + int ret; + mbedtls_des_context des; + u8 pkey[8], next, tmp; + int i; + + /* Add parity bits to the key */ + next = 0; + for (i = 0; i < 7; i++) { + tmp = key[i]; + pkey[i] = (tmp >> i) | next | 1; + next = tmp << (7 - i); + } + pkey[i] = next | 1; + + mbedtls_des_init(&des); + ret = mbedtls_des_setkey_enc(&des, pkey); + if (ret < 0) { + return ret; + } + ret = mbedtls_des_crypt_ecb(&des, clear, cypher); + mbedtls_des_free(&des); + + return ret; +} +#endif + +/* Only enable this if all other ciphers are using MbedTLS implementation */ +#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CMAC_C) && \ + defined(MBEDTLS_NIST_KW_C) +int aes_ccm_ae( + const u8 *key, size_t key_len, const u8 *nonce, size_t M, const u8 *plain, + size_t plain_len, const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth) +{ + int ret; + mbedtls_ccm_context ccm; + + mbedtls_ccm_init(&ccm); + + ret = mbedtls_ccm_setkey(&ccm, MBEDTLS_CIPHER_ID_AES, key, key_len * 8); + if (ret < 0) { + wpa_printf(MSG_ERROR, "mbedtls_ccm_setkey failed"); + goto cleanup; + } + + ret = mbedtls_ccm_encrypt_and_tag( + &ccm, plain_len, nonce, 13, aad, aad_len, plain, crypt, auth, M); + +cleanup: + mbedtls_ccm_free(&ccm); + + return ret; +} + +int aes_ccm_ad( + const u8 *key, size_t key_len, const u8 *nonce, size_t M, const u8 *crypt, + size_t crypt_len, const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain) +{ + int ret; + mbedtls_ccm_context ccm; + + mbedtls_ccm_init(&ccm); + + ret = mbedtls_ccm_setkey(&ccm, MBEDTLS_CIPHER_ID_AES, key, key_len * 8); + if (ret < 0) { + goto cleanup; + ; + } + + ret = mbedtls_ccm_star_auth_decrypt( + &ccm, crypt_len, nonce, 13, aad, aad_len, crypt, plain, auth, M); + +cleanup: + mbedtls_ccm_free(&ccm); + + return ret; +} +#endif + +#ifdef MBEDTLS_ARC4_C +int rc4_skip( + const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len) +{ + int ret; + unsigned char skip_buf_in[16]; + unsigned char skip_buf_out[16]; + mbedtls_arc4_context ctx; + unsigned char *obuf = os_malloc(data_len); + + if (!obuf) { + wpa_printf(MSG_ERROR, "%s:memory allocation failed", __func__); + return -1; + } + mbedtls_arc4_init(&ctx); + mbedtls_arc4_setup(&ctx, key, keylen); + while (skip >= sizeof(skip_buf_in)) { + size_t len = skip; + if (len > sizeof(skip_buf_in)) { + len = sizeof(skip_buf_in); + } + if ((ret = mbedtls_arc4_crypt( + &ctx, len, skip_buf_in, skip_buf_out)) != 0) { + wpa_printf(MSG_ERROR, "rc4 encryption failed"); + return -1; + } + os_memcpy(skip_buf_in, skip_buf_out, 16); + skip -= len; + } + + mbedtls_arc4_crypt(&ctx, data_len, data, obuf); + + memcpy(data, obuf, data_len); + os_free(obuf); + + return 0; +} +#endif + +#ifdef MBEDTLS_CMAC_C +int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); +} + +int omac1_aes_vector( + const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + mbedtls_cipher_type_t cipher_type; + mbedtls_cipher_context_t ctx; + + switch (key_len) { + case 16: + cipher_type = MBEDTLS_CIPHER_AES_128_ECB; + break; + case 24: + cipher_type = MBEDTLS_CIPHER_AES_192_ECB; + break; + case 32: + cipher_type = MBEDTLS_CIPHER_AES_256_ECB; + break; + default: + cipher_type = MBEDTLS_CIPHER_NONE; + break; + } + cipher_info = mbedtls_cipher_info_from_type(cipher_type); + if (cipher_info == NULL) { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto cleanup; + } + + if (key == NULL || mac == NULL) { + return -1; + } + + mbedtls_cipher_init(&ctx); + + ret = mbedtls_cipher_setup(&ctx, cipher_info); + if (ret != 0) { + goto cleanup; + } + + ret = mbedtls_cipher_cmac_starts(&ctx, key, key_len * 8); + if (ret != 0) { + goto cleanup; + } + + for (i = 0; i < num_elem; i++) { + ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]); + if (ret != 0) { + goto cleanup; + } + } + + ret = mbedtls_cipher_cmac_finish(&ctx, mac); +cleanup: + mbedtls_cipher_free(&ctx); + return (ret); +} + +int omac1_aes_128_vector( + const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + return omac1_aes_vector(key, 16, num_elem, addr, len, mac); +} + +int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_128_vector(key, 1, &data, &data_len, mac); +} +#endif + +int crypto_bignum_is_odd(const struct crypto_bignum *a) +{ + return mbedtls_mpi_get_bit((mbedtls_mpi *)a, 0); +} + +int crypto_dh_derive_secret( + u8 generator, const u8 *prime, size_t prime_len, const u8 *order, + size_t order_len, const u8 *privkey, size_t privkey_len, const u8 *pubkey, + size_t pubkey_len, u8 *secret, size_t *len) +{ + return crypto_mod_exp( + prime, prime_len, privkey, privkey_len, pubkey, pubkey_len, secret, + len); +} + +int crypto_dh_init( + u8 generator, const u8 *prime, size_t prime_len, u8 *privkey, u8 *pubkey) +{ + size_t pubkey_len, pad; + + if (os_get_random(privkey, prime_len) < 0) { + return -1; + } + if (os_memcmp(privkey, prime, prime_len) > 0) { + /* Make sure private value is smaller than prime */ + privkey[0] = 0; + } + + pubkey_len = prime_len; + if (crypto_mod_exp( + &generator, 1, privkey, prime_len, prime, prime_len, pubkey, + &pubkey_len) < 0) { + return -1; + } + if (pubkey_len < prime_len) { + pad = prime_len - pubkey_len; + os_memmove(pubkey + pad, pubkey, pubkey_len); + os_memset(pubkey, 0, pad); + } + + return 0; +} diff --git a/src/crypto/tls_mbedtls.c b/src/crypto/tls_mbedtls.c new file mode 100644 index 000000000..be24e1a9d --- /dev/null +++ b/src/crypto/tls_mbedtls.c @@ -0,0 +1,1181 @@ +/* + * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "utils/includes.h" +#include "utils/common.h" + +#include "tls.h" +#include "crypto/sha1.h" +#include "crypto/md5.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "random.h" +#include <mbedtls/ssl.h> +#include <mbedtls/x509_crt.h> +#include <mbedtls/ctr_drbg.h> +#include <mbedtls/entropy.h> +#include <mbedtls/debug.h> +#include <mbedtls/mbedtls_config.h> +#include <assert.h> + +#define TLS_RANDOM_LEN 32 +#define TLS_MASTER_SECRET_LEN 48 +#define MAX_CIPHERSUITE 32 + +/* Throw a compilation error if basic requirements in mbedtls are not enabled */ +#if !defined(MBEDTLS_SSL_TLS_C) +#error "TLS not enabled in mbedtls config" +#endif + +#if !defined(MBEDTLS_SHA256_C) +#error "SHA256 is disabled in mbedtls config" +#endif + +#if !defined(MBEDTLS_AES_C) +#error "AES support is disabled in mbedtls config" +#endif + +uint32_t tls_instance_count; +struct tls_data +{ + /* Data for mbedlts */ + struct wpabuf *in_data; + /* Data from mbedtls */ + struct wpabuf *out_data; +}; + +mbedtls_ssl_export_keys_t tls_connection_export_keys_cb; + +typedef struct tls_context +{ + mbedtls_ssl_context ssl; /*!< TLS/SSL context */ + mbedtls_entropy_context + entropy; /*!< mbedTLS entropy context structure */ + mbedtls_ctr_drbg_context + ctr_drbg; /*!< mbedTLS ctr drbg context structure */ + mbedtls_ssl_config conf; /*!< TLS/SSL config to be shared structures */ + mbedtls_x509_crt cacert; /*!< Container for X.509 CA certificate */ + mbedtls_x509_crt *cacert_ptr; /*!< Pointer to the cacert being used. */ + mbedtls_x509_crt + clientcert; /*!< Container for X.509 client certificate */ + mbedtls_pk_context clientkey; /*!< Private key of client certificate */ + int ciphersuite[MAX_CIPHERSUITE]; +} tls_context_t; + +struct tls_connection +{ + tls_context_t *tls; + struct tls_data tls_io_data; + unsigned char master_secret[TLS_MASTER_SECRET_LEN]; + unsigned char randbytes[2 * TLS_RANDOM_LEN]; + mbedtls_tls_prf_types tls_prf_type; +}; + +static int f_rng(void *p_rng, unsigned char *buf, size_t len) +{ + return random_get_bytes(buf, len); +} + +static void tls_mbedtls_cleanup(tls_context_t *tls) +{ + if (!tls) { + return; + } + tls->cacert_ptr = NULL; + mbedtls_x509_crt_free(&tls->cacert); + mbedtls_x509_crt_free(&tls->clientcert); + mbedtls_pk_free(&tls->clientkey); + mbedtls_entropy_free(&tls->entropy); + mbedtls_ssl_config_free(&tls->conf); + mbedtls_ctr_drbg_free(&tls->ctr_drbg); + mbedtls_ssl_free(&tls->ssl); +} + +static void tls_mbedtls_conn_delete(tls_context_t *tls) +{ + if (tls != NULL) { + tls_mbedtls_cleanup(tls); + } +} + +static int tls_mbedtls_write(void *ctx, const unsigned char *buf, size_t len) +{ + struct tls_connection *conn = (struct tls_connection *)ctx; + struct tls_data *data = &conn->tls_io_data; + + if (wpabuf_resize(&data->out_data, len) < 0) + return 0; + + wpabuf_put_data(data->out_data, buf, len); + + return len; +} + +static int tls_mbedtls_read(void *ctx, unsigned char *buf, size_t len) +{ + struct tls_connection *conn = (struct tls_connection *)ctx; + struct tls_data *data = &conn->tls_io_data; + struct wpabuf *local_buf; + size_t data_len = len; + + if (data->in_data == NULL) { + return MBEDTLS_ERR_SSL_WANT_READ; + } + + if (len > wpabuf_len(data->in_data)) { + wpa_printf(MSG_ERROR, "don't have suffient data\n"); + data_len = wpabuf_len(data->in_data); + } + + os_memcpy(buf, wpabuf_head(data->in_data), data_len); + /* adjust buffer */ + if (len < wpabuf_len(data->in_data)) { + local_buf = wpabuf_alloc_copy( + (char *)wpabuf_head(data->in_data) + data_len, + wpabuf_len(data->in_data) - data_len); + wpabuf_free(data->in_data); + data->in_data = local_buf; + } else { + wpabuf_free(data->in_data); + data->in_data = NULL; + } + + return data_len; +} + +static int +set_pki_context(tls_context_t *tls, const struct tls_connection_params *cfg) +{ + int ret; + + if (cfg->client_cert_blob == NULL || cfg->private_key_blob == NULL) { + wpa_printf(MSG_ERROR, "%s: config not correct", __func__); + return -1; + } + + mbedtls_x509_crt_init(&tls->clientcert); + mbedtls_pk_init(&tls->clientkey); + + ret = mbedtls_x509_crt_parse( + &tls->clientcert, cfg->client_cert_blob, cfg->client_cert_blob_len); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret); + return ret; + } + + ret = mbedtls_pk_parse_key( + &tls->clientkey, cfg->private_key_blob, cfg->private_key_blob_len, + (const unsigned char *)cfg->private_key_passwd, + cfg->private_key_passwd ? os_strlen(cfg->private_key_passwd) : 0, + f_rng, NULL); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_pk_parse_keyfile returned -0x%x", -ret); + return ret; + } + + ret = mbedtls_ssl_conf_own_cert( + &tls->conf, &tls->clientcert, &tls->clientkey); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_ssl_conf_own_cert returned -0x%x", + -ret); + return ret; + } + + return 0; +} + +static int +set_ca_cert(tls_context_t *tls, const unsigned char *cacert, size_t cacert_len) +{ + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + int ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cacert, cacert_len); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_x509_crt_parse returned -0x%x", -ret); + return ret; + } + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + + return 0; +} + +#ifdef CONFIG_SUITEB192 +static int tls_sig_hashes_for_suiteb[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA384, +#endif + MBEDTLS_MD_NONE}; + +const mbedtls_x509_crt_profile suiteb_mbedtls_x509_crt_profile = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | +#endif + 0, + 0xFFFFFFF, /* Any PK alg */ + MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1), + 1024, +}; + +static void tls_set_suiteb_config(tls_context_t *tls) +{ + const mbedtls_x509_crt_profile *crt_profile = + &suiteb_mbedtls_x509_crt_profile; + mbedtls_ssl_conf_cert_profile(&tls->conf, crt_profile); + mbedtls_ssl_conf_sig_hashes(&tls->conf, tls_sig_hashes_for_suiteb); +} +#endif + +static int tls_sig_hashes_for_eap[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE}; + +const mbedtls_x509_crt_profile eap_mbedtls_x509_crt_profile = { +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | +#endif +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | + MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512) | +#endif + 0, + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 1024, +}; + +static void tls_enable_sha1_config(tls_context_t *tls) +{ + const mbedtls_x509_crt_profile *crt_profile = + &eap_mbedtls_x509_crt_profile; + mbedtls_ssl_conf_cert_profile(&tls->conf, crt_profile); + mbedtls_ssl_conf_sig_hashes(&tls->conf, tls_sig_hashes_for_eap); +} + +static const int eap_ciphersuite_preference[] = { +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA, +#endif +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, +#endif + +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8, +#endif +#endif +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8, + + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8, +#endif +#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_256_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8, +#endif + +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_128_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8, +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, +#endif +/* The PSK suites */ +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_256_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, + MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8, +#endif + +#if defined(MBEDTLS_GCM_C) + MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_128_CCM, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, + MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, +#endif +#if defined(MBEDTLS_CCM_C) + MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8, +#endif +#endif + +#if 0 + /* 3DES suites */ + MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, + MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA, +#endif +#if defined(MBEDTLS_ARC4_C) + /* RC4 suites */ + MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA, MBEDTLS_TLS_RSA_WITH_RC4_128_SHA, + MBEDTLS_TLS_RSA_WITH_RC4_128_MD5, MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA, + MBEDTLS_TLS_PSK_WITH_RC4_128_SHA, +#endif + 0}; + +#ifdef CONFIG_SUITEB192 +static const int suiteb_rsa_ciphersuite_preference[] = { +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif +#endif + 0}; + +static const int suiteb_ecc_ciphersuite_preference[] = { +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, +#endif +#endif + 0}; +static const int suiteb_ciphersuite_preference[] = { +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, + MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, +#endif +#endif + 0}; +#endif + +static void +tls_set_ciphersuite(const struct tls_connection_params *cfg, tls_context_t *tls) +{ + /* Only set ciphersuite if cert's key length is high or ciphersuites are + * set by user */ +#ifdef CONFIG_SUITEB192 + if (cfg->flags & TLS_CONN_SUITEB) { + /* cipher suites will be set based on certificate */ + mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&tls->clientkey); + if (pk_alg == MBEDTLS_PK_RSA || + pk_alg == MBEDTLS_PK_RSASSA_PSS) { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, suiteb_rsa_ciphersuite_preference); + } else if ( + pk_alg == MBEDTLS_PK_ECDSA || pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH) { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, suiteb_ecc_ciphersuite_preference); + } else { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, suiteb_ciphersuite_preference); + } + } else +#endif + if (tls->ciphersuite[0]) { + mbedtls_ssl_conf_ciphersuites(&tls->conf, tls->ciphersuite); + } else if ( + mbedtls_pk_get_bitlen(&tls->clientkey) > 2048 || + (tls->cacert_ptr && + mbedtls_pk_get_bitlen(&tls->cacert_ptr->MBEDTLS_PRIVATE(pk)) > + 2048)) { + mbedtls_ssl_conf_ciphersuites( + &tls->conf, eap_ciphersuite_preference); + } +} + +static int +parse_certs(const struct tls_connection_params *cfg, tls_context_t *tls) +{ + int ret; + +#ifdef CONFIG_MBEDTLS_FS_IO + if (cfg->ca_cert) { + tls->cacert_ptr = &tls->cacert; + mbedtls_x509_crt_init(tls->cacert_ptr); + + ret = mbedtls_x509_crt_parse_file(&tls->cacert, cfg->ca_cert); + if (ret < 0) { + wpa_printf( + MSG_ERROR, + "mbedtls_x509_crt_parse_der failed -0x%x", -ret); + return -1; + } + + mbedtls_ssl_conf_authmode( + &tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + wpa_printf(MSG_ERROR, "Loaded CA cert: %s\n", cfg->ca_cert); + + } else +#endif + if (cfg->ca_cert_blob != NULL) { + ret = + set_ca_cert(tls, cfg->ca_cert_blob, cfg->ca_cert_blob_len); + if (ret != 0) { + return ret; + } + mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); + } else { + mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); + } + +#ifdef CONFIG_MBEDTLS_FS_IO + if (cfg->client_cert && cfg->private_key) { + mbedtls_x509_crt_init(&tls->clientcert); + ret = mbedtls_x509_crt_parse_file( + &tls->clientcert, cfg->client_cert); + if (ret < 0) { + wpa_printf( + MSG_ERROR, + "mbedtls_x509_crt_parse_der failed -0x%x", -ret); + return -1; + } + wpa_printf( + MSG_ERROR, "Loaded Client cert: %s\n", cfg->client_cert); + + mbedtls_pk_init(&tls->clientkey); + ret = mbedtls_pk_parse_keyfile( + &tls->clientkey, cfg->private_key, cfg->private_key_passwd, + f_rng, NULL); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "mbedtls_pk_parse_key failed -0x%x", + -ret); + return -1; + } + wpa_printf( + MSG_ERROR, "Loaded private key: %s\n", cfg->private_key); + + ret = mbedtls_ssl_conf_own_cert( + &tls->conf, &tls->clientcert, &tls->clientkey); + if (ret < 0) { + wpa_printf( + MSG_ERROR, + "mbedtls_ssl_conf_own_cert returned -0x%x", -ret); + return ret; + } + wpa_printf(MSG_ERROR, "Loaded client and key\n"); + + } else +#endif + if (cfg->client_cert_blob != NULL && + cfg->private_key_blob != NULL) { + ret = set_pki_context(tls, cfg); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "Failed to set client pki context"); + return ret; + } + } + + return 0; +} + +static int +set_client_config(const struct tls_connection_params *cfg, tls_context_t *tls) +{ + int ret; + int preset = MBEDTLS_SSL_PRESET_DEFAULT; + assert(cfg != NULL); + assert(tls != NULL); + +#ifdef CONFIG_SUITEB192 + if (cfg->flags & TLS_CONN_SUITEB) + preset = MBEDTLS_SSL_PRESET_SUITEB; +#endif + ret = mbedtls_ssl_config_defaults( + &tls->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, + preset); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "mbedtls_ssl_config_defaults returned -0x%x", + -ret); + return ret; + } + + if (preset != MBEDTLS_SSL_PRESET_SUITEB) { + /* Enable SHA1 support since it's not enabled by default in + * mbedtls */ + tls_enable_sha1_config(tls); +#ifdef CONFIG_SUITEB192 + } else { + tls_set_suiteb_config(tls); +#endif + } + wpa_printf( + MSG_ERROR, ": mbedtls_ssl_config_defaults: ciphersuite: %s\n", + mbedtls_ssl_get_ciphersuite(&tls->ssl)); + + wpa_printf(MSG_ERROR, ": CA cert: %s\n", cfg->ca_cert); + wpa_printf(MSG_ERROR, ": Client cert: %s\n", cfg->client_cert); + wpa_printf(MSG_ERROR, ": Client key: %s\n", cfg->private_key); + + if ((ret = parse_certs(cfg, tls))) { + wpa_printf(MSG_ERROR, "Failed to load certs: %d\n", ret); + return ret; + } + wpa_printf(MSG_INFO, "Loaded certs\n"); + + /* Usages of default ciphersuites can take a lot of time on low end + * device and can cause watchdog. Enabling the ciphers which are secured + * enough but doesn't take that much processing power */ + tls_set_ciphersuite(cfg, tls); + + return 0; +} + +static int tls_create_mbedtls_handle( + const struct tls_connection_params *params, tls_context_t *tls) +{ + int ret; + + assert(params != NULL); + assert(tls != NULL); + + mbedtls_ssl_init(&tls->ssl); + mbedtls_ctr_drbg_init(&tls->ctr_drbg); + mbedtls_ssl_config_init(&tls->conf); + mbedtls_entropy_init(&tls->entropy); + + ret = set_client_config(params, tls); + if (ret != 0) { + wpa_printf(MSG_ERROR, "Failed to set client configurations"); + goto exit; + } + + ret = mbedtls_ctr_drbg_seed( + &tls->ctr_drbg, mbedtls_entropy_func, &tls->entropy, NULL, 0); + if (ret != 0) { + wpa_printf( + MSG_ERROR, "mbedtls_ctr_drbg_seed returned -0x%x", -ret); + goto exit; + } + + mbedtls_ssl_conf_rng( + &tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); + + ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf); + if (ret != 0) { + wpa_printf(MSG_ERROR, "mbedtls_ssl_setup returned -0x%x", -ret); + goto exit; + } +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + /* Disable BEAST attack countermeasures for Windows 2008 + * interoperability */ + mbedtls_ssl_conf_cbc_record_splitting( + &tls->conf, MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED); +#endif + + return 0; + +exit: + tls_mbedtls_cleanup(tls); + return ret; +} + +void *tls_init(const struct tls_config *conf) +{ + tls_instance_count++; + return &tls_instance_count; +} + +void tls_deinit(void *tls_ctx) { tls_instance_count--; } + +struct tls_connection *tls_connection_init(void *tls_ctx) +{ + struct tls_connection *conn = os_zalloc(sizeof(*conn)); + if (!conn) { + wpa_printf( + MSG_ERROR, "TLS: Failed to allocate connection memory"); + return NULL; + } + + return conn; +} + +void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) +{ + /* case: tls init failed */ + if (!conn) { + return; + } + /* Free ssl ctx and data */ + tls_mbedtls_conn_delete((tls_context_t *)conn->tls); + os_free(conn->tls); + conn->tls = NULL; + /* Data in in ssl ctx, free connection */ + os_free(conn); +} + +int tls_get_errors(void *tls_ctx) { return 0; } + +int tls_connection_established(void *tls_ctx, struct tls_connection *conn) +{ + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_HANDSHAKE_OVER) { + return 1; + } + + return 0; +} + +int tls_global_set_verify(void *tls_ctx, int check_crl, int strict) +{ + wpa_printf(MSG_INFO, "TLS: global settings are not supported"); + return -1; +} + +int tls_connection_set_verify( + void *tls_ctx, struct tls_connection *conn, int verify_peer, + unsigned int flags, const u8 *session_ctx, size_t session_ctx_len) +{ + wpa_printf(MSG_INFO, "TLS: tls_connection_set_verify not supported"); + return -1; +} + +struct wpabuf *tls_connection_handshake( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + tls_context_t *tls = conn->tls; + int ret = 0; + + /* data freed by sender */ + conn->tls_io_data.out_data = NULL; + if (wpabuf_len(in_data)) { + conn->tls_io_data.in_data = wpabuf_dup(in_data); + } + + /* Multiple reads */ + while (tls->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { + ret = mbedtls_ssl_handshake_step(&tls->ssl); + + if (ret < 0) + break; + } + if (ret < 0 && ret != MBEDTLS_ERR_SSL_WANT_READ) { + wpa_printf(MSG_INFO, "%s: ret is %d", __func__, ret); + goto end; + } + + if (!conn->tls_io_data.out_data) { + wpa_printf( + MSG_INFO, + "application data is null, adding one byte for ack"); + u8 *dummy = os_zalloc(1); + conn->tls_io_data.out_data = wpabuf_alloc_ext_data(dummy, 0); + } + +end: + return conn->tls_io_data.out_data; +} + +struct wpabuf *tls_connection_server_handshake( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + wpa_printf(MSG_ERROR, "%s: not supported %d", __func__, __LINE__); + return NULL; +} + +struct wpabuf *tls_connection_encrypt( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) +{ + /* Reset dangling pointer */ + conn->tls_io_data.out_data = NULL; + + ssize_t ret = mbedtls_ssl_write( + &conn->tls->ssl, (unsigned char *)wpabuf_head(in_data), + wpabuf_len(in_data)); + + if (ret < wpabuf_len(in_data)) { + wpa_printf( + MSG_ERROR, "%s:%d, not able to write whole data", __func__, + __LINE__); + } + + return conn->tls_io_data.out_data; +} + +struct wpabuf *tls_connection_decrypt( + void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data) +{ + unsigned char buf[1200]; + int ret; + conn->tls_io_data.in_data = wpabuf_dup(in_data); + ret = mbedtls_ssl_read(&conn->tls->ssl, buf, 1200); + if (ret < 0) { + wpa_printf( + MSG_ERROR, "%s:%d, not able to write whole data", __func__, + __LINE__); + return NULL; + } + + struct wpabuf *out = wpabuf_alloc_copy(buf, ret); + + return out; +} + +int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) +{ + if (conn && conn->tls) { + mbedtls_ssl_session *session = NULL; + + // If we have a session, then its resumed + mbedtls_ssl_get_session(&conn->tls->ssl, session); + + if (session) { + return 1; + } + } + + return 0; +} + +/* cipher array should contain cipher number in mbedtls num as per IANA + * Please see cipherlist is u8, therefore only initial ones are supported */ +int tls_connection_set_cipher_list( + void *tls_ctx, struct tls_connection *conn, u8 *ciphers) +{ + int i = 0; + + while (*ciphers != 0 && i < MAX_CIPHERSUITE) { + conn->tls->ciphersuite[i] = ciphers[i]; + i++; + } + return 0; +} + +int tls_get_version( + void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) +{ + const char *name; + + if (conn == NULL) { + return -1; + } + + name = mbedtls_ssl_get_version(&conn->tls->ssl); + if (name == NULL) { + return -1; + } + + os_strlcpy(buf, name, buflen); + + return 0; +} + +int tls_get_library_version(char *buf, size_t buf_len) +{ + + return os_snprintf(buf, buf_len, "MbedTLS build=test run=test"); +} + +// Lifted from https://stackoverflow.com/a/47117431 +char *strremove(char *str, const char *sub) +{ + char *p, *q, *r; + if (*sub && (q = r = os_strstr(str, sub)) != NULL) { + size_t len = os_strlen(sub); + while ((r = os_strstr(p = r + len, sub)) != NULL) { + os_memmove(q, p, r - p); + q += r - p; + } + os_memmove(q, p, strlen(p) + 1); + } + return str; +} + +// Lifted from: https://stackoverflow.com/a/779960 +// You must free the result if result is non-NULL. +char *str_replace(char *orig, char *rep, char *with) +{ + char *result; // the return string + char *ins; // the next insert point + char *tmp; // varies + int len_rep; // length of rep (the string to remove) + int len_with; // length of with (the string to replace rep with) + int len_front; // distance between rep and end of last rep + int count; // number of replacements + + // sanity checks and initialization + if (!orig || !rep) + return NULL; + len_rep = strlen(rep); + if (len_rep == 0) + return NULL; // empty rep causes infinite loop during count + if (!with) + with = ""; + len_with = strlen(with); + + // count the number of replacements needed + ins = orig; + for (count = 0; (tmp = strstr(ins, rep)); ++count) { + ins = tmp + len_rep; + } + + tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1); + + if (!result) + return NULL; + + // first time through the loop, all the variable are set correctly + // from here on, + // tmp points to the end of the result string + // ins points to the next occurrence of rep in orig + // orig points to the remainder of orig after "end of rep" + while (count--) { + ins = strstr(orig, rep); + len_front = ins - orig; + tmp = strncpy(tmp, orig, len_front) + len_front; + tmp = strcpy(tmp, with) + len_with; + orig += len_front + len_rep; // move to next "end of rep" + } + strcpy(tmp, orig); + return result; +} + +int tls_get_cipher( + void *tls_ctx, struct tls_connection *conn, char *buf, size_t buflen) +{ + const char *name; + if (conn == NULL) { + return -1; + } + + name = mbedtls_ssl_get_ciphersuite(&conn->tls->ssl); + if (name == NULL) { + return -1; + } + + os_strlcpy(buf, name, buflen); + + // Translate to common format for hwsim tests to pass + strremove(buf, "TLS-"); + strremove(buf, "WITH-"); + char *tmp = str_replace(buf, "AES-", "AES"); + os_memcpy(buf, tmp, buflen); + free(tmp); + + return 0; +} + +int tls_connection_enable_workaround(void *tls_ctx, struct tls_connection *conn) +{ + return -1; +} + +int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + +int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + +int tls_connection_get_write_alerts(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + +void tls_connection_set_success_data( + struct tls_connection *conn, struct wpabuf *data) +{} + +void tls_connection_set_success_data_resumed(struct tls_connection *conn) {} + +const struct wpabuf * +tls_connection_get_success_data(struct tls_connection *conn) +{ + return NULL; +} + +void tls_connection_remove_session(struct tls_connection *conn) {} + +char *tls_connection_peer_serial_num(void *tls_ctx, struct tls_connection *conn) +{ + return NULL; +} + +int tls_connection_set_params( + void *tls_ctx, struct tls_connection *conn, + const struct tls_connection_params *params) +{ + int ret = 0; + + wpa_printf( + MSG_ERROR, " client_cert 4is %s, %p", params->client_cert, params); + + tls_context_t *tls = (tls_context_t *)os_zalloc(sizeof(tls_context_t)); + + if (!tls) { + wpa_printf(MSG_ERROR, "failed to allocate tls context"); + return -1; + } + if (!params) { + wpa_printf(MSG_ERROR, "configuration is null"); + ret = -1; + goto err; + } + // assert(params->client_cert != NULL); + + ret = tls_create_mbedtls_handle(params, tls); + if (ret < 0) { + wpa_printf(MSG_ERROR, "failed to create ssl handle"); + goto err; + } + mbedtls_ssl_set_bio( + &tls->ssl, conn, tls_mbedtls_write, tls_mbedtls_read, NULL); + conn->tls = (tls_context_t *)tls; + + mbedtls_ssl_set_export_keys_cb( + &conn->tls->ssl, tls_connection_export_keys_cb, conn); + + return ret; +err: + os_free(tls); + return ret; +} + +int tls_global_set_params( + void *tls_ctx, const struct tls_connection_params *params) +{ + wpa_printf(MSG_INFO, "TLS: Global parameters not supported"); + return -1; +} + +int tls_connection_set_session_ticket_cb( + void *tls_ctx, struct tls_connection *conn, tls_session_ticket_cb cb, + void *ctx) +{ + wpa_printf(MSG_ERROR, "TLS: %s not supported", __func__); + return -1; +} + +void tls_connection_export_keys_cb( + void *p_expkey, mbedtls_ssl_key_export_type secret_type, + const unsigned char *secret, size_t secret_len, + const unsigned char client_random[32], + const unsigned char server_random[32], mbedtls_tls_prf_types tls_prf_type) + +{ + struct tls_connection *conn = p_expkey; + + os_memcpy(conn->randbytes, client_random, TLS_RANDOM_LEN); + os_memcpy( + conn->randbytes + TLS_RANDOM_LEN, server_random, TLS_RANDOM_LEN); + os_memcpy(conn->master_secret, secret, secret_len); + conn->tls_prf_type = tls_prf_type; +} +static int tls_connection_prf( + void *tls_ctx, struct tls_connection *conn, const char *label, + int server_random_first, u8 *out, size_t out_len) +{ + int ret; + u8 seed[2 * TLS_RANDOM_LEN]; + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + if (!ssl || !conn) { + wpa_printf( + MSG_ERROR, "TLS: %s, connection info is null", __func__); + return -1; + } + if (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) { + wpa_printf( + MSG_ERROR, "TLS: %s, incorrect tls state=%d", __func__, + ssl->MBEDTLS_PRIVATE(state)); + return -1; + } + + if (server_random_first) { + os_memcpy( + seed, conn->randbytes + TLS_RANDOM_LEN, TLS_RANDOM_LEN); + os_memcpy( + seed + TLS_RANDOM_LEN, conn->randbytes, TLS_RANDOM_LEN); + } else { + os_memcpy(seed, conn->randbytes, 2 * TLS_RANDOM_LEN); + } + + wpa_hexdump_key(MSG_MSGDUMP, "random", seed, 2 * TLS_RANDOM_LEN); + wpa_hexdump_key( + MSG_MSGDUMP, "master", conn->master_secret, TLS_MASTER_SECRET_LEN); + + if (conn->tls_prf_type == MBEDTLS_SSL_TLS_PRF_SHA384) { + ret = tls_prf_sha384( + conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, + 2 * TLS_RANDOM_LEN, out, out_len); + } else if (conn->tls_prf_type == MBEDTLS_SSL_TLS_PRF_SHA256) { + ret = tls_prf_sha256( + conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, + 2 * TLS_RANDOM_LEN, out, out_len); + } else { + ret = tls_prf_sha1_md5( + conn->master_secret, TLS_MASTER_SECRET_LEN, label, seed, + 2 * TLS_RANDOM_LEN, out, out_len); + } + + if (ret < 0) { + wpa_printf(MSG_ERROR, "prf failed, ret=%d\n", ret); + } + wpa_hexdump_key(MSG_MSGDUMP, "key", out, out_len); + + return ret; +} + +int tls_connection_export_key( + void *tls_ctx, struct tls_connection *conn, const char *label, + const u8 *context, size_t context_len, u8 *out, size_t out_len) +{ + return tls_connection_prf(tls_ctx, conn, label, 0, out, out_len); +} + +int tls_connection_get_eap_fast_key( + void *tls_ctx, struct tls_connection *conn, u8 *out, size_t out_len) +{ + wpa_printf( + MSG_INFO, "TLS: tls_connection_get_eap_fast_key not supported, " + "please unset mbedtls crypto and try again"); + return -1; +} + +int tls_connection_client_hello_ext( + void *tls_ctx, struct tls_connection *conn, int ext_type, const u8 *data, + size_t data_len) +{ + wpa_printf( + MSG_INFO, "TLS: tls_connection_client_hello_ext not supported, " + "please unset mbedtls crypto and try again"); + return -1; +} + +int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) +{ + if (conn->tls_io_data.in_data) { + wpabuf_free(conn->tls_io_data.in_data); + } + conn->tls_io_data.in_data = NULL; + + /* outdata may have dangling pointer */ + conn->tls_io_data.out_data = NULL; + + return mbedtls_ssl_session_reset(&conn->tls->ssl); +} + +int tls_connection_get_random( + void *tls_ctx, struct tls_connection *conn, struct tls_random *data) +{ + mbedtls_ssl_context *ssl = &conn->tls->ssl; + + os_memset(data, 0, sizeof(*data)); + if (ssl->MBEDTLS_PRIVATE(state) == MBEDTLS_SSL_CLIENT_HELLO) { + return -1; + } + + data->client_random = conn->randbytes; + data->client_random_len = TLS_RANDOM_LEN; + + if (ssl->MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_SERVER_HELLO) { + data->server_random = conn->randbytes + TLS_RANDOM_LEN; + data->server_random_len = TLS_RANDOM_LEN; + } + + return 0; +} diff --git a/tests/build/build-wpa_supplicant-mbedtls-3.1.0.config b/tests/build/build-wpa_supplicant-mbedtls-3.1.0.config new file mode 100644 index 000000000..2ccfaef0e --- /dev/null +++ b/tests/build/build-wpa_supplicant-mbedtls-3.1.0.config @@ -0,0 +1,29 @@ +CONFIG_TLS=mbedtls +INSTALL_DIR=/usr/local/ +CFLAGS += -I$(INSTALL_DIR)/include +LIBS += -L$(INSTALL_DIR)/lib +LDFLAGS += -Wl,-rpath=$(INSTALL_DIR)/lib +CONFIG_TLS_ADD_DL=y + +CONFIG_WPS=y +CONFIG_EAP_TLS=y +CONFIG_EAP_MSCHAPV2=y + +CONFIG_EAP_PSK=y +CONFIG_EAP_GPSK=y +CONFIG_EAP_AKA=y +CONFIG_EAP_SIM=y +CONFIG_EAP_SAKE=y +CONFIG_EAP_PAX=y +CONFIG_EAP_FAST=y +CONFIG_EAP_IKEV2=y + +CONFIG_SAE=y +CONFIG_FILS=y +CONFIG_FILS_SK_PFS=y +CONFIG_OWE=y +CONFIG_DPP=y +CONFIG_SUITEB=y +CONFIG_SUITEB192=y + +CFLAGS += -Werror \ No newline at end of file diff --git a/tests/build/run-build-tests.sh b/tests/build/run-build-tests.sh index 347ca39a0..8cc446e90 100755 --- a/tests/build/run-build-tests.sh +++ b/tests/build/run-build-tests.sh @@ -8,13 +8,10 @@ popd > /dev/null echo "Build test directory: $DIR" echo -for i in build-hostapd-*.config; do - ./build-hostapd.sh $DIR $i -done - -for i in build-wpa_supplicant-*.config; do +for i in build-wpa_supplicant-mbedtls-3.1.0.config; do ./build-wpa_supplicant.sh $DIR $i done echo echo "Build test directory: $DIR" +cat $DIR/wpa_supplicant-mbedtls-3.1.0.log-* \ No newline at end of file diff --git a/tests/hwsim/test_suite_b.py b/tests/hwsim/test_suite_b.py index 7065b18bd..79f76f580 100644 --- a/tests/hwsim/test_suite_b.py +++ b/tests/hwsim/test_suite_b.py @@ -22,7 +22,7 @@ def check_suite_b_capa(dev): def check_suite_b_tls_lib(dev, dhe=False, level128=False): tls = dev[0].request("GET tls_library") - if tls.startswith("GnuTLS"): + if tls.startswith("GnuTLS") or tls.startswith("MbedTLS"): return if not tls.startswith("OpenSSL"): raise HwsimSkip("TLS library not supported for Suite B: " + tls) diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index ce1c8b2e3..536277c69 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -35,7 +35,7 @@ export INCDIR ?= /usr/local/include export BINDIR ?= /usr/local/sbin PKG_CONFIG ?= pkg-config -CFLAGS += $(EXTRA_CFLAGS) +CFLAGS += $(EXTRA_CFLAGS) -Werror CFLAGS += -I$(abspath ../src) CFLAGS += -I$(abspath ../src/utils) @@ -145,6 +145,7 @@ ifndef CONFIG_ELOOP CONFIG_ELOOP=eloop endif OBJS += ../src/utils/$(CONFIG_ELOOP).o +OBJS_p += ../src/utils/$(CONFIG_ELOOP).o OBJS_c += ../src/utils/$(CONFIG_ELOOP).o ifndef CONFIG_OSX @@ -258,9 +259,12 @@ ifdef CONFIG_SAE CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o ifdef CONFIG_SAE_PK +# NO ECDH support yet +ifneq ($(CONFIG_TLS), mbedtls) CFLAGS += -DCONFIG_SAE_PK OBJS += ../src/common/sae_pk.o endif +endif NEED_ECC=y NEED_DH_GROUPS=y NEED_HMAC_SHA256_KDF=y @@ -271,6 +275,8 @@ endif endif ifdef CONFIG_DPP +# NO ECDH support yet +ifneq ($(CONFIG_TLS), mbedtls) CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o OBJS += ../src/common/dpp_auth.o @@ -295,8 +301,11 @@ ifdef CONFIG_DPP2 CFLAGS += -DCONFIG_DPP2 endif endif +endif ifdef CONFIG_OWE +# NO ECDH support yet +ifneq ($(CONFIG_TLS), mbedtls) CFLAGS += -DCONFIG_OWE NEED_ECC=y NEED_HMAC_SHA256_KDF=y @@ -305,16 +314,20 @@ NEED_HMAC_SHA512_KDF=y NEED_SHA384=y NEED_SHA512=y endif +endif ifdef CONFIG_FILS CFLAGS += -DCONFIG_FILS NEED_SHA384=y NEED_AES_SIV=y ifdef CONFIG_FILS_SK_PFS +# NO ECDH support yet +ifneq ($(CONFIG_TLS), mbedtls) CFLAGS += -DCONFIG_FILS_SK_PFS NEED_ECC=y endif endif +endif ifdef CONFIG_MBO CONFIG_WNM=y @@ -396,6 +409,8 @@ endif endif ifdef CONFIG_PASN +# NO ECDH support yet +ifneq ($(CONFIG_TLS), mbedtls) CFLAGS += -DCONFIG_PASN CFLAGS += -DCONFIG_PTKSA_CACHE NEED_HMAC_SHA256_KDF=y @@ -405,6 +420,7 @@ NEED_SHA384=y OBJS += ../src/common/ptksa_cache.o OBJS += pasn_supplicant.o endif +endif ifdef CONFIG_HS20 OBJS += hs20_supplicant.o @@ -674,6 +690,7 @@ NEED_T_PRF=y endif ifdef CONFIG_EAP_TEAP +ifneq ($(CONFIG_TLS), mbedtls) # EAP-TEAP SRC_EAP_TEAP = ../src/eap_peer/eap_teap.c ../src/eap_peer/eap_teap_pac.c SRC_EAP_TEAP += ../src/eap_common/eap_teap_common.c @@ -684,6 +701,7 @@ else CFLAGS += -DEAP_TEAP OBJS += $(patsubst %.c, %.o, $(SRC_EAP_TEAP)) endif +endif TLS_FUNCS=y CONFIG_IEEE8021X_EAPOL=y NEED_T_PRF=y @@ -972,10 +990,13 @@ OBJS += ../src/ap/wps_hostapd.o OBJS += ../src/eap_server/eap_server_wsc.o endif ifdef CONFIG_DPP +# NO ECDH support yet +ifneq ($(CONFIG_TLS), mbedtls) OBJS += ../src/ap/dpp_hostapd.o OBJS += ../src/ap/gas_query_ap.o NEED_AP_GAS_SERV=y endif +endif ifdef CONFIG_INTERWORKING NEED_AP_GAS_SERV=y endif @@ -1125,6 +1146,41 @@ endif CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\" endif +ifeq ($(CONFIG_TLS), mbedtls) +CFLAGS += -DCONFIG_MBEDTLS_FS_IO +CFLAGS += -I/usr/local/include/ +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_mbedtls.o +LIBS += -lmbedtls -lmbedx509 +endif +OBJS += ../src/crypto/crypto_mbedtls.o +OBJS_p += ../src/crypto/crypto_mbedtls.o +OBJS_priv += ../src/crypto/crypto_mbedtls.o + +OBJS += ../src/crypto/crypto_mbedtls-bignum.o +OBJS_p += ../src/crypto/crypto_mbedtls-bignum.o +OBJS_priv += ../src/crypto/crypto_mbedtls-bignum.o + +OBJS += ../src/crypto/crypto_mbedtls-ec.o +OBJS_p += ../src/crypto/crypto_mbedtls-ec.o +OBJS_priv += ../src/crypto/crypto_mbedtls-ec.o +NEED_TLS_PRF_SHA256=y +NEED_TLS_PRF_SHA384=y +NEED_HMAC_SHA384_KDF=y +OBJS += ../src/crypto/fips_prf_internal.o +SHA1OBJS += ../src/crypto/sha1-internal.o +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_MD4=y +CONFIG_INTERNAL_DH_GROUP5=y +CONFIG_INTERNAL_SHA512=y +LIBS += -lmbedcrypto +LIBS_p += -lmbedcrypto +ifdef CONFIG_TLS_ADD_DL +LIBS += -ldl +LIBS_p += -ldl +endif +endif + ifeq ($(CONFIG_TLS), gnutls) ifndef CONFIG_CRYPTO # default to libgcrypt @@ -1317,9 +1373,11 @@ endif ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) NEED_INTERNAL_AES_WRAP=y endif endif +endif ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP # Seems to be needed at least with BoringSSL NEED_INTERNAL_AES_WRAP=y @@ -1345,8 +1403,10 @@ AESOBJS += ../src/crypto/aes-siv.o NEED_AES_CTR=y endif ifdef NEED_AES_CTR +ifneq ($(CONFIG_TLS), mbedtls) AESOBJS += ../src/crypto/aes-ctr.o endif +endif ifdef NEED_AES_ENCBLOCK AESOBJS += ../src/crypto/aes-encblock.o endif @@ -1356,10 +1416,12 @@ CFLAGS += -DCONFIG_OPENSSL_CMAC else ifneq ($(CONFIG_TLS), linux) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) AESOBJS += ../src/crypto/aes-omac1.o endif endif endif +endif ifdef NEED_AES_WRAP NEED_AES_ENC=y ifdef NEED_INTERNAL_AES_WRAP @@ -1371,11 +1433,13 @@ NEED_AES_ENC=y ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), linux) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) AESOBJS += ../src/crypto/aes-cbc.o endif endif endif endif +endif ifdef NEED_AES_ENC ifdef CONFIG_INTERNAL_AES AESOBJS += ../src/crypto/aes-internal-enc.o @@ -1390,11 +1454,14 @@ ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), linux) ifneq ($(CONFIG_TLS), gnutls) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) SHA1OBJS += ../src/crypto/sha1.o endif endif endif endif +endif + SHA1OBJS += ../src/crypto/sha1-prf.o ifdef CONFIG_INTERNAL_SHA1 SHA1OBJS += ../src/crypto/sha1-internal.o @@ -1407,10 +1474,12 @@ CFLAGS += -DCONFIG_NO_PBKDF2 else ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) SHA1OBJS += ../src/crypto/sha1-pbkdf2.o endif endif endif +endif ifdef NEED_T_PRF SHA1OBJS += ../src/crypto/sha1-tprf.o endif @@ -1424,12 +1493,14 @@ ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), linux) ifneq ($(CONFIG_TLS), gnutls) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) MD5OBJS += ../src/crypto/md5.o endif endif endif endif endif +endif ifdef NEED_MD5 ifdef CONFIG_INTERNAL_MD5 MD5OBJS += ../src/crypto/md5-internal.o @@ -1473,11 +1544,14 @@ ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), linux) ifneq ($(CONFIG_TLS), gnutls) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) SHA256OBJS += ../src/crypto/sha256.o endif endif endif endif +endif + SHA256OBJS += ../src/crypto/sha256-prf.o ifdef CONFIG_INTERNAL_SHA256 SHA256OBJS += ../src/crypto/sha256-internal.o @@ -1514,11 +1588,13 @@ ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), linux) ifneq ($(CONFIG_TLS), gnutls) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) OBJS += ../src/crypto/sha384.o endif endif endif endif +endif CFLAGS += -DCONFIG_SHA384 OBJS += ../src/crypto/sha384-prf.o endif @@ -1563,6 +1639,9 @@ ifdef CONFIG_GETRANDOM CFLAGS += -DCONFIG_GETRANDOM endif OBJS += ../src/crypto/random.o +OBJS_p += ../src/crypto/random.o +OBJS_priv += ../src/crypto/random.o + endif ifdef CONFIG_CTRL_IFACE @@ -1709,10 +1788,12 @@ ifdef CONFIG_FIPS CFLAGS += -DCONFIG_FIPS ifneq ($(CONFIG_TLS), openssl) ifneq ($(CONFIG_TLS), wolfssl) +ifneq ($(CONFIG_TLS), mbedtls) $(error CONFIG_FIPS=y requires CONFIG_TLS=openssl) endif endif endif +endif OBJS += $(SHA1OBJS) $(DESOBJS) diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index 708a82385..fabbd69e3 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -318,6 +318,7 @@ CONFIG_BACKEND=file # gnutls = GnuTLS # internal = Internal TLSv1 implementation (experimental) # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental) +# mbedtls = Mbed TLS # none = Empty template #CONFIG_TLS=openssl -- 2.32.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap