1/** @file 2 Measure TrEE required variable. 3 4Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR> 5This program and the accompanying materials 6are licensed and made available under the terms and conditions of the BSD License 7which accompanies this distribution. The full text of the license may be found at 8http://opensource.org/licenses/bsd-license.php 9 10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13**/ 14 15#include <PiDxe.h> 16#include <Guid/ImageAuthentication.h> 17#include <IndustryStandard/UefiTcgPlatform.h> 18#include <Protocol/TrEEProtocol.h> 19 20#include <Library/UefiBootServicesTableLib.h> 21#include <Library/UefiRuntimeServicesTableLib.h> 22#include <Library/MemoryAllocationLib.h> 23#include <Library/BaseMemoryLib.h> 24#include <Library/DebugLib.h> 25#include <Library/BaseLib.h> 26#include <Library/TpmMeasurementLib.h> 27 28typedef struct { 29 CHAR16 *VariableName; 30 EFI_GUID *VendorGuid; 31} VARIABLE_TYPE; 32 33typedef struct { 34 CHAR16 *VariableName; 35 EFI_GUID *VendorGuid; 36 VOID *Data; 37 UINTN Size; 38} VARIABLE_RECORD; 39 40#define MEASURED_AUTHORITY_COUNT_MAX 0x100 41 42UINTN mMeasuredAuthorityCount = 0; 43UINTN mMeasuredAuthorityCountMax = 0; 44VARIABLE_RECORD *mMeasuredAuthorityList = NULL; 45 46VARIABLE_TYPE mVariableType[] = { 47 {EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid}, 48}; 49 50/** 51 This function will check if VarName should be recorded and return the address of VarName if it is needed. 52 53 @param[in] VarName A Null-terminated string that is the name of the vendor's variable. 54 55 @return the address of VarName. 56**/ 57CHAR16 * 58AssignVarName ( 59 IN CHAR16 *VarName 60 ) 61{ 62 UINTN Index; 63 64 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { 65 if (StrCmp (VarName, mVariableType[Index].VariableName) == 0) { 66 return mVariableType[Index].VariableName; 67 } 68 } 69 70 return NULL; 71} 72 73/** 74 This function will check if VendorGuid should be recorded and return the address of VendorGuid if it is needed. 75 76 @param[in] VendorGuid A unique identifier for the vendor. 77 78 @return the address of VendorGuid. 79**/ 80EFI_GUID * 81AssignVendorGuid ( 82 IN EFI_GUID *VendorGuid 83 ) 84{ 85 UINTN Index; 86 87 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { 88 if (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)) { 89 return mVariableType[Index].VendorGuid; 90 } 91 } 92 93 return NULL; 94} 95 96/** 97 This function will add variable information to MeasuredAuthorityList. 98 99 @param[in] VarName A Null-terminated string that is the name of the vendor's variable. 100 @param[in] VendorGuid A unique identifier for the vendor. 101 @param[in] VarData The content of the variable data. 102 @param[in] VarSize The size of the variable data. 103 104 @retval EFI_SUCCESS Operation completed successfully. 105 @retval EFI_OUT_OF_RESOURCES Out of memory. 106**/ 107EFI_STATUS 108AddDataMeasured ( 109 IN CHAR16 *VarName, 110 IN EFI_GUID *VendorGuid, 111 IN VOID *Data, 112 IN UINTN Size 113 ) 114{ 115 VARIABLE_RECORD *NewMeasuredAuthorityList; 116 117 ASSERT (mMeasuredAuthorityCount <= mMeasuredAuthorityCountMax); 118 if (mMeasuredAuthorityCount == mMeasuredAuthorityCountMax) { 119 // 120 // Need enlarge 121 // 122 NewMeasuredAuthorityList = AllocateZeroPool (sizeof(VARIABLE_RECORD) * (mMeasuredAuthorityCountMax + MEASURED_AUTHORITY_COUNT_MAX)); 123 if (NewMeasuredAuthorityList == NULL) { 124 return EFI_OUT_OF_RESOURCES; 125 } 126 if (mMeasuredAuthorityList != NULL) { 127 CopyMem (NewMeasuredAuthorityList, mMeasuredAuthorityList, sizeof(VARIABLE_RECORD) * mMeasuredAuthorityCount); 128 FreePool (mMeasuredAuthorityList); 129 } 130 mMeasuredAuthorityList = NewMeasuredAuthorityList; 131 mMeasuredAuthorityCountMax += MEASURED_AUTHORITY_COUNT_MAX; 132 } 133 134 // 135 // Add new entry 136 // 137 mMeasuredAuthorityList[mMeasuredAuthorityCount].VariableName = AssignVarName (VarName); 138 mMeasuredAuthorityList[mMeasuredAuthorityCount].VendorGuid = AssignVendorGuid (VendorGuid); 139 mMeasuredAuthorityList[mMeasuredAuthorityCount].Size = Size; 140 mMeasuredAuthorityList[mMeasuredAuthorityCount].Data = AllocatePool (Size); 141 if (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data == NULL) { 142 return EFI_OUT_OF_RESOURCES; 143 } 144 CopyMem (mMeasuredAuthorityList[mMeasuredAuthorityCount].Data, Data, Size); 145 mMeasuredAuthorityCount++; 146 147 return EFI_SUCCESS; 148} 149 150/** 151 This function will return if this variable is already measured. 152 153 @param[in] VarName A Null-terminated string that is the name of the vendor's variable. 154 @param[in] VendorGuid A unique identifier for the vendor. 155 @param[in] VarData The content of the variable data. 156 @param[in] VarSize The size of the variable data. 157 158 @retval TRUE The data is already measured. 159 @retval FALSE The data is not measured yet. 160**/ 161BOOLEAN 162IsDataMeasured ( 163 IN CHAR16 *VarName, 164 IN EFI_GUID *VendorGuid, 165 IN VOID *Data, 166 IN UINTN Size 167 ) 168{ 169 UINTN Index; 170 171 for (Index = 0; Index < mMeasuredAuthorityCount; Index++) { 172 if ((StrCmp (VarName, mMeasuredAuthorityList[Index].VariableName) == 0) && 173 (CompareGuid (VendorGuid, mMeasuredAuthorityList[Index].VendorGuid)) && 174 (CompareMem (Data, mMeasuredAuthorityList[Index].Data, Size) == 0) && 175 (Size == mMeasuredAuthorityList[Index].Size)) { 176 return TRUE; 177 } 178 } 179 180 return FALSE; 181} 182 183/** 184 This function will return if this variable is SecureAuthority Variable. 185 186 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable. 187 @param[in] VendorGuid A unique identifier for the vendor. 188 189 @retval TRUE This is SecureAuthority Variable 190 @retval FALSE This is not SecureAuthority Variable 191**/ 192BOOLEAN 193IsSecureAuthorityVariable ( 194 IN CHAR16 *VariableName, 195 IN EFI_GUID *VendorGuid 196 ) 197{ 198 UINTN Index; 199 200 for (Index = 0; Index < sizeof(mVariableType)/sizeof(mVariableType[0]); Index++) { 201 if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) && 202 (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid))) { 203 return TRUE; 204 } 205 } 206 return FALSE; 207} 208 209/** 210 Measure and log an EFI variable, and extend the measurement result into a specific PCR. 211 212 @param[in] VarName A Null-terminated string that is the name of the vendor's variable. 213 @param[in] VendorGuid A unique identifier for the vendor. 214 @param[in] VarData The content of the variable data. 215 @param[in] VarSize The size of the variable data. 216 217 @retval EFI_SUCCESS Operation completed successfully. 218 @retval EFI_OUT_OF_RESOURCES Out of memory. 219 @retval EFI_DEVICE_ERROR The operation was unsuccessful. 220 221**/ 222EFI_STATUS 223EFIAPI 224MeasureVariable ( 225 IN CHAR16 *VarName, 226 IN EFI_GUID *VendorGuid, 227 IN VOID *VarData, 228 IN UINTN VarSize 229 ) 230{ 231 EFI_STATUS Status; 232 UINTN VarNameLength; 233 EFI_VARIABLE_DATA_TREE *VarLog; 234 UINT32 VarLogSize; 235 236 // 237 // The EFI_VARIABLE_DATA_TREE.VariableData value shall be the EFI_SIGNATURE_DATA value 238 // from the EFI_SIGNATURE_LIST that contained the authority that was used to validate the image 239 // 240 VarNameLength = StrLen (VarName); 241 VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize 242 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData)); 243 244 VarLog = (EFI_VARIABLE_DATA_TREE *) AllocateZeroPool (VarLogSize); 245 if (VarLog == NULL) { 246 return EFI_OUT_OF_RESOURCES; 247 } 248 249 CopyMem (&VarLog->VariableName, VendorGuid, sizeof(VarLog->VariableName)); 250 VarLog->UnicodeNameLength = VarNameLength; 251 VarLog->VariableDataLength = VarSize; 252 CopyMem ( 253 VarLog->UnicodeName, 254 VarName, 255 VarNameLength * sizeof (*VarName) 256 ); 257 CopyMem ( 258 (CHAR16 *)VarLog->UnicodeName + VarNameLength, 259 VarData, 260 VarSize 261 ); 262 263 DEBUG ((EFI_D_INFO, "DxeImageVerification: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_AUTHORITY)); 264 DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); 265 266 Status = TpmMeasureAndLogData ( 267 7, 268 EV_EFI_VARIABLE_AUTHORITY, 269 VarLog, 270 VarLogSize, 271 VarLog, 272 VarLogSize 273 ); 274 FreePool (VarLog); 275 276 return Status; 277} 278 279/** 280 SecureBoot Hook for processing image verification. 281 282 @param[in] VariableName Name of Variable to be found. 283 @param[in] VendorGuid Variable vendor GUID. 284 @param[in] DataSize Size of Data found. If size is less than the 285 data, this value contains the required size. 286 @param[in] Data Data pointer. 287 288**/ 289VOID 290EFIAPI 291SecureBootHook ( 292 IN CHAR16 *VariableName, 293 IN EFI_GUID *VendorGuid, 294 IN UINTN DataSize, 295 IN VOID *Data 296 ) 297{ 298 EFI_STATUS Status; 299 300 if (!IsSecureAuthorityVariable (VariableName, VendorGuid)) { 301 return ; 302 } 303 304 if (IsDataMeasured (VariableName, VendorGuid, Data, DataSize)) { 305 DEBUG ((EFI_D_ERROR, "MeasureSecureAuthorityVariable - IsDataMeasured\n")); 306 return ; 307 } 308 309 Status = MeasureVariable ( 310 VariableName, 311 VendorGuid, 312 Data, 313 DataSize 314 ); 315 DEBUG ((EFI_D_INFO, "MeasureBootPolicyVariable - %r\n", Status)); 316 317 if (!EFI_ERROR (Status)) { 318 AddDataMeasured (VariableName, VendorGuid, Data, DataSize); 319 } 320 321 return ; 322} 323