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