Implement SAE-PK with the using the wolfSSL backend Signed-off-by: Juliusz Sosinowicz <juliusz@xxxxxxxxxxx> --- src/crypto/crypto_wolfssl.c | 255 ++++++++++++++++++++++++++++++++++++ tests/hwsim/test_sae.py | 2 + 2 files changed, 257 insertions(+) diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c index 9d470ab92f..6014cfb940 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -29,6 +29,7 @@ #include <wolfssl/wolfcrypt/dh.h> #include <wolfssl/wolfcrypt/cmac.h> #include <wolfssl/wolfcrypt/ecc.h> +#include <wolfssl/wolfcrypt/asn_public.h> #include <wolfssl/openssl/bn.h> #ifdef ANDROID @@ -1847,6 +1848,260 @@ size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) return crypto_ec_prime_len(ecdh->ec); } +struct crypto_ec_key { + ecc_key* eckey; + WC_RNG* rng; /* Needs to be initialized before use. + * *NOT* initialized in crypto_ec_key_init */ +}; + +static struct crypto_ec_key* crypto_ec_key_init(void) +{ + struct crypto_ec_key* key; + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_init starting"); + key = os_zalloc(sizeof(struct crypto_ec_key)); + if (key) { + key->eckey = wc_ecc_key_new(NULL); + /* Omit key->rng initialization because it seeds itself and thus + * consumes entropy that may never be used. Lazy initialize when + * necessary. */ + if (!key->eckey) { + wpa_printf(MSG_ERROR, "wolfSSL: crypto_ec_key_init failed"); + crypto_ec_key_deinit(key); + key = NULL; + } + } + return key; +} + +void crypto_ec_key_deinit(struct crypto_ec_key *key) +{ + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_deinit starting"); + if (key) { + wc_rng_free(key->rng); + wc_ecc_key_free(key->eckey); + os_free(key); + } +} + +struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) +{ + struct crypto_ec_key *ret = NULL; + word32 idx = 0; + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_parse_priv starting"); + + if (!der && der_len == 0) { + wpa_printf(MSG_ERROR, "wolfSSL: invalid input parameters"); + goto fail; + } + + ret = crypto_ec_key_init(); + if (!ret) { + wpa_printf(MSG_ERROR, "wolfSSL: crypto_ec_key_init failed"); + goto fail; + } + + if (wc_EccPrivateKeyDecode(der, &idx, ret->eckey, (word32)der_len) != 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPrivateKeyDecode failed"); + goto fail; + } + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_parse_priv success"); + + return ret; +fail: + if (ret) + crypto_ec_key_deinit(ret); + return NULL; +} + +int crypto_ec_key_group(struct crypto_ec_key *key) +{ + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_group starting"); + + if (!key || !key->eckey || !key->eckey->dp) { + wpa_printf(MSG_ERROR, "wolfSSL: invalid input parameters"); + return -1; + } + + switch (key->eckey->dp->id) { + case ECC_SECP256R1: + return 19; + case ECC_SECP384R1: + return 20; + case ECC_SECP521R1: + return 21; + case ECC_BRAINPOOLP256R1: + return 28; + case ECC_BRAINPOOLP384R1: + return 29; + case ECC_BRAINPOOLP512R1: + return 30; + } + wpa_printf(MSG_ERROR, "wolfSSL: Unsupported curve (id=%d) in EC key", + key->eckey->dp->id); + return -1; +} + +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) +{ + byte *der = NULL; + int derLen; + struct wpabuf *ret = NULL; + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_group starting"); + + if (!key || !key->eckey) { + wpa_printf(MSG_ERROR, "wolfSSL: invalid input parameters"); + goto fail; + } + + derLen = wc_EccPublicKeyDerSize(key->eckey, 1); + if (derLen <= 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPublicKeyDerSize failed"); + goto fail; + } + + der = os_malloc(derLen); + if (!der) { + wpa_printf(MSG_ERROR, "wolfSSL: os_malloc failed"); + goto fail; + } + + derLen = wc_EccPublicKeyToDer(key->eckey, der, derLen, 1); + if (derLen <= 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPublicKeyToDer failed"); + goto fail; + } + + ret = wpabuf_alloc_copy(der, derLen); + os_free(der); + if (ret) + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_group success"); + else + wpa_printf(MSG_ERROR, "wolfSSL: wpabuf_alloc_copy failed"); + return ret; + +fail: + if (der) + os_free(der); + return NULL; +} + +struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) +{ + word32 idx = 0; + struct crypto_ec_key *ret = NULL; + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_parse_pub starting"); + + if (!der || der_len == 0) { + wpa_printf(MSG_ERROR, "wolfSSL: invalid input parameters"); + goto fail; + } + + ret = crypto_ec_key_init(); + if (!ret) { + wpa_printf(MSG_ERROR, "wolfSSL: crypto_ec_key_init failed"); + goto fail; + } + + if (wc_EccPublicKeyDecode(der, &idx, ret->eckey, (word32)der_len) != 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPublicKeyDecode failed"); + goto fail; + } + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_parse_pub success"); + + return ret; +fail: + if (ret) + crypto_ec_key_deinit(ret); + return NULL; +} + + +struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, + size_t len) +{ + byte *der = NULL; + int derLen; + word32 w32DerLen; + struct wpabuf *ret = NULL; + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_sign starting"); + + if (!key || !key->eckey || !data || len == 0) { + wpa_printf(MSG_ERROR, "wolfSSL: invalid input parameters"); + goto fail; + } + + if (!key->rng) { + /* Lazy init key->rng */ + key->rng = wc_rng_new(NULL, 0, NULL); + if (!key->rng) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_rng_new failed"); + goto fail; + } + } + + derLen = wc_ecc_sig_size(key->eckey); + if (derLen <= 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_sig_size failed"); + goto fail; + } + + der = os_malloc(derLen); + if (!der) { + wpa_printf(MSG_ERROR, "wolfSSL: os_malloc failed"); + goto fail; + } + + w32DerLen = (word32)derLen; + if (wc_ecc_sign_hash(data, len, der, &w32DerLen, key->rng, key->eckey) + != 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_sign_hash failed"); + goto fail; + } + + ret = wpabuf_alloc_copy(der, derLen); + os_free(der); + if (ret) + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_sign success"); + else + wpa_printf(MSG_ERROR, "wolfSSL: wpabuf_alloc_copy failed"); + return ret; +fail: + if (der) + os_free(der); + return NULL; +} + + +int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *sig, size_t sig_len) +{ + int res = 0; + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_verify_signature starting"); + + if (!key || !key->eckey || !data || len == 0 || !sig || sig_len == 0) { + wpa_printf(MSG_ERROR, "wolfSSL: invalid input parameters"); + return -1; + } + + if (wc_ecc_verify_hash(sig, sig_len, data, len, &res, key->eckey) != 0) { + wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_verify_hash failed"); + return -1; + } + + wpa_printf(MSG_DEBUG, "wolfSSL: crypto_ec_key_verify_signature %s", + res == 1 ? "success" : "failed"); + + return res; +} + #endif /* CONFIG_ECC */ diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index 276a484436..c3061b43f4 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -2119,6 +2119,8 @@ def run_sae_pwe_group(dev, apdev, group): if group in [27, 28, 29, 30]: if tls.startswith("OpenSSL") and ("run=OpenSSL 1." in tls or "run=OpenSSL 3." in tls): logger.info("Add Brainpool EC groups since OpenSSL is new enough") + elif tls.startswith("wolfSSL"): + logger.info("Make sure Brainpool EC groups were enabled when compiling wolfSSL") else: raise HwsimSkip("Brainpool curve not supported") start_sae_pwe_ap(apdev[0], group, 2) -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap