hide credentials headers in credential_factory.h
[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-2008 Andreas Steffen
5 *
6 * Hochschule fuer Technik Rapperswil
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
17 */
18
19 #include "x509_ac.h"
20 #include "ietf_attr_list.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 <asn1/pem.h>
30 #include <utils/identification.h>
31 #include <utils/linked_list.h>
32 #include <credentials/certificates/x509.h>
33 #include <credentials/keys/private_key.h>
34
35 extern identification_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 linked_list_t *charging;
104
105 /**
106 * List of groub attributes
107 */
108 linked_list_t *groups;
109
110 /**
111 * Authority Key Identifier
112 */
113 identification_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 u_char ASN1_group_oid_str[] = {
157 0x06, 0x08,
158 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a ,0x04
159 };
160
161 static const chunk_t ASN1_group_oid = chunk_from_buf(ASN1_group_oid_str);
162
163 static u_char ASN1_authorityKeyIdentifier_oid_str[] = {
164 0x06, 0x03,
165 0x55, 0x1d, 0x23
166 };
167
168 static const chunk_t ASN1_authorityKeyIdentifier_oid =
169 chunk_from_buf(ASN1_authorityKeyIdentifier_oid_str);
170
171 static u_char ASN1_noRevAvail_ext_str[] = {
172 0x30, 0x09,
173 0x06, 0x03,
174 0x55, 0x1d, 0x38,
175 0x04, 0x02,
176 0x05, 0x00
177 };
178
179 static const chunk_t ASN1_noRevAvail_ext = chunk_from_buf(ASN1_noRevAvail_ext_str);
180
181 /**
182 * declaration of function implemented in x509_cert.c
183 */
184 extern void x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
185 linked_list_t *list);
186 /**
187 * parses a directoryName
188 */
189 static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name)
190 {
191 bool has_directoryName;
192 linked_list_t *list = linked_list_create();
193
194 x509_parse_generalNames(blob, level, implicit, list);
195 has_directoryName = list->get_count(list) > 0;
196
197 if (has_directoryName)
198 {
199 iterator_t *iterator = list->create_iterator(list, TRUE);
200 identification_t *directoryName;
201 bool first = TRUE;
202
203 while (iterator->iterate(iterator, (void**)&directoryName))
204 {
205 if (first)
206 {
207 *name = directoryName;
208 first = FALSE;
209 }
210 else
211 {
212 DBG1("more than one directory name - first selected");
213 directoryName->destroy(directoryName);
214 }
215 }
216 iterator->destroy(iterator);
217 }
218 else
219 {
220 DBG1("no directoryName found");
221 }
222
223 list->destroy(list);
224 return has_directoryName;
225 }
226
227 /**
228 * ASN.1 definition of roleSyntax
229 */
230 static const asn1Object_t roleSyntaxObjects[] =
231 {
232 { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
233 { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
234 ASN1_OBJ }, /* 1 */
235 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
236 { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ }, /* 3 */
237 { 0, "exit", ASN1_EOC, ASN1_EXIT }
238 };
239
240 /**
241 * Parses roleSyntax
242 */
243 static void parse_roleSyntax(chunk_t blob, int level0)
244 {
245 asn1_parser_t *parser;
246 chunk_t object;
247 int objectID;
248
249 parser = asn1_parser_create(roleSyntaxObjects, blob);
250 parser->set_top_level(parser, level0);
251
252 while (parser->iterate(parser, &objectID, &object))
253 {
254 switch (objectID)
255 {
256 default:
257 break;
258 }
259 }
260 parser->destroy(parser);
261 }
262
263 /**
264 * ASN.1 definition of an X509 attribute certificate
265 */
266 static const asn1Object_t acObjects[] =
267 {
268 { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
269 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
270 { 2, "version", ASN1_INTEGER, ASN1_DEF |
271 ASN1_BODY }, /* 2 */
272 { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
273 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
274 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
275 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
276 { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
277 ASN1_BODY }, /* 7 */
278 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
279 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
280 { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
281 ASN1_OBJ }, /* 10 */
282 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
283 { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
284 { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13 */
285 { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
286 ASN1_BODY }, /* 14 */
287 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15 */
288 { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
289 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
290 { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
291 { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
292 ASN1_OBJ }, /* 19 */
293 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
294 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
295 { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
296 { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
297 { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
298 { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
299 ASN1_BODY }, /* 25 */
300 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
301 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
302 { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
303 { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
304 { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
305 { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
306 ASN1_BODY }, /* 31 */
307 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
308 { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
309 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
310 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
311 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
312 { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
313 { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
314 { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
315 { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
316 { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
317 { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
318 { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
319 { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
320 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
321 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
322 { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
323 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
324 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
325 { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
326 ASN1_BODY }, /* 50 */
327 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
328 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
329 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
330 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY }, /* 54 */
331 { 0, "exit", ASN1_EOC, ASN1_EXIT }
332 };
333 #define AC_OBJ_CERTIFICATE_INFO 1
334 #define AC_OBJ_VERSION 2
335 #define AC_OBJ_HOLDER_ISSUER 5
336 #define AC_OBJ_HOLDER_SERIAL 6
337 #define AC_OBJ_ENTITY_NAME 10
338 #define AC_OBJ_ISSUER_NAME 19
339 #define AC_OBJ_ISSUER 23
340 #define AC_OBJ_SIG_ALG 35
341 #define AC_OBJ_SERIAL_NUMBER 36
342 #define AC_OBJ_NOT_BEFORE 38
343 #define AC_OBJ_NOT_AFTER 39
344 #define AC_OBJ_ATTRIBUTE_TYPE 42
345 #define AC_OBJ_ATTRIBUTE_VALUE 44
346 #define AC_OBJ_EXTN_ID 49
347 #define AC_OBJ_CRITICAL 50
348 #define AC_OBJ_EXTN_VALUE 51
349 #define AC_OBJ_ALGORITHM 53
350 #define AC_OBJ_SIGNATURE 54
351
352 /**
353 * Parses an X.509 attribute certificate
354 */
355 static bool parse_certificate(private_x509_ac_t *this)
356 {
357 asn1_parser_t *parser;
358 chunk_t object;
359 int objectID;
360 int type = OID_UNKNOWN;
361 int extn_oid = OID_UNKNOWN;
362 int sig_alg = OID_UNKNOWN;
363 bool success = FALSE;
364 bool critical;
365
366 parser = asn1_parser_create(acObjects, this->encoding);
367
368 while (parser->iterate(parser, &objectID, &object))
369 {
370 u_int level = parser->get_level(parser)+1;
371
372 switch (objectID)
373 {
374 case AC_OBJ_CERTIFICATE_INFO:
375 this->certificateInfo = object;
376 break;
377 case AC_OBJ_VERSION:
378 this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
379 DBG2(" v%d", this->version);
380 if (this->version != 2)
381 {
382 DBG1("v%d attribute certificates are not supported", this->version);
383 goto end;
384 }
385 break;
386 case AC_OBJ_HOLDER_ISSUER:
387 if (!parse_directoryName(object, level, FALSE, &this->holderIssuer))
388 {
389 goto end;
390 }
391 break;
392 case AC_OBJ_HOLDER_SERIAL:
393 this->holderSerial = object;
394 break;
395 case AC_OBJ_ENTITY_NAME:
396 if (!parse_directoryName(object, level, TRUE, &this->entityName))
397 {
398 goto end;
399 }
400 break;
401 case AC_OBJ_ISSUER_NAME:
402 if (!parse_directoryName(object, level, FALSE, &this->issuerName))
403 {
404 goto end;
405 }
406 break;
407 case AC_OBJ_SIG_ALG:
408 sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL);
409 break;
410 case AC_OBJ_SERIAL_NUMBER:
411 this->serialNumber = chunk_clone(object);
412 break;
413 case AC_OBJ_NOT_BEFORE:
414 this->notBefore = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
415 break;
416 case AC_OBJ_NOT_AFTER:
417 this->notAfter = asn1_to_time(&object, ASN1_GENERALIZEDTIME);
418 break;
419 case AC_OBJ_ATTRIBUTE_TYPE:
420 type = asn1_known_oid(object);
421 break;
422 case AC_OBJ_ATTRIBUTE_VALUE:
423 {
424 switch (type)
425 {
426 case OID_AUTHENTICATION_INFO:
427 DBG2(" need to parse authenticationInfo");
428 break;
429 case OID_ACCESS_IDENTITY:
430 DBG2(" need to parse accessIdentity");
431 break;
432 case OID_CHARGING_IDENTITY:
433 ietfAttr_list_create_from_chunk(object, this->charging, level);
434 break;
435 case OID_GROUP:
436 ietfAttr_list_create_from_chunk(object, this->groups, level);
437 break;
438 case OID_ROLE:
439 parse_roleSyntax(object, level);
440 break;
441 default:
442 break;
443 }
444 break;
445 }
446 case AC_OBJ_EXTN_ID:
447 extn_oid = asn1_known_oid(object);
448 break;
449 case AC_OBJ_CRITICAL:
450 critical = object.len && *object.ptr;
451 DBG2(" %s",(critical)?"TRUE":"FALSE");
452 break;
453 case AC_OBJ_EXTN_VALUE:
454 {
455 switch (extn_oid)
456 {
457 case OID_CRL_DISTRIBUTION_POINTS:
458 DBG2(" need to parse crlDistributionPoints");
459 break;
460 case OID_AUTHORITY_KEY_ID:
461 this->authKeyIdentifier = x509_parse_authorityKeyIdentifier(object,
462 level, &this->authKeySerialNumber);
463 break;
464 case OID_TARGET_INFORMATION:
465 DBG2(" need to parse targetInformation");
466 break;
467 case OID_NO_REV_AVAIL:
468 this->noRevAvail = TRUE;
469 break;
470 default:
471 break;
472 }
473 break;
474 }
475 case AC_OBJ_ALGORITHM:
476 this->algorithm = asn1_parse_algorithmIdentifier(object, level,
477 NULL);
478 if (this->algorithm != sig_alg)
479 {
480 DBG1(" signature algorithms do not agree");
481 success = FALSE;
482 goto end;
483 }
484 break;
485 case AC_OBJ_SIGNATURE:
486 this->signature = object;
487 break;
488 default:
489 break;
490 }
491 }
492 success = parser->success(parser);
493
494 end:
495 parser->destroy(parser);
496 return success;
497 }
498
499 /**
500 * build directoryName
501 */
502 static chunk_t build_directoryName(asn1_t tag, chunk_t name)
503 {
504 return asn1_wrap(tag, "m",
505 asn1_simple_object(ASN1_CONTEXT_C_4, name));
506 }
507
508 /**
509 * build holder
510 */
511 static chunk_t build_holder(private_x509_ac_t *this)
512 {
513 x509_t* x509 = (x509_t*)this->holderCert;
514 identification_t *issuer = this->holderCert->get_issuer(this->holderCert);
515 identification_t *subject = this->holderCert->get_subject(this->holderCert);
516
517 return asn1_wrap(ASN1_SEQUENCE, "mm",
518 asn1_wrap(ASN1_CONTEXT_C_0, "mm",
519 build_directoryName(ASN1_SEQUENCE, issuer->get_encoding(issuer)),
520 asn1_simple_object(ASN1_INTEGER, x509->get_serial(x509))
521 ),
522 build_directoryName(ASN1_CONTEXT_C_1, subject->get_encoding(subject)));
523 }
524
525 /**
526 * build v2Form
527 */
528 static chunk_t build_v2_form(private_x509_ac_t *this)
529 {
530 identification_t *subject = this->signerCert->get_subject(this->signerCert);
531
532 return asn1_wrap(ASN1_CONTEXT_C_0, "m",
533 build_directoryName(ASN1_SEQUENCE, subject->get_encoding(subject)));
534 }
535
536 /**
537 * build attrCertValidityPeriod
538 */
539 static chunk_t build_attr_cert_validity(private_x509_ac_t *this)
540 {
541 return asn1_wrap(ASN1_SEQUENCE, "mm",
542 asn1_from_time(&this->notBefore, ASN1_GENERALIZEDTIME),
543 asn1_from_time(&this->notAfter, ASN1_GENERALIZEDTIME));
544 }
545
546
547 /**
548 * build attribute type
549 */
550 static chunk_t build_attribute_type(const chunk_t type, chunk_t content)
551 {
552 return asn1_wrap(ASN1_SEQUENCE, "cm",
553 type,
554 asn1_wrap(ASN1_SET, "m", content));
555 }
556
557 /**
558 * build attributes
559 */
560 static chunk_t build_attributes(private_x509_ac_t *this)
561 {
562 return asn1_wrap(ASN1_SEQUENCE, "m",
563 build_attribute_type(ASN1_group_oid, ietfAttr_list_encode(this->groups)));
564 }
565
566 /**
567 * build authorityKeyIdentifier
568 */
569 static chunk_t build_authorityKeyIdentifier(private_x509_ac_t *this)
570 {
571 chunk_t keyIdentifier;
572 chunk_t authorityCertIssuer;
573 chunk_t authorityCertSerialNumber;
574 x509_t *x509 = (x509_t*)this->signerCert;
575 identification_t *issuer = this->signerCert->get_issuer(this->signerCert);
576 public_key_t *public = this->signerCert->get_public_key(this->signerCert);
577
578 if (public)
579 {
580 identification_t *keyid = public->get_id(public, ID_PUBKEY_SHA1);
581
582 this->authKeyIdentifier = keyid = keyid->clone(keyid);
583 keyIdentifier = keyid->get_encoding(keyid);
584 public->destroy(public);
585 }
586 else
587 {
588 keyIdentifier = chunk_empty;
589 }
590 authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
591 issuer->get_encoding(issuer));
592 authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
593 x509->get_serial(x509));
594 return asn1_wrap(ASN1_SEQUENCE, "cm",
595 ASN1_authorityKeyIdentifier_oid,
596 asn1_wrap(ASN1_OCTET_STRING, "m",
597 asn1_wrap(ASN1_SEQUENCE, "cmm",
598 keyIdentifier,
599 authorityCertIssuer,
600 authorityCertSerialNumber
601 )
602 )
603 );
604 }
605
606 /**
607 * build extensions
608 */
609 static chunk_t build_extensions(private_x509_ac_t *this)
610 {
611 return asn1_wrap(ASN1_SEQUENCE, "mc",
612 build_authorityKeyIdentifier(this),
613 ASN1_noRevAvail_ext);
614 }
615
616 /**
617 * build attributeCertificateInfo
618 */
619 static chunk_t build_attr_cert_info(private_x509_ac_t *this)
620 {
621 return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm",
622 ASN1_INTEGER_1,
623 build_holder(this),
624 build_v2_form(this),
625 asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
626 asn1_simple_object(ASN1_INTEGER, this->serialNumber),
627 build_attr_cert_validity(this),
628 build_attributes(this),
629 build_extensions(this));
630 }
631
632
633 /**
634 * build an X.509 attribute certificate
635 */
636 static chunk_t build_ac(private_x509_ac_t *this)
637 {
638 chunk_t signatureValue;
639 chunk_t attributeCertificateInfo;
640
641 attributeCertificateInfo = build_attr_cert_info(this);
642
643 this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1,
644 attributeCertificateInfo, &signatureValue);
645
646 return asn1_wrap(ASN1_SEQUENCE, "mcm",
647 attributeCertificateInfo,
648 asn1_algorithmIdentifier(OID_SHA1_WITH_RSA),
649 asn1_bitstring("m", signatureValue));
650 }
651
652 /**
653 * Implementation of ac_t.get_serial.
654 */
655 static chunk_t get_serial(private_x509_ac_t *this)
656 {
657 return this->serialNumber;
658 }
659
660 /**
661 * Implementation of ac_t.get_holderSerial.
662 */
663 static chunk_t get_holderSerial(private_x509_ac_t *this)
664 {
665 return this->holderSerial;
666 }
667
668 /**
669 * Implementation of ac_t.get_holderIssuer.
670 */
671 static identification_t* get_holderIssuer(private_x509_ac_t *this)
672 {
673 return this->holderIssuer;
674 }
675
676 /**
677 * Implementation of ac_t.get_authKeyIdentifier.
678 */
679 static identification_t* get_authKeyIdentifier(private_x509_ac_t *this)
680 {
681 return this->authKeyIdentifier;
682 }
683
684 /**
685 * Implementation of certificate_t.get_type
686 */
687 static certificate_type_t get_type(private_x509_ac_t *this)
688 {
689 return CERT_X509_AC;
690 }
691
692 /**
693 * Implementation of certificate_t.get_subject
694 */
695 static identification_t* get_subject(private_x509_ac_t *this)
696 {
697 return this->entityName;
698 }
699
700 /**
701 * Implementation of certificate_t.get_issuer
702 */
703 static identification_t* get_issuer(private_x509_ac_t *this)
704 {
705 return this->issuerName;
706 }
707
708 /**
709 * Implementation of certificate_t.has_subject.
710 */
711 static id_match_t has_subject(private_x509_ac_t *this, identification_t *subject)
712 {
713 return ID_MATCH_NONE;
714 }
715
716 /**
717 * Implementation of certificate_t.has_issuer.
718 */
719 static id_match_t has_issuer(private_x509_ac_t *this, identification_t *issuer)
720 {
721 id_match_t match;
722
723 if (issuer->get_type(issuer) == ID_PUBKEY_SHA1)
724 {
725 if (this->authKeyIdentifier)
726 {
727 match = issuer->matches(issuer, this->authKeyIdentifier);
728 }
729 else
730 {
731 match = ID_MATCH_NONE;
732 }
733 }
734 else
735 {
736 match = this->issuerName->matches(this->issuerName, issuer);
737 }
738 return match;
739 }
740
741 /**
742 * Implementation of certificate_t.issued_by
743 */
744 static bool issued_by(private_x509_ac_t *this, certificate_t *issuer)
745 {
746 public_key_t *key;
747 signature_scheme_t scheme;
748 bool valid;
749 x509_t *x509 = (x509_t*)issuer;
750
751 /* check if issuer is an X.509 AA certificate */
752 if (issuer->get_type(issuer) != CERT_X509)
753 {
754 return FALSE;
755 }
756 if (!(x509->get_flags(x509) & X509_AA))
757 {
758 return FALSE;
759 }
760
761 /* get the public key of the issuer */
762 key = issuer->get_public_key(issuer);
763
764 /* compare keyIdentifiers if available, otherwise use DNs */
765 if (this->authKeyIdentifier && key)
766 {
767 identification_t *subjectKeyIdentifier = key->get_id(key, ID_PUBKEY_SHA1);
768
769 if (!subjectKeyIdentifier->equals(subjectKeyIdentifier,
770 this->authKeyIdentifier))
771 {
772 return FALSE;
773 }
774 }
775 else
776 {
777 if (!this->issuerName->equals(this->issuerName, issuer->get_subject(issuer)))
778 {
779 return FALSE;
780 }
781 }
782 /* TODO: generic OID to scheme mapper? */
783 switch (this->algorithm)
784 {
785 case OID_MD5_WITH_RSA:
786 scheme = SIGN_RSA_EMSA_PKCS1_MD5;
787 break;
788 case OID_SHA1_WITH_RSA:
789 scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
790 break;
791 case OID_SHA256_WITH_RSA:
792 scheme = SIGN_RSA_EMSA_PKCS1_SHA256;
793 break;
794 case OID_SHA384_WITH_RSA:
795 scheme = SIGN_RSA_EMSA_PKCS1_SHA384;
796 break;
797 case OID_SHA512_WITH_RSA:
798 scheme = SIGN_RSA_EMSA_PKCS1_SHA512;
799 break;
800 case OID_ECDSA_WITH_SHA1:
801 scheme = SIGN_ECDSA_WITH_SHA1;
802 break;
803 default:
804 return FALSE;
805 }
806 if (key == NULL)
807 {
808 return FALSE;
809 }
810 valid = key->verify(key, scheme, this->certificateInfo, this->signature);
811 key->destroy(key);
812 return valid;
813 }
814
815 /**
816 * Implementation of certificate_t.get_public_key.
817 */
818 static public_key_t* get_public_key(private_x509_ac_t *this)
819 {
820 return NULL;
821 }
822
823 /**
824 * Implementation of certificate_t.get_ref.
825 */
826 static private_x509_ac_t* get_ref(private_x509_ac_t *this)
827 {
828 ref_get(&this->ref);
829 return this;
830 }
831
832 /**
833 * Implementation of certificate_t.get_validity.
834 */
835 static bool get_validity(private_x509_ac_t *this, time_t *when,
836 time_t *not_before, time_t *not_after)
837 {
838 time_t t;
839
840 if (when)
841 {
842 t = *when;
843 }
844 else
845 {
846 t = time(NULL);
847 }
848 if (not_before)
849 {
850 *not_before = this->notBefore;
851 }
852 if (not_after)
853 {
854 *not_after = this->notAfter;
855 }
856 return (t >= this->notBefore && t <= this->notAfter);
857 }
858
859 /**
860 * Implementation of certificate_t.is_newer.
861 */
862 static bool is_newer(private_x509_ac_t *this, ac_t *that)
863 {
864 certificate_t *this_cert = &this->public.interface.certificate;
865 certificate_t *that_cert = &that->certificate;
866 time_t this_update, that_update, now = time(NULL);
867 bool new;
868
869 this_cert->get_validity(this_cert, &now, &this_update, NULL);
870 that_cert->get_validity(that_cert, &now, &that_update, NULL);
871 new = this_update > that_update;
872 DBG1(" attr cert from %T is %s - existing attr_cert from %T %s",
873 &this_update, FALSE, new ? "newer":"not newer",
874 &that_update, FALSE, new ? "replaced":"retained");
875 return new;
876 }
877
878 /**
879 * Implementation of certificate_t.get_encoding.
880 */
881 static chunk_t get_encoding(private_x509_ac_t *this)
882 {
883 return chunk_clone(this->encoding);
884 }
885
886 /**
887 * Implementation of certificate_t.equals.
888 */
889 static bool equals(private_x509_ac_t *this, certificate_t *other)
890 {
891 chunk_t encoding;
892 bool equal;
893
894 if ((certificate_t*)this == other)
895 {
896 return TRUE;
897 }
898 if (other->equals == (void*)equals)
899 { /* skip allocation if we have the same implementation */
900 return chunk_equals(this->encoding, ((private_x509_ac_t*)other)->encoding);
901 }
902 encoding = other->get_encoding(other);
903 equal = chunk_equals(this->encoding, encoding);
904 free(encoding.ptr);
905 return equal;
906 }
907
908 /**
909 * Implementation of x509_ac_t.destroy
910 */
911 static void destroy(private_x509_ac_t *this)
912 {
913 if (ref_put(&this->ref))
914 {
915 DESTROY_IF(this->holderIssuer);
916 DESTROY_IF(this->entityName);
917 DESTROY_IF(this->issuerName);
918 DESTROY_IF(this->authKeyIdentifier);
919 DESTROY_IF(this->holderCert);
920 DESTROY_IF(this->signerCert);
921 DESTROY_IF(this->signerKey);
922
923 ietfAttr_list_destroy(this->charging);
924 ietfAttr_list_destroy(this->groups);
925 free(this->serialNumber.ptr);
926 free(this->encoding.ptr);
927 free(this);
928 }
929 }
930
931 /**
932 * create an empty but initialized X.509 attribute certificate
933 */
934 static private_x509_ac_t *create_empty(void)
935 {
936 private_x509_ac_t *this = malloc_thing(private_x509_ac_t);
937
938 /* public functions */
939 this->public.interface.get_serial = (chunk_t (*)(ac_t*))get_serial;
940 this->public.interface.get_holderSerial = (chunk_t (*)(ac_t*))get_holderSerial;
941 this->public.interface.get_holderIssuer = (identification_t* (*)(ac_t*))get_holderIssuer;
942 this->public.interface.get_authKeyIdentifier = (identification_t* (*)(ac_t*))get_authKeyIdentifier;
943 this->public.interface.certificate.get_type = (certificate_type_t (*)(certificate_t *this))get_type;
944 this->public.interface.certificate.get_subject = (identification_t* (*)(certificate_t *this))get_subject;
945 this->public.interface.certificate.get_issuer = (identification_t* (*)(certificate_t *this))get_issuer;
946 this->public.interface.certificate.has_subject = (id_match_t(*)(certificate_t*, identification_t *subject))has_subject;
947 this->public.interface.certificate.has_issuer = (id_match_t(*)(certificate_t*, identification_t *issuer))has_issuer;
948 this->public.interface.certificate.issued_by = (bool (*)(certificate_t *this, certificate_t *issuer))issued_by;
949 this->public.interface.certificate.get_public_key = (public_key_t* (*)(certificate_t *this))get_public_key;
950 this->public.interface.certificate.get_validity = (bool(*)(certificate_t*, time_t *when, time_t *, time_t*))get_validity;
951 this->public.interface.certificate.is_newer = (bool (*)(certificate_t*,certificate_t*))is_newer;
952 this->public.interface.certificate.get_encoding = (chunk_t(*)(certificate_t*))get_encoding;
953 this->public.interface.certificate.equals = (bool(*)(certificate_t*, certificate_t *other))equals;
954 this->public.interface.certificate.get_ref = (certificate_t* (*)(certificate_t *this))get_ref;
955 this->public.interface.certificate.destroy = (void (*)(certificate_t *this))destroy;
956
957 /* initialize */
958 this->encoding = chunk_empty;
959 this->serialNumber = chunk_empty;
960 this->holderSerial = chunk_empty;
961 this->holderIssuer = NULL;
962 this->entityName = NULL;
963 this->issuerName = NULL;
964 this->authKeyIdentifier = NULL;
965 this->holderCert = NULL;
966 this->signerCert = NULL;
967 this->signerKey = NULL;
968 this->charging = linked_list_create();
969 this->groups = linked_list_create();
970 this->ref = 1;
971
972 return this;
973 }
974
975 /**
976 * create X.509 attribute certificate from a chunk
977 */
978 static private_x509_ac_t* create_from_chunk(chunk_t chunk)
979 {
980 private_x509_ac_t *this = create_empty();
981
982 this->encoding = chunk;
983 if (!parse_certificate(this))
984 {
985 destroy(this);
986 return NULL;
987 }
988 return this;
989 }
990
991 /**
992 * create X.509 crl from a file
993 */
994 static private_x509_ac_t* create_from_file(char *path)
995 {
996 bool pgp = FALSE;
997 chunk_t chunk;
998 private_x509_ac_t *this;
999
1000 if (!pem_asn1_load_file(path, NULL, &chunk, &pgp))
1001 {
1002 return NULL;
1003 }
1004
1005 this = create_from_chunk(chunk);
1006
1007 if (this == NULL)
1008 {
1009 DBG1(" could not parse loaded attribute certificate file '%s'", path);
1010 return NULL;
1011 }
1012 DBG1(" loaded attribute certificate file '%s'", path);
1013 return this;
1014 }
1015
1016 typedef struct private_builder_t private_builder_t;
1017 /**
1018 * Builder implementation for certificate loading
1019 */
1020 struct private_builder_t {
1021 /** implements the builder interface */
1022 builder_t public;
1023 /** X.509 attribute certificate to build */
1024 private_x509_ac_t *ac;
1025 };
1026
1027 /**
1028 * Implementation of builder_t.build
1029 */
1030 static private_x509_ac_t* build(private_builder_t *this)
1031 {
1032 private_x509_ac_t *ac = this->ac;
1033
1034 free(this);
1035
1036 /* synthesis if encoding does not exist */
1037 if (ac && ac->encoding.ptr == NULL)
1038 {
1039 if (ac->holderCert && ac->signerCert && ac->signerKey)
1040 {
1041 ac->encoding = build_ac(ac);
1042 return ac;
1043 }
1044 destroy(ac);
1045 return NULL;
1046 }
1047 else
1048 {
1049 return ac;
1050 }
1051 }
1052
1053 /**
1054 * Implementation of builder_t.add
1055 */
1056 static void add(private_builder_t *this, builder_part_t part, ...)
1057 {
1058 va_list args;
1059 certificate_t *cert;
1060 chunk_t chunk;
1061
1062 va_start(args, part);
1063 switch (part)
1064 {
1065 case BUILD_FROM_FILE:
1066 if (this->ac)
1067 {
1068 destroy(this->ac);
1069 }
1070 this->ac = create_from_file(va_arg(args, char*));
1071 break;
1072 case BUILD_BLOB_ASN1_DER:
1073 if (this->ac)
1074 {
1075 destroy(this->ac);
1076 }
1077 chunk = va_arg(args, chunk_t);
1078 this->ac = create_from_chunk(chunk_clone(chunk));
1079 break;
1080 case BUILD_NOT_BEFORE_TIME:
1081 this->ac->notBefore = va_arg(args, time_t);
1082 break;
1083 case BUILD_NOT_AFTER_TIME:
1084 this->ac->notAfter = va_arg(args, time_t);
1085 break;
1086 case BUILD_SERIAL:
1087 chunk = va_arg(args, chunk_t);
1088 this->ac->serialNumber = chunk_clone(chunk);
1089 break;
1090 case BUILD_IETF_GROUP_ATTR:
1091 ietfAttr_list_create_from_string(va_arg(args, char*),
1092 this->ac->groups);
1093 break;
1094 case BUILD_CERT:
1095 cert = va_arg(args, certificate_t*);
1096 if (cert->get_type(cert) == CERT_X509)
1097 {
1098 this->ac->holderCert = cert->get_ref(cert);
1099 }
1100 break;
1101 case BUILD_SIGNING_CERT:
1102 cert = va_arg(args, certificate_t*);
1103 if (cert->get_type(cert) == CERT_X509)
1104 {
1105 this->ac->signerCert = cert->get_ref(cert);
1106 }
1107 break;
1108 case BUILD_SIGNING_KEY:
1109 this->ac->signerKey = va_arg(args, private_key_t*);
1110 this->ac->signerKey->get_ref(this->ac->signerKey);
1111 break;
1112 default:
1113 /* abort if unsupported option */
1114 if (this->ac)
1115 {
1116 destroy(this->ac);
1117 }
1118 builder_cancel(&this->public);
1119 break;
1120 }
1121 va_end(args);
1122 }
1123
1124 /**
1125 * Builder construction function
1126 */
1127 builder_t *x509_ac_builder(certificate_type_t type)
1128 {
1129 private_builder_t *this;
1130
1131 if (type != CERT_X509_AC)
1132 {
1133 return NULL;
1134 }
1135
1136 this = malloc_thing(private_builder_t);
1137
1138 this->ac = create_empty();
1139 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
1140 this->public.build = (void*(*)(builder_t *this))build;
1141
1142 return &this->public;
1143 }
1144