2 Pkcs7Verify Driver to produce the UEFI PKCS7 Verification Protocol.
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.
8 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
9 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #include <Library/BaseLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/MemoryAllocationLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include <Library/BaseCryptLib.h>
18 #include <Protocol/Pkcs7Verify.h>
20 #define MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
23 Calculates the hash of the given data based on the specified hash GUID.
25 @param[in] Data Pointer to the data buffer to be hashed.
26 @param[in] DataSize The size of data buffer in bytes.
27 @param[in] CertGuid The GUID to identify the hash algorithm to be used.
28 @param[out] HashValue Pointer to a buffer that receives the hash result.
30 @retval TRUE Data hash calculation succeeded.
31 @retval FALSE Data hash calculation failed.
38 IN EFI_GUID
*CertGuid
,
49 if (CompareGuid (CertGuid
, &gEfiCertSha1Guid
)) {
53 CtxSize
= Sha1GetContextSize ();
54 HashCtx
= AllocatePool (CtxSize
);
55 if (HashCtx
== NULL
) {
59 Status
= Sha1Init (HashCtx
);
60 Status
= Sha1Update (HashCtx
, Data
, DataSize
);
61 Status
= Sha1Final (HashCtx
, HashValue
);
62 } else if (CompareGuid (CertGuid
, &gEfiCertSha256Guid
)) {
66 CtxSize
= Sha256GetContextSize ();
67 HashCtx
= AllocatePool (CtxSize
);
68 if (HashCtx
== NULL
) {
72 Status
= Sha256Init (HashCtx
);
73 Status
= Sha256Update (HashCtx
, Data
, DataSize
);
74 Status
= Sha256Final (HashCtx
, HashValue
);
75 } else if (CompareGuid (CertGuid
, &gEfiCertSha384Guid
)) {
79 CtxSize
= Sha384GetContextSize ();
80 HashCtx
= AllocatePool (CtxSize
);
81 if (HashCtx
== NULL
) {
85 Status
= Sha384Init (HashCtx
);
86 Status
= Sha384Update (HashCtx
, Data
, DataSize
);
87 Status
= Sha384Final (HashCtx
, HashValue
);
88 } else if (CompareGuid (CertGuid
, &gEfiCertSha512Guid
)) {
92 CtxSize
= Sha512GetContextSize ();
93 HashCtx
= AllocatePool (CtxSize
);
94 if (HashCtx
== NULL
) {
98 Status
= Sha512Init (HashCtx
);
99 Status
= Sha512Update (HashCtx
, Data
, DataSize
);
100 Status
= Sha512Final (HashCtx
, HashValue
);
104 if (HashCtx
!= NULL
) {
112 Check whether the hash of data content is revoked by the revocation database.
114 @param[in] Hash Pointer to the hash that is searched for.
115 @param[in] HashSize The size of the hash in bytes.
116 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
117 structure which contains list of X.509 certificates
118 of revoked signers and revoked content hashes.
120 @return TRUE The matched content hash is found in the revocation database.
121 @return FALSE The matched content hash is not found in the revocation database.
125 IsContentHashRevokedByHash (
128 IN EFI_SIGNATURE_LIST
**RevokedDb
131 EFI_SIGNATURE_LIST
*SigList
;
132 EFI_SIGNATURE_DATA
*SigData
;
138 if (RevokedDb
== NULL
) {
144 // Check if any hash matching content hash can be found in RevokedDB
146 for (Index
= 0; ; Index
++) {
147 SigList
= (EFI_SIGNATURE_LIST
*)(RevokedDb
[Index
]);
150 // The list is terminated by a NULL pointer.
152 if (SigList
== NULL
) {
157 // Search the signature database to search the revoked content hash
159 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
160 SigList
->SignatureHeaderSize
);
161 EntryCount
= (SigList
->SignatureListSize
- SigList
->SignatureHeaderSize
-
162 sizeof (EFI_SIGNATURE_LIST
)) / SigList
->SignatureSize
;
163 for (EntryIndex
= 0; EntryIndex
< EntryCount
; EntryIndex
++) {
165 // The problem case. There's a revocation hash but the sizes
166 // don't match, meaning it's a different hash algorithm and we
167 // can't tell if it's revoking our binary or not. Assume not.
169 if (SigList
->SignatureSize
- sizeof (EFI_GUID
) == HashSize
) {
171 // Compare Data Hash with Signature Data
173 if (CompareMem (SigData
->SignatureData
, Hash
, HashSize
) == 0) {
179 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigData
+ SigList
->SignatureSize
);
188 Check whether the hash of data content is revoked by the revocation database.
190 @param[in] Content Pointer to the content buffer that is searched for.
191 @param[in] ContentSize The size of data content in bytes.
192 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
193 structure which contains list of X.509 certificates
194 of revoked signers and revoked content hashes.
196 @return TRUE The matched content hash is found in the revocation database.
197 @return FALSE The matched content hash is not found in the revocation database.
201 IsContentHashRevoked (
203 IN UINTN ContentSize
,
204 IN EFI_SIGNATURE_LIST
**RevokedDb
207 EFI_SIGNATURE_LIST
*SigList
;
208 EFI_SIGNATURE_DATA
*SigData
;
210 UINT8 HashVal
[MAX_DIGEST_SIZE
];
215 if (RevokedDb
== NULL
) {
221 // Check if any hash matching content hash can be found in RevokedDB
223 for (Index
= 0; ; Index
++) {
224 SigList
= (EFI_SIGNATURE_LIST
*)(RevokedDb
[Index
]);
227 // The list is terminated by a NULL pointer.
229 if (SigList
== NULL
) {
234 // Calculate the digest of supplied data based on the signature hash type.
236 if (!CalculateDataHash (Content
, ContentSize
, &SigList
->SignatureType
, HashVal
)) {
238 // Un-matched Hash GUID or other failure.
244 // Search the signature database to search the revoked content hash
246 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
247 SigList
->SignatureHeaderSize
);
248 EntryCount
= (SigList
->SignatureListSize
- SigList
->SignatureHeaderSize
-
249 sizeof (EFI_SIGNATURE_LIST
)) / SigList
->SignatureSize
;
250 for (EntryIndex
= 0; EntryIndex
< EntryCount
; EntryIndex
++) {
252 // Compare Data Hash with Signature Data
254 if (CompareMem (SigData
->SignatureData
, HashVal
, (SigList
->SignatureSize
- sizeof (EFI_GUID
))) == 0) {
259 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigData
+ SigList
->SignatureSize
);
268 Check whether the hash of an given certificate is revoked by the revocation database.
270 @param[in] Certificate Pointer to the certificate that is searched for.
271 @param[in] CertSize Size of certificate in bytes.
272 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
273 structures which contains list of X.509 certificate
274 of revoked signers and revoked content hashes.
275 @param[out] RevocationTime Return the time that the certificate was revoked.
277 @return TRUE The certificate hash is found in the revocation database.
278 @return FALSE The certificate hash is not found in the revocation database.
283 IN UINT8
*Certificate
,
285 IN EFI_SIGNATURE_LIST
**RevokedDb
,
286 OUT EFI_TIME
*RevocationTime
290 EFI_SIGNATURE_LIST
*SigList
;
291 EFI_SIGNATURE_DATA
*SigData
;
297 UINT8 CertHashVal
[MAX_DIGEST_SIZE
];
299 if ((RevocationTime
== NULL
) || (RevokedDb
== NULL
)) {
304 // Retrieve the TBSCertificate from the X.509 Certificate for hash calculation
306 if (!X509GetTBSCert (Certificate
, CertSize
, &TBSCert
, &TBSCertSize
)) {
311 for (Index
= 0; ; Index
++) {
312 SigList
= (EFI_SIGNATURE_LIST
*)(RevokedDb
[Index
]);
314 // The list is terminated by a NULL pointer.
316 if (SigList
== NULL
) {
321 // Determine Hash Algorithm based on the entry type in revocation database, and
322 // calculate the certificate hash.
324 if (CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Sha256Guid
)) {
325 Status
= CalculateDataHash (TBSCert
, TBSCertSize
, &gEfiCertSha256Guid
, CertHashVal
);
326 } else if (CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Sha384Guid
)) {
327 Status
= CalculateDataHash (TBSCert
, TBSCertSize
, &gEfiCertSha384Guid
, CertHashVal
);
328 } else if (CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Sha512Guid
)) {
329 Status
= CalculateDataHash (TBSCert
, TBSCertSize
, &gEfiCertSha512Guid
, CertHashVal
);
332 // Un-matched Cert Hash GUID
341 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
342 SigList
->SignatureHeaderSize
);
343 EntryCount
= (SigList
->SignatureListSize
- SigList
->SignatureHeaderSize
-
344 sizeof (EFI_SIGNATURE_LIST
)) / SigList
->SignatureSize
;
345 for (EntryIndex
= 0; EntryIndex
< EntryCount
; Index
++) {
347 // Check if the Certificate Hash is revoked.
350 SigData
->SignatureData
,
352 SigList
->SignatureSize
- sizeof (EFI_GUID
) - sizeof (EFI_TIME
)
357 // Return the revocation time of this revoked certificate.
361 (EFI_TIME
*)((UINT8
*)SigData
+ SigList
->SignatureSize
- sizeof (EFI_TIME
)),
367 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigData
+ SigList
->SignatureSize
);
376 Check if the given time value is zero.
378 @param[in] Time Pointer of a time value.
380 @retval TRUE The Time is Zero.
381 @retval FALSE The Time is not Zero.
389 if ((Time
->Year
== 0) && (Time
->Month
== 0) && (Time
->Day
== 0) &&
390 (Time
->Hour
== 0) && (Time
->Minute
== 0) && (Time
->Second
== 0))
399 Check whether the timestamp is valid by comparing the signing time and the revocation time.
401 @param SigningTime Pointer to the signing time.
402 @param RevocationTime Pointer to the revocation time.
404 @retval TRUE The SigningTime is not later than the RevocationTime.
405 @retval FALSE The SigningTime is later than the RevocationTime.
410 IN EFI_TIME
*SigningTime
,
411 IN EFI_TIME
*RevocationTime
414 if (SigningTime
->Year
!= RevocationTime
->Year
) {
415 return (BOOLEAN
)(SigningTime
->Year
< RevocationTime
->Year
);
416 } else if (SigningTime
->Month
!= RevocationTime
->Month
) {
417 return (BOOLEAN
)(SigningTime
->Month
< RevocationTime
->Month
);
418 } else if (SigningTime
->Day
!= RevocationTime
->Day
) {
419 return (BOOLEAN
)(SigningTime
->Day
< RevocationTime
->Day
);
420 } else if (SigningTime
->Hour
!= RevocationTime
->Hour
) {
421 return (BOOLEAN
)(SigningTime
->Hour
< RevocationTime
->Hour
);
422 } else if (SigningTime
->Minute
!= RevocationTime
->Minute
) {
423 return (BOOLEAN
)(SigningTime
->Minute
< RevocationTime
->Minute
);
426 return (BOOLEAN
)(SigningTime
->Second
<= RevocationTime
->Second
);
430 Check whether the timestamp signature embedded in PKCS7 signedData is valid and
431 the signing time is also earlier than the revocation time.
433 @param[in] SignedData Pointer to the PKCS#7 signedData.
434 @param[in] SignedDataSize Size of SignedData in bytes.
435 @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
436 structures which is used to pass a list of X.509
437 certificates of trusted timestamp signers.
438 @param[in] RevocationTime The time that the certificate was revoked.
440 @retval TRUE Timestamp signature is valid and the signing time is no later
441 than the revocation time.
442 @retval FALSE Timestamp signature is not valid or the signing time is later
443 than the revocation time.
448 IN UINT8
*SignedData
,
449 IN UINTN SignedDataSize
,
450 IN EFI_SIGNATURE_LIST
**TimeStampDb
,
451 IN EFI_TIME
*RevocationTime
455 EFI_SIGNATURE_LIST
*SigList
;
456 EFI_SIGNATURE_DATA
*SigData
;
460 EFI_TIME SigningTime
;
463 // If no supplied database for verification or RevocationTime is zero,
464 // the certificate shall be considered to always be revoked.
466 if ((TimeStampDb
== NULL
) || (IsTimeZero (RevocationTime
))) {
472 // RevocationTime is non-zero, the certificate should be considered to be revoked
473 // from that time and onwards.
475 for (Index
= 0; ; Index
++) {
476 SigList
= (EFI_SIGNATURE_LIST
*)(TimeStampDb
[Index
]);
479 // The list is terminated by a NULL pointer.
481 if (SigList
== NULL
) {
486 // Ignore any non-X509-format entry in the list
488 if (!CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Guid
)) {
492 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
493 SigList
->SignatureHeaderSize
);
494 TsaCert
= SigData
->SignatureData
;
495 TsaCertSize
= SigList
->SignatureSize
- sizeof (EFI_GUID
);
498 // Each TSA Certificate will normally be in a separate EFI_SIGNATURE_LIST
499 // Leverage ImageTimestampVerify interface for Timestamp counterSignature Verification
501 if (ImageTimestampVerify (SignedData
, SignedDataSize
, TsaCert
, TsaCertSize
, &SigningTime
)) {
503 // The signer signature is valid only when the signing time is earlier than revocation time.
505 if (CompareTimestamp (&SigningTime
, RevocationTime
)) {
516 Check whether the PKCS7 signedData is revoked by verifying with the revoked
517 certificates database, and if the signedData is timestamped, the embedded timestamp
518 counterSignature will be checked with the supplied timestamp database.
520 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
522 @param[in] SignedDataSize The size of SignedData buffer in bytes.
523 @param[in] InHash Pointer to the buffer containing the hash of the message data
524 previously signed and to be verified.
525 @param[in] InHashSize The size of InHash buffer in bytes.
526 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
527 structure which contains list of X.509 certificates
528 of revoked signers and revoked content hashes.
529 @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
530 structures which is used to pass a list of X.509
531 certificates of trusted timestamp signers.
533 @retval EFI_SUCCESS The PKCS7 signedData is revoked.
534 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
535 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
537 Content is not NULL and ContentSize is NULL.
538 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
539 content embedded in PKCS7 signedData.
540 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
544 P7CheckRevocationByHash (
545 IN UINT8
*SignedData
,
546 IN UINTN SignedDataSize
,
549 IN EFI_SIGNATURE_LIST
**RevokedDb
,
550 IN EFI_SIGNATURE_LIST
**TimeStampDb
554 EFI_SIGNATURE_LIST
*SigList
;
555 EFI_SIGNATURE_DATA
*SigData
;
557 UINTN RevokedCertSize
;
562 UINTN TrustedCertLength
;
567 EFI_TIME RevocationTime
;
569 Status
= EFI_SECURITY_VIOLATION
;
577 // The signedData is revoked if the hash of content existed in RevokedDb
579 if (IsContentHashRevokedByHash (InHash
, InHashSize
, RevokedDb
)) {
580 Status
= EFI_SUCCESS
;
585 // Check if the signer's certificate can be found in Revoked database
587 for (Index
= 0; ; Index
++) {
588 SigList
= (EFI_SIGNATURE_LIST
*)(RevokedDb
[Index
]);
591 // The list is terminated by a NULL pointer.
593 if (SigList
== NULL
) {
598 // Ignore any non-X509-format entry in the list.
600 if (!CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Guid
)) {
604 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
605 SigList
->SignatureHeaderSize
);
607 RevokedCert
= SigData
->SignatureData
;
608 RevokedCertSize
= SigList
->SignatureSize
- sizeof (EFI_GUID
);
611 // Verifying the PKCS#7 SignedData with the revoked certificate in RevokedDb
613 if (AuthenticodeVerify (SignedData
, SignedDataSize
, RevokedCert
, RevokedCertSize
, InHash
, InHashSize
)) {
615 // The signedData was verified by one entry in Revoked Database
617 Status
= EFI_SUCCESS
;
622 if (!EFI_ERROR (Status
)) {
624 // The signedData was revoked, since it was hit by RevokedDb
630 // Now we will continue to check the X.509 Certificate Hash & Possible Timestamp
632 if ((TimeStampDb
== NULL
) || (*TimeStampDb
== NULL
)) {
636 Pkcs7GetSigners (SignedData
, SignedDataSize
, &CertBuffer
, &BufferLength
, &TrustedCert
, &TrustedCertLength
);
637 if ((BufferLength
== 0) || (CertBuffer
== NULL
)) {
638 Status
= EFI_SUCCESS
;
643 // Check if any hash of certificates embedded in P7 data is in the revoked database.
645 CertNumber
= (UINT8
)(*CertBuffer
);
646 CertPtr
= CertBuffer
+ 1;
647 for (Index
= 0; Index
< CertNumber
; Index
++) {
649 // Retrieve the Certificate data
651 CertSize
= (UINTN
)ReadUnaligned32 ((UINT32
*)CertPtr
);
652 Cert
= (UINT8
*)CertPtr
+ sizeof (UINT32
);
654 if (IsCertHashRevoked (Cert
, CertSize
, RevokedDb
, &RevocationTime
)) {
656 // Check the timestamp signature and signing time to determine if p7 data can be trusted.
658 Status
= EFI_SUCCESS
;
659 if (IsValidTimestamp (SignedData
, SignedDataSize
, TimeStampDb
, &RevocationTime
)) {
661 // Use EFI_NOT_READY to identify the P7Data is not revoked, because the timestamping
662 // occurred prior to the time of certificate revocation.
664 Status
= EFI_NOT_READY
;
670 CertPtr
= CertPtr
+ sizeof (UINT32
) + CertSize
;
674 Pkcs7FreeSigners (CertBuffer
);
675 Pkcs7FreeSigners (TrustedCert
);
681 Check whether the PKCS7 signedData is revoked by verifying with the revoked
682 certificates database, and if the signedData is timestamped, the embedded timestamp
683 counterSignature will be checked with the supplied timestamp database.
685 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
687 @param[in] SignedDataSize The size of SignedData buffer in bytes.
688 @param[in] InData Pointer to the buffer containing the raw message data
689 previously signed and to be verified.
690 @param[in] InDataSize The size of InData buffer in bytes.
691 @param[in] RevokedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
692 structure which contains list of X.509 certificates
693 of revoked signers and revoked content hashes.
694 @param[in] TimeStampDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
695 structures which is used to pass a list of X.509
696 certificates of trusted timestamp signers.
698 @retval EFI_SUCCESS The PKCS7 signedData is revoked.
699 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
700 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
702 Content is not NULL and ContentSize is NULL.
703 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
704 content embedded in PKCS7 signedData.
705 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
710 IN UINT8
*SignedData
,
711 IN UINTN SignedDataSize
,
714 IN EFI_SIGNATURE_LIST
**RevokedDb
,
715 IN EFI_SIGNATURE_LIST
**TimeStampDb
719 EFI_SIGNATURE_LIST
*SigList
;
720 EFI_SIGNATURE_DATA
*SigData
;
722 UINTN RevokedCertSize
;
727 UINTN TrustedCertLength
;
732 EFI_TIME RevocationTime
;
734 Status
= EFI_UNSUPPORTED
;
742 // The signedData is revoked if the hash of content existed in RevokedDb
744 if (IsContentHashRevoked (InData
, InDataSize
, RevokedDb
)) {
745 Status
= EFI_SUCCESS
;
750 // Check if the signer's certificate can be found in Revoked database
752 for (Index
= 0; ; Index
++) {
753 SigList
= (EFI_SIGNATURE_LIST
*)(RevokedDb
[Index
]);
756 // The list is terminated by a NULL pointer.
758 if (SigList
== NULL
) {
763 // Ignore any non-X509-format entry in the list.
765 if (!CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Guid
)) {
769 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
770 SigList
->SignatureHeaderSize
);
772 RevokedCert
= SigData
->SignatureData
;
773 RevokedCertSize
= SigList
->SignatureSize
- sizeof (EFI_GUID
);
776 // Verifying the PKCS#7 SignedData with the revoked certificate in RevokedDb
778 if (Pkcs7Verify (SignedData
, SignedDataSize
, RevokedCert
, RevokedCertSize
, InData
, InDataSize
)) {
780 // The signedData was verified by one entry in Revoked Database
782 Status
= EFI_SUCCESS
;
787 if (!EFI_ERROR (Status
)) {
789 // The signedData was revoked, since it was hit by RevokedDb
795 // Now we will continue to check the X.509 Certificate Hash & Possible Timestamp
797 if ((TimeStampDb
== NULL
) || (*TimeStampDb
== NULL
)) {
801 Pkcs7GetSigners (SignedData
, SignedDataSize
, &CertBuffer
, &BufferLength
, &TrustedCert
, &TrustedCertLength
);
802 if ((BufferLength
== 0) || (CertBuffer
== NULL
)) {
803 Status
= EFI_SUCCESS
;
808 // Check if any hash of certificates embedded in P7 data is in the revoked database.
810 CertNumber
= (UINT8
)(*CertBuffer
);
811 CertPtr
= CertBuffer
+ 1;
812 for (Index
= 0; Index
< CertNumber
; Index
++) {
814 // Retrieve the Certificate data
816 CertSize
= (UINTN
)ReadUnaligned32 ((UINT32
*)CertPtr
);
817 Cert
= (UINT8
*)CertPtr
+ sizeof (UINT32
);
819 if (IsCertHashRevoked (Cert
, CertSize
, RevokedDb
, &RevocationTime
)) {
821 // Check the timestamp signature and signing time to determine if p7 data can be trusted.
823 Status
= EFI_SUCCESS
;
824 if (IsValidTimestamp (SignedData
, SignedDataSize
, TimeStampDb
, &RevocationTime
)) {
826 // Use EFI_NOT_READY to identify the P7Data is not revoked, because the timestamping
827 // occurred prior to the time of certificate revocation.
829 Status
= EFI_NOT_READY
;
835 CertPtr
= CertPtr
+ sizeof (UINT32
) + CertSize
;
839 Pkcs7FreeSigners (CertBuffer
);
840 Pkcs7FreeSigners (TrustedCert
);
846 Check whether the PKCS7 signedData can be verified by the trusted certificates
847 database, and return the content of the signedData if requested.
849 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
851 @param[in] SignedDataSize The size of SignedData buffer in bytes.
852 @param[in] InHash Pointer to the buffer containing the hash of the message data
853 previously signed and to be verified.
854 @param[in] InHashSize The size of InHash buffer in bytes.
855 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
856 structures which contains lists of X.509 certificates
859 @retval EFI_SUCCESS The PKCS7 signedData is trusted.
860 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
861 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
863 Content is not NULL and ContentSize is NULL.
864 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
865 content embedded in PKCS7 signedData.
866 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
867 @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too
868 small to hold the content. ContentSize updated to
874 IN UINT8
*SignedData
,
875 IN UINTN SignedDataSize
,
878 IN EFI_SIGNATURE_LIST
**AllowedDb
882 EFI_SIGNATURE_LIST
*SigList
;
883 EFI_SIGNATURE_DATA
*SigData
;
888 Status
= EFI_SECURITY_VIOLATION
;
893 if (AllowedDb
== NULL
) {
894 return EFI_INVALID_PARAMETER
;
898 // Build Certificate Stack with all valid X509 certificates in the supplied
899 // Signature List for PKCS7 Verification.
901 for (Index
= 0; ; Index
++) {
902 SigList
= (EFI_SIGNATURE_LIST
*)(AllowedDb
[Index
]);
905 // The list is terminated by a NULL pointer.
907 if (SigList
== NULL
) {
912 // Ignore any non-X509-format entry in the list.
914 if (!CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Guid
)) {
918 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
919 SigList
->SignatureHeaderSize
);
921 TrustCert
= SigData
->SignatureData
;
922 TrustCertSize
= SigList
->SignatureSize
- sizeof (EFI_GUID
);
925 // Verifying the PKCS#7 SignedData with the trusted certificate from AllowedDb
927 if (AuthenticodeVerify (SignedData
, SignedDataSize
, TrustCert
, TrustCertSize
, InHash
, InHashSize
)) {
929 // The SignedData was verified successfully by one entry in Trusted Database
931 Status
= EFI_SUCCESS
;
940 Check whether the PKCS7 signedData can be verified by the trusted certificates
941 database, and return the content of the signedData if requested.
943 @param[in] SignedData Pointer to buffer containing ASN.1 DER-encoded PKCS7
945 @param[in] SignedDataSize The size of SignedData buffer in bytes.
946 @param[in] InData Pointer to the buffer containing the raw message data
947 previously signed and to be verified.
948 @param[in] InDataSize The size of InData buffer in bytes.
949 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
950 structures which contains lists of X.509 certificates
953 @retval EFI_SUCCESS The PKCS7 signedData is trusted.
954 @retval EFI_SECURITY_VIOLATION Fail to verify the signature in PKCS7 signedData.
955 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
957 Content is not NULL and ContentSize is NULL.
958 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
959 content embedded in PKCS7 signedData.
960 @retval EFI_UNSUPPORTED The PKCS7 signedData was not correctly formatted.
961 @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too
962 small to hold the content. ContentSize updated to
968 IN UINT8
*SignedData
,
969 IN UINTN SignedDataSize
,
972 IN EFI_SIGNATURE_LIST
**AllowedDb
976 EFI_SIGNATURE_LIST
*SigList
;
977 EFI_SIGNATURE_DATA
*SigData
;
982 Status
= EFI_SECURITY_VIOLATION
;
987 if (AllowedDb
== NULL
) {
988 return EFI_INVALID_PARAMETER
;
992 // Build Certificate Stack with all valid X509 certificates in the supplied
993 // Signature List for PKCS7 Verification.
995 for (Index
= 0; ; Index
++) {
996 SigList
= (EFI_SIGNATURE_LIST
*)(AllowedDb
[Index
]);
999 // The list is terminated by a NULL pointer.
1001 if (SigList
== NULL
) {
1006 // Ignore any non-X509-format entry in the list.
1008 if (!CompareGuid (&SigList
->SignatureType
, &gEfiCertX509Guid
)) {
1012 SigData
= (EFI_SIGNATURE_DATA
*)((UINT8
*)SigList
+ sizeof (EFI_SIGNATURE_LIST
) +
1013 SigList
->SignatureHeaderSize
);
1015 TrustCert
= SigData
->SignatureData
;
1016 TrustCertSize
= SigList
->SignatureSize
- sizeof (EFI_GUID
);
1019 // Verifying the PKCS#7 SignedData with the trusted certificate from AllowedDb
1021 if (Pkcs7Verify (SignedData
, SignedDataSize
, TrustCert
, TrustCertSize
, InData
, InDataSize
)) {
1023 // The SignedData was verified successfully by one entry in Trusted Database
1025 Status
= EFI_SUCCESS
;
1034 Processes a buffer containing binary DER-encoded PKCS7 signature.
1035 The signed data content may be embedded within the buffer or separated. Function
1036 verifies the signature of the content is valid and signing certificate was not
1037 revoked and is contained within a list of trusted signers.
1039 @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance.
1040 @param[in] SignedData Points to buffer containing ASN.1 DER-encoded PKCS7
1042 @param[in] SignedDataSize The size of SignedData buffer in bytes.
1043 @param[in] InData In case of detached signature, InData points to
1044 buffer containing the raw message data previously
1045 signed and to be verified by function. In case of
1046 SignedData containing embedded data, InData must be
1048 @param[in] InDataSize When InData is used, the size of InData buffer in
1049 bytes. When InData is NULL. This parameter must be
1051 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
1052 structures. The list is terminated by a null
1053 pointer. The EFI_SIGNATURE_LIST structures contain
1054 lists of X.509 certificates of approved signers.
1055 Function recognizes signer certificates of type
1056 EFI_CERT_X509_GUID. Any hash certificate in AllowedDb
1057 list is ignored by this function. Function returns
1058 success if signer of the buffer is within this list
1059 (and not within RevokedDb). This parameter is
1061 @param[in] RevokedDb Optional pointer to a list of pointers to
1062 EFI_SIGNATURE_LIST structures. The list is terminated
1063 by a null pointer. List of X.509 certificates of
1064 revoked signers and revoked file hashes. Except as
1065 noted in description of TimeStampDb signature
1066 verification will always fail if the signer of the
1067 file or the hash of the data component of the buffer
1068 is in RevokedDb list. This list is optional and
1069 caller may pass Null or pointer to NULL if not
1071 @param[in] TimeStampDb Optional pointer to a list of pointers to
1072 EFI_SIGNATURE_LIST structures. The list is terminated
1073 by a null pointer. This parameter can be used to pass
1074 a list of X.509 certificates of trusted time stamp
1075 signers. This list is optional and caller must pass
1076 Null or pointer to NULL if not required.
1077 @param[out] Content On input, points to an optional caller-allocated
1078 buffer into which the function will copy the content
1079 portion of the file after verification succeeds.
1080 This parameter is optional and if NULL, no copy of
1081 content from file is performed.
1082 @param[in,out] ContentSize On input, points to the size in bytes of the optional
1083 buffer Content previously allocated by caller. On
1084 output, if the verification succeeds, the value
1085 referenced by ContentSize will contain the actual
1086 size of the content from signed file. If ContentSize
1087 indicates the caller-allocated buffer is too small
1088 to contain content, an error is returned, and
1089 ContentSize will be updated with the required size.
1090 This parameter must be 0 if Content is Null.
1092 @retval EFI_SUCCESS Content signature was verified against hash of
1093 content, the signer's certificate was not found in
1094 RevokedDb, and was found in AllowedDb or if in signer
1095 is found in both AllowedDb and RevokedDb, the
1096 signing was allowed by reference to TimeStampDb as
1097 described above, and no hash matching content hash
1098 was found in RevokedDb.
1099 @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but
1100 signer was in RevokedDb or not in AllowedDb. Also
1101 returned if matching content hash found in RevokedDb.
1102 @retval EFI_COMPROMISED_DATA Calculated hash differs from signed hash.
1103 @retval EFI_INVALID_PARAMETER SignedData is NULL or SignedDataSize is zero.
1105 @retval EFI_INVALID_PARAMETER Content is not NULL and ContentSize is NULL.
1106 @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb,
1107 RevokedDb or AllowedDb list contents was detected.
1108 @retval EFI_NOT_FOUND Content not found because InData is NULL and no
1109 content embedded in SignedData.
1110 @retval EFI_UNSUPPORTED The SignedData buffer was not correctly formatted
1111 for processing by the function.
1112 @retval EFI_UNSUPPORTED Signed data embedded in SignedData but InData is not
1114 @retval EFI_BUFFER_TOO_SMALL The size of buffer indicated by ContentSize is too
1115 small to hold the content. ContentSize updated to
1122 IN EFI_PKCS7_VERIFY_PROTOCOL
*This
,
1123 IN VOID
*SignedData
,
1124 IN UINTN SignedDataSize
,
1125 IN VOID
*InData OPTIONAL
,
1126 IN UINTN InDataSize
,
1127 IN EFI_SIGNATURE_LIST
**AllowedDb
,
1128 IN EFI_SIGNATURE_LIST
**RevokedDb OPTIONAL
,
1129 IN EFI_SIGNATURE_LIST
**TimeStampDb OPTIONAL
,
1130 OUT VOID
*Content OPTIONAL
,
1131 IN OUT UINTN
*ContentSize
1135 EFI_SIGNATURE_LIST
*SigList
;
1137 UINT8
*AttachedData
;
1138 UINTN AttachedDataSize
;
1143 // Parameters Checking
1145 if ((SignedData
== NULL
) || (SignedDataSize
== 0) || (AllowedDb
== NULL
)) {
1146 return EFI_INVALID_PARAMETER
;
1149 if ((Content
!= NULL
) && (ContentSize
== NULL
)) {
1150 return EFI_INVALID_PARAMETER
;
1154 // Check if any invalid entry format in AllowedDb list contents
1156 for (Index
= 0; ; Index
++) {
1157 SigList
= (EFI_SIGNATURE_LIST
*)(AllowedDb
[Index
]);
1159 if (SigList
== NULL
) {
1163 if (SigList
->SignatureListSize
< sizeof (EFI_SIGNATURE_LIST
) +
1164 SigList
->SignatureHeaderSize
+
1165 SigList
->SignatureSize
)
1172 // Check if any invalid entry format in RevokedDb list contents
1174 if (RevokedDb
!= NULL
) {
1175 for (Index
= 0; ; Index
++) {
1176 SigList
= (EFI_SIGNATURE_LIST
*)(RevokedDb
[Index
]);
1178 if (SigList
== NULL
) {
1182 if (SigList
->SignatureListSize
< sizeof (EFI_SIGNATURE_LIST
) +
1183 SigList
->SignatureHeaderSize
+
1184 SigList
->SignatureSize
)
1192 // Check if any invalid entry format in TimeStampDb list contents
1194 if (TimeStampDb
!= NULL
) {
1195 for (Index
= 0; ; Index
++) {
1196 SigList
= (EFI_SIGNATURE_LIST
*)(TimeStampDb
[Index
]);
1198 if (SigList
== NULL
) {
1202 if (SigList
->SignatureListSize
< sizeof (EFI_SIGNATURE_LIST
) +
1203 SigList
->SignatureHeaderSize
+
1204 SigList
->SignatureSize
)
1212 // Try to retrieve the attached content from PKCS7 signedData
1214 AttachedData
= NULL
;
1215 AttachedDataSize
= 0;
1216 if (!Pkcs7GetAttachedContent (
1219 (VOID
**)&AttachedData
,
1224 // The SignedData buffer was not correctly formatted for processing
1226 return EFI_UNSUPPORTED
;
1229 if (AttachedData
!= NULL
) {
1230 if (InData
!= NULL
) {
1232 // The embedded content is found in SignedData but InData is not NULL
1234 Status
= EFI_UNSUPPORTED
;
1239 // PKCS7-formatted signedData with attached content; Use the embedded
1240 // content for verification
1242 DataPtr
= AttachedData
;
1243 DataSize
= AttachedDataSize
;
1244 } else if (InData
!= NULL
) {
1246 // PKCS7-formatted signedData with detached content; Use the user-supplied
1247 // input data for verification
1249 DataPtr
= (UINT8
*)InData
;
1250 DataSize
= InDataSize
;
1253 // Content not found because InData is NULL and no content attached in SignedData
1255 Status
= EFI_NOT_FOUND
;
1259 Status
= EFI_UNSUPPORTED
;
1262 // Verify PKCS7 SignedData with Revoked database
1264 if (RevokedDb
!= NULL
) {
1265 Status
= P7CheckRevocation (
1273 if (!EFI_ERROR (Status
)) {
1275 // The PKCS7 SignedData is revoked
1277 Status
= EFI_SECURITY_VIOLATION
;
1283 // Verify PKCS7 SignedData with AllowedDB
1285 Status
= P7CheckTrust (
1292 if (EFI_ERROR (Status
)) {
1294 // Verification failed with AllowedDb
1300 // Copy the content portion after verification succeeds
1302 if (Content
!= NULL
) {
1303 if (*ContentSize
< DataSize
) {
1305 // Caller-allocated buffer is too small to contain content
1307 *ContentSize
= DataSize
;
1308 Status
= EFI_BUFFER_TOO_SMALL
;
1310 *ContentSize
= DataSize
;
1311 CopyMem (Content
, DataPtr
, DataSize
);
1316 if (AttachedData
!= NULL
) {
1317 FreePool (AttachedData
);
1324 Processes a buffer containing binary DER-encoded detached PKCS7 signature.
1325 The hash of the signed data content is calculated and passed by the caller. Function
1326 verifies the signature of the content is valid and signing certificate was not revoked
1327 and is contained within a list of trusted signers.
1329 Note: because this function uses hashes and the specification contains a variety of
1330 hash choices, you should be aware that the check against the RevokedDb list
1331 will improperly succeed if the signature is revoked using a different hash
1332 algorithm. For this reason, you should either cycle through all UEFI supported
1333 hashes to see if one is forbidden, or rely on a single hash choice only if the
1334 UEFI signature authority only signs and revokes with a single hash (at time
1335 of writing, this hash choice is SHA256).
1337 @param[in] This Pointer to EFI_PKCS7_VERIFY_PROTOCOL instance.
1338 @param[in] Signature Points to buffer containing ASN.1 DER-encoded PKCS
1340 @param[in] SignatureSize The size of Signature buffer in bytes.
1341 @param[in] InHash InHash points to buffer containing the caller
1342 calculated hash of the data. The parameter may not
1344 @param[in] InHashSize The size in bytes of InHash buffer.
1345 @param[in] AllowedDb Pointer to a list of pointers to EFI_SIGNATURE_LIST
1346 structures. The list is terminated by a null
1347 pointer. The EFI_SIGNATURE_LIST structures contain
1348 lists of X.509 certificates of approved signers.
1349 Function recognizes signer certificates of type
1350 EFI_CERT_X509_GUID. Any hash certificate in AllowedDb
1351 list is ignored by this function. Function returns
1352 success if signer of the buffer is within this list
1353 (and not within RevokedDb). This parameter is
1355 @param[in] RevokedDb Optional pointer to a list of pointers to
1356 EFI_SIGNATURE_LIST structures. The list is terminated
1357 by a null pointer. List of X.509 certificates of
1358 revoked signers and revoked file hashes. Signature
1359 verification will always fail if the signer of the
1360 file or the hash of the data component of the buffer
1361 is in RevokedDb list. This parameter is optional
1362 and caller may pass Null if not required.
1363 @param[in] TimeStampDb Optional pointer to a list of pointers to
1364 EFI_SIGNATURE_LIST structures. The list is terminated
1365 by a null pointer. This parameter can be used to pass
1366 a list of X.509 certificates of trusted time stamp
1369 @retval EFI_SUCCESS Signed hash was verified against caller-provided
1370 hash of content, the signer's certificate was not
1371 found in RevokedDb, and was found in AllowedDb or
1372 if in signer is found in both AllowedDb and
1373 RevokedDb, the signing was allowed by reference to
1374 TimeStampDb as described above, and no hash matching
1375 content hash was found in RevokedDb.
1376 @retval EFI_SECURITY_VIOLATION The SignedData buffer was correctly formatted but
1377 signer was in RevokedDb or not in AllowedDb. Also
1378 returned if matching content hash found in RevokedDb.
1379 @retval EFI_COMPROMISED_DATA Caller provided hash differs from signed hash. Or,
1380 caller and encrypted hash are different sizes.
1381 @retval EFI_INVALID_PARAMETER Signature is NULL or SignatureSize is zero. InHash
1382 is NULL or InHashSize is zero. AllowedDb is NULL.
1383 @retval EFI_ABORTED Unsupported or invalid format in TimeStampDb,
1384 RevokedDb or AllowedDb list contents was detected.
1385 @retval EFI_UNSUPPORTED The Signature buffer was not correctly formatted
1386 for processing by the function.
1392 IN EFI_PKCS7_VERIFY_PROTOCOL
*This
,
1394 IN UINTN SignatureSize
,
1396 IN UINTN InHashSize
,
1397 IN EFI_SIGNATURE_LIST
**AllowedDb
,
1398 IN EFI_SIGNATURE_LIST
**RevokedDb OPTIONAL
,
1399 IN EFI_SIGNATURE_LIST
**TimeStampDb OPTIONAL
1405 // Parameters Checking
1407 if ( (Signature
== NULL
) || (SignatureSize
== 0) || (AllowedDb
== NULL
)
1408 || (InHash
== NULL
) || (InHashSize
== 0))
1410 return EFI_INVALID_PARAMETER
;
1414 // Verify PKCS7 SignedData with Revoked database
1416 if (RevokedDb
!= NULL
) {
1417 Status
= P7CheckRevocationByHash (
1426 if (!EFI_ERROR (Status
)) {
1428 // The PKCS7 SignedData is revoked
1430 return EFI_SECURITY_VIOLATION
;
1435 // Verify PKCS7 SignedData with AllowedDB
1437 Status
= P7CheckTrustByHash (
1449 // The PKCS7 Verification Protocol
1451 EFI_PKCS7_VERIFY_PROTOCOL mPkcs7Verify
= {
1457 The user Entry Point for the PKCS7 Verification driver.
1459 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1460 @param[in] SystemTable A pointer to the EFI System Table.
1462 @retval EFI_SUCCESS The entry point is executed successfully.
1463 @retval EFI_NOT_SUPPORTED Platform does not support PKCS7 Verification.
1464 @retval Other Some error occurs when executing this entry point.
1469 Pkcs7VerifyDriverEntry (
1470 IN EFI_HANDLE ImageHandle
,
1471 IN EFI_SYSTEM_TABLE
*SystemTable
1476 EFI_PKCS7_VERIFY_PROTOCOL Useless
;
1479 // Avoid loading a second copy if this is built as an external module
1481 Status
= gBS
->LocateProtocol (&gEfiPkcs7VerifyProtocolGuid
, NULL
, (VOID
**)&Useless
);
1482 if (!EFI_ERROR (Status
)) {
1487 // Install UEFI Pkcs7 Verification Protocol
1490 Status
= gBS
->InstallMultipleProtocolInterfaces (
1492 &gEfiPkcs7VerifyProtocolGuid
,