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