TianoCore EDK2 master
Loading...
Searching...
No Matches
CryptPkcs7VerifyEku.c
Go to the documentation of this file.
1
12#include <Base.h>
13#include "InternalCryptLib.h"
14#include <mbedtls/pkcs7.h>
15#include <mbedtls/asn1write.h>
16
17GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 EkuOID[] = { 0x55, 0x1D, 0x25 };
18
19/*leaf Cert basic_constraints case1: CA: false and CA object is excluded */
20GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase1[] = { 0x30, 0x00 };
21
22/*leaf Cert basic_constraints case2: CA: false */
23GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase2[] = { 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 };
24
25GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gOidBasicConstraints[] = { 0x55, 0x1D, 0x13 };
26
39BOOLEAN
41 UINT8 *Start,
42 UINT8 *End,
43 CONST UINT8 *Oid,
44 UINTN OidSize,
45 UINT8 **FindExtensionData,
46 UINTN *FindExtensionDataLen
47 )
48{
49 UINT8 *Ptr;
50 UINT8 *ExtensionPtr;
51 UINTN ObjLen;
52 INT32 Ret;
53 BOOLEAN Status;
54 UINTN FindExtensionLen;
55 UINTN HeaderLen;
56
57 /*If no Extension entry match Oid*/
58 Status = FALSE;
59 Ptr = Start;
60
61 Ret = 0;
62
63 while (TRUE) {
64 //
65 // Extension ::= SEQUENCE {
66 // extnID OBJECT IDENTIFIER,
67 // critical BOOLEAN DEFAULT FALSE,
68 // extnValue OCTET STRING }
69 //
70 ExtensionPtr = Ptr;
71 Ret = mbedtls_asn1_get_tag (
72 &Ptr,
73 End,
74 &ObjLen,
75 MBEDTLS_ASN1_CONSTRUCTED |
76 MBEDTLS_ASN1_SEQUENCE
77 );
78 if (Ret == 0) {
79 HeaderLen = (UINTN)(Ptr - ExtensionPtr);
80 FindExtensionLen = ObjLen;
81 /* Get Object Identifier*/
82 Ret = mbedtls_asn1_get_tag (
83 &Ptr,
84 End,
85 &ObjLen,
86 MBEDTLS_ASN1_OID
87 );
88 } else {
89 break;
90 }
91
92 if ((Ret == 0) && !CompareMem (Ptr, Oid, OidSize)) {
93 Ptr += ObjLen;
94
95 Ret = mbedtls_asn1_get_tag (
96 &Ptr,
97 End,
98 &ObjLen,
99 MBEDTLS_ASN1_BOOLEAN
100 );
101 if (Ret == 0) {
102 Ptr += ObjLen;
103 }
104
105 Ret = mbedtls_asn1_get_tag (
106 &Ptr,
107 End,
108 &ObjLen,
109 MBEDTLS_ASN1_OCTET_STRING
110 );
111 } else {
112 Ret = 1;
113 }
114
115 if (Ret == 0) {
116 *FindExtensionData = Ptr;
117 *FindExtensionDataLen = ObjLen;
118 Status = TRUE;
119 break;
120 }
121
122 /* move to next*/
123 Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;
124 Ret = 0;
125 }
126
127 return Status;
128}
129
149STATIC
150BOOLEAN
152 CONST mbedtls_x509_crt *Cert,
153 CONST UINT8 *Oid,
154 UINTN OidSize,
155 UINT8 *ExtensionData,
156 UINTN *ExtensionDataSize
157 )
158{
159 CONST mbedtls_x509_crt *Crt;
160 INT32 Ret;
161 BOOLEAN Status;
162 UINT8 *Ptr;
163 UINT8 *End;
164 UINTN ObjLen;
165
166 Ptr = NULL;
167 End = NULL;
168 ObjLen = 0;
169
170 if ((Cert == NULL) || (Oid == NULL) || (OidSize == 0) ||
171 (ExtensionDataSize == NULL))
172 {
173 return FALSE;
174 }
175
176 Status = FALSE;
177
178 Crt = Cert;
179
180 Ptr = Crt->v3_ext.p;
181 End = Crt->v3_ext.p + Crt->v3_ext.len;
182 Ret = mbedtls_asn1_get_tag (
183 &Ptr,
184 End,
185 &ObjLen,
186 MBEDTLS_ASN1_CONSTRUCTED |
187 MBEDTLS_ASN1_SEQUENCE
188 );
189
190 if (Ret == 0) {
192 Ptr,
193 End,
194 Oid,
195 OidSize,
196 &Ptr,
197 &ObjLen
198 );
199 }
200
201 if (Status) {
202 if (*ExtensionDataSize < ObjLen) {
203 *ExtensionDataSize = ObjLen;
204 Status = FALSE;
205 goto Cleanup;
206 }
207
208 if (Oid != NULL) {
209 if (ExtensionData == NULL) {
210 return FALSE;
211 }
212
213 CopyMem (ExtensionData, Ptr, ObjLen);
214 }
215
216 *ExtensionDataSize = ObjLen;
217 } else {
218 *ExtensionDataSize = 0;
219 }
220
221Cleanup:
222 return Status;
223}
224
238STATIC
241 IN CONST mbedtls_x509_crt *Cert,
242 IN UINT8 *EKU,
243 IN UINTN EkuLen
244 )
245{
246 EFI_STATUS Status;
247 BOOLEAN Ret;
248 UINT8 *Buffer;
249 UINTN Index;
250 UINTN Len;
251
252 if ((Cert == NULL) || (EKU == NULL)) {
253 Status = EFI_INVALID_PARAMETER;
254 return Status;
255 }
256
257 Len = 0;
258 Buffer = NULL;
259 Ret = GetExtensionData (
260 Cert,
261 (CONST UINT8 *)EkuOID,
262 sizeof (EkuOID),
263 NULL,
264 &Len
265 );
266 if (Len == 0) {
267 Status = EFI_NOT_FOUND;
268 goto Exit;
269 }
270
271 Buffer = AllocateZeroPool (Len);
272 if (Buffer == NULL) {
273 Status = EFI_NOT_FOUND;
274 goto Exit;
275 }
276
277 Ret = GetExtensionData (
278 Cert,
279 (CONST UINT8 *)EkuOID,
280 sizeof (EkuOID),
281 Buffer,
282 &Len
283 );
284
285 if ((Len == 0) || (!Ret)) {
286 Status = EFI_NOT_FOUND;
287 goto Exit;
288 }
289
290 Status = EFI_NOT_FOUND;
291 for (Index = 0; Index <= Len - EkuLen; Index++) {
292 if (!CompareMem (Buffer + Index, EKU, EkuLen)) {
293 // check sub EKU
294 if (Index == Len - EkuLen) {
295 Status = EFI_SUCCESS;
296 break;
297 // Ensure that the OID is complete
298 } else if (Buffer[Index + EkuLen] == 0x06) {
299 Status = EFI_SUCCESS;
300 break;
301 } else {
302 break;
303 }
304 }
305 }
306
307Exit:
308 if (Buffer != NULL) {
309 FreePool (Buffer);
310 }
311
312 return Status;
313}
314
325VOID
327 IN CONST CHAR8 *RequiredEKUs,
328 IN UINTN RequiredEKUsSize,
329 IN OUT UINT8 *CheckOid,
330 OUT UINT8 *OidLen
331 )
332{
333 UINT8 *Ptr;
334 UINT16 Index;
335 UINT32 Data;
336 UINT8 OidIndex;
337 UINTN EKUsSize;
338
339 EKUsSize = RequiredEKUsSize;
340 // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN
341 CheckOid[0] = (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] - '0'));
342
343 EKUsSize = EKUsSize - 4;
344 Ptr = (UINT8 *)(RequiredEKUs + 4);
345
346 OidIndex = 1;
347
348 while (EKUsSize) {
349 Index = 0;
350 Data = 0;
351
352 while ((*Ptr != '.') && (*Ptr != '\0')) {
353 Index++;
354 Ptr++;
355 EKUsSize--;
356 }
357
358 while (Index) {
359 Data = 10 * Data + (*(Ptr - Index) - '0');
360 Index--;
361 }
362
363 if (EKUsSize != 0) {
364 Ptr++;
365 EKUsSize--;
366 }
367
368 if (Data < 128) {
369 CheckOid[OidIndex] = (UINT8)Data;
370 OidIndex++;
371 } else {
372 CheckOid[OidIndex + 1] = (UINT8)(Data & 0xFF);
373 CheckOid[OidIndex] = (UINT8)(((((Data & 0xFF00) << 1) | 0x8000) >> 8) & 0xFF);
374 OidIndex = OidIndex + 2;
375 }
376 }
377
378 *OidLen = OidIndex;
379}
380
390STATIC
391BOOLEAN
393 UINT8 *Start,
394 UINT8 *End
395 )
396{
397 BOOLEAN Status;
398 UINT8 *Buffer;
399 UINTN Len;
400 mbedtls_x509_crt Cert;
401 UINTN ObjLen;
402
403 mbedtls_x509_crt_init (&Cert);
404
405 ObjLen = End - Start;
406
407 if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) != 0) {
408 return FALSE;
409 }
410
411 Len = 0;
412 Buffer = NULL;
413 Status = GetExtensionData (
414 &Cert,
415 (CONST UINT8 *)gOidBasicConstraints,
416 sizeof (gOidBasicConstraints),
417 NULL,
418 &Len
419 );
420 if (Len == 0) {
421 /* basic constraints is not present in Cert */
422 return TRUE;
423 }
424
425 Buffer = AllocateZeroPool (Len);
426 if (Buffer == NULL) {
427 return FALSE;
428 }
429
430 Status = GetExtensionData (
431 &Cert,
432 (CONST UINT8 *)gOidBasicConstraints,
433 sizeof (gOidBasicConstraints),
434 Buffer,
435 &Len
436 );
437
438 if (Len == 0) {
439 /* basic constraints is not present in Cert */
440 Status = TRUE;
441 goto Exit;
442 } else if (!Status) {
443 Status = FALSE;
444 goto Exit;
445 }
446
447 if ((Len == sizeof (gBasicConstraintsCase1)) &&
448 (!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstraintsCase1))))
449 {
450 Status = TRUE;
451 goto Exit;
452 }
453
454 if ((Len == sizeof (gBasicConstraintsCase2)) &&
455 (!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstraintsCase2))))
456 {
457 Status = TRUE;
458 goto Exit;
459 }
460
461 Status = FALSE;
462
463Exit:
464 mbedtls_x509_crt_free (&Cert);
465
466 if (Buffer != NULL) {
467 FreePool (Buffer);
468 }
469
470 return Status;
471}
472
486STATIC
489 IN CONST mbedtls_x509_crt *SignerCert,
490 IN CONST CHAR8 *RequiredEKUs[],
491 IN CONST UINT32 RequiredEKUsSize,
492 IN BOOLEAN RequireAllPresent
493 )
494{
495 EFI_STATUS Status;
496 UINT32 NumEkusFound;
497 UINT32 Index;
498 UINT8 *EKU;
499 UINTN EkuLen;
500 UINT8 CheckOid[20];
501 UINT8 OidLen;
502
503 Status = EFI_SUCCESS;
504 NumEkusFound = 0;
505
506 if ((SignerCert == NULL) || (RequiredEKUs == NULL) || (RequiredEKUsSize == 0)) {
507 Status = EFI_INVALID_PARAMETER;
508 goto Exit;
509 }
510
511 for (Index = 0; Index < RequiredEKUsSize; Index++) {
512 //
513 // Finding required EKU in Cert.
514 //
515 GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), CheckOid, &OidLen);
516
517 EKU = CheckOid;
518 EkuLen = OidLen;
519
520 Status = IsEkuInCertificate (SignerCert, EKU, EkuLen);
521 if (Status == EFI_SUCCESS) {
522 NumEkusFound++;
523 if (!RequireAllPresent) {
524 //
525 // Found at least one, so we are done.
526 //
527 goto Exit;
528 }
529 } else {
530 //
531 // Fail to find Eku in Cert
532 break;
533 }
534 }
535
536Exit:
537 if (RequireAllPresent &&
538 (NumEkusFound == RequiredEKUsSize))
539 {
540 //
541 // Found all required EKUs in certificate.
542 //
543 Status = EFI_SUCCESS;
544 }
545
546 return Status;
547}
548
580EFIAPI
582 IN CONST UINT8 *Pkcs7Signature,
583 IN CONST UINT32 SignatureSize,
584 IN CONST CHAR8 *RequiredEKUs[],
585 IN CONST UINT32 RequiredEKUsSize,
586 IN BOOLEAN RequireAllPresent
587 )
588{
589 EFI_STATUS Status;
590 mbedtls_x509_crt Cert;
591 UINT8 *Ptr;
592 UINT8 *End;
593 INT32 Len;
594 UINTN ObjLen;
595 UINT8 *OldEnd;
596
597 //
598 // Check input parameter.
599 //
600 if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) {
601 Status = EFI_INVALID_PARAMETER;
602 return Status;
603 }
604
605 mbedtls_x509_crt_init (&Cert);
606
607 Ptr = (UINT8 *)(UINTN)Pkcs7Signature;
608 Len = (UINT32)SignatureSize;
609 End = Ptr + Len;
610
611 // Cert
612 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
613 return FALSE;
614 }
615
616 // tbscert
617 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
618 return FALSE;
619 }
620
621 Ptr += ObjLen;
622 // signature algo
623 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
624 return FALSE;
625 }
626
627 Ptr += ObjLen;
628 // signature
629 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
630 return FALSE;
631 }
632
633 Ptr += ObjLen;
634 OldEnd = Ptr;
635 // Cert
636 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
637 return FALSE;
638 }
639
640 End = Ptr + ObjLen;
641
642 // leaf Cert
643 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
644 return FALSE;
645 }
646
647 Ptr += ObjLen;
648
649 while ((Ptr != End) && (Ptr < End)) {
650 if (IsCertSignerCert (OldEnd, Ptr)) {
651 break;
652 }
653
654 OldEnd = Ptr;
655 if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
656 return FALSE;
657 }
658
659 Ptr += ObjLen;
660 }
661
662 if (Ptr != End) {
663 return FALSE;
664 } else {
665 Ptr = End - ObjLen;
666 }
667
668 // leaf Cert
669 ObjLen += Ptr - OldEnd;
670 Ptr = OldEnd;
671
672 if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) != 0) {
673 return FALSE;
674 }
675
676 Status = CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent);
677 if (Status != EFI_SUCCESS) {
678 goto Exit;
679 }
680
681Exit:
682 //
683 // Release Resources
684 //
685 mbedtls_x509_crt_free (&Cert);
686
687 return Status;
688}
UINT64 UINTN
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)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
STATIC EFI_STATUS CheckEKUs(IN CONST X509 *SignerCert, IN CONST CHAR8 *RequiredEKUs[], IN CONST UINT32 RequiredEKUsSize, IN BOOLEAN RequireAllPresent)
STATIC EFI_STATUS IsEkuInCertificate(IN CONST X509 *Cert, IN ASN1_OBJECT *Asn1ToFind)
EFI_STATUS EFIAPI VerifyEKUsInPkcs7Signature(IN CONST UINT8 *Pkcs7Signature, IN CONST UINT32 SignatureSize, IN CONST CHAR8 *RequiredEKUs[], IN CONST UINT32 RequiredEKUsSize, IN BOOLEAN RequireAllPresent)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
STATIC BOOLEAN InternalX509FindExtensionData(UINT8 *Start, UINT8 *End, CONST UINT8 *Oid, UINTN OidSize, UINT8 **FindExtensionData, UINTN *FindExtensionDataLen)
STATIC BOOLEAN IsCertSignerCert(UINT8 *Start, UINT8 *End)
STATIC BOOLEAN GetExtensionData(CONST mbedtls_x509_crt *Cert, CONST UINT8 *Oid, UINTN OidSize, UINT8 *ExtensionData, UINTN *ExtensionDataSize)
VOID GetOidFromTxt(IN CONST CHAR8 *RequiredEKUs, IN UINTN RequiredEKUsSize, IN OUT UINT8 *CheckOid, OUT UINT8 *OidLen)