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