• 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 
30 
PKCS7_get_certificates(STACK_OF (X509)* out_certs,CBS * cbs)31 int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
32   int ret = 0;
33   const size_t initial_certs_len = sk_X509_num(out_certs);
34   STACK_OF(CRYPTO_BUFFER) *raw = sk_CRYPTO_BUFFER_new_null();
35   if (raw == NULL ||
36       !PKCS7_get_raw_certificates(raw, cbs, NULL)) {
37     goto err;
38   }
39 
40   for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(raw); i++) {
41     CRYPTO_BUFFER *buf = sk_CRYPTO_BUFFER_value(raw, i);
42     X509 *x509 = X509_parse_from_buffer(buf);
43     if (x509 == NULL ||
44         !sk_X509_push(out_certs, x509)) {
45       X509_free(x509);
46       goto err;
47     }
48   }
49 
50   ret = 1;
51 
52 err:
53   sk_CRYPTO_BUFFER_pop_free(raw, CRYPTO_BUFFER_free);
54   if (!ret) {
55     while (sk_X509_num(out_certs) != initial_certs_len) {
56       X509 *x509 = sk_X509_pop(out_certs);
57       X509_free(x509);
58     }
59   }
60 
61   return ret;
62 }
63 
PKCS7_get_CRLs(STACK_OF (X509_CRL)* out_crls,CBS * cbs)64 int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
65   CBS signed_data, crls;
66   uint8_t *der_bytes = NULL;
67   int ret = 0;
68   const size_t initial_crls_len = sk_X509_CRL_num(out_crls);
69 
70   if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) {
71     return 0;
72   }
73 
74   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
75 
76   /* Even if only CRLs are included, there may be an empty certificates block.
77    * OpenSSL does this, for example. */
78   if (CBS_peek_asn1_tag(&signed_data,
79                         CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) &&
80       !CBS_get_asn1(&signed_data, NULL /* certificates */,
81                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
82     goto err;
83   }
84 
85   if (!CBS_get_asn1(&signed_data, &crls,
86                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
87     OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_CRLS_INCLUDED);
88     goto err;
89   }
90 
91   while (CBS_len(&crls) > 0) {
92     CBS crl_data;
93     X509_CRL *crl;
94     const uint8_t *inp;
95 
96     if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) {
97       goto err;
98     }
99 
100     if (CBS_len(&crl_data) > LONG_MAX) {
101       goto err;
102     }
103     inp = CBS_data(&crl_data);
104     crl = d2i_X509_CRL(NULL, &inp, (long)CBS_len(&crl_data));
105     if (!crl) {
106       goto err;
107     }
108 
109     assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data));
110 
111     if (sk_X509_CRL_push(out_crls, crl) == 0) {
112       X509_CRL_free(crl);
113       goto err;
114     }
115   }
116 
117   ret = 1;
118 
119 err:
120   OPENSSL_free(der_bytes);
121 
122   if (!ret) {
123     while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
124       X509_CRL_free(sk_X509_CRL_pop(out_crls));
125     }
126   }
127 
128   return ret;
129 }
130 
PKCS7_get_PEM_certificates(STACK_OF (X509)* out_certs,BIO * pem_bio)131 int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) {
132   uint8_t *data;
133   long len;
134   int ret;
135 
136   /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
137    * internally will actually allow several other values too, including
138    * "CERTIFICATE". */
139   if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
140                           PEM_STRING_PKCS7, pem_bio,
141                           NULL /* password callback */,
142                           NULL /* password callback argument */)) {
143     return 0;
144   }
145 
146   CBS cbs;
147   CBS_init(&cbs, data, len);
148   ret = PKCS7_get_certificates(out_certs, &cbs);
149   OPENSSL_free(data);
150   return ret;
151 }
152 
PKCS7_get_PEM_CRLs(STACK_OF (X509_CRL)* out_crls,BIO * pem_bio)153 int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
154   uint8_t *data;
155   long len;
156   int ret;
157 
158   /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
159    * internally will actually allow several other values too, including
160    * "CERTIFICATE". */
161   if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
162                           PEM_STRING_PKCS7, pem_bio,
163                           NULL /* password callback */,
164                           NULL /* password callback argument */)) {
165     return 0;
166   }
167 
168   CBS cbs;
169   CBS_init(&cbs, data, len);
170   ret = PKCS7_get_CRLs(out_crls, &cbs);
171   OPENSSL_free(data);
172   return ret;
173 }
174 
pkcs7_bundle_certificates_cb(CBB * out,const void * arg)175 static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) {
176   const STACK_OF(X509) *certs = arg;
177   size_t i;
178   CBB certificates;
179 
180   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
181   if (!CBB_add_asn1(out, &certificates,
182                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
183     return 0;
184   }
185 
186   for (i = 0; i < sk_X509_num(certs); i++) {
187     X509 *x509 = sk_X509_value(certs, i);
188     uint8_t *buf;
189     int len = i2d_X509(x509, NULL);
190 
191     if (len < 0 ||
192         !CBB_add_space(&certificates, &buf, len) ||
193         i2d_X509(x509, &buf) < 0) {
194       return 0;
195     }
196   }
197 
198   return CBB_flush(out);
199 }
200 
PKCS7_bundle_certificates(CBB * out,const STACK_OF (X509)* certs)201 int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
202   return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs);
203 }
204 
pkcs7_bundle_crls_cb(CBB * out,const void * arg)205 static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
206   const STACK_OF(X509_CRL) *crls = arg;
207   size_t i;
208   CBB crl_data;
209 
210   /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
211   if (!CBB_add_asn1(out, &crl_data,
212                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
213     return 0;
214   }
215 
216   for (i = 0; i < sk_X509_CRL_num(crls); i++) {
217     X509_CRL *crl = sk_X509_CRL_value(crls, i);
218     uint8_t *buf;
219     int len = i2d_X509_CRL(crl, NULL);
220 
221     if (len < 0 ||
222         !CBB_add_space(&crl_data, &buf, len) ||
223         i2d_X509_CRL(crl, &buf) < 0) {
224       return 0;
225     }
226   }
227 
228   return CBB_flush(out);
229 }
230 
PKCS7_bundle_CRLs(CBB * out,const STACK_OF (X509_CRL)* crls)231 int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
232   return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
233 }
234