public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sheng Wei" <w.sheng@intel.com>
To: devel@edk2.groups.io
Cc: Jiewen Yao <jiewen.yao@intel.com>,
	Jian J Wang <jian.j.wang@intel.com>, Min Xu <min.m.xu@intel.com>,
	Zeyi Chen <zeyi.chen@intel.com>,
	Fiona Wang <fiona.wang@intel.com>
Subject: [edk2-devel] [PATCH V8 2/2] SecurityPkg/SecureBoot: Support RSA4096 and RSA3072
Date: Wed,  6 Sep 2023 16:16:26 +0800	[thread overview]
Message-ID: <20230906081626.1871-3-w.sheng@intel.com> (raw)
In-Reply-To: <20230906081626.1871-1-w.sheng@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3413

Change-Id: Ic13595ffb0581a178db71d231ba34f17862fa5d8
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Zeyi Chen <zeyi.chen@intel.com>
Cc: Fiona Wang <fiona.wang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Library/AuthVariableLib/AuthService.c     | 225 +++++++++++++++---
 .../AuthVariableLib/AuthServiceInternal.h     |   4 +-
 .../Library/AuthVariableLib/AuthVariableLib.c |  42 ++--
 .../DxeImageVerificationLib.c                 |  74 +++---
 .../SecureBootConfigDxe.inf                   |   8 +
 .../SecureBootConfigImpl.c                    |  52 +++-
 .../SecureBootConfigImpl.h                    |   7 +
 .../SecureBootConfigStrings.uni               |   2 +
 8 files changed, 329 insertions(+), 85 deletions(-)

diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c
index d81c581d78..aec0fad28a 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthService.c
+++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c
@@ -29,12 +29,125 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/VariablePolicy.h>
 #include <Library/VariablePolicyLib.h>
 
+#define SHA_DIGEST_SIZE_MAX  SHA512_DIGEST_SIZE
+
+/**
+  Retrieves the size, in bytes, of the context buffer required for hash operations.
+
+  If this interface is not supported, then return zero.
+
+  @return  The size, in bytes, of the context buffer required for hash operations.
+  @retval  0   This interface is not supported.
+
+**/
+typedef
+UINTN
+(EFIAPI *EFI_HASH_GET_CONTEXT_SIZE)(
+  VOID
+  );
+
+/**
+  Initializes user-supplied memory pointed by Sha1Context as hash context for
+  subsequent use.
+
+  If HashContext is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[out]  HashContext  Pointer to Hashcontext being initialized.
+
+  @retval TRUE   Hash context initialization succeeded.
+  @retval FALSE  Hash context initialization failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_INIT)(
+  OUT  VOID  *HashContext
+  );
+
+/**
+  Digests the input data and updates Hash context.
+
+  This function performs Hash digest on a data buffer of the specified size.
+  It can be called multiple times to compute the digest of long or discontinuous data streams.
+  Hash context should be already correctly initialized by HashInit(), and should not be finalized
+  by HashFinal(). Behavior with invalid context is undefined.
+
+  If HashContext is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in, out]  HashContext  Pointer to the Hash context.
+  @param[in]       Data         Pointer to the buffer containing the data to be hashed.
+  @param[in]       DataSize     Size of Data buffer in bytes.
+
+  @retval TRUE   SHA-1 data digest succeeded.
+  @retval FALSE  SHA-1 data digest failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_UPDATE)(
+  IN OUT  VOID        *HashContext,
+  IN      CONST VOID  *Data,
+  IN      UINTN       DataSize
+  );
+
+/**
+  Completes computation of the Hash digest value.
+
+  This function completes hash computation and retrieves the digest value into
+  the specified memory. After this function has been called, the Hash context cannot
+  be used again.
+  Hash context should be already correctly initialized by HashInit(), and should not be
+  finalized by HashFinal(). Behavior with invalid Hash context is undefined.
+
+  If HashContext is NULL, then return FALSE.
+  If HashValue is NULL, then return FALSE.
+  If this interface is not supported, then return FALSE.
+
+  @param[in, out]  HashContext  Pointer to the Hash context.
+  @param[out]      HashValue    Pointer to a buffer that receives the Hash digest
+                                value.
+
+  @retval TRUE   Hash digest computation succeeded.
+  @retval FALSE  Hash digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_FINAL)(
+  IN OUT  VOID   *HashContext,
+  OUT     UINT8  *HashValue
+  );
+
+typedef struct {
+  UINT32                       HashSize;
+  EFI_HASH_GET_CONTEXT_SIZE    GetContextSize;
+  EFI_HASH_INIT                Init;
+  EFI_HASH_UPDATE              Update;
+  EFI_HASH_FINAL               Final;
+  VOID                         **HashShaCtx;
+  UINT8                        *OidValue;
+  UINTN                        OidLength;
+} EFI_HASH_INFO;
+
 //
 // Public Exponent of RSA Key.
 //
 CONST UINT8  mRsaE[] = { 0x01, 0x00, 0x01 };
 
-CONST UINT8  mSha256OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 };
+UINT8  mSha256OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 };
+UINT8  mSha384OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02 };
+UINT8  mSha512OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03 };
+
+EFI_HASH_INFO  mHashInfo[] = {
+  { SHA256_DIGEST_SIZE, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final, &mHashSha256Ctx, mSha256OidValue, 9 },
+  { SHA384_DIGEST_SIZE, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final, &mHashSha384Ctx, mSha384OidValue, 9 },
+  { SHA512_DIGEST_SIZE, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final, &mHashSha512Ctx, mSha512OidValue, 9 },
+};
 
 //
 // Requirement for different signature type which have been defined in UEFI spec.
@@ -1090,26 +1203,28 @@ AuthServiceInternalCompareTimeStamp (
 }
 
 /**
-  Calculate SHA256 digest of SignerCert CommonName + ToplevelCert tbsCertificate
+  Calculate SHA digest of SignerCert CommonName + ToplevelCert tbsCertificate.
   SignerCert and ToplevelCert are inside the signer certificate chain.
 
+  @param[in]  HashAlgId           Hash algorithm index.
   @param[in]  SignerCert          A pointer to SignerCert data.
   @param[in]  SignerCertSize      Length of SignerCert data.
   @param[in]  TopLevelCert        A pointer to TopLevelCert data.
   @param[in]  TopLevelCertSize    Length of TopLevelCert data.
-  @param[out] Sha256Digest       Sha256 digest calculated.
+  @param[out] ShaDigest           Sha digest calculated.
 
   @return EFI_ABORTED          Digest process failed.
-  @return EFI_SUCCESS          SHA256 Digest is successfully calculated.
+  @return EFI_SUCCESS          SHA Digest is successfully calculated.
 
 **/
 EFI_STATUS
-CalculatePrivAuthVarSignChainSHA256Digest (
+CalculatePrivAuthVarSignChainSHADigest (
+  IN     UINT8  HashAlgId,
   IN     UINT8  *SignerCert,
   IN     UINTN  SignerCertSize,
   IN     UINT8  *TopLevelCert,
   IN     UINTN  TopLevelCertSize,
-  OUT    UINT8  *Sha256Digest
+  OUT    UINT8  *ShaDigest
   )
 {
   UINT8       *TbsCert;
@@ -1119,6 +1234,11 @@ CalculatePrivAuthVarSignChainSHA256Digest (
   BOOLEAN     CryptoStatus;
   EFI_STATUS  Status;
 
+  if (HashAlgId >= (sizeof (mHashInfo) / sizeof (EFI_HASH_INFO))) {
+    DEBUG ((DEBUG_INFO, "%a Unsupported Hash Algorithm %d\n", __func__, HashAlgId));
+    return EFI_ABORTED;
+  }
+
   CertCommonNameSize = sizeof (CertCommonName);
 
   //
@@ -1141,8 +1261,8 @@ CalculatePrivAuthVarSignChainSHA256Digest (
   //
   // Digest SignerCert CN + TopLevelCert tbsCertificate
   //
-  ZeroMem (Sha256Digest, SHA256_DIGEST_SIZE);
-  CryptoStatus = Sha256Init (mHashCtx);
+  ZeroMem (ShaDigest, mHashInfo[HashAlgId].HashSize);
+  CryptoStatus = mHashInfo[HashAlgId].Init (*(mHashInfo[HashAlgId].HashShaCtx));
   if (!CryptoStatus) {
     return EFI_ABORTED;
   }
@@ -1150,21 +1270,21 @@ CalculatePrivAuthVarSignChainSHA256Digest (
   //
   // '\0' is forced in CertCommonName. No overflow issue
   //
-  CryptoStatus = Sha256Update (
-                   mHashCtx,
-                   CertCommonName,
-                   AsciiStrLen (CertCommonName)
-                   );
+  CryptoStatus = mHashInfo[HashAlgId].Update (
+                                        *(mHashInfo[HashAlgId].HashShaCtx),
+                                        CertCommonName,
+                                        AsciiStrLen (CertCommonName)
+                                        );
   if (!CryptoStatus) {
     return EFI_ABORTED;
   }
 
-  CryptoStatus = Sha256Update (mHashCtx, TbsCert, TbsCertSize);
+  CryptoStatus = mHashInfo[HashAlgId].Update (*(mHashInfo[HashAlgId].HashShaCtx), TbsCert, TbsCertSize);
   if (!CryptoStatus) {
     return EFI_ABORTED;
   }
 
-  CryptoStatus = Sha256Final (mHashCtx, Sha256Digest);
+  CryptoStatus = mHashInfo[HashAlgId].Final (*(mHashInfo[HashAlgId].HashShaCtx), ShaDigest);
   if (!CryptoStatus) {
     return EFI_ABORTED;
   }
@@ -1516,9 +1636,10 @@ DeleteCertsFromDb (
 /**
   Insert signer's certificates for common authenticated variable with VariableName
   and VendorGuid in AUTH_CERT_DB_DATA to "certdb" or "certdbv" according to
-  time based authenticated variable attributes. CertData is the SHA256 digest of
+  time based authenticated variable attributes. CertData is the SHA digest of
   SignerCert CommonName + TopLevelCert tbsCertificate.
 
+  @param[in]  HashAlgId         Hash algorithm index.
   @param[in]  VariableName      Name of authenticated Variable.
   @param[in]  VendorGuid        Vendor GUID of authenticated Variable.
   @param[in]  Attributes        Attributes of authenticated variable.
@@ -1536,6 +1657,7 @@ DeleteCertsFromDb (
 **/
 EFI_STATUS
 InsertCertsToDb (
+  IN     UINT8     HashAlgId,
   IN     CHAR16    *VariableName,
   IN     EFI_GUID  *VendorGuid,
   IN     UINT32    Attributes,
@@ -1556,12 +1678,16 @@ InsertCertsToDb (
   UINT32             CertDataSize;
   AUTH_CERT_DB_DATA  *Ptr;
   CHAR16             *DbName;
-  UINT8              Sha256Digest[SHA256_DIGEST_SIZE];
+  UINT8              ShaDigest[SHA_DIGEST_SIZE_MAX];
 
   if ((VariableName == NULL) || (VendorGuid == NULL) || (SignerCert == NULL) || (TopLevelCert == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
+  if (HashAlgId >= (sizeof (mHashInfo) / sizeof (EFI_HASH_INFO))) {
+    return EFI_INVALID_PARAMETER;
+  }
+
   if ((Attributes & EFI_VARIABLE_NON_VOLATILE) != 0) {
     //
     // Get variable "certdb".
@@ -1618,20 +1744,22 @@ InsertCertsToDb (
   // Construct new data content of variable "certdb" or "certdbv".
   //
   NameSize      = (UINT32)StrLen (VariableName);
-  CertDataSize  = sizeof (Sha256Digest);
+  CertDataSize  = mHashInfo[HashAlgId].HashSize;
   CertNodeSize  = sizeof (AUTH_CERT_DB_DATA) + (UINT32)CertDataSize + NameSize * sizeof (CHAR16);
   NewCertDbSize = (UINT32)DataSize + CertNodeSize;
   if (NewCertDbSize > mMaxCertDbSize) {
     return EFI_OUT_OF_RESOURCES;
   }
 
-  Status = CalculatePrivAuthVarSignChainSHA256Digest (
+  Status = CalculatePrivAuthVarSignChainSHADigest (
+             HashAlgId,
              SignerCert,
              SignerCertSize,
              TopLevelCert,
              TopLevelCertSize,
-             Sha256Digest
+             ShaDigest
              );
+
   if (EFI_ERROR (Status)) {
     return Status;
   }
@@ -1663,7 +1791,7 @@ InsertCertsToDb (
 
   CopyMem (
     (UINT8 *)Ptr +  sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),
-    Sha256Digest,
+    ShaDigest,
     CertDataSize
     );
 
@@ -1790,6 +1918,37 @@ CleanCertsFromDb (
   return Status;
 }
 
+/**
+  Find hash algorithm index.
+
+  @param[in]  SigData      Pointer to the PKCS#7 message.
+  @param[in]  SigDataSize  Length of the PKCS#7 message.
+
+  @retval UINT8        Hash Algorithm Index.
+**/
+UINT8
+FindHashAlgorithmIndex (
+  IN     UINT8   *SigData,
+  IN     UINT32  SigDataSize
+  )
+{
+  UINT8  i;
+
+  for (i = 0; i < (sizeof (mHashInfo) / sizeof (EFI_HASH_INFO)); i++) {
+    if (  (  (SigDataSize >= (13 + mHashInfo[i].OidLength))
+          && (  ((*(SigData + 1) & TWO_BYTE_ENCODE) == TWO_BYTE_ENCODE)
+             && (CompareMem (SigData + 13, mHashInfo[i].OidValue, mHashInfo[i].OidLength) == 0)))
+       || ((  (SigDataSize >= (32 +  mHashInfo[i].OidLength)))
+          && (  ((*(SigData + 20) & TWO_BYTE_ENCODE) == TWO_BYTE_ENCODE)
+             && (CompareMem (SigData + 32, mHashInfo[i].OidValue, mHashInfo[i].OidLength) == 0))))
+    {
+      break;
+    }
+  }
+
+  return i;
+}
+
 /**
   Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set
 
@@ -1857,8 +2016,9 @@ VerifyTimeBasedPayload (
   UINTN                          CertStackSize;
   UINT8                          *CertsInCertDb;
   UINT32                         CertsSizeinDb;
-  UINT8                          Sha256Digest[SHA256_DIGEST_SIZE];
+  UINT8                          ShaDigest[SHA_DIGEST_SIZE_MAX];
   EFI_CERT_DATA                  *CertDataPtr;
+  UINT8                          HashAlgId;
 
   //
   // 1. TopLevelCert is the top-level issuer certificate in signature Signer Cert Chain
@@ -1928,7 +2088,7 @@ VerifyTimeBasedPayload (
 
   //
   // SignedData.digestAlgorithms shall contain the digest algorithm used when preparing the
-  // signature. Only a digest algorithm of SHA-256 is accepted.
+  // signature. Only a digest algorithm of SHA-256, SHA-384 or SHA-512 is accepted.
   //
   //    According to PKCS#7 Definition (https://www.rfc-editor.org/rfc/rfc2315):
   //        SignedData ::= SEQUENCE {
@@ -1972,14 +2132,9 @@ VerifyTimeBasedPayload (
   //
   // Example generated with: https://wiki.archlinux.org/title/Unified_Extensible_Firmware_Interface/Secure_Boot#Manual_process
   //
+  HashAlgId = FindHashAlgorithmIndex (SigData, SigDataSize);
   if ((Attributes & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
-    if (  (  (SigDataSize >= (13 + sizeof (mSha256OidValue)))
-          && (  ((*(SigData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE)
-             || (CompareMem (SigData + 13, &mSha256OidValue, sizeof (mSha256OidValue)) != 0)))
-       && (  (SigDataSize >= (32 + sizeof (mSha256OidValue)))
-          && (  ((*(SigData + 20) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE)
-             || (CompareMem (SigData + 32, &mSha256OidValue, sizeof (mSha256OidValue)) != 0))))
-    {
+    if (HashAlgId >= (sizeof (mHashInfo) / sizeof (EFI_HASH_INFO))) {
       return EFI_SECURITY_VIOLATION;
     }
   }
@@ -2170,19 +2325,20 @@ VerifyTimeBasedPayload (
         goto Exit;
       }
 
-      if (CertsSizeinDb == SHA256_DIGEST_SIZE) {
+      if ((HashAlgId < (sizeof (mHashInfo) / sizeof (EFI_HASH_INFO))) && (CertsSizeinDb == mHashInfo[HashAlgId].HashSize)) {
         //
         // Check hash of signer cert CommonName + Top-level issuer tbsCertificate against data in CertDb
         //
         CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1);
-        Status      = CalculatePrivAuthVarSignChainSHA256Digest (
+        Status      = CalculatePrivAuthVarSignChainSHADigest (
+                        HashAlgId,
                         CertDataPtr->CertDataBuffer,
                         ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)),
                         TopLevelCert,
                         TopLevelCertSize,
-                        Sha256Digest
+                        ShaDigest
                         );
-        if (EFI_ERROR (Status) || (CompareMem (Sha256Digest, CertsInCertDb, CertsSizeinDb) != 0)) {
+        if (EFI_ERROR (Status) || (CompareMem (ShaDigest, CertsInCertDb, CertsSizeinDb) != 0)) {
           goto Exit;
         }
       } else {
@@ -2215,6 +2371,7 @@ VerifyTimeBasedPayload (
       //
       CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1);
       Status      = InsertCertsToDb (
+                      HashAlgId,
                       VariableName,
                       VendorGuid,
                       Attributes,
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
index b202e613bc..f7bf771d55 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
+++ b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h
@@ -92,7 +92,9 @@ extern UINT32  mMaxCertDbSize;
 extern UINT32  mPlatformMode;
 extern UINT8   mVendorKeyState;
 
-extern VOID  *mHashCtx;
+extern VOID  *mHashSha256Ctx;
+extern VOID  *mHashSha384Ctx;
+extern VOID  *mHashSha512Ctx;
 
 extern AUTH_VAR_LIB_CONTEXT_IN  *mAuthVarLibContextIn;
 
diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
index dc61ae840c..dc11f38cb3 100644
--- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
+++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
@@ -26,12 +26,14 @@ UINT32  mMaxCertDbSize;
 UINT32  mPlatformMode;
 UINT8   mVendorKeyState;
 
-EFI_GUID  mSignatureSupport[] = { EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID };
+EFI_GUID  mSignatureSupport[] = { EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_SHA384_GUID, EFI_CERT_SHA512_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID };
 
 //
 // Hash context pointer
 //
-VOID  *mHashCtx = NULL;
+VOID  *mHashSha256Ctx = NULL;
+VOID  *mHashSha384Ctx = NULL;
+VOID  *mHashSha512Ctx = NULL;
 
 VARIABLE_ENTRY_PROPERTY  mAuthVarEntry[] = {
   {
@@ -91,7 +93,7 @@ VARIABLE_ENTRY_PROPERTY  mAuthVarEntry[] = {
   },
 };
 
-VOID  **mAuthVarAddressPointer[9];
+VOID  **mAuthVarAddressPointer[11];
 
 AUTH_VAR_LIB_CONTEXT_IN  *mAuthVarLibContextIn = NULL;
 
@@ -120,7 +122,6 @@ AuthVariableLibInitialize (
   UINT32      VarAttr;
   UINT8       *Data;
   UINTN       DataSize;
-  UINTN       CtxSize;
   UINT8       SecureBootMode;
   UINT8       SecureBootEnable;
   UINT8       CustomMode;
@@ -135,9 +136,18 @@ AuthVariableLibInitialize (
   //
   // Initialize hash context.
   //
-  CtxSize  = Sha256GetContextSize ();
-  mHashCtx = AllocateRuntimePool (CtxSize);
-  if (mHashCtx == NULL) {
+  mHashSha256Ctx = AllocateRuntimePool (Sha256GetContextSize ());
+  if (mHashSha256Ctx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  mHashSha384Ctx = AllocateRuntimePool (Sha384GetContextSize ());
+  if (mHashSha384Ctx == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  mHashSha512Ctx = AllocateRuntimePool (Sha512GetContextSize ());
+  if (mHashSha512Ctx == NULL) {
     return EFI_OUT_OF_RESOURCES;
   }
 
@@ -356,14 +366,16 @@ AuthVariableLibInitialize (
   AuthVarLibContextOut->AuthVarEntry        = mAuthVarEntry;
   AuthVarLibContextOut->AuthVarEntryCount   = ARRAY_SIZE (mAuthVarEntry);
   mAuthVarAddressPointer[0]                 = (VOID **)&mCertDbStore;
-  mAuthVarAddressPointer[1]                 = (VOID **)&mHashCtx;
-  mAuthVarAddressPointer[2]                 = (VOID **)&mAuthVarLibContextIn;
-  mAuthVarAddressPointer[3]                 = (VOID **)&(mAuthVarLibContextIn->FindVariable),
-  mAuthVarAddressPointer[4]                 = (VOID **)&(mAuthVarLibContextIn->FindNextVariable),
-  mAuthVarAddressPointer[5]                 = (VOID **)&(mAuthVarLibContextIn->UpdateVariable),
-  mAuthVarAddressPointer[6]                 = (VOID **)&(mAuthVarLibContextIn->GetScratchBuffer),
-  mAuthVarAddressPointer[7]                 = (VOID **)&(mAuthVarLibContextIn->CheckRemainingSpaceForConsistency),
-  mAuthVarAddressPointer[8]                 = (VOID **)&(mAuthVarLibContextIn->AtRuntime),
+  mAuthVarAddressPointer[1]                 = (VOID **)&mHashSha256Ctx;
+  mAuthVarAddressPointer[2]                 = (VOID **)&mHashSha384Ctx;
+  mAuthVarAddressPointer[3]                 = (VOID **)&mHashSha512Ctx;
+  mAuthVarAddressPointer[4]                 = (VOID **)&mAuthVarLibContextIn;
+  mAuthVarAddressPointer[5]                 = (VOID **)&(mAuthVarLibContextIn->FindVariable),
+  mAuthVarAddressPointer[6]                 = (VOID **)&(mAuthVarLibContextIn->FindNextVariable),
+  mAuthVarAddressPointer[7]                 = (VOID **)&(mAuthVarLibContextIn->UpdateVariable),
+  mAuthVarAddressPointer[8]                 = (VOID **)&(mAuthVarLibContextIn->GetScratchBuffer),
+  mAuthVarAddressPointer[9]                 = (VOID **)&(mAuthVarLibContextIn->CheckRemainingSpaceForConsistency),
+  mAuthVarAddressPointer[10]                = (VOID **)&(mAuthVarLibContextIn->AtRuntime),
   AuthVarLibContextOut->AddressPointer      = mAuthVarAddressPointer;
   AuthVarLibContextOut->AddressPointerCount = ARRAY_SIZE (mAuthVarAddressPointer);
 
diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index 5d8dbd5468..b05da19c2b 100644
--- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -1620,7 +1620,7 @@ Done:
       in the security database "db", and no valid signature nor any hash value of the image may
       be reflected in the security database "dbx".
     Otherwise, the image is not signed,
-      The SHA256 hash value of the image must match a record in the security database "db", and
+      The hash value of the image must match a record in the security database "db", and
       not be reflected in the security data base "dbx".
 
   Caution: This function may receive untrusted input.
@@ -1690,6 +1690,8 @@ DxeImageVerificationHandler (
   EFI_STATUS                    VarStatus;
   UINT32                        VarAttr;
   BOOLEAN                       IsFound;
+  UINT8                         HashAlg;
+  BOOLEAN                       IsFoundInDatabase;
 
   SignatureList     = NULL;
   SignatureListSize = 0;
@@ -1699,6 +1701,7 @@ DxeImageVerificationHandler (
   Action            = EFI_IMAGE_EXECUTION_AUTH_UNTESTED;
   IsVerified        = FALSE;
   IsFound           = FALSE;
+  IsFoundInDatabase = FALSE;
 
   //
   // Check the image type and get policy setting.
@@ -1837,40 +1840,51 @@ DxeImageVerificationHandler (
   //
   if ((SecDataDir == NULL) || (SecDataDir->Size == 0)) {
     //
-    // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",
+    // This image is not signed. The hash value of the image must match a record in the security database "db",
     // and not be reflected in the security data base "dbx".
     //
-    if (!HashPeImage (HASHALG_SHA256)) {
-      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHashTypeStr));
-      goto Failed;
-    }
+    HashAlg = sizeof (mHash) / sizeof (HASH_TABLE);
+    while (HashAlg > 0) {
+      HashAlg--;
+      if ((mHash[HashAlg].GetContextSize == NULL) || (mHash[HashAlg].HashInit == NULL) || (mHash[HashAlg].HashUpdate == NULL) || (mHash[HashAlg].HashFinal == NULL)) {
+        continue;
+      }
 
-    DbStatus = IsSignatureFoundInDatabase (
-                 EFI_IMAGE_SECURITY_DATABASE1,
-                 mImageDigest,
-                 &mCertType,
-                 mImageDigestSize,
-                 &IsFound
-                 );
-    if (EFI_ERROR (DbStatus) || IsFound) {
-      //
-      // Image Hash is in forbidden database (DBX).
-      //
-      DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));
-      goto Failed;
+      if (!HashPeImage (HashAlg)) {
+        continue;
+      }
+
+      DbStatus = IsSignatureFoundInDatabase (
+                   EFI_IMAGE_SECURITY_DATABASE1,
+                   mImageDigest,
+                   &mCertType,
+                   mImageDigestSize,
+                   &IsFound
+                   );
+      if (EFI_ERROR (DbStatus) || IsFound) {
+        //
+        // Image Hash is in forbidden database (DBX).
+        //
+        DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));
+        goto Failed;
+      }
+
+      DbStatus = IsSignatureFoundInDatabase (
+                   EFI_IMAGE_SECURITY_DATABASE,
+                   mImageDigest,
+                   &mCertType,
+                   mImageDigestSize,
+                   &IsFound
+                   );
+      if (!EFI_ERROR (DbStatus) && IsFound) {
+        //
+        // Image Hash is in allowed database (DB).
+        //
+        IsFoundInDatabase = TRUE;
+      }
     }
 
-    DbStatus = IsSignatureFoundInDatabase (
-                 EFI_IMAGE_SECURITY_DATABASE,
-                 mImageDigest,
-                 &mCertType,
-                 mImageDigestSize,
-                 &IsFound
-                 );
-    if (!EFI_ERROR (DbStatus) && IsFound) {
-      //
-      // Image Hash is in allowed database (DB).
-      //
+    if (IsFoundInDatabase) {
       return EFI_SUCCESS;
     }
 
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
index 1671d5be7c..0602acf702 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -82,6 +82,14 @@
   ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.
   gEfiCertSha256Guid
 
+  ## SOMETIMES_CONSUMES      ## GUID            # Unique ID for the type of the signature.
+  ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.
+  gEfiCertSha384Guid
+
+  ## SOMETIMES_CONSUMES      ## GUID            # Unique ID for the type of the signature.
+  ## SOMETIMES_PRODUCES      ## GUID            # Unique ID for the type of the signature.
+  gEfiCertSha512Guid
+
   ## SOMETIMES_CONSUMES      ## Variable:L"db"
   ## SOMETIMES_PRODUCES      ## Variable:L"db"
   ## SOMETIMES_CONSUMES      ## Variable:L"dbx"
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
index 0e31502b1b..2c11129526 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
@@ -1847,7 +1847,7 @@ HashPeImage (
   SectionHeader = NULL;
   Status        = FALSE;
 
-  if (HashAlg != HASHALG_SHA256) {
+  if ((HashAlg >= HASHALG_MAX)) {
     return FALSE;
   }
 
@@ -1856,8 +1856,25 @@ HashPeImage (
   //
   ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
 
-  mImageDigestSize = SHA256_DIGEST_SIZE;
-  mCertType        = gEfiCertSha256Guid;
+  switch (HashAlg) {
+    case HASHALG_SHA256:
+      mImageDigestSize = SHA256_DIGEST_SIZE;
+      mCertType        = gEfiCertSha256Guid;
+      break;
+
+    case HASHALG_SHA384:
+      mImageDigestSize = SHA384_DIGEST_SIZE;
+      mCertType        = gEfiCertSha384Guid;
+      break;
+
+    case HASHALG_SHA512:
+      mImageDigestSize = SHA512_DIGEST_SIZE;
+      mCertType        = gEfiCertSha512Guid;
+      break;
+
+    default:
+      return FALSE;
+  }
 
   CtxSize = mHash[HashAlg].GetContextSize ();
 
@@ -2251,6 +2268,7 @@ EnrollImageSignatureToSigDB (
   UINT32                     Attr;
   WIN_CERTIFICATE_UEFI_GUID  *GuidCertData;
   EFI_TIME                   Time;
+  UINT32                     HashAlg;
 
   Data         = NULL;
   GuidCertData = NULL;
@@ -2289,8 +2307,22 @@ EnrollImageSignatureToSigDB (
   }
 
   if (mSecDataDir->SizeOfCert == 0) {
-    if (!HashPeImage (HASHALG_SHA256)) {
-      Status =  EFI_SECURITY_VIOLATION;
+    Status  = EFI_SECURITY_VIOLATION;
+    HashAlg = sizeof (mHash) / sizeof (HASH_TABLE);
+    while (HashAlg > 0) {
+      HashAlg--;
+      if ((mHash[HashAlg].GetContextSize == NULL) || (mHash[HashAlg].HashInit == NULL) || (mHash[HashAlg].HashUpdate == NULL) || (mHash[HashAlg].HashFinal == NULL)) {
+        continue;
+      }
+
+      if (HashPeImage (HashAlg)) {
+        Status = EFI_SUCCESS;
+        break;
+      }
+    }
+
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Fail to get hash digest: %r", Status));
       goto ON_EXIT;
     }
   } else {
@@ -3764,6 +3796,10 @@ LoadSignatureList (
       ListType = STRING_TOKEN (STR_LIST_TYPE_SHA1);
     } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) {
       ListType = STRING_TOKEN (STR_LIST_TYPE_SHA256);
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha384Guid)) {
+      ListType = STRING_TOKEN (STR_LIST_TYPE_SHA384);
+    } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha512Guid)) {
+      ListType = STRING_TOKEN (STR_LIST_TYPE_SHA512);
     } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) {
       ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);
     } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) {
@@ -4011,6 +4047,12 @@ FormatHelpInfo (
   } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha256Guid)) {
     ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA256);
     DataSize   = 32;
+  } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha384Guid)) {
+    ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA384);
+    DataSize   = 48;
+  } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha512Guid)) {
+    ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA512);
+    DataSize   = 64;
   } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) {
     ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256);
     DataSize   = 32;
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
index 37c66f1b95..ff6e7301af 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
@@ -82,6 +82,8 @@ extern  EFI_IFR_GUID_LABEL  *mEndLabel;
 #define MAX_DIGEST_SIZE  SHA512_DIGEST_SIZE
 
 #define WIN_CERT_UEFI_RSA2048_SIZE  256
+#define WIN_CERT_UEFI_RSA3072_SIZE  384
+#define WIN_CERT_UEFI_RSA4096_SIZE  512
 
 //
 // Support hash types
@@ -98,6 +100,11 @@ extern  EFI_IFR_GUID_LABEL  *mEndLabel;
 //
 #define CER_PUBKEY_MIN_SIZE  256
 
+//
+// Define KeyType for public key storing file
+//
+#define KEY_TYPE_RSASSA  0
+
 //
 // Types of errors may occur during certificate enrollment.
 //
diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni
index 0d01701de7..177c585837 100644
--- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni
+++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni
@@ -124,6 +124,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #string STR_LIST_TYPE_X509                        #language en-US "X509"
 #string STR_LIST_TYPE_SHA1                        #language en-US "SHA1"
 #string STR_LIST_TYPE_SHA256                      #language en-US "SHA256"
+#string STR_LIST_TYPE_SHA384                      #language en-US "SHA384"
+#string STR_LIST_TYPE_SHA512                      #language en-US "SHA512"
 #string STR_LIST_TYPE_X509_SHA256                 #language en-US "X509_SHA256"
 #string STR_LIST_TYPE_X509_SHA384                 #language en-US "X509_SHA384"
 #string STR_LIST_TYPE_X509_SHA512                 #language en-US "X509_SHA512"
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#108314): https://edk2.groups.io/g/devel/message/108314
Mute This Topic: https://groups.io/mt/101188634/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



      parent reply	other threads:[~2023-09-06  8:16 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-06  8:16 [edk2-devel] [PATCH V8 0/2] Support RSA4096 and RSA3072 Sheng Wei
2023-09-06  8:16 ` [edk2-devel] [PATCH V8 1/2] CryptoPkg/BaseCryptLib: add sha384 and sha512 to ImageTimestampVerify Sheng Wei
2023-09-06  8:16 ` Sheng Wei [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230906081626.1871-3-w.sheng@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox