]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c
CryptoPkg: Add some comments for API usage clarification.
[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
1463ce18 4Copyright (c) 2009 - 2015, 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
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
1463ce18
QL
119 if (EVP_PKEY_assign_RSA (Key, (RSA *) RsaContext) == 0) {\r
120 goto _Exit;\r
121 }\r
532616bb 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
5b2956ea
YT
127 if (DataBio == NULL) {\r
128 goto _Exit;\r
129 }\r
130\r
131 if (BIO_write (DataBio, InData, (int) InDataSize) <= 0) {\r
132 goto _Exit;\r
133 }\r
532616bb 134\r
135 //\r
136 // Create the PKCS#7 signedData structure.\r
137 //\r
138 Pkcs7 = PKCS7_sign (\r
139 (X509 *) SignCert,\r
140 Key,\r
141 (STACK_OF(X509) *) OtherCerts,\r
142 DataBio,\r
143 PKCS7_BINARY | PKCS7_NOATTR | PKCS7_DETACHED\r
144 );\r
145 if (Pkcs7 == NULL) {\r
532616bb 146 goto _Exit;\r
147 }\r
148\r
149 //\r
150 // Convert PKCS#7 signedData structure into DER-encoded buffer.\r
151 //\r
152 P7DataSize = i2d_PKCS7 (Pkcs7, NULL);\r
153 if (P7DataSize <= 19) {\r
532616bb 154 goto _Exit;\r
155 }\r
156\r
157 P7Data = malloc (P7DataSize);\r
158 if (P7Data == NULL) {\r
532616bb 159 goto _Exit;\r
160 }\r
161\r
162 Tmp = P7Data;\r
163 P7DataSize = i2d_PKCS7 (Pkcs7, (unsigned char **) &Tmp);\r
5b2956ea 164 ASSERT (P7DataSize > 19);\r
532616bb 165\r
166 //\r
167 // Strip ContentInfo to content only for signeddata. The data be trimmed off\r
168 // is totally 19 bytes.\r
169 //\r
170 *SignedDataSize = P7DataSize - 19;\r
171 *SignedData = malloc (*SignedDataSize);\r
172 if (*SignedData == NULL) {\r
532616bb 173 OPENSSL_free (P7Data);\r
174 goto _Exit;\r
175 }\r
176\r
177 CopyMem (*SignedData, P7Data + 19, *SignedDataSize);\r
1463ce18 178\r
532616bb 179 OPENSSL_free (P7Data);\r
180\r
181 Status = TRUE;\r
182\r
183_Exit:\r
184 //\r
185 // Release Resources\r
186 //\r
187 if (RsaContext != NULL) {\r
188 RsaFree (RsaContext);\r
189 if (Key != NULL) {\r
190 Key->pkey.rsa = NULL;\r
191 }\r
192 }\r
193\r
194 if (Key != NULL) {\r
195 EVP_PKEY_free (Key);\r
196 }\r
197\r
198 if (DataBio != NULL) {\r
199 BIO_free (DataBio);\r
200 }\r
201\r
202 if (Pkcs7 != NULL) {\r
203 PKCS7_free (Pkcs7);\r
204 }\r
205\r
206 return Status;\r
207}\r