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