• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   return CBB_flush(out);
196 }
197 
PKCS7_bundle_certificates(CBB * out,const STACK_OF (X509)* certs)198 int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
199   return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs);
200 }
201 
pkcs7_bundle_crls_cb(CBB * out,const void * arg)202 static 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 
PKCS7_bundle_CRLs(CBB * out,const STACK_OF (X509_CRL)* crls)228 int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
229   return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
230 }
231 
pkcs7_new(CBS * cbs)232 static 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 
270 err:
271   PKCS7_free(ret);
272   return NULL;
273 }
274 
d2i_PKCS7(PKCS7 ** out,const uint8_t ** inp,size_t len)275 PKCS7 *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 
d2i_PKCS7_bio(BIO * bio,PKCS7 ** out)291 PKCS7 *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 
i2d_PKCS7(const PKCS7 * p7,uint8_t ** out)311 int 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 
i2d_PKCS7_bio(BIO * bio,const PKCS7 * p7)335 int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) {
336   return BIO_write_all(bio, p7->ber_bytes, p7->ber_len);
337 }
338 
PKCS7_free(PKCS7 * p7)339 void 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.
PKCS7_type_is_data(const PKCS7 * p7)356 int PKCS7_type_is_data(const PKCS7 *p7) { return 0; }
PKCS7_type_is_digest(const PKCS7 * p7)357 int PKCS7_type_is_digest(const PKCS7 *p7) { return 0; }
PKCS7_type_is_encrypted(const PKCS7 * p7)358 int PKCS7_type_is_encrypted(const PKCS7 *p7) { return 0; }
PKCS7_type_is_enveloped(const PKCS7 * p7)359 int PKCS7_type_is_enveloped(const PKCS7 *p7) { return 0; }
PKCS7_type_is_signed(const PKCS7 * p7)360 int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; }
PKCS7_type_is_signedAndEnveloped(const PKCS7 * p7)361 int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; }
362 
PKCS7_sign(X509 * sign_cert,EVP_PKEY * pkey,STACK_OF (X509)* certs,BIO * data,int flags)363 PKCS7 *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