]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Pkcs7Verify/Pkcs7VerifyDxe/Pkcs7VerifyDxe.c
0da549a6bd57a09071c1c2d1fc4819e566bc50ab
[mirror_edk2.git] / SecurityPkg / Pkcs7Verify / Pkcs7VerifyDxe / Pkcs7VerifyDxe.c
1 /** @file
2 Pkcs7Verify Driver to produce the UEFI PKCS7 Verification Protocol.
3
4 The driver will produce the UEFI PKCS7 Verification Protocol which is used to
5 verify data signed using PKCS7 structure. The PKCS7 data to be verified must
6 be ASN.1 (DER) encoded.
7
8 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/MemoryAllocationLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/BaseCryptLib.h>
24 #include <Protocol/Pkcs7Verify.h>
25
26 #define MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
27
28 /**
29 Calculates the hash of the given data based on the specified hash GUID.
30
31 @param[in] Data Pointer to the data buffer to be hashed.
32 @param[in] DataSize The size of data buffer in bytes.
33 @param[in] CertGuid The GUID to identify the hash algorithm to be used.
34 @param[out] HashValue Pointer to a buffer that receives the hash result.
35
36 @retval TRUE Data hash calculation succeeded.
37 @retval FALSE Data hash calculation failed.
38
39 **/
40 BOOLEAN
41 CalculateDataHash (
42 IN VOID *Data,
43 IN UINTN DataSize,
44 IN EFI_GUID *CertGuid,
45 OUT UINT8 *HashValue
46 )
47 {
48 BOOLEAN Status;
49 VOID *HashCtx;
50 UINTN CtxSize;
51
52 Status = FALSE;
53 HashCtx = NULL;
54
55 if (CompareGuid (CertGuid, &gEfiCertSha1Guid)) {
56 //
57 // SHA-1 Hash
58 //
59 CtxSize = Sha1GetContextSize ();
60 HashCtx = AllocatePool (CtxSize);
61 if (HashCtx == NULL) {
62 goto _Exit;
63 }
64 Status = Sha1Init (HashCtx);
65 Status = Sha1Update (HashCtx, Data, DataSize);
66 Status = Sha1Final (HashCtx, HashValue);
67
68 } else if (CompareGuid (CertGuid, &gEfiCertSha256Guid)) {
69 //
70 // SHA256 Hash
71 //
72 CtxSize = Sha256GetContextSize ();
73 HashCtx = AllocatePool (CtxSize);
74 if (HashCtx == NULL) {
75 goto _Exit;
76 }
77 Status = Sha256Init (HashCtx);
78 Status = Sha256Update (HashCtx, Data, DataSize);
79 Status = Sha256Final (HashCtx, HashValue);
80
81 } else if (CompareGuid (CertGuid, &gEfiCertSha384Guid)) {
82 //
83 // SHA384 Hash
84 //
85 CtxSize = Sha384GetContextSize ();
86 HashCtx = AllocatePool (CtxSize);
87 if (HashCtx == NULL) {
88 goto _Exit;
89 }
90 Status = Sha384Init (HashCtx);
91 Status = Sha384Update (HashCtx, Data, DataSize);
92 Status = Sha384Final (HashCtx, HashValue);
93
94 } else if (CompareGuid (CertGuid, &gEfiCertSha512Guid)) {
95 //
96 // SHA512 Hash
97 //
98 CtxSize = Sha512GetContextSize ();
99 HashCtx = AllocatePool (CtxSize);
100 if (HashCtx == NULL) {
101 goto _Exit;
102 }
103 Status = Sha512Init (HashCtx);
104 Status = Sha512Update (HashCtx, Data, DataSize);
105 Status = Sha512Final (HashCtx, HashValue);
106 }
107
108 _Exit:
109 if (HashCtx != NULL) {
110 FreePool (HashCtx);
111 }
112
113 return Status;
114 }
115
116 /**
117 Check whether the hash of data content is revoked by the revocation database.
118
119 @param[in] Hash Pointer to the hash that is searched for.
120 @param[in] HashSize The size of the hash in bytes.
121 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
122 structure which contains list of X.509 certificates
123 of revoked signers and revoked content hashes.
124
125 @return TRUE The matched content hash is found in the revocation database.
126 @return FALSE The matched content hash is not found in the revocation database.
127
128 **/
129 BOOLEAN
130 IsContentHashRevokedByHash (
131 IN UINT8 *Hash,
132 IN UINTN HashSize,
133 IN EFI_SIGNATURE_LIST **RevokedDb
134 )
135 {
136 EFI_SIGNATURE_LIST *SigList;
137 EFI_SIGNATURE_DATA *SigData;
138 UINTN Index;
139 UINTN EntryIndex;
140 UINTN EntryCount;
141 BOOLEAN Status;
142
143 if (RevokedDb == NULL) {
144 return FALSE;
145 }
146
147 Status = FALSE;
148 //
149 // Check if any hash matching content hash can be found in RevokedDB
150 //
151 for (Index = 0; ; Index++) {
152 SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]);
153
154 //
155 // The list is terminated by a NULL pointer.
156 //
157 if (SigList == NULL) {
158 break;
159 }
160
161 //
162 // Search the signature database to search the revoked content hash
163 //
164 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
165 SigList->SignatureHeaderSize);
166 EntryCount = (SigList->SignatureListSize - SigList->SignatureHeaderSize -
167 sizeof (EFI_SIGNATURE_LIST)) / SigList->SignatureSize;
168 for (EntryIndex = 0; EntryIndex < EntryCount; EntryIndex++) {
169 //
170 // The problem case. There's a revocation hash but the sizes
171 // don't match, meaning it's a different hash algorithm and we
172 // can't tell if it's revoking our binary or not. Assume not.
173 //
174 if (SigList->SignatureSize - sizeof(EFI_GUID) == HashSize) {
175 //
176 // Compare Data Hash with Signature Data
177 //
178 if (CompareMem (SigData->SignatureData, Hash, HashSize) == 0) {
179 Status = TRUE;
180 goto _Exit;
181 }
182 }
183
184 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigData + SigList->SignatureSize);
185 }
186 }
187
188 _Exit:
189 return Status;
190 }
191
192 /**
193 Check whether the hash of data content is revoked by the revocation database.
194
195 @param[in] Content Pointer to the content buffer that is searched for.
196 @param[in] ContentSize The size of data content in bytes.
197 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
198 structure which contains list of X.509 certificates
199 of revoked signers and revoked content hashes.
200
201 @return TRUE The matched content hash is found in the revocation database.
202 @return FALSE The matched content hash is not found in the revocation database.
203
204 **/
205 BOOLEAN
206 IsContentHashRevoked (
207 IN UINT8 *Content,
208 IN UINTN ContentSize,
209 IN EFI_SIGNATURE_LIST **RevokedDb
210 )
211 {
212 EFI_SIGNATURE_LIST *SigList;
213 EFI_SIGNATURE_DATA *SigData;
214 UINTN Index;
215 UINT8 HashVal[MAX_DIGEST_SIZE];
216 UINTN EntryIndex;
217 UINTN EntryCount;
218 BOOLEAN Status;
219
220 if (RevokedDb == NULL) {
221 return FALSE;
222 }
223
224 Status = FALSE;
225 //
226 // Check if any hash matching content hash can be found in RevokedDB
227 //
228 for (Index = 0; ; Index++) {
229 SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]);
230
231 //
232 // The list is terminated by a NULL pointer.
233 //
234 if (SigList == NULL) {
235 break;
236 }
237
238 //
239 // Calculate the digest of supplied data based on the signature hash type.
240 //
241 if (!CalculateDataHash (Content, ContentSize, &SigList->SignatureType, HashVal)) {
242 //
243 // Un-matched Hash GUID or other failure.
244 //
245 continue;
246 }
247
248 //
249 // Search the signature database to search the revoked content hash
250 //
251 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
252 SigList->SignatureHeaderSize);
253 EntryCount = (SigList->SignatureListSize - SigList->SignatureHeaderSize -
254 sizeof (EFI_SIGNATURE_LIST)) / SigList->SignatureSize;
255 for (EntryIndex = 0; EntryIndex < EntryCount; EntryIndex++) {
256 //
257 // Compare Data Hash with Signature Data
258 //
259 if (CompareMem (SigData->SignatureData, HashVal, (SigList->SignatureSize - sizeof (EFI_GUID))) == 0) {
260 Status = TRUE;
261 goto _Exit;
262 }
263
264 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigData + SigList->SignatureSize);
265 }
266 }
267
268 _Exit:
269 return Status;
270 }
271
272 /**
273 Check whether the hash of an given certificate is revoked by the revocation database.
274
275 @param[in] Certificate Pointer to the certificate that is searched for.
276 @param[in] CertSize Size of certificate in bytes.
277 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
278 structures which contains list of X.509 certificate
279 of revoked signers and revoked content hashes.
280 @param[out] RevocationTime Return the time that the certificate was revoked.
281
282 @return TRUE The certificate hash is found in the revocation database.
283 @return FALSE The certificate hash is not found in the revocation database.
284
285 **/
286 BOOLEAN
287 IsCertHashRevoked (
288 IN UINT8 *Certificate,
289 IN UINTN CertSize,
290 IN EFI_SIGNATURE_LIST **RevokedDb,
291 OUT EFI_TIME *RevocationTime
292 )
293 {
294 BOOLEAN Status;
295 EFI_SIGNATURE_LIST *SigList;
296 EFI_SIGNATURE_DATA *SigData;
297 UINT8 *TBSCert;
298 UINTN TBSCertSize;
299 UINTN Index;
300 UINTN EntryIndex;
301 UINTN EntryCount;
302 UINT8 CertHashVal[MAX_DIGEST_SIZE];
303
304 if ((RevocationTime == NULL) || (RevokedDb == NULL)) {
305 return FALSE;
306 }
307
308 //
309 // Retrieve the TBSCertificate from the X.509 Certificate for hash calculation
310 //
311 if (!X509GetTBSCert (Certificate, CertSize, &TBSCert, &TBSCertSize)) {
312 return FALSE;
313 }
314
315 Status = FALSE;
316 for (Index = 0; ; Index++) {
317
318 SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]);
319 //
320 // The list is terminated by a NULL pointer.
321 //
322 if (SigList == NULL) {
323 break;
324 }
325
326 //
327 // Determine Hash Algorithm based on the entry type in revocation database, and
328 // calculate the certificate hash.
329 //
330 if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Sha256Guid)) {
331 Status = CalculateDataHash (TBSCert, TBSCertSize, &gEfiCertSha256Guid, CertHashVal);
332
333 } else if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Sha384Guid)) {
334 Status = CalculateDataHash (TBSCert, TBSCertSize, &gEfiCertSha384Guid, CertHashVal);
335
336 } else if (CompareGuid (&SigList->SignatureType, &gEfiCertX509Sha512Guid)) {
337 Status = CalculateDataHash (TBSCert, TBSCertSize, &gEfiCertSha512Guid, CertHashVal);
338
339 } else {
340 //
341 // Un-matched Cert Hash GUID
342 //
343 continue;
344 }
345
346 if (!Status) {
347 continue;
348 }
349
350 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
351 SigList->SignatureHeaderSize);
352 EntryCount = (SigList->SignatureListSize - SigList->SignatureHeaderSize -
353 sizeof (EFI_SIGNATURE_LIST)) / SigList->SignatureSize;
354 for (EntryIndex = 0; EntryIndex < EntryCount; Index++) {
355 //
356 // Check if the Certificate Hash is revoked.
357 //
358 if (CompareMem (SigData->SignatureData, CertHashVal,
359 SigList->SignatureSize - sizeof (EFI_GUID) - sizeof (EFI_TIME)) == 0) {
360 Status = TRUE;
361 //
362 // Return the revocation time of this revoked certificate.
363 //
364 CopyMem (
365 RevocationTime,
366 (EFI_TIME *)((UINT8 *)SigData + SigList->SignatureSize - sizeof (EFI_TIME)),
367 sizeof (EFI_TIME)
368 );
369 goto _Exit;
370 }
371
372 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigData + SigList->SignatureSize);
373 }
374 }
375
376 _Exit:
377 return Status;
378 }
379
380 /**
381 Check if the given time value is zero.
382
383 @param[in] Time Pointer of a time value.
384
385 @retval TRUE The Time is Zero.
386 @retval FALSE The Time is not Zero.
387
388 **/
389 BOOLEAN
390 IsTimeZero (
391 IN EFI_TIME *Time
392 )
393 {
394 if ((Time->Year == 0) && (Time->Month == 0) && (Time->Day == 0) &&
395 (Time->Hour == 0) && (Time->Minute == 0) && (Time->Second == 0)) {
396 return TRUE;
397 }
398
399 return FALSE;
400 }
401
402 /**
403 Check whether the timestamp is valid by comparing the signing time and the revocation time.
404
405 @param SigningTime Pointer to the signing time.
406 @param RevocationTime Pointer to the revocation time.
407
408 @retval TRUE The SigningTime is not later than the RevocationTime.
409 @retval FALSE The SigningTime is later than the RevocationTime.
410
411 **/
412 BOOLEAN
413 CompareTimestamp (
414 IN EFI_TIME *SigningTime,
415 IN EFI_TIME *RevocationTime
416 )
417 {
418 if (SigningTime->Year != RevocationTime->Year) {
419 return (BOOLEAN) (SigningTime->Year < RevocationTime->Year);
420 } else if (SigningTime->Month != RevocationTime->Month) {
421 return (BOOLEAN) (SigningTime->Month < RevocationTime->Month);
422 } else if (SigningTime->Day != RevocationTime->Day) {
423 return (BOOLEAN) (SigningTime->Day < RevocationTime->Day);
424 } else if (SigningTime->Hour != RevocationTime->Hour) {
425 return (BOOLEAN) (SigningTime->Hour < RevocationTime->Hour);
426 } else if (SigningTime->Minute != RevocationTime->Minute) {
427 return (BOOLEAN) (SigningTime->Minute < RevocationTime->Minute);
428 }
429
430 return (BOOLEAN) (SigningTime->Second <= RevocationTime->Second);
431 }
432
433 /**
434 Check whether the timestamp signature embedded in PKCS7 signedData is valid and
435 the signing time is also earlier than the revocation time.
436
437 @param[in] SignedData Pointer to the PKCS#7 signedData.
438 @param[in] SignedDataSize Size of SignedData in bytes.
439 @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
440 structures which is used to pass a list of X.509
441 certificates of trusted timestamp signers.
442 @param[in] RevocationTime The time that the certificate was revoked.
443
444 @retval TRUE Timestamp signature is valid and the signing time is no later
445 than the revocation time.
446 @retval FALSE Timestamp signature is not valid or the signing time is later
447 than the revocation time.
448
449 **/
450 BOOLEAN
451 IsValidTimestamp (
452 IN UINT8 *SignedData,
453 IN UINTN SignedDataSize,
454 IN EFI_SIGNATURE_LIST **TimeStampDb,
455 IN EFI_TIME *RevocationTime
456 )
457 {
458 BOOLEAN Status;
459 EFI_SIGNATURE_LIST *SigList;
460 EFI_SIGNATURE_DATA *SigData;
461 UINT8 *TsaCert;
462 UINTN TsaCertSize;
463 UINTN Index;
464 EFI_TIME SigningTime;
465
466 //
467 // If no supplied database for verification or RevocationTime is zero,
468 // the certificate shall be considered to always be revoked.
469 //
470 if ((TimeStampDb == NULL) || (IsTimeZero (RevocationTime))) {
471 return FALSE;
472 }
473
474 Status = FALSE;
475 //
476 // RevocationTime is non-zero, the certificate should be considered to be revoked
477 // from that time and onwards.
478 //
479 for (Index = 0; ; Index++) {
480 SigList = (EFI_SIGNATURE_LIST *) (TimeStampDb[Index]);
481
482 //
483 // The list is terminated by a NULL pointer.
484 //
485 if (SigList == NULL) {
486 break;
487 }
488
489 //
490 // Ignore any non-X509-format entry in the list
491 //
492 if (!CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
493 continue;
494 }
495
496
497 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
498 SigList->SignatureHeaderSize);
499 TsaCert = SigData->SignatureData;
500 TsaCertSize = SigList->SignatureSize - sizeof (EFI_GUID);
501
502 //
503 // Each TSA Certificate will normally be in a seperate EFI_SIGNATURE_LIST
504 // Leverage ImageTimestampVerify interface for Timestamp counterSignature Verification
505 //
506 if (ImageTimestampVerify (SignedData, SignedDataSize, TsaCert, TsaCertSize, &SigningTime)) {
507 //
508 // The signer signature is valid only when the signing time is earlier than revocation time.
509 //
510 if (CompareTimestamp (&SigningTime, RevocationTime)) {
511 Status = TRUE;
512 break;
513 }
514 }
515 }
516
517 return Status;
518 }
519
520 /**
521 Check whether the PKCS7 signedData is revoked by verifying with the revoked
522 certificates database, and if the signedData is timestamped, the embedded timestamp
523 couterSignature will be checked with the supplied timestamp database.
524
525 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
526 signature.
527 @param[in] SignedDataSize The size of SignedData buffer in bytes.
528 @param[in] InHash Pointer to the buffer containing the hash of the mesage data
529 previously signed and to be verified.
530 @param[in] InHashSize The size of InHash buffer in bytes.
531 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
532 structure which contains list of X.509 certificates
533 of revoked signers and revoked content hashes.
534 @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
535 structures which is used to pass a list of X.509
536 certificates of trusted timestamp signers.
537
538 @retval EFI_SUCCESS The PKCS7 signedData is revoked.
539 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
540 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
541 AllowedDb is NULL.
542 Content is not NULL and ContentSize is NULL.
543 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
544 content embedded in PKCS7 signedData.
545 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
546
547 **/
548 EFI_STATUS
549 P7CheckRevocationByHash (
550 IN UINT8 *SignedData,
551 IN UINTN SignedDataSize,
552 IN UINT8 *InHash,
553 IN UINTN InHashSize,
554 IN EFI_SIGNATURE_LIST **RevokedDb,
555 IN EFI_SIGNATURE_LIST **TimeStampDb
556 )
557 {
558 EFI_STATUS Status;
559 EFI_SIGNATURE_LIST *SigList;
560 EFI_SIGNATURE_DATA *SigData;
561 UINT8 *RevokedCert;
562 UINTN RevokedCertSize;
563 UINTN Index;
564 UINT8 *CertBuffer;
565 UINTN BufferLength;
566 UINT8 *TrustedCert;
567 UINTN TrustedCertLength;
568 UINT8 CertNumber;
569 UINT8 *CertPtr;
570 UINT8 *Cert;
571 UINTN CertSize;
572 EFI_TIME RevocationTime;
573
574 Status = EFI_SECURITY_VIOLATION;
575 SigData = NULL;
576 RevokedCert = NULL;
577 RevokedCertSize = 0;
578 CertBuffer = NULL;
579 TrustedCert = NULL;
580
581 //
582 // The signedData is revoked if the hash of content existed in RevokedDb
583 //
584 if (IsContentHashRevokedByHash (InHash, InHashSize, RevokedDb)) {
585 Status = EFI_SUCCESS;
586 goto _Exit;
587 }
588
589 //
590 // Check if the signer's certificate can be found in Revoked database
591 //
592 for (Index = 0; ; Index++) {
593 SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]);
594
595 //
596 // The list is terminated by a NULL pointer.
597 //
598 if (SigList == NULL) {
599 break;
600 }
601
602 //
603 // Ignore any non-X509-format entry in the list.
604 //
605 if (!CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
606 continue;
607 }
608
609 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
610 SigList->SignatureHeaderSize);
611
612 RevokedCert = SigData->SignatureData;
613 RevokedCertSize = SigList->SignatureSize - sizeof (EFI_GUID);
614
615 //
616 // Verifying the PKCS#7 SignedData with the revoked certificate in RevokedDb
617 //
618 if (AuthenticodeVerify (SignedData, SignedDataSize, RevokedCert, RevokedCertSize, InHash, InHashSize)) {
619 //
620 // The signedData was verified by one entry in Revoked Database
621 //
622 Status = EFI_SUCCESS;
623 break;
624 }
625 }
626
627 if (!EFI_ERROR (Status)) {
628 //
629 // The signedData was revoked, since it was hit by RevokedDb
630 //
631 goto _Exit;
632 }
633
634 //
635 // Now we will continue to check the X.509 Certificate Hash & Possible Timestamp
636 //
637 if ((TimeStampDb == NULL) || (*TimeStampDb == NULL)) {
638 goto _Exit;
639 }
640
641 Pkcs7GetSigners (SignedData, SignedDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);
642 if ((BufferLength == 0) || (CertBuffer == NULL)) {
643 Status = EFI_SUCCESS;
644 goto _Exit;
645 }
646
647 //
648 // Check if any hash of certificates embedded in P7 data is in the revoked database.
649 //
650 CertNumber = (UINT8) (*CertBuffer);
651 CertPtr = CertBuffer + 1;
652 for (Index = 0; Index < CertNumber; Index++) {
653 //
654 // Retrieve the Certificate data
655 //
656 CertSize = (UINTN) ReadUnaligned32 ((UINT32 *) CertPtr);
657 Cert = (UINT8 *)CertPtr + sizeof (UINT32);
658
659 if (IsCertHashRevoked (Cert, CertSize, RevokedDb, &RevocationTime)) {
660 //
661 // Check the timestamp signature and signing time to determine if p7 data can be trusted.
662 //
663 Status = EFI_SUCCESS;
664 if (IsValidTimestamp (SignedData, SignedDataSize, TimeStampDb, &RevocationTime)) {
665 //
666 // Use EFI_NOT_READY to identify the P7Data is not reovked, because the timestamping
667 // occured prior to the time of certificate revocation.
668 //
669 Status = EFI_NOT_READY;
670 }
671
672 goto _Exit;
673 }
674
675 CertPtr = CertPtr + sizeof (UINT32) + CertSize;
676 }
677
678 _Exit:
679 Pkcs7FreeSigners (CertBuffer);
680 Pkcs7FreeSigners (TrustedCert);
681
682 return Status;
683 }
684
685 /**
686 Check whether the PKCS7 signedData is revoked by verifying with the revoked
687 certificates database, and if the signedData is timestamped, the embedded timestamp
688 couterSignature will be checked with the supplied timestamp database.
689
690 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
691 signature.
692 @param[in] SignedDataSize The size of SignedData buffer in bytes.
693 @param[in] InData Pointer to the buffer containing the raw message data
694 previously signed and to be verified.
695 @param[in] InDataSize The size of InData buffer in bytes.
696 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
697 structure which contains list of X.509 certificates
698 of revoked signers and revoked content hashes.
699 @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
700 structures which is used to pass a list of X.509
701 certificates of trusted timestamp signers.
702
703 @retval EFI_SUCCESS The PKCS7 signedData is revoked.
704 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
705 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
706 AllowedDb is NULL.
707 Content is not NULL and ContentSize is NULL.
708 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
709 content embedded in PKCS7 signedData.
710 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
711
712 **/
713 EFI_STATUS
714 P7CheckRevocation (
715 IN UINT8 *SignedData,
716 IN UINTN SignedDataSize,
717 IN UINT8 *InData,
718 IN UINTN InDataSize,
719 IN EFI_SIGNATURE_LIST **RevokedDb,
720 IN EFI_SIGNATURE_LIST **TimeStampDb
721 )
722 {
723 EFI_STATUS Status;
724 EFI_SIGNATURE_LIST *SigList;
725 EFI_SIGNATURE_DATA *SigData;
726 UINT8 *RevokedCert;
727 UINTN RevokedCertSize;
728 UINTN Index;
729 UINT8 *CertBuffer;
730 UINTN BufferLength;
731 UINT8 *TrustedCert;
732 UINTN TrustedCertLength;
733 UINT8 CertNumber;
734 UINT8 *CertPtr;
735 UINT8 *Cert;
736 UINTN CertSize;
737 EFI_TIME RevocationTime;
738
739 Status = EFI_UNSUPPORTED;
740 SigData = NULL;
741 RevokedCert = NULL;
742 RevokedCertSize = 0;
743 CertBuffer = NULL;
744 TrustedCert = NULL;
745
746 //
747 // The signedData is revoked if the hash of content existed in RevokedDb
748 //
749 if (IsContentHashRevoked (InData, InDataSize, RevokedDb)) {
750 Status = EFI_SUCCESS;
751 goto _Exit;
752 }
753
754 //
755 // Check if the signer's certificate can be found in Revoked database
756 //
757 for (Index = 0; ; Index++) {
758 SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]);
759
760 //
761 // The list is terminated by a NULL pointer.
762 //
763 if (SigList == NULL) {
764 break;
765 }
766
767 //
768 // Ignore any non-X509-format entry in the list.
769 //
770 if (!CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
771 continue;
772 }
773
774 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
775 SigList->SignatureHeaderSize);
776
777 RevokedCert = SigData->SignatureData;
778 RevokedCertSize = SigList->SignatureSize - sizeof (EFI_GUID);
779
780 //
781 // Verifying the PKCS#7 SignedData with the revoked certificate in RevokedDb
782 //
783 if (Pkcs7Verify (SignedData, SignedDataSize, RevokedCert, RevokedCertSize, InData, InDataSize)) {
784 //
785 // The signedData was verified by one entry in Revoked Database
786 //
787 Status = EFI_SUCCESS;
788 break;
789 }
790 }
791
792 if (!EFI_ERROR (Status)) {
793 //
794 // The signedData was revoked, since it was hit by RevokedDb
795 //
796 goto _Exit;
797 }
798
799 //
800 // Now we will continue to check the X.509 Certificate Hash & Possible Timestamp
801 //
802 if ((TimeStampDb == NULL) || (*TimeStampDb == NULL)) {
803 goto _Exit;
804 }
805
806 Pkcs7GetSigners (SignedData, SignedDataSize, &CertBuffer, &BufferLength, &TrustedCert, &TrustedCertLength);
807 if ((BufferLength == 0) || (CertBuffer == NULL)) {
808 Status = EFI_SUCCESS;
809 goto _Exit;
810 }
811
812 //
813 // Check if any hash of certificates embedded in P7 data is in the revoked database.
814 //
815 CertNumber = (UINT8) (*CertBuffer);
816 CertPtr = CertBuffer + 1;
817 for (Index = 0; Index < CertNumber; Index++) {
818 //
819 // Retrieve the Certificate data
820 //
821 CertSize = (UINTN) ReadUnaligned32 ((UINT32 *) CertPtr);
822 Cert = (UINT8 *)CertPtr + sizeof (UINT32);
823
824 if (IsCertHashRevoked (Cert, CertSize, RevokedDb, &RevocationTime)) {
825 //
826 // Check the timestamp signature and signing time to determine if p7 data can be trusted.
827 //
828 Status = EFI_SUCCESS;
829 if (IsValidTimestamp (SignedData, SignedDataSize, TimeStampDb, &RevocationTime)) {
830 //
831 // Use EFI_NOT_READY to identify the P7Data is not reovked, because the timestamping
832 // occured prior to the time of certificate revocation.
833 //
834 Status = EFI_NOT_READY;
835 }
836
837 goto _Exit;
838 }
839
840 CertPtr = CertPtr + sizeof (UINT32) + CertSize;
841 }
842
843 _Exit:
844 Pkcs7FreeSigners (CertBuffer);
845 Pkcs7FreeSigners (TrustedCert);
846
847 return Status;
848 }
849
850 /**
851 Check whether the PKCS7 signedData can be verified by the trusted certificates
852 database, and return the content of the signedData if requested.
853
854 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
855 signature.
856 @param[in] SignedDataSize The size of SignedData buffer in bytes.
857 @param[in] InHash Pointer to the buffer containing the hash of the message data
858 previously signed and to be verified.
859 @param[in] InHashSize The size of InHash buffer in bytes.
860 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
861 structures which contains lists of X.509 certificates
862 of approved signers.
863
864 @retval EFI_SUCCESS The PKCS7 signedData is trusted.
865 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
866 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
867 AllowedDb is NULL.
868 Content is not NULL and ContentSize is NULL.
869 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
870 content embedded in PKCS7 signedData.
871 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
872 @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too
873 small to hold the content. ContentSize updated to
874 the required size.
875
876 **/
877 EFI_STATUS
878 P7CheckTrustByHash (
879 IN UINT8 *SignedData,
880 IN UINTN SignedDataSize,
881 IN UINT8 *InHash,
882 IN UINTN InHashSize,
883 IN EFI_SIGNATURE_LIST **AllowedDb
884 )
885 {
886 EFI_STATUS Status;
887 EFI_SIGNATURE_LIST *SigList;
888 EFI_SIGNATURE_DATA *SigData;
889 UINT8 *TrustCert;
890 UINTN TrustCertSize;
891 UINTN Index;
892
893 Status = EFI_SECURITY_VIOLATION;
894 SigData = NULL;
895 TrustCert = NULL;
896 TrustCertSize = 0;
897
898 if (AllowedDb == NULL) {
899 return EFI_INVALID_PARAMETER;
900 }
901
902 //
903 // Build Certificate Stack with all valid X509 certificates in the supplied
904 // Signature List for PKCS7 Verification.
905 //
906 for (Index = 0; ; Index++) {
907 SigList = (EFI_SIGNATURE_LIST *)(AllowedDb[Index]);
908
909 //
910 // The list is terminated by a NULL pointer.
911 //
912 if (SigList == NULL) {
913 break;
914 }
915
916 //
917 // Ignore any non-X509-format entry in the list.
918 //
919 if (!CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
920 continue;
921 }
922
923 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
924 SigList->SignatureHeaderSize);
925
926 TrustCert = SigData->SignatureData;
927 TrustCertSize = SigList->SignatureSize - sizeof (EFI_GUID);
928
929 //
930 // Verifying the PKCS#7 SignedData with the trusted certificate from AllowedDb
931 //
932 if (AuthenticodeVerify (SignedData, SignedDataSize, TrustCert, TrustCertSize, InHash, InHashSize)) {
933 //
934 // The SignedData was verified successfully by one entry in Trusted Database
935 //
936 Status = EFI_SUCCESS;
937 break;
938 }
939 }
940
941 return Status;
942 }
943
944 /**
945 Check whether the PKCS7 signedData can be verified by the trusted certificates
946 database, and return the content of the signedData if requested.
947
948 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
949 signature.
950 @param[in] SignedDataSize The size of SignedData buffer in bytes.
951 @param[in] InData Pointer to the buffer containing the raw message data
952 previously signed and to be verified.
953 @param[in] InDataSize The size of InData buffer in bytes.
954 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
955 structures which contains lists of X.509 certificates
956 of approved signers.
957
958 @retval EFI_SUCCESS The PKCS7 signedData is trusted.
959 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
960 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
961 AllowedDb is NULL.
962 Content is not NULL and ContentSize is NULL.
963 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
964 content embedded in PKCS7 signedData.
965 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
966 @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too
967 small to hold the content. ContentSize updated to
968 the required size.
969
970 **/
971 EFI_STATUS
972 P7CheckTrust (
973 IN UINT8 *SignedData,
974 IN UINTN SignedDataSize,
975 IN UINT8 *InData,
976 IN UINTN InDataSize,
977 IN EFI_SIGNATURE_LIST **AllowedDb
978 )
979 {
980 EFI_STATUS Status;
981 EFI_SIGNATURE_LIST *SigList;
982 EFI_SIGNATURE_DATA *SigData;
983 UINT8 *TrustCert;
984 UINTN TrustCertSize;
985 UINTN Index;
986
987 Status = EFI_SECURITY_VIOLATION;
988 SigData = NULL;
989 TrustCert = NULL;
990 TrustCertSize = 0;
991
992 if (AllowedDb == NULL) {
993 return EFI_INVALID_PARAMETER;
994 }
995
996 //
997 // Build Certificate Stack with all valid X509 certificates in the supplied
998 // Signature List for PKCS7 Verification.
999 //
1000 for (Index = 0; ; Index++) {
1001 SigList = (EFI_SIGNATURE_LIST *)(AllowedDb[Index]);
1002
1003 //
1004 // The list is terminated by a NULL pointer.
1005 //
1006 if (SigList == NULL) {
1007 break;
1008 }
1009
1010 //
1011 // Ignore any non-X509-format entry in the list.
1012 //
1013 if (!CompareGuid (&SigList->SignatureType, &gEfiCertX509Guid)) {
1014 continue;
1015 }
1016
1017 SigData = (EFI_SIGNATURE_DATA *) ((UINT8 *) SigList + sizeof (EFI_SIGNATURE_LIST) +
1018 SigList->SignatureHeaderSize);
1019
1020 TrustCert = SigData->SignatureData;
1021 TrustCertSize = SigList->SignatureSize - sizeof (EFI_GUID);
1022
1023 //
1024 // Verifying the PKCS#7 SignedData with the trusted certificate from AllowedDb
1025 //
1026 if (Pkcs7Verify (SignedData, SignedDataSize, TrustCert, TrustCertSize, InData, InDataSize)) {
1027 //
1028 // The SignedData was verified successfully by one entry in Trusted Database
1029 //
1030 Status = EFI_SUCCESS;
1031 break;
1032 }
1033 }
1034
1035 return Status;
1036 }
1037
1038 /**
1039 Processes a buffer containing binary DER-encoded PKCS7 signature.
1040 The signed data content may be embedded within the buffer or separated. Function
1041 verifies the signature of the content is valid and signing certificate was not
1042 revoked and is contained within a list of trusted signers.
1043
1044 @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance.
1045 @param[in] SignedData Points to buffer containing ASN.1 DER-encoded PKCS7
1046 signature.
1047 @param[in] SignedDataSize The size of SignedData buffer in bytes.
1048 @param[in] InData In case of detached signature, InData points to
1049 buffer containing the raw message data previously
1050 signed and to be verified by function. In case of
1051 SignedData containing embedded data, InData must be
1052 NULL.
1053 @param[in] InDataSize When InData is used, the size of InData buffer in
1054 bytes. When InData is NULL. This parameter must be
1055 0.
1056 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
1057 structures. The list is terminated by a null
1058 pointer. The EFI_SIGNATURE_LIST structures contain
1059 lists of X.509 certificates of approved signers.
1060 Function recognizes signer certificates of type
1061 EFI_CERT_X509_GUID. Any hash certificate in AllowedDb
1062 list is ignored by this function. Function returns
1063 success if signer of the buffer is within this list
1064 (and not within RevokedDb). This parameter is
1065 required.
1066 @param[in] RevokedDb Optional pointer to a list of pointers to
1067 EFI_SIGNATURE_LIST structures. The list is terminated
1068 by a null pointer. List of X.509 certificates of
1069 revoked signers and revoked file hashes. Except as
1070 noted in description of TimeStampDb signature
1071 verification will always fail if the signer of the
1072 file or the hash of the data component of the buffer
1073 is in RevokedDb list. This list is optional and
1074 caller may pass Null or pointer to NULL if not
1075 required.
1076 @param[in] TimeStampDb Optional pointer to a list of pointers to
1077 EFI_SIGNATURE_LIST structures. The list is terminated
1078 by a null pointer. This parameter can be used to pass
1079 a list of X.509 certificates of trusted time stamp
1080 signers. This list is optional and caller must pass
1081 Null or pointer to NULL if not required.
1082 @param[out] Content On input, points to an optional caller-allocated
1083 buffer into which the function will copy the content
1084 portion of the file after verification succeeds.
1085 This parameter is optional and if NULL, no copy of
1086 content from file is performed.
1087 @param[in,out] ContentSize On input, points to the size in bytes of the optional
1088 buffer Content previously allocated by caller. On
1089 output, if the verification succeeds, the value
1090 referenced by ContentSize will contain the actual
1091 size of the content from signed file. If ContentSize
1092 indicates the caller-allocated buffer is too small
1093 to contain content, an error is returned, and
1094 ContentSize will be updated with the required size.
1095 This parameter must be 0 if Content is Null.
1096
1097 @retval EFI_SUCCESS Content signature was verified against hash of
1098 content, the signer's certificate was not found in
1099 RevokedDb, and was found in AllowedDb or if in signer
1100 is found in both AllowedDb and RevokedDb, the
1101 signing was allowed by reference to TimeStampDb as
1102 described above, and no hash matching content hash
1103 was found in RevokedDb.
1104 @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but
1105 signer was in RevokedDb or not in AllowedDb. Also
1106 returned if matching content hash found in RevokedDb.
1107 @retval EFI_COMPROMISED_DATA Calculated hash differs from signed hash.
1108 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
1109 AllowedDb is NULL.
1110 @retval EFI_INVALID_PARAMETER Content is not NULL and ContentSize is NULL.
1111 @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb,
1112 RevokedDb or AllowedDb list contents was detected.
1113 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
1114 content embedded in SignedData.
1115 @retval EFI_UNSUPPORTED The SignedData buffer was not correctly formatted
1116 for processing by the function.
1117 @retval EFI_UNSUPPORTED Signed data embedded in SignedData but InData is not
1118 NULL.
1119 @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too
1120 small to hold the content. ContentSize updated to
1121 required size.
1122
1123 **/
1124 EFI_STATUS
1125 EFIAPI
1126 VerifyBuffer (
1127 IN EFI_PKCS7_VERIFY_PROTOCOL *This,
1128 IN VOID *SignedData,
1129 IN UINTN SignedDataSize,
1130 IN VOID *InData OPTIONAL,
1131 IN UINTN InDataSize,
1132 IN EFI_SIGNATURE_LIST **AllowedDb,
1133 IN EFI_SIGNATURE_LIST **RevokedDb OPTIONAL,
1134 IN EFI_SIGNATURE_LIST **TimeStampDb OPTIONAL,
1135 OUT VOID *Content OPTIONAL,
1136 IN OUT UINTN *ContentSize
1137 )
1138 {
1139 EFI_STATUS Status;
1140 EFI_SIGNATURE_LIST *SigList;
1141 UINTN Index;
1142 UINT8 *AttachedData;
1143 UINTN AttachedDataSize;
1144 UINT8 *DataPtr;
1145 UINTN DataSize;
1146
1147 //
1148 // Parameters Checking
1149 //
1150 if ((SignedData == NULL) || (SignedDataSize == 0) || (AllowedDb == NULL)) {
1151 return EFI_INVALID_PARAMETER;
1152 }
1153 if ((Content != NULL) && (ContentSize == NULL)) {
1154 return EFI_INVALID_PARAMETER;
1155 }
1156
1157 //
1158 // Check if any invalid entry format in AllowedDb list contents
1159 //
1160 for (Index = 0; ; Index++) {
1161 SigList = (EFI_SIGNATURE_LIST *)(AllowedDb[Index]);
1162
1163 if (SigList == NULL) {
1164 break;
1165 }
1166 if (SigList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST) +
1167 SigList->SignatureHeaderSize +
1168 SigList->SignatureSize) {
1169 return EFI_ABORTED;
1170 }
1171 }
1172
1173 //
1174 // Check if any invalid entry format in RevokedDb list contents
1175 //
1176 if (RevokedDb != NULL) {
1177 for (Index = 0; ; Index++) {
1178 SigList = (EFI_SIGNATURE_LIST *)(RevokedDb[Index]);
1179
1180 if (SigList == NULL) {
1181 break;
1182 }
1183 if (SigList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST) +
1184 SigList->SignatureHeaderSize +
1185 SigList->SignatureSize) {
1186 return EFI_ABORTED;
1187 }
1188 }
1189 }
1190
1191 //
1192 // Check if any invalid entry format in TimeStampDb list contents
1193 //
1194 if (TimeStampDb != NULL) {
1195 for (Index = 0; ; Index++) {
1196 SigList = (EFI_SIGNATURE_LIST *)(TimeStampDb[Index]);
1197
1198 if (SigList == NULL) {
1199 break;
1200 }
1201 if (SigList->SignatureListSize < sizeof (EFI_SIGNATURE_LIST) +
1202 SigList->SignatureHeaderSize +
1203 SigList->SignatureSize) {
1204 return EFI_ABORTED;
1205 }
1206 }
1207 }
1208
1209 //
1210 // Try to retrieve the attached content from PKCS7 signedData
1211 //
1212 AttachedData = NULL;
1213 AttachedDataSize = 0;
1214 if (!Pkcs7GetAttachedContent (
1215 SignedData,
1216 SignedDataSize,
1217 (VOID **)&AttachedData,
1218 &AttachedDataSize)) {
1219 //
1220 // The SignedData buffer was not correctly formatted for processing
1221 //
1222 return EFI_UNSUPPORTED;
1223 }
1224 if (AttachedData != NULL) {
1225 if (InData != NULL) {
1226 //
1227 // The embedded content is found in SignedData but InData is not NULL
1228 //
1229 Status = EFI_UNSUPPORTED;
1230 goto _Exit;
1231 }
1232 //
1233 // PKCS7-formatted signedData with attached content; Use the embedded
1234 // content for verification
1235 //
1236 DataPtr = AttachedData;
1237 DataSize = AttachedDataSize;
1238
1239 } else if (InData != NULL) {
1240 //
1241 // PKCS7-formatted signedData with detached content; Use the user-supplied
1242 // input data for verification
1243 //
1244 DataPtr = (UINT8 *)InData;
1245 DataSize = InDataSize;
1246 } else {
1247 //
1248 // Content not found because InData is NULL and no content attached in SignedData
1249 //
1250 Status = EFI_NOT_FOUND;
1251 goto _Exit;
1252 }
1253
1254 Status = EFI_UNSUPPORTED;
1255
1256 //
1257 // Verify PKCS7 SignedData with Revoked database
1258 //
1259 if (RevokedDb != NULL) {
1260 Status = P7CheckRevocation (
1261 SignedData,
1262 SignedDataSize,
1263 DataPtr,
1264 DataSize,
1265 RevokedDb,
1266 TimeStampDb
1267 );
1268 if (!EFI_ERROR (Status)) {
1269 //
1270 // The PKCS7 SignedData is reovked
1271 //
1272 Status = EFI_SECURITY_VIOLATION;
1273 goto _Exit;
1274 }
1275 }
1276
1277 //
1278 // Verify PKCS7 SignedData with AllowedDB
1279 //
1280 Status = P7CheckTrust (
1281 SignedData,
1282 SignedDataSize,
1283 DataPtr,
1284 DataSize,
1285 AllowedDb
1286 );
1287 if (EFI_ERROR (Status)) {
1288 //
1289 // Verification failed with AllowedDb
1290 //
1291 goto _Exit;
1292 }
1293
1294 //
1295 // Copy the content portion after verification succeeds
1296 //
1297 if (Content != NULL) {
1298 if (*ContentSize < DataSize) {
1299 //
1300 // Caller-allocated buffer is too small to contain content
1301 //
1302 *ContentSize = DataSize;
1303 Status = EFI_BUFFER_TOO_SMALL;
1304 } else {
1305 *ContentSize = DataSize;
1306 CopyMem (Content, DataPtr, DataSize);
1307 }
1308 }
1309
1310 _Exit:
1311 if (AttachedData != NULL) {
1312 FreePool (AttachedData);
1313 }
1314
1315 return Status;
1316 }
1317
1318 /**
1319 Processes a buffer containing binary DER-encoded detached PKCS7 signature.
1320 The hash of the signed data content is calculated and passed by the caller. Function
1321 verifies the signature of the content is valid and signing certificate was not revoked
1322 and is contained within a list of trusted signers.
1323
1324 @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance.
1325 @param[in] Signature Points to buffer containing ASN.1 DER-encoded PKCS
1326 detached signature.
1327 @param[in] SignatureSize The size of Signature buffer in bytes.
1328 @param[in] InHash InHash points to buffer containing the caller
1329 calculated hash of the data. The parameter may not
1330 be NULL.
1331 @param[in] InHashSize The size in bytes of InHash buffer.
1332 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
1333 structures. The list is terminated by a null
1334 pointer. The EFI_SIGNATURE_LIST structures contain
1335 lists of X.509 certificates of approved signers.
1336 Function recognizes signer certificates of type
1337 EFI_CERT_X509_GUID. Any hash certificate in AllowedDb
1338 list is ignored by this function. Function returns
1339 success if signer of the buffer is within this list
1340 (and not within RevokedDb). This parameter is
1341 required.
1342 @param[in] RevokedDb Optional pointer to a list of pointers to
1343 EFI_SIGNATURE_LIST structures. The list is terminated
1344 by a null pointer. List of X.509 certificates of
1345 revoked signers and revoked file hashes. Signature
1346 verification will always fail if the signer of the
1347 file or the hash of the data component of the buffer
1348 is in RevokedDb list. This parameter is optional
1349 and caller may pass Null if not required.
1350 @param[in] TimeStampDb Optional pointer to a list of pointers to
1351 EFI_SIGNATURE_LIST structures. The list is terminated
1352 by a null pointer. This parameter can be used to pass
1353 a list of X.509 certificates of trusted time stamp
1354 counter-signers.
1355
1356 @retval EFI_SUCCESS Signed hash was verified against caller-provided
1357 hash of content, the signer's certificate was not
1358 found in RevokedDb, and was found in AllowedDb or
1359 if in signer is found in both AllowedDb and
1360 RevokedDb, the signing was allowed by reference to
1361 TimeStampDb as described above, and no hash matching
1362 content hash was found in RevokedDb.
1363 @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but
1364 signer was in RevokedDb or not in AllowedDb. Also
1365 returned if matching content hash found in RevokedDb.
1366 @retval EFI_COMPROMISED_DATA Caller provided hash differs from signed hash. Or,
1367 caller and encrypted hash are different sizes.
1368 @retval EFI_INVALID_PARAMETER Signature is NULL or SignatureSize is zero. InHash
1369 is NULL or InHashSize is zero. AllowedDb is NULL.
1370 @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb,
1371 RevokedDb or AllowedDb list contents was detected.
1372 @retval EFI_UNSUPPORTED The Signature buffer was not correctly formatted
1373 for processing by the function.
1374
1375 **/
1376 EFI_STATUS
1377 EFIAPI
1378 VerifySignature (
1379 IN EFI_PKCS7_VERIFY_PROTOCOL *This,
1380 IN VOID *Signature,
1381 IN UINTN SignatureSize,
1382 IN VOID *InHash,
1383 IN UINTN InHashSize,
1384 IN EFI_SIGNATURE_LIST **AllowedDb,
1385 IN EFI_SIGNATURE_LIST **RevokedDb OPTIONAL,
1386 IN EFI_SIGNATURE_LIST **TimeStampDb OPTIONAL
1387 )
1388 {
1389 EFI_STATUS Status;
1390
1391 //
1392 // Parameters Checking
1393 //
1394 if ((Signature == NULL) || (SignatureSize == 0) || (AllowedDb == NULL)
1395 || (InHash == NULL) || (InHashSize == 0)) {
1396 return EFI_INVALID_PARAMETER;
1397 }
1398
1399 //
1400 // Verify PKCS7 SignedData with Revoked database
1401 //
1402 if (RevokedDb != NULL) {
1403 Status = P7CheckRevocationByHash (
1404 Signature,
1405 SignatureSize,
1406 InHash,
1407 InHashSize,
1408 RevokedDb,
1409 TimeStampDb
1410 );
1411
1412 if (!EFI_ERROR (Status)) {
1413 //
1414 // The PKCS7 SignedData is reovked
1415 //
1416 return EFI_SECURITY_VIOLATION;
1417 }
1418 }
1419
1420 //
1421 // Verify PKCS7 SignedData with AllowedDB
1422 //
1423 Status = P7CheckTrustByHash (
1424 Signature,
1425 SignatureSize,
1426 InHash,
1427 InHashSize,
1428 AllowedDb
1429 );
1430
1431 return Status;
1432 }
1433
1434 //
1435 // The PKCS7 Verification Protocol
1436 //
1437 EFI_PKCS7_VERIFY_PROTOCOL mPkcs7Verify = {
1438 VerifyBuffer,
1439 VerifySignature
1440 };
1441
1442 /**
1443 The user Entry Point for the PKCS7 Verification driver.
1444
1445 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1446 @param[in] SystemTable A pointer to the EFI System Table.
1447
1448 @retval EFI_SUCCESS The entry point is executed successfully.
1449 @retval EFI_NOT_SUPPORTED Platform does not support PKCS7 Verification.
1450 @retval Other Some error occurs when executing this entry point.
1451
1452 **/
1453 EFI_STATUS
1454 EFIAPI
1455 Pkcs7VerifyDriverEntry (
1456 IN EFI_HANDLE ImageHandle,
1457 IN EFI_SYSTEM_TABLE *SystemTable
1458 )
1459 {
1460 EFI_STATUS Status;
1461 EFI_HANDLE Handle;
1462 EFI_PKCS7_VERIFY_PROTOCOL Useless;
1463
1464 //
1465 // Avoid loading a second copy if this is built as an external module
1466 //
1467 Status = gBS->LocateProtocol (&gEfiPkcs7VerifyProtocolGuid, NULL, (VOID **)&Useless);
1468 if (!EFI_ERROR (Status)) {
1469 return EFI_ABORTED;
1470 }
1471
1472 //
1473 // Install UEFI Pkcs7 Verification Protocol
1474 //
1475 Handle = NULL;
1476 Status = gBS->InstallMultipleProtocolInterfaces (
1477 &Handle,
1478 &gEfiPkcs7VerifyProtocolGuid,
1479 &mPkcs7Verify,
1480 NULL
1481 );
1482
1483 return Status;
1484 }