From e9d1bf1ea329160e46f24f133446c5966b967b17 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:18:47 -0700 Subject: [PATCH 1/9] OpensslPkg: Migrate CryptHmac.c from HMAC_CTX to EVP_MAC_CTX Replace deprecated HMAC_CTX_new/HMAC_Init_ex/HMAC_Update/HMAC_Final/HMAC_CTX_free with the OpenSSL 3.x EVP_MAC_CTX provider API. Signed-off-by: Doug Flick --- .../Library/BaseCryptLib/Hmac/CryptHmac.c | 247 +++++++++++++----- 1 file changed, 187 insertions(+), 60 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/Hmac/CryptHmac.c b/OpensslPkg/Library/BaseCryptLib/Hmac/CryptHmac.c index 1ae33b670..c51c66399 100644 --- a/OpensslPkg/Library/BaseCryptLib/Hmac/CryptHmac.c +++ b/OpensslPkg/Library/BaseCryptLib/Hmac/CryptHmac.c @@ -7,13 +7,27 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "InternalCryptLib.h" -#include +// MU_CHANGE [BEGIN] +#include +#include +#include + +// +// Wrapper structure to hold EVP_MAC_CTX so that HmacMdDuplicate can +// replace the inner context while preserving the outer pointer. +// +typedef struct { + EVP_MAC_CTX *Ctx; +} HMAC_CTX_WRAPPER; +// MU_CHANGE [END] /** - Allocates and initializes one HMAC_CTX context for subsequent HMAC-MD use. + Allocates and initializes one EVP_MAC_CTX context for subsequent HMAC-MD use. // MU_CHANGE - @return Pointer to the HMAC_CTX context that has been initialized. - If the allocations fails, HmacMdNew() returns NULL. + // MU_CHANGE [BEGIN] + @return Pointer to the HMAC_CTX_WRAPPER that has been initialized. + If the allocation fails, HmacMdNew() returns NULL. + // MU_CHANGE [END] **/ STATIC @@ -22,16 +36,48 @@ HmacMdNew ( VOID ) { + // MU_CHANGE [BEGIN] + EVP_MAC *Mac; + HMAC_CTX_WRAPPER *Wrapper; + + // + // Fetch the HMAC algorithm from the default provider. + // MU_CHANGE [END] + // + // MU_CHANGE [BEGIN] + Mac = EVP_MAC_fetch (NULL, "HMAC", NULL); + if (Mac == NULL) { + return NULL; + } + + Wrapper = AllocateZeroPool (sizeof (HMAC_CTX_WRAPPER)); + if (Wrapper == NULL) { + EVP_MAC_free (Mac); + return NULL; + } + + // MU_CHANGE [END] // - // Allocates & Initializes HMAC_CTX Context by OpenSSL HMAC_CTX_new() + // MU_CHANGE [BEGIN] + // Allocate EVP_MAC_CTX. The context holds its own reference to the + // EVP_MAC object, so we can free it immediately after ctx creation. // - return (VOID *)HMAC_CTX_new (); + Wrapper->Ctx = EVP_MAC_CTX_new (Mac); + EVP_MAC_free (Mac); + + if (Wrapper->Ctx == NULL) { + FreePool (Wrapper); + return NULL; + } + + return (VOID *)Wrapper; + // MU_CHANGE [END] } /** - Release the specified HMAC_CTX context. + Release the specified HMAC_CTX_WRAPPER context. // MU_CHANGE - @param[in] HmacMdCtx Pointer to the HMAC_CTX context to be released. + @param[in] HmacMdCtx Pointer to the HMAC_CTX_WRAPPER context to be released. // MU_CHANGE **/ STATIC @@ -40,10 +86,16 @@ HmacMdFree ( IN VOID *HmacMdCtx ) { - // - // Free OpenSSL HMAC_CTX Context - // - HMAC_CTX_free ((HMAC_CTX *)HmacMdCtx); + // MU_CHANGE [BEGIN] + HMAC_CTX_WRAPPER *Wrapper; + + if (HmacMdCtx != NULL) { + Wrapper = (HMAC_CTX_WRAPPER *)HmacMdCtx; + EVP_MAC_CTX_free (Wrapper->Ctx); + FreePool (Wrapper); + } + + // MU_CHANGE [END] } /** @@ -52,7 +104,7 @@ HmacMdFree ( If HmacMdContext is NULL, then return FALSE. - @param[in] Md Message Digest. + @param[in] MdName Digest algorithm name (e.g. "SHA256"). // MU_CHANGE @param[out] HmacMdContext Pointer to HMAC-MD context. @param[in] Key Pointer to the user-supplied key. @param[in] KeySize Key size in bytes. @@ -64,12 +116,19 @@ HmacMdFree ( STATIC BOOLEAN HmacMdSetKey ( - IN CONST EVP_MD *Md, - OUT VOID *HmacMdContext, - IN CONST UINT8 *Key, - IN UINTN KeySize + // MU_CHANGE [BEGIN] + IN CONST CHAR8 *MdName, + OUT VOID *HmacMdContext, + IN CONST UINT8 *Key, + IN UINTN KeySize + // MU_CHANGE [END] ) { + // MU_CHANGE [BEGIN] + HMAC_CTX_WRAPPER *Wrapper; + OSSL_PARAM Params[2]; + + // MU_CHANGE [END] // // Check input parameters. // @@ -77,7 +136,18 @@ HmacMdSetKey ( return FALSE; } - if (HMAC_Init_ex ((HMAC_CTX *)HmacMdContext, Key, (UINT32)KeySize, Md, NULL) != 1) { + // MU_CHANGE [BEGIN] + Wrapper = (HMAC_CTX_WRAPPER *)HmacMdContext; + + Params[0] = OSSL_PARAM_construct_utf8_string ( + OSSL_MAC_PARAM_DIGEST, + (char *)MdName, + 0 + ); + Params[1] = OSSL_PARAM_construct_end (); + + if (EVP_MAC_init (Wrapper->Ctx, Key, (size_t)KeySize, Params) != 1) { + // MU_CHANGE [END] return FALSE; } @@ -104,6 +174,12 @@ HmacMdDuplicate ( OUT VOID *NewHmacMdContext ) { + // MU_CHANGE [BEGIN] + HMAC_CTX_WRAPPER *SrcWrapper; + HMAC_CTX_WRAPPER *DstWrapper; + EVP_MAC_CTX *NewCtx; + + // MU_CHANGE [END] // // Check input parameters. // @@ -111,10 +187,24 @@ HmacMdDuplicate ( return FALSE; } - if (HMAC_CTX_copy ((HMAC_CTX *)NewHmacMdContext, (HMAC_CTX *)HmacMdContext) != 1) { + // MU_CHANGE [BEGIN] + SrcWrapper = (HMAC_CTX_WRAPPER *)HmacMdContext; + DstWrapper = (HMAC_CTX_WRAPPER *)NewHmacMdContext; + + NewCtx = EVP_MAC_CTX_dup (SrcWrapper->Ctx); + if (NewCtx == NULL) { + // MU_CHANGE [END] return FALSE; } + // MU_CHANGE [BEGIN] + // + // Replace the destination's inner context with the duplicated one. + // + EVP_MAC_CTX_free (DstWrapper->Ctx); + DstWrapper->Ctx = NewCtx; + + // MU_CHANGE [END] return TRUE; } @@ -144,6 +234,10 @@ HmacMdUpdate ( IN UINTN DataSize ) { + // MU_CHANGE [BEGIN] + HMAC_CTX_WRAPPER *Wrapper; + + // MU_CHANGE [END] // // Check input parameters. // @@ -158,10 +252,15 @@ HmacMdUpdate ( return FALSE; } + // MU_CHANGE [BEGIN] + Wrapper = (HMAC_CTX_WRAPPER *)HmacMdContext; + + // MU_CHANGE [END] // // OpenSSL HMAC-MD digest update // - if (HMAC_Update ((HMAC_CTX *)HmacMdContext, Data, DataSize) != 1) { + if (EVP_MAC_update (Wrapper->Ctx, Data, DataSize) != 1) { + // MU_CHANGE return FALSE; } @@ -195,7 +294,12 @@ HmacMdFinal ( OUT UINT8 *HmacValue ) { - UINT32 Length; + // MU_CHANGE [BEGIN] + HMAC_CTX_WRAPPER *Wrapper; + size_t MacSize; + size_t Length; + + // MU_CHANGE [END] // // Check input parameters. @@ -204,14 +308,17 @@ HmacMdFinal ( return FALSE; } + // MU_CHANGE [BEGIN] + Wrapper = (HMAC_CTX_WRAPPER *)HmacMdContext; + + // MU_CHANGE [END] // // OpenSSL HMAC-MD digest finalization // - if (HMAC_Final ((HMAC_CTX *)HmacMdContext, HmacValue, &Length) != 1) { - return FALSE; - } - - if (HMAC_CTX_reset ((HMAC_CTX *)HmacMdContext) != 1) { + // MU_CHANGE [BEGIN] + MacSize = EVP_MAC_CTX_get_mac_size (Wrapper->Ctx); + if (EVP_MAC_final (Wrapper->Ctx, HmacValue, &Length, MacSize) != 1) { + // MU_CHANGE [END] return FALSE; } @@ -226,7 +333,7 @@ HmacMdFinal ( If this interface is not supported, then return FALSE. - @param[in] Md Message Digest. + @param[in] MdName Digest algorithm name (e.g. "SHA256"). // MU_CHANGE @param[in] Data Pointer to the buffer containing the data to be digested. @param[in] DataSize Size of Data buffer in bytes. @param[in] Key Pointer to the user-supplied key. @@ -242,53 +349,73 @@ HmacMdFinal ( STATIC BOOLEAN HmacMdAll ( - IN CONST EVP_MD *Md, - IN CONST VOID *Data, - IN UINTN DataSize, - IN CONST UINT8 *Key, - IN UINTN KeySize, - OUT UINT8 *HmacValue + // MU_CHANGE [BEGIN] + IN CONST CHAR8 *MdName, + IN CONST VOID *Data, + IN UINTN DataSize, + IN CONST UINT8 *Key, + IN UINTN KeySize, + OUT UINT8 *HmacValue + // MU_CHANGE [END] ) { - UINT32 Length; - HMAC_CTX *Ctx; - BOOLEAN RetVal; + // MU_CHANGE [BEGIN] + EVP_MAC *Mac; + EVP_MAC_CTX *Ctx; + OSSL_PARAM Params[2]; + size_t MacSize; + size_t Length; + BOOLEAN RetVal; + + Mac = EVP_MAC_fetch (NULL, "HMAC", NULL); + if (Mac == NULL) { + return FALSE; + } + + // MU_CHANGE [END] - Ctx = HMAC_CTX_new (); + // MU_CHANGE [BEGIN] + Ctx = EVP_MAC_CTX_new (Mac); + EVP_MAC_free (Mac); + // MU_CHANGE [END] if (Ctx == NULL) { return FALSE; } - RetVal = (BOOLEAN)HMAC_CTX_reset (Ctx); - if (!RetVal) { - goto Done; - } + // MU_CHANGE [BEGIN] + Params[0] = OSSL_PARAM_construct_utf8_string ( + OSSL_MAC_PARAM_DIGEST, + (char *)MdName, + 0 + ); + Params[1] = OSSL_PARAM_construct_end (); + // MU_CHANGE [END] - RetVal = (BOOLEAN)HMAC_Init_ex (Ctx, Key, (UINT32)KeySize, Md, NULL); + RetVal = (BOOLEAN)(EVP_MAC_init (Ctx, Key, (size_t)KeySize, Params) == 1); // MU_CHANGE if (!RetVal) { goto Done; } - RetVal = (BOOLEAN)HMAC_Update (Ctx, Data, DataSize); + RetVal = (BOOLEAN)(EVP_MAC_update (Ctx, Data, DataSize) == 1); // MU_CHANGE if (!RetVal) { goto Done; } - RetVal = (BOOLEAN)HMAC_Final (Ctx, HmacValue, &Length); - if (!RetVal) { - goto Done; - } + // MU_CHANGE [BEGIN] + MacSize = EVP_MAC_CTX_get_mac_size (Ctx); + RetVal = (BOOLEAN)(EVP_MAC_final (Ctx, HmacValue, &Length, MacSize) == 1); + // MU_CHANGE [END] Done: - HMAC_CTX_free (Ctx); + EVP_MAC_CTX_free (Ctx); // MU_CHANGE return RetVal; } /** - Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA256 use. + Allocates and initializes one HMAC context for subsequent HMAC-SHA256 use. // MU_CHANGE - @return Pointer to the HMAC_CTX context that has been initialized. + @return Pointer to the HMAC context that has been initialized. // MU_CHANGE If the allocations fails, HmacSha256New() returns NULL. **/ @@ -302,9 +429,9 @@ HmacSha256New ( } /** - Release the specified HMAC_CTX context. + Release the specified HMAC context. // MU_CHANGE - @param[in] HmacSha256Ctx Pointer to the HMAC_CTX context to be released. + @param[in] HmacSha256Ctx Pointer to the HMAC context to be released. // MU_CHANGE **/ VOID @@ -338,7 +465,7 @@ HmacSha256SetKey ( IN UINTN KeySize ) { - return HmacMdSetKey (EVP_sha256 (), HmacSha256Context, Key, KeySize); + return HmacMdSetKey ("SHA256", HmacSha256Context, Key, KeySize); // MU_CHANGE } /** @@ -453,13 +580,13 @@ HmacSha256All ( OUT UINT8 *HmacValue ) { - return HmacMdAll (EVP_sha256 (), Data, DataSize, Key, KeySize, HmacValue); + return HmacMdAll ("SHA256", Data, DataSize, Key, KeySize, HmacValue); // MU_CHANGE } /** - Allocates and initializes one HMAC_CTX context for subsequent HMAC-SHA384 use. + Allocates and initializes one HMAC context for subsequent HMAC-SHA384 use. // MU_CHANGE - @return Pointer to the HMAC_CTX context that has been initialized. + @return Pointer to the HMAC context that has been initialized. // MU_CHANGE If the allocations fails, HmacSha384New() returns NULL. **/ @@ -473,9 +600,9 @@ HmacSha384New ( } /** - Release the specified HMAC_CTX context. + Release the specified HMAC context. // MU_CHANGE - @param[in] HmacSha384Ctx Pointer to the HMAC_CTX context to be released. + @param[in] HmacSha384Ctx Pointer to the HMAC context to be released. // MU_CHANGE **/ VOID @@ -511,7 +638,7 @@ HmacSha384SetKey ( IN UINTN KeySize ) { - return HmacMdSetKey (EVP_sha384 (), HmacSha384Context, Key, KeySize); + return HmacMdSetKey ("SHA384", HmacSha384Context, Key, KeySize); // MU_CHANGE } /** @@ -632,5 +759,5 @@ HmacSha384All ( OUT UINT8 *HmacValue ) { - return HmacMdAll (EVP_sha384 (), Data, DataSize, Key, KeySize, HmacValue); + return HmacMdAll ("SHA384", Data, DataSize, Key, KeySize, HmacValue); // MU_CHANGE } From ec3ef9bc39840b0512e264b67cd46e469190c683 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:18:56 -0700 Subject: [PATCH 2/9] OpensslPkg: Migrate RSA key context to EVP_PKEY APIs Replace direct RSA* usage with a new RSA_PKEY_CTX struct holding individual BIGNUMs (N, E, D, P, Q, Dp, Dq, QInv) plus a cached EVP_PKEY*. - Add CryptRsaPkeyCtx.h defining RSA_PKEY_CTX and helper declarations - RsaBuildEvpPkey(): lazily builds EVP_PKEY from stored BIGNUMs - RsaInvalidatePkey(): invalidates the cache on component change - RsaGetKey(): return TRUE with *BnSize=0 for unset (NULL) components - All operations (sign/verify/encrypt/decrypt) use EVP_PKEY_CTX Signed-off-by: Doug Flick --- .../Library/BaseCryptLib/Pk/CryptRsaBasic.c | 599 ++++++++++++------ .../Library/BaseCryptLib/Pk/CryptRsaExt.c | 314 ++++++--- .../Library/BaseCryptLib/Pk/CryptRsaPkeyCtx.h | 83 +++ 3 files changed, 733 insertions(+), 263 deletions(-) create mode 100644 OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPkeyCtx.h diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c index 56df73e64..a4c001da2 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c @@ -7,8 +7,13 @@ 3) RsaSetKey 4) RsaPkcs1Verify + // MU_CHANGE [BEGIN] + Uses OpenSSL 3.x EVP_PKEY provider-based APIs instead of deprecated RSA APIs. + + // MU_CHANGE [END] Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.
(c) Copyright 2025 HP Development Company, L.P. +Copyright (c) Microsoft Corporation. // MU_CHANGE SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -16,8 +21,252 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "InternalCryptLib.h" #include +#include // MU_CHANGE #include -#include +// MU_CHANGE [BEGIN] +#include +#include +#include + +#include "CryptRsaPkeyCtx.h" + +/** + Invalidate (free) the cached EVP_PKEY in the RSA context. + + @param[in,out] RsaPkeyCtx Pointer to RSA_PKEY_CTX whose cache to invalidate. + +**/ +VOID +RsaInvalidatePkey ( + IN OUT RSA_PKEY_CTX *RsaPkeyCtx + ) +{ + if (RsaPkeyCtx->Pkey != NULL) { + EVP_PKEY_free (RsaPkeyCtx->Pkey); + RsaPkeyCtx->Pkey = NULL; + } +} + +/** + Build (or return cached) EVP_PKEY from the stored BIGNUM components. + + @param[in,out] RsaPkeyCtx Pointer to RSA_PKEY_CTX holding key components. + + @return Pointer to EVP_PKEY on success, or NULL on failure. + +**/ +EVP_PKEY * +RsaBuildEvpPkey ( + IN OUT RSA_PKEY_CTX *RsaPkeyCtx + ) +{ + OSSL_PARAM_BLD *ParamBld; + OSSL_PARAM *Params; + EVP_PKEY_CTX *PkeyCtx; + EVP_PKEY *Pkey; + INT32 Selection; + + if (RsaPkeyCtx->Pkey != NULL) { + return RsaPkeyCtx->Pkey; + } + + // + // N and E are the minimum required components. + // + if ((RsaPkeyCtx->N == NULL) || (RsaPkeyCtx->E == NULL)) { + return NULL; + } + + ParamBld = NULL; + Params = NULL; + PkeyCtx = NULL; + Pkey = NULL; + + ParamBld = OSSL_PARAM_BLD_new (); + if (ParamBld == NULL) { + return NULL; + } + + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_N, RsaPkeyCtx->N) != 1) { + goto _Exit; + } + + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_E, RsaPkeyCtx->E) != 1) { + goto _Exit; + } + + if (RsaPkeyCtx->D != NULL) { + Selection = EVP_PKEY_KEYPAIR; + + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_D, RsaPkeyCtx->D) != 1) { + goto _Exit; + } + + if (RsaPkeyCtx->P != NULL) { + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_FACTOR1, RsaPkeyCtx->P) != 1) { + goto _Exit; + } + } + + if (RsaPkeyCtx->Q != NULL) { + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_FACTOR2, RsaPkeyCtx->Q) != 1) { + goto _Exit; + } + } + + if (RsaPkeyCtx->Dp != NULL) { + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_EXPONENT1, RsaPkeyCtx->Dp) != 1) { + goto _Exit; + } + } + + if (RsaPkeyCtx->Dq != NULL) { + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_EXPONENT2, RsaPkeyCtx->Dq) != 1) { + goto _Exit; + } + } + + if (RsaPkeyCtx->QInv != NULL) { + if (OSSL_PARAM_BLD_push_BN (ParamBld, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, RsaPkeyCtx->QInv) != 1) { + goto _Exit; + } + } + } else { + Selection = EVP_PKEY_PUBLIC_KEY; + } + + Params = OSSL_PARAM_BLD_to_param (ParamBld); + if (Params == NULL) { + goto _Exit; + } + + PkeyCtx = EVP_PKEY_CTX_new_from_name (NULL, "RSA", NULL); + if (PkeyCtx == NULL) { + goto _Exit; + } + + if (EVP_PKEY_fromdata_init (PkeyCtx) != 1) { + goto _Exit; + } + + if (EVP_PKEY_fromdata (PkeyCtx, &Pkey, Selection, Params) != 1) { + Pkey = NULL; + goto _Exit; + } + + // + // Cache the built EVP_PKEY. + // + RsaPkeyCtx->Pkey = Pkey; + +_Exit: + if (PkeyCtx != NULL) { + EVP_PKEY_CTX_free (PkeyCtx); + } + + if (Params != NULL) { + OSSL_PARAM_free (Params); + } + + if (ParamBld != NULL) { + OSSL_PARAM_BLD_free (ParamBld); + } + + return RsaPkeyCtx->Pkey; +} + +/** + Extract all RSA BIGNUM key components from an EVP_PKEY into RSA_PKEY_CTX. + + @param[in,out] RsaPkeyCtx Pointer to RSA_PKEY_CTX to populate. + @param[in] Pkey EVP_PKEY from which to extract components. + + @retval TRUE Components extracted successfully. + @retval FALSE Extraction failed. + +**/ +BOOLEAN +RsaExtractBigNums ( + IN OUT RSA_PKEY_CTX *RsaPkeyCtx, + IN EVP_PKEY *Pkey + ) +{ + // + // Free any existing BIGNUMs. + // + BN_free (RsaPkeyCtx->N); + BN_free (RsaPkeyCtx->E); + BN_clear_free (RsaPkeyCtx->D); + BN_clear_free (RsaPkeyCtx->P); + BN_clear_free (RsaPkeyCtx->Q); + BN_clear_free (RsaPkeyCtx->Dp); + BN_clear_free (RsaPkeyCtx->Dq); + BN_clear_free (RsaPkeyCtx->QInv); + + RsaPkeyCtx->N = NULL; + RsaPkeyCtx->E = NULL; + RsaPkeyCtx->D = NULL; + RsaPkeyCtx->P = NULL; + RsaPkeyCtx->Q = NULL; + RsaPkeyCtx->Dp = NULL; + RsaPkeyCtx->Dq = NULL; + RsaPkeyCtx->QInv = NULL; + + // + // Extract public components (required). + // + if (EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_N, &RsaPkeyCtx->N) != 1) { + return FALSE; + } + + if (EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_E, &RsaPkeyCtx->E) != 1) { + return FALSE; + } + + // + // Extract private components (optional -- may not be present for public keys). + // + EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_D, &RsaPkeyCtx->D); + EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &RsaPkeyCtx->P); + EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, &RsaPkeyCtx->Q); + EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_EXPONENT1, &RsaPkeyCtx->Dp); + EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_EXPONENT2, &RsaPkeyCtx->Dq); + EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &RsaPkeyCtx->QInv); + + return TRUE; +} + +/** + Retrieve a pointer to EVP message digest object. + + @param[in] HashSize Size of the message digest in bytes. + + @return Pointer to EVP_MD, or NULL if unsupported size. + +**/ +STATIC +CONST +EVP_MD * +GetEvpMdFromHashSize ( + IN UINTN HashSize + ) +{ + switch (HashSize) { + case MD5_DIGEST_SIZE: + return EVP_md5 (); + case SHA1_DIGEST_SIZE: + return EVP_sha1 (); + case SHA256_DIGEST_SIZE: + return EVP_sha256 (); + case SHA384_DIGEST_SIZE: + return EVP_sha384 (); + case SHA512_DIGEST_SIZE: + return EVP_sha512 (); + default: + return NULL; + } +} +// MU_CHANGE [END] /** Allocates and initializes one RSA context for subsequent use. @@ -33,9 +282,9 @@ RsaNew ( ) { // - // Allocates & Initializes RSA Context by OpenSSL RSA_new() + // Allocate and zero-initialize an RSA_PKEY_CTX structure. // MU_CHANGE // - return (VOID *)RSA_new (); + return (VOID *)AllocateZeroPool (sizeof (RSA_PKEY_CTX)); // MU_CHANGE } /** @@ -50,10 +299,42 @@ RsaFree ( IN VOID *RsaContext ) { + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + + if (RsaContext == NULL) { + return; + } + + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; + + // MU_CHANGE [END] // - // Free OpenSSL RSA Context + // Free cached EVP_PKEY. // MU_CHANGE + // + // MU_CHANGE [BEGIN] + if (RsaPkeyCtx->Pkey != NULL) { + EVP_PKEY_free (RsaPkeyCtx->Pkey); + } + // - RSA_free ((RSA *)RsaContext); + // Free public components. + // + BN_free (RsaPkeyCtx->N); + BN_free (RsaPkeyCtx->E); + + // + // Securely free private components. + // + BN_clear_free (RsaPkeyCtx->D); + BN_clear_free (RsaPkeyCtx->P); + BN_clear_free (RsaPkeyCtx->Q); + BN_clear_free (RsaPkeyCtx->Dp); + BN_clear_free (RsaPkeyCtx->Dq); + BN_clear_free (RsaPkeyCtx->QInv); + + FreePool (RsaPkeyCtx); + // MU_CHANGE [END] } /** @@ -87,16 +368,12 @@ RsaSetKey ( IN UINTN BnSize ) { - RSA *RsaKey; - BIGNUM *BnN; - BIGNUM *BnE; - BIGNUM *BnD; - BIGNUM *BnP; - BIGNUM *BnQ; - BIGNUM *BnDp; - BIGNUM *BnDq; - BIGNUM *BnQInv; - BIGNUM *AllocatedBn[3]; + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + BIGNUM **BnTarget; + BIGNUM *NewBn; + + // MU_CHANGE [END] // // Check input parameters. @@ -105,174 +382,92 @@ RsaSetKey ( return FALSE; } - BnN = NULL; - BnE = NULL; - BnD = NULL; - BnP = NULL; - BnQ = NULL; - BnDp = NULL; - BnDq = NULL; - BnQInv = NULL; + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; // MU_CHANGE - AllocatedBn[0] = NULL; - AllocatedBn[1] = NULL; - AllocatedBn[2] = NULL; // - // Retrieve the components from RSA object. + // Invalidate cached EVP_PKEY since a key component is changing. // MU_CHANGE // - RsaKey = (RSA *)RsaContext; - RSA_get0_key (RsaKey, (const BIGNUM **)&BnN, (const BIGNUM **)&BnE, (const BIGNUM **)&BnD); - RSA_get0_factors (RsaKey, (const BIGNUM **)&BnP, (const BIGNUM **)&BnQ); - RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnDp, (const BIGNUM **)&BnDq, (const BIGNUM **)&BnQInv); + RsaInvalidatePkey (RsaPkeyCtx); // MU_CHANGE // - // Set RSA Key Components by converting octet string to OpenSSL BN representation. - // NOTE: For RSA public key (used in signature verification), only public components - // (N, e) are needed. + // Select the target BIGNUM pointer based on key tag. // MU_CHANGE // switch (KeyTag) { - // - // RSA Public Modulus (N), Public Exponent (e) and Private Exponent (d) - // case RsaKeyN: + // MU_CHANGE [BEGIN] + BnTarget = &RsaPkeyCtx->N; + break; + // MU_CHANGE [END] case RsaKeyE: + // MU_CHANGE [BEGIN] + BnTarget = &RsaPkeyCtx->E; + break; + // MU_CHANGE [END] case RsaKeyD: - if (BnN == NULL) { - BnN = BN_new (); - AllocatedBn[0] = BnN; - } - - if (BnE == NULL) { - BnE = BN_new (); - AllocatedBn[1] = BnE; - } - - if (BnD == NULL) { - BnD = BN_new (); - AllocatedBn[2] = BnD; - } - - if ((BnN == NULL) || (BnE == NULL) || (BnD == NULL)) { - return FALSE; - } - - switch (KeyTag) { - case RsaKeyN: - BnN = BN_bin2bn (BigNumber, (UINT32)BnSize, BnN); - break; - case RsaKeyE: - BnE = BN_bin2bn (BigNumber, (UINT32)BnSize, BnE); - break; - case RsaKeyD: - BnD = BN_bin2bn (BigNumber, (UINT32)BnSize, BnD); - break; - default: - return FALSE; - } - - if (RSA_set0_key (RsaKey, BN_dup (BnN), BN_dup (BnE), BN_dup (BnD)) == 0) { - return FALSE; - } - - BN_free (AllocatedBn[0]); - BN_free (AllocatedBn[1]); - BN_clear_free (AllocatedBn[2]); - + BnTarget = &RsaPkeyCtx->D; // MU_CHANGE break; - - // - // RSA Secret Prime Factor of Modulus (p and q) - // case RsaKeyP: + // MU_CHANGE [BEGIN] + BnTarget = &RsaPkeyCtx->P; + break; + // MU_CHANGE [END] case RsaKeyQ: - if (BnP == NULL) { - BnP = BN_new (); - AllocatedBn[0] = BnP; - } - - if (BnQ == NULL) { - BnQ = BN_new (); - AllocatedBn[1] = BnQ; - } - - if ((BnP == NULL) || (BnQ == NULL)) { - return FALSE; - } - - switch (KeyTag) { - case RsaKeyP: - BnP = BN_bin2bn (BigNumber, (UINT32)BnSize, BnP); - break; - case RsaKeyQ: - BnQ = BN_bin2bn (BigNumber, (UINT32)BnSize, BnQ); - break; - default: - return FALSE; - } - - if (RSA_set0_factors (RsaKey, BN_dup (BnP), BN_dup (BnQ)) == 0) { - return FALSE; - } - - BN_clear_free (AllocatedBn[0]); - BN_clear_free (AllocatedBn[1]); - + BnTarget = &RsaPkeyCtx->Q; // MU_CHANGE break; - - // - // p's CRT Exponent (== d mod (p - 1)), q's CRT Exponent (== d mod (q - 1)), - // and CRT Coefficient (== 1/q mod p) - // case RsaKeyDp: + // MU_CHANGE [BEGIN] + BnTarget = &RsaPkeyCtx->Dp; + break; + // MU_CHANGE [END] case RsaKeyDq: + // MU_CHANGE [BEGIN] + BnTarget = &RsaPkeyCtx->Dq; + break; + // MU_CHANGE [END] case RsaKeyQInv: - if (BnDp == NULL) { - BnDp = BN_new (); - AllocatedBn[0] = BnDp; - } - - if (BnDq == NULL) { - BnDq = BN_new (); - AllocatedBn[1] = BnDq; - } - - if (BnQInv == NULL) { - BnQInv = BN_new (); - AllocatedBn[2] = BnQInv; - } - - if ((BnDp == NULL) || (BnDq == NULL) || (BnQInv == NULL)) { - return FALSE; - } - - switch (KeyTag) { - case RsaKeyDp: - BnDp = BN_bin2bn (BigNumber, (UINT32)BnSize, BnDp); - break; - case RsaKeyDq: - BnDq = BN_bin2bn (BigNumber, (UINT32)BnSize, BnDq); - break; - case RsaKeyQInv: - BnQInv = BN_bin2bn (BigNumber, (UINT32)BnSize, BnQInv); - break; - default: - return FALSE; - } + // MU_CHANGE [BEGIN] + BnTarget = &RsaPkeyCtx->QInv; + break; + default: + return FALSE; + } + // MU_CHANGE [END] - if (RSA_set0_crt_params (RsaKey, BN_dup (BnDp), BN_dup (BnDq), BN_dup (BnQInv)) == 0) { - return FALSE; + // MU_CHANGE [BEGIN] + // + // If BigNumber is NULL, clear the component. + // + if (BigNumber == NULL) { + if (*BnTarget != NULL) { + if ((KeyTag == RsaKeyN) || (KeyTag == RsaKeyE)) { + BN_free (*BnTarget); + } else { + BN_clear_free (*BnTarget); + // MU_CHANGE [END] } - BN_clear_free (AllocatedBn[0]); - BN_clear_free (AllocatedBn[1]); - BN_clear_free (AllocatedBn[2]); + // MU_CHANGE [BEGIN] + *BnTarget = NULL; + } + // MU_CHANGE [END] - break; + // MU_CHANGE [BEGIN] + return TRUE; + } + // MU_CHANGE [END] - default: - return FALSE; + // MU_CHANGE [BEGIN] + // + // Convert octet string to BIGNUM. + // + NewBn = BN_bin2bn (BigNumber, (UINT32)BnSize, *BnTarget); + if (NewBn == NULL) { + return FALSE; + // MU_CHANGE [END] } + *BnTarget = NewBn; + return TRUE; } @@ -305,8 +500,13 @@ RsaPkcs1Verify ( IN UINTN SigSize ) { - INT32 DigestType; - UINT8 *SigBuf; + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + EVP_PKEY *Pkey; + EVP_PKEY_CTX *PkeyCtx; + CONST EVP_MD *Md; + BOOLEAN Result; + // MU_CHANGE [END] // // Check input parameters. @@ -321,40 +521,61 @@ RsaPkcs1Verify ( // // Determine the message digest algorithm according to digest size. - // Only MD5, SHA-1, SHA-256, SHA-384 or SHA-512 algorithm is supported. // - switch (HashSize) { - case MD5_DIGEST_SIZE: - DigestType = NID_md5; - break; + // MU_CHANGE [BEGIN] + Md = GetEvpMdFromHashSize (HashSize); + if (Md == NULL) { + return FALSE; + } + // MU_CHANGE [END] - case SHA1_DIGEST_SIZE: - DigestType = NID_sha1; - break; + // MU_CHANGE [BEGIN] + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; + Result = FALSE; + PkeyCtx = NULL; + // MU_CHANGE [END] - case SHA256_DIGEST_SIZE: - DigestType = NID_sha256; - break; + // MU_CHANGE [BEGIN] + // + // Build EVP_PKEY from stored key components. + // + Pkey = RsaBuildEvpPkey (RsaPkeyCtx); + if (Pkey == NULL) { + return FALSE; + } + // MU_CHANGE [END] - case SHA384_DIGEST_SIZE: - DigestType = NID_sha384; - break; + // MU_CHANGE [BEGIN] + PkeyCtx = EVP_PKEY_CTX_new_from_pkey (NULL, Pkey, NULL); + if (PkeyCtx == NULL) { + goto _Exit; + } + // MU_CHANGE [END] - case SHA512_DIGEST_SIZE: - DigestType = NID_sha512; - break; + // MU_CHANGE [BEGIN] + if (EVP_PKEY_verify_init (PkeyCtx) != 1) { + goto _Exit; + } + // MU_CHANGE [END] - default: - return FALSE; + // MU_CHANGE [BEGIN] + if (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_PADDING) <= 0) { + goto _Exit; + } + + if (EVP_PKEY_CTX_set_signature_md (PkeyCtx, Md) <= 0) { + goto _Exit; + } + + if (EVP_PKEY_verify (PkeyCtx, Signature, SigSize, MessageHash, HashSize) == 1) { + Result = TRUE; + } + +_Exit: + if (PkeyCtx != NULL) { + EVP_PKEY_CTX_free (PkeyCtx); + // MU_CHANGE [END] } - SigBuf = (UINT8 *)Signature; - return (BOOLEAN)RSA_verify ( - DigestType, - MessageHash, - (UINT32)HashSize, - SigBuf, - (UINT32)SigSize, - (RSA *)RsaContext - ); + return Result; // MU_CHANGE } diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c index 1ea3d5e0e..36c78516a 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c @@ -7,7 +7,12 @@ 3) RsaCheckKey 4) RsaPkcs1Sign + // MU_CHANGE [BEGIN] + Uses OpenSSL 3.x EVP_PKEY provider-based APIs instead of deprecated RSA APIs. + + // MU_CHANGE [END] Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.
+Copyright (c) Microsoft Corporation. // MU_CHANGE SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -15,9 +20,48 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "InternalCryptLib.h" #include +#include // MU_CHANGE #include +// MU_CHANGE [BEGIN] +#include +#include +// MU_CHANGE [END] #include -#include +// MU_CHANGE [BEGIN] + +#include "CryptRsaPkeyCtx.h" + +/** + Retrieve a pointer to EVP message digest object. + + @param[in] HashSize Size of the message digest in bytes. + + @return Pointer to EVP_MD, or NULL if unsupported size. + +**/ +STATIC +CONST +EVP_MD * +GetEvpMdFromHashSize ( + IN UINTN HashSize + ) +{ + switch (HashSize) { + case MD5_DIGEST_SIZE: + return EVP_md5 (); + case SHA1_DIGEST_SIZE: + return EVP_sha1 (); + case SHA256_DIGEST_SIZE: + return EVP_sha256 (); + case SHA384_DIGEST_SIZE: + return EVP_sha384 (); + case SHA512_DIGEST_SIZE: + return EVP_sha512 (); + default: + return NULL; + } +} +// MU_CHANGE [END] /** Gets the tag-designated RSA key component from the established RSA context. @@ -54,9 +98,11 @@ RsaGetKey ( IN OUT UINTN *BnSize ) { - RSA *RsaKey; - BIGNUM *BnKey; - UINTN Size; + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + BIGNUM *BnKey; + UINTN Size; + // MU_CHANGE [END] // // Check input parameters. @@ -65,66 +111,68 @@ RsaGetKey ( return FALSE; } - RsaKey = (RSA *)RsaContext; - Size = *BnSize; - *BnSize = 0; - BnKey = NULL; + // MU_CHANGE [BEGIN] + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; + Size = *BnSize; + *BnSize = 0; + BnKey = NULL; + // MU_CHANGE [END] switch (KeyTag) { // // RSA Public Modulus (N) // case RsaKeyN: - RSA_get0_key (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL); + BnKey = RsaPkeyCtx->N; // MU_CHANGE break; // // RSA Public Exponent (e) // case RsaKeyE: - RSA_get0_key (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL); + BnKey = RsaPkeyCtx->E; // MU_CHANGE break; // // RSA Private Exponent (d) // case RsaKeyD: - RSA_get0_key (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey); + BnKey = RsaPkeyCtx->D; // MU_CHANGE break; // // RSA Secret Prime Factor of Modulus (p) // case RsaKeyP: - RSA_get0_factors (RsaKey, (const BIGNUM **)&BnKey, NULL); + BnKey = RsaPkeyCtx->P; // MU_CHANGE break; // // RSA Secret Prime Factor of Modules (q) // case RsaKeyQ: - RSA_get0_factors (RsaKey, NULL, (const BIGNUM **)&BnKey); + BnKey = RsaPkeyCtx->Q; // MU_CHANGE break; // // p's CRT Exponent (== d mod (p - 1)) // case RsaKeyDp: - RSA_get0_crt_params (RsaKey, (const BIGNUM **)&BnKey, NULL, NULL); + BnKey = RsaPkeyCtx->Dp; // MU_CHANGE break; // // q's CRT Exponent (== d mod (q - 1)) // case RsaKeyDq: - RSA_get0_crt_params (RsaKey, NULL, (const BIGNUM **)&BnKey, NULL); + BnKey = RsaPkeyCtx->Dq; // MU_CHANGE break; // // The CRT Coefficient (== 1/q mod p) // case RsaKeyQInv: - RSA_get0_crt_params (RsaKey, NULL, NULL, (const BIGNUM **)&BnKey); + BnKey = RsaPkeyCtx->QInv; // MU_CHANGE break; default: @@ -186,8 +234,13 @@ RsaGenerateKey ( IN UINTN PublicExponentSize ) { - BIGNUM *KeyE; - BOOLEAN RetVal; + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + EVP_PKEY_CTX *KeyGenCtx; + EVP_PKEY *Pkey; + BIGNUM *KeyE; + BOOLEAN RetVal; + // MU_CHANGE [END] // // Check input parameters. @@ -196,29 +249,89 @@ RsaGenerateKey ( return FALSE; } - KeyE = BN_new (); - if (KeyE == NULL) { + // MU_CHANGE [BEGIN] + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; + KeyGenCtx = NULL; + Pkey = NULL; + KeyE = NULL; + RetVal = FALSE; + + // + // Invalidate any cached key since we are generating a new one. + // + RsaInvalidatePkey (RsaPkeyCtx); + + KeyGenCtx = EVP_PKEY_CTX_new_from_name (NULL, "RSA", NULL); + if (KeyGenCtx == NULL) { + // MU_CHANGE [END] return FALSE; } - RetVal = FALSE; + // MU_CHANGE [BEGIN] + if (EVP_PKEY_keygen_init (KeyGenCtx) != 1) { + goto _Exit; + } + + if (EVP_PKEY_CTX_set_rsa_keygen_bits (KeyGenCtx, (INT32)ModulusLength) != 1) { + goto _Exit; + } + // MU_CHANGE [END] - if (PublicExponent == NULL) { - if (BN_set_word (KeyE, 0x10001) == 0) { + // MU_CHANGE [BEGIN] + // + // Set public exponent if provided, otherwise OpenSSL defaults to 0x10001. + // + if (PublicExponent != NULL) { + KeyE = BN_new (); + if (KeyE == NULL) { + // MU_CHANGE [END] goto _Exit; } - } else { + // MU_CHANGE if (BN_bin2bn (PublicExponent, (UINT32)PublicExponentSize, KeyE) == NULL) { goto _Exit; } +// MU_CHANGE [BEGIN] + + if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp (KeyGenCtx, KeyE) != 1) { + goto _Exit; + } +// MU_CHANGE [END] + } + + // MU_CHANGE [BEGIN] + if (EVP_PKEY_keygen (KeyGenCtx, &Pkey) != 1) { + goto _Exit; + // MU_CHANGE [END] } - if (RSA_generate_key_ex ((RSA *)RsaContext, (UINT32)ModulusLength, KeyE, NULL) == 1) { - RetVal = TRUE; + // MU_CHANGE [BEGIN] + // + // Extract all key components from the generated EVP_PKEY. + // + if (!RsaExtractBigNums (RsaPkeyCtx, Pkey)) { + EVP_PKEY_free (Pkey); + goto _Exit; } + // + // Cache the generated EVP_PKEY. + // + RsaPkeyCtx->Pkey = Pkey; + RetVal = TRUE; + + // MU_CHANGE [END] _Exit: - BN_free (KeyE); + // MU_CHANGE [BEGIN] + if (KeyE != NULL) { + BN_free (KeyE); + } + + if (KeyGenCtx != NULL) { + EVP_PKEY_CTX_free (KeyGenCtx); + } + + // MU_CHANGE [END] return RetVal; } @@ -247,7 +360,12 @@ RsaCheckKey ( IN VOID *RsaContext ) { - UINTN Reason; + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + EVP_PKEY *Pkey; + EVP_PKEY_CTX *PkeyCtx; + INT32 Result; + // MU_CHANGE [END] // // Check input parameters. @@ -256,15 +374,30 @@ RsaCheckKey ( return FALSE; } - if (RSA_check_key ((RSA *)RsaContext) != 1) { - Reason = ERR_GET_REASON (ERR_peek_last_error ()); - if ((Reason == RSA_R_P_NOT_PRIME) || - (Reason == RSA_R_Q_NOT_PRIME) || - (Reason == RSA_R_N_DOES_NOT_EQUAL_P_Q) || - (Reason == RSA_R_D_E_NOT_CONGRUENT_TO_1)) - { - return FALSE; - } + // MU_CHANGE [BEGIN] + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; + PkeyCtx = NULL; + + // + // Build EVP_PKEY from stored key components. + // + Pkey = RsaBuildEvpPkey (RsaPkeyCtx); + if (Pkey == NULL) { + return FALSE; + } + + PkeyCtx = EVP_PKEY_CTX_new_from_pkey (NULL, Pkey, NULL); + if (PkeyCtx == NULL) { + return FALSE; + } + + Result = EVP_PKEY_check (PkeyCtx); + + EVP_PKEY_CTX_free (PkeyCtx); + + if (Result != 1) { + return FALSE; + // MU_CHANGE [END] } return TRUE; @@ -305,9 +438,14 @@ RsaPkcs1Sign ( IN OUT UINTN *SigSize ) { - RSA *Rsa; - UINTN Size; - INT32 DigestType; + // MU_CHANGE [BEGIN] + RSA_PKEY_CTX *RsaPkeyCtx; + EVP_PKEY *Pkey; + EVP_PKEY_CTX *PkeyCtx; + CONST EVP_MD *Md; + UINTN RequiredSize; + BOOLEAN Result; + // MU_CHANGE [END] // // Check input parameters. @@ -316,53 +454,81 @@ RsaPkcs1Sign ( return FALSE; } - Rsa = (RSA *)RsaContext; - Size = RSA_size (Rsa); - - if (*SigSize < Size) { - *SigSize = Size; + // MU_CHANGE [BEGIN] + // + // Determine the message digest algorithm according to digest size. + // + Md = GetEvpMdFromHashSize (HashSize); + if (Md == NULL) { + // MU_CHANGE [END] return FALSE; } - if (Signature == NULL) { + // MU_CHANGE [BEGIN] + RsaPkeyCtx = (RSA_PKEY_CTX *)RsaContext; + PkeyCtx = NULL; + Result = FALSE; + + // + // Build EVP_PKEY from stored key components. + // + Pkey = RsaBuildEvpPkey (RsaPkeyCtx); + if (Pkey == NULL) { + // MU_CHANGE [END] return FALSE; } // - // Determine the message digest algorithm according to digest size. - // Only MD5, SHA-1, SHA-256, SHA-384 or SHA-512 algorithm is supported. + // Check if the signature buffer is large enough. // MU_CHANGE // - switch (HashSize) { - case MD5_DIGEST_SIZE: - DigestType = NID_md5; - break; + // MU_CHANGE [BEGIN] + RequiredSize = (UINTN)EVP_PKEY_get_size (Pkey); + if (*SigSize < RequiredSize) { + *SigSize = RequiredSize; + return FALSE; + } + // MU_CHANGE [END] - case SHA1_DIGEST_SIZE: - DigestType = NID_sha1; - break; + // MU_CHANGE [BEGIN] + if (Signature == NULL) { + return FALSE; + } + // MU_CHANGE [END] - case SHA256_DIGEST_SIZE: - DigestType = NID_sha256; - break; + // MU_CHANGE [BEGIN] + PkeyCtx = EVP_PKEY_CTX_new_from_pkey (NULL, Pkey, NULL); + if (PkeyCtx == NULL) { + goto _Exit; + } + // MU_CHANGE [END] - case SHA384_DIGEST_SIZE: - DigestType = NID_sha384; - break; + // MU_CHANGE [BEGIN] + if (EVP_PKEY_sign_init (PkeyCtx) != 1) { + goto _Exit; + } + // MU_CHANGE [END] - case SHA512_DIGEST_SIZE: - DigestType = NID_sha512; - break; + // MU_CHANGE [BEGIN] + if (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_PADDING) <= 0) { + goto _Exit; + } + // MU_CHANGE [END] - default: - return FALSE; + // MU_CHANGE [BEGIN] + if (EVP_PKEY_CTX_set_signature_md (PkeyCtx, Md) <= 0) { + goto _Exit; + } + + *SigSize = RequiredSize; + if (EVP_PKEY_sign (PkeyCtx, Signature, SigSize, MessageHash, HashSize) == 1) { + Result = TRUE; + } + +_Exit: + if (PkeyCtx != NULL) { + EVP_PKEY_CTX_free (PkeyCtx); + // MU_CHANGE [END] } - return (BOOLEAN)RSA_sign ( - DigestType, - MessageHash, - (UINT32)HashSize, - Signature, - (UINT32 *)SigSize, - (RSA *)RsaContext - ); + return Result; // MU_CHANGE } diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPkeyCtx.h b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPkeyCtx.h new file mode 100644 index 000000000..0a82011ae --- /dev/null +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPkeyCtx.h @@ -0,0 +1,83 @@ +/** @file +// MU_CHANGE + Internal header for RSA EVP_PKEY context shared between CryptRsaBasic.c + and CryptRsaExt.c. + + Defines the RSA_PKEY_CTX structure that replaces the deprecated OpenSSL RSA + object, and declares helper functions for building and managing EVP_PKEY + instances from stored BIGNUM key components. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef CRYPT_RSA_PKEY_CTX_H_ +#define CRYPT_RSA_PKEY_CTX_H_ + +#include +#include + +/// +/// Internal RSA key context that holds individual BIGNUM key components +/// and a cached EVP_PKEY built from those components. +/// +typedef struct { + EVP_PKEY *Pkey; + BIGNUM *N; ///< Public modulus + BIGNUM *E; ///< Public exponent + BIGNUM *D; ///< Private exponent + BIGNUM *P; ///< Secret prime factor p + BIGNUM *Q; ///< Secret prime factor q + BIGNUM *Dp; ///< p's CRT exponent (d mod (p-1)) + BIGNUM *Dq; ///< q's CRT exponent (d mod (q-1)) + BIGNUM *QInv; ///< CRT coefficient (1/q mod p) +} RSA_PKEY_CTX; + +/** + Build (or return cached) EVP_PKEY from the stored BIGNUM components. + + If the EVP_PKEY is already cached and valid, return it directly. + Otherwise, construct a new EVP_PKEY using OSSL_PARAM_BLD and + EVP_PKEY_fromdata. + + @param[in,out] RsaPkeyCtx Pointer to RSA_PKEY_CTX holding key components. + + @return Pointer to EVP_PKEY on success, or NULL on failure. +**/ +EVP_PKEY * +RsaBuildEvpPkey ( + IN OUT RSA_PKEY_CTX *RsaPkeyCtx + ); + +/** + Extract all RSA BIGNUM key components from an EVP_PKEY into RSA_PKEY_CTX. + + Any previously stored BIGNUMs in the context are freed before extraction. + + @param[in,out] RsaPkeyCtx Pointer to RSA_PKEY_CTX to populate. + @param[in] Pkey EVP_PKEY from which to extract components. + + @retval TRUE Components extracted successfully. + @retval FALSE Extraction failed. +**/ +BOOLEAN +RsaExtractBigNums ( + IN OUT RSA_PKEY_CTX *RsaPkeyCtx, + IN EVP_PKEY *Pkey + ); + +/** + Invalidate (free) the cached EVP_PKEY in the RSA context. + + Called when key components change so the EVP_PKEY will be rebuilt + on next use. + + @param[in,out] RsaPkeyCtx Pointer to RSA_PKEY_CTX whose cache to invalidate. +**/ +VOID +RsaInvalidatePkey ( + IN OUT RSA_PKEY_CTX *RsaPkeyCtx + ); + +#endif // CRYPT_RSA_PKEY_CTX_H_ From bfd0049964fcf9221f80b81052bec87be4b27b9d Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:19:03 -0700 Subject: [PATCH 3/9] OpensslPkg: Migrate RSA consumers to RSA_PKEY_CTX Update files that consume RSA keys to work with the new RSA_PKEY_CTX type instead of the deprecated RSA* direct usage: - CryptPkcs7Sign.c: remove EVP_PKEY_assign_RSA; use RSA_PKEY_CTX->Pkey - CryptPkcs1Oaep.c: remove EVP_PKEY_set1_RSA; use RSA_PKEY_CTX->Pkey - CryptRsaPss.c: update context casting to RSA_PKEY_CTX - CryptRsaPssSign.c: update context casting to RSA_PKEY_CTX Signed-off-by: Doug Flick --- .../Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c | 58 ++++-------- .../Library/BaseCryptLib/Pk/CryptPkcs7Sign.c | 89 ++++++++++++------- .../Library/BaseCryptLib/Pk/CryptRsaPss.c | 36 +++++--- .../Library/BaseCryptLib/Pk/CryptRsaPssSign.c | 42 +++++---- 4 files changed, 122 insertions(+), 103 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c index 7634ab1f6..dc8be18bc 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs1Oaep.c @@ -14,6 +14,11 @@ #include #include +// MU_CHANGE [BEGIN] +#include "CryptRsaPkeyCtx.h" + +// MU_CHANGE [END] + /** Retrieve a pointer to EVP message digest object. @@ -374,7 +379,7 @@ RsaOaepEncrypt ( OUT UINTN *EncryptedDataSize ) { - BOOLEAN Result; + // MU_CHANGE - BOOLEAN Result; EVP_PKEY *Pkey; // @@ -386,31 +391,21 @@ RsaOaepEncrypt ( return FALSE; } + // MU_CHANGE [BEGIN] + *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 + // Build EVP_PKEY from the RSA_PKEY_CTX key components. // MU_CHANGE // - if (Pkey != NULL) { - EVP_PKEY_free (Pkey); + Pkey = RsaBuildEvpPkey ((RSA_PKEY_CTX *)RsaContext); + if (Pkey == NULL) { + return FALSE; + // MU_CHANGE [END] } - return Result; + return InternalPkcs1v2Encrypt (Pkey, InData, InDataSize, PrngSeed, PrngSeedSize, DigestLen, EncryptedData, EncryptedDataSize); // MU_CHANGE } /** @@ -675,7 +670,7 @@ RsaOaepDecrypt ( OUT UINTN *OutDataSize ) { - BOOLEAN Result; + // MU_CHANGE - BOOLEAN Result; EVP_PKEY *Pkey; // @@ -687,28 +682,13 @@ RsaOaepDecrypt ( return FALSE; } - Result = FALSE; - Pkey = NULL; - // - // Create a context for the decryption operation. + // Build EVP_PKEY from the RSA_PKEY_CTX key components. // MU_CHANGE // - - Pkey = EVP_PKEY_new (); + Pkey = RsaBuildEvpPkey ((RSA_PKEY_CTX *)RsaContext); // MU_CHANGE if (Pkey == NULL) { - goto _Exit; + return FALSE; // MU_CHANGE } - 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; + return InternalPkcs1v2Decrypt (Pkey, EncryptedData, EncryptedDataSize, DigestLen, OutData, OutDataSize); // MU_CHANGE } diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c index 087c02da4..dc2e6be70 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c @@ -11,6 +11,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include // MU_CHANGE /** Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message @@ -56,42 +57,58 @@ Pkcs7Sign ( X509 *Cert; // MU_CHANGE [TCBZ3925] - Pkcs7Sign is broken EVP_PKEY *Key; BIO *DataBio; + BIO *PemBio; // MU_CHANGE PKCS7 *Pkcs7; - UINT8 *RsaContext; - UINT8 *P7Data; - UINTN P7DataSize; - UINT8 *Tmp; + // MU_CHANGE - UINT8 *RsaContext; + UINT8 *P7Data; + UINTN P7DataSize; + UINT8 *Tmp; // // Check input parameters. // if ((PrivateKey == NULL) || (KeyPassword == NULL) || (InData == NULL) || - (SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL) || (InDataSize > INT_MAX)) + // MU_CHANGE [BEGIN] + (SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL) || + (PrivateKeySize > INT_MAX) || (InDataSize > INT_MAX)) + // MU_CHANGE [END] { return FALSE; } - RsaContext = NULL; - Cert = NULL; // MU_CHANGE [TCBZ3925] - Pkcs7Sign is broken - Key = NULL; - Pkcs7 = NULL; - DataBio = NULL; - Status = FALSE; + Cert = NULL; // MU_CHANGE [TCBZ3925] - Pkcs7Sign is broken + Key = NULL; + Pkcs7 = NULL; + DataBio = NULL; + PemBio = NULL; + Status = FALSE; // - // Retrieve RSA private key from PEM data. + // Retrieve RSA private key from PEM data as EVP_PKEY directly. // MU_CHANGE // - Status = RsaGetPrivateKeyFromPem ( - PrivateKey, - PrivateKeySize, - (CONST CHAR8 *)KeyPassword, - (VOID **)&RsaContext - ); - if (!Status) { - return Status; + // MU_CHANGE [BEGIN] + PemBio = BIO_new_mem_buf (PrivateKey, (int)PrivateKeySize); + if (PemBio == NULL) { + goto _Exit; } - Status = FALSE; + Key = PEM_read_bio_PrivateKey (PemBio, NULL, NULL, (void *)KeyPassword); + if (Key == NULL) { + goto _Exit; + // MU_CHANGE [END] + } + + // MU_CHANGE [BEGIN] + // + // Pkcs7Sign currently supports RSA private keys only. + // Additional key types (for example, MLDSA or composite keys) require + // extending this flow with algorithm-specific signing support. + // + if (EVP_PKEY_id (Key) != EVP_PKEY_RSA) { + goto _Exit; + } + + // MU_CHANGE [END] // // Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling @@ -121,18 +138,18 @@ Pkcs7Sign ( // MU_CHANGE [TCBZ3925] [END] - Pkcs7Sign is broken - // - // Construct OpenSSL EVP_PKEY for private key. - // - Key = EVP_PKEY_new (); - if (Key == NULL) { - goto _Exit; - } - - if (EVP_PKEY_assign_RSA (Key, (RSA *)RsaContext) == 0) { - goto _Exit; - } - + // MU_CHANGE [BEGIN] + // // + // // Construct OpenSSL EVP_PKEY for private key. + // // + // Key = EVP_PKEY_new (); + // if (Key == NULL) { + // goto _Exit; + // } + // if (EVP_PKEY_assign_RSA (Key, (RSA *)RsaContext) == 0) { + // goto _Exit; + // } + // MU_CHANGE [END] // // Convert the data to be signed to BIO format. // @@ -212,6 +229,12 @@ Pkcs7Sign ( BIO_free (DataBio); } + // MU_CHANGE [BEGIN] + if (PemBio != NULL) { + BIO_free (PemBio); + } + + // MU_CHANGE [END] if (Pkcs7 != NULL) { PKCS7_free (Pkcs7); } diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c index bdc9155e1..e53987a7b 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c @@ -4,6 +4,10 @@ This file implements following APIs which provide basic capabilities for RSA: 1) RsaPssVerify + // MU_CHANGE [BEGIN] + Uses OpenSSL 3.x EVP_PKEY provider-based APIs instead of deprecated RSA APIs. + + // MU_CHANGE [END] Copyright (c) 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -16,6 +20,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include +// MU_CHANGE [BEGIN] +#include "CryptRsaPkeyCtx.h" + +// MU_CHANGE [END] + /** Retrieve a pointer to EVP message digest object. @@ -75,13 +84,13 @@ RsaPssVerify ( ) { BOOLEAN Result; - EVP_PKEY *EvpRsaKey; + EVP_PKEY *Pkey; // MU_CHANGE EVP_MD_CTX *EvpVerifyCtx; EVP_PKEY_CTX *KeyCtx; CONST EVP_MD *HashAlg; Result = FALSE; - EvpRsaKey = NULL; + Pkey = NULL; // MU_CHANGE EvpVerifyCtx = NULL; KeyCtx = NULL; HashAlg = NULL; @@ -108,19 +117,22 @@ RsaPssVerify ( return FALSE; } - EvpRsaKey = EVP_PKEY_new (); - if (EvpRsaKey == NULL) { - goto _Exit; + // MU_CHANGE [BEGIN] + // + // Build EVP_PKEY from the RSA_PKEY_CTX key components. + // + Pkey = RsaBuildEvpPkey ((RSA_PKEY_CTX *)RsaContext); + if (Pkey == NULL) { + return FALSE; + // MU_CHANGE [END] } - EVP_PKEY_set1_RSA (EvpRsaKey, RsaContext); - - EvpVerifyCtx = EVP_MD_CTX_create (); + EvpVerifyCtx = EVP_MD_CTX_new (); // MU_CHANGE if (EvpVerifyCtx == NULL) { goto _Exit; } - Result = EVP_DigestVerifyInit (EvpVerifyCtx, &KeyCtx, HashAlg, NULL, EvpRsaKey) > 0; + Result = EVP_DigestVerifyInit (EvpVerifyCtx, &KeyCtx, HashAlg, NULL, Pkey) > 0; // MU_CHANGE if (KeyCtx == NULL) { goto _Exit; } @@ -146,12 +158,8 @@ RsaPssVerify ( } _Exit: - if (EvpRsaKey != NULL) { - EVP_PKEY_free (EvpRsaKey); - } - if (EvpVerifyCtx != NULL) { - EVP_MD_CTX_destroy (EvpVerifyCtx); + EVP_MD_CTX_free (EvpVerifyCtx); // MU_CHANGE } return Result; diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c index 07c24f6e8..e522efcfe 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c @@ -4,6 +4,10 @@ This file implements following APIs which provide basic capabilities for RSA: 1) RsaPssSign + // MU_CHANGE [BEGIN] + Uses OpenSSL 3.x EVP_PKEY provider-based APIs instead of deprecated RSA APIs. + + // MU_CHANGE [END] Copyright (c) 2021, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent @@ -16,6 +20,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include +// MU_CHANGE [BEGIN] +#include "CryptRsaPkeyCtx.h" + +// MU_CHANGE [END] + /** Retrieve a pointer to EVP message digest object. @@ -90,13 +99,13 @@ RsaPssSign ( { BOOLEAN Result; UINTN RsaSigSize; - EVP_PKEY *EvpRsaKey; + EVP_PKEY *Pkey; // MU_CHANGE EVP_MD_CTX *EvpVerifyCtx; EVP_PKEY_CTX *KeyCtx; CONST EVP_MD *HashAlg; Result = FALSE; - EvpRsaKey = NULL; + Pkey = NULL; // MU_CHANGE EvpVerifyCtx = NULL; KeyCtx = NULL; HashAlg = NULL; @@ -109,7 +118,17 @@ RsaPssSign ( return FALSE; } - RsaSigSize = RSA_size (RsaContext); + // MU_CHANGE [BEGIN] + // + // Build EVP_PKEY from the RSA_PKEY_CTX key components. + // + Pkey = RsaBuildEvpPkey ((RSA_PKEY_CTX *)RsaContext); + if (Pkey == NULL) { + return FALSE; + } + + RsaSigSize = (UINTN)EVP_PKEY_get_size (Pkey); + // MU_CHANGE [END] if (*SigSize < RsaSigSize) { *SigSize = RsaSigSize; return FALSE; @@ -129,19 +148,12 @@ RsaPssSign ( return FALSE; } - EvpRsaKey = EVP_PKEY_new (); - if (EvpRsaKey == NULL) { - goto _Exit; - } - - EVP_PKEY_set1_RSA (EvpRsaKey, RsaContext); - - EvpVerifyCtx = EVP_MD_CTX_create (); + EvpVerifyCtx = EVP_MD_CTX_new (); // MU_CHANGE if (EvpVerifyCtx == NULL) { goto _Exit; } - Result = EVP_DigestSignInit (EvpVerifyCtx, &KeyCtx, HashAlg, NULL, EvpRsaKey) > 0; + Result = EVP_DigestSignInit (EvpVerifyCtx, &KeyCtx, HashAlg, NULL, Pkey) > 0; // MU_CHANGE if (KeyCtx == NULL) { goto _Exit; } @@ -167,12 +179,8 @@ RsaPssSign ( } _Exit: - if (EvpRsaKey != NULL) { - EVP_PKEY_free (EvpRsaKey); - } - if (EvpVerifyCtx != NULL) { - EVP_MD_CTX_destroy (EvpVerifyCtx); + EVP_MD_CTX_free (EvpVerifyCtx); // MU_CHANGE } return Result; From 05bf4bf5c0ac2125de924a589c69e73558eef2b3 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:19:13 -0700 Subject: [PATCH 4/9] OpensslPkg: Migrate CryptEc.c to EVP_PKEY APIs Replace EC_KEY* based implementation with a new EC_PKEY_CTX struct holding the curve NID and a cached EVP_PKEY*: - Add CryptEcPkeyCtx.h defining EC_PKEY_CTX - EcNewByNid(): allocates EC_PKEY_CTX with OpenSSL NID - EcDhComputeKey(): uses EVP_PKEY_derive with OSSL_PARAM_BLD peer key - EcDsaSign(): uses EVP_PKEY_sign producing DER; converts to raw R||S - EcDsaVerify(): converts raw R||S to DER via i2d_ECDSA_SIG; EVP_PKEY_verify - EC public key export: EVP_PKEY_get_octet_string_param returns 04||X||Y; skip leading 0x04 byte to match caller expectation of raw X||Y Signed-off-by: Doug Flick --- OpensslPkg/Library/BaseCryptLib/Pk/CryptEc.c | 566 ++++++++++++------ .../Library/BaseCryptLib/Pk/CryptEcPkeyCtx.h | 22 + 2 files changed, 400 insertions(+), 188 deletions(-) create mode 100644 OpensslPkg/Library/BaseCryptLib/Pk/CryptEcPkeyCtx.h diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptEc.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptEc.c index cba70557e..b6066be36 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptEc.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptEc.c @@ -10,6 +10,13 @@ #include #include #include +// MU_CHANGE [BEGIN] +#include +#include +#include +#include +#include "CryptEcPkeyCtx.h" +// MU_CHANGE [END] // ===================================================================================== // Basic Elliptic Curve Primitives @@ -405,6 +412,52 @@ EcPointSetCompressedCoordinates ( // Elliptic Curve Diffie Hellman Primitives // ===================================================================================== +// MU_CHANGE [BEGIN] + +/** + Map an OpenSSL NID to the curve name string used by EVP_PKEY_Q_keygen / OSSL_PARAM. + + @param[in] Nid OpenSSL NID for the EC curve. + + @return ASCII curve name string, or NULL if not supported. +**/ +STATIC CONST CHAR8 * +OpenSslNidToCurveName ( + INT32 Nid + ) +{ + switch (Nid) { + case NID_X9_62_prime256v1: return "prime256v1"; + case NID_secp384r1: return "secp384r1"; + case NID_secp521r1: return "secp521r1"; + case NID_brainpoolP512r1: return "brainpoolP512r1"; + default: return NULL; + } +} + +/** + Return the coordinate half-size (in bytes) for a given OpenSSL NID. + + @param[in] Nid OpenSSL NID for the EC curve. + + @return Byte length of one coordinate, or 0 if not supported. +**/ +STATIC UINTN +GetHalfSizeFromNid ( + INT32 Nid + ) +{ + switch (Nid) { + case NID_X9_62_prime256v1: return 32; + case NID_secp384r1: return 48; + case NID_secp521r1: return 66; + case NID_brainpoolP512r1: return 64; + default: return 0; + } +} + +// MU_CHANGE [END] + /** Allocates and Initializes one Elliptic Curve Context for subsequent use with the NID. @@ -420,14 +473,27 @@ EcNewByNid ( IN UINTN Nid ) { - INT32 OpenSslNid; + // MU_CHANGE [BEGIN] + EC_PKEY_CTX *EcPkeyCtx; + INT32 OpenSslNid; + + // MU_CHANGE [END] OpenSslNid = CryptoNidToOpensslNid (Nid); if (OpenSslNid < 0) { return NULL; } - return (VOID *)EC_KEY_new_by_curve_name (OpenSslNid); + // MU_CHANGE [BEGIN] + EcPkeyCtx = AllocateZeroPool (sizeof (EC_PKEY_CTX)); + if (EcPkeyCtx == NULL) { + return NULL; + } + + EcPkeyCtx->Nid = OpenSslNid; + EcPkeyCtx->Pkey = NULL; + return (VOID *)EcPkeyCtx; + // MU_CHANGE [END] } /** @@ -441,7 +507,20 @@ EcFree ( IN VOID *EcContext ) { - EC_KEY_free ((EC_KEY *)EcContext); + // MU_CHANGE [BEGIN] + EC_PKEY_CTX *EcPkeyCtx; + + if (EcContext == NULL) { + return; + } + + EcPkeyCtx = (EC_PKEY_CTX *)EcContext; + if (EcPkeyCtx->Pkey != NULL) { + EVP_PKEY_free (EcPkeyCtx->Pkey); + } + + FreePool (EcPkeyCtx); + // MU_CHANGE [END] } /** @@ -478,15 +557,15 @@ EcGenerateKey ( IN OUT UINTN *PublicKeySize ) { - EC_KEY *EcKey; - CONST EC_GROUP *Group; - CONST EC_POINT *EcPoint; - BOOLEAN RetVal; - BIGNUM *BnX; - BIGNUM *BnY; - UINTN HalfSize; - INTN XSize; - INTN YSize; + // MU_CHANGE [BEGIN] + EC_PKEY_CTX *EcPkeyCtx; + CONST CHAR8 *CurveName; + UINTN HalfSize; + EVP_PKEY *Pkey; + UINT8 PubKeyBuf[133]; + UINTN PubKeyBufLen; + + // MU_CHANGE [END] if ((EcContext == NULL) || (PublicKeySize == NULL)) { return FALSE; @@ -496,12 +575,11 @@ EcGenerateKey ( return FALSE; } - EcKey = (EC_KEY *)EcContext; - Group = EC_KEY_get0_group (EcKey); - HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8; - - // Assume RAND_seed was called - if (EC_KEY_generate_key (EcKey) != 1) { + // MU_CHANGE [BEGIN] + EcPkeyCtx = (EC_PKEY_CTX *)EcContext; + HalfSize = GetHalfSizeFromNid (EcPkeyCtx->Nid); + if (HalfSize == 0) { + // MU_CHANGE [END] return FALSE; } @@ -512,40 +590,55 @@ EcGenerateKey ( *PublicKeySize = HalfSize * 2; - EcPoint = EC_KEY_get0_public_key (EcKey); - if (EcPoint == NULL) { + // MU_CHANGE [BEGIN] + CurveName = OpenSslNidToCurveName (EcPkeyCtx->Nid); + if (CurveName == NULL) { + // MU_CHANGE [END] return FALSE; } - RetVal = FALSE; - BnX = BN_new (); - BnY = BN_new (); - if ((BnX == NULL) || (BnY == NULL)) { - goto fail; + // MU_CHANGE [BEGIN] + if (EcPkeyCtx->Pkey != NULL) { + EVP_PKEY_free (EcPkeyCtx->Pkey); + EcPkeyCtx->Pkey = NULL; + // MU_CHANGE [END] } - if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) { - goto fail; + // MU_CHANGE [BEGIN] + Pkey = EVP_PKEY_Q_keygen (NULL, NULL, "EC", CurveName); + if (Pkey == NULL) { + return FALSE; + // MU_CHANGE [END] } - XSize = BN_num_bytes (BnX); - YSize = BN_num_bytes (BnY); - if ((XSize <= 0) || (YSize <= 0)) { - goto fail; + // MU_CHANGE [BEGIN] + EcPkeyCtx->Pkey = Pkey; + + PubKeyBufLen = sizeof (PubKeyBuf); + if (EVP_PKEY_get_octet_string_param ( + Pkey, + OSSL_PKEY_PARAM_PUB_KEY, + PubKeyBuf, + sizeof (PubKeyBuf), + &PubKeyBufLen + ) != 1) + { + return FALSE; + // MU_CHANGE [END] } - ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize); + // MU_CHANGE [BEGIN] + // PubKeyBuf is 0x04 || X || Y; skip the leading uncompressed-point prefix + if (PubKeyBufLen != 1 + HalfSize * 2) { + return FALSE; + } - ZeroMem (PublicKey, *PublicKeySize); - BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]); - BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]); + // MU_CHANGE [END] - RetVal = TRUE; + ZeroMem (PublicKey, *PublicKeySize); + CopyMem (PublicKey, PubKeyBuf + 1, HalfSize * 2); // MU_CHANGE -fail: - BN_free (BnX); - BN_free (BnY); - return RetVal; + return TRUE; // MU_CHANGE } /** @@ -570,15 +663,13 @@ EcGetPubKey ( IN OUT UINTN *PublicKeySize ) { - EC_KEY *EcKey; - CONST EC_GROUP *Group; - CONST EC_POINT *EcPoint; - BIGNUM *BnX; - BIGNUM *BnY; - UINTN HalfSize; - INTN XSize; - INTN YSize; - BOOLEAN RetVal; + // MU_CHANGE [BEGIN] + EC_PKEY_CTX *EcPkeyCtx; + UINTN HalfSize; + UINT8 PubKeyBuf[133]; + UINTN PubKeyBufLen; + + // MU_CHANGE [END] if ((EcContext == NULL) || (PublicKeySize == NULL)) { return FALSE; @@ -588,12 +679,20 @@ EcGetPubKey ( return FALSE; } - BnX = NULL; - BnY = NULL; + // MU_CHANGE [BEGIN] + EcPkeyCtx = (EC_PKEY_CTX *)EcContext; + HalfSize = GetHalfSizeFromNid (EcPkeyCtx->Nid); + if (HalfSize == 0) { + return FALSE; + } + + // MU_CHANGE [END] - EcKey = (EC_KEY *)EcContext; - Group = EC_KEY_get0_group (EcKey); - HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8; + // MU_CHANGE [BEGIN] + // EcKey = (EC_KEY *)EcContext; + // Group = EC_KEY_get0_group (EcKey); + // HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8; + // MU_CHANGE [END] if (*PublicKeySize < HalfSize * 2) { *PublicKeySize = HalfSize * 2; return FALSE; @@ -601,48 +700,39 @@ EcGetPubKey ( *PublicKeySize = HalfSize * 2; - EcPoint = EC_KEY_get0_public_key (EcKey); - if (EcPoint == NULL) { + if (EcPkeyCtx->Pkey == NULL) { + // MU_CHANGE return FALSE; } - RetVal = FALSE; - BnX = BN_new (); - BnY = BN_new (); - if ((BnX == NULL) || (BnY == NULL)) { - goto fail; - } - - if (EC_POINT_get_affine_coordinates (Group, EcPoint, BnX, BnY, NULL) != 1) { - goto fail; + // MU_CHANGE [BEGIN] + PubKeyBufLen = sizeof (PubKeyBuf); + if (EVP_PKEY_get_octet_string_param ( + EcPkeyCtx->Pkey, + OSSL_PKEY_PARAM_PUB_KEY, + PubKeyBuf, + sizeof (PubKeyBuf), + &PubKeyBufLen + ) != 1) + { + return FALSE; + // MU_CHANGE [END] } - XSize = BN_num_bytes (BnX); - YSize = BN_num_bytes (BnY); - if ((XSize <= 0) || (YSize <= 0)) { - goto fail; + // MU_CHANGE [BEGIN] + // PubKeyBuf is 0x04 || X || Y; skip the leading uncompressed-point prefix + if (PubKeyBufLen != 1 + HalfSize * 2) { + return FALSE; + // MU_CHANGE [END] } - ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize); - + // MU_CHANGE - ASSERT ((UINTN)XSize <= HalfSize && (UINTN)YSize <= HalfSize); if (PublicKey != NULL) { ZeroMem (PublicKey, *PublicKeySize); - BN_bn2bin (BnX, &PublicKey[0 + HalfSize - XSize]); - BN_bn2bin (BnY, &PublicKey[HalfSize + HalfSize - YSize]); + CopyMem (PublicKey, PubKeyBuf + 1, HalfSize * 2); // MU_CHANGE } - RetVal = TRUE; - -fail: - if (BnX != NULL) { - BN_free (BnX); - } - - if (BnY != NULL) { - BN_free (BnY); - } - - return RetVal; + return TRUE; // MU_CHANGE } /** @@ -682,15 +772,23 @@ EcDhComputeKey ( IN OUT UINTN *KeySize ) { - EC_KEY *EcKey; - EC_KEY *PeerEcKey; - CONST EC_GROUP *Group; + // MU_CHANGE [BEGIN] + EC_PKEY_CTX *EcPkeyCtx; + CONST CHAR8 *CurveName; + // MU_CHANGE [END] + UINTN HalfSize; + // MU_CHANGE [BEGIN] BOOLEAN RetVal; - BIGNUM *BnX; - BIGNUM *BnY; - EC_POINT *Point; - INT32 OpenSslNid; - UINTN HalfSize; + UINT8 PubKeyBuf[133]; + UINTN PubKeyLen; + OSSL_PARAM_BLD *Bld; + OSSL_PARAM *Params; + EVP_PKEY_CTX *FromdataCtx; + EVP_PKEY *PeerPkey; + EVP_PKEY_CTX *DeriveCtx; + UINTN DerivedLen; + + // MU_CHANGE [END] if ((EcContext == NULL) || (PeerPublic == NULL) || (KeySize == NULL)) { return FALSE; @@ -704,9 +802,14 @@ EcDhComputeKey ( return FALSE; } - EcKey = (EC_KEY *)EcContext; - Group = EC_KEY_get0_group (EcKey); - HalfSize = (EC_GROUP_get_degree (Group) + 7) / 8; + // MU_CHANGE [BEGIN] + EcPkeyCtx = (EC_PKEY_CTX *)EcContext; + HalfSize = GetHalfSizeFromNid (EcPkeyCtx->Nid); + if (HalfSize == 0) { + return FALSE; + } + + // MU_CHANGE [END] if ((CompressFlag == NULL) && (PeerPublicSize != HalfSize * 2)) { return FALSE; } @@ -722,57 +825,108 @@ EcDhComputeKey ( *KeySize = HalfSize; - RetVal = FALSE; - Point = NULL; - BnX = BN_bin2bn (PeerPublic, (INT32)HalfSize, NULL); - BnY = NULL; - Point = EC_POINT_new (Group); - PeerEcKey = NULL; - if ((BnX == NULL) || (Point == NULL)) { - goto fail; + // MU_CHANGE [BEGIN] + if (EcPkeyCtx->Pkey == NULL) { + return FALSE; + // MU_CHANGE [END] + } + + // MU_CHANGE [BEGIN] + CurveName = OpenSslNidToCurveName (EcPkeyCtx->Nid); + if (CurveName == NULL) { + return FALSE; } + // Build uncompressed or compressed peer public key buffer + // MU_CHANGE [END] if (CompressFlag == NULL) { - BnY = BN_bin2bn (PeerPublic + HalfSize, (INT32)HalfSize, NULL); - if (BnY == NULL) { - goto fail; - } - - if (EC_POINT_set_affine_coordinates (Group, Point, BnX, BnY, NULL) != 1) { - goto fail; - } + // MU_CHANGE [BEGIN] + PubKeyBuf[0] = 0x04; + CopyMem (PubKeyBuf + 1, PeerPublic, HalfSize * 2); + PubKeyLen = 1 + HalfSize * 2; + // MU_CHANGE [END] } else { - if (EC_POINT_set_compressed_coordinates (Group, Point, BnX, *CompressFlag, NULL) != 1) { - goto fail; - } + // MU_CHANGE [BEGIN] + PubKeyBuf[0] = (UINT8)((*CompressFlag & 1) ? 0x03 : 0x02); + CopyMem (PubKeyBuf + 1, PeerPublic, HalfSize); + PubKeyLen = 1 + HalfSize; + } + + RetVal = FALSE; + Bld = NULL; + Params = NULL; + FromdataCtx = NULL; + PeerPkey = NULL; + DeriveCtx = NULL; + + Bld = OSSL_PARAM_BLD_new (); + if (Bld == NULL) { + goto fail; + } + + if (OSSL_PARAM_BLD_push_utf8_string (Bld, OSSL_PKEY_PARAM_GROUP_NAME, CurveName, 0) != 1) { + goto fail; + } + + if (OSSL_PARAM_BLD_push_octet_string (Bld, OSSL_PKEY_PARAM_PUB_KEY, PubKeyBuf, PubKeyLen) != 1) { + goto fail; + } + + Params = OSSL_PARAM_BLD_to_param (Bld); + if (Params == NULL) { + goto fail; + // MU_CHANGE [END] } - // Validate NIST ECDH public key - OpenSslNid = EC_GROUP_get_curve_name (Group); - PeerEcKey = EC_KEY_new_by_curve_name (OpenSslNid); - if (PeerEcKey == NULL) { + // MU_CHANGE [BEGIN] + FromdataCtx = EVP_PKEY_CTX_new_from_name (NULL, "EC", NULL); + if (FromdataCtx == NULL) { + // MU_CHANGE [END] goto fail; } - if (EC_KEY_set_public_key (PeerEcKey, Point) != 1) { + if (EVP_PKEY_fromdata_init (FromdataCtx) != 1) { + // MU_CHANGE goto fail; } - if (EC_KEY_check_key (PeerEcKey) != 1) { + if (EVP_PKEY_fromdata (FromdataCtx, &PeerPkey, EVP_PKEY_PUBLIC_KEY, Params) != 1) { + // MU_CHANGE goto fail; } - if (ECDH_compute_key (Key, *KeySize, Point, EcKey, NULL) <= 0) { + // MU_CHANGE [BEGIN] + DeriveCtx = EVP_PKEY_CTX_new (EcPkeyCtx->Pkey, NULL); + if (DeriveCtx == NULL) { + goto fail; + } + + if (EVP_PKEY_derive_init (DeriveCtx) != 1) { + goto fail; + } + + // EVP_PKEY_derive_set_peer also validates the peer key + if (EVP_PKEY_derive_set_peer (DeriveCtx, PeerPkey) != 1) { + goto fail; + } + + DerivedLen = *KeySize; + // Use <= 0 (not != 1) to match OpenSSL convention: 1 = success, 0 or negative = error + if (EVP_PKEY_derive (DeriveCtx, Key, &DerivedLen) <= 0) { + // MU_CHANGE [END] goto fail; } RetVal = TRUE; fail: - BN_free (BnX); - BN_free (BnY); - EC_POINT_free (Point); - EC_KEY_free (PeerEcKey); + // MU_CHANGE [BEGIN] + OSSL_PARAM_BLD_free (Bld); + OSSL_PARAM_free (Params); + EVP_PKEY_CTX_free (FromdataCtx); + EVP_PKEY_free (PeerPkey); + EVP_PKEY_CTX_free (DeriveCtx); + // MU_CHANGE [END] return RetVal; } @@ -816,14 +970,20 @@ EcDsaSign ( IN OUT UINTN *SigSize ) { - EC_KEY *EcKey; - ECDSA_SIG *EcDsaSig; - INT32 OpenSslNid; - UINT8 HalfSize; - BIGNUM *R; - BIGNUM *S; - INTN RSize; - INTN SSize; + // MU_CHANGE [BEGIN] + EC_PKEY_CTX *EcPkeyCtx; + UINTN HalfSize; + EVP_PKEY_CTX *PkeyCtx; + ECDSA_SIG *EcDsaSig; + UINT8 DerSig[150]; + UINTN DerSigLen; + CONST UINT8 *DerSigPtr; + BIGNUM *R; + BIGNUM *S; + INTN RSize; + INTN SSize; + + // MU_CHANGE [END] if ((EcContext == NULL) || (MessageHash == NULL)) { return FALSE; @@ -833,23 +993,12 @@ EcDsaSign ( return FALSE; } - EcKey = (EC_KEY *)EcContext; - OpenSslNid = EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey)); - switch (OpenSslNid) { - case NID_X9_62_prime256v1: - HalfSize = 32; - break; - case NID_secp384r1: - HalfSize = 48; - break; - case NID_secp521r1: - HalfSize = 66; - break; - case NID_brainpoolP512r1: - HalfSize = 64; - break; - default: - return FALSE; + // MU_CHANGE [BEGIN] + EcPkeyCtx = (EC_PKEY_CTX *)EcContext; + HalfSize = GetHalfSizeFromNid (EcPkeyCtx->Nid); + if (HalfSize == 0) { + return FALSE; + // MU_CHANGE [END] } if (*SigSize < (UINTN)(HalfSize * 2)) { @@ -886,11 +1035,33 @@ EcDsaSign ( return FALSE; } - EcDsaSig = ECDSA_do_sign ( - MessageHash, - (UINT32)HashSize, - (EC_KEY *)EcContext - ); + // MU_CHANGE [BEGIN] + if (EcPkeyCtx->Pkey == NULL) { + return FALSE; + } + + PkeyCtx = EVP_PKEY_CTX_new (EcPkeyCtx->Pkey, NULL); + if (PkeyCtx == NULL) { + return FALSE; + } + + if (EVP_PKEY_sign_init (PkeyCtx) != 1) { + EVP_PKEY_CTX_free (PkeyCtx); + return FALSE; + } + + DerSigLen = sizeof (DerSig); + if (EVP_PKEY_sign (PkeyCtx, DerSig, &DerSigLen, MessageHash, HashSize) != 1) { + EVP_PKEY_CTX_free (PkeyCtx); + return FALSE; + } + + EVP_PKEY_CTX_free (PkeyCtx); + + // Parse DER-encoded ECDSA signature into R and S bignums + DerSigPtr = DerSig; + EcDsaSig = d2i_ECDSA_SIG (NULL, &DerSigPtr, (long)DerSigLen); + // MU_CHANGE [END] if (EcDsaSig == NULL) { return FALSE; } @@ -948,13 +1119,19 @@ EcDsaVerify ( IN UINTN SigSize ) { - INT32 Result; - EC_KEY *EcKey; - ECDSA_SIG *EcDsaSig; - INT32 OpenSslNid; - UINT8 HalfSize; - BIGNUM *R; - BIGNUM *S; + // MU_CHANGE [BEGIN] + INT32 Result; + EC_PKEY_CTX *EcPkeyCtx; + ECDSA_SIG *EcDsaSig; + UINTN HalfSize; + BIGNUM *R; + BIGNUM *S; + UINT8 DerSig[150]; + UINT8 *DerSigPtr; + INT32 DerSigLen; + EVP_PKEY_CTX *PkeyCtx; + + // MU_CHANGE [END] if ((EcContext == NULL) || (MessageHash == NULL) || (Signature == NULL)) { return FALSE; @@ -964,23 +1141,12 @@ EcDsaVerify ( return FALSE; } - EcKey = (EC_KEY *)EcContext; - OpenSslNid = EC_GROUP_get_curve_name (EC_KEY_get0_group (EcKey)); - switch (OpenSslNid) { - case NID_X9_62_prime256v1: - HalfSize = 32; - break; - case NID_secp384r1: - HalfSize = 48; - break; - case NID_secp521r1: - HalfSize = 66; - break; - case NID_brainpoolP512r1: - HalfSize = 64; - break; - default: - return FALSE; + // MU_CHANGE [BEGIN] + EcPkeyCtx = (EC_PKEY_CTX *)EcContext; + HalfSize = GetHalfSizeFromNid (EcPkeyCtx->Nid); + if (HalfSize == 0) { + return FALSE; + // MU_CHANGE [END] } if (SigSize != (UINTN)(HalfSize * 2)) { @@ -1013,29 +1179,53 @@ EcDsaVerify ( return FALSE; } + // Build ECDSA_SIG from raw R || S, then DER-encode for EVP_PKEY_verify // MU_CHANGE EcDsaSig = ECDSA_SIG_new (); if (EcDsaSig == NULL) { - ECDSA_SIG_free (EcDsaSig); + // MU_CHANGE - ECDSA_SIG_free (EcDsaSig); return FALSE; } R = BN_bin2bn (Signature, (UINT32)HalfSize, NULL); S = BN_bin2bn (Signature + HalfSize, (UINT32)HalfSize, NULL); if ((R == NULL) || (S == NULL)) { + // MU_CHANGE [BEGIN] + BN_free (R); + BN_free (S); + // MU_CHANGE [END] ECDSA_SIG_free (EcDsaSig); return FALSE; } + // ECDSA_SIG_set0 takes ownership of R and S // MU_CHANGE ECDSA_SIG_set0 (EcDsaSig, R, S); - Result = ECDSA_do_verify ( - MessageHash, - (UINT32)HashSize, - EcDsaSig, - (EC_KEY *)EcContext - ); - + // MU_CHANGE [BEGIN] + DerSigPtr = DerSig; + DerSigLen = i2d_ECDSA_SIG (EcDsaSig, &DerSigPtr); ECDSA_SIG_free (EcDsaSig); + if (DerSigLen <= 0) { + return FALSE; + } + + if (EcPkeyCtx->Pkey == NULL) { + return FALSE; + } + + PkeyCtx = EVP_PKEY_CTX_new (EcPkeyCtx->Pkey, NULL); + if (PkeyCtx == NULL) { + return FALSE; + } + + if (EVP_PKEY_verify_init (PkeyCtx) != 1) { + EVP_PKEY_CTX_free (PkeyCtx); + return FALSE; + } + + Result = EVP_PKEY_verify (PkeyCtx, DerSig, (UINTN)DerSigLen, MessageHash, HashSize); + + EVP_PKEY_CTX_free (PkeyCtx); + // MU_CHANGE [END] return (Result == 1); } diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptEcPkeyCtx.h b/OpensslPkg/Library/BaseCryptLib/Pk/CryptEcPkeyCtx.h new file mode 100644 index 000000000..8540c65b6 --- /dev/null +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptEcPkeyCtx.h @@ -0,0 +1,22 @@ +/** @file +// MU_CHANGE + Internal header defining EC_PKEY_CTX shared between CryptEc.c and CryptX509.c. + + Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#ifndef CRYPT_EC_PKEY_CTX_H_ +#define CRYPT_EC_PKEY_CTX_H_ + +#include + +/// +/// Internal EC key context wrapping an EVP_PKEY with the associated curve NID. +/// +typedef struct { + INT32 Nid; ///< OpenSSL NID (NID_X9_62_prime256v1, NID_secp384r1, etc.) + EVP_PKEY *Pkey; ///< NULL until EcGenerateKey() or EcGetPublicKeyFromX509() +} EC_PKEY_CTX; + +#endif // CRYPT_EC_PKEY_CTX_H_ From f7883a3008f54012cb6709be58e0c46873b1045d Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:19:19 -0700 Subject: [PATCH 5/9] OpensslPkg: Migrate CryptDh.c to EVP_PKEY APIs Replace DH* based implementation with a new DH_PKEY_CTX struct: - DH_PKEY_CTX holds BnP, BnG (set independently by DhSetParameter) and EVP_PKEY* (generated on DhGenerateKey) - DhSetParameter(): stores BnP/BnG; defers key generation - DhGenerateKey(): uses EVP_PKEY_paramgen + EVP_PKEY_keygen - DhComputeKey(): uses EVP_PKEY_derive with peer public key Signed-off-by: Doug Flick --- OpensslPkg/Library/BaseCryptLib/Pk/CryptDh.c | 524 +++++++++++++++++-- 1 file changed, 469 insertions(+), 55 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptDh.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptDh.c index 950e18158..9af25b456 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptDh.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptDh.c @@ -8,8 +8,25 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "InternalCryptLib.h" #include +// MU_CHANGE [BEGIN] +#include +#include +#include +// MU_CHANGE [END] #include +// MU_CHANGE [BEGIN] +/// +/// Internal context structure wrapping EVP_PKEY-based DH state. +/// +typedef struct { + BIGNUM *BnP; ///< Prime p (NULL until DhGenerateParameter or DhSetParameter) + BIGNUM *BnG; ///< Generator g (NULL until DhGenerateParameter or DhSetParameter) + EVP_PKEY *Pkey; ///< NULL until DhGenerateKey() +} DH_PKEY_CTX; + +// MU_CHANGE [END] + /** Allocates and Initializes one Diffie-Hellman Context for subsequent use. @@ -23,10 +40,7 @@ DhNew ( VOID ) { - // - // Allocates & Initializes DH Context by OpenSSL DH_new() - // - return (VOID *)DH_new (); + return (VOID *)AllocateZeroPool (sizeof (DH_PKEY_CTX)); // MU_CHANGE } /** @@ -43,10 +57,29 @@ DhFree ( IN VOID *DhContext ) { - // - // Free OpenSSL DH Context - // - DH_free ((DH *)DhContext); + // MU_CHANGE [BEGIN] + DH_PKEY_CTX *Ctx; + + if (DhContext == NULL) { + return; + } + + Ctx = (DH_PKEY_CTX *)DhContext; + + if (Ctx->BnP != NULL) { + BN_free (Ctx->BnP); + } + + if (Ctx->BnG != NULL) { + BN_free (Ctx->BnG); + } + + if (Ctx->Pkey != NULL) { + EVP_PKEY_free (Ctx->Pkey); + } + + FreePool (Ctx); + // MU_CHANGE [END] } /** @@ -80,8 +113,20 @@ DhGenerateParameter ( OUT UINT8 *Prime ) { - BOOLEAN RetVal; - BIGNUM *BnP; + // MU_CHANGE [BEGIN] + BOOLEAN RetVal; + DH_PKEY_CTX *Ctx; + EVP_PKEY_CTX *PgenCtx; + EVP_PKEY *ParamsPkey; + BIGNUM *BnP; + BIGNUM *BnG; + + RetVal = FALSE; + PgenCtx = NULL; + ParamsPkey = NULL; + BnP = NULL; + BnG = NULL; + // MU_CHANGE [END] // // Check input parameters. @@ -94,15 +139,100 @@ DhGenerateParameter ( return FALSE; } - RetVal = (BOOLEAN)DH_generate_parameters_ex (DhContext, (UINT32)PrimeLength, (UINT32)Generator, NULL); - if (!RetVal) { - return FALSE; + // MU_CHANGE [BEGIN] + Ctx = (DH_PKEY_CTX *)DhContext; + + // + // Generate DH parameters using EVP_PKEY paramgen. + // + PgenCtx = EVP_PKEY_CTX_new_from_name (NULL, "DH", NULL); + if (PgenCtx == NULL) { + goto Fail; + // MU_CHANGE [END] } - DH_get0_pqg (DhContext, (const BIGNUM **)&BnP, NULL, NULL); - BN_bn2bin (BnP, Prime); + // MU_CHANGE [BEGIN] + if (EVP_PKEY_paramgen_init (PgenCtx) <= 0) { + goto Fail; + } - return TRUE; + // MU_CHANGE [END] + + // MU_CHANGE [BEGIN] + if (EVP_PKEY_CTX_set_dh_paramgen_prime_len (PgenCtx, (INT32)PrimeLength) <= 0) { + goto Fail; + } + + if (EVP_PKEY_CTX_set_dh_paramgen_generator (PgenCtx, (INT32)Generator) <= 0) { + goto Fail; + } + + if (EVP_PKEY_paramgen (PgenCtx, &ParamsPkey) <= 0) { + goto Fail; + } + + // + // Extract the generated prime p. + // + if (EVP_PKEY_get_bn_param (ParamsPkey, OSSL_PKEY_PARAM_FFC_P, &BnP) <= 0) { + goto Fail; + } + + // + // Build a new BnG from the generator value. + // + BnG = BN_new (); + if (BnG == NULL) { + goto Fail; + } + + if (!BN_set_word (BnG, (BN_ULONG)Generator)) { + goto Fail; + } + + // + // Update context, releasing any previous params and key. + // + if (Ctx->BnP != NULL) { + BN_free (Ctx->BnP); + } + + if (Ctx->BnG != NULL) { + BN_free (Ctx->BnG); + } + + if (Ctx->Pkey != NULL) { + EVP_PKEY_free (Ctx->Pkey); + Ctx->Pkey = NULL; + } + + Ctx->BnP = BnP; + Ctx->BnG = BnG; + BnP = NULL; + BnG = NULL; + + BN_bn2bin (Ctx->BnP, Prime); + RetVal = TRUE; + +Fail: + if (BnP != NULL) { + BN_free (BnP); + } + + if (BnG != NULL) { + BN_free (BnG); + } + + if (ParamsPkey != NULL) { + EVP_PKEY_free (ParamsPkey); + } + + if (PgenCtx != NULL) { + EVP_PKEY_CTX_free (PgenCtx); + } + + return RetVal; + // MU_CHANGE [END] } /** @@ -135,9 +265,14 @@ DhSetParameter ( IN CONST UINT8 *Prime ) { - DH *Dh; - BIGNUM *BnP; - BIGNUM *BnG; + // MU_CHANGE [BEGIN] + DH_PKEY_CTX *Ctx; + BIGNUM *BnP; + BIGNUM *BnG; + + BnP = NULL; + BnG = NULL; + // MU_CHANGE [END] // // Check input parameters. @@ -151,15 +286,43 @@ DhSetParameter ( } // - // Set the generator and prime parameters for DH object. + // Convert prime bytes to BIGNUM and build generator BIGNUM. // MU_CHANGE // - Dh = (DH *)DhContext; - BnP = BN_bin2bn ((const unsigned char *)Prime, (int)(PrimeLength / 8), NULL); - BnG = BN_bin2bn ((const unsigned char *)&Generator, 1, NULL); - if ((BnP == NULL) || (BnG == NULL) || !DH_set0_pqg (Dh, BnP, NULL, BnG)) { + // MU_CHANGE [BEGIN] + BnP = BN_bin2bn ((const unsigned char *)Prime, (INT32)(PrimeLength / 8), NULL); + BnG = BN_new (); + if ((BnP == NULL) || (BnG == NULL)) { + // MU_CHANGE [END] goto Error; } + // MU_CHANGE [BEGIN] + if (!BN_set_word (BnG, (BN_ULONG)Generator)) { + goto Error; + } + + // + // Store into context, releasing any previous state. + // + Ctx = (DH_PKEY_CTX *)DhContext; + + if (Ctx->BnP != NULL) { + BN_free (Ctx->BnP); + } + + if (Ctx->BnG != NULL) { + BN_free (Ctx->BnG); + } + + if (Ctx->Pkey != NULL) { + EVP_PKEY_free (Ctx->Pkey); + Ctx->Pkey = NULL; + } + + Ctx->BnP = BnP; + Ctx->BnG = BnG; + + // MU_CHANGE [END] return TRUE; Error: @@ -204,10 +367,25 @@ DhGenerateKey ( IN OUT UINTN *PublicKeySize ) { - BOOLEAN RetVal; - DH *Dh; - BIGNUM *DhPubKey; - INTN Size; + // MU_CHANGE [BEGIN] + BOOLEAN RetVal; + DH_PKEY_CTX *Ctx; + OSSL_PARAM_BLD *Bld; + OSSL_PARAM *Params; + EVP_PKEY_CTX *ParamCtx; + EVP_PKEY *DhParamsPkey; + EVP_PKEY_CTX *KeygenCtx; + BIGNUM *BnPubKey; + INTN Size; + + RetVal = FALSE; + Bld = NULL; + Params = NULL; + ParamCtx = NULL; + DhParamsPkey = NULL; + KeygenCtx = NULL; + BnPubKey = NULL; + // MU_CHANGE [END] // // Check input parameters. @@ -220,22 +398,132 @@ DhGenerateKey ( return FALSE; } - Dh = (DH *)DhContext; + // MU_CHANGE [BEGIN] + Ctx = (DH_PKEY_CTX *)DhContext; - RetVal = (BOOLEAN)DH_generate_key (DhContext); - if (RetVal) { - DH_get0_key (Dh, (const BIGNUM **)&DhPubKey, NULL); - Size = BN_num_bytes (DhPubKey); - if ((Size > 0) && (*PublicKeySize < (UINTN)Size)) { - *PublicKeySize = Size; - return FALSE; - } + if ((Ctx->BnP == NULL) || (Ctx->BnG == NULL)) { + return FALSE; + } - if (PublicKey != NULL) { - BN_bn2bin (DhPubKey, PublicKey); - } + // + // Release any previously generated key. + // + if (Ctx->Pkey != NULL) { + EVP_PKEY_free (Ctx->Pkey); + Ctx->Pkey = NULL; + } + // + // Build an EVP_PKEY carrying only the DH domain parameters (p, g). + // + Bld = OSSL_PARAM_BLD_new (); + if (Bld == NULL) { + goto Fail; + } + + if (!OSSL_PARAM_BLD_push_BN (Bld, OSSL_PKEY_PARAM_FFC_P, Ctx->BnP)) { + goto Fail; + } + + if (!OSSL_PARAM_BLD_push_BN (Bld, OSSL_PKEY_PARAM_FFC_G, Ctx->BnG)) { + goto Fail; + } + + Params = OSSL_PARAM_BLD_to_param (Bld); + if (Params == NULL) { + goto Fail; + } + + ParamCtx = EVP_PKEY_CTX_new_from_name (NULL, "DH", NULL); + if (ParamCtx == NULL) { + goto Fail; + } + + if (EVP_PKEY_fromdata_init (ParamCtx) <= 0) { + goto Fail; + } + + if (EVP_PKEY_fromdata (ParamCtx, &DhParamsPkey, EVP_PKEY_KEY_PARAMETERS, Params) <= 0) { + goto Fail; + } + + // MU_CHANGE [END] + + // MU_CHANGE [BEGIN] + // + // Generate the DH key pair from the domain parameters. + // + KeygenCtx = EVP_PKEY_CTX_new (DhParamsPkey, NULL); + if (KeygenCtx == NULL) { + goto Fail; + } + + // MU_CHANGE [END] + + // MU_CHANGE [BEGIN] + if (EVP_PKEY_keygen_init (KeygenCtx) <= 0) { + goto Fail; + } + + // MU_CHANGE [END] + + // MU_CHANGE [BEGIN] + if (EVP_PKEY_keygen (KeygenCtx, &Ctx->Pkey) <= 0) { + goto Fail; + } + + // + // Extract the public key as a BIGNUM. + // + if (EVP_PKEY_get_bn_param (Ctx->Pkey, OSSL_PKEY_PARAM_PUB_KEY, &BnPubKey) <= 0) { + goto Fail; + } + + Size = BN_num_bytes (BnPubKey); + if ((Size > 0) && (*PublicKeySize < (UINTN)Size)) { + // MU_CHANGE [END] *PublicKeySize = Size; + // MU_CHANGE [BEGIN] + // + // Keep Ctx->Pkey; caller may retry with a larger buffer, but free the + // temporary BnPubKey extracted for this attempt to avoid leaking it. + // + BN_free (BnPubKey); + BnPubKey = NULL; + goto Fail; + } + + if (PublicKey != NULL) { + BN_bn2bin (BnPubKey, PublicKey); + } + + *PublicKeySize = Size; + RetVal = TRUE; + +Fail: + if (BnPubKey != NULL) { + BN_free (BnPubKey); + } + + if (KeygenCtx != NULL) { + EVP_PKEY_CTX_free (KeygenCtx); + } + + if (DhParamsPkey != NULL) { + EVP_PKEY_free (DhParamsPkey); + } + + if (ParamCtx != NULL) { + EVP_PKEY_CTX_free (ParamCtx); + } + + if (Params != NULL) { + OSSL_PARAM_free (Params); + } + + if (Bld != NULL) { + OSSL_PARAM_BLD_free (Bld); + // MU_CHANGE [END] } return RetVal; @@ -275,8 +563,25 @@ DhComputeKey ( IN OUT UINTN *KeySize ) { - BIGNUM *Bn; - INTN Size; + // MU_CHANGE [BEGIN] + BOOLEAN RetVal; + DH_PKEY_CTX *Ctx; + BIGNUM *BnPeerPubKey; + OSSL_PARAM_BLD *Bld; + OSSL_PARAM *Params; + EVP_PKEY_CTX *FromdataCtx; + EVP_PKEY *PeerPkey; + EVP_PKEY_CTX *DeriveCtx; + UINTN SharedKeyLen; + + RetVal = FALSE; + BnPeerPubKey = NULL; + Bld = NULL; + Params = NULL; + FromdataCtx = NULL; + PeerPkey = NULL; + DeriveCtx = NULL; + // MU_CHANGE [END] // // Check input parameters. @@ -289,24 +594,133 @@ DhComputeKey ( return FALSE; } - Bn = BN_bin2bn (PeerPublicKey, (UINT32)PeerPublicKeySize, NULL); - if (Bn == NULL) { + // MU_CHANGE [BEGIN] + Ctx = (DH_PKEY_CTX *)DhContext; + + if ((Ctx->Pkey == NULL) || (Ctx->BnP == NULL) || (Ctx->BnG == NULL)) { + // MU_CHANGE [END] return FALSE; } - Size = DH_compute_key (Key, Bn, DhContext); - if (Size < 0) { - BN_free (Bn); - return FALSE; + // MU_CHANGE [BEGIN] + // + // Convert peer's public key bytes to BIGNUM. + // + BnPeerPubKey = BN_bin2bn ((const unsigned char *)PeerPublicKey, (INT32)PeerPublicKeySize, NULL); + if (BnPeerPubKey == NULL) { + goto Fail; + // MU_CHANGE [END] } - if (*KeySize < (UINTN)Size) { - *KeySize = Size; - BN_free (Bn); - return FALSE; + // MU_CHANGE [BEGIN] + // + // Build a peer EVP_PKEY with p, g, and the peer's public key. + // + Bld = OSSL_PARAM_BLD_new (); + if (Bld == NULL) { + goto Fail; + // MU_CHANGE [END] } - *KeySize = Size; - BN_free (Bn); - return TRUE; + // MU_CHANGE [BEGIN] + if (!OSSL_PARAM_BLD_push_BN (Bld, OSSL_PKEY_PARAM_FFC_P, Ctx->BnP)) { + goto Fail; + } + + if (!OSSL_PARAM_BLD_push_BN (Bld, OSSL_PKEY_PARAM_FFC_G, Ctx->BnG)) { + goto Fail; + } + + if (!OSSL_PARAM_BLD_push_BN (Bld, OSSL_PKEY_PARAM_PUB_KEY, BnPeerPubKey)) { + goto Fail; + } + + Params = OSSL_PARAM_BLD_to_param (Bld); + if (Params == NULL) { + goto Fail; + } + + FromdataCtx = EVP_PKEY_CTX_new_from_name (NULL, "DH", NULL); + if (FromdataCtx == NULL) { + goto Fail; + } + + if (EVP_PKEY_fromdata_init (FromdataCtx) <= 0) { + goto Fail; + } + + if (EVP_PKEY_fromdata (FromdataCtx, &PeerPkey, EVP_PKEY_PUBLIC_KEY, Params) <= 0) { + goto Fail; + } + + // + // Derive the shared secret. + // + DeriveCtx = EVP_PKEY_CTX_new (Ctx->Pkey, NULL); + if (DeriveCtx == NULL) { + goto Fail; + } + + if (EVP_PKEY_derive_init (DeriveCtx) <= 0) { + goto Fail; + } + + if (EVP_PKEY_derive_set_peer (DeriveCtx, PeerPkey) <= 0) { + goto Fail; + } + + // + // First, query the required shared key length. + // + SharedKeyLen = 0; + if (EVP_PKEY_derive (DeriveCtx, NULL, &SharedKeyLen) <= 0) { + goto Fail; + } + + // + // If the caller-provided buffer is too small, report the required size + // while returning FALSE, preserving the previous behavior. + // + if (*KeySize < SharedKeyLen) { + *KeySize = SharedKeyLen; + goto Fail; + } + + // + // Derive the shared key into the caller-provided buffer. + // + if (EVP_PKEY_derive (DeriveCtx, Key, &SharedKeyLen) <= 0) { + goto Fail; + } + + *KeySize = SharedKeyLen; + RetVal = TRUE; + +Fail: + if (DeriveCtx != NULL) { + EVP_PKEY_CTX_free (DeriveCtx); + } + + if (PeerPkey != NULL) { + EVP_PKEY_free (PeerPkey); + } + + if (FromdataCtx != NULL) { + EVP_PKEY_CTX_free (FromdataCtx); + } + + if (Params != NULL) { + OSSL_PARAM_free (Params); + } + + if (Bld != NULL) { + OSSL_PARAM_BLD_free (Bld); + } + + if (BnPeerPubKey != NULL) { + BN_free (BnPeerPubKey); + } + + return RetVal; + // MU_CHANGE [END] } From de97401c2721afe0792faf12c4d7cfaec6755f96 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:19:26 -0700 Subject: [PATCH 6/9] OpensslPkg: Migrate CryptX509 to EVP_PKEY APIs Signed-off-by: Doug Flick --- .../Library/BaseCryptLib/Pk/CryptX509.c | 85 ++++++++++++++++--- 1 file changed, 75 insertions(+), 10 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptX509.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptX509.c index 25b7882a4..64e6f87f2 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptX509.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptX509.c @@ -12,6 +12,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +// MU_CHANGE [BEGIN] +#include "Pk/CryptRsaPkeyCtx.h" +#include "Pk/CryptEcPkeyCtx.h" +#include +#include +// MU_CHANGE [END] /* OID*/ #define OID_EXT_KEY_USAGE { 0x55, 0x1D, 0x25 } @@ -591,9 +597,13 @@ RsaGetPublicKeyFromX509 ( OUT VOID **RsaContext ) { - BOOLEAN Status; - EVP_PKEY *Pkey; - X509 *X509Cert; + // MU_CHANGE [BEGIN] + BOOLEAN Status; + EVP_PKEY *Pkey; + X509 *X509Cert; + RSA_PKEY_CTX *RsaPkeyCtx; + + // MU_CHANGE [END] // // Check input parameters. @@ -627,8 +637,22 @@ RsaGetPublicKeyFromX509 ( // // Duplicate RSA Context from the retrieved EVP_PKEY. // - if ((*RsaContext = RSAPublicKey_dup (EVP_PKEY_get0_RSA (Pkey))) != NULL) { - Status = TRUE; + // MU_CHANGE [BEGIN] + RsaPkeyCtx = AllocateZeroPool (sizeof (RSA_PKEY_CTX)); + if (RsaPkeyCtx != NULL) { + RsaPkeyCtx->Pkey = EVP_PKEY_dup (Pkey); + if ((RsaPkeyCtx->Pkey != NULL) && RsaExtractBigNums (RsaPkeyCtx, RsaPkeyCtx->Pkey)) { + *RsaContext = (VOID *)RsaPkeyCtx; + Status = TRUE; + } else { + if (RsaPkeyCtx->Pkey != NULL) { + EVP_PKEY_free (RsaPkeyCtx->Pkey); + } + + FreePool (RsaPkeyCtx); + } + + // MU_CHANGE [END] } _Exit: @@ -891,9 +915,16 @@ EcGetPublicKeyFromX509 ( OUT VOID **EcContext ) { - BOOLEAN Status; - EVP_PKEY *Pkey; - X509 *X509Cert; + // MU_CHANGE [BEGIN] + BOOLEAN Status; + EVP_PKEY *Pkey; + X509 *X509Cert; + EC_PKEY_CTX *EcPkeyCtx; + CHAR8 CurveNameBuf[64]; + UINTN CurveNameLen; + INT32 OpenSslNid; + + // MU_CHANGE [END] // // Check input parameters. @@ -927,8 +958,42 @@ EcGetPublicKeyFromX509 ( // // Duplicate EC Context from the retrieved EVP_PKEY. // - if ((*EcContext = EC_KEY_dup (EVP_PKEY_get0_EC_KEY (Pkey))) != NULL) { - Status = TRUE; + // MU_CHANGE [BEGIN] + EcPkeyCtx = AllocateZeroPool (sizeof (EC_PKEY_CTX)); + CurveNameLen = sizeof (CurveNameBuf); + if ((EcPkeyCtx != NULL) && + (EVP_PKEY_get_utf8_string_param ( + Pkey, + OSSL_PKEY_PARAM_GROUP_NAME, + CurveNameBuf, + CurveNameLen, + &CurveNameLen + ) == 1)) + { + OpenSslNid = OBJ_sn2nid (CurveNameBuf); + if (OpenSslNid == NID_undef) { + OpenSslNid = OBJ_ln2nid (CurveNameBuf); + } + + if (OpenSslNid == NID_undef) { + // + // Unknown/unsupported curve name: treat as error. + // + FreePool (EcPkeyCtx); + EcPkeyCtx = NULL; + } else { + EcPkeyCtx->Nid = OpenSslNid; + EcPkeyCtx->Pkey = EVP_PKEY_dup (Pkey); + if (EcPkeyCtx->Pkey != NULL) { + *EcContext = (VOID *)EcPkeyCtx; + Status = TRUE; + } else { + FreePool (EcPkeyCtx); + } + } + } else if (EcPkeyCtx != NULL) { + FreePool (EcPkeyCtx); + // MU_CHANGE [END] } _Exit: From 5708763fafa4b67c34a43eca31976553e9383e59 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Sat, 21 Mar 2026 21:19:32 -0700 Subject: [PATCH 7/9] OpensslPkg: Migrate CryptPem to EVP_PKEY APIs Signed-off-by: Doug Flick --- .../Library/BaseCryptLib/Pem/CryptPem.c | 107 ++++++++++++++++-- 1 file changed, 97 insertions(+), 10 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/Pem/CryptPem.c b/OpensslPkg/Library/BaseCryptLib/Pem/CryptPem.c index d64cf3d68..4d6050177 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pem/CryptPem.c +++ b/OpensslPkg/Library/BaseCryptLib/Pem/CryptPem.c @@ -8,6 +8,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "InternalCryptLib.h" #include +// MU_CHANGE [BEGIN] +#include +#include +#include +#include "Pk/CryptRsaPkeyCtx.h" +#include "Pk/CryptEcPkeyCtx.h" +// MU_CHANGE [END] /** Callback function for password phrase conversion used for retrieving the encrypted PEM. @@ -70,8 +77,13 @@ RsaGetPrivateKeyFromPem ( OUT VOID **RsaContext ) { - BOOLEAN Status; - BIO *PemBio; + // MU_CHANGE [BEGIN] + BOOLEAN Status; + BIO *PemBio; + EVP_PKEY *Pkey; + RSA_PKEY_CTX *RsaPkeyCtx; + + // MU_CHANGE [END] // // Check input parameters. @@ -97,6 +109,7 @@ RsaGetPrivateKeyFromPem ( } Status = FALSE; + Pkey = NULL; // MU_CHANGE // // Read encrypted PEM Data. @@ -113,15 +126,37 @@ RsaGetPrivateKeyFromPem ( // // Retrieve RSA Private Key from encrypted PEM data. // - *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password); - if (*RsaContext != NULL) { - Status = TRUE; + // MU_CHANGE [BEGIN] + Pkey = PEM_read_bio_PrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password); + if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_RSA)) { + goto _Exit; + } + + RsaPkeyCtx = AllocateZeroPool (sizeof (RSA_PKEY_CTX)); + if (RsaPkeyCtx != NULL) { + RsaPkeyCtx->Pkey = Pkey; + if (RsaExtractBigNums (RsaPkeyCtx, RsaPkeyCtx->Pkey)) { + Pkey = NULL; + *RsaContext = (VOID *)RsaPkeyCtx; + Status = TRUE; + } else { + RsaFree ((VOID *)RsaPkeyCtx); + Pkey = NULL; + } + + // MU_CHANGE [END] } _Exit: // // Release Resources. // + // MU_CHANGE [BEGIN] + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); + } + + // MU_CHANGE [END] BIO_free (PemBio); return Status; @@ -153,8 +188,16 @@ EcGetPrivateKeyFromPem ( OUT VOID **EcContext ) { - BOOLEAN Status; - BIO *PemBio; + // MU_CHANGE [BEGIN] + BOOLEAN Status; + BIO *PemBio; + EVP_PKEY *Pkey; + EC_PKEY_CTX *EcPkeyCtx; + CHAR8 CurveNameBuf[64]; + UINTN CurveNameLen; + INT32 OpenSslNid; + + // MU_CHANGE [END] // // Check input parameters. @@ -180,6 +223,7 @@ EcGetPrivateKeyFromPem ( } Status = FALSE; + Pkey = NULL; // MU_CHANGE // // Read encrypted PEM Data. @@ -196,15 +240,58 @@ EcGetPrivateKeyFromPem ( // // Retrieve EC Private Key from encrypted PEM data. // - *EcContext = PEM_read_bio_ECPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password); - if (*EcContext != NULL) { - Status = TRUE; + // MU_CHANGE [BEGIN] + Pkey = PEM_read_bio_PrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password); + if ((Pkey == NULL) || (EVP_PKEY_id (Pkey) != EVP_PKEY_EC)) { + goto _Exit; + } + + CurveNameLen = sizeof (CurveNameBuf); + if (EVP_PKEY_get_utf8_string_param ( + Pkey, + OSSL_PKEY_PARAM_GROUP_NAME, + CurveNameBuf, + CurveNameLen, + &CurveNameLen + ) != 1) + { + goto _Exit; + } + + // + // Convert OpenSSL curve group name to an internal NID. + // Try short-name lookup first (for example, "prime256v1"), then + // fall back to long-name lookup if the short name is not recognized. + // + OpenSslNid = OBJ_sn2nid (CurveNameBuf); + if (OpenSslNid == NID_undef) { + OpenSslNid = OBJ_ln2nid (CurveNameBuf); + } + + if (OpenSslNid == NID_undef) { + goto _Exit; + } + + EcPkeyCtx = AllocateZeroPool (sizeof (EC_PKEY_CTX)); + if (EcPkeyCtx != NULL) { + EcPkeyCtx->Nid = OpenSslNid; + EcPkeyCtx->Pkey = Pkey; + Pkey = NULL; + *EcContext = (VOID *)EcPkeyCtx; + Status = TRUE; + // MU_CHANGE [END] } _Exit: // // Release Resources. // + // MU_CHANGE [BEGIN] + if (Pkey != NULL) { + EVP_PKEY_free (Pkey); + } + + // MU_CHANGE [END] BIO_free (PemBio); return Status; From 85d1393e92301111aee6e34ef7e8c73f6af54315 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Mon, 30 Mar 2026 22:35:00 -0700 Subject: [PATCH 8/9] OpensslPkg: Remove OPENSSL_NO_DEPRECATED override All BaseCryptLib files now use OpenSSL 3.x non-deprecated EVP_PKEY provider APIs. Remove the OPENSSL_NO_DEPRECATED=0 override from InternalCryptLib.h that was previously required to suppress deprecation warnings. Signed-off-by: Doug Flick --- OpensslPkg/Library/BaseCryptLib/InternalCryptLib.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/InternalCryptLib.h b/OpensslPkg/Library/BaseCryptLib/InternalCryptLib.h index cbb3378cd..461858a01 100644 --- a/OpensslPkg/Library/BaseCryptLib/InternalCryptLib.h +++ b/OpensslPkg/Library/BaseCryptLib/InternalCryptLib.h @@ -20,10 +20,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "CrtLibSupport.h" +// MU_CHANGE [BEGIN] // TODO: remove in near future to stop using deprecated OpenSSL APIs -#undef OPENSSL_NO_DEPRECATED // MU_CHANGE -#define OPENSSL_NO_DEPRECATED 0 - +// #define OPENSSL_NO_DEPRECATED 0 +// MU_CHANGE [END] #include #if OPENSSL_VERSION_NUMBER < 0x10100000L From 30dadde565fdfa70daf0dfdb459c289bda30ab85 Mon Sep 17 00:00:00 2001 From: Doug Flick Date: Tue, 24 Mar 2026 20:53:13 +0000 Subject: [PATCH 9/9] OpensslPkg: Fix memory leak in RsaExtractBigNums - RsaExtractBigNums now cleans up partially extracted BIGNUMs on failure instead of leaving them dangling in the RSA_PKEY_CTX. - RsaGetPublicKeyFromX509 error path uses RsaFree() for proper cleanup of all RSA_PKEY_CTX resources. - Fix RsaGetKey doc comment: BigNumber=NULL with sufficient BnSize returns TRUE (size query), not FALSE. Signed-off-by: Doug Flick --- .../Library/BaseCryptLib/Pk/CryptRsaBasic.c | 59 +++++++++++++++---- .../Library/BaseCryptLib/Pk/CryptRsaExt.c | 39 ++++++++---- 2 files changed, 74 insertions(+), 24 deletions(-) diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c index a4c001da2..0b7d820e2 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaBasic.c @@ -216,11 +216,11 @@ RsaExtractBigNums ( // Extract public components (required). // if (EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_N, &RsaPkeyCtx->N) != 1) { - return FALSE; + goto Fail; // MU_CHANGE } if (EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_E, &RsaPkeyCtx->E) != 1) { - return FALSE; + goto Fail; // MU_CHANGE } // @@ -234,6 +234,30 @@ RsaExtractBigNums ( EVP_PKEY_get_bn_param (Pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1, &RsaPkeyCtx->QInv); return TRUE; + // MU_CHANGE [BEGIN] + +Fail: + // + // Clean up any partially extracted BIGNUMs on failure. + // + BN_free (RsaPkeyCtx->N); + BN_free (RsaPkeyCtx->E); + BN_clear_free (RsaPkeyCtx->D); + BN_clear_free (RsaPkeyCtx->P); + BN_clear_free (RsaPkeyCtx->Q); + BN_clear_free (RsaPkeyCtx->Dp); + BN_clear_free (RsaPkeyCtx->Dq); + BN_clear_free (RsaPkeyCtx->QInv); + RsaPkeyCtx->N = NULL; + RsaPkeyCtx->E = NULL; + RsaPkeyCtx->D = NULL; + RsaPkeyCtx->P = NULL; + RsaPkeyCtx->Q = NULL; + RsaPkeyCtx->Dp = NULL; + RsaPkeyCtx->Dq = NULL; + RsaPkeyCtx->QInv = NULL; + return FALSE; + // MU_CHANGE [END] } /** @@ -266,6 +290,7 @@ GetEvpMdFromHashSize ( return NULL; } } + // MU_CHANGE [END] /** @@ -397,12 +422,12 @@ RsaSetKey ( // MU_CHANGE [BEGIN] BnTarget = &RsaPkeyCtx->N; break; - // MU_CHANGE [END] + // MU_CHANGE [END] case RsaKeyE: // MU_CHANGE [BEGIN] BnTarget = &RsaPkeyCtx->E; break; - // MU_CHANGE [END] + // MU_CHANGE [END] case RsaKeyD: BnTarget = &RsaPkeyCtx->D; // MU_CHANGE break; @@ -410,7 +435,7 @@ RsaSetKey ( // MU_CHANGE [BEGIN] BnTarget = &RsaPkeyCtx->P; break; - // MU_CHANGE [END] + // MU_CHANGE [END] case RsaKeyQ: BnTarget = &RsaPkeyCtx->Q; // MU_CHANGE break; @@ -418,12 +443,12 @@ RsaSetKey ( // MU_CHANGE [BEGIN] BnTarget = &RsaPkeyCtx->Dp; break; - // MU_CHANGE [END] + // MU_CHANGE [END] case RsaKeyDq: // MU_CHANGE [BEGIN] BnTarget = &RsaPkeyCtx->Dq; break; - // MU_CHANGE [END] + // MU_CHANGE [END] case RsaKeyQInv: // MU_CHANGE [BEGIN] BnTarget = &RsaPkeyCtx->QInv; @@ -431,7 +456,8 @@ RsaSetKey ( default: return FALSE; } - // MU_CHANGE [END] + + // MU_CHANGE [END] // MU_CHANGE [BEGIN] // @@ -443,18 +469,20 @@ RsaSetKey ( BN_free (*BnTarget); } else { BN_clear_free (*BnTarget); - // MU_CHANGE [END] + // MU_CHANGE [END] } // MU_CHANGE [BEGIN] *BnTarget = NULL; } - // MU_CHANGE [END] + + // MU_CHANGE [END] // MU_CHANGE [BEGIN] return TRUE; } - // MU_CHANGE [END] + + // MU_CHANGE [END] // MU_CHANGE [BEGIN] // @@ -463,7 +491,7 @@ RsaSetKey ( NewBn = BN_bin2bn (BigNumber, (UINT32)BnSize, *BnTarget); if (NewBn == NULL) { return FALSE; - // MU_CHANGE [END] + // MU_CHANGE [END] } *BnTarget = NewBn; @@ -506,6 +534,7 @@ RsaPkcs1Verify ( EVP_PKEY_CTX *PkeyCtx; CONST EVP_MD *Md; BOOLEAN Result; + // MU_CHANGE [END] // @@ -527,6 +556,7 @@ RsaPkcs1Verify ( if (Md == NULL) { return FALSE; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] @@ -543,6 +573,7 @@ RsaPkcs1Verify ( if (Pkey == NULL) { return FALSE; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] @@ -550,12 +581,14 @@ RsaPkcs1Verify ( if (PkeyCtx == NULL) { goto _Exit; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] if (EVP_PKEY_verify_init (PkeyCtx) != 1) { goto _Exit; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] @@ -574,7 +607,7 @@ RsaPkcs1Verify ( _Exit: if (PkeyCtx != NULL) { EVP_PKEY_CTX_free (PkeyCtx); - // MU_CHANGE [END] + // MU_CHANGE [END] } return Result; // MU_CHANGE diff --git a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c index 36c78516a..8511334b6 100644 --- a/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c +++ b/OpensslPkg/Library/BaseCryptLib/Pk/CryptRsaExt.c @@ -61,6 +61,7 @@ GetEvpMdFromHashSize ( return NULL; } } + // MU_CHANGE [END] /** @@ -76,7 +77,10 @@ GetEvpMdFromHashSize ( If RsaContext is NULL, then return FALSE. If BnSize is NULL, then return FALSE. - If BnSize is large enough but BigNumber is NULL, then return FALSE. + // MU_CHANGE [BEGIN] + If BnSize is large enough but BigNumber is NULL, then return TRUE with BnSize set to + the required size. + // MU_CHANGE [END] @param[in, out] RsaContext Pointer to RSA context being set. @param[in] KeyTag Tag of RSA key component being set. @@ -102,6 +106,7 @@ RsaGetKey ( RSA_PKEY_CTX *RsaPkeyCtx; BIGNUM *BnKey; UINTN Size; + // MU_CHANGE [END] // @@ -240,6 +245,7 @@ RsaGenerateKey ( EVP_PKEY *Pkey; BIGNUM *KeyE; BOOLEAN RetVal; + // MU_CHANGE [END] // @@ -263,7 +269,7 @@ RsaGenerateKey ( KeyGenCtx = EVP_PKEY_CTX_new_from_name (NULL, "RSA", NULL); if (KeyGenCtx == NULL) { - // MU_CHANGE [END] + // MU_CHANGE [END] return FALSE; } @@ -275,6 +281,7 @@ RsaGenerateKey ( if (EVP_PKEY_CTX_set_rsa_keygen_bits (KeyGenCtx, (INT32)ModulusLength) != 1) { goto _Exit; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] @@ -284,25 +291,28 @@ RsaGenerateKey ( if (PublicExponent != NULL) { KeyE = BN_new (); if (KeyE == NULL) { - // MU_CHANGE [END] + // MU_CHANGE [END] goto _Exit; } - // MU_CHANGE + + // MU_CHANGE if (BN_bin2bn (PublicExponent, (UINT32)PublicExponentSize, KeyE) == NULL) { goto _Exit; } -// MU_CHANGE [BEGIN] + + // MU_CHANGE [BEGIN] if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp (KeyGenCtx, KeyE) != 1) { goto _Exit; } -// MU_CHANGE [END] + + // MU_CHANGE [END] } // MU_CHANGE [BEGIN] if (EVP_PKEY_keygen (KeyGenCtx, &Pkey) != 1) { goto _Exit; - // MU_CHANGE [END] + // MU_CHANGE [END] } // MU_CHANGE [BEGIN] @@ -365,6 +375,7 @@ RsaCheckKey ( EVP_PKEY *Pkey; EVP_PKEY_CTX *PkeyCtx; INT32 Result; + // MU_CHANGE [END] // @@ -397,7 +408,7 @@ RsaCheckKey ( if (Result != 1) { return FALSE; - // MU_CHANGE [END] + // MU_CHANGE [END] } return TRUE; @@ -445,6 +456,7 @@ RsaPkcs1Sign ( CONST EVP_MD *Md; UINTN RequiredSize; BOOLEAN Result; + // MU_CHANGE [END] // @@ -460,7 +472,7 @@ RsaPkcs1Sign ( // Md = GetEvpMdFromHashSize (HashSize); if (Md == NULL) { - // MU_CHANGE [END] + // MU_CHANGE [END] return FALSE; } @@ -474,7 +486,7 @@ RsaPkcs1Sign ( // Pkey = RsaBuildEvpPkey (RsaPkeyCtx); if (Pkey == NULL) { - // MU_CHANGE [END] + // MU_CHANGE [END] return FALSE; } @@ -487,12 +499,14 @@ RsaPkcs1Sign ( *SigSize = RequiredSize; return FALSE; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] if (Signature == NULL) { return FALSE; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] @@ -500,18 +514,21 @@ RsaPkcs1Sign ( if (PkeyCtx == NULL) { goto _Exit; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] if (EVP_PKEY_sign_init (PkeyCtx) != 1) { goto _Exit; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] if (EVP_PKEY_CTX_set_rsa_padding (PkeyCtx, RSA_PKCS1_PADDING) <= 0) { goto _Exit; } + // MU_CHANGE [END] // MU_CHANGE [BEGIN] @@ -527,7 +544,7 @@ RsaPkcs1Sign ( _Exit: if (PkeyCtx != NULL) { EVP_PKEY_CTX_free (PkeyCtx); - // MU_CHANGE [END] + // MU_CHANGE [END] } return Result; // MU_CHANGE