x509: Skip parsing of acert chargingIdentity, as we don't use it anyway
[strongswan.git] / src / libstrongswan / plugins / x509 / x509_ac.c
1 /*
2 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
3 * Copyright (C) 2003 Martin Berner, Lukas Suter
4 * Copyright (C) 2002-2009 Andreas Steffen
5 * Copyright (C) 2009 Martin Willi
6 *
7 * HSR Hochschule fuer Technik Rapperswil
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * for more details.
18 */
19
20 #include "x509_ac.h"
21
22 #include <time.h>
23
24 #include <library.h>
25 #include <utils/debug.h>
26 #include <asn1/oid.h>
27 #include <asn1/asn1.h>
28 #include <asn1/asn1_parser.h>
29 #include <utils/identification.h>
30 #include <collections/linked_list.h>
31 #include <credentials/certificates/x509.h>
32 #include <credentials/ietf_attributes/ietf_attributes.h>
33 #include <credentials/keys/private_key.h>
34
35 extern chunk_t x509_parse_authorityKeyIdentifier(chunk_t blob,
36 int level0, chunk_t *authKeySerialNumber);
37
38 typedef struct private_x509_ac_t private_x509_ac_t;
39
40 /**
41 * private data of x509_ac_t object
42 */
43 struct private_x509_ac_t {
44
45 /**
46 * public functions
47 */
48 x509_ac_t public;
49
50 /**
51 * X.509 attribute certificate encoding in ASN.1 DER format
52 */
53 chunk_t encoding;
54
55 /**
56 * X.509 attribute certificate body over which signature is computed
57 */
58 chunk_t certificateInfo;
59
60 /**
61 * Version of the X.509 attribute certificate
62 */
63 u_int version;
64
65 /**
66 * Serial number of the X.509 attribute certificate
67 */
68 chunk_t serialNumber;
69
70 /**
71 * ID representing the issuer of the holder certificate
72 */
73 identification_t *holderIssuer;
74
75 /**
76 * Serial number of the holder certificate
77 */
78 chunk_t holderSerial;
79
80 /**
81 * ID representing the holder
82 */
83 identification_t *entityName;
84
85 /**
86 * ID representing the attribute certificate issuer
87 */
88 identification_t *issuerName;
89
90 /**
91 * Start time of certificate validity
92 */
93 time_t notBefore;
94
95 /**
96 * End time of certificate validity
97 */
98 time_t notAfter;
99
100 /**
101 * List of groub attributes
102 */
103 ietf_attributes_t *groups;
104
105 /**
106 * Authority Key Identifier
107 */
108 chunk_t authKeyIdentifier;
109
110 /**
111 * Authority Key Serial Number
112 */
113 chunk_t authKeySerialNumber;
114
115 /**
116 * No revocation information available
117 */
118 bool noRevAvail;
119
120 /**
121 * Signature algorithm
122 */
123 int algorithm;
124
125 /**
126 * Signature
127 */
128 chunk_t signature;
129
130 /**
131 * Holder certificate
132 */
133 certificate_t *holderCert;
134
135 /**
136 * Signer certificate
137 */
138 certificate_t *signerCert;
139
140 /**
141 * Signer private key;
142 */
143 private_key_t *signerKey;
144
145 /**
146 * reference count
147 */
148 refcount_t ref;
149 };
150
151 static chunk_t ASN1_noRevAvail_ext = chunk_from_chars(
152 0x30, 0x09,
153 0x06, 0x03,
154 0x55, 0x1d, 0x38,
155 0x04, 0x02,
156 0x05, 0x00
157 );
158
159 /**
160 * declaration of function implemented in x509_cert.c
161 */
162 extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
163 linked_list_t *list);
164 /**
165 * parses a directoryName
166 */
167 static bool parse_directoryName(chunk_t blob, int level, bool implicit,
168 identification_t **name)
169 {
170 identification_t *directoryName;
171 enumerator_t *enumerator;
172 bool first = TRUE;
173 linked_list_t *list;
174
175 list = linked_list_create();
176 x509_parse_generalNames(blob, level, implicit, list);
177
178 enumerator = list->create_enumerator(list);
179 while (enumerator->enumerate(enumerator, &directoryName))
180 {
181 if (first)
182 {
183 *name = directoryName;
184 first = FALSE;
185 }
186 else
187 {
188 DBG1(DBG_ASN, "more than one directory name - first selected");
189 directoryName->destroy(directoryName);
190 break;
191 }
192 }
193 enumerator->destroy(enumerator);
194 list->destroy(list);
195
196 if (first)
197 {
198 DBG1(DBG_ASN, "no directoryName found");
199 return FALSE;
200 }
201 return TRUE;
202 }
203
204 /**
205 * ASN.1 definition of roleSyntax
206 */
207 static const asn1Object_t roleSyntaxObjects[] =
208 {
209 { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
210 { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
211 ASN1_OBJ }, /* 1 */
212 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
213 { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */
214 { 0, "exit", ASN1_EOC, ASN1_EXIT }
215 };
216
217 /**
218 * Parses roleSyntax
219 */
220 static void parse_roleSyntax(chunk_t blob, int level0)
221 {
222 asn1_parser_t *parser;
223 chunk_t object;
224 int objectID;
225
226 parser = asn1_parser_create(roleSyntaxObjects, blob);
227 parser->set_top_level(parser, level0);
228
229 while (parser->iterate(parser, &objectID, &object))
230 {
231 switch (objectID)
232 {
233 default:
234 break;
235 }
236 }
237 parser->destroy(parser);
238 }
239
240 /**
241 * ASN.1 definition of an X509 attribute certificate
242 */
243 static const asn1Object_t acObjects[] =
244 {
245 { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
246 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
247 { 2, "version", ASN1_INTEGER, ASN1_DEF |
248 ASN1_BODY }, /* 2 */
249 { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
250 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
251 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
252 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
253 { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
254 ASN1_BODY }, /* 7 */
255 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
256 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
257 { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
258 ASN1_OBJ }, /* 10 */
259 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
260 { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
261 { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
262 { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
263 ASN1_BODY }, /* 14 */
264 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
265 { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
266 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
267 { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
268 { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
269 ASN1_OBJ }, /* 19 */
270 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
271 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
272 { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
273 { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
274 { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
275 { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
276 ASN1_BODY }, /* 25 */
277 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
278 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
279 { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
280 { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
281 { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
282 { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
283 ASN1_BODY }, /* 31 */
284 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
285 { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
286 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
287 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
288 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
289 { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
290 { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
291 { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
292 { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
293 { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
294 { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
295 { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
296 { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
297 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
298 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
299 { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
300 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
301 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
302 { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
303 ASN1_BODY }, /* 50 */
304 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
305 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
306 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
307 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */
308 { 0, "exit", ASN1_EOC, ASN1_EXIT }
309 };
310 #define AC_OBJ_CERTIFICATE_INFO 1
311 #define AC_OBJ_VERSION 2
312 #define AC_OBJ_HOLDER_ISSUER 5
313 #define AC_OBJ_HOLDER_SERIAL 6
314 #define AC_OBJ_ENTITY_NAME 10
315 #define AC_OBJ_ISSUER_NAME 19
316 #define AC_OBJ_ISSUER 23
317 #define AC_OBJ_SIG_ALG 35
318 #define AC_OBJ_SERIAL_NUMBER 36
319 #define AC_OBJ_NOT_BEFORE 38
320 #define AC_OBJ_NOT_AFTER 39
321 #define AC_OBJ_ATTRIBUTE_TYPE 42
322 #define AC_OBJ_ATTRIBUTE_VALUE 44
323 #define AC_OBJ_EXTN_ID 49
324 #define AC_OBJ_CRITICAL 50
325 #define AC_OBJ_EXTN_VALUE 51
326 #define AC_OBJ_ALGORITHM 53
327 #define AC_OBJ_SIGNATURE 54
328
329 /**
330 * Parses an X.509 attribute certificate
331 */
332 static bool parse_certificate(private_x509_ac_t *this)
333 {
334 asn1_parser_t *parser;
335 chunk_t object;
336 int objectID;
337 int type = OID_UNKNOWN;
338 int extn_oid = OID_UNKNOWN;
339 int sig_alg = OID_UNKNOWN;
340 bool success = FALSE;
341 bool critical;
342
343 parser = asn1_parser_create(acObjects, this->encoding);
344
345 while (parser->iterate(parser, &objectID, &object))
346 {
347 u_int level = parser->get_level(parser)+1;
348
349 switch (objectID)
350 {
351 case AC_OBJ_CERTIFICATE_INFO:
352 this->certificateInfo = object;
353 break;
354 case AC_OBJ_VERSION:
355 this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
356 DBG2(DBG_ASN, " v%d", this->version);
357 if (this->version != 2)
358 {
359 DBG1(DBG_ASN, "v%d attribute certificates are not "
360 "supported", this->version);
361 goto end;
362 }
363 break;
364 case AC_OBJ_HOLDER_ISSUER:
365 if (!parse_directoryName(object, level, FALSE,
366 &this->holderIssuer))
367 {
368 goto end;
369 }
370 break;
371 case AC_OBJ_HOLDER_SERIAL:
372 this->holderSerial = object;
373 break;
374 case AC_OBJ_ENTITY_NAME:
375 if (!parse_directoryName(object, level, TRUE,
376 &this->entityName))
377 {
378 goto end;
379 }
380 break;
381 case AC_OBJ_ISSUER_NAME:
382 if (!parse_directoryName(object, level, FALSE,
383 &this->issuerName))
384 {
385 goto end;
386 }
387 break;
388 case AC_OBJ_SIG_ALG:
389 sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
390 break;
391 case AC_OBJ_SERIAL_NUMBER:
392 this->serialNumber = chunk_clone(object);
393 break;
394 case AC_OBJ_NOT_BEFORE:
395 this->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
396 break;
397 case AC_OBJ_NOT_AFTER:
398 this->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
399 break;
400 case AC_OBJ_ATTRIBUTE_TYPE:
401 type = asn1_known_oid(object);
402 break;
403 case AC_OBJ_ATTRIBUTE_VALUE:
404 {
405 switch (type)
406 {
407 case OID_AUTHENTICATION_INFO:
408 DBG2(DBG_ASN, " need to parse authenticationInfo");
409 break;
410 case OID_ACCESS_IDENTITY:
411 DBG2(DBG_ASN, " need to parse accessIdentity");
412 break;
413 case OID_CHARGING_IDENTITY:
414 DBG2(DBG_ASN, " need to parse chargingIdentity");
415 break;
416 case OID_GROUP:
417 DBG2(DBG_ASN, "-- > --");
418 this->groups = ietf_attributes_create_from_encoding(object);
419 DBG2(DBG_ASN, "-- < --");
420 break;
421 case OID_ROLE:
422 parse_roleSyntax(object, level);
423 break;
424 default:
425 break;
426 }
427 break;
428 }
429 case AC_OBJ_EXTN_ID:
430 extn_oid = asn1_known_oid(object);
431 break;
432 case AC_OBJ_CRITICAL:
433 critical = object.len && *object.ptr;
434 DBG2(DBG_ASN, " %s",(critical)?"TRUE":"FALSE");
435 break;
436 case AC_OBJ_EXTN_VALUE:
437 {
438 switch (extn_oid)
439 {
440 case OID_CRL_DISTRIBUTION_POINTS:
441 DBG2(DBG_ASN, " need to parse crlDistributionPoints");
442 break;
443 case OID_AUTHORITY_KEY_ID:
444 this->authKeyIdentifier =
445 x509_parse_authorityKeyIdentifier(object,
446 level, &this->authKeySerialNumber);
447 break;
448 case OID_TARGET_INFORMATION:
449 DBG2(DBG_ASN, " need to parse targetInformation");
450 break;
451 case OID_NO_REV_AVAIL:
452 this->noRevAvail = TRUE;
453 break;
454 default:
455 break;
456 }
457 break;
458 }
459 case AC_OBJ_ALGORITHM:
460 this->algorithm = asn1_parse_algorithmIdentifier(object, level,
461 NULL);
462 if (this->algorithm != sig_alg)
463 {
464 DBG1(DBG_ASN, " signature algorithms do not agree");
465 success = FALSE;
466 goto end;
467 }
468 break;
469 case AC_OBJ_SIGNATURE:
470 this->signature = object;
471 break;
472 default:
473 break;
474 }
475 }
476 success = parser->success(parser);
477
478 end:
479 parser->destroy(parser);
480 return success;
481 }
482
483 /**
484 * build directoryName
485 */
486 static chunk_t build_directoryName(asn1_t tag, chunk_t name)
487 {
488 return asn1_wrap(tag, "m",
489 asn1_simple_object(ASN1_CONTEXT_C_4, name));
490 }
491
492 /**
493 * build holder
494 */
495 static chunk_t build_holder(private_x509_ac_t *this)
496 {
497 x509_t* x509 = (x509_t*)this->holderCert;
498 identification_t *issuer, *subject;
499
500 issuer = this->holderCert->get_issuer(this->holderCert);
501 subject = this->holderCert->get_subject(this->holderCert);
502
503 return asn1_wrap(ASN1_SEQUENCE, "mm",
504 asn1_wrap(ASN1_CONTEXT_C_0, "mm",
505 build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)),
506 asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))),
507 build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
508 }
509
510 /**
511 * build v2Form
512 */
513 static chunk_t build_v2_form(private_x509_ac_t *this)
514 {
515 identification_t *subject;
516
517 subject = this->signerCert->get_subject(this->signerCert);
518 return asn1_wrap(ASN1_CONTEXT_C_0, "m",
519 build_directoryName(ASN1_SEQUENCE,
520 subject->get_encoding(subject)));
521 }
522
523 /**
524 * build attrCertValidityPeriod
525 */
526 static chunk_t build_attr_cert_validity(private_x509_ac_t *this)
527 {
528 return asn1_wrap(ASN1_SEQUENCE, "mm",
529 asn1_from_time(&this->notBefore, ASN1_GENERALIZEDTIME),
530 asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME));
531 }
532
533 /**
534 * build attribute type
535 */
536 static chunk_t build_attribute_type(int type, chunk_t content)
537 {
538 return asn1_wrap(ASN1_SEQUENCE, "mm",
539 asn1_build_known_oid(type),
540 asn1_wrap(ASN1_SET, "m", content));
541 }
542
543 /**
544 * build attributes
545 */
546 static chunk_t build_attributes(private_x509_ac_t *this)
547 {
548 return asn1_wrap(ASN1_SEQUENCE, "m",
549 build_attribute_type(OID_GROUP,
550 this->groups->get_encoding(this->groups)));
551 }
552
553 /**
554 * build authorityKeyIdentifier
555 */
556 static chunk_t build_authorityKeyIdentifier(private_x509_ac_t *this)
557 {
558 chunk_t keyIdentifier = chunk_empty;
559 chunk_t authorityCertIssuer;
560 chunk_t authorityCertSerialNumber;
561 identification_t *issuer;
562 public_key_t *public;
563 x509_t *x509;
564
565 x509 = (x509_t*)this->signerCert;
566 issuer = this->signerCert->get_issuer(this->signerCert);
567 public = this->signerCert->get_public_key(this->signerCert);
568 if (public)
569 {
570 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyIdentifier))
571 {
572 this->authKeyIdentifier = chunk_clone(keyIdentifier);
573 }
574 public->destroy(public);
575 }
576 authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
577 issuer->get_encoding(issuer));
578 authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
579 x509->get_serial(x509));
580 return asn1_wrap(ASN1_SEQUENCE, "mm",
581 asn1_build_known_oid(OID_AUTHORITY_KEY_ID),
582 asn1_wrap(ASN1_OCTET_STRING, "m",
583 asn1_wrap(ASN1_SEQUENCE, "cmm",
584 keyIdentifier,
585 authorityCertIssuer,
586 authorityCertSerialNumber
587 )
588 )
589 );
590 }
591
592 /**
593 * build extensions
594 */
595 static chunk_t build_extensions(private_x509_ac_t *this)
596 {
597 return asn1_wrap(ASN1_SEQUENCE, "mc",
598 build_authorityKeyIdentifier(this),
599 ASN1_noRevAvail_ext);
600 }
601
602 /**
603 * build attributeCertificateInfo
604 */
605 static chunk_t build_attr_cert_info(private_x509_ac_t *this)
606 {
607 return asn1_wrap(ASN1_SEQUENCE, "cmmmmmmm",
608 ASN1_INTEGER_1,
609 build_holder(this),
610 build_v2_form(this),
611 asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
612 asn1_simple_object(ASN1_INTEGER, this->serialNumber),
613 build_attr_cert_validity(this),
614 build_attributes(this),
615 build_extensions(this));
616 }
617
618 /**
619 * build an X.509 attribute certificate
620 */
621 static chunk_t build_ac(private_x509_ac_t *this)
622 {
623 chunk_t signatureValue, attributeCertificateInfo;
624
625 attributeCertificateInfo = build_attr_cert_info(this);
626 this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1,
627 attributeCertificateInfo, &signatureValue);
628 return asn1_wrap(ASN1_SEQUENCE, "mmm",
629 attributeCertificateInfo,
630 asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
631 asn1_bitstring("m", signatureValue));
632 }
633
634 METHOD(ac_t, get_serial, chunk_t,
635 private_x509_ac_t *this)
636 {
637 return this->serialNumber;
638 }
639
640 METHOD(ac_t, get_holderSerial, chunk_t,
641 private_x509_ac_t *this)
642 {
643 return this->holderSerial;
644 }
645
646 METHOD(ac_t, get_holderIssuer, identification_t*,
647 private_x509_ac_t *this)
648 {
649 return this->holderIssuer;
650 }
651
652 METHOD(ac_t, get_authKeyIdentifier, chunk_t,
653 private_x509_ac_t *this)
654 {
655 return this->authKeyIdentifier;
656 }
657
658 METHOD(ac_t, get_groups, ietf_attributes_t*,
659 private_x509_ac_t *this)
660 {
661 return this->groups ? this->groups->get_ref(this->groups) : NULL;
662 }
663
664 METHOD(certificate_t, get_type, certificate_type_t,
665 private_x509_ac_t *this)
666 {
667 return CERT_X509_AC;
668 }
669
670 METHOD(certificate_t, get_subject, identification_t*,
671 private_x509_ac_t *this)
672 {
673 return this->entityName;
674 }
675
676 METHOD(certificate_t, get_issuer, identification_t*,
677 private_x509_ac_t *this)
678 {
679 return this->issuerName;
680 }
681
682 METHOD(certificate_t, has_subject, id_match_t,
683 private_x509_ac_t *this, identification_t *subject)
684 {
685 return ID_MATCH_NONE;
686 }
687
688 METHOD(certificate_t, has_issuer, id_match_t,
689 private_x509_ac_t *this, identification_t *issuer)
690 {
691 if (issuer->get_type(issuer) == ID_KEY_ID &&
692 this->authKeyIdentifier.ptr &&
693 chunk_equals(this->authKeyIdentifier, issuer->get_encoding(issuer)))
694 {
695 return ID_MATCH_PERFECT;
696 }
697 return this->issuerName->matches(this->issuerName, issuer);
698 }
699
700 METHOD(certificate_t, issued_by, bool,
701 private_x509_ac_t *this, certificate_t *issuer, signature_scheme_t *schemep)
702 {
703 public_key_t *key;
704 signature_scheme_t scheme;
705 bool valid;
706 x509_t *x509 = (x509_t*)issuer;
707
708 /* check if issuer is an X.509 AA certificate */
709 if (issuer->get_type(issuer) != CERT_X509)
710 {
711 return FALSE;
712 }
713 if (!(x509->get_flags(x509) & X509_AA))
714 {
715 return FALSE;
716 }
717
718 /* get the public key of the issuer */
719 key = issuer->get_public_key(issuer);
720
721 /* compare keyIdentifiers if available, otherwise use DNs */
722 if (this->authKeyIdentifier.ptr && key)
723 {
724 chunk_t fingerprint;
725
726 if (!key->get_fingerprint(key, KEYID_PUBKEY_SHA1, &fingerprint) ||
727 !chunk_equals(fingerprint, this->authKeyIdentifier))
728 {
729 return FALSE;
730 }
731 }
732 else
733 {
734 if (!this->issuerName->equals(this->issuerName,
735 issuer->get_subject(issuer)))
736 {
737 return FALSE;
738 }
739 }
740
741 /* determine signature scheme */
742 scheme = signature_scheme_from_oid(this->algorithm);
743
744 if (scheme == SIGN_UNKNOWN || key == NULL)
745 {
746 return FALSE;
747 }
748 valid = key->verify(key, scheme, this->certificateInfo, this->signature);
749 key->destroy(key);
750 if (valid && schemep)
751 {
752 *schemep = scheme;
753 }
754 return valid;
755 }
756
757 METHOD(certificate_t, get_public_key, public_key_t*,
758 private_x509_ac_t *this)
759 {
760 return NULL;
761 }
762
763 METHOD(certificate_t, get_ref, certificate_t*,
764 private_x509_ac_t *this)
765 {
766 ref_get(&this->ref);
767 return &this->public.interface.certificate;
768 }
769
770 METHOD(certificate_t, get_validity, bool,
771 private_x509_ac_t *this, time_t *when, time_t *not_before, time_t *not_after)
772 {
773 time_t t = when ? *when : time(NULL);
774
775 if (not_before)
776 {
777 *not_before = this->notBefore;
778 }
779 if (not_after)
780 {
781 *not_after = this->notAfter;
782 }
783 return (t >= this->notBefore && t <= this->notAfter);
784 }
785
786 METHOD(certificate_t, get_encoding, bool,
787 private_x509_ac_t *this, cred_encoding_type_t type, chunk_t *encoding)
788 {
789 if (type == CERT_ASN1_DER)
790 {
791 *encoding = chunk_clone(this->encoding);
792 return TRUE;
793 }
794 return lib->encoding->encode(lib->encoding, type, NULL, encoding,
795 CRED_PART_X509_AC_ASN1_DER, this->encoding, CRED_PART_END);
796 }
797
798 METHOD(certificate_t, equals, bool,
799 private_x509_ac_t *this, certificate_t *other)
800 {
801 chunk_t encoding;
802 bool equal;
803
804 if ((certificate_t*)this == other)
805 {
806 return TRUE;
807 }
808 if (other->equals == _equals)
809 { /* skip allocation if we have the same implementation */
810 return chunk_equals(this->encoding,
811 ((private_x509_ac_t*)other)->encoding);
812 }
813 if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
814 {
815 return FALSE;
816 }
817 equal = chunk_equals(this->encoding, encoding);
818 free(encoding.ptr);
819 return equal;
820 }
821
822 METHOD(certificate_t, destroy, void,
823 private_x509_ac_t *this)
824 {
825 if (ref_put(&this->ref))
826 {
827 DESTROY_IF(this->holderIssuer);
828 DESTROY_IF(this->entityName);
829 DESTROY_IF(this->issuerName);
830 DESTROY_IF(this->holderCert);
831 DESTROY_IF(this->signerCert);
832 DESTROY_IF(this->signerKey);
833 DESTROY_IF(this->groups);
834 free(this->serialNumber.ptr);
835 free(this->authKeyIdentifier.ptr);
836 free(this->encoding.ptr);
837 free(this);
838 }
839 }
840
841 /**
842 * create an empty but initialized X.509 attribute certificate
843 */
844 static private_x509_ac_t *create_empty(void)
845 {
846 private_x509_ac_t *this;
847
848 INIT(this,
849 .public = {
850 .interface = {
851 .certificate = {
852 .get_type = _get_type,
853 .get_subject = _get_subject,
854 .get_issuer = _get_issuer,
855 .has_subject = _has_subject,
856 .has_issuer = _has_issuer,
857 .issued_by = _issued_by,
858 .get_public_key = _get_public_key,
859 .get_validity = _get_validity,
860 .get_encoding = _get_encoding,
861 .equals = _equals,
862 .get_ref = _get_ref,
863 .destroy = _destroy,
864 },
865 .get_serial = _get_serial,
866 .get_holderSerial = _get_holderSerial,
867 .get_holderIssuer = _get_holderIssuer,
868 .get_authKeyIdentifier = _get_authKeyIdentifier,
869 .get_groups = _get_groups,
870 },
871 },
872 .ref = 1,
873 );
874
875 return this;
876 }
877
878 /**
879 * See header.
880 */
881 x509_ac_t *x509_ac_load(certificate_type_t type, va_list args)
882 {
883 chunk_t blob = chunk_empty;
884
885 while (TRUE)
886 {
887 switch (va_arg(args, builder_part_t))
888 {
889 case BUILD_BLOB_ASN1_DER:
890 blob = va_arg(args, chunk_t);
891 continue;
892 case BUILD_END:
893 break;
894 default:
895 return NULL;
896 }
897 break;
898 }
899 if (blob.ptr)
900 {
901 private_x509_ac_t *ac = create_empty();
902
903 ac->encoding = chunk_clone(blob);
904 if (parse_certificate(ac))
905 {
906 return &ac->public;
907 }
908 destroy(ac);
909 }
910 return NULL;
911 }
912
913 /**
914 * See header.
915 */
916 x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args)
917 {
918 private_x509_ac_t *ac;
919
920 ac = create_empty();
921 while (TRUE)
922 {
923 switch (va_arg(args, builder_part_t))
924 {
925 case BUILD_NOT_BEFORE_TIME:
926 ac->notBefore = va_arg(args, time_t);
927 continue;
928 case BUILD_NOT_AFTER_TIME:
929 ac->notAfter = va_arg(args, time_t);
930 continue;
931 case BUILD_SERIAL:
932 ac->serialNumber = chunk_clone(va_arg(args, chunk_t));
933 continue;
934 case BUILD_IETF_GROUP_ATTR:
935 ac->groups = ietf_attributes_create_from_string(va_arg(args, char*));
936 continue;
937 case BUILD_CERT:
938 ac->holderCert = va_arg(args, certificate_t*);
939 ac->holderCert->get_ref(ac->holderCert);
940 continue;
941 case BUILD_SIGNING_CERT:
942 ac->signerCert = va_arg(args, certificate_t*);
943 ac->signerCert->get_ref(ac->signerCert);
944 continue;
945 case BUILD_SIGNING_KEY:
946 ac->signerKey = va_arg(args, private_key_t*);
947 ac->signerKey->get_ref(ac->signerKey);
948 continue;
949 case BUILD_END:
950 break;
951 default:
952 destroy(ac);
953 return NULL;
954 }
955 break;
956 }
957
958 if (ac->signerKey && ac->holderCert && ac->signerCert &&
959 ac->holderCert->get_type(ac->holderCert) == CERT_X509 &&
960 ac->signerCert->get_type(ac->signerCert) == CERT_X509)
961 {
962 ac->encoding = build_ac(ac);
963 return &ac->public;
964 }
965 destroy(ac);
966 return NULL;
967 }