From: Juliusz Sosinowicz Date: Thu, 4 Apr 2024 18:16:12 +0000 (+0200) Subject: wolfssl: Implement RSA-OAEP-SHA256 for EAP-AKA privacy protection X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=99239d08de3e1f5cf68652d71b839468cc6f6fc3;p=thirdparty%2Fhostap.git wolfssl: Implement RSA-OAEP-SHA256 for EAP-AKA privacy protection Implement the crypto_rsa_key set of functions in the wolfSSL backend to enable IMSI encryption for EAP-AKA and EAP-SIM. Signed-off-by: Juliusz Sosinowicz --- diff --git a/hostapd/Makefile b/hostapd/Makefile index d7688001d..93a11dd86 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -709,6 +709,7 @@ CFLAGS += -DCONFIG_TLSV12 endif ifeq ($(CONFIG_TLS), wolfssl) +CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 CONFIG_CRYPTO=wolfssl ifdef TLS_FUNCS OBJS += ../src/crypto/tls_wolfssl.o diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c index 269174321..3543100c3 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -3555,6 +3556,284 @@ fail: #endif /* CONFIG_DPP */ +struct crypto_rsa_key { + RsaKey key; + WC_RNG *rng; +}; + +static struct crypto_rsa_key * crypto_rsa_key_init(void) +{ + struct crypto_rsa_key *ret; + int err; + + ret = os_zalloc(sizeof(*ret)); + if (!ret) + return NULL; + + err = wc_InitRsaKey(&ret->key, NULL); + if (err != MP_OKAY) { + LOG_WOLF_ERROR_FUNC(wc_InitRsaKey, err); + goto fail; + } + + ret->rng = wc_rng_init(); + if (!ret->rng) { + LOG_WOLF_ERROR_FUNC_NULL(wc_rng_init); + goto fail; + } + + err = wc_RsaSetRNG(&ret->key, ret->rng); + if (err != 0) { + LOG_WOLF_ERROR_FUNC(wc_RsaSetRNG, err); + goto fail; + } + + return ret; +fail: + crypto_rsa_key_free(ret); + return NULL; +} + + +void crypto_rsa_key_free(struct crypto_rsa_key *key) +{ + if (key) { + int err; + + err = wc_FreeRsaKey(&key->key); + if (err != 0) + LOG_WOLF_ERROR_FUNC(wc_FreeRsaKey, err); + wc_rng_free(key->rng); + os_free(key); + } +} + + +static void read_rsa_key_from_x509(unsigned char *key_pem, size_t key_pem_len, + DerBuffer **key_der) +{ + struct DecodedCert cert; + DerBuffer *cert_der = NULL; + word32 der_key_sz = 0; + int err; + + err = wc_PemToDer(key_pem, (long) key_pem_len, CERT_TYPE, &cert_der, + NULL, NULL, NULL); + if (err != 0) { + LOG_WOLF_ERROR_FUNC(wc_PemToDer, err); + goto fail; + } + + wc_InitDecodedCert(&cert, cert_der->buffer, cert_der->length, NULL); + err = wc_ParseCert(&cert, CERT_TYPE, NO_VERIFY, NULL); + if (err != 0) { + LOG_WOLF_ERROR_FUNC(wc_PemToDer, err); + goto fail; + } + + err = wc_GetPubKeyDerFromCert(&cert, NULL, &der_key_sz); + if (err != LENGTH_ONLY_E) { + LOG_WOLF_ERROR_FUNC(wc_GetPubKeyDerFromCert, err); + goto fail; + } + + if (*key_der) + wc_FreeDer(key_der); + *key_der = NULL; + + err = wc_AllocDer(key_der, der_key_sz, PUBLICKEY_TYPE, NULL); + if (err != 0) { + LOG_WOLF_ERROR_FUNC(wc_AllocDer, err); + goto fail; + } + + err = wc_GetPubKeyDerFromCert(&cert, (*key_der)->buffer, + &(*key_der)->length); + if (err != 0) { + LOG_WOLF_ERROR_FUNC(wc_GetPubKeyDerFromCert, err); + goto fail; + } + +fail: + if (cert_der) { + wc_FreeDecodedCert(&cert); + wc_FreeDer(&cert_der); + } + + /* caller is responsible for free'ing key_der */ +} + + +struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key) +{ + struct crypto_rsa_key *ret = NULL; + unsigned char *key_pem = NULL; + size_t key_pem_len = 0; + DerBuffer *key_der = NULL; + int key_format = 0; + int err; + int success = 0; + word32 idx = 0; + + key_pem = (unsigned char *) os_readfile(file, &key_pem_len); + if (!key_pem) { + LOG_WOLF_ERROR_FUNC_NULL(os_readfile); + goto fail; + } + + err = wc_PemToDer(key_pem, (long) key_pem_len, + private_key ? PRIVATEKEY_TYPE : PUBLICKEY_TYPE, + &key_der, NULL, NULL, &key_format); + if (err != 0) { + if (private_key) { + LOG_WOLF_ERROR_FUNC(wc_PemToDer, err); + goto fail; + } + + /* Input file might be public key or x509 cert we want to + *extract the key from */ + wpa_printf(MSG_DEBUG, + "wolfSSL: Trying to extract key from x509 cert"); + read_rsa_key_from_x509(key_pem, key_pem_len, &key_der); + if (!key_der) { + LOG_WOLF_ERROR_FUNC(wc_PemToDer, err); + LOG_WOLF_ERROR_FUNC_NULL(read_rsa_key_from_x509); + goto fail; + } + } + + if (private_key && key_format != RSAk) { + LOG_WOLF_ERROR("Private key is not RSA key"); + goto fail; + } + + /* No longer needed so let's free the memory early */ + os_free(key_pem); + key_pem = NULL; + + ret = crypto_rsa_key_init(); + if (!ret) { + LOG_WOLF_ERROR_FUNC_NULL(crypto_rsa_key_init); + goto fail; + } + + if (private_key) + err = wc_RsaPrivateKeyDecode(key_der->buffer, &idx, &ret->key, + key_der->length); + else + err = wc_RsaPublicKeyDecode(key_der->buffer, &idx, &ret->key, + key_der->length); + + if (err != 0) { + if (private_key) + LOG_WOLF_ERROR_FUNC(wc_RsaPrivateKeyDecode, err); + else + LOG_WOLF_ERROR_FUNC(wc_RsaPublicKeyDecode, err); + goto fail; + } + + success = 1; +fail: + os_free(key_pem); + if (key_der) + wc_FreeDer(&key_der); + if (!success && ret) { + crypto_rsa_key_free(ret); + ret = NULL; + } + + return ret; +} + + +struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key, + const struct wpabuf *in) +{ + int err; + int success = 0; + struct wpabuf *ret = NULL; + + if (!key || !in) { + LOG_INVALID_PARAMETERS(); + return NULL; + } + + ret = wpabuf_alloc(wc_RsaEncryptSize(&key->key)); + if (!ret) { + LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc); + goto fail; + } + + wpa_printf(MSG_DEBUG, + "wolfSSL: crypto_rsa_oaep_sha256_encrypt: wpabuf_len(in) %ld wc_RsaEncryptSize(key->key) %d", + wpabuf_len(in), wc_RsaEncryptSize(&key->key)); + + err = wc_RsaPublicEncrypt_ex(wpabuf_head_u8(in), wpabuf_len(in), + wpabuf_mhead_u8(ret), wpabuf_size(ret), + &key->key, key->rng, + WC_RSA_OAEP_PAD, WC_HASH_TYPE_SHA256, + WC_MGF1SHA256, NULL, 0); + if (err <= 0) { + LOG_WOLF_ERROR_FUNC(wc_RsaPublicEncrypt_ex, err); + goto fail; + } + wpabuf_put(ret, err); + + success = 1; +fail: + if (!success && ret) { + wpabuf_free(ret); + ret = NULL; + } + + return ret; +} + + +struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key, + const struct wpabuf *in) +{ + int err; + int success = 0; + struct wpabuf *ret = NULL; + + if (!key || !in) { + LOG_INVALID_PARAMETERS(); + return NULL; + } + + ret = wpabuf_alloc(wc_RsaEncryptSize(&key->key)); + if (!ret) { + LOG_WOLF_ERROR_FUNC_NULL(wpabuf_alloc); + goto fail; + } + + wpa_printf(MSG_DEBUG, + "wolfSSL: crypto_rsa_oaep_sha256_decrypt: wpabuf_len(in) %ld wc_RsaEncryptSize(key->key) %d", + wpabuf_len(in), wc_RsaEncryptSize(&key->key)); + + err = wc_RsaPrivateDecrypt_ex(wpabuf_head_u8(in), wpabuf_len(in), + wpabuf_mhead_u8(ret), wpabuf_size(ret), + &key->key, WC_RSA_OAEP_PAD, + WC_HASH_TYPE_SHA256, WC_MGF1SHA256, + NULL, 0); + if (err <= 0) { + LOG_WOLF_ERROR_FUNC(wc_RsaPublicEncrypt_ex, err); + goto fail; + } + wpabuf_put(ret, err); + + success = 1; +fail: + if (!success && ret) { + wpabuf_free(ret); + ret = NULL; + } + + return ret; +} + + void crypto_unload(void) { } diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 391321bf0..bf9875e6d 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1190,6 +1190,7 @@ TLS_FUNCS=y endif ifeq ($(CONFIG_TLS), wolfssl) +CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ifdef TLS_FUNCS CFLAGS += -DWOLFSSL_DER_LOAD OBJS += ../src/crypto/tls_wolfssl.o