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