]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Variable/RuntimeDxe/Measurement.c
MdeModulePkg: Apply uncrustify changes
[mirror_edk2.git] / MdeModulePkg / Universal / Variable / RuntimeDxe / Measurement.c
CommitLineData
fa0737a8 1/** @file\r
1de3b7fd 2 Measure TCG required variable.\r
fa0737a8 3\r
dc9bd6ed 4Copyright (c) 2013 - 2017, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
fa0737a8
SZ
6\r
7**/\r
8\r
9#include <PiDxe.h>\r
10#include <Guid/ImageAuthentication.h>\r
11#include <IndustryStandard/UefiTcgPlatform.h>\r
fa0737a8
SZ
12\r
13#include <Library/UefiBootServicesTableLib.h>\r
14#include <Library/UefiRuntimeServicesTableLib.h>\r
15#include <Library/MemoryAllocationLib.h>\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/BaseLib.h>\r
19#include <Library/TpmMeasurementLib.h>\r
20\r
00663d04
LE
21#include "PrivilegePolymorphic.h"\r
22\r
fa0737a8 23typedef struct {\r
1436aea4
MK
24 CHAR16 *VariableName;\r
25 EFI_GUID *VendorGuid;\r
fa0737a8
SZ
26} VARIABLE_TYPE;\r
27\r
28VARIABLE_TYPE mVariableType[] = {\r
1436aea4
MK
29 { EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid },\r
30 { EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid },\r
31 { EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid },\r
32 { EFI_IMAGE_SECURITY_DATABASE, &gEfiImageSecurityDatabaseGuid },\r
33 { EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid },\r
34 { EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid },\r
fa0737a8
SZ
35};\r
36\r
dc9bd6ed
ZC
37//\r
38// "SecureBoot" may update following PK Del/Add\r
39// Cache its value to detect value update\r
40//\r
1436aea4
MK
41UINT8 *mSecureBootVarData = NULL;\r
42UINTN mSecureBootVarDataSize = 0;\r
dc9bd6ed 43\r
fa0737a8
SZ
44/**\r
45 This function will return if this variable is SecureBootPolicy Variable.\r
46\r
47 @param[in] VariableName A Null-terminated string that is the name of the vendor's variable.\r
48 @param[in] VendorGuid A unique identifier for the vendor.\r
49\r
50 @retval TRUE This is SecureBootPolicy Variable\r
51 @retval FALSE This is not SecureBootPolicy Variable\r
52**/\r
53BOOLEAN\r
54IsSecureBootPolicyVariable (\r
1436aea4
MK
55 IN CHAR16 *VariableName,\r
56 IN EFI_GUID *VendorGuid\r
fa0737a8
SZ
57 )\r
58{\r
1436aea4 59 UINTN Index;\r
fa0737a8 60\r
1436aea4 61 for (Index = 0; Index < sizeof (mVariableType)/sizeof (mVariableType[0]); Index++) {\r
fa0737a8 62 if ((StrCmp (VariableName, mVariableType[Index].VariableName) == 0) &&\r
1436aea4
MK
63 (CompareGuid (VendorGuid, mVariableType[Index].VendorGuid)))\r
64 {\r
fa0737a8
SZ
65 return TRUE;\r
66 }\r
67 }\r
1436aea4 68\r
fa0737a8
SZ
69 return FALSE;\r
70}\r
71\r
72/**\r
73 Measure and log an EFI variable, and extend the measurement result into a specific PCR.\r
74\r
75 @param[in] VarName A Null-terminated string that is the name of the vendor's variable.\r
76 @param[in] VendorGuid A unique identifier for the vendor.\r
77 @param[in] VarData The content of the variable data.\r
78 @param[in] VarSize The size of the variable data.\r
79\r
80 @retval EFI_SUCCESS Operation completed successfully.\r
81 @retval EFI_OUT_OF_RESOURCES Out of memory.\r
82 @retval EFI_DEVICE_ERROR The operation was unsuccessful.\r
83\r
84**/\r
85EFI_STATUS\r
86EFIAPI\r
87MeasureVariable (\r
1436aea4
MK
88 IN CHAR16 *VarName,\r
89 IN EFI_GUID *VendorGuid,\r
90 IN VOID *VarData,\r
91 IN UINTN VarSize\r
fa0737a8
SZ
92 )\r
93{\r
1436aea4
MK
94 EFI_STATUS Status;\r
95 UINTN VarNameLength;\r
96 UEFI_VARIABLE_DATA *VarLog;\r
97 UINT32 VarLogSize;\r
fa0737a8
SZ
98\r
99 ASSERT ((VarSize == 0 && VarData == NULL) || (VarSize != 0 && VarData != NULL));\r
100\r
1436aea4
MK
101 VarNameLength = StrLen (VarName);\r
102 VarLogSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize\r
103 - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData));\r
fa0737a8 104\r
1436aea4 105 VarLog = (UEFI_VARIABLE_DATA *)AllocateZeroPool (VarLogSize);\r
fa0737a8
SZ
106 if (VarLog == NULL) {\r
107 return EFI_OUT_OF_RESOURCES;\r
108 }\r
109\r
1436aea4 110 CopyMem (&VarLog->VariableName, VendorGuid, sizeof (VarLog->VariableName));\r
fa0737a8
SZ
111 VarLog->UnicodeNameLength = VarNameLength;\r
112 VarLog->VariableDataLength = VarSize;\r
113 CopyMem (\r
1436aea4
MK
114 VarLog->UnicodeName,\r
115 VarName,\r
116 VarNameLength * sizeof (*VarName)\r
117 );\r
fa0737a8
SZ
118 if (VarSize != 0) {\r
119 CopyMem (\r
1436aea4
MK
120 (CHAR16 *)VarLog->UnicodeName + VarNameLength,\r
121 VarData,\r
122 VarSize\r
123 );\r
fa0737a8
SZ
124 }\r
125\r
87000d77
MK
126 DEBUG ((DEBUG_INFO, "VariableDxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)7, (UINTN)EV_EFI_VARIABLE_DRIVER_CONFIG));\r
127 DEBUG ((DEBUG_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid));\r
fa0737a8
SZ
128\r
129 Status = TpmMeasureAndLogData (\r
130 7,\r
131 EV_EFI_VARIABLE_DRIVER_CONFIG,\r
132 VarLog,\r
133 VarLogSize,\r
134 VarLog,\r
135 VarLogSize\r
136 );\r
137 FreePool (VarLog);\r
138 return Status;\r
139}\r
140\r
141/**\r
142 Returns the status whether get the variable success. The function retrieves\r
143 variable through the UEFI Runtime Service GetVariable(). The\r
144 returned buffer is allocated using AllocatePool(). The caller is responsible\r
145 for freeing this buffer with FreePool().\r
146\r
147 This API is only invoked in boot time. It may NOT be invoked at runtime.\r
148\r
149 @param[in] Name The pointer to a Null-terminated Unicode string.\r
150 @param[in] Guid The pointer to an EFI_GUID structure\r
151 @param[out] Value The buffer point saved the variable info.\r
152 @param[out] Size The buffer size of the variable.\r
153\r
154 @return EFI_OUT_OF_RESOURCES Allocate buffer failed.\r
155 @return EFI_SUCCESS Find the specified variable.\r
156 @return Others Errors Return errors from call to gRT->GetVariable.\r
157\r
158**/\r
159EFI_STATUS\r
160InternalGetVariable (\r
161 IN CONST CHAR16 *Name,\r
162 IN CONST EFI_GUID *Guid,\r
163 OUT VOID **Value,\r
164 OUT UINTN *Size\r
165 )\r
166{\r
167 EFI_STATUS Status;\r
168 UINTN BufferSize;\r
169\r
170 //\r
171 // Try to get the variable size.\r
172 //\r
173 BufferSize = 0;\r
174 *Value = NULL;\r
175 if (Size != NULL) {\r
1436aea4 176 *Size = 0;\r
fa0737a8
SZ
177 }\r
178\r
1436aea4 179 Status = gRT->GetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid, NULL, &BufferSize, *Value);\r
fa0737a8
SZ
180 if (Status != EFI_BUFFER_TOO_SMALL) {\r
181 return Status;\r
182 }\r
183\r
184 //\r
185 // Allocate buffer to get the variable.\r
186 //\r
187 *Value = AllocatePool (BufferSize);\r
188 ASSERT (*Value != NULL);\r
189 if (*Value == NULL) {\r
190 return EFI_OUT_OF_RESOURCES;\r
191 }\r
192\r
193 //\r
194 // Get the variable data.\r
195 //\r
1436aea4 196 Status = gRT->GetVariable ((CHAR16 *)Name, (EFI_GUID *)Guid, NULL, &BufferSize, *Value);\r
fa0737a8 197 if (EFI_ERROR (Status)) {\r
1436aea4 198 FreePool (*Value);\r
fa0737a8
SZ
199 *Value = NULL;\r
200 }\r
201\r
202 if (Size != NULL) {\r
203 *Size = BufferSize;\r
204 }\r
205\r
206 return Status;\r
207}\r
208\r
209/**\r
210 SecureBoot Hook for SetVariable.\r
211\r
212 @param[in] VariableName Name of Variable to be found.\r
213 @param[in] VendorGuid Variable vendor GUID.\r
214\r
215**/\r
216VOID\r
217EFIAPI\r
218SecureBootHook (\r
1436aea4
MK
219 IN CHAR16 *VariableName,\r
220 IN EFI_GUID *VendorGuid\r
fa0737a8
SZ
221 )\r
222{\r
1436aea4
MK
223 EFI_STATUS Status;\r
224 UINTN VariableDataSize;\r
225 VOID *VariableData;\r
fa0737a8
SZ
226\r
227 if (!IsSecureBootPolicyVariable (VariableName, VendorGuid)) {\r
1436aea4 228 return;\r
fa0737a8
SZ
229 }\r
230\r
231 //\r
232 // We should NOT use Data and DataSize here,because it may include signature,\r
233 // or is just partial with append attributes, or is deleted.\r
234 // We should GetVariable again, to get full variable content.\r
235 //\r
236 Status = InternalGetVariable (\r
237 VariableName,\r
238 VendorGuid,\r
239 &VariableData,\r
240 &VariableDataSize\r
241 );\r
242 if (EFI_ERROR (Status)) {\r
588bb5ae
ZC
243 //\r
244 // Measure DBT only if present and not empty\r
245 //\r
1436aea4
MK
246 if ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) &&\r
247 CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid))\r
248 {\r
249 DEBUG ((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2));\r
588bb5ae
ZC
250 return;\r
251 } else {\r
252 VariableData = NULL;\r
253 VariableDataSize = 0;\r
254 }\r
fa0737a8
SZ
255 }\r
256\r
257 Status = MeasureVariable (\r
258 VariableName,\r
259 VendorGuid,\r
260 VariableData,\r
261 VariableDataSize\r
262 );\r
87000d77 263 DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status));\r
fa0737a8
SZ
264\r
265 if (VariableData != NULL) {\r
266 FreePool (VariableData);\r
267 }\r
268\r
dc9bd6ed
ZC
269 //\r
270 // "SecureBoot" is 8bit & read-only. It can only be changed according to PK update\r
271 //\r
272 if ((StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0) &&\r
1436aea4
MK
273 CompareGuid (VendorGuid, &gEfiGlobalVariableGuid))\r
274 {\r
275 Status = InternalGetVariable (\r
276 EFI_SECURE_BOOT_MODE_NAME,\r
277 &gEfiGlobalVariableGuid,\r
278 &VariableData,\r
279 &VariableDataSize\r
280 );\r
281 if (EFI_ERROR (Status)) {\r
282 return;\r
283 }\r
284\r
285 //\r
286 // If PK update is successful. "SecureBoot" shall always exist ever since variable write service is ready\r
287 //\r
288 ASSERT (mSecureBootVarData != NULL);\r
289\r
290 if (CompareMem (mSecureBootVarData, VariableData, VariableDataSize) != 0) {\r
291 FreePool (mSecureBootVarData);\r
292 mSecureBootVarData = VariableData;\r
293 mSecureBootVarDataSize = VariableDataSize;\r
294\r
295 DEBUG ((DEBUG_INFO, "%s variable updated according to PK change. Remeasure the value!\n", EFI_SECURE_BOOT_MODE_NAME));\r
296 Status = MeasureVariable (\r
297 EFI_SECURE_BOOT_MODE_NAME,\r
298 &gEfiGlobalVariableGuid,\r
299 mSecureBootVarData,\r
300 mSecureBootVarDataSize\r
301 );\r
302 DEBUG ((DEBUG_INFO, "MeasureBootPolicyVariable - %r\n", Status));\r
303 } else {\r
304 //\r
305 // "SecureBoot" variable is not changed\r
306 //\r
307 FreePool (VariableData);\r
308 }\r
dc9bd6ed
ZC
309 }\r
310\r
1436aea4 311 return;\r
fa0737a8 312}\r
dc9bd6ed
ZC
313\r
314/**\r
315 Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).\r
316 Record their initial State when variable write service is ready.\r
317\r
318**/\r
319VOID\r
320EFIAPI\r
1436aea4 321RecordSecureBootPolicyVarData (\r
dc9bd6ed
ZC
322 VOID\r
323 )\r
324{\r
1436aea4 325 EFI_STATUS Status;\r
dc9bd6ed
ZC
326\r
327 //\r
328 // Record initial "SecureBoot" variable value.\r
329 // It is used to detect SecureBoot variable change in SecureBootHook.\r
330 //\r
331 Status = InternalGetVariable (\r
332 EFI_SECURE_BOOT_MODE_NAME,\r
333 &gEfiGlobalVariableGuid,\r
334 (VOID **)&mSecureBootVarData,\r
335 &mSecureBootVarDataSize\r
336 );\r
1436aea4 337 if (EFI_ERROR (Status)) {\r
dc9bd6ed
ZC
338 //\r
339 // Read could fail when Auth Variable solution is not supported\r
340 //\r
1436aea4 341 DEBUG ((DEBUG_INFO, "RecordSecureBootPolicyVarData GetVariable %s Status %x\n", EFI_SECURE_BOOT_MODE_NAME, Status));\r
dc9bd6ed
ZC
342 }\r
343}\r