From: Andreas Steffen Date: Mon, 8 Nov 2021 08:34:57 +0000 (+0100) Subject: openssl: Implemented RSA OAEP encryption/decryption with optional labels X-Git-Tag: 5.9.5dr2~5^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6adb5433418eaeb731f5d0cbcfcad9e8dc2275b9;p=thirdparty%2Fstrongswan.git openssl: Implemented RSA OAEP encryption/decryption with optional labels --- diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index bf6a3dad2e..5009f4e3f0 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -689,12 +689,20 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_256), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_224), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_256), + PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA224), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA224), + PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA256), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA256), #endif #ifndef OPENSSL_NO_SHA512 PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_384), PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_512), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_384), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_512), + PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA384), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA384), + PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA512), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA512), #endif #if OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_SHA3) PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA3_224), @@ -711,7 +719,9 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5), #endif PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_PKCS1), - PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_PKCS1), + PLUGIN_PROVIDE(PRIVKEY_DECRYPT, ENCRYPT_RSA_OAEP_SHA1), + PLUGIN_PROVIDE(PUBKEY_ENCRYPT, ENCRYPT_RSA_OAEP_SHA1), #endif /* OPENSSL_NO_RSA */ /* certificate/CRL loading */ PLUGIN_REGISTER(CERT_DECODE, openssl_x509_load, TRUE), diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index b4a122b5ad..15a4ead3da 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -308,8 +309,14 @@ METHOD(private_key_t, decrypt, bool, private_openssl_rsa_private_key_t *this, encryption_scheme_t scheme, void *params, chunk_t crypto, chunk_t *plain) { - int padding, len; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *evp_key = NULL; + chunk_t label = chunk_empty; + hash_algorithm_t hash_alg = HASH_UNKNOWN; + size_t len; + int padding; char *decrypted; + bool success = FALSE; switch (scheme) { @@ -317,24 +324,115 @@ METHOD(private_key_t, decrypt, bool, padding = RSA_PKCS1_PADDING; break; case ENCRYPT_RSA_OAEP_SHA1: + hash_alg = HASH_SHA1; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA224: + hash_alg = HASH_SHA224; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA256: + hash_alg = HASH_SHA256; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA384: + hash_alg = HASH_SHA384; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA512: + hash_alg = HASH_SHA512; padding = RSA_PKCS1_OAEP_PADDING; break; default: - DBG1(DBG_LIB, "encryption scheme %N not supported via openssl", + DBG1(DBG_LIB, "encryption scheme %N not supported by openssl", encryption_scheme_names, scheme); return FALSE; } - decrypted = malloc(RSA_size(this->rsa)); - len = RSA_private_decrypt(crypto.len, crypto.ptr, decrypted, - this->rsa, padding); - if (len < 0) + + evp_key = EVP_PKEY_new(); + if (!evp_key) + { + DBG1(DBG_LIB, "could not create EVP key"); + goto error; + } + if (EVP_PKEY_set1_RSA(evp_key, this->rsa) <= 0) + { + DBG1(DBG_LIB, "could not set EVP key to RSA key"); + goto error; + } + + ctx = EVP_PKEY_CTX_new(evp_key, NULL); + if (!ctx) + { + DBG1(DBG_LIB, "could not create EVP context"); + goto error; + } + + if (EVP_PKEY_decrypt_init(ctx) <= 0) + { + DBG1(DBG_LIB, "could not initialize RSA decryption"); + goto error; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0) + { + DBG1(DBG_LIB, "could not set RSA padding"); + goto error; + } + if (padding == RSA_PKCS1_OAEP_PADDING) + { + const EVP_MD *md = openssl_get_md(hash_alg); + + if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) + { + DBG1(DBG_LIB, "could not set RSA OAEP hash algorithm"); + goto error; + } + + if (params) + { + label = *(chunk_t *)params; + } + if (label.len > 0) + { + uint8_t *label_cpy; + + /* Openssl requires a copy of its own */ + label_cpy = (uint8_t *)OPENSSL_malloc(label.len); + memcpy(label_cpy, label.ptr, label.len); + + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_cpy, label.len) <= 0) + { + OPENSSL_free(label_cpy); + DBG1(DBG_LIB, "could not set RSA OAEP label"); + goto error; + } + } + } + + /* determine maximum plaintext size */ + len = RSA_size(this->rsa); + decrypted = malloc(len); + + /* decrypt data */ + if (EVP_PKEY_decrypt(ctx, decrypted, &len, crypto.ptr, crypto.len) <= 0) { DBG1(DBG_LIB, "RSA decryption failed"); free(decrypted); - return FALSE; + goto error; } *plain = chunk_create(decrypted, len); - return TRUE; + success = TRUE; + +error: + if (ctx) + { + EVP_PKEY_CTX_free(ctx); + } + if (evp_key) + { + EVP_PKEY_free(evp_key); + } + return success; } METHOD(private_key_t, get_keysize, int, diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 41793484ef..d5c9eed1ea 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -309,8 +310,14 @@ METHOD(public_key_t, encrypt, bool, private_openssl_rsa_public_key_t *this, encryption_scheme_t scheme, void *params, chunk_t plain, chunk_t *crypto) { - int padding, len; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *evp_key = NULL; + chunk_t label = chunk_empty; + hash_algorithm_t hash_alg = HASH_UNKNOWN; + size_t len; + int padding; char *encrypted; + bool success = FALSE; switch (scheme) { @@ -318,24 +325,115 @@ METHOD(public_key_t, encrypt, bool, padding = RSA_PKCS1_PADDING; break; case ENCRYPT_RSA_OAEP_SHA1: + hash_alg = HASH_SHA1; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA224: + hash_alg = HASH_SHA224; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA256: + hash_alg = HASH_SHA256; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA384: + hash_alg = HASH_SHA384; + padding = RSA_PKCS1_OAEP_PADDING; + break; + case ENCRYPT_RSA_OAEP_SHA512: + hash_alg = HASH_SHA512; padding = RSA_PKCS1_OAEP_PADDING; break; default: - DBG1(DBG_LIB, "decryption scheme %N not supported via openssl", + DBG1(DBG_LIB, "encryption scheme %N not supported by openssl", encryption_scheme_names, scheme); return FALSE; } - encrypted = malloc(RSA_size(this->rsa)); - len = RSA_public_encrypt(plain.len, plain.ptr, encrypted, - this->rsa, padding); - if (len < 0) + + evp_key = EVP_PKEY_new(); + if (!evp_key) + { + DBG1(DBG_LIB, "could not create EVP key"); + goto error; + } + if (EVP_PKEY_set1_RSA(evp_key, this->rsa) <= 0) + { + DBG1(DBG_LIB, "could not set EVP key to RSA key"); + goto error; + } + + ctx = EVP_PKEY_CTX_new(evp_key, NULL); + if (!ctx) + { + DBG1(DBG_LIB, "could not create EVP context"); + goto error; + } + + if (EVP_PKEY_encrypt_init(ctx) <= 0) + { + DBG1(DBG_LIB, "could not initialize RSA encryption"); + goto error; + } + if (EVP_PKEY_CTX_set_rsa_padding(ctx, padding) <= 0) + { + DBG1(DBG_LIB, "could not set RSA padding"); + goto error; + } + if (padding == RSA_PKCS1_OAEP_PADDING) { - DBG1(DBG_LIB, "RSA decryption failed"); + const EVP_MD *md = openssl_get_md(hash_alg); + + if (EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md) <= 0) + { + DBG1(DBG_LIB, "could not set RSA OAEP hash algorithm"); + goto error; + } + + if (params) + { + label = *(chunk_t *)params; + } + if (label.len > 0) + { + uint8_t *label_cpy; + + /* Openssl requires a copy of its own */ + label_cpy = (uint8_t *)OPENSSL_malloc(label.len); + memcpy(label_cpy, label.ptr, label.len); + + if (EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, label_cpy, label.len) <= 0) + { + OPENSSL_free(label_cpy); + DBG1(DBG_LIB, "could not set RSA OAEP label"); + goto error; + } + } + } + + /* determine maximum ciphertext size */ + len = RSA_size(this->rsa); + encrypted = malloc(len); + + /* decrypt data */ + if (EVP_PKEY_encrypt(ctx, encrypted, &len, plain.ptr, plain.len) <= 0) + { + DBG1(DBG_LIB, "RSA encryption failed"); free(encrypted); - return FALSE; + goto error; } *crypto = chunk_create(encrypted, len); - return TRUE; + success = TRUE; + +error: + if (ctx) + { + EVP_PKEY_CTX_free(ctx); + } + if (evp_key) + { + EVP_PKEY_free(evp_key); + } + return success; } METHOD(public_key_t, get_keysize, int,