:p
atchew
Login
Patch V8: Update the patch comments for CryptoPkg. Comment should be <76 characters in each line. Refine coding format. Patch V7: Drop raw RSA3072 and RSA4096. Only use gEfiCertX509Guid for RSA3072 and RSA4096 Do the positive tests and the negative tests below. And got all the expected results. Patch V6: Remove the changes in MdePkg. The changes of patch v6 are in CryptoPkg and SecurityPkg. Set signature type to gEfiCertX509Guid when enroll RSA3072/RSA4096 KEK. This signature type is used to check the supported signature and show the strings. Patch V5: Using define KEY_TYPE_RSASSA to replace the magic number. Patch V4: Determine the RSA algorithm by a supported algorithm list. Patch V3: Select SHA algorithm automaticly for a unsigned efi image. Patch V2: Determine the SHA algorithm by a supported algorithm list. Create SHA context for each algorithm. Test Case: 1. Enroll a RSA4096 Cert, and execute an RSA4096 signed efi image under UEFI shell. 2. Enroll a RSA3072 Cert, and execute an RSA3072 signed efi image under UEFI shell. 3. Enroll a RSA2048 Cert, and execute an RSA2048 signed efi image under UEFI shell. 4. Enroll an unsigned efi image, execute the unsigned efi image under UEFI shell Test Result: Pass Negative Test Case: 1) Enroll a RSA2048 Cert, execute an unsigned efi image. 2) Enroll a RSA2048 Cert, execute a RSA4096 signed efi image. 3) Enroll a RSA4096 Cert, execute a RSA3072 signed efi image. 4) Enroll a RSA4096 Cert to both DB and DBX, execute the RSA4096 signed efi image. Test Result: Get "Access Denied" when try to execute the efi image. 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> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Sheng Wei (2): CryptoPkg/BaseCryptLib: add sha384 and sha512 to ImageTimestampVerify SecurityPkg/SecureBoot: Support RSA4096 and RSA3072 CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c | 3 +- .../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 + 9 files changed, 331 insertions(+), 86 deletions(-) -- 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108312): https://edk2.groups.io/g/devel/message/108312 Mute This Topic: https://groups.io/mt/101188631/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Register and initialize sha384/sha512 digest algorithms for PKCS#7 Handling. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3413 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> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Change-Id: I208a618e3f6eb12704e528ab842494082de1464d Signed-off-by: Sheng Wei <w.sheng@intel.com> --- CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c index XXXXXXX..XXXXXXX 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c @@ -XXX,XX +XXX,XX @@ ImageTimestampVerify ( // Register & Initialize necessary digest algorithms for PKCS#7 Handling. // if ((EVP_add_digest (EVP_md5 ()) == 0) || (EVP_add_digest (EVP_sha1 ()) == 0) || - (EVP_add_digest (EVP_sha256 ()) == 0) || ((EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0)) + (EVP_add_digest (EVP_sha256 ()) == 0) || (EVP_add_digest (EVP_sha384 ()) == 0) || + (EVP_add_digest (EVP_sha512 ()) == 0) || ((EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0)) { return FALSE; } -- 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108313): https://edk2.groups.io/g/devel/message/108313 Mute This Topic: https://groups.io/mt/101188632/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthService.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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); // @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ DeleteCertsFromDb ( **/ EFI_STATUS InsertCertsToDb ( + IN UINT8 HashAlgId, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, @@ -XXX,XX +XXX,XX @@ 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". @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ InsertCertsToDb ( CopyMem ( (UINT8 *)Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16), - Sha256Digest, + ShaDigest, CertDataSize ); @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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; } } @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h +++ b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c @@ -XXX,XX +XXX,XX @@ 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[] = { { @@ -XXX,XX +XXX,XX @@ VARIABLE_ENTRY_PROPERTY mAuthVarEntry[] = { }, }; -VOID **mAuthVarAddressPointer[9]; +VOID **mAuthVarAddressPointer[11]; AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn = NULL; @@ -XXX,XX +XXX,XX @@ AuthVariableLibInitialize ( UINT32 VarAttr; UINT8 *Data; UINTN DataSize; - UINTN CtxSize; UINT8 SecureBootMode; UINT8 SecureBootEnable; UINT8 CustomMode; @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ DxeImageVerificationHandler ( EFI_STATUS VarStatus; UINT32 VarAttr; BOOLEAN IsFound; + UINT8 HashAlg; + BOOLEAN IsFoundInDatabase; SignatureList = NULL; SignatureListSize = 0; @@ -XXX,XX +XXX,XX @@ DxeImageVerificationHandler ( Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED; IsVerified = FALSE; IsFound = FALSE; + IsFoundInDatabase = FALSE; // // Check the image type and get policy setting. @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf @@ -XXX,XX +XXX,XX @@ ## 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -XXX,XX +XXX,XX @@ HashPeImage ( SectionHeader = NULL; Status = FALSE; - if (HashAlg != HASHALG_SHA256) { + if ((HashAlg >= HASHALG_MAX)) { return FALSE; } @@ -XXX,XX +XXX,XX @@ 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 (); @@ -XXX,XX +XXX,XX @@ EnrollImageSignatureToSigDB ( UINT32 Attr; WIN_CERTIFICATE_UEFI_GUID *GuidCertData; EFI_TIME Time; + UINT32 HashAlg; Data = NULL; GuidCertData = NULL; @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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)) { @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni @@ -XXX,XX +XXX,XX @@ 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/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Patch V9: Refine coding format for file AuthService.c Patch V8: Update the patch comments for CryptoPkg. Comment should be <76 characters in each line. Refine coding format. Patch V7: Drop raw RSA3072 and RSA4096. Only use gEfiCertX509Guid for RSA3072 and RSA4096 Do the positive tests and the negative tests below. And got all the expected results. Patch V6: Remove the changes in MdePkg. The changes of patch v6 are in CryptoPkg and SecurityPkg. Set signature type to gEfiCertX509Guid when enroll RSA3072/RSA4096 KEK. This signature type is used to check the supported signature and show the strings. Patch V5: Using define KEY_TYPE_RSASSA to replace the magic number. Patch V4: Determine the RSA algorithm by a supported algorithm list. Patch V3: Select SHA algorithm automaticly for a unsigned efi image. Patch V2: Determine the SHA algorithm by a supported algorithm list. Create SHA context for each algorithm. Test Case: 1. Enroll a RSA4096 Cert, and execute an RSA4096 signed efi image under UEFI shell. 2. Enroll a RSA3072 Cert, and execute an RSA3072 signed efi image under UEFI shell. 3. Enroll a RSA2048 Cert, and execute an RSA2048 signed efi image under UEFI shell. 4. Enroll an unsigned efi image, execute the unsigned efi image under UEFI shell Test Result: Pass Negative Test Case: 1) Enroll a RSA2048 Cert, execute an unsigned efi image. 2) Enroll a RSA2048 Cert, execute a RSA4096 signed efi image. 3) Enroll a RSA4096 Cert, execute a RSA3072 signed efi image. 4) Enroll a RSA4096 Cert to both DB and DBX, execute the RSA4096 signed efi image. Test Result: Get "Access Denied" when try to execute the efi image. 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> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Sheng Wei (2): CryptoPkg/BaseCryptLib: add sha384 and sha512 to ImageTimestampVerify SecurityPkg/SecureBoot: Support RSA4096 and RSA3072 CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c | 3 +- .../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 + 9 files changed, 331 insertions(+), 86 deletions(-) -- 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108352): https://edk2.groups.io/g/devel/message/108352 Mute This Topic: https://groups.io/mt/101207366/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
Register and initialize sha384/sha512 digest algorithms for PKCS#7 Handling. REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3413 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> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Change-Id: I208a618e3f6eb12704e528ab842494082de1464d Signed-off-by: Sheng Wei <w.sheng@intel.com> --- CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c index XXXXXXX..XXXXXXX 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c @@ -XXX,XX +XXX,XX @@ ImageTimestampVerify ( // Register & Initialize necessary digest algorithms for PKCS#7 Handling. // if ((EVP_add_digest (EVP_md5 ()) == 0) || (EVP_add_digest (EVP_sha1 ()) == 0) || - (EVP_add_digest (EVP_sha256 ()) == 0) || ((EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0)) + (EVP_add_digest (EVP_sha256 ()) == 0) || (EVP_add_digest (EVP_sha384 ()) == 0) || + (EVP_add_digest (EVP_sha512 ()) == 0) || ((EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA)) == 0)) { return FALSE; } -- 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#108354): https://edk2.groups.io/g/devel/message/108354 Mute This Topic: https://groups.io/mt/101207368/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-
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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthService.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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); // @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ DeleteCertsFromDb ( **/ EFI_STATUS InsertCertsToDb ( + IN UINT8 HashAlgId, IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, @@ -XXX,XX +XXX,XX @@ 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". @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ InsertCertsToDb ( CopyMem ( (UINT8 *)Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16), - Sha256Digest, + ShaDigest, CertDataSize ); @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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; } } @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h +++ b/SecurityPkg/Library/AuthVariableLib/AuthServiceInternal.h @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c @@ -XXX,XX +XXX,XX @@ 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[] = { { @@ -XXX,XX +XXX,XX @@ VARIABLE_ENTRY_PROPERTY mAuthVarEntry[] = { }, }; -VOID **mAuthVarAddressPointer[9]; +VOID **mAuthVarAddressPointer[11]; AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn = NULL; @@ -XXX,XX +XXX,XX @@ AuthVariableLibInitialize ( UINT32 VarAttr; UINT8 *Data; UINTN DataSize; - UINTN CtxSize; UINT8 SecureBootMode; UINT8 SecureBootEnable; UINT8 CustomMode; @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ DxeImageVerificationHandler ( EFI_STATUS VarStatus; UINT32 VarAttr; BOOLEAN IsFound; + UINT8 HashAlg; + BOOLEAN IsFoundInDatabase; SignatureList = NULL; SignatureListSize = 0; @@ -XXX,XX +XXX,XX @@ DxeImageVerificationHandler ( Action = EFI_IMAGE_EXECUTION_AUTH_UNTESTED; IsVerified = FALSE; IsFound = FALSE; + IsFoundInDatabase = FALSE; // // Check the image type and get policy setting. @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf @@ -XXX,XX +XXX,XX @@ ## 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -XXX,XX +XXX,XX @@ HashPeImage ( SectionHeader = NULL; Status = FALSE; - if (HashAlg != HASHALG_SHA256) { + if ((HashAlg >= HASHALG_MAX)) { return FALSE; } @@ -XXX,XX +XXX,XX @@ 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 (); @@ -XXX,XX +XXX,XX @@ EnrollImageSignatureToSigDB ( UINT32 Attr; WIN_CERTIFICATE_UEFI_GUID *GuidCertData; EFI_TIME Time; + UINT32 HashAlg; Data = NULL; GuidCertData = NULL; @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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)) { @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni @@ -XXX,XX +XXX,XX @@ 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 (#108353): https://edk2.groups.io/g/devel/message/108353 Mute This Topic: https://groups.io/mt/101207367/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=-=-=-=-=-=-=-=-=-=-=-