From 89ff5da9f9787be29c173ad5d5c0beb0c262e3cc Mon Sep 17 00:00:00 2001 From: Chris Ruffin Date: Sun, 31 Mar 2024 05:59:43 +0800 Subject: CryptoPkg/BaseCryptLib: add additional RSAES-OAEP crypto functions Expand the availability of the RSAES-OAEP crypto capability in BaseCryptLib. Applications using RSA crypto functions directly from OpensslLib can transition to BaseCryptLib to take advantage of the shared crypto feature in CryptoDxe. Pkcs1v2Decrypt(): decryption using DER-encoded private key RsaOaepEncrypt(): encryption using RSA contexts RsaOaepDecrypt(): decryption using RSA contexts Fixes: https://bugzilla.tianocore.org/show_bug.cgi?id=4732 Gihub PR: https://github.com/tianocore/edk2/pull/5473 Signed-off-by: Chris Ruffin Cc: Chris Ruffin Cc: Jiewen Yao Cc: Yi Li Cc: Wenxing Hou Reviewed-by: Yi Li --- CryptoPkg/Include/Library/BaseCryptLib.h | 117 ++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c | 598 +++++++++++++++++++-- .../Library/BaseCryptLib/Pk/CryptPkcs1OaepNull.c | 130 ++++- .../BaseCryptLibMbedTls/Pk/CryptPkcs1OaepNull.c | 129 +++++ .../BaseCryptLibNull/Pk/CryptPkcs1OaepNull.c | 130 ++++- 5 files changed, 1054 insertions(+), 50 deletions(-) (limited to 'CryptoPkg') diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index a52bd91..86f784a 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -5,6 +5,7 @@ functionality enabling. Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -2148,6 +2149,122 @@ Pkcs1v2Encrypt ( ); /** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a public key using RsaSetKey(). + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepEncrypt ( + IN VOID *RsaContext, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ); + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] PrivateKey A pointer to the DER-encoded private key. + @param[in] PrivateKeySize Size of the private key buffer. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Decrypt ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ); + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a private key using RsaSetKey(). + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepDecrypt ( + IN VOID *RsaContext, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ); + +/** The 3rd parameter of Pkcs7GetSigners will return all embedded X.509 certificate in one given PKCS7 signature. The format is: // diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c index ea43c13..7634ab1 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c @@ -3,7 +3,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent - Copyright (C) 2016 Microsoft Corporation. All Rights Reserved. + Copyright (C) Microsoft Corporation. All Rights Reserved. Copyright (c) 2019, Intel Corporation. All rights reserved.
**/ @@ -15,6 +15,37 @@ #include /** + Retrieve a pointer to EVP message digest object. + + @param[in] DigestLen Length of the message digest. + +**/ +STATIC +const +EVP_MD * +GetEvpMD ( + IN UINT16 DigestLen + ) +{ + switch (DigestLen) { + case SHA1_DIGEST_SIZE: + return EVP_sha1 (); + break; + case SHA256_DIGEST_SIZE: + return EVP_sha256 (); + break; + case SHA384_DIGEST_SIZE: + return EVP_sha384 (); + break; + case SHA512_DIGEST_SIZE: + return EVP_sha512 (); + break; + default: + return NULL; + } +} + +/** Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the encrypted message in a newly allocated buffer. @@ -26,15 +57,20 @@ - Data size is too large for the provided key size (max size is a function of key size and hash digest size). - @param[in] PublicKey A pointer to the DER-encoded X509 certificate that + @param[in] Pkey A pointer to an EVP_PKEY struct that will be used to encrypt the data. - @param[in] PublicKeySize Size of the X509 cert buffer. @param[in] InData Data to be encrypted. @param[in] InDataSize Size of the data buffer. @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer to be used when initializing the PRNG. NULL otherwise. @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted message. @param[out] EncryptedDataSize Size of the encrypted message buffer. @@ -45,50 +81,35 @@ **/ BOOLEAN EFIAPI -Pkcs1v2Encrypt ( - IN CONST UINT8 *PublicKey, - IN UINTN PublicKeySize, +InternalPkcs1v2Encrypt ( + EVP_PKEY *Pkey, IN UINT8 *InData, IN UINTN InDataSize, IN CONST UINT8 *PrngSeed OPTIONAL, IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, OUT UINT8 **EncryptedData, OUT UINTN *EncryptedDataSize ) { BOOLEAN Result; - CONST UINT8 *TempPointer; - X509 *CertData; - EVP_PKEY *InternalPublicKey; EVP_PKEY_CTX *PkeyCtx; UINT8 *OutData; UINTN OutDataSize; + CONST EVP_MD *HashAlg; // // Check input parameters. // - if ((PublicKey == NULL) || (InData == NULL) || + if ((Pkey == NULL) || (InData == NULL) || (EncryptedData == NULL) || (EncryptedDataSize == NULL)) { return FALSE; } - // - // Check public key size. - // - if (PublicKeySize > 0xFFFFFFFF) { - // - // Public key size is too large for implementation. - // - return FALSE; - } - *EncryptedData = NULL; *EncryptedDataSize = 0; Result = FALSE; - TempPointer = NULL; - CertData = NULL; - InternalPublicKey = NULL; PkeyCtx = NULL; OutData = NULL; OutDataSize = 0; @@ -105,6 +126,169 @@ Pkcs1v2Encrypt ( } // + // Create a context for the public key operation. + // + PkeyCtx = EVP_PKEY_CTX_new (Pkey, NULL); + if (PkeyCtx == NULL) { + // + // Fail to create contex. + // + goto _Exit; + } + + // + // Initialize the context and set the desired padding. + // + if ((EVP_PKEY_encrypt_init (PkeyCtx) <= 0) || + (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_OAEP_PADDING) <= 0)) + { + // + // Fail to initialize the context. + // + goto _Exit; + } + + if (DigestLen != 0) { + HashAlg = GetEvpMD (DigestLen); + if (HashAlg == NULL) { + goto _Exit; + } + + if (EVP_PKEY_CTX_set_rsa_oaep_md (PkeyCtx, HashAlg) <= 0) { + goto _Exit; + } + + if (EVP_PKEY_CTX_set_rsa_mgf1_md (PkeyCtx, HashAlg) <= 0) { + goto _Exit; + } + } + + // + // Determine the required buffer length for malloc'ing. + // + if (EVP_PKEY_encrypt (PkeyCtx, NULL, &OutDataSize, InData, InDataSize) <= 0) { + // + // Fail to determine output buffer size. + // + goto _Exit; + } + + // + // Allocate a buffer for the output data. + // + OutData = AllocatePool (OutDataSize); + if (OutData == NULL) { + // + // Fail to allocate the output buffer. + // + goto _Exit; + } + + // + // Encrypt Data. + // + if (EVP_PKEY_encrypt (PkeyCtx, OutData, &OutDataSize, InData, InDataSize) <= 0) { + // + // Fail to encrypt data, need to free the output buffer. + // + FreePool (OutData); + OutData = NULL; + OutDataSize = 0; + goto _Exit; + } + + // + // Encrypt done. + // + *EncryptedData = OutData; + *EncryptedDataSize = OutDataSize; + Result = TRUE; + +_Exit: + // + // Release Resources + // + if (PkeyCtx != NULL) { + EVP_PKEY_CTX_free (PkeyCtx); + } + + return Result; +} + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to parse X509 certificate. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] PublicKey A pointer to the DER-encoded X509 certificate that + will be used to encrypt the data. + @param[in] PublicKeySize Size of the X509 cert buffer. + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Encrypt ( + IN CONST UINT8 *PublicKey, + IN UINTN PublicKeySize, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + BOOLEAN Result; + CONST UINT8 *TempPointer; + X509 *CertData; + EVP_PKEY *Pkey; + + // + // Check input parameters. + // + if ((PublicKey == NULL) || (InData == NULL) || + (EncryptedData == NULL) || (EncryptedDataSize == NULL)) + { + return FALSE; + } + + // + // Check public key size. + // + if (PublicKeySize > 0xFFFFFFFF) { + // + // Public key size is too large for implementation. + // + return FALSE; + } + + *EncryptedData = NULL; + *EncryptedDataSize = 0; + Result = FALSE; + TempPointer = NULL; + CertData = NULL; + Pkey = NULL; + + // // Parse the X509 cert and extract the public key. // TempPointer = PublicKey; @@ -120,52 +304,230 @@ Pkcs1v2Encrypt ( // Extract the public key from the x509 cert in a format that // OpenSSL can use. // - InternalPublicKey = X509_get_pubkey (CertData); - if (InternalPublicKey == NULL) { + Pkey = X509_get_pubkey (CertData); + if (Pkey == NULL) { // // Fail to extract public key. // goto _Exit; } + Result = InternalPkcs1v2Encrypt (Pkey, InData, InDataSize, PrngSeed, PrngSeedSize, 0, EncryptedData, EncryptedDataSize); + +_Exit: // - // Create a context for the public key operation. + // Release Resources + // + if (CertData != NULL) { + X509_free (CertData); + } + + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); + } + + return Result; +} + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a public key using RsaSetKey(). + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepEncrypt ( + IN VOID *RsaContext, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + BOOLEAN Result; + EVP_PKEY *Pkey; + // - PkeyCtx = EVP_PKEY_CTX_new (InternalPublicKey, NULL); + // Check input parameters. + // + if (((RsaContext == NULL) || (InData == NULL)) || + (EncryptedData == NULL) || (EncryptedDataSize == NULL)) + { + return FALSE; + } + + *EncryptedData = NULL; + *EncryptedDataSize = 0; + Result = FALSE; + Pkey = NULL; + + Pkey = EVP_PKEY_new (); + if (Pkey == NULL) { + goto _Exit; + } + + if (EVP_PKEY_set1_RSA (Pkey, (RSA *)RsaContext) == 0) { + goto _Exit; + } + + Result = InternalPkcs1v2Encrypt (Pkey, InData, InDataSize, PrngSeed, PrngSeedSize, DigestLen, EncryptedData, EncryptedDataSize); + +_Exit: + // + // Release Resources + // + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); + } + + return Result; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] Pkey A pointer to an EVP_PKEY which will decrypt that data. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +InternalPkcs1v2Decrypt ( + EVP_PKEY *Pkey, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + BOOLEAN Result; + EVP_PKEY_CTX *PkeyCtx; + UINT8 *TempData; + UINTN TempDataSize; + INTN ReturnCode; + CONST EVP_MD *HashAlg; + + // + // Check input parameters. + // + if ((Pkey == NULL) || (EncryptedData == NULL) || + (OutData == NULL) || (OutDataSize == NULL)) + { + return FALSE; + } + + Result = FALSE; + PkeyCtx = NULL; + TempData = NULL; + TempDataSize = 0; + + // + // Create a context for the decryption operation. + // + PkeyCtx = EVP_PKEY_CTX_new (Pkey, NULL); if (PkeyCtx == NULL) { // // Fail to create contex. // + DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_CTK_new() failed\n", __func__)); goto _Exit; } // // Initialize the context and set the desired padding. // - if ((EVP_PKEY_encrypt_init (PkeyCtx) <= 0) || + if ((EVP_PKEY_decrypt_init (PkeyCtx) <= 0) || (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_OAEP_PADDING) <= 0)) { // // Fail to initialize the context. // + DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_decrypt_init() failed\n", __func__)); goto _Exit; } + if (DigestLen != 0) { + HashAlg = GetEvpMD (DigestLen); + if (HashAlg == NULL) { + goto _Exit; + } + + if (EVP_PKEY_CTX_set_rsa_oaep_md (PkeyCtx, HashAlg) <= 0) { + goto _Exit; + } + + if (EVP_PKEY_CTX_set_rsa_mgf1_md (PkeyCtx, HashAlg) <= 0) { + goto _Exit; + } + } + // // Determine the required buffer length for malloc'ing. // - if (EVP_PKEY_encrypt (PkeyCtx, NULL, &OutDataSize, InData, InDataSize) <= 0) { + ReturnCode = EVP_PKEY_decrypt (PkeyCtx, NULL, &TempDataSize, EncryptedData, EncryptedDataSize); + if (ReturnCode <= 0) { // // Fail to determine output buffer size. // + DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_decrypt() failed to determine output buffer size (rc=%d)\n", __func__, ReturnCode)); goto _Exit; } // // Allocate a buffer for the output data. // - OutData = AllocatePool (OutDataSize); - if (OutData == NULL) { + TempData = AllocatePool (TempDataSize); + if (TempData == NULL) { // // Fail to allocate the output buffer. // @@ -173,39 +535,179 @@ Pkcs1v2Encrypt ( } // - // Encrypt Data. + // Decrypt Data. // - if (EVP_PKEY_encrypt (PkeyCtx, OutData, &OutDataSize, InData, InDataSize) <= 0) { + ReturnCode = EVP_PKEY_decrypt (PkeyCtx, TempData, &TempDataSize, EncryptedData, EncryptedDataSize); + if (ReturnCode <= 0) { // - // Fail to encrypt data, need to free the output buffer. + // Fail to decrypt data, need to free the output buffer. // - FreePool (OutData); - OutData = NULL; - OutDataSize = 0; + FreePool (TempData); + TempData = NULL; + TempDataSize = 0; + + DEBUG ((DEBUG_ERROR, "[%a] EVP_PKEY_decrypt(TempData) failed to decrypt (rc=%d)\n", __func__, ReturnCode)); goto _Exit; } // - // Encrypt done. + // Decrypt done. // - *EncryptedData = OutData; - *EncryptedDataSize = OutDataSize; - Result = TRUE; + *OutData = TempData; + *OutDataSize = TempDataSize; + Result = TRUE; _Exit: + if (PkeyCtx != NULL) { + EVP_PKEY_CTX_free (PkeyCtx); + } + + return Result; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] PrivateKey A pointer to the DER-encoded private key. + @param[in] PrivateKeySize Size of the private key buffer. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Decrypt ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + BOOLEAN Result; + EVP_PKEY *Pkey; + CONST UINT8 *TempPointer; + // - // Release Resources + // Check input parameters. // - if (CertData != NULL) { - X509_free (CertData); + if ((PrivateKey == NULL) || (EncryptedData == NULL) || + (OutData == NULL) || (OutDataSize == NULL)) + { + return FALSE; + } + + Result = FALSE; + Pkey = NULL; + TempPointer = NULL; + + // + // Parse the private key. + // + TempPointer = PrivateKey; + Pkey = d2i_PrivateKey (EVP_PKEY_RSA, &Pkey, &TempPointer, (UINT32)PrivateKeySize); + if (Pkey == NULL) { + // + // Fail to parse private key. + // + DEBUG ((DEBUG_ERROR, "[%a] d2i_PrivateKey() failed\n", __func__)); + goto _Exit; } - if (InternalPublicKey != NULL) { - EVP_PKEY_free (InternalPublicKey); + Result = InternalPkcs1v2Decrypt (Pkey, EncryptedData, EncryptedDataSize, 0, OutData, OutDataSize); + +_Exit: + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); } - if (PkeyCtx != NULL) { - EVP_PKEY_CTX_free (PkeyCtx); + return Result; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a private key using RsaSetKey(). + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepDecrypt ( + IN VOID *RsaContext, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + BOOLEAN Result; + EVP_PKEY *Pkey; + + // + // Check input parameters. + // + if ((RsaContext == NULL) || (EncryptedData == NULL) || + (OutData == NULL) || (OutDataSize == NULL)) + { + return FALSE; + } + + Result = FALSE; + Pkey = NULL; + + // + // Create a context for the decryption operation. + // + + Pkey = EVP_PKEY_new (); + if (Pkey == NULL) { + goto _Exit; + } + + if (EVP_PKEY_set1_RSA (Pkey, (RSA *)RsaContext) == 0) { + goto _Exit; + } + + Result = InternalPkcs1v2Decrypt (Pkey, EncryptedData, EncryptedDataSize, DigestLen, OutData, OutDataSize); + +_Exit: + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); } return Result; diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1OaepNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1OaepNull.c index 3650894..01d3c5a 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1OaepNull.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs1OaepNull.c @@ -3,7 +3,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent - Copyright (C) 2016 Microsoft Corporation. All Rights Reserved. + Copyright (C) Microsoft Corporation. All Rights Reserved. Copyright (c) 2019, Intel Corporation. All rights reserved.
**/ @@ -48,3 +48,131 @@ Pkcs1v2Encrypt ( ASSERT (FALSE); return FALSE; } + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a public key using RsaSetKey(). + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepEncrypt ( + IN VOID *RsaContext, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] PrivateKey A pointer to the DER-encoded private key. + @param[in] PrivateKeySize Size of the private key buffer. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Decrypt ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a private key using RsaSetKey(). + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepDecrypt ( + IN VOID *RsaContext, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1OaepNull.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1OaepNull.c index 0273b7b..ee49f4f 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1OaepNull.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1OaepNull.c @@ -4,6 +4,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent Copyright (c) 2023, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -47,3 +48,131 @@ Pkcs1v2Encrypt ( ASSERT (FALSE); return FALSE; } + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a public key using RsaSetKey(). + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepEncrypt ( + IN VOID *RsaContext, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] PrivateKey A pointer to the DER-encoded private key. + @param[in] PrivateKeySize Size of the private key buffer. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Decrypt ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a private key using RsaSetKey(). + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepDecrypt ( + IN VOID *RsaContext, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptPkcs1OaepNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptPkcs1OaepNull.c index 3650894..01d3c5a 100644 --- a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptPkcs1OaepNull.c +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptPkcs1OaepNull.c @@ -3,7 +3,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent - Copyright (C) 2016 Microsoft Corporation. All Rights Reserved. + Copyright (C) Microsoft Corporation. All Rights Reserved. Copyright (c) 2019, Intel Corporation. All rights reserved.
**/ @@ -48,3 +48,131 @@ Pkcs1v2Encrypt ( ASSERT (FALSE); return FALSE; } + +/** + Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + encrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - X509 key size does not match any known key size. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + - Data size is too large for the provided key size (max size is a function of key size + and hash digest size). + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a public key using RsaSetKey(). + @param[in] InData Data to be encrypted. + @param[in] InDataSize Size of the data buffer. + @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer + to be used when initializing the PRNG. NULL otherwise. + @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer. + 0 otherwise. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted + message. + @param[out] EncryptedDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepEncrypt ( + IN VOID *RsaContext, + IN UINT8 *InData, + IN UINTN InDataSize, + IN CONST UINT8 *PrngSeed OPTIONAL, + IN UINTN PrngSeedSize OPTIONAL, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **EncryptedData, + OUT UINTN *EncryptedDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] PrivateKey A pointer to the DER-encoded private key. + @param[in] PrivateKeySize Size of the private key buffer. + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +Pkcs1v2Decrypt ( + IN CONST UINT8 *PrivateKey, + IN UINTN PrivateKeySize, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the + decrypted message in a newly allocated buffer. + + Things that can cause a failure include: + - Fail to parse private key. + - Fail to allocate an intermediate buffer. + - Null pointer provided for a non-optional parameter. + + @param[in] RsaContext A pointer to an RSA context created by RsaNew() and + provisioned with a private key using RsaSetKey(). + @param[in] EncryptedData Data to be decrypted. + @param[in] EncryptedDataSize Size of the encrypted buffer. + @param[in] DigestLen [Optional] If provided, size of the hash used: + SHA1_DIGEST_SIZE + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + 0 to use default (SHA1) + @param[out] OutData Pointer to an allocated buffer containing the encrypted + message. + @param[out] OutDataSize Size of the encrypted message buffer. + + @retval TRUE Encryption was successful. + @retval FALSE Encryption failed. + +**/ +BOOLEAN +EFIAPI +RsaOaepDecrypt ( + IN VOID *RsaContext, + IN UINT8 *EncryptedData, + IN UINTN EncryptedDataSize, + IN UINT16 DigestLen OPTIONAL, + OUT UINT8 **OutData, + OUT UINTN *OutDataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} -- cgit v1.1