return (BOOLEAN) (FirstTime->Second <= SecondTime->Second);\r
}\r
\r
+/**\r
+ Calculate SHA256 digest of SignerCert CommonName + ToplevelCert tbsCertificate\r
+ SignerCert and ToplevelCert are inside the signer certificate chain.\r
+\r
+ @param[in] SignerCert A pointer to SignerCert data.\r
+ @param[in] SignerCertSize Length of SignerCert data.\r
+ @param[in] TopLevelCert A pointer to TopLevelCert data.\r
+ @param[in] TopLevelCertSize Length of TopLevelCert data.\r
+ @param[out] Sha256Digest Sha256 digest calculated.\r
+\r
+ @return EFI_ABORTED Digest process failed.\r
+ @return EFI_SUCCESS SHA256 Digest is succesfully calculated.\r
+\r
+**/\r
+EFI_STATUS\r
+CalculatePrivAuthVarSignChainSHA256Digest(\r
+ IN UINT8 *SignerCert,\r
+ IN UINTN SignerCertSize,\r
+ IN UINT8 *TopLevelCert,\r
+ IN UINTN TopLevelCertSize,\r
+ OUT UINT8 *Sha256Digest\r
+ )\r
+{\r
+ UINT8 *TbsCert;\r
+ UINTN TbsCertSize;\r
+ UINT8 CertCommonName[128];\r
+ UINTN CertCommonNameSize;\r
+ BOOLEAN CryptoStatus;\r
+ EFI_STATUS Status;\r
+\r
+ CertCommonNameSize = sizeof(CertCommonName);\r
+\r
+ //\r
+ // Get SignerCert CommonName\r
+ //\r
+ Status = X509GetCommonName(SignerCert, SignerCertSize, CertCommonName, &CertCommonNameSize);\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_INFO, "%a Get SignerCert CommonName failed with status %x\n", __FUNCTION__, Status));\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Get TopLevelCert tbsCertificate\r
+ //\r
+ if (!X509GetTBSCert(TopLevelCert, TopLevelCertSize, &TbsCert, &TbsCertSize)) {\r
+ DEBUG((DEBUG_INFO, "%a Get Top-level Cert tbsCertificate failed!\n", __FUNCTION__));\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // Digest SignerCert CN + TopLevelCert tbsCertificate\r
+ //\r
+ ZeroMem (Sha256Digest, SHA256_DIGEST_SIZE);\r
+ CryptoStatus = Sha256Init (mHashCtx);\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ //\r
+ // '\0' is forced in CertCommonName. No overflow issue\r
+ //\r
+ CryptoStatus = Sha256Update (mHashCtx, CertCommonName, AsciiStrLen((CHAR8 *)CertCommonName));\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ CryptoStatus = Sha256Update (mHashCtx, TbsCert, TbsCertSize);\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ CryptoStatus = Sha256Final (mHashCtx, Sha256Digest);\r
+ if (!CryptoStatus) {\r
+ return EFI_ABORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Find matching signer's certificates for common authenticated variable\r
by corresponding VariableName and VendorGuid from "certdb" or "certdbv".\r
/**\r
Insert signer's certificates for common authenticated variable with VariableName\r
and VendorGuid in AUTH_CERT_DB_DATA to "certdb" or "certdbv" according to\r
- time based authenticated variable attributes.\r
+ time based authenticated variable attributes. CertData is the SHA256 digest of\r
+ SignerCert CommonName + TopLevelCert tbsCertificate.\r
\r
- @param[in] VariableName Name of authenticated Variable.\r
- @param[in] VendorGuid Vendor GUID of authenticated Variable.\r
- @param[in] Attributes Attributes of authenticated variable.\r
- @param[in] CertData Pointer to signer's certificates.\r
- @param[in] CertDataSize Length of CertData in bytes.\r
+ @param[in] VariableName Name of authenticated Variable.\r
+ @param[in] VendorGuid Vendor GUID of authenticated Variable.\r
+ @param[in] Attributes Attributes of authenticated variable.\r
+ @param[in] SignerCert Signer certificate data.\r
+ @param[in] SignerCertSize Length of signer certificate.\r
+ @param[in] TopLevelCert Top-level certificate data.\r
+ @param[in] TopLevelCertSize Length of top-level certificate.\r
\r
@retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
@retval EFI_ACCESS_DENIED An AUTH_CERT_DB_DATA entry with same VariableName\r
IN CHAR16 *VariableName,\r
IN EFI_GUID *VendorGuid,\r
IN UINT32 Attributes,\r
- IN UINT8 *CertData,\r
- IN UINTN CertDataSize\r
+ IN UINT8 *SignerCert,\r
+ IN UINTN SignerCertSize,\r
+ IN UINT8 *TopLevelCert,\r
+ IN UINTN TopLevelCertSize\r
)\r
{\r
EFI_STATUS Status;\r
UINT32 NewCertDbSize;\r
UINT32 CertNodeSize;\r
UINT32 NameSize;\r
+ UINT32 CertDataSize;\r
AUTH_CERT_DB_DATA *Ptr;\r
CHAR16 *DbName;\r
+ UINT8 Sha256Digest[SHA256_DIGEST_SIZE];\r
\r
- if ((VariableName == NULL) || (VendorGuid == NULL) || (CertData == NULL)) {\r
+ if ((VariableName == NULL) || (VendorGuid == NULL) || (SignerCert == NULL) ||(TopLevelCert == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
// Construct new data content of variable "certdb" or "certdbv".\r
//\r
NameSize = (UINT32) StrLen (VariableName);\r
+ CertDataSize = sizeof(Sha256Digest);\r
CertNodeSize = sizeof (AUTH_CERT_DB_DATA) + (UINT32) CertDataSize + NameSize * sizeof (CHAR16);\r
NewCertDbSize = (UINT32) DataSize + CertNodeSize;\r
if (NewCertDbSize > mMaxCertDbSize) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+\r
+ Status = CalculatePrivAuthVarSignChainSHA256Digest(\r
+ SignerCert,\r
+ SignerCertSize,\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
+ Sha256Digest\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
NewCertDb = (UINT8*) mCertDbStore;\r
\r
//\r
\r
CopyMem (\r
(UINT8 *) Ptr + sizeof (AUTH_CERT_DB_DATA) + NameSize * sizeof (CHAR16),\r
- CertData,\r
+ Sha256Digest,\r
CertDataSize\r
);\r
\r
UINTN NewDataSize;\r
UINT8 *Buffer;\r
UINTN Length;\r
- UINT8 *RootCert;\r
- UINTN RootCertSize;\r
+ UINT8 *TopLevelCert;\r
+ UINTN TopLevelCertSize;\r
+ UINT8 *TrustedCert;\r
+ UINTN TrustedCertSize;\r
UINT8 *SignerCerts;\r
UINTN CertStackSize;\r
UINT8 *CertsInCertDb;\r
UINT32 CertsSizeinDb;\r
+ UINT8 Sha256Digest[SHA256_DIGEST_SIZE];\r
\r
+ //\r
+ // 1. TopLevelCert is the top-level issuer certificate in signature Signer Cert Chain\r
+ // 2. TrustedCert is the certificate which firmware trusts. It could be saved in protected\r
+ // storage or PK payload on PK init\r
+ //\r
VerifyStatus = FALSE;\r
CertData = NULL;\r
NewData = NULL;\r
Attr = Attributes;\r
SignerCerts = NULL;\r
- RootCert = NULL;\r
+ TopLevelCert = NULL;\r
CertsInCertDb = NULL;\r
\r
//\r
SigDataSize,\r
&SignerCerts,\r
&CertStackSize,\r
- &RootCert,\r
- &RootCertSize\r
+ &TopLevelCert,\r
+ &TopLevelCertSize\r
);\r
if (!VerifyStatus) {\r
goto Exit;\r
}\r
CertList = (EFI_SIGNATURE_LIST *) Data;\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- if ((RootCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
- (CompareMem (Cert->SignatureData, RootCert, RootCertSize) != 0)) {\r
+ if ((TopLevelCertSize != (CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1))) ||\r
+ (CompareMem (Cert->SignatureData, TopLevelCert, TopLevelCertSize) != 0)) {\r
VerifyStatus = FALSE;\r
goto Exit;\r
}\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
NewData,\r
NewDataSize\r
);\r
//\r
// Iterate each Signature Data Node within this CertList for a verify\r
//\r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
+ TrustedCert = Cert->SignatureData;\r
+ TrustedCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
\r
//\r
// Verify Pkcs7 SignedData via Pkcs7Verify library.\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TrustedCert,\r
+ TrustedCertSize,\r
NewData,\r
NewDataSize\r
);\r
SigDataSize,\r
&SignerCerts,\r
&CertStackSize,\r
- &RootCert,\r
- &RootCertSize\r
+ &TopLevelCert,\r
+ &TopLevelCertSize\r
);\r
if (!VerifyStatus) {\r
goto Exit;\r
goto Exit;\r
}\r
\r
- if ((CertStackSize != CertsSizeinDb) ||\r
- (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
- goto Exit;\r
+ if (CertsSizeinDb == SHA256_DIGEST_SIZE) {\r
+ //\r
+ // Check hash of signer cert CommonName + Top-level issuer tbsCertificate against data in CertDb\r
+ //\r
+ Status = CalculatePrivAuthVarSignChainSHA256Digest(\r
+ SignerCerts + sizeof(UINT8) + sizeof(UINT32),\r
+ ReadUnaligned32 ((UINT32 *)(SignerCerts + sizeof(UINT8))),\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
+ Sha256Digest\r
+ );\r
+ if (EFI_ERROR(Status) || CompareMem (Sha256Digest, CertsInCertDb, CertsSizeinDb) != 0){\r
+ goto Exit;\r
+ }\r
+ } else {\r
+ //\r
+ // Keep backward compatible with previous solution which saves whole signer certs stack in CertDb\r
+ //\r
+ if ((CertStackSize != CertsSizeinDb) ||\r
+ (CompareMem (SignerCerts, CertsInCertDb, CertsSizeinDb) != 0)) {\r
+ goto Exit;\r
+ }\r
}\r
}\r
\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TopLevelCert,\r
+ TopLevelCertSize,\r
NewData,\r
NewDataSize\r
);\r
\r
if ((OrgTimeStamp == NULL) && (PayloadSize != 0)) {\r
//\r
- // Insert signer's certificates when adding a new common authenticated variable.\r
+ // When adding a new common authenticated variable, always save Hash of cn of signer cert + tbsCertificate of Top-level issuer\r
//\r
- Status = InsertCertsToDb (VariableName, VendorGuid, Attributes, SignerCerts, CertStackSize);\r
+ Status = InsertCertsToDb (\r
+ VariableName,\r
+ VendorGuid,\r
+ Attributes,\r
+ SignerCerts + sizeof(UINT8) + sizeof(UINT32),\r
+ ReadUnaligned32 ((UINT32 *)(SignerCerts + sizeof(UINT8))),\r
+ TopLevelCert,\r
+ TopLevelCertSize\r
+ );\r
if (EFI_ERROR (Status)) {\r
VerifyStatus = FALSE;\r
goto Exit;\r
} else if (AuthVarType == AuthVarTypePayload) {\r
CertList = (EFI_SIGNATURE_LIST *) PayloadPtr;\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
+ TrustedCert = Cert->SignatureData;\r
+ TrustedCertSize = CertList->SignatureSize - (sizeof (EFI_SIGNATURE_DATA) - 1);\r
//\r
// Verify Pkcs7 SignedData via Pkcs7Verify library.\r
//\r
VerifyStatus = Pkcs7Verify (\r
SigData,\r
SigDataSize,\r
- RootCert,\r
- RootCertSize,\r
+ TrustedCert,\r
+ TrustedCertSize,\r
NewData,\r
NewDataSize\r
);\r
Exit:\r
\r
if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {\r
- Pkcs7FreeSigners (RootCert);\r
+ Pkcs7FreeSigners (TopLevelCert);\r
Pkcs7FreeSigners (SignerCerts);\r
}\r
\r