};\r
\r
HASH_TABLE mHash[] = {\r
- { L"SHA1", 20, &mHashOidValue[0], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },\r
- { L"SHA224", 28, &mHashOidValue[5], 9, NULL, NULL, NULL, NULL },\r
- { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize,Sha256Init, Sha256Update, Sha256Final},\r
- { L"SHA384", 48, &mHashOidValue[23], 9, NULL, NULL, NULL, NULL },\r
- { L"SHA512", 64, &mHashOidValue[32], 9, NULL, NULL, NULL, NULL }\r
+ { L"SHA1", 20, &mHashOidValue[0], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },\r
+ { L"SHA224", 28, &mHashOidValue[5], 9, NULL, NULL, NULL, NULL },\r
+ { L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},\r
+ { L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},\r
+ { L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
};\r
\r
/**\r
\r
@param FileHandle Pointer to the file handle to read the PE/COFF image.\r
@param FileOffset Offset into the PE/COFF image to begin the read operation.\r
- @param ReadSize On input, the size in bytes of the requested read operation. \r
+ @param ReadSize On input, the size in bytes of the requested read operation.\r
On output, the number of bytes actually read.\r
@param Buffer Output buffer that contains the data read from the PE/COFF image.\r
- \r
- @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size \r
+\r
+ @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size\r
**/\r
EFI_STATUS\r
EFIAPI\r
UINTN EndPosition;\r
\r
if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) {\r
- return EFI_INVALID_PARAMETER; \r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
if (MAX_ADDRESS - FileOffset < *ReadSize) {\r
SectionHeader = NULL;\r
Status = FALSE;\r
\r
- if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) {\r
+ if ((HashAlg >= HASHALG_MAX)) {\r
return FALSE;\r
}\r
\r
//\r
ZeroMem (mImageDigest, MAX_DIGEST_SIZE);\r
\r
- if (HashAlg == HASHALG_SHA1) {\r
- mImageDigestSize = SHA1_DIGEST_SIZE;\r
- mCertType = gEfiCertSha1Guid;\r
- } else if (HashAlg == HASHALG_SHA256) {\r
- mImageDigestSize = SHA256_DIGEST_SIZE;\r
- mCertType = gEfiCertSha256Guid;\r
- } else {\r
+ switch (HashAlg) {\r
+ case HASHALG_SHA1:\r
+ mImageDigestSize = SHA1_DIGEST_SIZE;\r
+ mCertType = gEfiCertSha1Guid;\r
+ break;\r
+\r
+ case HASHALG_SHA256:\r
+ mImageDigestSize = SHA256_DIGEST_SIZE;\r
+ mCertType = gEfiCertSha256Guid;\r
+ break;\r
+\r
+ case HASHALG_SHA384:\r
+ mImageDigestSize = SHA384_DIGEST_SIZE;\r
+ mCertType = gEfiCertSha384Guid;\r
+ break;\r
+\r
+ case HASHALG_SHA512:\r
+ mImageDigestSize = SHA512_DIGEST_SIZE;\r
+ mCertType = gEfiCertSha512Guid;\r
+ break;\r
+\r
+ default:\r
return FALSE;\r
}\r
\r
//\r
if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
- // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
- // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
// Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
// then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
//\r
//\r
Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
}\r
- \r
+\r
//\r
// 3. Calculate the distance from the base of the image header to the image checksum address.\r
// 4. Hash the image header from its base to beginning of the image checksum.\r
if (!Status) {\r
goto Done;\r
}\r
- } \r
+ }\r
}\r
\r
//\r
\r
@param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.\r
@param[in] AuthDataSize Size of the Authenticode Signature in bytes.\r
- \r
+\r
@retval EFI_UNSUPPORTED Hash algorithm is not supported.\r
@retval EFI_SUCCESS Hash successfully.\r
\r
//\r
// Update new item's information.\r
//\r
- WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->Action, Action);\r
- WriteUnaligned32 ((UINT32 *) &ImageExeInfoEntry->InfoSize, (UINT32) NewImageExeInfoEntrySize);\r
+ WriteUnaligned32 ((UINT32 *) ImageExeInfoEntry, Action);\r
+ WriteUnaligned32 ((UINT32 *) ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32) NewImageExeInfoEntrySize);\r
\r
if (Name != NULL) {\r
- CopyMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), Name, NameStringLen);\r
+ CopyMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), Name, NameStringLen);\r
} else {\r
- ZeroMem ((UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32), sizeof (CHAR16));\r
+ ZeroMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), sizeof (CHAR16));\r
}\r
CopyMem (\r
- (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen,\r
+ (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen,\r
DevicePath,\r
DevicePathSize\r
);\r
if (Signature != NULL) {\r
CopyMem (\r
- (UINT8 *) &ImageExeInfoEntry->InfoSize + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
+ (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
Signature,\r
SignatureSize\r
);\r
}\r
}\r
\r
+/**\r
+ Check whether the hash of an given X.509 certificate is in forbidden database (DBX).\r
+\r
+ @param[in] Certificate Pointer to X.509 Certificate that is searched for.\r
+ @param[in] CertSize Size of X.509 Certificate.\r
+ @param[in] SignatureList Pointer to the Signature List in forbidden database.\r
+ @param[in] SignatureListSize Size of Signature List.\r
+ @param[out] RevocationTime Return the time that the certificate was revoked.\r
+\r
+ @return TRUE The certificate hash is found in the forbidden database.\r
+ @return FALSE The certificate hash is not found in the forbidden database.\r
+\r
+**/\r
+BOOLEAN\r
+IsCertHashFoundInDatabase (\r
+ IN UINT8 *Certificate,\r
+ IN UINTN CertSize,\r
+ IN EFI_SIGNATURE_LIST *SignatureList,\r
+ IN UINTN SignatureListSize,\r
+ OUT EFI_TIME *RevocationTime\r
+ )\r
+{\r
+ BOOLEAN IsFound;\r
+ EFI_STATUS Status;\r
+ EFI_SIGNATURE_LIST *DbxList;\r
+ UINTN DbxSize;\r
+ EFI_SIGNATURE_DATA *CertHash;\r
+ UINTN CertHashCount;\r
+ UINTN Index;\r
+ UINT32 HashAlg;\r
+ VOID *HashCtx;\r
+ UINT8 CertDigest[MAX_DIGEST_SIZE];\r
+ UINT8 *DbxCertHash;\r
+ UINTN SiglistHeaderSize;\r
+\r
+ IsFound = FALSE;\r
+ DbxList = SignatureList;\r
+ DbxSize = SignatureListSize;\r
+ HashCtx = NULL;\r
+ HashAlg = HASHALG_MAX;\r
+\r
+ ASSERT (RevocationTime != NULL);\r
+\r
+ while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
+ //\r
+ // Determine Hash Algorithm of Certificate in the forbidden database.\r
+ //\r
+ if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) {\r
+ HashAlg = HASHALG_SHA256;\r
+ } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) {\r
+ HashAlg = HASHALG_SHA384;\r
+ } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) {\r
+ HashAlg = HASHALG_SHA512;\r
+ } else {\r
+ DbxSize -= DbxList->SignatureListSize;\r
+ DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Calculate the hash value of current db certificate for comparision.\r
+ //\r
+ if (mHash[HashAlg].GetContextSize == NULL) {\r
+ goto Done;\r
+ }\r
+ ZeroMem (CertDigest, MAX_DIGEST_SIZE);\r
+ HashCtx = AllocatePool (mHash[HashAlg].GetContextSize ());\r
+ if (HashCtx == NULL) {\r
+ goto Done;\r
+ }\r
+ Status = mHash[HashAlg].HashInit (HashCtx);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+ Status = mHash[HashAlg].HashFinal (HashCtx, CertDigest);\r
+ if (!Status) {\r
+ goto Done;\r
+ }\r
+\r
+ SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize;\r
+ CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize);\r
+ CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize;\r
+ for (Index = 0; Index < CertHashCount; Index++) {\r
+ //\r
+ // Iterate each Signature Data Node within this CertList for verify.\r
+ //\r
+ DbxCertHash = CertHash->SignatureData;\r
+ if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) {\r
+ //\r
+ // Hash of Certificate is found in forbidden database.\r
+ //\r
+ IsFound = TRUE;\r
+\r
+ //\r
+ // Return the revocation time.\r
+ //\r
+ CopyMem (RevocationTime, (EFI_TIME *)(DbxCertHash + mHash[HashAlg].DigestLength), sizeof (EFI_TIME));\r
+ goto Done;\r
+ }\r
+ CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize);\r
+ }\r
+\r
+ DbxSize -= DbxList->SignatureListSize;\r
+ DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize);\r
+ }\r
+\r
+Done:\r
+ if (HashCtx != NULL) {\r
+ FreePool (HashCtx);\r
+ }\r
+\r
+ return IsFound;\r
+}\r
+\r
/**\r
Check whether signature is in specified database.\r
\r
UINTN Index;\r
UINTN CertCount;\r
BOOLEAN IsFound;\r
+\r
//\r
// Read signature database variable.\r
//\r
}\r
\r
/**\r
- Verify PKCS#7 SignedData using certificate found in Variable which formatted\r
- as EFI_SIGNATURE_LIST. The Variable may be PK, KEK, DB or DBX.\r
+ Check whether the timestamp is valid by comparing the signing time and the revocation time.\r
\r
- @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed image.\r
- @param[in] AuthDataSize Size of the Authenticode Signature in bytes.\r
- @param[in] VariableName Name of Variable to search for Certificate.\r
- @param[in] VendorGuid Variable vendor GUID.\r
+ @param SigningTime A pointer to the signing time.\r
+ @param RevocationTime A pointer to the revocation time.\r
\r
- @retval TRUE Image pass verification.\r
- @retval FALSE Image fail verification.\r
+ @retval TRUE The SigningTime is not later than the RevocationTime.\r
+ @retval FALSE The SigningTime is later than the RevocationTime.\r
\r
**/\r
BOOLEAN\r
-IsPkcsSignedDataVerifiedBySignatureList (\r
+IsValidSignatureByTimestamp (\r
+ IN EFI_TIME *SigningTime,\r
+ IN EFI_TIME *RevocationTime\r
+ )\r
+{\r
+ if (SigningTime->Year != RevocationTime->Year) {\r
+ return (BOOLEAN) (SigningTime->Year < RevocationTime->Year);\r
+ } else if (SigningTime->Month != RevocationTime->Month) {\r
+ return (BOOLEAN) (SigningTime->Month < RevocationTime->Month);\r
+ } else if (SigningTime->Day != RevocationTime->Day) {\r
+ return (BOOLEAN) (SigningTime->Day < RevocationTime->Day);\r
+ } else if (SigningTime->Hour != RevocationTime->Hour) {\r
+ return (BOOLEAN) (SigningTime->Hour < RevocationTime->Hour);\r
+ } else if (SigningTime->Minute != RevocationTime->Minute) {\r
+ return (BOOLEAN) (SigningTime->Minute < RevocationTime->Minute);\r
+ }\r
+\r
+ return (BOOLEAN) (SigningTime->Second <= RevocationTime->Second);\r
+}\r
+\r
+/**\r
+ Check if the given time value is zero.\r
+\r
+ @param[in] Time Pointer of a time value.\r
+\r
+ @retval TRUE The Time is Zero.\r
+ @retval FALSE The Time is not Zero.\r
+\r
+**/\r
+BOOLEAN\r
+IsTimeZero (\r
+ IN EFI_TIME *Time\r
+ )\r
+{\r
+ if ((Time->Year == 0) && (Time->Month == 0) && (Time->Day == 0) &&\r
+ (Time->Hour == 0) && (Time->Minute == 0) && (Time->Second == 0)) {\r
+ return TRUE;\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Check whether the timestamp signature is valid and the signing time is also earlier than \r
+ the revocation time.\r
+\r
+ @param[in] AuthData Pointer to the Authenticode signature retrieved from signed image.\r
+ @param[in] AuthDataSize Size of the Authenticode signature in bytes.\r
+ @param[in] RevocationTime The time that the certificate was revoked.\r
+\r
+ @retval TRUE Timestamp signature is valid and signing time is no later than the \r
+ revocation time.\r
+ @retval FALSE Timestamp signature is not valid or the signing time is later than the\r
+ revocation time.\r
+\r
+**/\r
+BOOLEAN\r
+PassTimestampCheck (\r
+ IN UINT8 *AuthData,\r
+ IN UINTN AuthDataSize,\r
+ IN EFI_TIME *RevocationTime\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN VerifyStatus;\r
+ EFI_SIGNATURE_LIST *CertList;\r
+ EFI_SIGNATURE_DATA *Cert;\r
+ UINT8 *DbtData;\r
+ UINTN DbtDataSize;\r
+ UINT8 *RootCert;\r
+ UINTN RootCertSize;\r
+ UINTN Index;\r
+ UINTN CertCount;\r
+ EFI_TIME SigningTime;\r
+\r
+ //\r
+ // Variable Initialization\r
+ //\r
+ VerifyStatus = FALSE;\r
+ DbtData = NULL;\r
+ CertList = NULL;\r
+ Cert = NULL;\r
+ RootCert = NULL;\r
+ RootCertSize = 0;\r
+\r
+ //\r
+ // If RevocationTime is zero, the certificate shall be considered to always be revoked.\r
+ //\r
+ if (IsTimeZero (RevocationTime)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // RevocationTime is non-zero, the certificate should be considered to be revoked from that time and onwards.\r
+ // Using the dbt to get the trusted TSA certificates.\r
+ //\r
+ DbtDataSize = 0;\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ DbtData = (UINT8 *) AllocateZeroPool (DbtDataSize);\r
+ if (DbtData == NULL) {\r
+ goto Done;\r
+ }\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, NULL, &DbtDataSize, (VOID *) DbtData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ CertList = (EFI_SIGNATURE_LIST *) DbtData;\r
+ while ((DbtDataSize > 0) && (DbtDataSize >= CertList->SignatureListSize)) {\r
+ if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+ for (Index = 0; Index < CertCount; Index++) {\r
+ //\r
+ // Iterate each Signature Data Node within this CertList for verify.\r
+ //\r
+ RootCert = Cert->SignatureData;\r
+ RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
+ //\r
+ // Get the signing time if the timestamp signature is valid.\r
+ //\r
+ if (ImageTimestampVerify (AuthData, AuthDataSize, RootCert, RootCertSize, &SigningTime)) {\r
+ //\r
+ // The signer signature is valid only when the signing time is earlier than revocation time.\r
+ //\r
+ if (IsValidSignatureByTimestamp (&SigningTime, RevocationTime)) {\r
+ VerifyStatus = TRUE;\r
+ goto Done;\r
+ }\r
+ }\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+ }\r
+ }\r
+ DbtDataSize -= CertList->SignatureListSize;\r
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+ }\r
+\r
+Done:\r
+ if (DbtData != NULL) {\r
+ FreePool (DbtData);\r
+ }\r
+\r
+ return VerifyStatus;\r
+}\r
+\r
+/**\r
+ Check whether the image signature is forbidden by the forbidden database (dbx).\r
+ The image is forbidden to load if any certificates for signing are revoked before signing time.\r
+\r
+ @param[in] AuthData Pointer to the Authenticode signature retrieved from the signed image.\r
+ @param[in] AuthDataSize Size of the Authenticode signature in bytes.\r
+\r
+ @retval TRUE Image is forbidden by dbx.\r
+ @retval FALSE Image is not forbidden by dbx.\r
+\r
+**/\r
+BOOLEAN\r
+IsForbiddenByDbx (\r
+ IN UINT8 *AuthData,\r
+ IN UINTN AuthDataSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN IsForbidden;\r
+ UINT8 *Data;\r
+ UINTN DataSize;\r
+ UINTN Index;\r
+ UINT8 *CertBuffer;\r
+ UINTN BufferLength;\r
+ UINT8 *TrustedCert;\r
+ UINTN TrustedCertLength;\r
+ UINT8 CertNumber;\r
+ UINT8 *CertPtr;\r
+ UINT8 *Cert;\r
+ UINTN CertSize;\r
+ EFI_TIME RevocationTime;\r
+\r
+ //\r
+ // Variable Initialization\r
+ //\r
+ IsForbidden = FALSE;\r
+ Data = NULL;\r
+ Cert = NULL;\r
+ CertBuffer = NULL;\r
+ BufferLength = 0;\r
+ TrustedCert = NULL;\r
+ TrustedCertLength = 0;\r
+\r
+ //\r
+ // The image will not be forbidden if dbx can't be got.\r
+ //\r
+ DataSize = 0;\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ Data = (UINT8 *) AllocateZeroPool (DataSize);\r
+ if (Data == NULL) {\r
+ return IsForbidden;\r
+ }\r
+\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return IsForbidden;\r
+ }\r
+\r
+ //\r
+ // Retrieve the certificate stack from AuthData\r
+ // The output CertStack format will be:\r
+ // UINT8 CertNumber;\r
+ // UINT32 Cert1Length;\r
+ // UINT8 Cert1[];\r
+ // UINT32 Cert2Length;\r
+ // UINT8 Cert2[];\r
+ // ...\r
+ // UINT32 CertnLength;\r
+ // UINT8 Certn[];\r
+ //\r
+ Pkcs7GetSigners (AuthData, AuthDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);\r
+ if (BufferLength == 0) {\r
+ IsForbidden = TRUE;\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Check if any certificates in AuthData is in the forbidden database.\r
+ //\r
+ CertNumber = (UINT8) (*CertBuffer);\r
+ CertPtr = CertBuffer + 1;\r
+ for (Index = 0; Index < CertNumber; Index++) {\r
+ CertSize = (UINTN) ReadUnaligned32 ((UINT32 *)CertPtr);\r
+ Cert = (UINT8 *)CertPtr + sizeof (UINT32);\r
+ if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, Cert, &gEfiCertX509Guid, CertSize)) {\r
+ //\r
+ // Raw certificate in dbx means the image signed by the certificate is forbidden.\r
+ //\r
+ IsForbidden = TRUE;\r
+ goto Done;\r
+ }\r
+\r
+ if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
+ //\r
+ // Check the timestamp signature and signing time to determine if the image can be trusted.\r
+ //\r
+ IsForbidden = TRUE;\r
+ if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {\r
+ IsForbidden = FALSE;\r
+ }\r
+ goto Done;\r
+ }\r
+\r
+ CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
+ }\r
+\r
+Done:\r
+ if (Data != NULL) {\r
+ FreePool (Data);\r
+ }\r
+\r
+ Pkcs7FreeSigners (CertBuffer);\r
+ Pkcs7FreeSigners (TrustedCert);\r
+\r
+ return IsForbidden;\r
+}\r
+\r
+/**\r
+ Check whether the image signature can be verified by the trusted certificates in DB database.\r
+\r
+ @param[in] AuthData Pointer to the Authenticode signature retrieved from signed image.\r
+ @param[in] AuthDataSize Size of the Authenticode signature in bytes.\r
+\r
+ @retval TRUE Image passed verification using certificate in db.\r
+ @retval FALSE Image didn't pass verification using certificate in db.\r
+\r
+**/\r
+BOOLEAN\r
+IsAllowedByDb (\r
IN UINT8 *AuthData,\r
- IN UINTN AuthDataSize,\r
- IN CHAR16 *VariableName,\r
- IN EFI_GUID *VendorGuid\r
+ IN UINTN AuthDataSize\r
)\r
{\r
EFI_STATUS Status;\r
VerifyStatus = FALSE;\r
\r
DataSize = 0;\r
- Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\r
if (Status == EFI_BUFFER_TOO_SMALL) {\r
Data = (UINT8 *) AllocateZeroPool (DataSize);\r
if (Data == NULL) {\r
return VerifyStatus;\r
}\r
\r
- Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, (VOID *) Data);\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, (VOID *) Data);\r
if (EFI_ERROR (Status)) {\r
goto Done;\r
}\r
CertList = (EFI_SIGNATURE_LIST *) Data;\r
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
- Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
- CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+ Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);\r
+ CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;\r
+\r
for (Index = 0; Index < CertCount; Index++) {\r
//\r
// Iterate each Signature Data Node within this CertList for verify.\r
//\r
- RootCert = Cert->SignatureData;\r
- RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
+ RootCert = Cert->SignatureData;\r
+ RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
\r
//\r
// Call AuthenticodeVerify library to Verify Authenticode struct.\r
mImageDigestSize\r
);\r
if (VerifyStatus) {\r
- SecureBootHook (VariableName, VendorGuid, CertList->SignatureSize, Cert);\r
+ SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
goto Done;\r
}\r
+\r
Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
}\r
}\r
+\r
DataSize -= CertList->SignatureListSize;\r
CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
}\r
}\r
\r
//\r
- // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION \r
+ // The policy QUERY_USER_ON_SECURITY_VIOLATION and ALLOW_EXECUTE_ON_SECURITY_VIOLATION\r
// violates the UEFI spec and has been removed.\r
//\r
ASSERT (Policy != QUERY_USER_ON_SECURITY_VIOLATION && Policy != ALLOW_EXECUTE_ON_SECURITY_VIOLATION);\r
\r
if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
- // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value \r
- // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the \r
+ // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
+ // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the\r
// Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
// then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
//\r
//\r
Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
}\r
- \r
+\r
if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
SecDataDir = (EFI_IMAGE_DATA_DIRECTORY *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY];\r
- } \r
+ }\r
} else {\r
//\r
// Use PE32+ offset.\r
//\r
if (SecDataDir == NULL || SecDataDir->Size == 0) {\r
//\r
- // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db", \r
+ // This image is not signed. The SHA256 hash value of the image must match a record in the security database "db",\r
// and not be reflected in the security data base "dbx".\r
//\r
if (!HashPeImage (HASHALG_SHA256)) {\r
}\r
\r
//\r
- // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7 \r
+ // Verify the signature of the image, multiple signatures are allowed as per PE/COFF Section 4.7\r
// "Attribute Certificate Table".\r
// The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.\r
//\r
for (OffSet = SecDataDir->VirtualAddress;\r
OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);\r
- OffSet += WinCertificate->dwLength, OffSet += ALIGN_SIZE (OffSet)) {\r
+ OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {\r
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);\r
if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||\r
(SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {\r
break;\r
}\r
- \r
+\r
//\r
// Verify the image's Authenticode signature, only DER-encoded PKCS#7 signed data is supported.\r
//\r
if (WinCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) {\r
//\r
- // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the \r
+ // The certificate is formatted as WIN_CERTIFICATE_EFI_PKCS which is described in the\r
// Authenticode specification.\r
//\r
PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) WinCertificate;\r
if (EFI_ERROR (Status)) {\r
continue;\r
}\r
- \r
+\r
//\r
// Check the digital signature against the revoked certificate in forbidden database (dbx).\r
//\r
- if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid)) {\r
+ if (IsForbiddenByDbx (AuthData, AuthDataSize)) {\r
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED;\r
VerifyStatus = EFI_ACCESS_DENIED;\r
break;\r
// Check the digital signature against the valid certificate in allowed database (db).\r
//\r
if (EFI_ERROR (VerifyStatus)) {\r
- if (IsPkcsSignedDataVerifiedBySignatureList (AuthData, AuthDataSize, EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid)) {\r
+ if (IsAllowedByDb (AuthData, AuthDataSize)) {\r
VerifyStatus = EFI_SUCCESS;\r
}\r
}\r
//\r
VerifyStatus = EFI_ACCESS_DENIED;\r
}\r
- \r
+\r
if (!EFI_ERROR (VerifyStatus)) {\r
return EFI_SUCCESS;\r
} else {\r
return ;\r
}\r
\r
- ImageExeInfoTable->NumberOfImages = 0; \r
+ ImageExeInfoTable->NumberOfImages = 0;\r
gBS->InstallConfigurationTable (&gEfiImageSecurityDatabaseGuid, (VOID *) ImageExeInfoTable);\r
\r
}\r
//\r
EfiCreateEventReadyToBootEx (\r
TPL_CALLBACK,\r
- OnReadyToBoot, \r
- NULL, \r
+ OnReadyToBoot,\r
+ NULL,\r
&Event\r
- ); \r
+ );\r
\r
return RegisterSecurity2Handler (\r
DxeImageVerificationHandler,\r