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