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