]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.c
OvmfPkg/EnrollDefaultKeys: extract MICROSOFT_VENDOR_GUID
[mirror_edk2.git] / OvmfPkg / EnrollDefaultKeys / EnrollDefaultKeys.c
CommitLineData
b1163623 1/** @file\r
3defea06 2 Enroll default PK, KEK, db, dbx.\r
b1163623 3\r
3defea06 4 Copyright (C) 2014-2019, Red Hat, Inc.\r
b1163623 5\r
3defea06 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
b1163623
LE
7**/\r
8#include <Guid/AuthenticatedVariableFormat.h> // gEfiCustomModeEnableGuid\r
9#include <Guid/GlobalVariable.h> // EFI_SETUP_MODE_NAME\r
10#include <Guid/ImageAuthentication.h> // EFI_IMAGE_SECURITY_DATABASE\r
7eeaa758 11#include <Guid/MicrosoftVendor.h> // gMicrosoftVendorGuid\r
b1163623
LE
12#include <Library/BaseMemoryLib.h> // CopyGuid()\r
13#include <Library/DebugLib.h> // ASSERT()\r
14#include <Library/MemoryAllocationLib.h> // FreePool()\r
15#include <Library/ShellCEntryLib.h> // ShellAppMain()\r
16#include <Library/UefiLib.h> // AsciiPrint()\r
17#include <Library/UefiRuntimeServicesTableLib.h> // gRT\r
18\r
1c9418fc
LE
19#include "EnrollDefaultKeys.h"\r
20\r
b1163623
LE
21/**\r
22 Enroll a set of certificates in a global variable, overwriting it.\r
23\r
24 The variable will be rewritten with NV+BS+RT+AT attributes.\r
25\r
26 @param[in] VariableName The name of the variable to overwrite.\r
27\r
28 @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to\r
29 overwrite.\r
30\r
31 @param[in] CertType The GUID determining the type of all the\r
32 certificates in the set that is passed in. For\r
33 example, gEfiCertX509Guid stands for DER-encoded\r
34 X.509 certificates, while gEfiCertSha256Guid stands\r
35 for SHA256 image hashes.\r
36\r
37 @param[in] ... A list of\r
38\r
39 IN CONST UINT8 *Cert,\r
40 IN UINTN CertSize,\r
41 IN CONST EFI_GUID *OwnerGuid\r
42\r
43 triplets. If the first component of a triplet is\r
44 NULL, then the other two components are not\r
45 accessed, and processing is terminated. The list of\r
46 certificates is enrolled in the variable specified,\r
47 overwriting it. The OwnerGuid component identifies\r
48 the agent installing the certificate.\r
49\r
50 @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert\r
51 value is NULL), or one of the CertSize values\r
52 is 0, or one of the CertSize values would\r
53 overflow the accumulated UINT32 data size.\r
54\r
55 @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable\r
56 payload.\r
57\r
58 @retval EFI_SUCCESS Enrollment successful; the variable has been\r
59 overwritten (or created).\r
60\r
61 @return Error codes from gRT->GetTime() and\r
62 gRT->SetVariable().\r
63**/\r
64STATIC\r
65EFI_STATUS\r
66EFIAPI\r
67EnrollListOfCerts (\r
68 IN CHAR16 *VariableName,\r
69 IN EFI_GUID *VendorGuid,\r
70 IN EFI_GUID *CertType,\r
71 ...\r
72 )\r
73{\r
74 UINTN DataSize;\r
75 SINGLE_HEADER *SingleHeader;\r
76 REPEATING_HEADER *RepeatingHeader;\r
77 VA_LIST Marker;\r
78 CONST UINT8 *Cert;\r
79 EFI_STATUS Status;\r
80 UINT8 *Data;\r
81 UINT8 *Position;\r
82\r
83 Status = EFI_SUCCESS;\r
84\r
85 //\r
86 // compute total size first, for UINT32 range check, and allocation\r
87 //\r
88 DataSize = sizeof *SingleHeader;\r
89 VA_START (Marker, CertType);\r
90 for (Cert = VA_ARG (Marker, CONST UINT8 *);\r
91 Cert != NULL;\r
92 Cert = VA_ARG (Marker, CONST UINT8 *)) {\r
93 UINTN CertSize;\r
94\r
95 CertSize = VA_ARG (Marker, UINTN);\r
96 (VOID)VA_ARG (Marker, CONST EFI_GUID *);\r
97\r
98 if (CertSize == 0 ||\r
99 CertSize > MAX_UINT32 - sizeof *RepeatingHeader ||\r
100 DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) {\r
101 Status = EFI_INVALID_PARAMETER;\r
102 break;\r
103 }\r
104 DataSize += sizeof *RepeatingHeader + CertSize;\r
105 }\r
106 VA_END (Marker);\r
107\r
108 if (DataSize == sizeof *SingleHeader) {\r
109 Status = EFI_INVALID_PARAMETER;\r
110 }\r
111 if (EFI_ERROR (Status)) {\r
112 goto Out;\r
113 }\r
114\r
115 Data = AllocatePool (DataSize);\r
116 if (Data == NULL) {\r
117 Status = EFI_OUT_OF_RESOURCES;\r
118 goto Out;\r
119 }\r
120\r
121 Position = Data;\r
122\r
123 SingleHeader = (SINGLE_HEADER *)Position;\r
124 Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL);\r
125 if (EFI_ERROR (Status)) {\r
126 goto FreeData;\r
127 }\r
128 SingleHeader->TimeStamp.Pad1 = 0;\r
129 SingleHeader->TimeStamp.Nanosecond = 0;\r
130 SingleHeader->TimeStamp.TimeZone = 0;\r
131 SingleHeader->TimeStamp.Daylight = 0;\r
132 SingleHeader->TimeStamp.Pad2 = 0;\r
133#if 0\r
134 SingleHeader->dwLength = DataSize - sizeof SingleHeader->TimeStamp;\r
135#else\r
136 //\r
137 // This looks like a bug in edk2. According to the UEFI specification,\r
138 // dwLength is "The length of the entire certificate, including the length of\r
139 // the header, in bytes". That shouldn't stop right after CertType -- it\r
140 // should include everything below it.\r
141 //\r
142 SingleHeader->dwLength = sizeof *SingleHeader\r
143 - sizeof SingleHeader->TimeStamp;\r
144#endif\r
145 SingleHeader->wRevision = 0x0200;\r
146 SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID;\r
147 CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid);\r
148 Position += sizeof *SingleHeader;\r
149\r
150 VA_START (Marker, CertType);\r
151 for (Cert = VA_ARG (Marker, CONST UINT8 *);\r
152 Cert != NULL;\r
153 Cert = VA_ARG (Marker, CONST UINT8 *)) {\r
154 UINTN CertSize;\r
155 CONST EFI_GUID *OwnerGuid;\r
156\r
157 CertSize = VA_ARG (Marker, UINTN);\r
158 OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *);\r
159\r
160 RepeatingHeader = (REPEATING_HEADER *)Position;\r
161 CopyGuid (&RepeatingHeader->SignatureType, CertType);\r
162 RepeatingHeader->SignatureListSize =\r
163 (UINT32)(sizeof *RepeatingHeader + CertSize);\r
164 RepeatingHeader->SignatureHeaderSize = 0;\r
165 RepeatingHeader->SignatureSize =\r
166 (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize);\r
167 CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid);\r
168 Position += sizeof *RepeatingHeader;\r
169\r
170 CopyMem (Position, Cert, CertSize);\r
171 Position += CertSize;\r
172 }\r
173 VA_END (Marker);\r
174\r
175 ASSERT (Data + DataSize == Position);\r
176\r
177 Status = gRT->SetVariable (VariableName, VendorGuid,\r
178 (EFI_VARIABLE_NON_VOLATILE |\r
179 EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
180 EFI_VARIABLE_RUNTIME_ACCESS |\r
181 EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),\r
182 DataSize, Data);\r
183\r
184FreeData:\r
185 FreePool (Data);\r
186\r
187Out:\r
188 if (EFI_ERROR (Status)) {\r
189 AsciiPrint ("error: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName,\r
190 VendorGuid, Status);\r
191 }\r
192 return Status;\r
193}\r
194\r
195\r
196STATIC\r
197EFI_STATUS\r
b1163623
LE
198GetExact (\r
199 IN CHAR16 *VariableName,\r
200 IN EFI_GUID *VendorGuid,\r
201 OUT VOID *Data,\r
202 IN UINTN DataSize,\r
203 IN BOOLEAN AllowMissing\r
204 )\r
205{\r
206 UINTN Size;\r
207 EFI_STATUS Status;\r
208\r
209 Size = DataSize;\r
210 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data);\r
211 if (EFI_ERROR (Status)) {\r
212 if (Status == EFI_NOT_FOUND && AllowMissing) {\r
213 ZeroMem (Data, DataSize);\r
214 return EFI_SUCCESS;\r
215 }\r
216\r
217 AsciiPrint ("error: GetVariable(\"%s\", %g): %r\n", VariableName,\r
218 VendorGuid, Status);\r
219 return Status;\r
220 }\r
221\r
222 if (Size != DataSize) {\r
223 AsciiPrint ("error: GetVariable(\"%s\", %g): expected size 0x%Lx, "\r
224 "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size);\r
225 return EFI_PROTOCOL_ERROR;\r
226 }\r
227\r
228 return EFI_SUCCESS;\r
229}\r
230\r
b1163623
LE
231STATIC\r
232EFI_STATUS\r
b1163623
LE
233GetSettings (\r
234 OUT SETTINGS *Settings\r
235 )\r
236{\r
237 EFI_STATUS Status;\r
238\r
239 Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid,\r
240 &Settings->SetupMode, sizeof Settings->SetupMode, FALSE);\r
241 if (EFI_ERROR (Status)) {\r
242 return Status;\r
243 }\r
244\r
245 Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid,\r
246 &Settings->SecureBoot, sizeof Settings->SecureBoot, FALSE);\r
247 if (EFI_ERROR (Status)) {\r
248 return Status;\r
249 }\r
250\r
251 Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME,\r
252 &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable,\r
253 sizeof Settings->SecureBootEnable, TRUE);\r
254 if (EFI_ERROR (Status)) {\r
255 return Status;\r
256 }\r
257\r
258 Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,\r
259 &Settings->CustomMode, sizeof Settings->CustomMode, FALSE);\r
260 if (EFI_ERROR (Status)) {\r
261 return Status;\r
262 }\r
263\r
264 Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid,\r
265 &Settings->VendorKeys, sizeof Settings->VendorKeys, FALSE);\r
266 return Status;\r
267}\r
268\r
269STATIC\r
270VOID\r
b1163623
LE
271PrintSettings (\r
272 IN CONST SETTINGS *Settings\r
273 )\r
274{\r
275 AsciiPrint ("info: SetupMode=%d SecureBoot=%d SecureBootEnable=%d "\r
276 "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot,\r
277 Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys);\r
278}\r
279\r
280\r
281INTN\r
282EFIAPI\r
283ShellAppMain (\r
284 IN UINTN Argc,\r
285 IN CHAR16 **Argv\r
286 )\r
287{\r
288 EFI_STATUS Status;\r
289 SETTINGS Settings;\r
290\r
291 Status = GetSettings (&Settings);\r
292 if (EFI_ERROR (Status)) {\r
293 return 1;\r
294 }\r
295 PrintSettings (&Settings);\r
296\r
297 if (Settings.SetupMode != 1) {\r
298 AsciiPrint ("error: already in User Mode\n");\r
299 return 1;\r
300 }\r
301\r
302 if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) {\r
303 Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE;\r
304 Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,\r
305 (EFI_VARIABLE_NON_VOLATILE |\r
306 EFI_VARIABLE_BOOTSERVICE_ACCESS),\r
307 sizeof Settings.CustomMode, &Settings.CustomMode);\r
308 if (EFI_ERROR (Status)) {\r
309 AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,\r
310 &gEfiCustomModeEnableGuid, Status);\r
311 return 1;\r
312 }\r
313 }\r
314\r
315 Status = EnrollListOfCerts (\r
316 EFI_IMAGE_SECURITY_DATABASE,\r
317 &gEfiImageSecurityDatabaseGuid,\r
318 &gEfiCertX509Guid,\r
7eeaa758
LE
319 mMicrosoftPca, mSizeOfMicrosoftPca, &gMicrosoftVendorGuid,\r
320 mMicrosoftUefiCa, mSizeOfMicrosoftUefiCa, &gMicrosoftVendorGuid,\r
b1163623
LE
321 NULL);\r
322 if (EFI_ERROR (Status)) {\r
323 return 1;\r
324 }\r
325\r
326 Status = EnrollListOfCerts (\r
327 EFI_IMAGE_SECURITY_DATABASE1,\r
328 &gEfiImageSecurityDatabaseGuid,\r
329 &gEfiCertSha256Guid,\r
a79b115a 330 mSha256OfDevNull, mSizeOfSha256OfDevNull, &gEfiCallerIdGuid,\r
b1163623
LE
331 NULL);\r
332 if (EFI_ERROR (Status)) {\r
333 return 1;\r
334 }\r
335\r
336 Status = EnrollListOfCerts (\r
337 EFI_KEY_EXCHANGE_KEY_NAME,\r
338 &gEfiGlobalVariableGuid,\r
339 &gEfiCertX509Guid,\r
a79b115a 340 mRedHatPkKek1, mSizeOfRedHatPkKek1, &gEfiCallerIdGuid,\r
7eeaa758 341 mMicrosoftKek, mSizeOfMicrosoftKek, &gMicrosoftVendorGuid,\r
b1163623
LE
342 NULL);\r
343 if (EFI_ERROR (Status)) {\r
344 return 1;\r
345 }\r
346\r
347 Status = EnrollListOfCerts (\r
348 EFI_PLATFORM_KEY_NAME,\r
349 &gEfiGlobalVariableGuid,\r
350 &gEfiCertX509Guid,\r
a79b115a 351 mRedHatPkKek1, mSizeOfRedHatPkKek1, &gEfiGlobalVariableGuid,\r
b1163623
LE
352 NULL);\r
353 if (EFI_ERROR (Status)) {\r
354 return 1;\r
355 }\r
356\r
357 Settings.CustomMode = STANDARD_SECURE_BOOT_MODE;\r
358 Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid,\r
359 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
360 sizeof Settings.CustomMode, &Settings.CustomMode);\r
361 if (EFI_ERROR (Status)) {\r
362 AsciiPrint ("error: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME,\r
363 &gEfiCustomModeEnableGuid, Status);\r
364 return 1;\r
365 }\r
366\r
367 Status = GetSettings (&Settings);\r
368 if (EFI_ERROR (Status)) {\r
369 return 1;\r
370 }\r
371 PrintSettings (&Settings);\r
372\r
373 if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 ||\r
374 Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 ||\r
375 Settings.VendorKeys != 0) {\r
376 AsciiPrint ("error: unexpected\n");\r
377 return 1;\r
378 }\r
379\r
380 AsciiPrint ("info: success\n");\r
381 return 0;\r
382}\r