]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Measurement.c
1 /** @file
2 Measure TCG required variable.
3
4 Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
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
21 #include "PrivilegePolymorphic.h"
22
23 typedef struct {
24 CHAR16 *VariableName;
25 EFI_GUID *VendorGuid;
26 } VARIABLE_TYPE;
27
28 VARIABLE_TYPE mVariableType[] = {
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 //
41 UINT8 *mSecureBootVarData = NULL;
42 UINTN mSecureBootVarDataSize = 0;
43
44 /**
45 This function will return if this variable is SecureBootPolicy Variable.
46
47 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable.
48 @param[in] VendorGuid A unique identifier for the vendor.
49
50 @retval TRUE This is SecureBootPolicy Variable
51 @retval FALSE This is not SecureBootPolicy Variable
52 **/
53 BOOLEAN
54 IsSecureBootPolicyVariable (
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
72 /**
73 Measure and log an EFI variable, and extend the measurement result into a specific PCR.
74
75 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.
76 @param[in] VendorGuid A unique identifier for the vendor.
77 @param[in] VarData The content of the variable data.
78 @param[in] VarSize The size of the variable data.
79
80 @retval EFI_SUCCESS Operation completed successfully.
81 @retval EFI_OUT_OF_RESOURCES Out of memory.
82 @retval EFI_DEVICE_ERROR The operation was unsuccessful.
83
84 **/
85 EFI_STATUS
86 EFIAPI
87 MeasureVariable (
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
141 /**
142 Returns the status whether get the variable success. The function retrieves
143 variable through the UEFI Runtime Service GetVariable(). The
144 returned buffer is allocated using AllocatePool(). The caller is responsible
145 for freeing this buffer with FreePool().
146
147 This API is only invoked in boot time. It may NOT be invoked at runtime.
148
149 @param[in] Name The pointer to a Null-terminated Unicode string.
150 @param[in] Guid The pointer to an EFI_GUID structure
151 @param[out] Value The buffer point saved the variable info.
152 @param[out] Size The buffer size of the variable.
153
154 @return EFI_OUT_OF_RESOURCES Allocate buffer failed.
155 @return EFI_SUCCESS Find the specified variable.
156 @return Others Errors Return errors from call to gRT->GetVariable.
157
158 **/
159 EFI_STATUS
160 InternalGetVariable (
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
209 /**
210 SecureBoot Hook for SetVariable.
211
212 @param[in] VariableName Name of Variable to be found.
213 @param[in] VendorGuid Variable vendor GUID.
214
215 **/
216 VOID
217 EFIAPI
218 SecureBootHook (
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,
277 &gEfiGlobalVariableGuid,
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,
298 &gEfiGlobalVariableGuid,
299 mSecureBootVarData,
300 mSecureBootVarDataSize
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
314 /**
315 Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).
316 Record their initial State when variable write service is ready.
317
318 **/
319 VOID
320 EFIAPI
321 RecordSecureBootPolicyVarData (
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,
333 &gEfiGlobalVariableGuid,
334 (VOID **)&mSecureBootVarData,
335 &mSecureBootVarDataSize
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 }