]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7.c
d0a6ea544a4ab336691660412bb1bbc175d2001d
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptPkcs7.c
1 /** @file
2 PKCS#7 SignedData Verification Wrapper Implementation over OpenSSL.
3
4 Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <Library/BaseLib.h>
16 #include <Library/BaseMemoryLib.h>
17 #include <Library/DebugLib.h>
18
19 #include <Library/BaseCryptLib.h>
20 #include <openssl/objects.h>
21 #include <openssl/x509.h>
22 #include <openssl/pkcs7.h>
23
24
25 /**
26 Verifies the validility of a PKCS#7 signed data as described in "PKCS #7: Cryptographic
27 Message Syntax Standard".
28
29 If P7Data is NULL, then ASSERT().
30
31 @param[in] P7Data Pointer to the PKCS#7 message to verify.
32 @param[in] P7Length Length of the PKCS#7 message in bytes.
33 @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which
34 is used for certificate chain verification.
35 @param[in] CertLength Length of the trusted certificate in bytes.
36 @param[in] InData Pointer to the content to be verified.
37 @param[in] DataLength Length of InData in bytes.
38
39 @return TRUE The specified PKCS#7 signed data is valid.
40 @return FALSE Invalid PKCS#7 signed data.
41
42 **/
43 BOOLEAN
44 EFIAPI
45 Pkcs7Verify (
46 IN CONST UINT8 *P7Data,
47 IN UINTN P7Length,
48 IN CONST UINT8 *TrustedCert,
49 IN UINTN CertLength,
50 IN CONST UINT8 *InData,
51 IN UINTN DataLength
52 )
53 {
54 PKCS7 *Pkcs7;
55 UINT8 *Content;
56 BIO *CertBio;
57 BIO *DataBio;
58 BOOLEAN Status;
59 X509 *Cert;
60 X509_STORE *CertStore;
61
62 //
63 // ASSERT if P7Data is NULL
64 //
65 ASSERT (P7Data != NULL);
66
67 Status = FALSE;
68 Pkcs7 = NULL;
69 CertBio = NULL;
70 DataBio = NULL;
71 Cert = NULL;
72 CertStore = NULL;
73
74 //
75 // Register & Initialize necessary digest algorithms for PKCS#7 Handling
76 //
77 EVP_add_digest (EVP_md5());
78 EVP_add_digest (EVP_sha1());
79 EVP_add_digest (EVP_sha256());
80
81 //
82 // Retrieve PKCS#7 Data (DER encoding)
83 //
84 Pkcs7 = d2i_PKCS7 (NULL, &P7Data, (int)P7Length);
85 if (Pkcs7 == NULL) {
86 goto _Exit;
87 }
88
89 //
90 // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
91 //
92 if (!PKCS7_type_is_signed (Pkcs7)) {
93 goto _Exit;
94 }
95
96 //
97 // Check PKCS#7 embedded signed content with InData.
98 //
99 if (InData != NULL) {
100 //
101 // NOTE: PKCS7_dataDecode() didn't work for Authenticode-format signed data due to
102 // some authenticode-specific structure. Use opaque ASN.1 string to retrieve
103 // PKCS#7 ContentInfo here.
104 //
105 Content = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data);
106
107 // Ignore two bytes for DER encoding of ASN.1 "SEQUENCE"
108 if (CompareMem (Content + 2, InData, DataLength) != 0) {
109 goto _Exit;
110 }
111 }
112
113 //
114 // Read DER-encoded root certificate and Construct X509 Certificate
115 //
116 CertBio = BIO_new (BIO_s_mem ());
117 BIO_write (CertBio, TrustedCert, (int)CertLength);
118 if (CertBio == NULL) {
119 goto _Exit;
120 }
121 Cert = d2i_X509_bio (CertBio, NULL);
122 if (Cert == NULL) {
123 goto _Exit;
124 }
125
126 //
127 // Setup X509 Store for trusted certificate
128 //
129 CertStore = X509_STORE_new ();
130 if (CertStore == NULL) {
131 goto _Exit;
132 }
133 if (!(X509_STORE_add_cert (CertStore, Cert))) {
134 goto _Exit;
135 }
136
137 //
138 // For generic PKCS#7 handling, InData may be NULL if the content is present
139 // in PKCS#7 structure. So ignore NULL checking here.
140 //
141 DataBio = BIO_new (BIO_s_mem ());
142 BIO_write (DataBio, InData, (int)DataLength);
143
144 //
145 // Verifies the PKCS#7 signedData structure
146 //
147 Status = (BOOLEAN) PKCS7_verify (Pkcs7, NULL, CertStore, DataBio, NULL, 0);
148
149 _Exit:
150 //
151 // Release Resources
152 //
153 BIO_free (DataBio);
154 BIO_free (CertBio);
155 X509_free (Cert);
156 X509_STORE_free (CertStore);
157 PKCS7_free (Pkcs7);
158
159 return Status;
160 }