1 /** @file 2 Measure TrEE required variable. 3 4 Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT 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 28 typedef struct { 29 CHAR16 *VariableName; 30 EFI_GUID *VendorGuid; 31 } VARIABLE_TYPE; 32 33 typedef 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 42 UINTN mMeasuredAuthorityCount = 0; 43 UINTN mMeasuredAuthorityCountMax = 0; 44 VARIABLE_RECORD *mMeasuredAuthorityList = NULL; 45 46 VARIABLE_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 **/ 57 CHAR16 * 58 AssignVarName ( 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 **/ 80 EFI_GUID * 81 AssignVendorGuid ( 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 **/ 107 EFI_STATUS 108 AddDataMeasured ( 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 **/ 161 BOOLEAN 162 IsDataMeasured ( 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 **/ 192 BOOLEAN 193 IsSecureAuthorityVariable ( 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 **/ 222 EFI_STATUS 223 EFIAPI 224 MeasureVariable ( 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 **/ 289 VOID 290 EFIAPI 291 SecureBootHook ( 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