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
32int 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
53err:
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
65int 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
116err:
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
128int 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
150int 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
172static 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 return CBB_flush(out);
196}
197
198int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
199 return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs);
200}
201
202static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
203 const STACK_OF(X509_CRL) *crls = arg;
204 size_t i;
205 CBB crl_data;
206
207 // See https://tools.ietf.org/html/rfc2315#section-9.1
208 if (!CBB_add_asn1(out, &crl_data,
209 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
210 return 0;
211 }
212
213 for (i = 0; i < sk_X509_CRL_num(crls); i++) {
214 X509_CRL *crl = sk_X509_CRL_value(crls, i);
215 uint8_t *buf;
216 int len = i2d_X509_CRL(crl, NULL);
217
218 if (len < 0 ||
219 !CBB_add_space(&crl_data, &buf, len) ||
220 i2d_X509_CRL(crl, &buf) < 0) {
221 return 0;
222 }
223 }
224
225 return CBB_flush(out);
226}
227
228int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
229 return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
230}
231
232static PKCS7 *pkcs7_new(CBS *cbs) {
233 PKCS7 *ret = OPENSSL_malloc(sizeof(PKCS7));
234 if (ret == NULL) {
235 return NULL;
236 }
237 OPENSSL_memset(ret, 0, sizeof(PKCS7));
238 ret->type = (ASN1_OBJECT *)OBJ_nid2obj(NID_pkcs7_signed);
239 ret->d.sign = OPENSSL_malloc(sizeof(PKCS7_SIGNED));
240 if (ret->d.sign == NULL) {
241 goto err;
242 }
243 ret->d.sign->cert = sk_X509_new_null();
244 ret->d.sign->crl = sk_X509_CRL_new_null();
245 CBS copy = *cbs, copy2 = *cbs;
246 if (ret->d.sign->cert == NULL || ret->d.sign->crl == NULL ||
247 !PKCS7_get_certificates(ret->d.sign->cert, &copy) ||
248 !PKCS7_get_CRLs(ret->d.sign->crl, cbs)) {
249 goto err;
250 }
251
252 if (sk_X509_num(ret->d.sign->cert) == 0) {
253 sk_X509_free(ret->d.sign->cert);
254 ret->d.sign->cert = NULL;
255 }
256
257 if (sk_X509_CRL_num(ret->d.sign->crl) == 0) {
258 sk_X509_CRL_free(ret->d.sign->crl);
259 ret->d.sign->crl = NULL;
260 }
261
262 ret->ber_len = CBS_len(&copy2) - CBS_len(cbs);
263 ret->ber_bytes = BUF_memdup(CBS_data(&copy2), ret->ber_len);
264 if (ret->ber_bytes == NULL) {
265 goto err;
266 }
267
268 return ret;
269
270err:
271 PKCS7_free(ret);
272 return NULL;
273}
274
275PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp,
276 size_t len) {
277 CBS cbs;
278 CBS_init(&cbs, *inp, len);
279 PKCS7 *ret = pkcs7_new(&cbs);
280 if (ret == NULL) {
281 return NULL;
282 }
283 *inp = CBS_data(&cbs);
284 if (out != NULL) {
285 PKCS7_free(*out);
286 *out = ret;
287 }
288 return ret;
289}
290
291PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out) {
292 // Use a generous bound, to allow for PKCS#7 files containing large root sets.
293 static const size_t kMaxSize = 4 * 1024 * 1024;
294 uint8_t *data;
295 size_t len;
296 if (!BIO_read_asn1(bio, &data, &len, kMaxSize)) {
297 return NULL;
298 }
299
300 CBS cbs;
301 CBS_init(&cbs, data, len);
302 PKCS7 *ret = pkcs7_new(&cbs);
303 OPENSSL_free(data);
304 if (out != NULL && ret != NULL) {
305 PKCS7_free(*out);
306 *out = ret;
307 }
308 return ret;
309}
310
311int i2d_PKCS7(const PKCS7 *p7, uint8_t **out) {
312 if (p7->ber_len > INT_MAX) {
313 OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
314 return -1;
315 }
316
317 if (out == NULL) {
318 return (int)p7->ber_len;
319 }
320
321 if (*out == NULL) {
322 *out = OPENSSL_malloc(p7->ber_len);
323 if (*out == NULL) {
324 OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
325 return -1;
326 }
327 OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
328 } else {
329 OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
330 *out += p7->ber_len;
331 }
332 return (int)p7->ber_len;
333}
334
335int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) {
336 return BIO_write_all(bio, p7->ber_bytes, p7->ber_len);
337}
338
339void PKCS7_free(PKCS7 *p7) {
340 if (p7 == NULL) {
341 return;
342 }
343
344 OPENSSL_free(p7->ber_bytes);
345 ASN1_OBJECT_free(p7->type);
346 // We only supported signed data.
347 if (p7->d.sign != NULL) {
348 sk_X509_pop_free(p7->d.sign->cert, X509_free);
349 sk_X509_CRL_pop_free(p7->d.sign->crl, X509_CRL_free);
350 OPENSSL_free(p7->d.sign);
351 }
352 OPENSSL_free(p7);
353}
354
355// We only support signed data, so these getters are no-ops.
356int PKCS7_type_is_data(const PKCS7 *p7) { return 0; }
357int PKCS7_type_is_digest(const PKCS7 *p7) { return 0; }
358int PKCS7_type_is_encrypted(const PKCS7 *p7) { return 0; }
359int PKCS7_type_is_enveloped(const PKCS7 *p7) { return 0; }
360int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; }
361int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; }
362
363PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
364 BIO *data, int flags) {
365 if (sign_cert != NULL || pkey != NULL || flags != PKCS7_DETACHED) {
366 OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
367 return NULL;
368 }
369
370 uint8_t *der;
371 size_t len;
372 CBB cbb;
373 if (!CBB_init(&cbb, 2048) ||
374 !PKCS7_bundle_certificates(&cbb, certs) ||
375 !CBB_finish(&cbb, &der, &len)) {
376 CBB_cleanup(&cbb);
377 return NULL;
378 }
379
380 CBS cbs;
381 CBS_init(&cbs, der, len);
382 PKCS7 *ret = pkcs7_new(&cbs);
383 OPENSSL_free(der);
384 return ret;
385}
386