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