1 /* Copyright (c) 2017, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15 #include <openssl/pkcs7.h>
16
17 #include <assert.h>
18 #include <limits.h>
19
20 #include <openssl/bytestring.h>
21 #include <openssl/err.h>
22 #include <openssl/mem.h>
23 #include <openssl/pem.h>
24 #include <openssl/pool.h>
25 #include <openssl/stack.h>
26 #include <openssl/x509.h>
27
28 #include "internal.h"
29 #include "../internal.h"
30
31
PKCS7_get_certificates(STACK_OF (X509)* out_certs,CBS * cbs)32 int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
33 int ret = 0;
34 const size_t initial_certs_len = sk_X509_num(out_certs);
35 STACK_OF(CRYPTO_BUFFER) *raw = sk_CRYPTO_BUFFER_new_null();
36 if (raw == NULL ||
37 !PKCS7_get_raw_certificates(raw, cbs, NULL)) {
38 goto err;
39 }
40
41 for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(raw); i++) {
42 CRYPTO_BUFFER *buf = sk_CRYPTO_BUFFER_value(raw, i);
43 X509 *x509 = X509_parse_from_buffer(buf);
44 if (x509 == NULL ||
45 !sk_X509_push(out_certs, x509)) {
46 X509_free(x509);
47 goto err;
48 }
49 }
50
51 ret = 1;
52
53 err:
54 sk_CRYPTO_BUFFER_pop_free(raw, CRYPTO_BUFFER_free);
55 if (!ret) {
56 while (sk_X509_num(out_certs) != initial_certs_len) {
57 X509 *x509 = sk_X509_pop(out_certs);
58 X509_free(x509);
59 }
60 }
61
62 return ret;
63 }
64
PKCS7_get_CRLs(STACK_OF (X509_CRL)* out_crls,CBS * cbs)65 int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
66 CBS signed_data, crls;
67 uint8_t *der_bytes = NULL;
68 int ret = 0, has_crls;
69 const size_t initial_crls_len = sk_X509_CRL_num(out_crls);
70
71 // See https://tools.ietf.org/html/rfc2315#section-9.1
72 if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs) ||
73 // Even if only CRLs are included, there may be an empty certificates
74 // block. OpenSSL does this, for example.
75 !CBS_get_optional_asn1(
76 &signed_data, NULL, NULL,
77 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
78 !CBS_get_optional_asn1(
79 &signed_data, &crls, &has_crls,
80 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
81 goto err;
82 }
83
84 if (!has_crls) {
85 CBS_init(&crls, NULL, 0);
86 }
87
88 while (CBS_len(&crls) > 0) {
89 CBS crl_data;
90 X509_CRL *crl;
91 const uint8_t *inp;
92
93 if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) {
94 goto err;
95 }
96
97 if (CBS_len(&crl_data) > LONG_MAX) {
98 goto err;
99 }
100 inp = CBS_data(&crl_data);
101 crl = d2i_X509_CRL(NULL, &inp, (long)CBS_len(&crl_data));
102 if (!crl) {
103 goto err;
104 }
105
106 assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data));
107
108 if (sk_X509_CRL_push(out_crls, crl) == 0) {
109 X509_CRL_free(crl);
110 goto err;
111 }
112 }
113
114 ret = 1;
115
116 err:
117 OPENSSL_free(der_bytes);
118
119 if (!ret) {
120 while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
121 X509_CRL_free(sk_X509_CRL_pop(out_crls));
122 }
123 }
124
125 return ret;
126 }
127
PKCS7_get_PEM_certificates(STACK_OF (X509)* out_certs,BIO * pem_bio)128 int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) {
129 uint8_t *data;
130 long len;
131 int ret;
132
133 // Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
134 // internally will actually allow several other values too, including
135 // "CERTIFICATE".
136 if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
137 PEM_STRING_PKCS7, pem_bio,
138 NULL /* password callback */,
139 NULL /* password callback argument */)) {
140 return 0;
141 }
142
143 CBS cbs;
144 CBS_init(&cbs, data, len);
145 ret = PKCS7_get_certificates(out_certs, &cbs);
146 OPENSSL_free(data);
147 return ret;
148 }
149
PKCS7_get_PEM_CRLs(STACK_OF (X509_CRL)* out_crls,BIO * pem_bio)150 int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
151 uint8_t *data;
152 long len;
153 int ret;
154
155 // Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
156 // internally will actually allow several other values too, including
157 // "CERTIFICATE".
158 if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
159 PEM_STRING_PKCS7, pem_bio,
160 NULL /* password callback */,
161 NULL /* password callback argument */)) {
162 return 0;
163 }
164
165 CBS cbs;
166 CBS_init(&cbs, data, len);
167 ret = PKCS7_get_CRLs(out_crls, &cbs);
168 OPENSSL_free(data);
169 return ret;
170 }
171
pkcs7_bundle_certificates_cb(CBB * out,const void * arg)172 static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) {
173 const STACK_OF(X509) *certs = arg;
174 size_t i;
175 CBB certificates;
176
177 // See https://tools.ietf.org/html/rfc2315#section-9.1
178 if (!CBB_add_asn1(out, &certificates,
179 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
180 return 0;
181 }
182
183 for (i = 0; i < sk_X509_num(certs); i++) {
184 X509 *x509 = sk_X509_value(certs, i);
185 uint8_t *buf;
186 int len = i2d_X509(x509, NULL);
187
188 if (len < 0 ||
189 !CBB_add_space(&certificates, &buf, len) ||
190 i2d_X509(x509, &buf) < 0) {
191 return 0;
192 }
193 }
194
195 // |certificates| is a implicitly-tagged SET OF.
196 return CBB_flush_asn1_set_of(&certificates) && CBB_flush(out);
197 }
198
PKCS7_bundle_certificates(CBB * out,const STACK_OF (X509)* certs)199 int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
200 return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs);
201 }
202
pkcs7_bundle_crls_cb(CBB * out,const void * arg)203 static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
204 const STACK_OF(X509_CRL) *crls = arg;
205 size_t i;
206 CBB crl_data;
207
208 // See https://tools.ietf.org/html/rfc2315#section-9.1
209 if (!CBB_add_asn1(out, &crl_data,
210 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
211 return 0;
212 }
213
214 for (i = 0; i < sk_X509_CRL_num(crls); i++) {
215 X509_CRL *crl = sk_X509_CRL_value(crls, i);
216 uint8_t *buf;
217 int len = i2d_X509_CRL(crl, NULL);
218
219 if (len < 0 ||
220 !CBB_add_space(&crl_data, &buf, len) ||
221 i2d_X509_CRL(crl, &buf) < 0) {
222 return 0;
223 }
224 }
225
226 // |crl_data| is a implicitly-tagged SET OF.
227 return CBB_flush_asn1_set_of(&crl_data) && CBB_flush(out);
228 }
229
PKCS7_bundle_CRLs(CBB * out,const STACK_OF (X509_CRL)* crls)230 int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
231 return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
232 }
233
pkcs7_new(CBS * cbs)234 static PKCS7 *pkcs7_new(CBS *cbs) {
235 PKCS7 *ret = OPENSSL_malloc(sizeof(PKCS7));
236 if (ret == NULL) {
237 return NULL;
238 }
239 OPENSSL_memset(ret, 0, sizeof(PKCS7));
240 ret->type = OBJ_nid2obj(NID_pkcs7_signed);
241 ret->d.sign = OPENSSL_malloc(sizeof(PKCS7_SIGNED));
242 if (ret->d.sign == NULL) {
243 goto err;
244 }
245 ret->d.sign->cert = sk_X509_new_null();
246 ret->d.sign->crl = sk_X509_CRL_new_null();
247 CBS copy = *cbs, copy2 = *cbs;
248 if (ret->d.sign->cert == NULL || ret->d.sign->crl == NULL ||
249 !PKCS7_get_certificates(ret->d.sign->cert, ©) ||
250 !PKCS7_get_CRLs(ret->d.sign->crl, cbs)) {
251 goto err;
252 }
253
254 if (sk_X509_num(ret->d.sign->cert) == 0) {
255 sk_X509_free(ret->d.sign->cert);
256 ret->d.sign->cert = NULL;
257 }
258
259 if (sk_X509_CRL_num(ret->d.sign->crl) == 0) {
260 sk_X509_CRL_free(ret->d.sign->crl);
261 ret->d.sign->crl = NULL;
262 }
263
264 ret->ber_len = CBS_len(©2) - CBS_len(cbs);
265 ret->ber_bytes = OPENSSL_memdup(CBS_data(©2), ret->ber_len);
266 if (ret->ber_bytes == NULL) {
267 goto err;
268 }
269
270 return ret;
271
272 err:
273 PKCS7_free(ret);
274 return NULL;
275 }
276
d2i_PKCS7(PKCS7 ** out,const uint8_t ** inp,size_t len)277 PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp,
278 size_t len) {
279 CBS cbs;
280 CBS_init(&cbs, *inp, len);
281 PKCS7 *ret = pkcs7_new(&cbs);
282 if (ret == NULL) {
283 return NULL;
284 }
285 *inp = CBS_data(&cbs);
286 if (out != NULL) {
287 PKCS7_free(*out);
288 *out = ret;
289 }
290 return ret;
291 }
292
d2i_PKCS7_bio(BIO * bio,PKCS7 ** out)293 PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out) {
294 // Use a generous bound, to allow for PKCS#7 files containing large root sets.
295 static const size_t kMaxSize = 4 * 1024 * 1024;
296 uint8_t *data;
297 size_t len;
298 if (!BIO_read_asn1(bio, &data, &len, kMaxSize)) {
299 return NULL;
300 }
301
302 CBS cbs;
303 CBS_init(&cbs, data, len);
304 PKCS7 *ret = pkcs7_new(&cbs);
305 OPENSSL_free(data);
306 if (out != NULL && ret != NULL) {
307 PKCS7_free(*out);
308 *out = ret;
309 }
310 return ret;
311 }
312
i2d_PKCS7(const PKCS7 * p7,uint8_t ** out)313 int i2d_PKCS7(const PKCS7 *p7, uint8_t **out) {
314 if (p7->ber_len > INT_MAX) {
315 OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
316 return -1;
317 }
318
319 if (out == NULL) {
320 return (int)p7->ber_len;
321 }
322
323 if (*out == NULL) {
324 *out = OPENSSL_malloc(p7->ber_len);
325 if (*out == NULL) {
326 OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
327 return -1;
328 }
329 OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
330 } else {
331 OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
332 *out += p7->ber_len;
333 }
334 return (int)p7->ber_len;
335 }
336
i2d_PKCS7_bio(BIO * bio,const PKCS7 * p7)337 int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) {
338 return BIO_write_all(bio, p7->ber_bytes, p7->ber_len);
339 }
340
PKCS7_free(PKCS7 * p7)341 void PKCS7_free(PKCS7 *p7) {
342 if (p7 == NULL) {
343 return;
344 }
345
346 OPENSSL_free(p7->ber_bytes);
347 ASN1_OBJECT_free(p7->type);
348 // We only supported signed data.
349 if (p7->d.sign != NULL) {
350 sk_X509_pop_free(p7->d.sign->cert, X509_free);
351 sk_X509_CRL_pop_free(p7->d.sign->crl, X509_CRL_free);
352 OPENSSL_free(p7->d.sign);
353 }
354 OPENSSL_free(p7);
355 }
356
357 // We only support signed data, so these getters are no-ops.
PKCS7_type_is_data(const PKCS7 * p7)358 int PKCS7_type_is_data(const PKCS7 *p7) { return 0; }
PKCS7_type_is_digest(const PKCS7 * p7)359 int PKCS7_type_is_digest(const PKCS7 *p7) { return 0; }
PKCS7_type_is_encrypted(const PKCS7 * p7)360 int PKCS7_type_is_encrypted(const PKCS7 *p7) { return 0; }
PKCS7_type_is_enveloped(const PKCS7 * p7)361 int PKCS7_type_is_enveloped(const PKCS7 *p7) { return 0; }
PKCS7_type_is_signed(const PKCS7 * p7)362 int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; }
PKCS7_type_is_signedAndEnveloped(const PKCS7 * p7)363 int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; }
364
PKCS7_sign(X509 * sign_cert,EVP_PKEY * pkey,STACK_OF (X509)* certs,BIO * data,int flags)365 PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
366 BIO *data, int flags) {
367 if (sign_cert != NULL || pkey != NULL || flags != PKCS7_DETACHED) {
368 OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
369 return NULL;
370 }
371
372 uint8_t *der;
373 size_t len;
374 CBB cbb;
375 if (!CBB_init(&cbb, 2048) ||
376 !PKCS7_bundle_certificates(&cbb, certs) ||
377 !CBB_finish(&cbb, &der, &len)) {
378 CBB_cleanup(&cbb);
379 return NULL;
380 }
381
382 CBS cbs;
383 CBS_init(&cbs, der, len);
384 PKCS7 *ret = pkcs7_new(&cbs);
385 OPENSSL_free(der);
386 return ret;
387 }
388