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