xref: /dragonfly/crypto/libressl/crypto/asn1/x_crl.c (revision f5b1c8a1)
1 /* $OpenBSD: x_crl.c,v 1.24 2015/02/11 04:00:39 jsing Exp $ */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58 
59 #include <stdio.h>
60 
61 #include <openssl/opensslconf.h>
62 
63 #include <openssl/asn1t.h>
64 #include <openssl/err.h>
65 #include <openssl/x509.h>
66 #include <openssl/x509v3.h>
67 
68 #include "asn1_locl.h"
69 
70 static int X509_REVOKED_cmp(const X509_REVOKED * const *a,
71     const X509_REVOKED * const *b);
72 static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
73 
74 static const ASN1_TEMPLATE X509_REVOKED_seq_tt[] = {
75 	{
76 		.offset = offsetof(X509_REVOKED, serialNumber),
77 		.field_name = "serialNumber",
78 		.item = &ASN1_INTEGER_it,
79 	},
80 	{
81 		.offset = offsetof(X509_REVOKED, revocationDate),
82 		.field_name = "revocationDate",
83 		.item = &ASN1_TIME_it,
84 	},
85 	{
86 		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
87 		.offset = offsetof(X509_REVOKED, extensions),
88 		.field_name = "extensions",
89 		.item = &X509_EXTENSION_it,
90 	},
91 };
92 
93 const ASN1_ITEM X509_REVOKED_it = {
94 	.itype = ASN1_ITYPE_SEQUENCE,
95 	.utype = V_ASN1_SEQUENCE,
96 	.templates = X509_REVOKED_seq_tt,
97 	.tcount = sizeof(X509_REVOKED_seq_tt) / sizeof(ASN1_TEMPLATE),
98 	.size = sizeof(X509_REVOKED),
99 	.sname = "X509_REVOKED",
100 };
101 
102 static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
103 static int def_crl_lookup(X509_CRL *crl, X509_REVOKED **ret,
104     ASN1_INTEGER *serial, X509_NAME *issuer);
105 
106 static X509_CRL_METHOD int_crl_meth = {
107 	.crl_lookup = def_crl_lookup,
108 	.crl_verify = def_crl_verify
109 };
110 
111 static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
112 
113 /* The X509_CRL_INFO structure needs a bit of customisation.
114  * Since we cache the original encoding the signature wont be affected by
115  * reordering of the revoked field.
116  */
117 static int
118 crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
119 {
120 	X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
121 
122 	if (!a || !a->revoked)
123 		return 1;
124 	switch (operation) {
125 		/* Just set cmp function here. We don't sort because that
126 		 * would affect the output of X509_CRL_print().
127 		 */
128 	case ASN1_OP_D2I_POST:
129 		(void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
130 		break;
131 	}
132 	return 1;
133 }
134 
135 
136 static const ASN1_AUX X509_CRL_INFO_aux = {
137 	.flags = ASN1_AFLG_ENCODING,
138 	.asn1_cb = crl_inf_cb,
139 	.enc_offset = offsetof(X509_CRL_INFO, enc),
140 };
141 static const ASN1_TEMPLATE X509_CRL_INFO_seq_tt[] = {
142 	{
143 		.flags = ASN1_TFLG_OPTIONAL,
144 		.offset = offsetof(X509_CRL_INFO, version),
145 		.field_name = "version",
146 		.item = &ASN1_INTEGER_it,
147 	},
148 	{
149 		.offset = offsetof(X509_CRL_INFO, sig_alg),
150 		.field_name = "sig_alg",
151 		.item = &X509_ALGOR_it,
152 	},
153 	{
154 		.offset = offsetof(X509_CRL_INFO, issuer),
155 		.field_name = "issuer",
156 		.item = &X509_NAME_it,
157 	},
158 	{
159 		.offset = offsetof(X509_CRL_INFO, lastUpdate),
160 		.field_name = "lastUpdate",
161 		.item = &ASN1_TIME_it,
162 	},
163 	{
164 		.flags = ASN1_TFLG_OPTIONAL,
165 		.offset = offsetof(X509_CRL_INFO, nextUpdate),
166 		.field_name = "nextUpdate",
167 		.item = &ASN1_TIME_it,
168 	},
169 	{
170 		.flags = ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
171 		.offset = offsetof(X509_CRL_INFO, revoked),
172 		.field_name = "revoked",
173 		.item = &X509_REVOKED_it,
174 	},
175 	{
176 		.flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
177 		.offset = offsetof(X509_CRL_INFO, extensions),
178 		.field_name = "extensions",
179 		.item = &X509_EXTENSION_it,
180 	},
181 };
182 
183 const ASN1_ITEM X509_CRL_INFO_it = {
184 	.itype = ASN1_ITYPE_SEQUENCE,
185 	.utype = V_ASN1_SEQUENCE,
186 	.templates = X509_CRL_INFO_seq_tt,
187 	.tcount = sizeof(X509_CRL_INFO_seq_tt) / sizeof(ASN1_TEMPLATE),
188 	.funcs = &X509_CRL_INFO_aux,
189 	.size = sizeof(X509_CRL_INFO),
190 	.sname = "X509_CRL_INFO",
191 };
192 
193 /* Set CRL entry issuer according to CRL certificate issuer extension.
194  * Check for unhandled critical CRL entry extensions.
195  */
196 
197 static int
198 crl_set_issuers(X509_CRL *crl)
199 {
200 	int i, j;
201 	GENERAL_NAMES *gens, *gtmp;
202 	STACK_OF(X509_REVOKED) *revoked;
203 
204 	revoked = X509_CRL_get_REVOKED(crl);
205 
206 	gens = NULL;
207 	for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
208 		X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
209 		STACK_OF(X509_EXTENSION) *exts;
210 		ASN1_ENUMERATED *reason;
211 		X509_EXTENSION *ext;
212 		gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer,
213 		    &j, NULL);
214 		if (!gtmp && (j != -1)) {
215 			crl->flags |= EXFLAG_INVALID;
216 			return 1;
217 		}
218 
219 		if (gtmp) {
220 			gens = gtmp;
221 			if (!crl->issuers) {
222 				crl->issuers = sk_GENERAL_NAMES_new_null();
223 				if (!crl->issuers)
224 					return 0;
225 			}
226 			if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
227 				return 0;
228 		}
229 		rev->issuer = gens;
230 
231 		reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason,
232 		    &j, NULL);
233 		if (!reason && (j != -1)) {
234 			crl->flags |= EXFLAG_INVALID;
235 			return 1;
236 		}
237 
238 		if (reason) {
239 			rev->reason = ASN1_ENUMERATED_get(reason);
240 			ASN1_ENUMERATED_free(reason);
241 		} else
242 			rev->reason = CRL_REASON_NONE;
243 
244 		/* Check for critical CRL entry extensions */
245 
246 		exts = rev->extensions;
247 
248 		for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) {
249 			ext = sk_X509_EXTENSION_value(exts, j);
250 			if (ext->critical > 0) {
251 				if (OBJ_obj2nid(ext->object) ==
252 				    NID_certificate_issuer)
253 					continue;
254 				crl->flags |= EXFLAG_CRITICAL;
255 				break;
256 			}
257 		}
258 	}
259 
260 	return 1;
261 }
262 
263 /* The X509_CRL structure needs a bit of customisation. Cache some extensions
264  * and hash of the whole CRL.
265  */
266 static int
267 crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
268 {
269 	X509_CRL *crl = (X509_CRL *)*pval;
270 	STACK_OF(X509_EXTENSION) *exts;
271 	X509_EXTENSION *ext;
272 	int idx;
273 	int rc = 1;
274 
275 	switch (operation) {
276 	case ASN1_OP_NEW_POST:
277 		crl->idp = NULL;
278 		crl->akid = NULL;
279 		crl->flags = 0;
280 		crl->idp_flags = 0;
281 		crl->idp_reasons = CRLDP_ALL_REASONS;
282 		crl->meth = default_crl_method;
283 		crl->meth_data = NULL;
284 		crl->issuers = NULL;
285 		crl->crl_number = NULL;
286 		crl->base_crl_number = NULL;
287 		break;
288 
289 	case ASN1_OP_D2I_POST:
290 #ifndef OPENSSL_NO_SHA
291 		X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
292 #endif
293 		crl->idp = X509_CRL_get_ext_d2i(crl,
294 		    NID_issuing_distribution_point, NULL, NULL);
295 		if (crl->idp)
296 			setup_idp(crl, crl->idp);
297 
298 		crl->akid = X509_CRL_get_ext_d2i(crl,
299 		    NID_authority_key_identifier, NULL, NULL);
300 
301 		crl->crl_number = X509_CRL_get_ext_d2i(crl,
302 		    NID_crl_number, NULL, NULL);
303 
304 		crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
305 		    NID_delta_crl, NULL, NULL);
306 		/* Delta CRLs must have CRL number */
307 		if (crl->base_crl_number && !crl->crl_number)
308 			crl->flags |= EXFLAG_INVALID;
309 
310 		/* See if we have any unhandled critical CRL extensions and
311 		 * indicate this in a flag. We only currently handle IDP,
312 		 * AKID and deltas, so anything else critical sets the flag.
313 		 *
314 		 * This code accesses the X509_CRL structure directly:
315 		 * applications shouldn't do this.
316 		 */
317 
318 		exts = crl->crl->extensions;
319 
320 		for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
321 			int nid;
322 			ext = sk_X509_EXTENSION_value(exts, idx);
323 			nid = OBJ_obj2nid(ext->object);
324 			if (nid == NID_freshest_crl)
325 				crl->flags |= EXFLAG_FRESHEST;
326 			if (ext->critical > 0) {
327 				/* We handle IDP, AKID and deltas */
328 				if (nid == NID_issuing_distribution_point ||
329 				    nid == NID_authority_key_identifier ||
330 				    nid == NID_delta_crl)
331 					break;
332 				crl->flags |= EXFLAG_CRITICAL;
333 				break;
334 			}
335 		}
336 
337 		if (!crl_set_issuers(crl))
338 			return 0;
339 
340 		if (crl->meth->crl_init) {
341 			if (crl->meth->crl_init(crl) == 0)
342 				return 0;
343 		}
344 		break;
345 
346 	case ASN1_OP_FREE_POST:
347 		if (crl->meth->crl_free) {
348 			if (!crl->meth->crl_free(crl))
349 				rc = 0;
350 		}
351 		if (crl->akid)
352 			AUTHORITY_KEYID_free(crl->akid);
353 		if (crl->idp)
354 			ISSUING_DIST_POINT_free(crl->idp);
355 		ASN1_INTEGER_free(crl->crl_number);
356 		ASN1_INTEGER_free(crl->base_crl_number);
357 		sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
358 		break;
359 	}
360 	return rc;
361 }
362 
363 /* Convert IDP into a more convenient form */
364 
365 static void
366 setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
367 {
368 	int idp_only = 0;
369 
370 	/* Set various flags according to IDP */
371 	crl->idp_flags |= IDP_PRESENT;
372 	if (idp->onlyuser > 0) {
373 		idp_only++;
374 		crl->idp_flags |= IDP_ONLYUSER;
375 	}
376 	if (idp->onlyCA > 0) {
377 		idp_only++;
378 		crl->idp_flags |= IDP_ONLYCA;
379 	}
380 	if (idp->onlyattr > 0) {
381 		idp_only++;
382 		crl->idp_flags |= IDP_ONLYATTR;
383 	}
384 
385 	if (idp_only > 1)
386 		crl->idp_flags |= IDP_INVALID;
387 
388 	if (idp->indirectCRL > 0)
389 		crl->idp_flags |= IDP_INDIRECT;
390 
391 	if (idp->onlysomereasons) {
392 		crl->idp_flags |= IDP_REASONS;
393 		if (idp->onlysomereasons->length > 0)
394 			crl->idp_reasons = idp->onlysomereasons->data[0];
395 		if (idp->onlysomereasons->length > 1)
396 			crl->idp_reasons |=
397 			    (idp->onlysomereasons->data[1] << 8);
398 		crl->idp_reasons &= CRLDP_ALL_REASONS;
399 	}
400 
401 	DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
402 }
403 
404 static const ASN1_AUX X509_CRL_aux = {
405 	.app_data = NULL,
406 	.flags = ASN1_AFLG_REFCOUNT,
407 	.ref_offset = offsetof(X509_CRL, references),
408 	.ref_lock = CRYPTO_LOCK_X509_CRL,
409 	.asn1_cb = crl_cb,
410 };
411 static const ASN1_TEMPLATE X509_CRL_seq_tt[] = {
412 	{
413 		.offset = offsetof(X509_CRL, crl),
414 		.field_name = "crl",
415 		.item = &X509_CRL_INFO_it,
416 	},
417 	{
418 		.offset = offsetof(X509_CRL, sig_alg),
419 		.field_name = "sig_alg",
420 		.item = &X509_ALGOR_it,
421 	},
422 	{
423 		.offset = offsetof(X509_CRL, signature),
424 		.field_name = "signature",
425 		.item = &ASN1_BIT_STRING_it,
426 	},
427 };
428 
429 const ASN1_ITEM X509_CRL_it = {
430 	.itype = ASN1_ITYPE_SEQUENCE,
431 	.utype = V_ASN1_SEQUENCE,
432 	.templates = X509_CRL_seq_tt,
433 	.tcount = sizeof(X509_CRL_seq_tt) / sizeof(ASN1_TEMPLATE),
434 	.funcs = &X509_CRL_aux,
435 	.size = sizeof(X509_CRL),
436 	.sname = "X509_CRL",
437 };
438 
439 
440 X509_REVOKED *
441 d2i_X509_REVOKED(X509_REVOKED **a, const unsigned char **in, long len)
442 {
443 	return (X509_REVOKED *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
444 	    &X509_REVOKED_it);
445 }
446 
447 int
448 i2d_X509_REVOKED(X509_REVOKED *a, unsigned char **out)
449 {
450 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_REVOKED_it);
451 }
452 
453 X509_REVOKED *
454 X509_REVOKED_new(void)
455 {
456 	return (X509_REVOKED *)ASN1_item_new(&X509_REVOKED_it);
457 }
458 
459 void
460 X509_REVOKED_free(X509_REVOKED *a)
461 {
462 	ASN1_item_free((ASN1_VALUE *)a, &X509_REVOKED_it);
463 }
464 
465 X509_CRL_INFO *
466 d2i_X509_CRL_INFO(X509_CRL_INFO **a, const unsigned char **in, long len)
467 {
468 	return (X509_CRL_INFO *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
469 	    &X509_CRL_INFO_it);
470 }
471 
472 int
473 i2d_X509_CRL_INFO(X509_CRL_INFO *a, unsigned char **out)
474 {
475 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CRL_INFO_it);
476 }
477 
478 X509_CRL_INFO *
479 X509_CRL_INFO_new(void)
480 {
481 	return (X509_CRL_INFO *)ASN1_item_new(&X509_CRL_INFO_it);
482 }
483 
484 void
485 X509_CRL_INFO_free(X509_CRL_INFO *a)
486 {
487 	ASN1_item_free((ASN1_VALUE *)a, &X509_CRL_INFO_it);
488 }
489 
490 X509_CRL *
491 d2i_X509_CRL(X509_CRL **a, const unsigned char **in, long len)
492 {
493 	return (X509_CRL *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
494 	    &X509_CRL_it);
495 }
496 
497 int
498 i2d_X509_CRL(X509_CRL *a, unsigned char **out)
499 {
500 	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_CRL_it);
501 }
502 
503 X509_CRL *
504 X509_CRL_new(void)
505 {
506 	return (X509_CRL *)ASN1_item_new(&X509_CRL_it);
507 }
508 
509 void
510 X509_CRL_free(X509_CRL *a)
511 {
512 	ASN1_item_free((ASN1_VALUE *)a, &X509_CRL_it);
513 }
514 
515 X509_CRL *
516 X509_CRL_dup(X509_CRL *x)
517 {
518 	return ASN1_item_dup(&X509_CRL_it, x);
519 }
520 
521 static int
522 X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b)
523 {
524 	return(ASN1_STRING_cmp(
525 	    (ASN1_STRING *)(*a)->serialNumber,
526 	    (ASN1_STRING *)(*b)->serialNumber));
527 }
528 
529 int
530 X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
531 {
532 	X509_CRL_INFO *inf;
533 
534 	inf = crl->crl;
535 	if (!inf->revoked)
536 		inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
537 	if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
538 		ASN1err(ASN1_F_X509_CRL_ADD0_REVOKED, ERR_R_MALLOC_FAILURE);
539 		return 0;
540 	}
541 	inf->enc.modified = 1;
542 	return 1;
543 }
544 
545 int
546 X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
547 {
548 	if (crl->meth->crl_verify)
549 		return crl->meth->crl_verify(crl, r);
550 	return 0;
551 }
552 
553 int
554 X509_CRL_get0_by_serial(X509_CRL *crl, X509_REVOKED **ret,
555     ASN1_INTEGER *serial)
556 {
557 	if (crl->meth->crl_lookup)
558 		return crl->meth->crl_lookup(crl, ret, serial, NULL);
559 	return 0;
560 }
561 
562 int
563 X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
564 {
565 	if (crl->meth->crl_lookup)
566 		return crl->meth->crl_lookup(crl, ret,
567 		    X509_get_serialNumber(x), X509_get_issuer_name(x));
568 	return 0;
569 }
570 
571 static int
572 def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
573 {
574 	return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
575 	    crl->sig_alg, crl->signature, crl->crl, r));
576 }
577 
578 static int
579 crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm, X509_REVOKED *rev)
580 {
581 	int i;
582 
583 	if (!rev->issuer) {
584 		if (!nm)
585 			return 1;
586 		if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
587 			return 1;
588 		return 0;
589 	}
590 
591 	if (!nm)
592 		nm = X509_CRL_get_issuer(crl);
593 
594 	for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
595 		GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
596 		if (gen->type != GEN_DIRNAME)
597 			continue;
598 		if (!X509_NAME_cmp(nm, gen->d.directoryName))
599 			return 1;
600 	}
601 	return 0;
602 
603 }
604 
605 static int
606 def_crl_lookup(X509_CRL *crl, X509_REVOKED **ret, ASN1_INTEGER *serial,
607     X509_NAME *issuer)
608 {
609 	X509_REVOKED rtmp, *rev;
610 	int idx;
611 
612 	rtmp.serialNumber = serial;
613 	/* Sort revoked into serial number order if not already sorted.
614 	 * Do this under a lock to avoid race condition.
615  	 */
616 	if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
617 		CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
618 		sk_X509_REVOKED_sort(crl->crl->revoked);
619 		CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
620 	}
621 	idx = sk_X509_REVOKED_find(crl->crl->revoked, &rtmp);
622 	if (idx < 0)
623 		return 0;
624 	/* Need to look for matching name */
625 	for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
626 		rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
627 		if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
628 			return 0;
629 		if (crl_revoked_issuer_match(crl, issuer, rev)) {
630 			if (ret)
631 				*ret = rev;
632 			if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
633 				return 2;
634 			return 1;
635 		}
636 	}
637 	return 0;
638 }
639 
640 void
641 X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
642 {
643 	if (meth == NULL)
644 		default_crl_method = &int_crl_meth;
645 	else
646 		default_crl_method = meth;
647 }
648 
649 X509_CRL_METHOD *
650 X509_CRL_METHOD_new(int (*crl_init)(X509_CRL *crl),
651     int (*crl_free)(X509_CRL *crl),
652     int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
653     ASN1_INTEGER *ser, X509_NAME *issuer),
654     int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk))
655 {
656 	X509_CRL_METHOD *m;
657 
658 	m = malloc(sizeof(X509_CRL_METHOD));
659 	if (!m)
660 		return NULL;
661 	m->crl_init = crl_init;
662 	m->crl_free = crl_free;
663 	m->crl_lookup = crl_lookup;
664 	m->crl_verify = crl_verify;
665 	m->flags = X509_CRL_METHOD_DYNAMIC;
666 	return m;
667 }
668 
669 void
670 X509_CRL_METHOD_free(X509_CRL_METHOD *m)
671 {
672 	if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
673 		return;
674 	free(m);
675 }
676 
677 void
678 X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
679 {
680 	crl->meth_data = dat;
681 }
682 
683 void *
684 X509_CRL_get_meth_data(X509_CRL *crl)
685 {
686 	return crl->meth_data;
687 }
688