x509: Evaluate return codes of parsing functions
[strongswan.git] / src / libstrongswan / plugins / x509 / x509_crl.c
1 /*
2 * Copyright (C) 2008-2009 Martin Willi
3 * Copyright (C) 2017 Andreas Steffen
4 * HSR Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "x509_crl.h"
18
19 typedef struct private_x509_crl_t private_x509_crl_t;
20 typedef struct revoked_t revoked_t;
21
22 #include <time.h>
23
24 #include <utils/debug.h>
25 #include <library.h>
26 #include <asn1/oid.h>
27 #include <asn1/asn1.h>
28 #include <asn1/asn1_parser.h>
29 #include <credentials/certificates/x509.h>
30 #include <credentials/keys/private_key.h>
31 #include <collections/linked_list.h>
32
33 /**
34 * entry for a revoked certificate
35 */
36 struct revoked_t {
37 /**
38 * serial of the revoked certificate
39 */
40 chunk_t serial;
41
42 /**
43 * date of revocation
44 */
45 time_t date;
46
47 /**
48 * reason for revocation
49 */
50 crl_reason_t reason;
51 };
52
53 /**
54 * private data of x509_crl
55 */
56 struct private_x509_crl_t {
57
58 /**
59 * public functions
60 */
61 x509_crl_t public;
62
63 /**
64 * X.509 crl encoding in ASN.1 DER format
65 */
66 chunk_t encoding;
67
68 /**
69 * X.509 crl body over which signature is computed
70 */
71 chunk_t tbsCertList;
72
73 /**
74 * Version of the X.509 crl
75 */
76 u_int version;
77
78 /**
79 * ID representing the crl issuer
80 */
81 identification_t *issuer;
82
83 /**
84 * CRL number
85 */
86 chunk_t crlNumber;
87
88 /**
89 * Time when the crl was generated
90 */
91 time_t thisUpdate;
92
93 /**
94 * Time when an update crl will be available
95 */
96 time_t nextUpdate;
97
98 /**
99 * list of revoked certificates as revoked_t
100 */
101 linked_list_t *revoked;
102
103 /**
104 * List of Freshest CRL distribution points
105 */
106 linked_list_t *crl_uris;
107
108 /**
109 * Authority Key Identifier
110 */
111 chunk_t authKeyIdentifier;
112
113 /**
114 * Authority Key Serial Number
115 */
116 chunk_t authKeySerialNumber;
117
118 /**
119 * Number of BaseCRL, if a delta CRL
120 */
121 chunk_t baseCrlNumber;
122
123 /**
124 * Signature algorithm
125 */
126 int algorithm;
127
128 /**
129 * Signature
130 */
131 chunk_t signature;
132
133 /**
134 * has this CRL been generated
135 */
136 bool generated;
137
138 /**
139 * reference counter
140 */
141 refcount_t ref;
142 };
143
144 /**
145 * from x509_cert
146 */
147 extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob, int level0,
148 chunk_t *authKeySerialNumber);
149
150 /**
151 * from x509_cert
152 */
153 extern bool x509_parse_crlDistributionPoints(chunk_t blob, int level0,
154 linked_list_t *list);
155
156 /**
157 * from x509_cert
158 */
159 extern chunk_t x509_build_crlDistributionPoints(linked_list_t *list, int extn);
160
161 /**
162 * ASN.1 definition of an X.509 certificate revocation list
163 */
164 static const asn1Object_t crlObjects[] = {
165 { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
166 { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
167 { 2, "version", ASN1_INTEGER, ASN1_OPT |
168 ASN1_BODY }, /* 2 */
169 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
170 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */
171 { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
172 { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */
173 { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */
174 { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT |
175 ASN1_LOOP }, /* 8 */
176 { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */
177 { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */
178 { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */
179 { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT |
180 ASN1_LOOP }, /* 12 */
181 { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
182 { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */
183 { 6, "critical", ASN1_BOOLEAN, ASN1_DEF |
184 ASN1_BODY }, /* 15 */
185 { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
186 { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */
187 { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */
188 { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */
189 { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
190 { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
191 { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
192 { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
193 ASN1_BODY }, /* 23 */
194 { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
195 { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
196 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
197 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
198 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 28 */
199 { 0, "exit", ASN1_EOC, ASN1_EXIT }
200 };
201 #define CRL_OBJ_TBS_CERT_LIST 1
202 #define CRL_OBJ_VERSION 2
203 #define CRL_OBJ_SIG_ALG 4
204 #define CRL_OBJ_ISSUER 5
205 #define CRL_OBJ_THIS_UPDATE 6
206 #define CRL_OBJ_NEXT_UPDATE 7
207 #define CRL_OBJ_USER_CERTIFICATE 10
208 #define CRL_OBJ_REVOCATION_DATE 11
209 #define CRL_OBJ_CRL_ENTRY_EXTN_ID 14
210 #define CRL_OBJ_CRL_ENTRY_CRITICAL 15
211 #define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16
212 #define CRL_OBJ_EXTN_ID 22
213 #define CRL_OBJ_CRITICAL 23
214 #define CRL_OBJ_EXTN_VALUE 24
215 #define CRL_OBJ_ALGORITHM 27
216 #define CRL_OBJ_SIGNATURE 28
217
218 /**
219 * Parses an X.509 Certificate Revocation List (CRL)
220 */
221 static bool parse(private_x509_crl_t *this)
222 {
223 asn1_parser_t *parser;
224 chunk_t object;
225 chunk_t extnID = chunk_empty;
226 chunk_t userCertificate = chunk_empty;
227 int objectID;
228 int sig_alg = OID_UNKNOWN;
229 bool success = FALSE;
230 bool critical = FALSE;
231 revoked_t *revoked = NULL;
232
233 parser = asn1_parser_create(crlObjects, this->encoding);
234
235 while (parser->iterate(parser, &objectID, &object))
236 {
237 u_int level = parser->get_level(parser)+1;
238
239 switch (objectID)
240 {
241 case CRL_OBJ_TBS_CERT_LIST:
242 this->tbsCertList = object;
243 break;
244 case CRL_OBJ_VERSION:
245 this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
246 DBG2(DBG_ASN, " v%d", this->version);
247 break;
248 case CRL_OBJ_SIG_ALG:
249 sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
250 break;
251 case CRL_OBJ_ISSUER:
252 this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
253 DBG2(DBG_ASN, " '%Y'", this->issuer);
254 break;
255 case CRL_OBJ_THIS_UPDATE:
256 this->thisUpdate = asn1_parse_time(object, level);
257 break;
258 case CRL_OBJ_NEXT_UPDATE:
259 this->nextUpdate = asn1_parse_time(object, level);
260 break;
261 case CRL_OBJ_USER_CERTIFICATE:
262 userCertificate = object;
263 break;
264 case CRL_OBJ_REVOCATION_DATE:
265 revoked = malloc_thing(revoked_t);
266 revoked->serial = chunk_clone(userCertificate);
267 revoked->date = asn1_parse_time(object, level);
268 revoked->reason = CRL_REASON_UNSPECIFIED;
269 this->revoked->insert_last(this->revoked, (void *)revoked);
270 break;
271 case CRL_OBJ_CRL_ENTRY_EXTN_ID:
272 case CRL_OBJ_EXTN_ID:
273 extnID = object;
274 break;
275 case CRL_OBJ_CRL_ENTRY_CRITICAL:
276 case CRL_OBJ_CRITICAL:
277 critical = object.len && *object.ptr;
278 DBG2(DBG_ASN, " %s", critical ? "TRUE" : "FALSE");
279 break;
280 case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
281 case CRL_OBJ_EXTN_VALUE:
282 {
283 int extn_oid = asn1_known_oid(extnID);
284
285 switch (extn_oid)
286 {
287 case OID_CRL_REASON_CODE:
288 if (revoked)
289 {
290 if (object.len && *object.ptr == ASN1_ENUMERATED &&
291 asn1_length(&object) == 1)
292 {
293 revoked->reason = *object.ptr;
294 }
295 DBG2(DBG_ASN, " '%N'", crl_reason_names,
296 revoked->reason);
297 }
298 break;
299 case OID_AUTHORITY_KEY_ID:
300 this->authKeyIdentifier =
301 x509_parse_authorityKeyIdentifier(
302 object, level, &this->authKeySerialNumber);
303 break;
304 case OID_CRL_NUMBER:
305 if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
306 level, "crlNumber"))
307 {
308 goto end;
309 }
310 this->crlNumber = object;
311 break;
312 case OID_FRESHEST_CRL:
313 if (!x509_parse_crlDistributionPoints(object, level,
314 this->crl_uris))
315 {
316 goto end;
317 }
318 break;
319 case OID_DELTA_CRL_INDICATOR:
320 if (!asn1_parse_simple_object(&object, ASN1_INTEGER,
321 level, "deltaCrlIndicator"))
322 {
323 goto end;
324 }
325 this->baseCrlNumber = object;
326 break;
327 case OID_ISSUING_DIST_POINT:
328 /* TODO support of IssuingDistributionPoints */
329 break;
330 default:
331 if (critical && lib->settings->get_bool(lib->settings,
332 "%s.x509.enforce_critical", TRUE, lib->ns))
333 {
334 DBG1(DBG_ASN, "critical '%s' extension not supported",
335 (extn_oid == OID_UNKNOWN) ? "unknown" :
336 (char*)oid_names[extn_oid].name);
337 goto end;
338 }
339 break;
340 }
341 break;
342 }
343 case CRL_OBJ_ALGORITHM:
344 {
345 this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL);
346 if (this->algorithm != sig_alg)
347 {
348 DBG1(DBG_ASN, " signature algorithms do not agree");
349 goto end;
350 }
351 break;
352 }
353 case CRL_OBJ_SIGNATURE:
354 this->signature = chunk_skip(object, 1);
355 break;
356 default:
357 break;
358 }
359 }
360 success = parser->success(parser);
361
362 end:
363 parser->destroy(parser);
364 return success;
365 }
366
367 /**
368 * enumerator filter callback for create_enumerator
369 */
370 static bool filter(void *data, revoked_t **revoked, chunk_t *serial, void *p2,
371 time_t *date, void *p3, crl_reason_t *reason)
372 {
373 if (serial)
374 {
375 *serial = (*revoked)->serial;
376 }
377 if (date)
378 {
379 *date = (*revoked)->date;
380 }
381 if (reason)
382 {
383 *reason = (*revoked)->reason;
384 }
385 return TRUE;
386 }
387
388 METHOD(crl_t, get_serial, chunk_t,
389 private_x509_crl_t *this)
390 {
391 return this->crlNumber;
392 }
393
394 METHOD(crl_t, get_authKeyIdentifier, chunk_t,
395 private_x509_crl_t *this)
396 {
397 return this->authKeyIdentifier;
398 }
399
400 METHOD(crl_t, is_delta_crl, bool,
401 private_x509_crl_t *this, chunk_t *base_crl)
402 {
403 if (this->baseCrlNumber.len)
404 {
405 if (base_crl)
406 {
407 *base_crl = this->baseCrlNumber;
408 }
409 return TRUE;
410 }
411 return FALSE;
412 }
413
414 METHOD(crl_t, create_delta_crl_uri_enumerator, enumerator_t*,
415 private_x509_crl_t *this)
416 {
417 return this->crl_uris->create_enumerator(this->crl_uris);
418 }
419
420 METHOD(crl_t, create_enumerator, enumerator_t*,
421 private_x509_crl_t *this)
422 {
423 return enumerator_create_filter(
424 this->revoked->create_enumerator(this->revoked),
425 (void*)filter, NULL, NULL);
426 }
427
428 METHOD(certificate_t, get_type, certificate_type_t,
429 private_x509_crl_t *this)
430 {
431 return CERT_X509_CRL;
432 }
433
434 METHOD(certificate_t, get_issuer, identification_t*,
435 private_x509_crl_t *this)
436 {
437 return this->issuer;
438 }
439
440 METHOD(certificate_t, has_issuer, id_match_t,
441 private_x509_crl_t *this, identification_t *issuer)
442 {
443 if (issuer->get_type(issuer) == ID_KEY_ID && this->authKeyIdentifier.ptr &&
444 chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
445 {
446 return ID_MATCH_PERFECT;
447 }
448 return this->issuer->matches(this->issuer, issuer);
449 }
450
451 METHOD(certificate_t, issued_by, bool,
452 private_x509_crl_t *this, certificate_t *issuer, signature_scheme_t *schemep)
453 {
454 public_key_t *key;
455 signature_scheme_t scheme;
456 bool valid;
457 x509_t *x509 = (x509_t*)issuer;
458 chunk_t keyid = chunk_empty;
459
460 /* check if issuer is an X.509 CA certificate */
461 if (issuer->get_type(issuer) != CERT_X509)
462 {
463 return FALSE;
464 }
465 if (!(x509->get_flags(x509) & (X509_CA | X509_CRL_SIGN)))
466 {
467 return FALSE;
468 }
469
470 /* compare keyIdentifiers if available, otherwise use DNs */
471 if (this->authKeyIdentifier.ptr)
472 {
473 keyid = x509->get_subjectKeyIdentifier(x509);
474 if (keyid.len && !chunk_equals(keyid, this->authKeyIdentifier))
475 {
476 return FALSE;
477 }
478 }
479 if (!keyid.len)
480 {
481 if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
482 {
483 return FALSE;
484 }
485 }
486
487 scheme = signature_scheme_from_oid(this->algorithm);
488 if (scheme == SIGN_UNKNOWN)
489 {
490 return FALSE;
491 }
492 key = issuer->get_public_key(issuer);
493 if (!key)
494 {
495 return FALSE;
496 }
497 valid = key->verify(key, scheme, this->tbsCertList, this->signature);
498 key->destroy(key);
499 if (valid && schemep)
500 {
501 *schemep = scheme;
502 }
503 return valid;
504 }
505
506 METHOD(certificate_t, get_public_key, public_key_t*,
507 private_x509_crl_t *this)
508 {
509 return NULL;
510 }
511
512 METHOD(certificate_t, get_ref, certificate_t*,
513 private_x509_crl_t *this)
514 {
515 ref_get(&this->ref);
516 return &this->public.crl.certificate;
517 }
518
519 METHOD(certificate_t, get_validity, bool,
520 private_x509_crl_t *this, time_t *when,
521 time_t *not_before, time_t *not_after)
522 {
523 time_t t = when ? *when : time(NULL);
524
525 if (not_before)
526 {
527 *not_before = this->thisUpdate;
528 }
529 if (not_after)
530 {
531 *not_after = this->nextUpdate;
532 }
533 return (t <= this->nextUpdate);
534 }
535
536 METHOD(certificate_t, get_encoding, bool,
537 private_x509_crl_t *this, cred_encoding_type_t type, chunk_t *encoding)
538 {
539 if (type == CERT_ASN1_DER)
540 {
541 *encoding = chunk_clone(this->encoding);
542 return TRUE;
543 }
544 return lib->encoding->encode(lib->encoding, type, NULL, encoding,
545 CRED_PART_X509_CRL_ASN1_DER, this->encoding, CRED_PART_END);
546 }
547
548 METHOD(certificate_t, equals, bool,
549 private_x509_crl_t *this, certificate_t *other)
550 {
551 chunk_t encoding;
552 bool equal;
553
554 if ((certificate_t*)this == other)
555 {
556 return TRUE;
557 }
558 if (other->equals == (void*)equals)
559 { /* skip allocation if we have the same implementation */
560 return chunk_equals(this->encoding, ((private_x509_crl_t*)other)->encoding);
561 }
562 if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
563 {
564 return FALSE;
565 }
566 equal = chunk_equals(this->encoding, encoding);
567 free(encoding.ptr);
568 return equal;
569 }
570
571 /**
572 * Destroy a revoked_t entry
573 */
574 static void revoked_destroy(revoked_t *revoked)
575 {
576 free(revoked->serial.ptr);
577 free(revoked);
578 }
579
580 /**
581 * Destroy a CDP entry
582 */
583 static void cdp_destroy(x509_cdp_t *this)
584 {
585 free(this->uri);
586 DESTROY_IF(this->issuer);
587 free(this);
588 }
589
590 METHOD(certificate_t, destroy, void,
591 private_x509_crl_t *this)
592 {
593 if (ref_put(&this->ref))
594 {
595 this->revoked->destroy_function(this->revoked, (void*)revoked_destroy);
596 this->crl_uris->destroy_function(this->crl_uris, (void*)cdp_destroy);
597 DESTROY_IF(this->issuer);
598 free(this->authKeyIdentifier.ptr);
599 free(this->encoding.ptr);
600 if (this->generated)
601 {
602 free(this->crlNumber.ptr);
603 free(this->baseCrlNumber.ptr);
604 free(this->signature.ptr);
605 free(this->tbsCertList.ptr);
606 }
607 free(this);
608 }
609 }
610
611 /**
612 * create an empty but initialized X.509 crl
613 */
614 static private_x509_crl_t* create_empty(void)
615 {
616 private_x509_crl_t *this;
617
618 INIT(this,
619 .public = {
620 .crl = {
621 .certificate = {
622 .get_type = _get_type,
623 .get_subject = _get_issuer,
624 .get_issuer = _get_issuer,
625 .has_subject = _has_issuer,
626 .has_issuer = _has_issuer,
627 .issued_by = _issued_by,
628 .get_public_key = _get_public_key,
629 .get_validity = _get_validity,
630 .get_encoding = _get_encoding,
631 .equals = _equals,
632 .get_ref = _get_ref,
633 .destroy = _destroy,
634 },
635 .get_serial = _get_serial,
636 .get_authKeyIdentifier = _get_authKeyIdentifier,
637 .is_delta_crl = _is_delta_crl,
638 .create_delta_crl_uri_enumerator = _create_delta_crl_uri_enumerator,
639 .create_enumerator = _create_enumerator,
640 },
641 },
642 .revoked = linked_list_create(),
643 .crl_uris = linked_list_create(),
644 .ref = 1,
645 );
646 return this;
647 }
648
649 /**
650 * See header.
651 */
652 x509_crl_t *x509_crl_load(certificate_type_t type, va_list args)
653 {
654 chunk_t blob = chunk_empty;
655
656 while (TRUE)
657 {
658 switch (va_arg(args, builder_part_t))
659 {
660 case BUILD_BLOB_ASN1_DER:
661 blob = va_arg(args, chunk_t);
662 continue;
663 case BUILD_END:
664 break;
665 default:
666 return NULL;
667 }
668 break;
669 }
670 if (blob.ptr)
671 {
672 private_x509_crl_t *crl = create_empty();
673
674 crl->encoding = chunk_clone(blob);
675 if (parse(crl))
676 {
677 return &crl->public;
678 }
679 destroy(crl);
680 }
681 return NULL;
682 };
683
684 /**
685 * Read certificate status from enumerator, copy to crl
686 */
687 static void read_revoked(private_x509_crl_t *crl, enumerator_t *enumerator)
688 {
689 revoked_t *revoked;
690 chunk_t serial;
691 time_t date;
692 crl_reason_t reason;
693
694 while (enumerator->enumerate(enumerator, &serial, &date, &reason))
695 {
696 INIT(revoked,
697 .serial = chunk_clone(serial),
698 .date = date,
699 .reason = reason,
700 );
701 crl->revoked->insert_last(crl->revoked, revoked);
702 }
703 }
704
705 /**
706 * Generate CRL encoding, sign CRL
707 */
708 static bool generate(private_x509_crl_t *this, certificate_t *cert,
709 private_key_t *key, hash_algorithm_t digest_alg)
710 {
711 chunk_t extensions = chunk_empty, certList = chunk_empty, serial;
712 chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty;
713 enumerator_t *enumerator;
714 crl_reason_t reason;
715 time_t date;
716 x509_t *x509;
717
718 x509 = (x509_t*)cert;
719
720 this->issuer = cert->get_subject(cert);
721 this->issuer = this->issuer->clone(this->issuer);
722
723 this->authKeyIdentifier = chunk_clone(x509->get_subjectKeyIdentifier(x509));
724
725 /* select signature scheme */
726 this->algorithm = hasher_signature_algorithm_to_oid(digest_alg,
727 key->get_type(key));
728 if (this->algorithm == OID_UNKNOWN)
729 {
730 return FALSE;
731 }
732
733 enumerator = create_enumerator(this);
734 while (enumerator->enumerate(enumerator, &serial, &date, &reason))
735 {
736 chunk_t revoked, entry_ext = chunk_empty;
737
738 if (reason != CRL_REASON_UNSPECIFIED)
739 {
740 entry_ext = asn1_wrap(ASN1_SEQUENCE, "m",
741 asn1_wrap(ASN1_SEQUENCE, "mm",
742 asn1_build_known_oid(OID_CRL_REASON_CODE),
743 asn1_wrap(ASN1_OCTET_STRING, "m",
744 asn1_wrap(ASN1_ENUMERATED, "c",
745 chunk_from_chars(reason)))));
746 }
747 revoked = asn1_wrap(ASN1_SEQUENCE, "mmm",
748 asn1_integer("c", serial),
749 asn1_from_time(&date, ASN1_UTCTIME),
750 entry_ext);
751 certList = chunk_cat("mm", certList, revoked);
752 }
753 enumerator->destroy(enumerator);
754
755 crlDistributionPoints = x509_build_crlDistributionPoints(this->crl_uris,
756 OID_FRESHEST_CRL);
757
758 if (this->baseCrlNumber.len)
759 {
760 baseCrlNumber = asn1_wrap(ASN1_SEQUENCE, "mmm",
761 asn1_build_known_oid(OID_DELTA_CRL_INDICATOR),
762 asn1_wrap(ASN1_BOOLEAN, "c",
763 chunk_from_chars(0xFF)),
764 asn1_wrap(ASN1_OCTET_STRING, "m",
765 asn1_integer("c", this->baseCrlNumber)));
766 }
767
768 extensions = asn1_wrap(ASN1_CONTEXT_C_0, "m",
769 asn1_wrap(ASN1_SEQUENCE, "mmmm",
770 asn1_wrap(ASN1_SEQUENCE, "mm",
771 asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
772 asn1_wrap(ASN1_OCTET_STRING, "m",
773 asn1_wrap(ASN1_SEQUENCE, "m",
774 asn1_wrap(ASN1_CONTEXT_S_0, "c",
775 this->authKeyIdentifier)))),
776 asn1_wrap(ASN1_SEQUENCE, "mm",
777 asn1_build_known_oid(OID_CRL_NUMBER),
778 asn1_wrap(ASN1_OCTET_STRING, "m",
779 asn1_integer("c", this->crlNumber))),
780 crlDistributionPoints, baseCrlNumber));
781
782 this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cmcmmmm",
783 ASN1_INTEGER_1,
784 asn1_algorithmIdentifier(this->algorithm),
785 this->issuer->get_encoding(this->issuer),
786 asn1_from_time(&this->thisUpdate, ASN1_UTCTIME),
787 asn1_from_time(&this->nextUpdate, ASN1_UTCTIME),
788 asn1_wrap(ASN1_SEQUENCE, "m", certList),
789 extensions);
790
791 if (!key->sign(key, signature_scheme_from_oid(this->algorithm),
792 this->tbsCertList, &this->signature))
793 {
794 return FALSE;
795 }
796 this->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
797 this->tbsCertList,
798 asn1_algorithmIdentifier(this->algorithm),
799 asn1_bitstring("c", this->signature));
800 return TRUE;
801 }
802
803 /**
804 * See header.
805 */
806 x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args)
807 {
808 hash_algorithm_t digest_alg = HASH_SHA1;
809 private_x509_crl_t *crl;
810 certificate_t *cert = NULL;
811 private_key_t *key = NULL;
812
813 crl = create_empty();
814 crl->generated = TRUE;
815 while (TRUE)
816 {
817 builder_part_t part = va_arg(args, builder_part_t);
818
819 switch (part)
820 {
821 case BUILD_SIGNING_KEY:
822 key = va_arg(args, private_key_t*);
823 continue;
824 case BUILD_SIGNING_CERT:
825 cert = va_arg(args, certificate_t*);
826 continue;
827 case BUILD_NOT_BEFORE_TIME:
828 crl->thisUpdate = va_arg(args, time_t);
829 continue;
830 case BUILD_NOT_AFTER_TIME:
831 crl->nextUpdate = va_arg(args, time_t);
832 continue;
833 case BUILD_SERIAL:
834 crl->crlNumber = va_arg(args, chunk_t);
835 crl->crlNumber = chunk_clone(crl->crlNumber);
836 continue;
837 case BUILD_DIGEST_ALG:
838 digest_alg = va_arg(args, int);
839 continue;
840 case BUILD_REVOKED_ENUMERATOR:
841 read_revoked(crl, va_arg(args, enumerator_t*));
842 continue;
843 case BUILD_BASE_CRL:
844 crl->baseCrlNumber = va_arg(args, chunk_t);
845 crl->baseCrlNumber = chunk_clone(crl->baseCrlNumber);
846 break;
847 case BUILD_CRL_DISTRIBUTION_POINTS:
848 {
849 enumerator_t *enumerator;
850 linked_list_t *list;
851 x509_cdp_t *in, *cdp;
852
853 list = va_arg(args, linked_list_t*);
854 enumerator = list->create_enumerator(list);
855 while (enumerator->enumerate(enumerator, &in))
856 {
857 INIT(cdp,
858 .uri = strdup(in->uri),
859 .issuer = in->issuer ? in->issuer->clone(in->issuer) : NULL,
860 );
861 crl->crl_uris->insert_last(crl->crl_uris, cdp);
862 }
863 enumerator->destroy(enumerator);
864 continue;
865 }
866 case BUILD_END:
867 break;
868 default:
869 destroy(crl);
870 return NULL;
871 }
872 break;
873 }
874
875 if (key && cert && cert->get_type(cert) == CERT_X509 &&
876 generate(crl, cert, key, digest_alg))
877 {
878 return &crl->public;
879 }
880 destroy(crl);
881 return NULL;
882 }