1 /* Copyright (c) 2014, 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/x509.h>
16
17 #include <assert.h>
18
19 #include <openssl/bytestring.h>
20 #include <openssl/err.h>
21 #include <openssl/mem.h>
22 #include <openssl/obj.h>
23 #include <openssl/pem.h>
24 #include <openssl/stack.h>
25
26 #include "../bytestring/internal.h"
27
28
29 /* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7
30 * SignedData blob from |cbs| and sets |*out| to point to the rest of the
31 * input. If the input is in BER format, then |*der_bytes| will be set to a
32 * pointer that needs to be freed by the caller once they have finished
33 * processing |*out| (which will be pointing into |*der_bytes|).
34 *
35 * It returns one on success or zero on error. On error, |*der_bytes| is
36 * NULL. */
pkcs7_parse_header(uint8_t ** der_bytes,CBS * out,CBS * cbs)37 static int pkcs7_parse_header(uint8_t **der_bytes, CBS *out, CBS *cbs) {
38 size_t der_len;
39 CBS in, content_info, content_type, wrapped_signed_data, signed_data;
40 uint64_t version;
41
42 /* The input may be in BER format. */
43 *der_bytes = NULL;
44 if (!CBS_asn1_ber_to_der(cbs, der_bytes, &der_len)) {
45 return 0;
46 }
47 if (*der_bytes != NULL) {
48 CBS_init(&in, *der_bytes, der_len);
49 } else {
50 CBS_init(&in, CBS_data(cbs), CBS_len(cbs));
51 }
52
53 /* See https://tools.ietf.org/html/rfc2315#section-7 */
54 if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
55 !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {
56 goto err;
57 }
58
59 if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
60 OPENSSL_PUT_ERROR(X509, pkcs7_parse_header,
61 X509_R_NOT_PKCS7_SIGNED_DATA);
62 goto err;
63 }
64
65 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
66 if (!CBS_get_asn1(&content_info, &wrapped_signed_data,
67 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
68 !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) ||
69 !CBS_get_asn1_uint64(&signed_data, &version) ||
70 !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
71 !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
72 goto err;
73 }
74
75 if (version < 1) {
76 OPENSSL_PUT_ERROR(X509, pkcs7_parse_header,
77 X509_R_BAD_PKCS7_VERSION);
78 goto err;
79 }
80
81 CBS_init(out, CBS_data(&signed_data), CBS_len(&signed_data));
82 return 1;
83
84 err:
85 if (*der_bytes) {
86 OPENSSL_free(*der_bytes);
87 *der_bytes = NULL;
88 }
89
90 return 0;
91 }
92
PKCS7_get_certificates(STACK_OF (X509)* out_certs,CBS * cbs)93 int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
94 CBS signed_data, certificates;
95 uint8_t *der_bytes = NULL;
96 int ret = 0;
97 const size_t initial_certs_len = sk_X509_num(out_certs);
98
99 if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) {
100 return 0;
101 }
102
103 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
104 if (!CBS_get_asn1(&signed_data, &certificates,
105 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
106 OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
107 X509_R_NO_CERTIFICATES_INCLUDED);
108 goto err;
109 }
110
111 while (CBS_len(&certificates) > 0) {
112 CBS cert;
113 X509 *x509;
114 const uint8_t *inp;
115
116 if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) {
117 goto err;
118 }
119
120 inp = CBS_data(&cert);
121 x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
122 if (!x509) {
123 goto err;
124 }
125
126 assert(inp == CBS_data(&cert) + CBS_len(&cert));
127
128 if (sk_X509_push(out_certs, x509) == 0) {
129 X509_free(x509);
130 goto err;
131 }
132 }
133
134 ret = 1;
135
136 err:
137 if (der_bytes) {
138 OPENSSL_free(der_bytes);
139 }
140
141 if (!ret) {
142 while (sk_X509_num(out_certs) != initial_certs_len) {
143 X509 *x509 = sk_X509_pop(out_certs);
144 X509_free(x509);
145 }
146 }
147
148 return ret;
149 }
150
PKCS7_get_CRLs(STACK_OF (X509_CRL)* out_crls,CBS * cbs)151 int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
152 CBS signed_data, crls;
153 uint8_t *der_bytes = NULL;
154 int ret = 0;
155 const size_t initial_crls_len = sk_X509_CRL_num(out_crls);
156
157 if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) {
158 return 0;
159 }
160
161 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
162
163 /* Even if only CRLs are included, there may be an empty certificates block.
164 * OpenSSL does this, for example. */
165 if (CBS_peek_asn1_tag(&signed_data,
166 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) &&
167 !CBS_get_asn1(&signed_data, NULL /* certificates */,
168 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
169 goto err;
170 }
171
172 if (!CBS_get_asn1(&signed_data, &crls,
173 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
174 OPENSSL_PUT_ERROR(X509, PKCS7_get_CRLs,
175 X509_R_NO_CRLS_INCLUDED);
176 goto err;
177 }
178
179 while (CBS_len(&crls) > 0) {
180 CBS crl_data;
181 X509_CRL *crl;
182 const uint8_t *inp;
183
184 if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) {
185 goto err;
186 }
187
188 inp = CBS_data(&crl_data);
189 crl = d2i_X509_CRL(NULL, &inp, CBS_len(&crl_data));
190 if (!crl) {
191 goto err;
192 }
193
194 assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data));
195
196 if (sk_X509_CRL_push(out_crls, crl) == 0) {
197 X509_CRL_free(crl);
198 goto err;
199 }
200 }
201
202 ret = 1;
203
204 err:
205 if (der_bytes) {
206 OPENSSL_free(der_bytes);
207 }
208
209 if (!ret) {
210 while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
211 X509_CRL_free(sk_X509_CRL_pop(out_crls));
212 }
213 }
214
215 return ret;
216 }
217
PKCS7_get_PEM_certificates(STACK_OF (X509)* out_certs,BIO * pem_bio)218 int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) {
219 uint8_t *data;
220 long len;
221 int ret;
222
223 /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
224 * internally will actually allow several other values too, including
225 * "CERTIFICATE". */
226 if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
227 PEM_STRING_PKCS7, pem_bio,
228 NULL /* password callback */,
229 NULL /* password callback argument */)) {
230 return 0;
231 }
232
233 CBS cbs;
234 CBS_init(&cbs, data, len);
235 ret = PKCS7_get_certificates(out_certs, &cbs);
236 OPENSSL_free(data);
237 return ret;
238 }
239
PKCS7_get_PEM_CRLs(STACK_OF (X509_CRL)* out_crls,BIO * pem_bio)240 int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
241 uint8_t *data;
242 long len;
243 int ret;
244
245 /* Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
246 * internally will actually allow several other values too, including
247 * "CERTIFICATE". */
248 if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
249 PEM_STRING_PKCS7, pem_bio,
250 NULL /* password callback */,
251 NULL /* password callback argument */)) {
252 return 0;
253 }
254
255 CBS cbs;
256 CBS_init(&cbs, data, len);
257 ret = PKCS7_get_CRLs(out_crls, &cbs);
258 OPENSSL_free(data);
259 return ret;
260 }
261
262 /* pkcs7_bundle writes a PKCS#7, SignedData structure to |out| and then calls
263 * |cb| with a CBB to which certificate or CRL data can be written, and the
264 * opaque context pointer, |arg|. The callback can return zero to indicate an
265 * error.
266 *
267 * pkcs7_bundle returns one on success or zero on error. */
pkcs7_bundle(CBB * out,int (* cb)(CBB * out,const void * arg),const void * arg)268 static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
269 const void *arg) {
270 CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set,
271 content_info;
272
273 /* See https://tools.ietf.org/html/rfc2315#section-7 */
274 if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
275 !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
276 !CBB_add_asn1(&outer_seq, &wrapped_seq,
277 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
278 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
279 !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
280 !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) ||
281 !CBB_add_u8(&version_bytes, 1) ||
282 !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
283 !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
284 !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
285 !cb(&seq, arg)) {
286 return 0;
287 }
288
289 return CBB_flush(out);
290 }
291
pkcs7_bundle_certificates_cb(CBB * out,const void * arg)292 static int pkcs7_bundle_certificates_cb(CBB *out, const void *arg) {
293 const STACK_OF(X509) *certs = arg;
294 size_t i;
295 CBB certificates;
296
297 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
298 if (!CBB_add_asn1(out, &certificates,
299 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
300 return 0;
301 }
302
303 for (i = 0; i < sk_X509_num(certs); i++) {
304 X509 *x509 = sk_X509_value(certs, i);
305 uint8_t *buf;
306 int len = i2d_X509(x509, NULL);
307
308 if (len < 0 ||
309 !CBB_add_space(&certificates, &buf, len) ||
310 i2d_X509(x509, &buf) < 0) {
311 return 0;
312 }
313 }
314
315 return CBB_flush(out);
316 }
317
PKCS7_bundle_certificates(CBB * out,const STACK_OF (X509)* certs)318 int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
319 return pkcs7_bundle(out, pkcs7_bundle_certificates_cb, certs);
320 }
321
pkcs7_bundle_crls_cb(CBB * out,const void * arg)322 static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) {
323 const STACK_OF(X509_CRL) *crls = arg;
324 size_t i;
325 CBB crl_data;
326
327 /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
328 if (!CBB_add_asn1(out, &crl_data,
329 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
330 return 0;
331 }
332
333 for (i = 0; i < sk_X509_CRL_num(crls); i++) {
334 X509_CRL *crl = sk_X509_CRL_value(crls, i);
335 uint8_t *buf;
336 int len = i2d_X509_CRL(crl, NULL);
337
338 if (len < 0 ||
339 !CBB_add_space(&crl_data, &buf, len) ||
340 i2d_X509_CRL(crl, &buf) < 0) {
341 return 0;
342 }
343 }
344
345 return CBB_flush(out);
346 }
347
PKCS7_bundle_CRLs(CBB * out,const STACK_OF (X509_CRL)* crls)348 int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
349 return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls);
350 }
351