]> git.proxmox.com Git - mirror_edk2.git/blame - CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7Sign.c
CryptoPkg: Replace BSD License with BSD+Patent License
[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
65 if (PrivateKey == NULL || KeyPassword == NULL || InData == NULL ||\r
66 SignCert == NULL || SignedData == NULL || SignedDataSize == NULL || InDataSize > INT_MAX) {\r
67 return FALSE;\r
68 }\r
69\r
70 RsaContext = NULL;\r
71 Key = NULL;\r
72 Pkcs7 = NULL;\r
73 DataBio = NULL;\r
74 Status = FALSE;\r
75\r
76 //\r
77 // Retrieve RSA private key from PEM data.\r
78 //\r
79 Status = RsaGetPrivateKeyFromPem (\r
80 PrivateKey,\r
81 PrivateKeySize,\r
82 (CONST CHAR8 *) KeyPassword,\r
83 (VOID **) &RsaContext\r
84 );\r
85 if (!Status) {\r
86 return Status;\r
87 }\r
88\r
dda39f3a 89 Status = FALSE;\r
90\r
532616bb 91 //\r
92 // Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling\r
93 //\r
dda39f3a 94 if (EVP_add_digest (EVP_md5 ()) == 0) {\r
95 goto _Exit;\r
96 }\r
97 if (EVP_add_digest (EVP_sha1 ()) == 0) {\r
98 goto _Exit;\r
99 }\r
100 if (EVP_add_digest (EVP_sha256 ()) == 0) {\r
101 goto _Exit;\r
102 }\r
103\r
532616bb 104 RandomSeed (NULL, 0);\r
105\r
106 //\r
107 // Construct OpenSSL EVP_PKEY for private key.\r
108 //\r
109 Key = EVP_PKEY_new ();\r
110 if (Key == NULL) {\r
532616bb 111 goto _Exit;\r
112 }\r
1463ce18
QL
113 if (EVP_PKEY_assign_RSA (Key, (RSA *) RsaContext) == 0) {\r
114 goto _Exit;\r
115 }\r
532616bb 116\r
117 //\r
630f67dd 118 // Convert the data to be signed to BIO format.\r
532616bb 119 //\r
120 DataBio = BIO_new (BIO_s_mem ());\r
5b2956ea
YT
121 if (DataBio == NULL) {\r
122 goto _Exit;\r
123 }\r
124\r
125 if (BIO_write (DataBio, InData, (int) InDataSize) <= 0) {\r
126 goto _Exit;\r
127 }\r
532616bb 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
5b2956ea 158 ASSERT (P7DataSize > 19);\r
532616bb 159\r
160 //\r
161 // Strip ContentInfo to content only for signeddata. The data be trimmed off\r
162 // is totally 19 bytes.\r
163 //\r
164 *SignedDataSize = P7DataSize - 19;\r
6fe575d0 165 *SignedData = AllocatePool (*SignedDataSize);\r
532616bb 166 if (*SignedData == NULL) {\r
532616bb 167 OPENSSL_free (P7Data);\r
168 goto _Exit;\r
169 }\r
170\r
171 CopyMem (*SignedData, P7Data + 19, *SignedDataSize);\r
1463ce18 172\r
532616bb 173 OPENSSL_free (P7Data);\r
174\r
175 Status = TRUE;\r
176\r
177_Exit:\r
178 //\r
179 // Release Resources\r
180 //\r
532616bb 181 if (Key != NULL) {\r
182 EVP_PKEY_free (Key);\r
183 }\r
184\r
185 if (DataBio != NULL) {\r
186 BIO_free (DataBio);\r
187 }\r
188\r
189 if (Pkcs7 != NULL) {\r
190 PKCS7_free (Pkcs7);\r
191 }\r
192\r
193 return Status;\r
194}\r