Review-by -----Original Message----- From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Sheng, W Sent: Thursday, May 25, 2023 1:23 PM To: devel@edk2.groups.io Cc: Yao, Jiewen <jiewen....@intel.com>; Wang, Jian J <jian.j.w...@intel.com>; Xu, Min M <min.m...@intel.com>; Chen, Zeyi <zeyi.c...@intel.com>; Wang, Fiona <fiona.w...@intel.com> Subject: [edk2-devel] [PATCH] SecurityPkg/SecureBoot: Support RSA 512 and RSA 384
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3413 Cc: Jiewen Yao <jiewen....@intel.com> Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Min Xu <min.m...@intel.com> Cc: Zeyi Chen <zeyi.c...@intel.com> Cc: Fiona Wang <fiona.w...@intel.com> Signed-off-by: Sheng Wei <w.sh...@intel.com> --- CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c | 3 +- MdePkg/Include/Guid/ImageAuthentication.h | 26 ++ MdePkg/MdePkg.dec | 2 + .../Library/AuthVariableLib/AuthService.c | 272 ++++++++++++++++-- .../Library/AuthVariableLib/AuthVariableLib.c | 4 +- .../DxeImageVerificationLib.c | 35 ++- .../DxeImageVerificationLib.inf | 1 + SecurityPkg/SecurityPkg.dec | 7 + .../SecureBootConfigDxe.inf | 19 ++ .../SecureBootConfigImpl.c | 122 +++++++- .../SecureBootConfigImpl.h | 2 + .../SecureBootConfigStrings.uni | 6 + 12 files changed, 463 insertions(+), 36 deletions(-) diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c index 027dbb6842..944bcf8d38 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptTs.c @@ -591,7 +591,8 @@ 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; } diff --git a/MdePkg/Include/Guid/ImageAuthentication.h b/MdePkg/Include/Guid/ImageAuthentication.h index fe83596571..c8ea2c14fb 100644 --- a/MdePkg/Include/Guid/ImageAuthentication.h +++ b/MdePkg/Include/Guid/ImageAuthentication.h @@ -144,6 +144,30 @@ typedef struct { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6} \ } +/// +/// This identifies a signature containing an RSA-3072 key. The key +(only the modulus +/// since the public key exponent is known to be 0x10001) shall be +stored in big-endian +/// order. +/// The SignatureHeader size shall always be 0. The SignatureSize shall +always be 16 (size +/// of SignatureOwner component) + 384 bytes. +/// +#define EFI_CERT_RSA3072_GUID \ + { \ + 0xedd320c2, 0xb057, 0x4b8e, {0xad, 0x46, 0x2c, 0x9b, 0x85, 0x89, + 0xee, 0x92 } \ + } + +/// +/// This identifies a signature containing an RSA-4096 key. The key +(only the modulus +/// since the public key exponent is known to be 0x10001) shall be +stored in big-endian +/// order. +/// The SignatureHeader size shall always be 0. The SignatureSize shall +always be 16 (size +/// of SignatureOwner component) + 512 bytes. +/// +#define EFI_CERT_RSA4096_GUID \ + { \ + 0xb23e89a6, 0x8c8b, 0x4412, {0x85, 0x73, 0x15, 0x4e, 0x8d, 0x00, + 0x98, 0x2c } \ + } + /// /// This identifies a signature containing a RSA-2048 signature of a SHA-256 hash. The /// SignatureHeader size shall always be 0. The SignatureSize shall always be 16 (size of @@ -330,6 +354,8 @@ typedef struct { extern EFI_GUID gEfiImageSecurityDatabaseGuid; extern EFI_GUID gEfiCertSha256Guid; extern EFI_GUID gEfiCertRsa2048Guid; +extern EFI_GUID gEfiCertRsa3072Guid; +extern EFI_GUID gEfiCertRsa4096Guid; extern EFI_GUID gEfiCertRsa2048Sha256Guid; extern EFI_GUID gEfiCertSha1Guid; extern EFI_GUID gEfiCertRsa2048Sha1Guid; diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index 80b6559053..782f6d184d 100644 --- a/MdePkg/MdePkg.dec +++ b/MdePkg/MdePkg.dec @@ -562,6 +562,8 @@ gEfiImageSecurityDatabaseGuid = { 0xd719b2cb, 0x3d3a, 0x4596, {0xa3, 0xbc, 0xda, 0xd0, 0xe, 0x67, 0x65, 0x6f }} gEfiCertSha256Guid = { 0xc1c41626, 0x504c, 0x4092, {0xac, 0xa9, 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28 }} gEfiCertRsa2048Guid = { 0x3c5766e8, 0x269c, 0x4e34, {0xaa, 0x14, 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6 }} + gEfiCertRsa3072Guid = { 0xedd320c2, 0xb057, 0x4b8e, {0xad, 0x46, 0x2c, 0x9b, 0x85, 0x89, 0xee, 0x92 }} + gEfiCertRsa4096Guid = { 0xb23e89a6, 0x8c8b, 0x4412, {0x85, 0x73, 0x15, 0x4e, 0x8d, 0x00, 0x98, 0x2c }} gEfiCertRsa2048Sha256Guid = { 0xe2b36190, 0x879b, 0x4a3d, {0xad, 0x8d, 0xf2, 0xe7, 0xbb, 0xa3, 0x27, 0x84 }} gEfiCertSha1Guid = { 0x826ca512, 0xcf10, 0x4ac9, {0xb1, 0x87, 0xbe, 0x1, 0x49, 0x66, 0x31, 0xbd }} gEfiCertRsa2048Sha1Guid = { 0x67f8444f, 0x8743, 0x48f1, {0xa3, 0x28, 0x1e, 0xaa, 0xb8, 0x73, 0x60, 0x80 }} diff --git a/SecurityPkg/Library/AuthVariableLib/AuthService.c b/SecurityPkg/Library/AuthVariableLib/AuthService.c index 452ed491ea..288e44a359 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthService.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthService.c @@ -29,12 +29,16 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include <Protocol/VariablePolicy.h> #include <Library/VariablePolicyLib.h> +#define SHA_DIGEST_SIZE_MAX SHA512_DIGEST_SIZE + // // Public Exponent of RSA Key. // CONST UINT8 mRsaE[] = { 0x01, 0x00, 0x01 }; CONST UINT8 mSha256OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01 }; +CONST UINT8 mSha384OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, +0x04, 0x02, 0x02 }; +CONST UINT8 mSha512OidValue[] = { 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, +0x04, 0x02, 0x03 }; // // Requirement for different signature type which have been defined in UEFI spec. @@ -44,6 +48,8 @@ EFI_SIGNATURE_ITEM mSupportSigItem[] = { // {SigType, SigHeaderSize, SigDataSize } { EFI_CERT_SHA256_GUID, 0, 32 }, { EFI_CERT_RSA2048_GUID, 0, 256 }, + { EFI_CERT_RSA3072_GUID, 0, 384 }, + { EFI_CERT_RSA4096_GUID, 0, 512 }, { EFI_CERT_RSA2048_SHA256_GUID, 0, 256 }, { EFI_CERT_SHA1_GUID, 0, 20 }, { EFI_CERT_RSA2048_SHA1_GUID, 0, 256 }, @@ -1172,6 +1178,172 @@ CalculatePrivAuthVarSignChainSHA256Digest ( return EFI_SUCCESS; } +/** + Calculate SHA38 digest of SignerCert CommonName + ToplevelCert + tbsCertificate + SignerCert and ToplevelCert are inside the signer certificate chain. + + @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] Sha384Digest Sha384 digest calculated. + + @return EFI_ABORTED Digest process failed. + @return EFI_SUCCESS SHA384 Digest is successfully calculated. + +**/ +EFI_STATUS +CalculatePrivAuthVarSignChainSHA384Digest ( + IN UINT8 *SignerCert, + IN UINTN SignerCertSize, + IN UINT8 *TopLevelCert, + IN UINTN TopLevelCertSize, + OUT UINT8 *Sha384Digest + ) +{ + UINT8 *TbsCert; + UINTN TbsCertSize; + CHAR8 CertCommonName[128]; + UINTN CertCommonNameSize; + BOOLEAN CryptoStatus; + EFI_STATUS Status; + + CertCommonNameSize = sizeof (CertCommonName); + + // + // Get SignerCert CommonName + // + Status = X509GetCommonName (SignerCert, SignerCertSize, + CertCommonName, &CertCommonNameSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a Get SignerCert CommonName failed with + status %x\n", __FUNCTION__, Status)); + return EFI_ABORTED; + } + + // + // Get TopLevelCert tbsCertificate + // + if (!X509GetTBSCert (TopLevelCert, TopLevelCertSize, &TbsCert, + &TbsCertSize)) { + DEBUG ((DEBUG_INFO, "%a Get Top-level Cert tbsCertificate + failed!\n", __FUNCTION__)); + return EFI_ABORTED; + } + + // + // Digest SignerCert CN + TopLevelCert tbsCertificate + // + ZeroMem (Sha384Digest, SHA384_DIGEST_SIZE); + CryptoStatus = Sha384Init (mHashCtx); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + // + // '\0' is forced in CertCommonName. No overflow issue + // + CryptoStatus = Sha384Update ( + mHashCtx, + CertCommonName, + AsciiStrLen (CertCommonName) + ); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + CryptoStatus = Sha384Update (mHashCtx, TbsCert, TbsCertSize); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + CryptoStatus = Sha384Final (mHashCtx, Sha384Digest); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +/** + Calculate SHA512 digest of SignerCert CommonName + ToplevelCert + tbsCertificate + SignerCert and ToplevelCert are inside the signer certificate chain. + + @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] Sha512Digest Sha512 digest calculated. + + @return EFI_ABORTED Digest process failed. + @return EFI_SUCCESS SHA512 Digest is successfully calculated. + +**/ +EFI_STATUS +CalculatePrivAuthVarSignChainSHA512Digest ( + IN UINT8 *SignerCert, + IN UINTN SignerCertSize, + IN UINT8 *TopLevelCert, + IN UINTN TopLevelCertSize, + OUT UINT8 *Sha512Digest + ) +{ + UINT8 *TbsCert; + UINTN TbsCertSize; + CHAR8 CertCommonName[128]; + UINTN CertCommonNameSize; + BOOLEAN CryptoStatus; + EFI_STATUS Status; + + CertCommonNameSize = sizeof (CertCommonName); + + // + // Get SignerCert CommonName + // + Status = X509GetCommonName (SignerCert, SignerCertSize, + CertCommonName, &CertCommonNameSize); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a Get SignerCert CommonName failed with + status %x\n", __FUNCTION__, Status)); + return EFI_ABORTED; + } + + // + // Get TopLevelCert tbsCertificate + // + if (!X509GetTBSCert (TopLevelCert, TopLevelCertSize, &TbsCert, + &TbsCertSize)) { + DEBUG ((DEBUG_INFO, "%a Get Top-level Cert tbsCertificate + failed!\n", __FUNCTION__)); + return EFI_ABORTED; + } + + // + // Digest SignerCert CN + TopLevelCert tbsCertificate + // + ZeroMem (Sha512Digest, SHA512_DIGEST_SIZE); + CryptoStatus = Sha512Init (mHashCtx); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + // + // '\0' is forced in CertCommonName. No overflow issue + // + CryptoStatus = Sha512Update ( + mHashCtx, + CertCommonName, + AsciiStrLen (CertCommonName) + ); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + CryptoStatus = Sha512Update (mHashCtx, TbsCert, TbsCertSize); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + CryptoStatus = Sha512Final (mHashCtx, Sha512Digest); + if (!CryptoStatus) { + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + /** Find matching signer's certificates for common authenticated variable by corresponding VariableName and VendorGuid from "certdb" or "certdbv". @@ -1526,6 +1698,7 @@ DeleteCertsFromDb ( @param[in] SignerCertSize Length of signer certificate. @param[in] TopLevelCert Top-level certificate data. @param[in] TopLevelCertSize Length of top-level certificate. + @param[in] DigestSize Digest Size. @retval EFI_INVALID_PARAMETER Any input parameter is invalid. @retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName @@ -1542,7 +1715,8 @@ InsertCertsToDb ( IN UINT8 *SignerCert, IN UINTN SignerCertSize, IN UINT8 *TopLevelCert, - IN UINTN TopLevelCertSize + IN UINTN TopLevelCertSize, + IN UINT32 DigestSize ) { EFI_STATUS Status; @@ -1556,7 +1730,7 @@ 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; @@ -1618,20 +1792,41 @@ InsertCertsToDb ( // Construct new data content of variable "certdb" or "certdbv". // NameSize = (UINT32)StrLen (VariableName); - CertDataSize = sizeof (Sha256Digest); + CertDataSize = DigestSize; 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 ( - SignerCert, - SignerCertSize, - TopLevelCert, - TopLevelCertSize, - Sha256Digest - ); + if (DigestSize == SHA256_DIGEST_SIZE) { + Status = CalculatePrivAuthVarSignChainSHA256Digest ( + SignerCert, + SignerCertSize, + TopLevelCert, + TopLevelCertSize, + ShaDigest + ); + } else if (DigestSize == SHA384_DIGEST_SIZE) { + Status = CalculatePrivAuthVarSignChainSHA384Digest ( + SignerCert, + SignerCertSize, + TopLevelCert, + TopLevelCertSize, + ShaDigest + ); + } else if (DigestSize == SHA512_DIGEST_SIZE) { + Status = CalculatePrivAuthVarSignChainSHA512Digest ( + SignerCert, + SignerCertSize, + TopLevelCert, + TopLevelCertSize, + ShaDigest + ); + } else { + return EFI_UNSUPPORTED; + } + if (EFI_ERROR (Status)) { return Status; } @@ -1663,7 +1858,7 @@ InsertCertsToDb ( CopyMem ( (UINT8 *)Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16), - Sha256Digest, + ShaDigest, CertDataSize ); @@ -1857,7 +2052,7 @@ VerifyTimeBasedPayload ( UINTN CertStackSize; UINT8 *CertsInCertDb; UINT32 CertsSizeinDb; - UINT8 Sha256Digest[SHA256_DIGEST_SIZE]; + UINT8 ShaDigest[SHA_DIGEST_SIZE_MAX]; EFI_CERT_DATA *CertDataPtr; // @@ -1928,7 +2123,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 { @@ -1978,7 +2173,19 @@ VerifyTimeBasedPayload ( || (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)))) + || (CompareMem (SigData + 32, &mSha256OidValue, sizeof + (mSha256OidValue)) != 0))) + && ( (SigDataSize >= (13 + sizeof (mSha384OidValue))) + && ( ((*(SigData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) + || (CompareMem (SigData + 13, &mSha384OidValue, sizeof + (mSha384OidValue)) != 0))) + && ( (SigDataSize >= (32 + sizeof (mSha384OidValue))) + && ( ((*(SigData + 20) & TWO_BYTE_ENCODE) != + TWO_BYTE_ENCODE) + || (CompareMem (SigData + 32, &mSha384OidValue, sizeof + (mSha384OidValue)) != 0))) + && ( (SigDataSize >= (13 + sizeof (mSha512OidValue))) + && ( ((*(SigData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) + || (CompareMem (SigData + 13, &mSha512OidValue, sizeof + (mSha512OidValue)) != 0))) + && ( (SigDataSize >= (32 + sizeof (mSha512OidValue))) + && ( ((*(SigData + 20) & TWO_BYTE_ENCODE) != + TWO_BYTE_ENCODE) + || (CompareMem (SigData + 32, &mSha512OidValue, sizeof + (mSha512OidValue)) != 0)))) { return EFI_SECURITY_VIOLATION; } @@ -2180,9 +2387,39 @@ VerifyTimeBasedPayload ( ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)), TopLevelCert, TopLevelCertSize, - Sha256Digest + ShaDigest + ); + if (EFI_ERROR (Status) || (CompareMem (ShaDigest, + CertsInCertDb, CertsSizeinDb) != 0)) { + goto Exit; + } + } else if (CertsSizeinDb == SHA384_DIGEST_SIZE) { + // + // Check hash of signer cert CommonName + Top-level issuer + tbsCertificate against data in CertDb + // + CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1); + Status = CalculatePrivAuthVarSignChainSHA384Digest ( + CertDataPtr->CertDataBuffer, + ReadUnaligned32 ((UINT32 + *)&(CertDataPtr->CertDataLength)), + TopLevelCert, + TopLevelCertSize, + ShaDigest + ); + if (EFI_ERROR (Status) || (CompareMem (ShaDigest, + CertsInCertDb, CertsSizeinDb) != 0)) { + goto Exit; + } + } else if (CertsSizeinDb == SHA512_DIGEST_SIZE) { + // + // Check hash of signer cert CommonName + Top-level issuer + tbsCertificate against data in CertDb + // + CertDataPtr = (EFI_CERT_DATA *)(SignerCerts + 1); + Status = CalculatePrivAuthVarSignChainSHA512Digest ( + CertDataPtr->CertDataBuffer, + ReadUnaligned32 ((UINT32 + *)&(CertDataPtr->CertDataLength)), + TopLevelCert, + TopLevelCertSize, + ShaDigest ); - if (EFI_ERROR (Status) || (CompareMem (Sha256Digest, CertsInCertDb, CertsSizeinDb) != 0)) { + if (EFI_ERROR (Status) || (CompareMem (ShaDigest, + CertsInCertDb, CertsSizeinDb) != 0)) { goto Exit; } } else { @@ -2221,7 +2458,8 @@ VerifyTimeBasedPayload ( CertDataPtr->CertDataBuffer, ReadUnaligned32 ((UINT32 *)&(CertDataPtr->CertDataLength)), TopLevelCert, - TopLevelCertSize + TopLevelCertSize, + CertsSizeinDb ); if (EFI_ERROR (Status)) { VerifyStatus = FALSE; diff --git a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c index dc61ae840c..552c0e99be 100644 --- a/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c +++ b/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c @@ -26,7 +26,7 @@ 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_RSA3072_GUID, EFI_CERT_RSA4096_GUID, +EFI_CERT_X509_GUID }; // // Hash context pointer @@ -135,7 +135,7 @@ AuthVariableLibInitialize ( // // Initialize hash context. // - CtxSize = Sha256GetContextSize (); + CtxSize = Sha512GetContextSize (); mHashCtx = AllocateRuntimePool (CtxSize); if (mHashCtx == NULL) { return EFI_OUT_OF_RESOURCES; diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 66e2f5eaa3..f642aad64d 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLi +++ b.c @@ -1606,6 +1606,35 @@ Done: return VerifyStatus; } +/** + Get Hash Alg by PcdSecureBootDefaultHashAlg + + @retval UINT32 Hash Alg + **/ +UINT32 +GetDefaultHashAlg ( + VOID + ) +{ + UINT32 HashAlg; + + switch (PcdGet8 (PcdSecureBootDefaultHashAlg)) { + case 1: + DEBUG ((DEBUG_INFO, "%a use SHA384", __func__)); + HashAlg = HASHALG_SHA384; + break; + case 2: + DEBUG ((DEBUG_INFO, "%a use SHA512", __func__)); + HashAlg = HASHALG_SHA512; + break; + default: + DEBUG ((DEBUG_INFO, "%a use SHA256", __func__)); + HashAlg = HASHALG_SHA256; + break; + } + return HashAlg; +} + /** Provide verification service for signed images, which include both signature validation and platform policy control. For signature types, both UEFI WIN_CERTIFICATE_UEFI_GUID and @@ -1620,7 +1649,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. @@ -1832,10 +1861,10 @@ 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)) { + if (!HashPeImage (GetDefaultHashAlg ())) { DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHashTypeStr)); goto Failed; } diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf index 1e1a639857..f1ef9236c2 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLi +++ b.inf @@ -93,3 +93,4 @@ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy ## SOMETIMES_CONSUMES gEfiSecurityPkgTokenSpaceGuid.PcdRemovableMediaImageVerificationPolicy ## SOMETIMES_CONSUMES gEfiSecurityPkgTokenSpaceGuid.PcdFixedMediaImageVerificationPolicy ## SOMETIMES_CONSUMES + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultHashAlg ## CONSUMES diff --git a/SecurityPkg/SecurityPkg.dec b/SecurityPkg/SecurityPkg.dec index 0382090f4e..4adc2a72ab 100644 --- a/SecurityPkg/SecurityPkg.dec +++ b/SecurityPkg/SecurityPkg.dec @@ -521,6 +521,13 @@ # @Prompt Skip Hdd Password prompt. gEfiSecurityPkgTokenSpaceGuid.PcdSkipHddPasswordPrompt|FALSE|BOOLEAN|0x00010021 + ## Indicates default hash algorithm in Secure Boot + # 0 - Use SHA256 + # 1 - Use SHA384 + # 2 - Use SHA512 + # @Prompt Secure Boot default hash algorithm + + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultHashAlg|0|UINT8|0x00 + 010040 + [PcdsDynamic, PcdsDynamicEx] ## This PCD indicates Hash mask for TPM 2.0. Bit definition strictly follows TCG Algorithm Registry.<BR><BR> diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf index 1671d5be7c..4b0012d033 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootCo +++ nfigDxe.inf @@ -70,6 +70,14 @@ ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature. gEfiCertRsa2048Guid + ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature. + ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature. + gEfiCertRsa3072Guid + + ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature. + ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature. + gEfiCertRsa4096Guid + ## SOMETIMES_CONSUMES ## GUID # Unique ID for the type of the signature. ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the signature. gEfiCertX509Guid @@ -82,6 +90,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" @@ -107,6 +123,9 @@ gEfiCertX509Sha384Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate. gEfiCertX509Sha512Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID for the type of the certificate. +[Pcd] + gEfiSecurityPkgTokenSpaceGuid.PcdSecureBootDefaultHashAlg ## CONSUMES + [Protocols] gEfiHiiConfigAccessProtocolGuid ## PRODUCES gEfiDevicePathProtocolGuid ## PRODUCES diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index 4299a6b5e5..0ba029a394 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootCo +++ nfigImpl.c @@ -560,7 +560,7 @@ ON_EXIT: **/ EFI_STATUS -EnrollRsa2048ToKek ( +EnrollRsaToKek ( IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private ) { @@ -603,8 +603,13 @@ EnrollRsa2048ToKek ( ASSERT (KeyBlob != NULL); KeyInfo = (CPL_KEY_INFO *)KeyBlob; - if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) { - DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n")); + switch (KeyInfo->KeyLengthInBits / 8) { + case WIN_CERT_UEFI_RSA2048_SIZE: + case WIN_CERT_UEFI_RSA3072_SIZE: + case WIN_CERT_UEFI_RSA4096_SIZE: + break; + default : + DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048, RSA3072 + and RSA4096 are supported.\n")); Status = EFI_UNSUPPORTED; goto ON_EXIT; } @@ -632,7 +637,7 @@ EnrollRsa2048ToKek ( // KekSigListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 - + WIN_CERT_UEFI_RSA2048_SIZE; + + KeyLenInBytes; KekSigList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (KekSigListSize); if (KekSigList == NULL) { @@ -642,17 +647,32 @@ EnrollRsa2048ToKek ( KekSigList->SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 - + WIN_CERT_UEFI_RSA2048_SIZE; + + (UINT32) KeyLenInBytes; KekSigList->SignatureHeaderSize = 0; - KekSigList->SignatureSize = sizeof (EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE; - CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid); + KekSigList->SignatureSize = sizeof (EFI_SIGNATURE_DATA) - 1 + (UINT32) KeyLenInBytes; + switch (KeyLenInBytes) { + case WIN_CERT_UEFI_RSA2048_SIZE: + CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid); + break; + case WIN_CERT_UEFI_RSA3072_SIZE: + CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa3072Guid); + break; + case WIN_CERT_UEFI_RSA4096_SIZE: + CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa4096Guid); + break; + break; + default : + DEBUG ((DEBUG_ERROR, "Unsupported key length.\n")); + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } KEKSigData = (EFI_SIGNATURE_DATA *)((UINT8 *)KekSigList + sizeof (EFI_SIGNATURE_LIST)); CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID); CopyMem ( KEKSigData->SignatureData, KeyBlob + sizeof (CPL_KEY_INFO), - WIN_CERT_UEFI_RSA2048_SIZE + KeyLenInBytes ); // @@ -890,7 +910,7 @@ EnrollKeyExchangeKey ( if (IsDerEncodeCertificate (FilePostFix)) { return EnrollX509ToKek (Private); } else if (CompareMem (FilePostFix, L".pbk", 4) == 0) { - return EnrollRsa2048ToKek (Private); + return EnrollRsaToKek (Private); } else { // // File type is wrong, simply close it @@ -1847,7 +1867,7 @@ HashPeImage ( SectionHeader = NULL; Status = FALSE; - if (HashAlg != HASHALG_SHA256) { + if ((HashAlg >= HASHALG_MAX)) { return FALSE; } @@ -1856,8 +1876,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 (); @@ -2222,6 +2259,35 @@ ON_EXIT: return Status; } +/** + Get Hash Alg by PcdSecureBootDefaultHashAlg + + @retval UINT32 Hash Alg + **/ +UINT32 +GetDefaultHashAlg ( + VOID + ) +{ + UINT32 HashAlg; + + switch (PcdGet8 (PcdSecureBootDefaultHashAlg)) { + case 1: + DEBUG ((DEBUG_INFO, "%a use SHA384", __func__)); + HashAlg = HASHALG_SHA384; + break; + case 2: + DEBUG ((DEBUG_INFO, "%a use SHA512", __func__)); + HashAlg = HASHALG_SHA512; + break; + default: + DEBUG ((DEBUG_INFO, "%a use SHA256", __func__)); + HashAlg = HASHALG_SHA256; + break; + } + return HashAlg; +} + /** Enroll a new signature of executable into Signature Database. @@ -2289,7 +2355,7 @@ EnrollImageSignatureToSigDB ( } if (mSecDataDir->SizeOfCert == 0) { - if (!HashPeImage (HASHALG_SHA256)) { + if (!HashPeImage (GetDefaultHashAlg ())) { Status = EFI_SECURITY_VIOLATION; goto ON_EXIT; } @@ -2589,6 +2655,10 @@ UpdateDeletePage ( while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) { Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID); + } else if (CompareGuid (&CertList->SignatureType, + &gEfiCertRsa3072Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_RSA3072_SHA384_GUID); + } else if (CompareGuid (&CertList->SignatureType, + &gEfiCertRsa4096Guid)) { + Help = STRING_TOKEN (STR_CERT_TYPE_RSA4096_SHA512_GUID); } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID); } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) { @@ -2750,6 +2820,8 @@ DeleteKeyExchangeKey ( GuidIndex = 0; while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) { if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertRsa3072Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertRsa4096Guid) || CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { CopyMem (Data + Offset, CertList, (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize)); @@ -2952,6 +3024,8 @@ DeleteSignature ( GuidIndex = 0; while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertRsa3072Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertRsa4096Guid) || CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) || CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) || CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) || @@ -3758,12 +3832,20 @@ LoadSignatureList ( while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) { if (CompareGuid (&ListWalker->SignatureType, &gEfiCertRsa2048Guid)) { ListType = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256); + } else if (CompareGuid (&ListWalker->SignatureType, + &gEfiCertRsa3072Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_RSA3072_SHA384); + } else if (CompareGuid (&ListWalker->SignatureType, + &gEfiCertRsa4096Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_RSA4096_SHA512); } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) { ListType = STRING_TOKEN (STR_LIST_TYPE_X509); } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha1Guid)) { 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)) { @@ -4001,6 +4083,14 @@ FormatHelpInfo ( ListTypeId = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256); DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); IsCert = TRUE; + } else if (CompareGuid (&ListEntry->SignatureType, + &gEfiCertRsa3072Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_RSA3072_SHA384); + DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); + IsCert = TRUE; + } else if (CompareGuid (&ListEntry->SignatureType, + &gEfiCertRsa4096Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_RSA4096_SHA512); + DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); + IsCert = TRUE; } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Guid)) { ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509); DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); @@ -4011,6 +4101,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..ae50d929a7 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootCo +++ nfigImpl.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 diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni index 0d01701de7..1b48acc800 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigStrings.uni +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootCo +++ nfigStrings.uni @@ -113,6 +113,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_FORM_ENROLL_KEK_FROM_FILE_TITLE_HELP #language en-US "Read the public key of KEK from file" #string STR_FILE_EXPLORER_TITLE #language en-US "File Explorer" #string STR_CERT_TYPE_RSA2048_SHA256_GUID #language en-US "RSA2048_SHA256_GUID" +#string STR_CERT_TYPE_RSA3072_SHA384_GUID #language en-US "RSA3072_SHA384_GUID" +#string STR_CERT_TYPE_RSA4096_SHA512_GUID #language en-US "RSA4096_SHA512_GUID" #string STR_CERT_TYPE_PCKS7_GUID #language en-US "PKCS7_GUID" #string STR_CERT_TYPE_SHA1_GUID #language en-US "SHA1_GUID" #string STR_CERT_TYPE_SHA256_GUID #language en-US "SHA256_GUID" @@ -121,9 +123,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #string STR_CERT_TYPE_X509_SHA512_GUID #language en-US "X509_SHA512_GUID" #string STR_LIST_TYPE_RSA2048_SHA256 #language en-US "RSA2048_SHA256" +#string STR_LIST_TYPE_RSA3072_SHA384 #language en-US "RSA3072_SHA384" +#string STR_LIST_TYPE_RSA4096_SHA512 #language en-US "RSA4096_SHA512" #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 (#105296): https://edk2.groups.io/g/devel/message/105296 Mute This Topic: https://groups.io/mt/99124387/2558558 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [w.sh...@intel.com] -=-=-=-=-=-= -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#105741): https://edk2.groups.io/g/devel/message/105741 Mute This Topic: https://groups.io/mt/99124387/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-