From 36b11bbcffb6f5dce964c4c6c57ca9d4b51ff9a3 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 30 Apr 2022 13:34:00 +0300 Subject: [PATCH] OpenSSL: RSA-OAEP-SHA-256 encryption/decryption Add new crypto wrappers for performing RSA-OAEP-SHA-256 encryption and decryption. These are needed for IMSI privacy. Signed-off-by: Jouni Malinen --- hostapd/Android.mk | 1 + hostapd/Makefile | 1 + src/crypto/crypto.h | 34 ++++++++++ src/crypto/crypto_openssl.c | 121 +++++++++++++++++++++++++++++++++++- wpa_supplicant/Android.mk | 1 + wpa_supplicant/Makefile | 1 + 6 files changed, 158 insertions(+), 1 deletion(-) diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 885dae7f6..953031577 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -659,6 +659,7 @@ L_CFLAGS += -DCONFIG_TLSV12 endif ifeq ($(CONFIG_TLS), openssl) +L_CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ifdef TLS_FUNCS OBJS += src/crypto/tls_openssl.c OBJS += src/crypto/tls_openssl_ocsp.c diff --git a/hostapd/Makefile b/hostapd/Makefile index 9967e270c..3325937ff 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -714,6 +714,7 @@ endif endif ifeq ($(CONFIG_TLS), openssl) +CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 CONFIG_CRYPTO=openssl ifdef TLS_FUNCS OBJS += ../src/crypto/tls_openssl.o diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 410196597..e4f3eb3e6 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -1275,6 +1275,40 @@ struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, struct crypto_ec_key *key, enum crypto_hash_alg algo); +struct crypto_rsa_key; + +/** + * crypto_rsa_key_read - Read an RSA key + * @file: File from which to read (PEM encoded, can be X.509v3 certificate) + * @private_key: Whether to read the private key instead of public key + * Returns: RSA key or %NULL on failure + */ +struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key); + +/** + * crypto_rsa_oaep_sha256_encrypt - RSA-OAEP-SHA-256 encryption + * @key: RSA key from crypto_rsa_key_read() + * @in: Plaintext input data + * Returns: Encrypted output data or %NULL on failure + */ +struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key, + const struct wpabuf *in); + +/** + * crypto_rsa_oaep_sha256_decrypt - RSA-OAEP-SHA-256 decryption + * @key: RSA key from crypto_rsa_key_read() + * @in: Encrypted input data + * Returns: Decrypted output data or %NULL on failure + */ +struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key, + const struct wpabuf *in); + +/** + * crypto_rsa_key_free - Free an RSA key + * @key: RSA key from crypto_rsa_key_read() + */ +void crypto_rsa_key_free(struct crypto_rsa_key *key); + /** * crypto_unload - Unload crypto resources * diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index cd3d3e245..fbda869c1 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -16,10 +16,10 @@ #include #include #include +#include #ifdef CONFIG_ECC #include #include -#include #endif /* CONFIG_ECC */ #if OPENSSL_VERSION_NUMBER >= 0x30000000L #include @@ -3939,6 +3939,125 @@ struct wpabuf * crypto_csr_sign(struct crypto_csr *csr, #endif /* CONFIG_ECC */ +static EVP_PKEY * crypto_rsa_key_read_public(FILE *f) +{ + EVP_PKEY *pkey; + X509 *x509; + + pkey = PEM_read_PUBKEY(f, NULL, NULL, NULL); + if (pkey) + return pkey; + + rewind(f); + x509 = PEM_read_X509(f, NULL, NULL, NULL); + if (!x509) + return NULL; + + pkey = X509_get_pubkey(x509); + X509_free(x509); + + if (!pkey) + return NULL; + if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { + EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; +} + + +struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key) +{ + FILE *f; + EVP_PKEY *pkey; + + f = fopen(file, "r"); + if (!f) + return NULL; + if (private_key) + pkey = PEM_read_PrivateKey(f, NULL, NULL, NULL); + else + pkey = crypto_rsa_key_read_public(f); + fclose(f); + return (struct crypto_rsa_key *) pkey; +} + + +#ifndef OPENSSL_NO_SHA256 + +struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key, + const struct wpabuf *in) +{ + EVP_PKEY *pkey = (EVP_PKEY *) key; + EVP_PKEY_CTX *pkctx; + struct wpabuf *res = NULL; + size_t outlen; + + pkctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pkctx) + goto fail; + + if (EVP_PKEY_encrypt_init(pkctx) != 1 || + EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 || + EVP_PKEY_encrypt(pkctx, NULL, &outlen, wpabuf_head(in), + wpabuf_len(in)) != 1 || + !(res = wpabuf_alloc(outlen)) || + EVP_PKEY_encrypt(pkctx, wpabuf_put(res, 0), &outlen, + wpabuf_head(in), wpabuf_len(in)) != 1) { + wpabuf_free(res); + res = NULL; + goto fail; + } + wpabuf_put(res, outlen); + +fail: + EVP_PKEY_CTX_free(pkctx); + return res; +} + + +struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key, + const struct wpabuf *in) +{ + EVP_PKEY *pkey = (EVP_PKEY *) key; + EVP_PKEY_CTX *pkctx; + struct wpabuf *res = NULL; + size_t outlen; + + pkctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pkctx) + goto fail; + + if (EVP_PKEY_decrypt_init(pkctx) != 1 || + EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, EVP_sha256()) <= 0 || + EVP_PKEY_decrypt(pkctx, NULL, &outlen, wpabuf_head(in), + wpabuf_len(in)) != 1 || + !(res = wpabuf_alloc(outlen)) || + EVP_PKEY_decrypt(pkctx, wpabuf_put(res, 0), &outlen, + wpabuf_head(in), wpabuf_len(in)) != 1) { + wpabuf_free(res); + res = NULL; + goto fail; + } + wpabuf_put(res, outlen); + +fail: + EVP_PKEY_CTX_free(pkctx); + return res; +} + +#endif /* OPENSSL_NO_SHA256 */ + + +void crypto_rsa_key_free(struct crypto_rsa_key *key) +{ + EVP_PKEY_free((EVP_PKEY *) key); +} + + void crypto_unload(void) { openssl_unload_legacy_provider(); diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index 5d68ffa1d..34d37fdcc 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -1071,6 +1071,7 @@ L_CFLAGS += -DCONFIG_TLSV12 endif ifeq ($(CONFIG_TLS), openssl) +L_CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ifdef TLS_FUNCS L_CFLAGS += -DEAP_TLS_OPENSSL OBJS += src/crypto/tls_openssl.c diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index ead9205ff..d12b485a8 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1121,6 +1121,7 @@ LIBS_p += -lwolfssl -lm endif ifeq ($(CONFIG_TLS), openssl) +CFLAGS += -DCRYPTO_RSA_OAEP_SHA256 ifdef TLS_FUNCS CFLAGS += -DEAP_TLS_OPENSSL OBJS += ../src/crypto/tls_openssl.o