OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
TlsAuthConfigImpl.c
Go to the documentation of this file.
1
10
11#define TLS_AUTH_CONFIG_VAR_BASE_ATTR (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
12
13typedef
14EFI_STATUS
16 IN VOID *Context,
17 IN UINTN CertIndex,
18 IN UINTN CertSize,
19 IN EFI_SIGNATURE_DATA *Cert
20 );
21
22typedef struct {
23 EFI_GUID *OwnerGuid;
25 VOID *X509Data;
27
41STATIC
42EFI_STATUS
44 IN CHAR16 *VariableName,
45 IN EFI_GUID *VendorGuid,
46 IN PROCESS_CERT ProcessCert,
47 IN VOID *Context OPTIONAL
48 )
49{
50 EFI_STATUS Status;
51 UINT32 Index;
52 UINTN CertCount;
53 UINTN GuidIndex;
54 UINTN DataSize;
55 UINT8 *Data;
56 EFI_SIGNATURE_LIST *CertList;
57 EFI_SIGNATURE_DATA *Cert;
58 UINT32 ItemDataSize;
59
60 ASSERT (ProcessCert != NULL);
61
62 Data = NULL;
63 CertList = NULL;
64 Cert = NULL;
65
66 //
67 // Read Variable.
68 //
69 DataSize = 0;
70 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
71 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
72 if (Status == EFI_NOT_FOUND) {
73 Status = EFI_SUCCESS;
74 }
75
76 return Status;
77 }
78
79 Data = (UINT8 *)AllocateZeroPool (DataSize);
80 if (Data == NULL) {
81 return EFI_OUT_OF_RESOURCES;
82 }
83
84 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
85 if (EFI_ERROR (Status)) {
86 FreePool (Data);
87 return Status;
88 }
89
90 //
91 // Enumerate all data.
92 //
93 ItemDataSize = (UINT32)DataSize;
94 CertList = (EFI_SIGNATURE_LIST *)Data;
95 GuidIndex = 0;
96
97 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
98 if (!CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
99 //
100 // The signature type is not supported in current implementation.
101 //
102 ItemDataSize -= CertList->SignatureListSize;
103 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
104 continue;
105 }
106
107 Status = EFI_SUCCESS;
108 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
109 for (Index = 0; Index < CertCount; Index++) {
110 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList
111 + sizeof (EFI_SIGNATURE_LIST)
112 + CertList->SignatureHeaderSize
113 + Index * CertList->SignatureSize);
114
115 Status = ProcessCert (Context, GuidIndex, CertList->SignatureSize, Cert);
116 if (EFI_ERROR (Status)) {
117 break;
118 }
119
120 ++GuidIndex;
121 }
122
123 if (EFI_ERROR (Status)) {
124 break;
125 }
126
127 ItemDataSize -= CertList->SignatureListSize;
128 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
129 }
130
131 FreePool (Data);
132
133 return Status;
134}
135
139STATIC
140EFI_STATUS
142 IN VOID *Context,
143 IN UINTN CertIndex,
144 IN UINTN CertSize,
145 IN EFI_SIGNATURE_DATA *Cert
146 )
147{
148 DEBUG ((DEBUG_INFO, "NETB: Cert %u owner %g\n", CertIndex, &Cert->SignatureOwner));
149 return EFI_SUCCESS;
150}
151
160EFI_STATUS
162 IN CHAR16 *VariableName,
163 IN EFI_GUID *VendorGuid
164 )
165{
166 DEBUG ((DEBUG_INFO, "NETB: Listing installed certs...\n"));
167 return ProcessAllCerts (
168 VariableName,
169 VendorGuid,
170 LogCert,
171 NULL
172 );
173}
174
179STATIC
180EFI_STATUS
182 IN VOID *VoidContext,
183 IN UINTN CertIndex,
184 IN UINTN CertSize,
185 IN EFI_SIGNATURE_DATA *Cert
186 )
187{
189
190 Context = VoidContext;
191
192 if (!CompareGuid (&Cert->SignatureOwner, Context->OwnerGuid)) {
193 return EFI_SUCCESS;
194 }
195
196 if ( (CertSize == sizeof (EFI_SIGNATURE_DATA) - 1 + Context->X509DataSize)
197 && (CompareMem (Cert->SignatureData, Context->X509Data, Context->X509DataSize) == 0)
198 )
199 {
200 return EFI_ALREADY_STARTED;
201 }
202
203 return EFI_SUCCESS;
204}
205
218EFI_STATUS
220 IN CHAR16 *VariableName,
221 IN EFI_GUID *VendorGuid,
222 IN EFI_GUID *OwnerGuid,
223 IN UINTN X509DataSize,
224 IN VOID *X509Data
225 )
226{
228
229 ASSERT (X509Data != NULL);
230
231 Context.OwnerGuid = OwnerGuid;
232 Context.X509DataSize = X509DataSize;
233 Context.X509Data = X509Data;
234
235 return ProcessAllCerts (
236 VariableName,
237 VendorGuid,
239 &Context
240 );
241}
242
258EFI_STATUS
260 IN CHAR16 *VariableName,
261 IN EFI_GUID *VendorGuid,
262 IN EFI_GUID *OwnerGuid,
263 IN UINTN X509DataSize,
264 IN VOID *X509Data,
265 OUT UINTN *DeletedCount
266 )
267{
268 EFI_STATUS Status;
269 UINTN DataSize;
270 UINT8 *Data;
271 UINT8 *OldData;
272 UINT32 Attr;
273 UINT32 Index;
274 EFI_SIGNATURE_LIST *CertList;
275 EFI_SIGNATURE_LIST *NewCertList;
276 EFI_SIGNATURE_DATA *Cert;
277 UINTN CertCount;
278 UINT32 Offset;
279 UINTN LocalDeleteCount;
280 UINT32 ItemDataSize;
281
282 ASSERT ((X509Data == NULL) || (X509DataSize != 0));
283
284 if (DeletedCount == NULL) {
285 DeletedCount = &LocalDeleteCount;
286 }
287
288 *DeletedCount = 0;
289
290 Data = NULL;
291 OldData = NULL;
292 CertList = NULL;
293 Cert = NULL;
294 Attr = 0;
295
296 //
297 // Get original signature list data.
298 //
299 DataSize = 0;
300 Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
301 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
302 if (Status == EFI_NOT_FOUND) {
303 Status = EFI_SUCCESS;
304 }
305
306 return Status;
307 }
308
309 OldData = AllocateZeroPool (DataSize);
310 if (OldData == NULL) {
311 return EFI_OUT_OF_RESOURCES;
312 }
313
314 Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
315 if (EFI_ERROR (Status)) {
316 FreePool (OldData);
317 return Status;
318 }
319
320 //
321 // Allocate space for new variable.
322 //
323 Data = AllocateZeroPool (DataSize);
324 if (Data == NULL) {
325 FreePool (OldData);
326 return EFI_OUT_OF_RESOURCES;
327 }
328
329 //
330 // Enumerate all data, erasing target items.
331 //
332 ItemDataSize = (UINT32)DataSize;
333 CertList = (EFI_SIGNATURE_LIST *)OldData;
334 Offset = 0;
335 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
336 if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
337 //
338 // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
339 //
340 CopyMem (Data + Offset, CertList, (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
341 NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset);
342 Offset += (sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
343 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
344 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
345 for (Index = 0; Index < CertCount; Index++) {
346 if ( CompareGuid (&Cert->SignatureOwner, OwnerGuid)
347 && ( (X509Data == NULL)
348 || ( (CertList->SignatureSize == (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize))
349 && (CompareMem ((UINT8 *)(Cert->SignatureData), X509Data, X509DataSize) == 0)
350 )
351 )
352 )
353 {
354 //
355 // Find it! Skip it!
356 //
357 NewCertList->SignatureListSize -= CertList->SignatureSize;
358 ++(*DeletedCount);
359 } else {
360 //
361 // This item doesn't match. Copy it to the Data buffer.
362 //
363 CopyMem (Data + Offset, (UINT8 *)(Cert), CertList->SignatureSize);
364 Offset += CertList->SignatureSize;
365 }
366
367 Cert = (EFI_SIGNATURE_DATA *)((UINT8 *)Cert + CertList->SignatureSize);
368 }
369 } else {
370 //
371 // This List doesn't match. Just copy it to the Data buffer.
372 //
373 CopyMem (Data + Offset, (UINT8 *)(CertList), CertList->SignatureListSize);
374 Offset += CertList->SignatureListSize;
375 }
376
377 ItemDataSize -= CertList->SignatureListSize;
378 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
379 }
380
381 if (*DeletedCount != 0) {
382 //
383 // Delete the EFI_SIGNATURE_LIST header if there is no signature remaining in any list.
384 //
385 ItemDataSize = Offset;
386 CertList = (EFI_SIGNATURE_LIST *)Data;
387 Offset = 0;
388 ZeroMem (OldData, ItemDataSize);
389 while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
390 CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
391 if (CertCount != 0) {
392 CopyMem (OldData + Offset, (UINT8 *)(CertList), CertList->SignatureListSize);
393 Offset += CertList->SignatureListSize;
394 }
395
396 ItemDataSize -= CertList->SignatureListSize;
397 CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize);
398 }
399
400 DataSize = Offset;
401
402 //
403 // Set (or delete if everything was removed) the Variable.
404 //
405 Status = gRT->SetVariable (
406 VariableName,
407 VendorGuid,
408 Attr,
409 DataSize,
410 OldData
411 );
412 }
413
414 FreePool (Data);
415 FreePool (OldData);
416
417 return Status;
418}
419
432EFI_STATUS
434 IN CHAR16 *VariableName,
435 IN EFI_GUID *VendorGuid,
436 IN EFI_GUID *OwnerGuid,
437 IN UINTN X509DataSize,
438 IN VOID *X509Data
439 )
440{
441 EFI_STATUS Status;
442 EFI_SIGNATURE_LIST *CACert;
443 EFI_SIGNATURE_DATA *CACertData;
444 VOID *Data;
445 UINTN DataSize;
446 UINTN SigDataSize;
447 UINT32 Attr;
448
449 SigDataSize = 0;
450 DataSize = 0;
451 CACert = NULL;
452 CACertData = NULL;
453 Data = NULL;
454 Attr = 0;
455
456 ASSERT (X509Data != NULL);
457
458 //
459 // Note: As implemented in EDK 2, each signature list can have multiple
460 // instances of signature data (owner guid followed by raw signature data),
461 // but every instance in one list must have the same size.
462 // The signature data is the unprocessed contents of a .pem or .der file.
463 // It is not immediately obvious how the multiple signature feature would
464 // be useful as signature file data does not in general have a fixed size
465 // (not even for .pem files: https://security.stackexchange.com/q/152584).
466 //
467 SigDataSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize;
468
469 Data = AllocateZeroPool (SigDataSize);
470 if (Data == NULL) {
471 return EFI_OUT_OF_RESOURCES;
472 }
473
474 //
475 // Fill Certificate Database parameters.
476 //
477 CACert = (EFI_SIGNATURE_LIST *)Data;
478 CACert->SignatureListSize = (UINT32)SigDataSize;
479 CACert->SignatureHeaderSize = 0;
480 CACert->SignatureSize = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + X509DataSize);
481 CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
482
483 CACertData = (EFI_SIGNATURE_DATA *)((UINT8 *)CACert + sizeof (EFI_SIGNATURE_LIST));
484 CopyGuid (&CACertData->SignatureOwner, OwnerGuid);
485 CopyMem ((UINT8 *)(CACertData->SignatureData), X509Data, X509DataSize);
486
487 //
488 // Check if the signature database entry already exists. If it does, use the
489 // EFI_VARIABLE_APPEND_WRITE attribute to append the new signature data to
490 // the original variable, plus preserve the original variable attributes.
491 //
492 Status = gRT->GetVariable (
493 VariableName,
494 VendorGuid,
495 &Attr,
496 &DataSize,
497 NULL
498 );
499 if (Status == EFI_BUFFER_TOO_SMALL) {
500 Attr |= EFI_VARIABLE_APPEND_WRITE;
501 } else if (Status == EFI_NOT_FOUND) {
503 } else {
504 FreePool (Data);
505 return Status;
506 }
507
508 Status = gRT->SetVariable (
509 VariableName,
510 VendorGuid,
511 Attr,
512 SigDataSize,
513 Data
514 );
515
516 FreePool (Data);
517
518 return Status;
519}
EFI_STATUS LogInstalledCerts(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid)
EFI_STATUS EnrollX509toVariable(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN EFI_GUID *OwnerGuid, IN UINTN X509DataSize, IN VOID *X509Data)
EFI_STATUS DeleteCertsForOwner(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN EFI_GUID *OwnerGuid, IN UINTN X509DataSize, IN VOID *X509Data, OUT UINTN *DeletedCount)
EFI_STATUS CertIsPresent(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN EFI_GUID *OwnerGuid, IN UINTN X509DataSize, IN VOID *X509Data)
#define TLS_AUTH_CONFIG_VAR_BASE_ATTR
STATIC EFI_STATUS CheckCertPresent(IN VOID *VoidContext, IN UINTN CertIndex, IN UINTN CertSize, IN EFI_SIGNATURE_DATA *Cert)
STATIC EFI_STATUS ProcessAllCerts(IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN PROCESS_CERT ProcessCert, IN VOID *Context OPTIONAL)
STATIC EFI_STATUS LogCert(IN VOID *Context, IN UINTN CertIndex, IN UINTN CertSize, IN EFI_SIGNATURE_DATA *Cert)
EFI_STATUS(* PROCESS_CERT)(IN VOID *Context, IN UINTN CertIndex, IN UINTN CertSize, IN EFI_SIGNATURE_DATA *Cert)
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
#define ASSERT(x)
Definition coder.h:55