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