2 Measure TCG required variable.
4 Copyright (c) 2013 - 2017, 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
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.
16 #include <Guid/ImageAuthentication.h>
17 #include <IndustryStandard/UefiTcgPlatform.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/UefiRuntimeServicesTableLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/BaseMemoryLib.h>
23 #include <Library/DebugLib.h>
24 #include <Library/BaseLib.h>
25 #include <Library/TpmMeasurementLib.h>
27 #include "PrivilegePolymorphic.h"
34 VARIABLE_TYPE mVariableType
[] = {
35 {EFI_SECURE_BOOT_MODE_NAME
, &gEfiGlobalVariableGuid
},
36 {EFI_PLATFORM_KEY_NAME
, &gEfiGlobalVariableGuid
},
37 {EFI_KEY_EXCHANGE_KEY_NAME
, &gEfiGlobalVariableGuid
},
38 {EFI_IMAGE_SECURITY_DATABASE
, &gEfiImageSecurityDatabaseGuid
},
39 {EFI_IMAGE_SECURITY_DATABASE1
, &gEfiImageSecurityDatabaseGuid
},
40 {EFI_IMAGE_SECURITY_DATABASE2
, &gEfiImageSecurityDatabaseGuid
},
44 // "SecureBoot" may update following PK Del/Add
45 // Cache its value to detect value update
47 UINT8
*mSecureBootVarData
= NULL
;
48 UINTN mSecureBootVarDataSize
= 0;
51 This function will return if this variable is SecureBootPolicy Variable.
53 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable.
54 @param[in] VendorGuid A unique identifier for the vendor.
56 @retval TRUE This is SecureBootPolicy Variable
57 @retval FALSE This is not SecureBootPolicy Variable
60 IsSecureBootPolicyVariable (
61 IN CHAR16
*VariableName
,
62 IN EFI_GUID
*VendorGuid
67 for (Index
= 0; Index
< sizeof(mVariableType
)/sizeof(mVariableType
[0]); Index
++) {
68 if ((StrCmp (VariableName
, mVariableType
[Index
].VariableName
) == 0) &&
69 (CompareGuid (VendorGuid
, mVariableType
[Index
].VendorGuid
))) {
77 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
79 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
80 @param[in] VendorGuid A unique identifier for the vendor.
81 @param[in] VarData The content of the variable data.
82 @param[in] VarSize The size of the variable data.
84 @retval EFI_SUCCESS Operation completed successfully.
85 @retval EFI_OUT_OF_RESOURCES Out of memory.
86 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
93 IN EFI_GUID
*VendorGuid
,
100 UEFI_VARIABLE_DATA
*VarLog
;
103 ASSERT ((VarSize
== 0 && VarData
== NULL
) || (VarSize
!= 0 && VarData
!= NULL
));
105 VarNameLength
= StrLen (VarName
);
106 VarLogSize
= (UINT32
)(sizeof (*VarLog
) + VarNameLength
* sizeof (*VarName
) + VarSize
107 - sizeof (VarLog
->UnicodeName
) - sizeof (VarLog
->VariableData
));
109 VarLog
= (UEFI_VARIABLE_DATA
*) AllocateZeroPool (VarLogSize
);
110 if (VarLog
== NULL
) {
111 return EFI_OUT_OF_RESOURCES
;
114 CopyMem (&VarLog
->VariableName
, VendorGuid
, sizeof(VarLog
->VariableName
));
115 VarLog
->UnicodeNameLength
= VarNameLength
;
116 VarLog
->VariableDataLength
= VarSize
;
120 VarNameLength
* sizeof (*VarName
)
124 (CHAR16
*)VarLog
->UnicodeName
+ VarNameLength
,
130 DEBUG ((EFI_D_INFO
, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN
)7, (UINTN
)EV_EFI_VARIABLE_DRIVER_CONFIG
));
131 DEBUG ((EFI_D_INFO
, "VariableName - %s, VendorGuid - %g)\n", VarName
, VendorGuid
));
133 Status
= TpmMeasureAndLogData (
135 EV_EFI_VARIABLE_DRIVER_CONFIG
,
146 Returns the status whether get the variable success. The function retrieves
147 variable through the UEFI Runtime Service GetVariable(). The
148 returned buffer is allocated using AllocatePool(). The caller is responsible
149 for freeing this buffer with FreePool().
151 This API is only invoked in boot time. It may NOT be invoked at runtime.
153 @param[in] Name The pointer to a Null-terminated Unicode string.
154 @param[in] Guid The pointer to an EFI_GUID structure
155 @param[out] Value The buffer point saved the variable info.
156 @param[out] Size The buffer size of the variable.
158 @return EFI_OUT_OF_RESOURCES Allocate buffer failed.
159 @return EFI_SUCCESS Find the specified variable.
160 @return Others Errors Return errors from call to gRT->GetVariable.
164 InternalGetVariable (
165 IN CONST CHAR16
*Name
,
166 IN CONST EFI_GUID
*Guid
,
175 // Try to get the variable size.
183 Status
= gRT
->GetVariable ((CHAR16
*) Name
, (EFI_GUID
*) Guid
, NULL
, &BufferSize
, *Value
);
184 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
189 // Allocate buffer to get the variable.
191 *Value
= AllocatePool (BufferSize
);
192 ASSERT (*Value
!= NULL
);
193 if (*Value
== NULL
) {
194 return EFI_OUT_OF_RESOURCES
;
198 // Get the variable data.
200 Status
= gRT
->GetVariable ((CHAR16
*) Name
, (EFI_GUID
*) Guid
, NULL
, &BufferSize
, *Value
);
201 if (EFI_ERROR (Status
)) {
214 SecureBoot Hook for SetVariable.
216 @param[in] VariableName Name of Variable to be found.
217 @param[in] VendorGuid Variable vendor GUID.
223 IN CHAR16
*VariableName
,
224 IN EFI_GUID
*VendorGuid
228 UINTN VariableDataSize
;
231 if (!IsSecureBootPolicyVariable (VariableName
, VendorGuid
)) {
236 // We should NOT use Data and DataSize here,because it may include signature,
237 // or is just partial with append attributes, or is deleted.
238 // We should GetVariable again, to get full variable content.
240 Status
= InternalGetVariable (
246 if (EFI_ERROR (Status
)) {
248 // Measure DBT only if present and not empty
250 if (StrCmp (VariableName
, EFI_IMAGE_SECURITY_DATABASE2
) == 0 &&
251 CompareGuid (VendorGuid
, &gEfiImageSecurityDatabaseGuid
)) {
252 DEBUG((DEBUG_INFO
, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2
));
256 VariableDataSize
= 0;
260 Status
= MeasureVariable (
266 DEBUG ((EFI_D_INFO
, "MeasureBootPolicyVariable - %r\n", Status
));
268 if (VariableData
!= NULL
) {
269 FreePool (VariableData
);
273 // "SecureBoot" is 8bit & read-only. It can only be changed according to PK update
275 if ((StrCmp (VariableName
, EFI_PLATFORM_KEY_NAME
) == 0) &&
276 CompareGuid (VendorGuid
, &gEfiGlobalVariableGuid
)) {
277 Status
= InternalGetVariable (
278 EFI_SECURE_BOOT_MODE_NAME
,
279 &gEfiGlobalVariableGuid
,
283 if (EFI_ERROR (Status
)) {
288 // If PK update is successful. "SecureBoot" shall always exist ever since variable write service is ready
290 ASSERT(mSecureBootVarData
!= NULL
);
292 if (CompareMem(mSecureBootVarData
, VariableData
, VariableDataSize
) != 0) {
293 FreePool(mSecureBootVarData
);
294 mSecureBootVarData
= VariableData
;
295 mSecureBootVarDataSize
= VariableDataSize
;
297 DEBUG((DEBUG_INFO
, "%s variable updated according to PK change. Remeasure the value!\n", EFI_SECURE_BOOT_MODE_NAME
));
298 Status
= MeasureVariable (
299 EFI_SECURE_BOOT_MODE_NAME
,
300 &gEfiGlobalVariableGuid
,
302 mSecureBootVarDataSize
304 DEBUG ((DEBUG_INFO
, "MeasureBootPolicyVariable - %r\n", Status
));
307 // "SecureBoot" variable is not changed
309 FreePool(VariableData
);
317 Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).
318 Record their initial State when variable write service is ready.
323 RecordSecureBootPolicyVarData(
330 // Record initial "SecureBoot" variable value.
331 // It is used to detect SecureBoot variable change in SecureBootHook.
333 Status
= InternalGetVariable (
334 EFI_SECURE_BOOT_MODE_NAME
,
335 &gEfiGlobalVariableGuid
,
336 (VOID
**)&mSecureBootVarData
,
337 &mSecureBootVarDataSize
339 if (EFI_ERROR(Status
)) {
341 // Read could fail when Auth Variable solution is not supported
343 DEBUG((DEBUG_INFO
, "RecordSecureBootPolicyVarData GetVariable %s Status %x\n", EFI_SECURE_BOOT_MODE_NAME
, Status
));