1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57 #include <openssl/asn1.h>
58 #include <openssl/asn1t.h>
59 #include <openssl/digest.h>
60 #include <openssl/err.h>
61 #include <openssl/mem.h>
62 #include <openssl/obj.h>
63 #include <openssl/stack.h>
64 #include <openssl/thread.h>
65 #include <openssl/x509.h>
66 #include <openssl/x509v3.h>
67
68 #include <assert.h>
69
70 #include "../asn1/internal.h"
71 #include "../internal.h"
72 #include "internal.h"
73
74 static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
75 const X509_REVOKED *const *b);
76 static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
77
78 ASN1_SEQUENCE(X509_REVOKED) = {
79 ASN1_SIMPLE(X509_REVOKED, serialNumber, ASN1_INTEGER),
80 ASN1_SIMPLE(X509_REVOKED, revocationDate, ASN1_TIME),
81 ASN1_SEQUENCE_OF_OPT(X509_REVOKED, extensions, X509_EXTENSION),
82 } ASN1_SEQUENCE_END(X509_REVOKED)
83
84 static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
85 const ASN1_INTEGER *serial, X509_NAME *issuer);
86
87 // The X509_CRL_INFO structure needs a bit of customisation. Since we cache
88 // the original encoding the signature wont be affected by reordering of the
89 // revoked field.
crl_inf_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)90 static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
91 void *exarg) {
92 X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
93
94 if (!a || !a->revoked) {
95 return 1;
96 }
97 switch (operation) {
98 // Just set cmp function here. We don't sort because that would
99 // affect the output of X509_CRL_print().
100 case ASN1_OP_D2I_POST:
101 (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
102 break;
103 }
104 return 1;
105 }
106
107
108 ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
109 ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
110 ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
111 ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
112 ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
113 ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
114 ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
115 ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0),
116 } ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
117
118 // Set CRL entry issuer according to CRL certificate issuer extension. Check
119 // for unhandled critical CRL entry extensions.
120
121 static int crl_set_issuers(X509_CRL *crl) {
122 size_t i, k;
123 int j;
124 GENERAL_NAMES *gens, *gtmp;
125 STACK_OF(X509_REVOKED) *revoked;
126
127 revoked = X509_CRL_get_REVOKED(crl);
128
129 gens = NULL;
130 for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
131 X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
132 STACK_OF(X509_EXTENSION) *exts;
133 ASN1_ENUMERATED *reason;
134 X509_EXTENSION *ext;
135 gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer, &j, NULL);
136 if (!gtmp && (j != -1)) {
137 crl->flags |= EXFLAG_INVALID;
138 return 1;
139 }
140
141 if (gtmp) {
142 gens = gtmp;
143 if (!crl->issuers) {
144 crl->issuers = sk_GENERAL_NAMES_new_null();
145 if (!crl->issuers) {
146 return 0;
147 }
148 }
149 if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) {
150 return 0;
151 }
152 }
153 rev->issuer = gens;
154
155 reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL);
156 if (!reason && (j != -1)) {
157 crl->flags |= EXFLAG_INVALID;
158 return 1;
159 }
160
161 if (reason) {
162 rev->reason = ASN1_ENUMERATED_get(reason);
163 ASN1_ENUMERATED_free(reason);
164 } else {
165 rev->reason = CRL_REASON_NONE;
166 }
167
168 // Check for critical CRL entry extensions
169
170 exts = rev->extensions;
171
172 for (k = 0; k < sk_X509_EXTENSION_num(exts); k++) {
173 ext = sk_X509_EXTENSION_value(exts, k);
174 if (X509_EXTENSION_get_critical(ext)) {
175 if (OBJ_obj2nid(X509_EXTENSION_get_object(ext)) ==
176 NID_certificate_issuer) {
177 continue;
178 }
179 crl->flags |= EXFLAG_CRITICAL;
180 break;
181 }
182 }
183 }
184
185 return 1;
186 }
187
188 // The X509_CRL structure needs a bit of customisation. Cache some extensions
189 // and hash of the whole CRL.
crl_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)190 static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
191 void *exarg) {
192 X509_CRL *crl = (X509_CRL *)*pval;
193 STACK_OF(X509_EXTENSION) *exts;
194 X509_EXTENSION *ext;
195 size_t idx;
196 int i;
197
198 switch (operation) {
199 case ASN1_OP_NEW_POST:
200 crl->idp = NULL;
201 crl->akid = NULL;
202 crl->flags = 0;
203 crl->idp_flags = 0;
204 crl->idp_reasons = CRLDP_ALL_REASONS;
205 crl->issuers = NULL;
206 crl->crl_number = NULL;
207 crl->base_crl_number = NULL;
208 break;
209
210 case ASN1_OP_D2I_POST: {
211 // The version must be one of v1(0) or v2(1).
212 long version = X509_CRL_VERSION_1;
213 if (crl->crl->version != NULL) {
214 version = ASN1_INTEGER_get(crl->crl->version);
215 // TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1|
216 // should also be rejected. This means an explicitly-encoded X.509v1
217 // version. v1 is DEFAULT, so DER requires it be omitted.
218 if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) {
219 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
220 return 0;
221 }
222 }
223
224 // Per RFC 5280, section 5.1.2.1, extensions require v2.
225 if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) {
226 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
227 return 0;
228 }
229
230 if (!X509_CRL_digest(crl, EVP_sha256(), crl->crl_hash, NULL)) {
231 return 0;
232 }
233
234 crl->idp =
235 X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, &i, NULL);
236 if (crl->idp != NULL) {
237 if (!setup_idp(crl, crl->idp)) {
238 return 0;
239 }
240 } else if (i != -1) {
241 return 0;
242 }
243
244 crl->akid =
245 X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, &i, NULL);
246 if (crl->akid == NULL && i != -1) {
247 return 0;
248 }
249
250 crl->crl_number = X509_CRL_get_ext_d2i(crl, NID_crl_number, &i, NULL);
251 if (crl->crl_number == NULL && i != -1) {
252 return 0;
253 }
254
255 crl->base_crl_number = X509_CRL_get_ext_d2i(crl, NID_delta_crl, &i, NULL);
256 if (crl->base_crl_number == NULL && i != -1) {
257 return 0;
258 }
259 // Delta CRLs must have CRL number
260 if (crl->base_crl_number && !crl->crl_number) {
261 OPENSSL_PUT_ERROR(X509, X509_R_DELTA_CRL_WITHOUT_CRL_NUMBER);
262 return 0;
263 }
264
265 // See if we have any unhandled critical CRL extensions and indicate
266 // this in a flag. We only currently handle IDP so anything else
267 // critical sets the flag. This code accesses the X509_CRL structure
268 // directly: applications shouldn't do this.
269
270 exts = crl->crl->extensions;
271
272 for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
273 int nid;
274 ext = sk_X509_EXTENSION_value(exts, idx);
275 nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
276 if (nid == NID_freshest_crl) {
277 crl->flags |= EXFLAG_FRESHEST;
278 }
279 if (X509_EXTENSION_get_critical(ext)) {
280 // We handle IDP and deltas
281 if ((nid == NID_issuing_distribution_point) ||
282 (nid == NID_authority_key_identifier) || (nid == NID_delta_crl)) {
283 continue;
284 }
285 crl->flags |= EXFLAG_CRITICAL;
286 break;
287 }
288 }
289
290 if (!crl_set_issuers(crl)) {
291 return 0;
292 }
293
294 break;
295 }
296
297 case ASN1_OP_FREE_POST:
298 AUTHORITY_KEYID_free(crl->akid);
299 ISSUING_DIST_POINT_free(crl->idp);
300 ASN1_INTEGER_free(crl->crl_number);
301 ASN1_INTEGER_free(crl->base_crl_number);
302 sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
303 break;
304 }
305 return 1;
306 }
307
308 // Convert IDP into a more convenient form
309
setup_idp(X509_CRL * crl,ISSUING_DIST_POINT * idp)310 static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) {
311 int idp_only = 0;
312 // Set various flags according to IDP
313 crl->idp_flags |= IDP_PRESENT;
314 if (idp->onlyuser > 0) {
315 idp_only++;
316 crl->idp_flags |= IDP_ONLYUSER;
317 }
318 if (idp->onlyCA > 0) {
319 idp_only++;
320 crl->idp_flags |= IDP_ONLYCA;
321 }
322 if (idp->onlyattr > 0) {
323 idp_only++;
324 crl->idp_flags |= IDP_ONLYATTR;
325 }
326
327 if (idp_only > 1) {
328 crl->idp_flags |= IDP_INVALID;
329 }
330
331 if (idp->indirectCRL > 0) {
332 crl->idp_flags |= IDP_INDIRECT;
333 }
334
335 if (idp->onlysomereasons) {
336 crl->idp_flags |= IDP_REASONS;
337 if (idp->onlysomereasons->length > 0) {
338 crl->idp_reasons = idp->onlysomereasons->data[0];
339 }
340 if (idp->onlysomereasons->length > 1) {
341 crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8);
342 }
343 crl->idp_reasons &= CRLDP_ALL_REASONS;
344 }
345
346 return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
347 }
348
349 ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
350 ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
351 ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
352 ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING),
353 } ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
354
355 // Although |X509_REVOKED| contains an |X509_NAME|, it can be const. It is not
356 // affected by https://crbug.com/boringssl/407 because the |X509_NAME| does
357 // not participate in serialization.
358 IMPLEMENT_ASN1_FUNCTIONS_const(X509_REVOKED)
359 IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_REVOKED)
360
361 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
362 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
363 IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
364
365 static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
366 const X509_REVOKED *const *b) {
367 return ASN1_STRING_cmp((*a)->serialNumber, (*b)->serialNumber);
368 }
369
X509_CRL_add0_revoked(X509_CRL * crl,X509_REVOKED * rev)370 int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) {
371 X509_CRL_INFO *inf;
372 inf = crl->crl;
373 if (!inf->revoked) {
374 inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
375 }
376 if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
377 return 0;
378 }
379 asn1_encoding_clear(&inf->enc);
380 return 1;
381 }
382
X509_CRL_verify(X509_CRL * crl,EVP_PKEY * pkey)383 int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey) {
384 if (X509_ALGOR_cmp(crl->sig_alg, crl->crl->sig_alg) != 0) {
385 OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH);
386 return 0;
387 }
388
389 return ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), crl->sig_alg,
390 crl->signature, crl->crl, pkey);
391 }
392
X509_CRL_get0_by_serial(X509_CRL * crl,X509_REVOKED ** ret,const ASN1_INTEGER * serial)393 int X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
394 const ASN1_INTEGER *serial) {
395 return crl_lookup(crl, ret, serial, NULL);
396 }
397
X509_CRL_get0_by_cert(X509_CRL * crl,X509_REVOKED ** ret,X509 * x)398 int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) {
399 return crl_lookup(crl, ret, X509_get_serialNumber(x),
400 X509_get_issuer_name(x));
401 }
402
crl_revoked_issuer_match(X509_CRL * crl,X509_NAME * nm,X509_REVOKED * rev)403 static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
404 X509_REVOKED *rev) {
405 size_t i;
406
407 if (!rev->issuer) {
408 if (!nm) {
409 return 1;
410 }
411 if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl))) {
412 return 1;
413 }
414 return 0;
415 }
416
417 if (!nm) {
418 nm = X509_CRL_get_issuer(crl);
419 }
420
421 for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
422 GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
423 if (gen->type != GEN_DIRNAME) {
424 continue;
425 }
426 if (!X509_NAME_cmp(nm, gen->d.directoryName)) {
427 return 1;
428 }
429 }
430 return 0;
431 }
432
433 static CRYPTO_MUTEX g_crl_sort_lock = CRYPTO_MUTEX_INIT;
434
crl_lookup(X509_CRL * crl,X509_REVOKED ** ret,const ASN1_INTEGER * serial,X509_NAME * issuer)435 static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
436 const ASN1_INTEGER *serial, X509_NAME *issuer) {
437 // Use an assert, rather than a runtime error, because returning nothing for a
438 // CRL is arguably failing open, rather than closed.
439 assert(serial->type == V_ASN1_INTEGER || serial->type == V_ASN1_NEG_INTEGER);
440 X509_REVOKED rtmp, *rev;
441 size_t idx;
442 rtmp.serialNumber = (ASN1_INTEGER *)serial;
443 // Sort revoked into serial number order if not already sorted. Do this
444 // under a lock to avoid race condition.
445
446 CRYPTO_MUTEX_lock_read(&g_crl_sort_lock);
447 const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
448 CRYPTO_MUTEX_unlock_read(&g_crl_sort_lock);
449
450 if (!is_sorted) {
451 CRYPTO_MUTEX_lock_write(&g_crl_sort_lock);
452 if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
453 sk_X509_REVOKED_sort(crl->crl->revoked);
454 }
455 CRYPTO_MUTEX_unlock_write(&g_crl_sort_lock);
456 }
457
458 if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) {
459 return 0;
460 }
461 // Need to look for matching name
462 for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
463 rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
464 if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) {
465 return 0;
466 }
467 if (crl_revoked_issuer_match(crl, issuer, rev)) {
468 if (ret) {
469 *ret = rev;
470 }
471 if (rev->reason == CRL_REASON_REMOVE_FROM_CRL) {
472 return 2;
473 }
474 return 1;
475 }
476 }
477 return 0;
478 }
479