TianoCore EDK2 master
Loading...
Searching...
No Matches
CryptPkcs7Sign.c
Go to the documentation of this file.
1
9#include "InternalCryptLib.h"
10
11#include <openssl/objects.h>
12#include <openssl/x509.h>
13#include <openssl/pkcs7.h>
14
39BOOLEAN
40EFIAPI
42 IN CONST UINT8 *PrivateKey,
43 IN UINTN PrivateKeySize,
44 IN CONST UINT8 *KeyPassword,
45 IN UINT8 *InData,
46 IN UINTN InDataSize,
47 IN UINT8 *SignCert,
48 IN UINT8 *OtherCerts OPTIONAL,
49 OUT UINT8 **SignedData,
50 OUT UINTN *SignedDataSize
51 )
52{
53 BOOLEAN Status;
54 EVP_PKEY *Key;
55 BIO *DataBio;
56 PKCS7 *Pkcs7;
57 UINT8 *RsaContext;
58 UINT8 *P7Data;
59 UINTN P7DataSize;
60 UINT8 *Tmp;
61
62 //
63 // Check input parameters.
64 //
65 if ((PrivateKey == NULL) || (KeyPassword == NULL) || (InData == NULL) ||
66 (SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL) || (InDataSize > INT_MAX))
67 {
68 return FALSE;
69 }
70
71 RsaContext = NULL;
72 Key = NULL;
73 Pkcs7 = NULL;
74 DataBio = NULL;
75 Status = FALSE;
76
77 //
78 // Retrieve RSA private key from PEM data.
79 //
81 PrivateKey,
82 PrivateKeySize,
83 (CONST CHAR8 *)KeyPassword,
84 (VOID **)&RsaContext
85 );
86 if (!Status) {
87 return Status;
88 }
89
90 Status = FALSE;
91
92 //
93 // Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling
94 //
95 if (EVP_add_digest (EVP_md5 ()) == 0) {
96 goto _Exit;
97 }
98
99 if (EVP_add_digest (EVP_sha1 ()) == 0) {
100 goto _Exit;
101 }
102
103 if (EVP_add_digest (EVP_sha256 ()) == 0) {
104 goto _Exit;
105 }
106
107 RandomSeed (NULL, 0);
108
109 //
110 // Construct OpenSSL EVP_PKEY for private key.
111 //
112 Key = EVP_PKEY_new ();
113 if (Key == NULL) {
114 goto _Exit;
115 }
116
117 if (EVP_PKEY_assign_RSA (Key, (RSA *)RsaContext) == 0) {
118 goto _Exit;
119 }
120
121 //
122 // Convert the data to be signed to BIO format.
123 //
124 DataBio = BIO_new (BIO_s_mem ());
125 if (DataBio == NULL) {
126 goto _Exit;
127 }
128
129 if (BIO_write (DataBio, InData, (int)InDataSize) <= 0) {
130 goto _Exit;
131 }
132
133 //
134 // Create the PKCS#7 signedData structure.
135 //
136 Pkcs7 = PKCS7_sign (
137 (X509 *)SignCert,
138 Key,
139 (STACK_OF (X509) *) OtherCerts,
140 DataBio,
141 PKCS7_BINARY | PKCS7_NOATTR | PKCS7_DETACHED
142 );
143 if (Pkcs7 == NULL) {
144 goto _Exit;
145 }
146
147 //
148 // Convert PKCS#7 signedData structure into DER-encoded buffer.
149 //
150 P7DataSize = i2d_PKCS7 (Pkcs7, NULL);
151 if (P7DataSize <= 19) {
152 goto _Exit;
153 }
154
155 P7Data = malloc (P7DataSize);
156 if (P7Data == NULL) {
157 goto _Exit;
158 }
159
160 Tmp = P7Data;
161 P7DataSize = i2d_PKCS7 (Pkcs7, (unsigned char **)&Tmp);
162 ASSERT (P7DataSize > 19);
163
164 //
165 // Strip ContentInfo to content only for signeddata. The data be trimmed off
166 // is totally 19 bytes.
167 //
168 *SignedDataSize = P7DataSize - 19;
169 *SignedData = AllocatePool (*SignedDataSize);
170 if (*SignedData == NULL) {
171 OPENSSL_free (P7Data);
172 goto _Exit;
173 }
174
175 CopyMem (*SignedData, P7Data + 19, *SignedDataSize);
176
177 OPENSSL_free (P7Data);
178
179 Status = TRUE;
180
181_Exit:
182 //
183 // Release Resources
184 //
185 if (Key != NULL) {
186 EVP_PKEY_free (Key);
187 }
188
189 if (DataBio != NULL) {
190 BIO_free (DataBio);
191 }
192
193 if (Pkcs7 != NULL) {
194 PKCS7_free (Pkcs7);
195 }
196
197 return Status;
198}
UINT64 UINTN
BOOLEAN EFIAPI RsaGetPrivateKeyFromPem(IN CONST UINT8 *PemData, IN UINTN PemSize, IN CONST CHAR8 *Password, OUT VOID **RsaContext)
Definition: CryptPem.c:66
BOOLEAN EFIAPI RandomSeed(IN CONST UINT8 *Seed OPTIONAL, IN UINTN SeedSize)
Definition: CryptRand.c:36
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
BOOLEAN EFIAPI Pkcs7Sign(IN CONST UINT8 *PrivateKey, IN UINTN PrivateKeySize, IN CONST UINT8 *KeyPassword, IN UINT8 *InData, IN UINTN InDataSize, IN UINT8 *SignCert, IN UINT8 *OtherCerts OPTIONAL, OUT UINT8 **SignedData, OUT UINTN *SignedDataSize)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)