d59b1530315494ce90c48c056ce64bf1026a8ef9
[strongswan.git] / src / libstrongswan / plugins / x509 / x509_crl.c
1 /*
2 * Copyright (C) 2008 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 * $Id$
16 */
17
18 #include "x509_crl.h"
19
20 typedef struct private_x509_crl_t private_x509_crl_t;
21 typedef struct revoked_t revoked_t;
22
23 #include <debug.h>
24 #include <library.h>
25 #include <asn1/asn1.h>
26 #include <asn1/pem.h>
27 #include <credentials/certificates/x509.h>
28 #include <utils/linked_list.h>
29
30 /**
31 * entry for a revoked certificate
32 */
33 struct revoked_t {
34 /**
35 * serial of the revoked certificate
36 */
37 chunk_t serial;
38
39 /**
40 * date of revocation
41 */
42 time_t date;
43
44 /**
45 * reason for revocation
46 */
47 crl_reason_t reason;
48 };
49
50 /**
51 * private data of x509_crl
52 */
53 struct private_x509_crl_t {
54
55 /**
56 * public functions
57 */
58 x509_crl_t public;
59
60 /**
61 * X.509 crl encoding in ASN.1 DER format
62 */
63 chunk_t encoding;
64
65 /**
66 * X.509 crl body over which signature is computed
67 */
68 chunk_t tbsCertList;
69
70 /**
71 * Version of the X.509 crl
72 */
73 u_int version;
74
75 /**
76 * ID representing the crl issuer
77 */
78 identification_t *issuer;
79
80 /**
81 * CRL number
82 */
83 chunk_t crlNumber;
84
85 /**
86 * Time when the crl was generated
87 */
88 time_t thisUpdate;
89
90 /**
91 * Time when an update crl will be available
92 */
93 time_t nextUpdate;
94
95 /**
96 * list of revoked certificates as revoked_t
97 */
98 linked_list_t *revoked;
99
100 /**
101 * Authority Key Identifier
102 */
103 identification_t *authKeyIdentifier;
104
105 /**
106 * Authority Key Serial Number
107 */
108 chunk_t authKeySerialNumber;
109
110 /**
111 * Signature algorithm
112 */
113 int algorithm;
114
115 /**
116 * Signature
117 */
118 chunk_t signature;
119
120 /**
121 * reference counter
122 */
123 refcount_t ref;
124 };
125
126 /**
127 * from x509_cert
128 */
129 extern identification_t* x509_parse_authorityKeyIdentifier(
130 chunk_t blob, int level0,
131 chunk_t *authKeySerialNumber);
132
133 /**
134 * ASN.1 definition of an X.509 certificate revocation list
135 */
136 static const asn1Object_t crlObjects[] = {
137 { 0, "certificateList", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
138 { 1, "tbsCertList", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
139 { 2, "version", ASN1_INTEGER, ASN1_OPT |
140 ASN1_BODY }, /* 2 */
141 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 3 */
142 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 4 */
143 { 2, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
144 { 2, "thisUpdate", ASN1_EOC, ASN1_RAW }, /* 6 */
145 { 2, "nextUpdate", ASN1_EOC, ASN1_RAW }, /* 7 */
146 { 2, "revokedCertificates", ASN1_SEQUENCE, ASN1_OPT |
147 ASN1_LOOP }, /* 8 */
148 { 3, "certList", ASN1_SEQUENCE, ASN1_NONE }, /* 9 */
149 { 4, "userCertificate", ASN1_INTEGER, ASN1_BODY }, /* 10 */
150 { 4, "revocationDate", ASN1_EOC, ASN1_RAW }, /* 11 */
151 { 4, "crlEntryExtensions", ASN1_SEQUENCE, ASN1_OPT |
152 ASN1_LOOP }, /* 12 */
153 { 5, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 13 */
154 { 6, "extnID", ASN1_OID, ASN1_BODY }, /* 14 */
155 { 6, "critical", ASN1_BOOLEAN, ASN1_DEF |
156 ASN1_BODY }, /* 15 */
157 { 6, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 16 */
158 { 4, "end opt or loop", ASN1_EOC, ASN1_END }, /* 17 */
159 { 2, "end opt or loop", ASN1_EOC, ASN1_END }, /* 18 */
160 { 2, "optional extensions", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 19 */
161 { 3, "crlExtensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 20 */
162 { 4, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 21 */
163 { 5, "extnID", ASN1_OID, ASN1_BODY }, /* 22 */
164 { 5, "critical", ASN1_BOOLEAN, ASN1_DEF |
165 ASN1_BODY }, /* 23 */
166 { 5, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 24 */
167 { 3, "end loop", ASN1_EOC, ASN1_END }, /* 25 */
168 { 2, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
169 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 27 */
170 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 28 */
171 };
172
173 #define CRL_OBJ_TBS_CERT_LIST 1
174 #define CRL_OBJ_VERSION 2
175 #define CRL_OBJ_SIG_ALG 4
176 #define CRL_OBJ_ISSUER 5
177 #define CRL_OBJ_THIS_UPDATE 6
178 #define CRL_OBJ_NEXT_UPDATE 7
179 #define CRL_OBJ_USER_CERTIFICATE 10
180 #define CRL_OBJ_REVOCATION_DATE 11
181 #define CRL_OBJ_CRL_ENTRY_EXTN_ID 14
182 #define CRL_OBJ_CRL_ENTRY_CRITICAL 15
183 #define CRL_OBJ_CRL_ENTRY_EXTN_VALUE 16
184 #define CRL_OBJ_EXTN_ID 22
185 #define CRL_OBJ_CRITICAL 23
186 #define CRL_OBJ_EXTN_VALUE 24
187 #define CRL_OBJ_ALGORITHM 27
188 #define CRL_OBJ_SIGNATURE 28
189 #define CRL_OBJ_ROOF 29
190
191 /**
192 * Parses an X.509 Certificate Revocation List (CRL)
193 */
194 static bool parse(private_x509_crl_t *this)
195 {
196 asn1_ctx_t ctx;
197 bool critical;
198 chunk_t extnID;
199 chunk_t userCertificate = chunk_empty;
200 revoked_t *revoked = NULL;
201 chunk_t object;
202 u_int level;
203 int sig_alg = OID_UNKNOWN;
204 int objectID = 0;
205
206 asn1_init(&ctx, this->encoding, 0, FALSE, FALSE);
207 while (objectID < CRL_OBJ_ROOF)
208 {
209 if (!extract_object(crlObjects, &objectID, &object, &level, &ctx))
210 {
211 return FALSE;
212 }
213
214 /* those objects which will parsed further need the next higher level */
215 level++;
216
217 switch (objectID)
218 {
219 case CRL_OBJ_TBS_CERT_LIST:
220 this->tbsCertList = object;
221 break;
222 case CRL_OBJ_VERSION:
223 this->version = (object.len) ? (1+(u_int)*object.ptr) : 1;
224 DBG2(" v%d", this->version);
225 break;
226 case CRL_OBJ_SIG_ALG:
227 sig_alg = parse_algorithmIdentifier(object, level, NULL);
228 break;
229 case CRL_OBJ_ISSUER:
230 this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object);
231 DBG2(" '%D'", this->issuer);
232 break;
233 case CRL_OBJ_THIS_UPDATE:
234 this->thisUpdate = parse_time(object, level);
235 break;
236 case CRL_OBJ_NEXT_UPDATE:
237 this->nextUpdate = parse_time(object, level);
238 break;
239 case CRL_OBJ_USER_CERTIFICATE:
240 userCertificate = object;
241 break;
242 case CRL_OBJ_REVOCATION_DATE:
243 revoked = malloc_thing(revoked_t);
244 revoked->serial = userCertificate;
245 revoked->date = parse_time(object, level);
246 revoked->reason = CRL_UNSPECIFIED;
247 this->revoked->insert_last(this->revoked, (void *)revoked);
248 break;
249 case CRL_OBJ_CRL_ENTRY_EXTN_ID:
250 case CRL_OBJ_EXTN_ID:
251 extnID = object;
252 break;
253 case CRL_OBJ_CRL_ENTRY_CRITICAL:
254 case CRL_OBJ_CRITICAL:
255 critical = object.len && *object.ptr;
256 DBG2(" %s", critical ? "TRUE" : "FALSE");
257 break;
258 case CRL_OBJ_CRL_ENTRY_EXTN_VALUE:
259 case CRL_OBJ_EXTN_VALUE:
260 {
261 int extn_oid = known_oid(extnID);
262
263 if (revoked && extn_oid == OID_CRL_REASON_CODE)
264 {
265 if (*object.ptr == ASN1_ENUMERATED &&
266 asn1_length(&object) == 1)
267 {
268 revoked->reason = *object.ptr;
269 }
270 DBG2(" '%N'", crl_reason_names, revoked->reason);
271 }
272 else if (extn_oid == OID_AUTHORITY_KEY_ID)
273 {
274
275 this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
276 level, &this->authKeySerialNumber);
277 }
278 else if (extn_oid == OID_CRL_NUMBER)
279 {
280 if (!parse_asn1_simple_object(&object, ASN1_INTEGER,
281 level, "crlNumber"))
282 {
283 return FALSE;
284 }
285 this->crlNumber = object;
286 }
287 }
288 break;
289 case CRL_OBJ_ALGORITHM:
290 {
291 this->algorithm = parse_algorithmIdentifier(object, level, NULL);
292 if (this->algorithm != sig_alg)
293 {
294 DBG1(" signature algorithms do not agree");
295 return FALSE;
296 }
297 break;
298 }
299 case CRL_OBJ_SIGNATURE:
300 this->signature = object;
301 break;
302 default:
303 break;
304 }
305 objectID++;
306 }
307 return TRUE;
308 }
309
310 /**
311 * enumerator filter callback for create_enumerator
312 */
313 static bool filter(void *data, revoked_t **revoked, chunk_t *serial, void *p2,
314 time_t *date, void *p3, crl_reason_t *reason)
315 {
316 if (serial)
317 {
318 *serial = (*revoked)->serial;
319 }
320 if (date)
321 {
322 *date = (*revoked)->date;
323 }
324 if (reason)
325 {
326 *reason = (*revoked)->reason;
327 }
328 return TRUE;
329 }
330
331 /**
332 * Implementation of crl_t.get_serial.
333 */
334 static chunk_t get_serial(private_x509_crl_t *this)
335 {
336 return this->crlNumber;
337 }
338
339 /**
340 * Implementation of crl_t.get_authKeyIdentifier.
341 */
342 static identification_t* get_authKeyIdentifier(private_x509_crl_t *this)
343 {
344 return this->authKeyIdentifier;
345 }
346 /**
347 * Implementation of crl_t.create_enumerator.
348 */
349 static enumerator_t* create_enumerator(private_x509_crl_t *this)
350 {
351 return enumerator_create_filter(
352 this->revoked->create_enumerator(this->revoked),
353 (void*)filter, NULL, NULL);
354 }
355
356 /**
357 * Implementation of certificate_t.get_type
358 */
359 static certificate_type_t get_type(private_x509_crl_t *this)
360 {
361 return CERT_X509_CRL;
362 }
363
364 /**
365 * Implementation of certificate_t.get_subject
366 */
367 static identification_t* get_subject(private_x509_crl_t *this)
368 {
369 return this->issuer;
370 }
371
372 /**
373 * Implementation of certificate_t.get_issuer
374 */
375 static identification_t* get_issuer(private_x509_crl_t *this)
376 {
377 return this->issuer;
378 }
379
380 /**
381 * Implementation of certificate_t.has_subject.
382 */
383 static id_match_t has_subject(private_x509_crl_t *this, identification_t *subject)
384 {
385 return ID_MATCH_NONE;
386 }
387
388 /**
389 * Implementation of certificate_t.has_issuer.
390 */
391 static id_match_t has_issuer(private_x509_crl_t *this, identification_t *issuer)
392 {
393 id_match_t match;
394
395 if (issuer->get_type(issuer) == ID_PUBKEY_SHA1)
396 {
397 if (this->authKeyIdentifier)
398 {
399 match = issuer->matches(issuer, this->authKeyIdentifier);
400 }
401 else
402 {
403 match = ID_MATCH_NONE;
404 }
405 }
406 else
407 {
408 match = this->issuer->matches(this->issuer, issuer);
409 }
410 return match;
411 }
412
413 /**
414 * Implementation of certificate_t.issued_by
415 */
416 static bool issued_by(private_x509_crl_t *this, certificate_t *issuer,
417 bool sigcheck)
418 {
419 public_key_t *key;
420 signature_scheme_t scheme;
421 bool valid;
422 x509_t *x509 = (x509_t*)issuer;
423
424 /* check if issuer is an X.509 CA certificate */
425 if (issuer->get_type(issuer) != CERT_X509)
426 {
427 return FALSE;
428 }
429 if (!(x509->get_flags(x509) & X509_CA))
430 {
431 return FALSE;
432 }
433
434 /* get the public key of the issuer */
435 key = issuer->get_public_key(issuer);
436
437 /* compare keyIdentifiers if available, otherwise use DNs */
438 if (this->authKeyIdentifier && key)
439 {
440 identification_t *subjectKeyIdentifier = key->get_id(key, ID_PUBKEY_SHA1);
441
442 if (!subjectKeyIdentifier->equals(subjectKeyIdentifier,
443 this->authKeyIdentifier))
444 {
445 return FALSE;
446 }
447 }
448 else
449 {
450 if (!this->issuer->equals(this->issuer, issuer->get_subject(issuer)))
451 {
452 return FALSE;
453 }
454 }
455
456 if (!sigcheck)
457 {
458 return TRUE;
459 }
460 /* TODO: generic OID to scheme mapper? */
461 switch (this->algorithm)
462 {
463 case OID_MD5_WITH_RSA:
464 scheme = SIGN_RSA_EMSA_PKCS1_MD5;
465 break;
466 case OID_SHA1_WITH_RSA:
467 scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
468 break;
469 case OID_SHA256_WITH_RSA:
470 scheme = SIGN_RSA_EMSA_PKCS1_SHA256;
471 break;
472 case OID_SHA384_WITH_RSA:
473 scheme = SIGN_RSA_EMSA_PKCS1_SHA384;
474 break;
475 case OID_SHA512_WITH_RSA:
476 scheme = SIGN_RSA_EMSA_PKCS1_SHA512;
477 break;
478 default:
479 return FALSE;
480 }
481 if (key == NULL)
482 {
483 return FALSE;
484 }
485 valid = key->verify(key, scheme, this->tbsCertList, this->signature);
486 key->destroy(key);
487 return valid;
488 }
489
490 /**
491 * Implementation of certificate_t.get_public_key
492 */
493 static public_key_t* get_public_key(private_x509_crl_t *this)
494 {
495 return NULL;
496 }
497
498 /**
499 * Implementation of certificate_t.asdf
500 */
501 static private_x509_crl_t* get_ref(private_x509_crl_t *this)
502 {
503 ref_get(&this->ref);
504 return this;
505 }
506
507 /**
508 * Implementation of certificate_t.get_validity.
509 */
510 static bool get_validity(private_x509_crl_t *this, time_t *when,
511 time_t *not_before, time_t *not_after)
512 {
513 time_t t;
514
515 if (when)
516 {
517 t = *when;
518 }
519 else
520 {
521 t = time(NULL);
522 }
523 if (not_before)
524 {
525 *not_before = this->thisUpdate;
526 }
527 if (not_after)
528 {
529 *not_after = this->nextUpdate;
530 }
531 return (t <= this->nextUpdate);
532 }
533
534 /**
535 * Implementation of certificate_t.is_newer.
536 */
537 static bool is_newer(private_x509_crl_t *this, crl_t *that)
538 {
539 chunk_t that_crlNumber = that->get_serial(that);
540 bool new;
541
542 /* compare crlNumbers if available - otherwise use thisUpdate */
543 if (this->crlNumber.ptr != NULL && that_crlNumber.ptr != NULL)
544 {
545 new = chunk_compare(this->crlNumber, that_crlNumber) > 0;
546 DBG1(" crl #%#B is %s - existing crl #%#B %s",
547 &this->crlNumber, new ? "newer":"not newer",
548 &that_crlNumber, new ? "replaced":"retained");
549 }
550 else
551 {
552 certificate_t *this_cert = &this->public.crl.certificate;
553 certificate_t *that_cert = &that->certificate;
554
555 time_t this_update, that_update, now = time(NULL);
556
557 this_cert->get_validity(this_cert, &now, &this_update, NULL);
558 that_cert->get_validity(that_cert, &now, &that_update, NULL);
559 new = this_update > that_update;
560 DBG1(" crl from %#T is %s - existing crl from %#T %s",
561 &this_update, FALSE, new ? "newer":"not newer",
562 &that_update, FALSE, new ? "replaced":"retained");
563 }
564 return new;
565 }
566
567 /**
568 * Implementation of certificate_t.get_encoding.
569 */
570 static chunk_t get_encoding(private_x509_crl_t *this)
571 {
572 return chunk_clone(this->encoding);
573 }
574
575 /**
576 * Implementation of certificate_t.equals.
577 */
578 static bool equals(private_x509_crl_t *this, certificate_t *other)
579 {
580 if ((certificate_t*)this == other)
581 {
582 return TRUE;
583 }
584 if (other->equals == (void*)equals)
585 { /* same implementation */
586 return chunk_equals(this->signature,
587 ((private_x509_crl_t*)other)->signature);
588 }
589 /* TODO: compare against other implementations */
590 return FALSE;
591 }
592
593 /**
594 * Implementation of certificate_t.destroy
595 */
596 static void destroy(private_x509_crl_t *this)
597 {
598 if (ref_put(&this->ref))
599 {
600 this->revoked->destroy_function(this->revoked, free);
601 DESTROY_IF(this->issuer);
602 DESTROY_IF(this->authKeyIdentifier);
603 free(this->encoding.ptr);
604 free(this);
605 }
606 }
607
608 /**
609 * create an empty but initialized X.509 crl
610 */
611 static private_x509_crl_t* create_empty(void)
612 {
613 private_x509_crl_t *this = malloc_thing(private_x509_crl_t);
614
615 this->public.crl.get_serial = (chunk_t (*)(crl_t*))get_serial;
616 this->public.crl.get_authKeyIdentifier = (identification_t* (*)(crl_t*))get_authKeyIdentifier;
617 this->public.crl.create_enumerator = (enumerator_t* (*)(crl_t*))create_enumerator;
618 this->public.crl.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
619 this->public.crl.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
620 this->public.crl.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
621 this->public.crl.certificate.has_subject = (id_match_t (*)(certificate_t*, identification_t *subject))has_subject;
622 this->public.crl.certificate.has_issuer = (id_match_t (*)(certificate_t*, identification_t *issuer))has_issuer;
623 this->public.crl.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer,bool))issued_by;
624 this->public.crl.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
625 this->public.crl.certificate.get_validity = (bool (*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
626 this->public.crl.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
627 this->public.crl.certificate.get_encoding = (chunk_t (*)(certificate_t*))get_encoding;
628 this->public.crl.certificate.equals = (bool (*)(certificate_t*, certificate_t *other))equals;
629 this->public.crl.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
630 this->public.crl.certificate.destroy = (void (*)(certificate_t *this))destroy;
631
632 this->encoding = chunk_empty;
633 this->tbsCertList = chunk_empty;
634 this->issuer = NULL;
635 this->crlNumber = chunk_empty;
636 this->revoked = linked_list_create();
637 this->authKeyIdentifier = NULL;
638 this->authKeySerialNumber = chunk_empty;
639 this->ref = 1;
640
641 return this;
642 }
643
644 /**
645 * create an X.509 crl from a chunk
646 */
647 static private_x509_crl_t* create_from_chunk(chunk_t chunk)
648 {
649 private_x509_crl_t *this = create_empty();
650
651 this->encoding = chunk;
652 if (!parse(this))
653 {
654 destroy(this);
655 return NULL;
656 }
657 return this;
658 }
659
660 /**
661 * create an X.509 crl from a file
662 */
663 static private_x509_crl_t* create_from_file(char *path)
664 {
665 bool pgp = FALSE;
666 chunk_t chunk;
667 private_x509_crl_t *this;
668
669 if (!pem_asn1_load_file(path, NULL, &chunk, &pgp))
670 {
671 return NULL;
672 }
673
674 this = create_from_chunk(chunk);
675
676 if (this == NULL)
677 {
678 DBG1(" could not parse loaded crl file '%s'",path);
679 return NULL;
680 }
681 DBG1(" loaded crl file '%s'", path);
682 return this;
683 }
684
685 typedef struct private_builder_t private_builder_t;
686 /**
687 * Builder implementation for certificate loading
688 */
689 struct private_builder_t {
690 /** implements the builder interface */
691 builder_t public;
692 /** loaded CRL */
693 private_x509_crl_t *crl;
694 };
695
696 /**
697 * Implementation of builder_t.build
698 */
699 static private_x509_crl_t *build(private_builder_t *this)
700 {
701 private_x509_crl_t *crl = this->crl;
702
703 free(this);
704 return crl;
705 }
706
707 /**
708 * Implementation of builder_t.add
709 */
710 static void add(private_builder_t *this, builder_part_t part, ...)
711 {
712 va_list args;
713
714 if (this->crl)
715 {
716 DBG1("ignoring surplus build part %N", builder_part_names, part);
717 return;
718 }
719
720 va_start(args, part);
721 switch (part)
722 {
723 case BUILD_FROM_FILE:
724 this->crl = create_from_file(va_arg(args, char*));
725 break;
726 case BUILD_BLOB_ASN1_DER:
727 {
728 this->crl = create_from_chunk(va_arg(args, chunk_t));
729 break;
730 }
731 default:
732 DBG1("ignoring unsupported build part %N", builder_part_names, part);
733 break;
734 }
735 va_end(args);
736 }
737
738 /**
739 * Builder construction function
740 */
741 builder_t *x509_crl_builder(certificate_type_t type)
742 {
743 private_builder_t *this;
744
745 if (type != CERT_X509_CRL)
746 {
747 return NULL;
748 }
749
750 this = malloc_thing(private_builder_t);
751
752 this->crl = NULL;
753 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
754 this->public.build = (void*(*)(builder_t *this))build;
755
756 return &this->public;
757 }
758