From c1d932429ef9700a2da64452546be14e92468b07 Mon Sep 17 00:00:00 2001 From: jyao1 Date: Wed, 18 Sep 2013 05:31:18 +0000 Subject: Add TPM2 implementation. signed off by: jiewen.yao@intel.com reviewed by: guo.dong@intel.com git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@14687 6f19259b-4bc3-4df7-8a09-765794883524 --- .../DxeImageVerificationLib.c | 21 ++ .../DxeImageVerificationLib.inf | 2 + .../Library/DxeImageVerificationLib/Measurement.c | 322 +++++++++++++++++++++ 3 files changed, 345 insertions(+) create mode 100644 SecurityPkg/Library/DxeImageVerificationLib/Measurement.c (limited to 'SecurityPkg/Library/DxeImageVerificationLib') diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 2458ee2ae1..8860daeafa 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -71,6 +71,25 @@ HASH_TABLE mHash[] = { { L"SHA512", 64, &mHashOidValue[32], 9, NULL, NULL, NULL, NULL } }; +/** + SecureBoot Hook for processing image verification. + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] Data Data pointer. + +**/ +VOID +EFIAPI +SecureBootHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINTN DataSize, + IN VOID *Data + ); + /** Reads contents of a PE/COFF image in memory buffer. @@ -846,6 +865,7 @@ IsSignatureFoundInDatabase ( // Find the signature in database. // IsFound = TRUE; + SecureBootHook (VariableName, &gEfiImageSecurityDatabaseGuid, CertList->SignatureSize, Cert); break; } @@ -948,6 +968,7 @@ IsPkcsSignedDataVerifiedBySignatureList ( mImageDigestSize ); if (VerifyStatus) { + SecureBootHook (VariableName, VendorGuid, CertList->SignatureSize, Cert); goto Done; } Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize); diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf index 0c6ab968f0..0e6a5d1ce6 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf @@ -35,6 +35,7 @@ [Sources] DxeImageVerificationLib.c DxeImageVerificationLib.h + Measurement.c [Packages] MdePkg/MdePkg.dec @@ -54,6 +55,7 @@ BaseCryptLib SecurityManagementLib PeCoffLib + TpmMeasurementLib [Protocols] gEfiFirmwareVolume2ProtocolGuid diff --git a/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c b/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c new file mode 100644 index 0000000000..2213423c33 --- /dev/null +++ b/SecurityPkg/Library/DxeImageVerificationLib/Measurement.c @@ -0,0 +1,322 @@ +/** @file + Measure TrEE required variable. + +Copyright (c) 2013, Intel Corporation. All rights reserved.
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + CHAR16 *VariableName; + EFI_GUID *VendorGuid; +} VARIABLE_TYPE; + +typedef struct { + CHAR16 *VariableName; + EFI_GUID *VendorGuid; + VOID *Data; + UINTN Size; +} VARIABLE_RECORD; + +#define MEASURED_AUTHORITY_COUNT_MAX 0x100 + +UINTN mMeasuredAuthorityCount = 0; +UINTN mMeasuredAuthorityCountMax = 0; +VARIABLE_RECORD *mMeasuredAuthorityList = NULL; + +VARIABLE_TYPE mVariableType[] = { + {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid}, +}; + +/** + This function will check if VarName should be recorded and return the address of VarName if it is needed. + + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + + @return the address of VarName. +**/ +CHAR16 * +AssignVarName ( + IN CHAR16 *VarName + ) +{ + UINTN Index; + + for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { + if (StrCmp (VarName, mVariableType[Index].VariableName) == 0) { + return mVariableType[Index].VariableName; + } + } + + return NULL; +} + +/** + This function will check if VendorGuid should be recorded and return the address of VendorGuid if it is needed. + + @param[in] VendorGuid A unique identifier for the vendor. + + @return the address of VendorGuid. +**/ +EFI_GUID * +AssignVendorGuid ( + IN EFI_GUID *VendorGuid + ) +{ + UINTN Index; + + for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { + if (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)) { + return mVariableType[Index].VendorGuid; + } + } + + return NULL; +} + +/** + This function will add variable information to MeasuredAuthorityList. + + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] VarData The content of the variable data. + @param[in] VarSize The size of the variable data. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. +**/ +EFI_STATUS +AddDataMeasured ( + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN Size + ) +{ + VARIABLE_RECORD *NewMeasuredAuthorityList; + + ASSERT (mMeasuredAuthorityCount <= mMeasuredAuthorityCountMax); + if (mMeasuredAuthorityCount == mMeasuredAuthorityCountMax) { + // + // Need enlarge + // + NewMeasuredAuthorityList = AllocateZeroPool (sizeof(VARIABLE_RECORD) * (mMeasuredAuthorityCountMax + MEASURED_AUTHORITY_COUNT_MAX)); + if (NewMeasuredAuthorityList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + if (mMeasuredAuthorityList != NULL) { + CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof(VARIABLE_RECORD) * mMeasuredAuthorityCount); + FreePool (mMeasuredAuthorityList); + } + mMeasuredAuthorityList = NewMeasuredAuthorityList; + mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX; + } + + // + // Add new entry + // + mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName); + mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid = AssignVendorGuid (VendorGuid); + mMeasuredAuthorityList[mMeasuredAuthorityCount].Size = Size; + mMeasuredAuthorityList[mMeasuredAuthorityCount].Data = AllocatePool (Size); + if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size); + mMeasuredAuthorityCount++; + + return EFI_SUCCESS; +} + +/** + This function will return if this variable is already measured. + + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] VarData The content of the variable data. + @param[in] VarSize The size of the variable data. + + @retval TRUE The data is already measured. + @retval FALSE The data is not measured yet. +**/ +BOOLEAN +IsDataMeasured ( + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN Size + ) +{ + UINTN Index; + + for (Index = 0; Index < mMeasuredAuthorityCount; Index++) { + if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) && + (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) && + (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) && + (Size == mMeasuredAuthorityList[Index].Size)) { + return TRUE; + } + } + + return FALSE; +} + +/** + This function will return if this variable is SecureAuthority Variable. + + @param[in] VariableName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + + @retval TRUE This is SecureAuthority Variable + @retval FALSE This is not SecureAuthority Variable +**/ +BOOLEAN +IsSecureAuthorityVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + UINTN Index; + + for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { + if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) && + (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) { + return TRUE; + } + } + return FALSE; +} + +/** + Measure and log an EFI variable, and extend the measurement result into a specific PCR. + + @param[in] VarName A Null-terminated string that is the name of the vendor's variable. + @param[in] VendorGuid A unique identifier for the vendor. + @param[in] VarData The content of the variable data. + @param[in] VarSize The size of the variable data. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_OUT_OF_RESOURCES Out of memory. + @retval EFI_DEVICE_ERROR The operation was unsuccessful. + +**/ +EFI_STATUS +EFIAPI +MeasureVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VendorGuid, + IN VOID *VarData, + IN UINTN VarSize + ) +{ + EFI_STATUS Status; + UINTN VarNameLength; + EFI_VARIABLE_DATA_TREE *VarLog; + UINT32 VarLogSize; + + // + // The EFI_VARIABLE_DATA_TREE.VariableData value shall be the EFI_SIGNATURE_DATA value + // from the EFI_SIGNATURE_LIST that contained the authority that was used to validate the image + // + VarNameLength = StrLen (VarName); + VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize + - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData)); + + VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize); + if (VarLog == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName)); + VarLog->UnicodeNameLength = VarNameLength; + VarLog->VariableDataLength = VarSize; + CopyMem ( + VarLog->UnicodeName, + VarName, + VarNameLength * sizeof (*VarName) + ); + CopyMem ( + (CHAR16 *)VarLog->UnicodeName + VarNameLength, + VarData, + VarSize + ); + + DEBUG ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY)); + DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); + + Status = TpmMeasureAndLogData ( + 7, + EV_EFI_VARIABLE_AUTHORITY, + VarLog, + VarLogSize, + VarLog, + VarLogSize + ); + FreePool (VarLog); + + return Status; +} + +/** + SecureBoot Hook for processing image verification. + + @param[in] VariableName Name of Variable to be found. + @param[in] VendorGuid Variable vendor GUID. + @param[in] DataSize Size of Data found. If size is less than the + data, this value contains the required size. + @param[in] Data Data pointer. + +**/ +VOID +EFIAPI +SecureBootHook ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINTN DataSize, + IN VOID *Data + ) +{ + EFI_STATUS Status; + + if (!IsSecureAuthorityVariable (VariableName, VendorGuid)) { + return ; + } + + if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) { + DEBUG ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n")); + return ; + } + + Status = MeasureVariable ( + VariableName, + VendorGuid, + Data, + DataSize + ); + DEBUG ((EFI_D_ERROR, "MeasureBootPolicyVariable - %r\n", Status)); + + if (!EFI_ERROR (Status)) { + AddDataMeasured (VariableName, VendorGuid, Data, DataSize); + } + + return ; +} -- cgit v1.2.3