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