1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 static int crl_parse_entry_extensions(X509_CRL *crl) {
119 STACK_OF(X509_REVOKED) *revoked = X509_CRL_get_REVOKED(crl);
120 for (size_t i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
121 X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
122
123 int crit;
124 ASN1_ENUMERATED *reason =
125 X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &crit, NULL);
126 if (!reason && crit != -1) {
127 crl->flags |= EXFLAG_INVALID;
128 return 1;
129 }
130
131 if (reason) {
132 rev->reason = ASN1_ENUMERATED_get(reason);
133 ASN1_ENUMERATED_free(reason);
134 } else {
135 rev->reason = CRL_REASON_NONE;
136 }
137
138 // We do not support any critical CRL entry extensions.
139 const STACK_OF(X509_EXTENSION) *exts = rev->extensions;
140 for (size_t j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
141 const X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, j);
142 if (X509_EXTENSION_get_critical(ext)) {
143 crl->flags |= EXFLAG_CRITICAL;
144 break;
145 }
146 }
147 }
148
149 return 1;
150 }
151
152 // The X509_CRL structure needs a bit of customisation. Cache some extensions
153 // and hash of the whole CRL.
crl_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)154 static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
155 void *exarg) {
156 X509_CRL *crl = (X509_CRL *)*pval;
157 int i;
158
159 switch (operation) {
160 case ASN1_OP_NEW_POST:
161 crl->idp = NULL;
162 crl->akid = NULL;
163 crl->flags = 0;
164 crl->idp_flags = 0;
165 break;
166
167 case ASN1_OP_D2I_POST: {
168 // The version must be one of v1(0) or v2(1).
169 long version = X509_CRL_VERSION_1;
170 if (crl->crl->version != NULL) {
171 version = ASN1_INTEGER_get(crl->crl->version);
172 // TODO(https://crbug.com/boringssl/364): |X509_CRL_VERSION_1|
173 // should also be rejected. This means an explicitly-encoded X.509v1
174 // version. v1 is DEFAULT, so DER requires it be omitted.
175 if (version < X509_CRL_VERSION_1 || version > X509_CRL_VERSION_2) {
176 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
177 return 0;
178 }
179 }
180
181 // Per RFC 5280, section 5.1.2.1, extensions require v2.
182 if (version != X509_CRL_VERSION_2 && crl->crl->extensions != NULL) {
183 OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
184 return 0;
185 }
186
187 if (!X509_CRL_digest(crl, EVP_sha256(), crl->crl_hash, NULL)) {
188 return 0;
189 }
190
191 crl->idp =
192 X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, &i, NULL);
193 if (crl->idp != NULL) {
194 if (!setup_idp(crl, crl->idp)) {
195 return 0;
196 }
197 } else if (i != -1) {
198 return 0;
199 }
200
201 crl->akid =
202 X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, &i, NULL);
203 if (crl->akid == NULL && i != -1) {
204 return 0;
205 }
206
207 // See if we have any unhandled critical CRL extensions and indicate
208 // this in a flag. We only currently handle IDP so anything else
209 // critical sets the flag. This code accesses the X509_CRL structure
210 // directly: applications shouldn't do this.
211 const STACK_OF(X509_EXTENSION) *exts = crl->crl->extensions;
212 for (size_t idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
213 const X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, idx);
214 int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ext));
215 if (X509_EXTENSION_get_critical(ext)) {
216 if (nid == NID_issuing_distribution_point ||
217 nid == NID_authority_key_identifier) {
218 continue;
219 }
220 crl->flags |= EXFLAG_CRITICAL;
221 break;
222 }
223 }
224
225 if (!crl_parse_entry_extensions(crl)) {
226 return 0;
227 }
228
229 break;
230 }
231
232 case ASN1_OP_FREE_POST:
233 AUTHORITY_KEYID_free(crl->akid);
234 ISSUING_DIST_POINT_free(crl->idp);
235 break;
236 }
237 return 1;
238 }
239
240 // Convert IDP into a more convenient form
241 //
242 // TODO(davidben): Each of these flags are already booleans, so this is not
243 // really more convenient. We can probably remove |idp_flags|.
setup_idp(X509_CRL * crl,ISSUING_DIST_POINT * idp)244 static int setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) {
245 int idp_only = 0;
246 // Set various flags according to IDP
247 crl->idp_flags |= IDP_PRESENT;
248 if (idp->onlyuser > 0) {
249 idp_only++;
250 crl->idp_flags |= IDP_ONLYUSER;
251 }
252 if (idp->onlyCA > 0) {
253 idp_only++;
254 crl->idp_flags |= IDP_ONLYCA;
255 }
256 if (idp->onlyattr > 0) {
257 idp_only++;
258 crl->idp_flags |= IDP_ONLYATTR;
259 }
260
261 // Per RFC 5280, section 5.2.5, at most one of onlyContainsUserCerts,
262 // onlyContainsCACerts, and onlyContainsAttributeCerts may be true.
263 //
264 // TODO(crbug.com/boringssl/443): Move this check to the |ISSUING_DIST_POINT|
265 // parser.
266 if (idp_only > 1) {
267 crl->idp_flags |= IDP_INVALID;
268 }
269
270 if (idp->indirectCRL > 0) {
271 crl->idp_flags |= IDP_INDIRECT;
272 }
273
274 if (idp->onlysomereasons) {
275 crl->idp_flags |= IDP_REASONS;
276 }
277
278 // TODO(davidben): The new verifier does not support nameRelativeToCRLIssuer.
279 // Remove this?
280 return DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
281 }
282
283 ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
284 ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
285 ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
286 ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING),
287 } ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
288
289 // Although |X509_REVOKED| contains an |X509_NAME|, it can be const. It is not
290 // affected by https://crbug.com/boringssl/407 because the |X509_NAME| does
291 // not participate in serialization.
292 IMPLEMENT_ASN1_FUNCTIONS_const(X509_REVOKED)
293 IMPLEMENT_ASN1_DUP_FUNCTION_const(X509_REVOKED)
294
295 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
296 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
297 IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
298
299 static int X509_REVOKED_cmp(const X509_REVOKED *const *a,
300 const X509_REVOKED *const *b) {
301 return ASN1_STRING_cmp((*a)->serialNumber, (*b)->serialNumber);
302 }
303
X509_CRL_add0_revoked(X509_CRL * crl,X509_REVOKED * rev)304 int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev) {
305 X509_CRL_INFO *inf;
306 inf = crl->crl;
307 if (!inf->revoked) {
308 inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
309 }
310 if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
311 return 0;
312 }
313 asn1_encoding_clear(&inf->enc);
314 return 1;
315 }
316
X509_CRL_verify(X509_CRL * crl,EVP_PKEY * pkey)317 int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *pkey) {
318 if (X509_ALGOR_cmp(crl->sig_alg, crl->crl->sig_alg) != 0) {
319 OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH);
320 return 0;
321 }
322
323 return ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO), crl->sig_alg,
324 crl->signature, crl->crl, pkey);
325 }
326
X509_CRL_get0_by_serial(X509_CRL * crl,X509_REVOKED ** ret,const ASN1_INTEGER * serial)327 int X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
328 const ASN1_INTEGER *serial) {
329 return crl_lookup(crl, ret, serial, NULL);
330 }
331
X509_CRL_get0_by_cert(X509_CRL * crl,X509_REVOKED ** ret,X509 * x)332 int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x) {
333 return crl_lookup(crl, ret, X509_get_serialNumber(x),
334 X509_get_issuer_name(x));
335 }
336
crl_revoked_issuer_match(X509_CRL * crl,X509_NAME * nm,X509_REVOKED * rev)337 static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
338 X509_REVOKED *rev) {
339 return nm == NULL || X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)) == 0;
340 }
341
342 static CRYPTO_MUTEX g_crl_sort_lock = CRYPTO_MUTEX_INIT;
343
crl_lookup(X509_CRL * crl,X509_REVOKED ** ret,const ASN1_INTEGER * serial,X509_NAME * issuer)344 static int crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
345 const ASN1_INTEGER *serial, X509_NAME *issuer) {
346 // Use an assert, rather than a runtime error, because returning nothing for a
347 // CRL is arguably failing open, rather than closed.
348 assert(serial->type == V_ASN1_INTEGER || serial->type == V_ASN1_NEG_INTEGER);
349 X509_REVOKED rtmp, *rev;
350 size_t idx;
351 rtmp.serialNumber = (ASN1_INTEGER *)serial;
352 // Sort revoked into serial number order if not already sorted. Do this
353 // under a lock to avoid race condition.
354
355 CRYPTO_MUTEX_lock_read(&g_crl_sort_lock);
356 const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
357 CRYPTO_MUTEX_unlock_read(&g_crl_sort_lock);
358
359 if (!is_sorted) {
360 CRYPTO_MUTEX_lock_write(&g_crl_sort_lock);
361 if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
362 sk_X509_REVOKED_sort(crl->crl->revoked);
363 }
364 CRYPTO_MUTEX_unlock_write(&g_crl_sort_lock);
365 }
366
367 if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp)) {
368 return 0;
369 }
370 // Need to look for matching name
371 for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
372 rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
373 if (ASN1_INTEGER_cmp(rev->serialNumber, serial)) {
374 return 0;
375 }
376 if (crl_revoked_issuer_match(crl, issuer, rev)) {
377 if (ret) {
378 *ret = rev;
379 }
380 return 1;
381 }
382 }
383 return 0;
384 }
385