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