/** @file\r
- Implement image verification services for secure boot service in UEFI2.3.1.\r
+ Implement image verification services for secure boot service\r
\r
Caution: This file requires additional review when modified.\r
This library will have external input - PE/COFF image.\r
DxeImageVerificationHandler(), HashPeImageByType(), HashPeImage() function will accept\r
untrusted PE/COFF image and validate its data structure within this image buffer before use.\r
\r
-Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
{ L"SHA512", 64, &mHashOidValue[32], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final}\r
};\r
\r
+EFI_STRING mHashTypeStr;\r
+\r
/**\r
SecureBoot Hook for processing image verification.\r
\r
}\r
\r
/**\r
- Caculate hash of Pe/Coff image based on the authenticode image hashing in\r
+ Calculate hash of Pe/Coff image based on the authenticode image hashing in\r
PE/COFF Specification 8.0 Appendix A\r
\r
Caution: This function may receive untrusted input.\r
PE/COFF image is external input, so this function will validate its data structure\r
within this image buffer before use.\r
\r
+ Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in\r
+ its caller function DxeImageVerificationHandler().\r
+\r
@param[in] HashAlg Hash algorithm type.\r
\r
@retval TRUE Successfully hash image.\r
)\r
{\r
BOOLEAN Status;\r
- UINT16 Magic;\r
EFI_IMAGE_SECTION_HEADER *Section;\r
VOID *HashCtx;\r
UINTN CtxSize;\r
return FALSE;\r
}\r
\r
+ mHashTypeStr = mHash[HashAlg].Name;\r
CtxSize = mHash[HashAlg].GetContextSize();\r
\r
HashCtx = AllocatePool (CtxSize);\r
// Measuring PE/COFF Image Header;\r
// But CheckSum field and SECURITY data directory (certificate) are excluded\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
- // 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
- Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
- } else {\r
- //\r
- // Get the magic value from the PE/COFF Optional Header\r
- //\r
- Magic = mNtHeader.Pe32->OptionalHeader.Magic;\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
//\r
HashBase = mImageBase;\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
- HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase);\r
+ HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
NumberOfRvaAndSizes = mNtHeader.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
- } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+ } else if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
//\r
// Use PE32+ offset.\r
//\r
- HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase);\r
+ HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase;\r
NumberOfRvaAndSizes = mNtHeader.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
} else {\r
//\r
// 6. Since there is no Cert Directory in optional header, hash everything\r
// from the end of the checksum to the end of image header.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
} else {\r
//\r
// Use PE32+ offset.\r
//\r
HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
}\r
\r
if (HashSize != 0) {\r
//\r
// 7. Hash everything from the end of the checksum to the start of the Cert Directory.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+ HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
} else {\r
//\r
// Use PE32+ offset.\r
//\r
HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32);\r
- HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase);\r
+ HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase;\r
}\r
\r
if (HashSize != 0) {\r
// 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.)\r
// 9. Hash everything from the end of the Cert Directory to the end of image header.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset\r
//\r
HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
- HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+ HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
} else {\r
//\r
// Use PE32+ offset.\r
//\r
HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1];\r
- HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) (HashBase - mImageBase);\r
+ HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) HashBase - (UINTN) mImageBase);\r
}\r
\r
if (HashSize != 0) {\r
//\r
// 10. Set the SUM_OF_BYTES_HASHED to the size of the header.\r
//\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_SECURITY) {\r
CertSize = 0;\r
} else {\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
}\r
\r
/**\r
- Recognize the Hash algorithm in PE/COFF Authenticode and caculate hash of\r
+ Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of\r
Pe/Coff image based on the authenticode image hashing in PE/COFF Specification\r
8.0 Appendix A\r
\r
UINTN NewImageExeInfoEntrySize;\r
UINTN NameStringLen;\r
UINTN DevicePathSize;\r
+ CHAR16 *NameStr;\r
\r
ImageExeInfoTable = NULL;\r
NewImageExeInfoTable = NULL;\r
ImageExeInfoEntry = NULL;\r
NameStringLen = 0;\r
+ NameStr = NULL;\r
\r
if (DevicePath == NULL) {\r
return ;\r
if (ImageExeInfoTable != NULL) {\r
//\r
// The table has been found!\r
- // We must enlarge the table to accomodate the new exe info entry.\r
+ // We must enlarge the table to accommodate the new exe info entry.\r
//\r
ImageExeInfoTableSize = GetImageExeInfoTableSize (ImageExeInfoTable);\r
} else {\r
}\r
\r
DevicePathSize = GetDevicePathSize (DevicePath);\r
- NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) - sizeof (EFI_SIGNATURE_LIST) + NameStringLen + DevicePathSize + SignatureSize;\r
+\r
+ //\r
+ // Signature size can be odd. Pad after signature to ensure next EXECUTION_INFO entry align\r
+ //\r
+ NewImageExeInfoEntrySize = sizeof (EFI_IMAGE_EXECUTION_INFO) + NameStringLen + DevicePathSize + SignatureSize;\r
+\r
NewImageExeInfoTable = (EFI_IMAGE_EXECUTION_INFO_TABLE *) AllocateRuntimePool (ImageExeInfoTableSize + NewImageExeInfoEntrySize);\r
if (NewImageExeInfoTable == NULL) {\r
return ;\r
WriteUnaligned32 ((UINT32 *) ImageExeInfoEntry, Action);\r
WriteUnaligned32 ((UINT32 *) ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION)), (UINT32) NewImageExeInfoEntrySize);\r
\r
+ NameStr = (CHAR16 *)(ImageExeInfoEntry + 1);\r
if (Name != NULL) {\r
- CopyMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), Name, NameStringLen);\r
+ CopyMem ((UINT8 *) NameStr, Name, NameStringLen);\r
} else {\r
- ZeroMem ((UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32), sizeof (CHAR16));\r
+ ZeroMem ((UINT8 *) NameStr, sizeof (CHAR16));\r
}\r
+\r
CopyMem (\r
- (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen,\r
+ (UINT8 *) NameStr + NameStringLen,\r
DevicePath,\r
DevicePathSize\r
);\r
if (Signature != NULL) {\r
CopyMem (\r
- (UINT8 *) ImageExeInfoEntry + sizeof (EFI_IMAGE_EXECUTION_ACTION) + sizeof (UINT32) + NameStringLen + DevicePathSize,\r
+ (UINT8 *) NameStr + NameStringLen + DevicePathSize,\r
Signature,\r
SignatureSize\r
);\r
)\r
{\r
BOOLEAN IsFound;\r
- EFI_STATUS Status;\r
+ BOOLEAN Status;\r
EFI_SIGNATURE_LIST *DbxList;\r
UINTN DbxSize;\r
EFI_SIGNATURE_DATA *CertHash;\r
UINT8 CertDigest[MAX_DIGEST_SIZE];\r
UINT8 *DbxCertHash;\r
UINTN SiglistHeaderSize;\r
+ UINT8 *TBSCert;\r
+ UINTN TBSCertSize;\r
\r
IsFound = FALSE;\r
DbxList = SignatureList;\r
HashCtx = NULL;\r
HashAlg = HASHALG_MAX;\r
\r
- ASSERT (RevocationTime != NULL);\r
- ASSERT (DbxList != NULL);\r
+ if ((RevocationTime == NULL) || (DbxList == NULL)) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Retrieve the TBSCertificate from the X.509 Certificate.\r
+ //\r
+ if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {\r
+ return FALSE;\r
+ }\r
\r
while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) {\r
//\r
}\r
\r
//\r
- // Calculate the hash value of current db certificate for comparision.\r
+ // Calculate the hash value of current TBSCertificate for comparision.\r
//\r
if (mHash[HashAlg].GetContextSize == NULL) {\r
goto Done;\r
if (!Status) {\r
goto Done;\r
}\r
- Status = mHash[HashAlg].HashUpdate (HashCtx, Certificate, CertSize);\r
+ Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize);\r
if (!Status) {\r
goto Done;\r
}\r
\r
@param[in] VariableName Name of database variable that is searched in.\r
@param[in] Signature Pointer to signature that is searched for.\r
- @param[in] CertType Pointer to hash algrithom.\r
+ @param[in] CertType Pointer to hash algorithm.\r
@param[in] SignatureSize Size of Signature.\r
\r
@return TRUE Found the signature in the variable database.\r
goto Done;\r
}\r
//\r
- // Enumerate all signature data in SigDB to check if executable's signature exists.\r
+ // Enumerate all signature data in SigDB to check if signature exists for executable.\r
//\r
CertList = (EFI_SIGNATURE_LIST *) Data;\r
while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) {\r
// Find the signature in database.\r
//\r
IsFound = TRUE;\r
- SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+ //\r
+ // Entries in UEFI_IMAGE_SECURITY_DATABASE that are used to validate image should be measured\r
+ //\r
+ if (StrCmp(VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) {\r
+ SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+ }\r
break;\r
}\r
\r
}\r
\r
/**\r
- Check whether the timestamp signature is valid and the signing time is also earlier than \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
+ @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
BOOLEAN IsForbidden;\r
UINT8 *Data;\r
UINTN DataSize;\r
+ EFI_SIGNATURE_LIST *CertList;\r
+ UINTN CertListSize;\r
+ EFI_SIGNATURE_DATA *CertData;\r
+ UINT8 *RootCert;\r
+ UINTN RootCertSize;\r
+ UINTN CertCount;\r
UINTN Index;\r
UINT8 *CertBuffer;\r
UINTN BufferLength;\r
UINT8 *Cert;\r
UINTN CertSize;\r
EFI_TIME RevocationTime;\r
-\r
//\r
// Variable Initialization\r
//\r
IsForbidden = FALSE;\r
Data = NULL;\r
+ CertList = NULL;\r
+ CertData = NULL;\r
+ RootCert = NULL;\r
+ RootCertSize = 0;\r
Cert = NULL;\r
CertBuffer = NULL;\r
BufferLength = 0;\r
return IsForbidden;\r
}\r
\r
+ //\r
+ // Verify image signature with RAW X509 certificates in DBX database.\r
+ // If passed, the image will be forbidden.\r
+ //\r
+ CertList = (EFI_SIGNATURE_LIST *) Data;\r
+ CertListSize = DataSize;\r
+ while ((CertListSize > 0) && (CertListSize >= CertList->SignatureListSize)) {\r
+ if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {\r
+ CertData = (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 = CertData->SignatureData;\r
+ RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
+\r
+ //\r
+ // Call AuthenticodeVerify library to Verify Authenticode struct.\r
+ //\r
+ IsForbidden = AuthenticodeVerify (\r
+ AuthData,\r
+ AuthDataSize,\r
+ RootCert,\r
+ RootCertSize,\r
+ mImageDigest,\r
+ mImageDigestSize\r
+ );\r
+ if (IsForbidden) {\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is forbidden by DBX.\n"));\r
+ goto Done;\r
+ }\r
+\r
+ CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
+ }\r
+ }\r
+\r
+ CertListSize -= CertList->SignatureListSize;\r
+ CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);\r
+ }\r
+\r
+ //\r
+ // Check X.509 Certificate Hash & Possible Timestamp.\r
+ //\r
+\r
//\r
// Retrieve the certificate stack from AuthData\r
// The output CertStack format will be:\r
}\r
\r
//\r
- // Check if any certificates in AuthData is in the forbidden database.\r
+ // Check if any hash of certificates embedded 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
+ // Advance CertPtr to the next cert in image signer's cert list\r
+ //\r
+ CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
\r
if (IsCertHashFoundInDatabase (Cert, CertSize, (EFI_SIGNATURE_LIST *)Data, DataSize, &RevocationTime)) {\r
//\r
IsForbidden = TRUE;\r
if (PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime)) {\r
IsForbidden = FALSE;\r
+ //\r
+ // Pass DBT check. Continue to check other certs in image signer's cert list against DBX, DBT\r
+ //\r
+ continue;\r
}\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature failed the timestamp check.\n"));\r
goto Done;\r
}\r
\r
- CertPtr = CertPtr + sizeof (UINT32) + CertSize;\r
}\r
\r
Done:\r
return IsForbidden;\r
}\r
\r
+\r
/**\r
Check whether the image signature can be verified by the trusted certificates in DB database.\r
\r
EFI_STATUS Status;\r
BOOLEAN VerifyStatus;\r
EFI_SIGNATURE_LIST *CertList;\r
- EFI_SIGNATURE_DATA *Cert;\r
+ EFI_SIGNATURE_DATA *CertData;\r
UINTN DataSize;\r
UINT8 *Data;\r
UINT8 *RootCert;\r
UINTN RootCertSize;\r
UINTN Index;\r
UINTN CertCount;\r
+ UINTN DbxDataSize;\r
+ UINT8 *DbxData;\r
+ EFI_TIME RevocationTime;\r
\r
- Data = NULL;\r
- CertList = NULL;\r
- Cert = NULL;\r
- RootCert = NULL;\r
- RootCertSize = 0;\r
- VerifyStatus = FALSE;\r
+ Data = NULL;\r
+ CertList = NULL;\r
+ CertData = NULL;\r
+ RootCert = NULL;\r
+ DbxData = NULL;\r
+ RootCertSize = 0;\r
+ VerifyStatus = FALSE;\r
\r
DataSize = 0;\r
Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL);\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
+ CertData = (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
+ RootCert = CertData->SignatureData;\r
RootCertSize = CertList->SignatureSize - sizeof (EFI_GUID);\r
\r
//\r
mImageDigestSize\r
);\r
if (VerifyStatus) {\r
- SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert);\r
+ //\r
+ // Here We still need to check if this RootCert's Hash is revoked\r
+ //\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ goto Done;\r
+ }\r
+ DbxData = (UINT8 *) AllocateZeroPool (DbxDataSize);\r
+ if (DbxData == NULL) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DbxDataSize, (VOID *) DbxData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ if (IsCertHashFoundInDatabase (RootCert, RootCertSize, (EFI_SIGNATURE_LIST *)DbxData, DbxDataSize, &RevocationTime)) {\r
+ //\r
+ // Check the timestamp signature and signing time to determine if the RootCert can be trusted.\r
+ //\r
+ VerifyStatus = PassTimestampCheck (AuthData, AuthDataSize, &RevocationTime);\r
+ if (!VerifyStatus) {\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed and signature is accepted by DB, but its root cert failed the timestamp check.\n"));\r
+ }\r
+ }\r
+\r
goto Done;\r
}\r
\r
- Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);\r
+ CertData = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertData + CertList->SignatureSize);\r
}\r
}\r
\r
}\r
\r
Done:\r
+\r
+ if (VerifyStatus) {\r
+ SecureBootHook (EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, CertData);\r
+ }\r
+\r
if (Data != NULL) {\r
FreePool (Data);\r
}\r
+ if (DbxData != NULL) {\r
+ FreePool (DbxData);\r
+ }\r
\r
return VerifyStatus;\r
}\r
)\r
{\r
EFI_STATUS Status;\r
- UINT16 Magic;\r
EFI_IMAGE_DOS_HEADER *DosHdr;\r
EFI_STATUS VerifyStatus;\r
EFI_SIGNATURE_LIST *SignatureList;\r
Status = EFI_ACCESS_DENIED;\r
VerifyStatus = EFI_ACCESS_DENIED;\r
\r
+\r
//\r
// Check the image type and get policy setting.\r
//\r
}\r
\r
//\r
- // Skip verification if SecureBoot is disabled.\r
+ // Skip verification if SecureBoot is disabled but not AuditMode\r
//\r
if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {\r
FreePool (SecureBoot);\r
//\r
// The information can't be got from the invalid PeImage\r
//\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: PeImage invalid. Cannot retrieve image information.\n"));\r
goto Done;\r
}\r
\r
//\r
// It is not a valid Pe/Coff file.\r
//\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Not a valid PE/COFF image.\n"));\r
goto Done;\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
- // 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
- Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
- } else {\r
- //\r
- // Get the magic value from the PE/COFF Optional Header\r
- //\r
- Magic = mNtHeader.Pe32->OptionalHeader.Magic;\r
- }\r
-\r
- if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+ if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
// Use PE32 offset.\r
//\r
// and not be reflected in the security data base "dbx".\r
//\r
if (!HashPeImage (HASHALG_SHA256)) {\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Failed to hash this image using %s.\n", mHashTypeStr));\r
goto Done;\r
}\r
\r
//\r
// Image Hash is in forbidden database (DBX).\r
//\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is forbidden by DBX.\n", mHashTypeStr));\r
goto Done;\r
}\r
\r
//\r
// Image Hash is not found in both forbidden and allowed database.\r
//\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is not signed and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));\r
goto Done;\r
}\r
\r
//\r
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, mImageDigest, &mCertType, mImageDigestSize)) {\r
Action = EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND;\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but %s hash of image is found in DBX.\n", mHashTypeStr));\r
VerifyStatus = EFI_ACCESS_DENIED;\r
break;\r
} else if (EFI_ERROR (VerifyStatus)) {\r
if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE, mImageDigest, &mCertType, mImageDigestSize)) {\r
VerifyStatus = EFI_SUCCESS;\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "DxeImageVerificationLib: Image is signed but signature is not allowed by DB and %s hash of image is not found in DB/DBX.\n", mHashTypeStr));\r
}\r
}\r
}\r
\r
if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {\r
//\r
- // The Size in Certificate Table or the attribute certicate table is corrupted.\r
+ // The Size in Certificate Table or the attribute certificate table is corrupted.\r
//\r
VerifyStatus = EFI_ACCESS_DENIED;\r
}\r
Status = EFI_ACCESS_DENIED;\r
if (Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FAILED || Action == EFI_IMAGE_EXECUTION_AUTH_SIG_FOUND) {\r
//\r
- // Get image hash value as executable's signature.\r
+ // Get image hash value as signature of executable.\r
//\r
SignatureListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize;\r
SignatureList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SignatureListSize);\r
}\r
SignatureList->SignatureHeaderSize = 0;\r
SignatureList->SignatureListSize = (UINT32) SignatureListSize;\r
- SignatureList->SignatureSize = (UINT32) mImageDigestSize;\r
+ SignatureList->SignatureSize = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + mImageDigestSize);\r
CopyMem (&SignatureList->SignatureType, &mCertType, sizeof (EFI_GUID));\r
Signature = (EFI_SIGNATURE_DATA *) ((UINT8 *) SignatureList + sizeof (EFI_SIGNATURE_LIST));\r
CopyMem (Signature->SignatureData, mImageDigest, mImageDigestSize);\r