OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
Measurement.c
Go to the documentation of this file.
1
9#include <PiDxe.h>
10#include <Guid/ImageAuthentication.h>
11#include <IndustryStandard/UefiTcgPlatform.h>
12
13#include <Library/UefiBootServicesTableLib.h>
14#include <Library/UefiRuntimeServicesTableLib.h>
15#include <Library/MemoryAllocationLib.h>
16#include <Library/BaseMemoryLib.h>
17#include <Library/DebugLib.h>
18#include <Library/BaseLib.h>
19#include <Library/TpmMeasurementLib.h>
20
22
23typedef struct {
24 CHAR16 *VariableName;
25 EFI_GUID *VendorGuid;
27
29 { EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid },
30 { EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid },
31 { EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid },
32 { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },
33 { EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid },
34 { EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid },
35};
36
37//
38// "SecureBoot" may update following PK Del/Add
39// Cache its value to detect value update
40//
41UINT8 *mSecureBootVarData = NULL;
43
53BOOLEAN
55 IN CHAR16 *VariableName,
56 IN EFI_GUID *VendorGuid
57 )
58{
59 UINTN Index;
60
61 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {
62 if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&
63 (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)))
64 {
65 return TRUE;
66 }
67 }
68
69 return FALSE;
70}
71
85EFI_STATUS
86EFIAPI
88 IN CHAR16 *VarName,
89 IN EFI_GUID *VendorGuid,
90 IN VOID *VarData,
91 IN UINTN VarSize
92 )
93{
94 EFI_STATUS Status;
95 UINTN VarNameLength;
96 UEFI_VARIABLE_DATA *VarLog;
97 UINT32 VarLogSize;
98
99 ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));
100
101 VarNameLength = StrLen (VarName);
102 VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize
103 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));
104
105 VarLog = (UEFI_VARIABLE_DATA *)AllocateZeroPool (VarLogSize);
106 if (VarLog == NULL) {
107 return EFI_OUT_OF_RESOURCES;
108 }
109
110 CopyMem (&VarLog->VariableName, VendorGuid, sizeof (VarLog->VariableName));
111 VarLog->UnicodeNameLength = VarNameLength;
112 VarLog->VariableDataLength = VarSize;
113 CopyMem (
114 VarLog->UnicodeName,
115 VarName,
116 VarNameLength * sizeof (*VarName)
117 );
118 if (VarSize != 0) {
119 CopyMem (
120 (CHAR16 *)VarLog->UnicodeName + VarNameLength,
121 VarData,
122 VarSize
123 );
124 }
125
126 DEBUG ((DEBUG_INFO, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_DRIVER_CONFIG));
127 DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));
128
129 Status = TpmMeasureAndLogData (
130 7,
131 EV_EFI_VARIABLE_DRIVER_CONFIG,
132 VarLog,
133 VarLogSize,
134 VarLog,
135 VarLogSize
136 );
137 FreePool (VarLog);
138 return Status;
139}
140
159EFI_STATUS
161 IN CONST CHAR16 *Name,
162 IN CONST EFI_GUID *Guid,
163 OUT VOID **Value,
164 OUT UINTN *Size
165 )
166{
167 EFI_STATUS Status;
168 UINTN BufferSize;
169
170 //
171 // Try to get the variable size.
172 //
173 BufferSize = 0;
174 *Value = NULL;
175 if (Size != NULL) {
176 *Size = 0;
177 }
178
179 Status = gRT->GetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid, NULL, &BufferSize, *Value);
180 if (Status != EFI_BUFFER_TOO_SMALL) {
181 return Status;
182 }
183
184 //
185 // Allocate buffer to get the variable.
186 //
187 *Value = AllocatePool (BufferSize);
188 ASSERT (*Value != NULL);
189 if (*Value == NULL) {
190 return EFI_OUT_OF_RESOURCES;
191 }
192
193 //
194 // Get the variable data.
195 //
196 Status = gRT->GetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid, NULL, &BufferSize, *Value);
197 if (EFI_ERROR (Status)) {
198 FreePool (*Value);
199 *Value = NULL;
200 }
201
202 if (Size != NULL) {
203 *Size = BufferSize;
204 }
205
206 return Status;
207}
208
216VOID
217EFIAPI
219 IN CHAR16 *VariableName,
220 IN EFI_GUID *VendorGuid
221 )
222{
223 EFI_STATUS Status;
224 UINTN VariableDataSize;
225 VOID *VariableData;
226
227 if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) {
228 return;
229 }
230
231 //
232 // We should NOT use Data and DataSize here,because it may include signature,
233 // or is just partial with append attributes, or is deleted.
234 // We should GetVariable again, to get full variable content.
235 //
236 Status = InternalGetVariable (
237 VariableName,
238 VendorGuid,
239 &VariableData,
240 &VariableDataSize
241 );
242 if (EFI_ERROR (Status)) {
243 //
244 // Measure DBT only if present and not empty
245 //
246 if ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) &&
247 CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid))
248 {
249 DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));
250 return;
251 } else {
252 VariableData = NULL;
253 VariableDataSize = 0;
254 }
255 }
256
257 Status = MeasureVariable (
258 VariableName,
259 VendorGuid,
260 VariableData,
261 VariableDataSize
262 );
263 DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status));
264
265 if (VariableData != NULL) {
266 FreePool (VariableData);
267 }
268
269 //
270 // "SecureBoot" is 8bit & read-only. It can only be changed according to PK update
271 //
272 if ((StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0) &&
273 CompareGuid (VendorGuid, &gEfiGlobalVariableGuid))
274 {
275 Status = InternalGetVariable (
276 EFI_SECURE_BOOT_MODE_NAME,
278 &VariableData,
279 &VariableDataSize
280 );
281 if (EFI_ERROR (Status)) {
282 return;
283 }
284
285 //
286 // If PK update is successful. "SecureBoot" shall always exist ever since variable write service is ready
287 //
288 ASSERT (mSecureBootVarData != NULL);
289
290 if (CompareMem (mSecureBootVarData, VariableData, VariableDataSize) != 0) {
291 FreePool (mSecureBootVarData);
292 mSecureBootVarData = VariableData;
293 mSecureBootVarDataSize = VariableDataSize;
294
295 DEBUG ((DEBUG_INFO, "%s variable updated according to PK change. Remeasure the value!\n", EFI_SECURE_BOOT_MODE_NAME));
296 Status = MeasureVariable (
297 EFI_SECURE_BOOT_MODE_NAME,
301 );
302 DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status));
303 } else {
304 //
305 // "SecureBoot" variable is not changed
306 //
307 FreePool (VariableData);
308 }
309 }
310
311 return;
312}
313
319VOID
320EFIAPI
322 VOID
323 )
324{
325 EFI_STATUS Status;
326
327 //
328 // Record initial "SecureBoot" variable value.
329 // It is used to detect SecureBoot variable change in SecureBootHook.
330 //
331 Status = InternalGetVariable (
332 EFI_SECURE_BOOT_MODE_NAME,
334 (VOID **)&mSecureBootVarData,
336 );
337 if (EFI_ERROR (Status)) {
338 //
339 // Read could fail when Auth Variable solution is not supported
340 //
341 DEBUG ((DEBUG_INFO, "RecordSecureBootPolicyVarData GetVariable %s Status %x\n", EFI_SECURE_BOOT_MODE_NAME, Status));
342 }
343}
EFI_STATUS EFIAPI MeasureVariable(IN CHAR16 *VarName, IN EFI_GUID *VendorGuid, IN VOID *VarData, IN UINTN VarSize)
Definition Measurement.c:87
UINTN mSecureBootVarDataSize
Definition Measurement.c:42
VOID EFIAPI SecureBootHook(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
BOOLEAN IsSecureBootPolicyVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
Definition Measurement.c:54
EFI_STATUS InternalGetVariable(IN CONST CHAR16 *Name, IN CONST EFI_GUID *Guid, OUT VOID **Value, OUT UINTN *Size)
VOID EFIAPI RecordSecureBootPolicyVarData(VOID)
VARIABLE_TYPE mVariableType[]
Definition Measurement.c:28
UINT8 * mSecureBootVarData
Definition Measurement.c:41
DMG_SIZE_DEVICE_PATH Size
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
EFI_RUNTIME_SERVICES * gRT
EFI_GUID gEfiGlobalVariableGuid
#define ASSERT(x)
Definition coder.h:55
EFI_GUID * VendorGuid
Definition Measurement.c:25
CHAR16 * VariableName
Definition Measurement.c:24