diff --git a/README.md b/README.md index 0ea5a8f6c..488923ddc 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ SoftHSM depends on a cryptographic library, Botan or OpenSSL. Minimum required versions: - Botan 2.0.0 -- OpenSSL 1.0.0 +- OpenSSL 1.0.2 If you are using Botan, use at least version 2.6.0. This will improve the performance when doing public key operations. diff --git a/m4/acx_crypto_backend.m4 b/m4/acx_crypto_backend.m4 index fe59ca97f..f0ea1f33b 100644 --- a/m4/acx_crypto_backend.m4 +++ b/m4/acx_crypto_backend.m4 @@ -75,9 +75,11 @@ AC_DEFUN([ACX_CRYPTO_BACKEND],[ AC_MSG_RESULT(OpenSSL) if test "x${enable_fips}" = "xyes"; then - ACX_OPENSSL(1,0,1) + # needed for FIPS compliance, so change only when FIPS requirements change + ACX_OPENSSL(1,0,2) else - ACX_OPENSSL(1,0,0) + # increase this as features from newer versions needed + ACX_OPENSSL(1,0,2) fi CRYPTO_INCLUDES=$OPENSSL_INCLUDES diff --git a/src/lib/SoftHSM.cpp b/src/lib/SoftHSM.cpp index 234fbfa18..421f63038 100644 --- a/src/lib/SoftHSM.cpp +++ b/src/lib/SoftHSM.cpp @@ -2478,7 +2478,27 @@ CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMec if (rv != CKR_OK) return rv; - mechanism = AsymMech::RSA_PKCS_OAEP; + switch(CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg) { + case CKM_SHA_1: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA1; + break; + case CKM_SHA224: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA224; + break; + case CKM_SHA256: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA256; + break; + case CKM_SHA384: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA384; + break; + case CKM_SHA512: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA512; + break; + default: + DEBUG_MSG("hashAlg must be one of: CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512"); + return CKR_ARGUMENTS_BAD; + } + isRSA = true; break; default: @@ -3214,18 +3234,38 @@ CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMec DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS"); return CKR_ARGUMENTS_BAD; } - if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1) - { - DEBUG_MSG("hashAlg must be CKM_SHA_1"); - return CKR_ARGUMENTS_BAD; + + switch(CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg) { + case CKM_SHA_1: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA1; + break; + case CKM_SHA224: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA224; + break; + case CKM_SHA256: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA256; + break; + case CKM_SHA384: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA384; + break; + case CKM_SHA512: + mechanism = AsymMech::RSA_PKCS_OAEP_SHA512; + break; + default: + DEBUG_MSG("hashAlg must be one of: CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512"); + return CKR_ARGUMENTS_BAD; } - if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1) + + if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1 && + CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224 && + CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256 && + CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384 && + CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512) { - DEBUG_MSG("mgf must be CKG_MGF1_SHA1"); + DEBUG_MSG("mgf must be one of: CKG_MGF1_SHA1, CKG_MGF1_SHA224, CKG_MGF1_SHA256, CKG_MGF1_SHA384, CKG_MGF1_SHA512"); return CKR_ARGUMENTS_BAD; } - mechanism = AsymMech::RSA_PKCS_OAEP; isRSA = true; break; default: @@ -6474,11 +6514,40 @@ CK_RV SoftHSM::WrapKeyAsym break; case CKM_RSA_PKCS_OAEP: - mech = AsymMech::RSA_PKCS_OAEP; - // SHA-1 is the only supported option - // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen - if (keydata.size() > modulus_length - 2 - 2 * 160 / 8) - return CKR_KEY_SIZE_RANGE; + switch(CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg) { + case CKM_SHA_1: + mech = AsymMech::RSA_PKCS_OAEP_SHA1; + // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen + if (keydata.size() > modulus_length - 2 - 2 * 160 / 8) + return CKR_KEY_SIZE_RANGE; + break; + case CKM_SHA224: + mech = AsymMech::RSA_PKCS_OAEP_SHA224; + // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen + if (keydata.size() > modulus_length - 2 - 2 * 224 / 8) + return CKR_KEY_SIZE_RANGE; + break; + case CKM_SHA256: + mech = AsymMech::RSA_PKCS_OAEP_SHA256; + // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen + if (keydata.size() > modulus_length - 2 - 2 * 256 / 8) + return CKR_KEY_SIZE_RANGE; + break; + case CKM_SHA384: + mech = AsymMech::RSA_PKCS_OAEP_SHA384; + // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen + if (keydata.size() > modulus_length - 2 - 2 * 384 / 8) + return CKR_KEY_SIZE_RANGE; + break; + case CKM_SHA512: + mech = AsymMech::RSA_PKCS_OAEP_SHA512; + // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen + if (keydata.size() > modulus_length - 2 - 2 * 512 / 8) + return CKR_KEY_SIZE_RANGE; + break; + default: + return CKR_MECHANISM_INVALID; + } break; default: @@ -7044,7 +7113,25 @@ CK_RV SoftHSM::UnwrapKeyAsym case CKM_RSA_PKCS_OAEP: algo = AsymAlgo::RSA; - mode = AsymMech::RSA_PKCS_OAEP; + switch(CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg) { + case CKM_SHA_1: + mode = AsymMech::RSA_PKCS_OAEP_SHA1; + break; + case CKM_SHA224: + mode = AsymMech::RSA_PKCS_OAEP_SHA224; + break; + case CKM_SHA256: + mode = AsymMech::RSA_PKCS_OAEP_SHA256; + break; + case CKM_SHA384: + mode = AsymMech::RSA_PKCS_OAEP_SHA384; + break; + case CKM_SHA512: + mode = AsymMech::RSA_PKCS_OAEP_SHA512; + break; + default: + return CKR_MECHANISM_INVALID; + } break; default: @@ -13175,14 +13262,22 @@ CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism) } CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter; - if (params->hashAlg != CKM_SHA_1) + if (params->hashAlg != CKM_SHA_1 && + params->hashAlg != CKM_SHA224 && + params->hashAlg != CKM_SHA256 && + params->hashAlg != CKM_SHA384 && + params->hashAlg != CKM_SHA512) { - ERROR_MSG("hashAlg must be CKM_SHA_1"); + ERROR_MSG("hashAlg must be one of: CKM_SHA_1, CKM_SHA224, CKM_SHA256, CKM_SHA384, CKM_SHA512"); return CKR_ARGUMENTS_BAD; } - if (params->mgf != CKG_MGF1_SHA1) + if (params->mgf != CKG_MGF1_SHA1 && + params->mgf != CKG_MGF1_SHA224 && + params->mgf != CKG_MGF1_SHA256 && + params->mgf != CKG_MGF1_SHA384 && + params->mgf != CKG_MGF1_SHA512) { - ERROR_MSG("mgf must be CKG_MGF1_SHA1"); + ERROR_MSG("mgf must be one of: CKG_MGF1_SHA1, CKG_MGF1_SHA224, CKG_MGF1_SHA256, CKG_MGF1_SHA384, CKG_MGF1_SHA512"); return CKR_ARGUMENTS_BAD; } if (params->source != CKZ_DATA_SPECIFIED) diff --git a/src/lib/crypto/AsymmetricAlgorithm.cpp b/src/lib/crypto/AsymmetricAlgorithm.cpp index 20a50a5fc..c4bbdf069 100644 --- a/src/lib/crypto/AsymmetricAlgorithm.cpp +++ b/src/lib/crypto/AsymmetricAlgorithm.cpp @@ -147,7 +147,11 @@ bool AsymmetricAlgorithm::isWrappingMech(AsymMech::Type padding) { case AsymMech::RSA: case AsymMech::RSA_PKCS: - case AsymMech::RSA_PKCS_OAEP: + case AsymMech::RSA_PKCS_OAEP_SHA1: + case AsymMech::RSA_PKCS_OAEP_SHA224: + case AsymMech::RSA_PKCS_OAEP_SHA256: + case AsymMech::RSA_PKCS_OAEP_SHA384: + case AsymMech::RSA_PKCS_OAEP_SHA512: return true; default: diff --git a/src/lib/crypto/AsymmetricAlgorithm.h b/src/lib/crypto/AsymmetricAlgorithm.h index 52519db65..1fa8882c0 100644 --- a/src/lib/crypto/AsymmetricAlgorithm.h +++ b/src/lib/crypto/AsymmetricAlgorithm.h @@ -65,7 +65,11 @@ struct AsymMech RSA, RSA_MD5_PKCS, RSA_PKCS, - RSA_PKCS_OAEP, + RSA_PKCS_OAEP_SHA1, + RSA_PKCS_OAEP_SHA224, + RSA_PKCS_OAEP_SHA256, + RSA_PKCS_OAEP_SHA384, + RSA_PKCS_OAEP_SHA512, RSA_SHA1_PKCS, RSA_SHA224_PKCS, RSA_SHA256_PKCS, diff --git a/src/lib/crypto/BotanRSA.cpp b/src/lib/crypto/BotanRSA.cpp index 3ed450ef0..9a0b9a74e 100644 --- a/src/lib/crypto/BotanRSA.cpp +++ b/src/lib/crypto/BotanRSA.cpp @@ -761,8 +761,20 @@ bool BotanRSA::encrypt(PublicKey* publicKey, const ByteString& data, case AsymMech::RSA_PKCS: eme = "PKCS1v15"; break; - case AsymMech::RSA_PKCS_OAEP: - eme = "EME1(SHA-160)"; + case AsymMech::RSA_PKCS_OAEP_SHA1: + eme = "OAEP(SHA-160)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA224: + eme = "OAEP(SHA-224)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA256: + eme = "OAEP(SHA-256)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA384: + eme = "OAEP(SHA-384)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA512: + eme = "OAEP(SHA-512)"; break; case AsymMech::RSA: eme = "Raw"; @@ -840,8 +852,20 @@ bool BotanRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, case AsymMech::RSA_PKCS: eme = "PKCS1v15"; break; - case AsymMech::RSA_PKCS_OAEP: - eme = "EME1(SHA-160)"; + case AsymMech::RSA_PKCS_OAEP_SHA1: + eme = "OAEP(SHA-160)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA224: + eme = "OAEP(SHA-224)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA256: + eme = "OAEP(SHA-256)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA384: + eme = "OAEP(SHA-384)"; + break; + case AsymMech::RSA_PKCS_OAEP_SHA512: + eme = "OAEP(SHA-512)"; break; case AsymMech::RSA: eme = "Raw"; diff --git a/src/lib/crypto/OSSLRSA.cpp b/src/lib/crypto/OSSLRSA.cpp index d36a1e682..5dd0c0ff4 100644 --- a/src/lib/crypto/OSSLRSA.cpp +++ b/src/lib/crypto/OSSLRSA.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include // Constructor @@ -1219,64 +1220,137 @@ bool OSSLRSA::encrypt(PublicKey* publicKey, const ByteString& data, // Retrieve the OpenSSL key object RSA* rsa = ((OSSLRSAPublicKey*) publicKey)->getOSSLKey(); - // Check the data and padding algorithm - int osslPadding = 0; + EVP_PKEY *pkey = EVP_PKEY_new(); + if (pkey == NULL) { + ERROR_MSG("Failed to generate new EVP_PKEY (0x%08lX)", ERR_get_error()); + return false; + } - if (padding == AsymMech::RSA_PKCS) - { - // The size of the input data cannot be more than the modulus - // length of the key - 11 - if (data.size() > (size_t) (RSA_size(rsa) - 11)) - { - ERROR_MSG("Too much data supplied for RSA PKCS #1 encryption"); + if (EVP_PKEY_set1_RSA(pkey, rsa) != 1) { + ERROR_MSG("EVP_PKEY_set1_RSA failed (0x%08lX)", ERR_get_error()); + return false; + } + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (ctx == NULL) { + ERROR_MSG("EVP_PKEY_CTX_new failed"); + EVP_PKEY_free(pkey); + return false; + } + if (EVP_PKEY_encrypt_init(ctx) != 1) { + ERROR_MSG("EVP_PKEY_encrypt_init failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } - return false; - } + size_t maxPad = 0; - osslPadding = RSA_PKCS1_PADDING; - } - else if (padding == AsymMech::RSA_PKCS_OAEP) + switch (padding) { - // The size of the input data cannot be more than the modulus - // length of the key - 41 - if (data.size() > (size_t) (RSA_size(rsa) - 41)) - { - ERROR_MSG("Too much data supplied for RSA OAEP encryption"); + case AsymMech::RSA_PKCS: + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); + maxPad = 11; + break; + case AsymMech::RSA_PKCS_OAEP_SHA1: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha1()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha1()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-1) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + maxPad = 2 * 160/8 + 2; + break; + case AsymMech::RSA_PKCS_OAEP_SHA224: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha224()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha224()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-224) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + maxPad = 2 * 224/8 + 2; + break; + case AsymMech::RSA_PKCS_OAEP_SHA256: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-256) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + maxPad = 2 * 256/8 + 2; + break; + case AsymMech::RSA_PKCS_OAEP_SHA384: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha384()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha384()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-384) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + maxPad = 2 * 384/8 + 2; + break; + case AsymMech::RSA_PKCS_OAEP_SHA512: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha512()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha512()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-512) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + maxPad = 2 * 512/8 + 2; + break; + case AsymMech::RSA: + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING); + break; + default: + ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return false; - } - - osslPadding = RSA_PKCS1_OAEP_PADDING; } - else if (padding == AsymMech::RSA) - { - // The size of the input data should be exactly equal to the modulus length - if (data.size() != (size_t) RSA_size(rsa)) - { - ERROR_MSG("Incorrect amount of input data supplied for raw RSA encryption"); - return false; - } + // The size of the input data cannot be more than the modulus + // length of the key - maxPad + if (data.size() > (size_t) (RSA_size(rsa) - maxPad)) + { + ERROR_MSG("Too much data supplied for encryption"); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); - osslPadding = RSA_NO_PADDING; + return false; } - else - { - ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + + size_t outSize = 0; + int ret = EVP_PKEY_encrypt(ctx, NULL, &outSize, data.const_byte_str(), data.size()); + if (ret <= 0) { + ERROR_MSG("RSA public key encryption failed (0x%08X)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return false; } // Perform the RSA operation - encryptedData.resize(RSA_size(rsa)); - - if (RSA_public_encrypt(data.size(), (unsigned char*) data.const_byte_str(), &encryptedData[0], rsa, osslPadding) == -1) - { - ERROR_MSG("RSA public key encryption failed (0x%08X)", ERR_get_error()); + encryptedData.resize(outSize); + ret = EVP_PKEY_encrypt(ctx, &encryptedData[0], &outSize, data.const_byte_str(), data.size()); + if (ret <= 0) { + ERROR_MSG("RSA private key encryption failed (0x%08X)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return false; } + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return true; } @@ -1303,38 +1377,121 @@ bool OSSLRSA::decrypt(PrivateKey* privateKey, const ByteString& encryptedData, return false; } - // Determine the OpenSSL padding algorithm - int osslPadding = 0; + EVP_PKEY *pkey = EVP_PKEY_new(); + if (!pkey) { + ERROR_MSG("Failed to generate new EVP_PKEY (0x%08lX)", ERR_get_error()); + return false; + } + if (EVP_PKEY_set1_RSA(pkey, rsa) != 1) { + ERROR_MSG("EVP_PKEY_set1_RSA failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_free(pkey); + return false; + } + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!ctx) { + ERROR_MSG("EVP_PKEY_CTX_new failed"); + EVP_PKEY_free(pkey); + return false; + } + if (EVP_PKEY_decrypt_init(ctx) != 1) { + ERROR_MSG("EVP_PKEY_decrypt_init failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } switch (padding) { case AsymMech::RSA_PKCS: - osslPadding = RSA_PKCS1_PADDING; + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); + break; + case AsymMech::RSA_PKCS_OAEP_SHA1: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha1()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha1()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-1) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + break; + case AsymMech::RSA_PKCS_OAEP_SHA224: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha224()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha224()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-224) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + break; + case AsymMech::RSA_PKCS_OAEP_SHA256: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha256()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha256()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-256) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } + break; + case AsymMech::RSA_PKCS_OAEP_SHA384: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha384()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha384()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-384) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } break; - case AsymMech::RSA_PKCS_OAEP: - osslPadding = RSA_PKCS1_OAEP_PADDING; + case AsymMech::RSA_PKCS_OAEP_SHA512: + if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_oaep_md(ctx, EVP_sha512()) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(ctx, EVP_sha512()) <= 0) { + ERROR_MSG("Configuring RSA OAEP(SHA-512) failed (0x%08lX)", ERR_get_error()); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; + } break; case AsymMech::RSA: - osslPadding = RSA_NO_PADDING; + EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING); break; default: ERROR_MSG("Invalid padding mechanism supplied (%i)", padding); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + return false; } - // Perform the RSA operation - data.resize(RSA_size(rsa)); + size_t outSize = 0; + int ret = EVP_PKEY_decrypt(ctx, NULL, &outSize, encryptedData.const_byte_str(), encryptedData.size()); + if (ret <= 0) { + ERROR_MSG("RSA private key decryption failed (0x%08X)", ret); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); - int decSize = RSA_private_decrypt(encryptedData.size(), (unsigned char*) encryptedData.const_byte_str(), &data[0], rsa, osslPadding); + return false; + } - if (decSize == -1) - { - ERROR_MSG("RSA private key decryption failed (0x%08X)", ERR_get_error()); + // Perform the RSA operation + data.resize(outSize); + ret = EVP_PKEY_decrypt(ctx, &data[0], &outSize, encryptedData.const_byte_str(), encryptedData.size()); + if (ret <= 0) { + ERROR_MSG("RSA private key decryption failed (0x%08X)", ret); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return false; } - data.resize(decSize); + // Resize result + data.resize(outSize); + + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); return true; } diff --git a/src/lib/crypto/OSSLRSAPrivateKey.cpp b/src/lib/crypto/OSSLRSAPrivateKey.cpp index 26065cf31..9e708d4ef 100644 --- a/src/lib/crypto/OSSLRSAPrivateKey.cpp +++ b/src/lib/crypto/OSSLRSAPrivateKey.cpp @@ -36,6 +36,7 @@ #include "OSSLRSAPrivateKey.h" #include "OSSLUtil.h" #include +#include #include #ifdef WITH_FIPS #include diff --git a/src/lib/crypto/test/RSATests.cpp b/src/lib/crypto/test/RSATests.cpp index 6af1e19fb..9ae340511 100644 --- a/src/lib/crypto/test/RSATests.cpp +++ b/src/lib/crypto/test/RSATests.cpp @@ -619,7 +619,11 @@ void RSATests::testEncryptDecrypt() // Paddings to test std::vector paddings; paddings.push_back(AsymMech::RSA_PKCS); - paddings.push_back(AsymMech::RSA_PKCS_OAEP); + paddings.push_back(AsymMech::RSA_PKCS_OAEP_SHA1); + paddings.push_back(AsymMech::RSA_PKCS_OAEP_SHA224); + paddings.push_back(AsymMech::RSA_PKCS_OAEP_SHA256); + paddings.push_back(AsymMech::RSA_PKCS_OAEP_SHA384); + paddings.push_back(AsymMech::RSA_PKCS_OAEP_SHA512); paddings.push_back(AsymMech::RSA); for (std::vector::iterator e = exponents.begin(); e != exponents.end(); e++) @@ -641,11 +645,28 @@ void RSATests::testEncryptDecrypt() if (*pad == AsymMech::RSA_PKCS) { - CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 12)); + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 11)); } - else if (*pad == AsymMech::RSA_PKCS_OAEP) + else if (*pad == AsymMech::RSA_PKCS_OAEP_SHA1) { - CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - 42)); + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - (2*160/8+2))); + } + else if (*pad == AsymMech::RSA_PKCS_OAEP_SHA224) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - (2*224/8+2))); + } + else if (*pad == AsymMech::RSA_PKCS_OAEP_SHA256) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - (2*256/8+2))); + } + else if (*pad == AsymMech::RSA_PKCS_OAEP_SHA384) + { + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - (2*384/8+2))); + } + else if (*pad == AsymMech::RSA_PKCS_OAEP_SHA512) + { + if (*k < 1280) continue; + CPPUNIT_ASSERT(rng->generateRandom(testData, (*k >> 3) - (2*512/8+2))); } else if (*pad == AsymMech::RSA) { diff --git a/src/lib/test/AsymEncryptDecryptTests.cpp b/src/lib/test/AsymEncryptDecryptTests.cpp index 2a537d00a..24092ec53 100644 --- a/src/lib/test/AsymEncryptDecryptTests.cpp +++ b/src/lib/test/AsymEncryptDecryptTests.cpp @@ -137,11 +137,6 @@ void AsymEncryptDecryptTests::rsaOAEPParams(CK_SESSION_HANDLE hSession, CK_OBJEC rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) ); CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); - oaepParams.hashAlg = CKM_SHA_1; - oaepParams.mgf = CKG_MGF1_SHA256; - rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) ); - CPPUNIT_ASSERT(rv==CKR_ARGUMENTS_BAD); - oaepParams.mgf = CKG_MGF1_SHA1; oaepParams.source = CKZ_DATA_SPECIFIED - 1; rv = CRYPTOKI_F_PTR( C_EncryptInit(hSession,&mechanism,hPublicKey) );