]> git.proxmox.com Git - mirror_edk2.git/blob - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c
CryptoPkg: Update PK Cipher Wrappers work with opaque objects.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Pk / CryptPkcs7Sign.c
1 /** @file
2 PKCS#7 SignedData Sign Wrapper Implementation over OpenSSL.
3
4 Copyright (c) 2009 - 2017, 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 "InternalCryptLib.h"
16
17 #include <openssl/objects.h>
18 #include <openssl/x509.h>
19 #include <openssl/pkcs7.h>
20
21 /**
22 Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message
23 Syntax Standard, version 1.5". This interface is only intended to be used for
24 application to perform PKCS#7 functionality validation.
25
26 @param[in] PrivateKey Pointer to the PEM-formatted private key data for
27 data signing.
28 @param[in] PrivateKeySize Size of the PEM private key data in bytes.
29 @param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM
30 key data.
31 @param[in] InData Pointer to the content to be signed.
32 @param[in] InDataSize Size of InData in bytes.
33 @param[in] SignCert Pointer to signer's DER-encoded certificate to sign with.
34 @param[in] OtherCerts Pointer to an optional additional set of certificates to
35 include in the PKCS#7 signedData (e.g. any intermediate
36 CAs in the chain).
37 @param[out] SignedData Pointer to output PKCS#7 signedData.
38 @param[out] SignedDataSize Size of SignedData in bytes.
39
40 @retval TRUE PKCS#7 data signing succeeded.
41 @retval FALSE PKCS#7 data signing failed.
42
43 **/
44 BOOLEAN
45 EFIAPI
46 Pkcs7Sign (
47 IN CONST UINT8 *PrivateKey,
48 IN UINTN PrivateKeySize,
49 IN CONST UINT8 *KeyPassword,
50 IN UINT8 *InData,
51 IN UINTN InDataSize,
52 IN UINT8 *SignCert,
53 IN UINT8 *OtherCerts OPTIONAL,
54 OUT UINT8 **SignedData,
55 OUT UINTN *SignedDataSize
56 )
57 {
58 BOOLEAN Status;
59 EVP_PKEY *Key;
60 BIO *DataBio;
61 PKCS7 *Pkcs7;
62 UINT8 *RsaContext;
63 UINT8 *P7Data;
64 UINTN P7DataSize;
65 UINT8 *Tmp;
66
67 //
68 // Check input parameters.
69 //
70 if (PrivateKey == NULL || KeyPassword == NULL || InData == NULL ||
71 SignCert == NULL || SignedData == NULL || SignedDataSize == NULL || InDataSize > INT_MAX) {
72 return FALSE;
73 }
74
75 RsaContext = NULL;
76 Key = NULL;
77 Pkcs7 = NULL;
78 DataBio = NULL;
79 Status = FALSE;
80
81 //
82 // Retrieve RSA private key from PEM data.
83 //
84 Status = RsaGetPrivateKeyFromPem (
85 PrivateKey,
86 PrivateKeySize,
87 (CONST CHAR8 *) KeyPassword,
88 (VOID **) &RsaContext
89 );
90 if (!Status) {
91 return Status;
92 }
93
94 Status = FALSE;
95
96 //
97 // Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling
98 //
99 if (EVP_add_digest (EVP_md5 ()) == 0) {
100 goto _Exit;
101 }
102 if (EVP_add_digest (EVP_sha1 ()) == 0) {
103 goto _Exit;
104 }
105 if (EVP_add_digest (EVP_sha256 ()) == 0) {
106 goto _Exit;
107 }
108
109 RandomSeed (NULL, 0);
110
111 //
112 // Construct OpenSSL EVP_PKEY for private key.
113 //
114 Key = EVP_PKEY_new ();
115 if (Key == NULL) {
116 goto _Exit;
117 }
118 if (EVP_PKEY_assign_RSA (Key, (RSA *) RsaContext) == 0) {
119 goto _Exit;
120 }
121
122 //
123 // Convert the data to be signed to BIO format.
124 //
125 DataBio = BIO_new (BIO_s_mem ());
126 if (DataBio == NULL) {
127 goto _Exit;
128 }
129
130 if (BIO_write (DataBio, InData, (int) InDataSize) <= 0) {
131 goto _Exit;
132 }
133
134 //
135 // Create the PKCS#7 signedData structure.
136 //
137 Pkcs7 = PKCS7_sign (
138 (X509 *) SignCert,
139 Key,
140 (STACK_OF(X509) *) OtherCerts,
141 DataBio,
142 PKCS7_BINARY | PKCS7_NOATTR | PKCS7_DETACHED
143 );
144 if (Pkcs7 == NULL) {
145 goto _Exit;
146 }
147
148 //
149 // Convert PKCS#7 signedData structure into DER-encoded buffer.
150 //
151 P7DataSize = i2d_PKCS7 (Pkcs7, NULL);
152 if (P7DataSize <= 19) {
153 goto _Exit;
154 }
155
156 P7Data = malloc (P7DataSize);
157 if (P7Data == NULL) {
158 goto _Exit;
159 }
160
161 Tmp = P7Data;
162 P7DataSize = i2d_PKCS7 (Pkcs7, (unsigned char **) &Tmp);
163 ASSERT (P7DataSize > 19);
164
165 //
166 // Strip ContentInfo to content only for signeddata. The data be trimmed off
167 // is totally 19 bytes.
168 //
169 *SignedDataSize = P7DataSize - 19;
170 *SignedData = malloc (*SignedDataSize);
171 if (*SignedData == NULL) {
172 OPENSSL_free (P7Data);
173 goto _Exit;
174 }
175
176 CopyMem (*SignedData, P7Data + 19, *SignedDataSize);
177
178 OPENSSL_free (P7Data);
179
180 Status = TRUE;
181
182 _Exit:
183 //
184 // Release Resources
185 //
186 if (Key != NULL) {
187 EVP_PKEY_free (Key);
188 }
189
190 if (DataBio != NULL) {
191 BIO_free (DataBio);
192 }
193
194 if (Pkcs7 != NULL) {
195 PKCS7_free (Pkcs7);
196 }
197
198 return Status;
199 }