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