added parsing of charging and group attributes
[strongswan.git] / src / libstrongswan / crypto / ac.c
1 /**
2 * @file ac.c
3 *
4 * @brief Implementation of x509ac_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
10 * Copyright (C) 2003 Martin Berner, Lukas Suter
11 * Copyright (C) 2007 Andreas Steffen, Hochschule fuer Technik Rapperswil
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 *
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
22 */
23
24 #include <library.h>
25 #include <debug.h>
26
27 #include <asn1/asn1.h>
28 #include <utils/identification.h>
29 #include <utils/linked_list.h>
30
31 #include "ac.h"
32
33 typedef struct private_x509ac_t private_x509ac_t;
34
35 /**
36 * Private data of a x509ac_t object.
37 */
38 struct private_x509ac_t {
39 /**
40 * Public interface for this attribute certificate.
41 */
42 x509ac_t public;
43
44 /**
45 * Time when attribute certificate was installed
46 */
47 time_t installed;
48
49 /**
50 * X.509 attribute certificate in DER format
51 */
52 chunk_t certificate;
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 * Signature algorithm
91 */
92 int sigAlg;
93
94 /**
95 * Start time of certificate validity
96 */
97 time_t notBefore;
98
99 /**
100 * End time of certificate validity
101 */
102 time_t notAfter;
103
104 /**
105 * List of charging attributes
106 */
107 linked_list_t *charging;
108
109 /**
110 * List of groub attributes
111 */
112 linked_list_t *groups;
113
114 /**
115 * Authority Key Identifier
116 */
117 chunk_t authKeyID;
118
119 /**
120 * Authority Key Serial Number
121 */
122 chunk_t authKeySerialNumber;
123
124 /**
125 * No revocation information available
126 */
127 bool noRevAvail;
128
129 /**
130 * Signature algorithm (must be identical to sigAlg)
131 */
132 int algorithm;
133
134 /**
135 * Signature
136 */
137 chunk_t signature;
138 };
139
140 /**
141 * definition of ietfAttribute kinds
142 */
143 typedef enum {
144 IETF_ATTRIBUTE_OCTETS = 0,
145 IETF_ATTRIBUTE_OID = 1,
146 IETF_ATTRIBUTE_STRING = 2
147 } ietfAttribute_t;
148
149 /**
150 * access structure for an ietfAttribute
151 */
152 typedef struct ietfAttr_t ietfAttr_t;
153
154 struct ietfAttr_t {
155 /**
156 * IETF attribute kind
157 */
158 ietfAttribute_t kind;
159
160 /**
161 * IETF attribute valuse
162 */
163 chunk_t value;
164
165 /**
166 * Destroys the ietfAttr_t object.
167 *
168 * @param this ietfAttr_t to destroy
169 */
170 void (*destroy) (ietfAttr_t *this);
171 };
172
173 /**
174 * Destroys an ietfAttr_t object
175 */
176 static void ietfAttr_destroy(ietfAttr_t *this)
177 {
178 free(this->value.ptr);
179 free(this);
180 }
181
182 /**
183 * Creates an ietfAttr_t object.
184 */
185 ietfAttr_t *ietfAttr_create(ietfAttribute_t kind, chunk_t value)
186 {
187 ietfAttr_t *this = malloc_thing(ietfAttr_t);
188
189 /* initialize */
190 this->kind = kind;
191 this->value = chunk_clone(value);
192
193 /* function */
194 this->destroy = ietfAttr_destroy;
195
196 return this;
197 }
198
199 /**
200 * ASN.1 definition of ietfAttrSyntax
201 */
202 static const asn1Object_t ietfAttrSyntaxObjects[] =
203 {
204 { 0, "ietfAttrSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
205 { 1, "policyAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
206 ASN1_BODY }, /* 1 */
207 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
208 { 1, "values", ASN1_SEQUENCE, ASN1_LOOP }, /* 3 */
209 { 2, "octets", ASN1_OCTET_STRING, ASN1_OPT |
210 ASN1_BODY }, /* 4 */
211 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 5 */
212 { 2, "oid", ASN1_OID, ASN1_OPT |
213 ASN1_BODY }, /* 6 */
214 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
215 { 2, "string", ASN1_UTF8STRING, ASN1_OPT |
216 ASN1_BODY }, /* 8 */
217 { 2, "end choice", ASN1_EOC, ASN1_END }, /* 9 */
218 { 1, "end loop", ASN1_EOC, ASN1_END } /* 10 */
219 };
220
221 #define IETF_ATTR_OCTETS 4
222 #define IETF_ATTR_OID 6
223 #define IETF_ATTR_STRING 8
224 #define IETF_ATTR_ROOF 11
225
226 /**
227 * ASN.1 definition of roleSyntax
228 */
229 static const asn1Object_t roleSyntaxObjects[] =
230 {
231 { 0, "roleSyntax", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
232 { 1, "roleAuthority", ASN1_CONTEXT_C_0, ASN1_OPT |
233 ASN1_OBJ }, /* 1 */
234 { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
235 { 1, "roleName", ASN1_CONTEXT_C_1, ASN1_OBJ } /* 3 */
236 };
237
238 #define ROLE_ROOF 4
239
240 /**
241 * ASN.1 definition of an X509 attribute certificate
242 */
243 static const asn1Object_t acObjects[] =
244 {
245 { 0, "AttributeCertificate", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */
246 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 1 */
247 { 2, "version", ASN1_INTEGER, ASN1_DEF |
248 ASN1_BODY }, /* 2 */
249 { 2, "holder", ASN1_SEQUENCE, ASN1_NONE }, /* 3 */
250 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 4 */
251 { 4, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 5 */
252 { 4, "serial", ASN1_INTEGER, ASN1_BODY }, /* 6 */
253 { 4, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
254 ASN1_BODY }, /* 7 */
255 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 8 */
256 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
257 { 3, "entityName", ASN1_CONTEXT_C_1, ASN1_OPT |
258 ASN1_OBJ }, /* 10 */
259 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
260 { 3, "objectDigestInfo", ASN1_CONTEXT_C_2, ASN1_OPT }, /* 12 */
261 { 4, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 13*/
262 { 4, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
263 ASN1_BODY }, /* 14 */
264 { 4, "end opt", ASN1_EOC, ASN1_END }, /* 15*/
265 { 4, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 16 */
266 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 17 */
267 { 2, "v2Form", ASN1_CONTEXT_C_0, ASN1_NONE }, /* 18 */
268 { 3, "issuerName", ASN1_SEQUENCE, ASN1_OPT |
269 ASN1_OBJ }, /* 19 */
270 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 20 */
271 { 3, "baseCertificateID", ASN1_CONTEXT_C_0, ASN1_OPT }, /* 21 */
272 { 4, "issuerSerial", ASN1_SEQUENCE, ASN1_NONE }, /* 22 */
273 { 5, "issuer", ASN1_SEQUENCE, ASN1_OBJ }, /* 23 */
274 { 5, "serial", ASN1_INTEGER, ASN1_BODY }, /* 24 */
275 { 5, "issuerUID", ASN1_BIT_STRING, ASN1_OPT |
276 ASN1_BODY }, /* 25 */
277 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 26 */
278 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 27 */
279 { 3, "objectDigestInfo", ASN1_CONTEXT_C_1, ASN1_OPT }, /* 28 */
280 { 4, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 29 */
281 { 5, "digestedObjectType", ASN1_ENUMERATED, ASN1_BODY }, /* 30 */
282 { 5, "otherObjectTypeID", ASN1_OID, ASN1_OPT |
283 ASN1_BODY }, /* 31 */
284 { 5, "end opt", ASN1_EOC, ASN1_END }, /* 32 */
285 { 5, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 33 */
286 { 3, "end opt", ASN1_EOC, ASN1_END }, /* 34 */
287 { 2, "signature", ASN1_EOC, ASN1_RAW }, /* 35 */
288 { 2, "serialNumber", ASN1_INTEGER, ASN1_BODY }, /* 36 */
289 { 2, "attrCertValidityPeriod", ASN1_SEQUENCE, ASN1_NONE }, /* 37 */
290 { 3, "notBeforeTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 38 */
291 { 3, "notAfterTime", ASN1_GENERALIZEDTIME, ASN1_BODY }, /* 39 */
292 { 2, "attributes", ASN1_SEQUENCE, ASN1_LOOP }, /* 40 */
293 { 3, "attribute", ASN1_SEQUENCE, ASN1_NONE }, /* 41 */
294 { 4, "type", ASN1_OID, ASN1_BODY }, /* 42 */
295 { 4, "values", ASN1_SET, ASN1_LOOP }, /* 43 */
296 { 5, "value", ASN1_EOC, ASN1_RAW }, /* 44 */
297 { 4, "end loop", ASN1_EOC, ASN1_END }, /* 45 */
298 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 46 */
299 { 2, "extensions", ASN1_SEQUENCE, ASN1_LOOP }, /* 47 */
300 { 3, "extension", ASN1_SEQUENCE, ASN1_NONE }, /* 48 */
301 { 4, "extnID", ASN1_OID, ASN1_BODY }, /* 49 */
302 { 4, "critical", ASN1_BOOLEAN, ASN1_DEF |
303 ASN1_BODY }, /* 50 */
304 { 4, "extnValue", ASN1_OCTET_STRING, ASN1_BODY }, /* 51 */
305 { 2, "end loop", ASN1_EOC, ASN1_END }, /* 52 */
306 { 1, "signatureAlgorithm", ASN1_EOC, ASN1_RAW }, /* 53 */
307 { 1, "signatureValue", ASN1_BIT_STRING, ASN1_BODY } /* 54 */
308 };
309
310 #define AC_OBJ_CERTIFICATE 0
311 #define AC_OBJ_CERTIFICATE_INFO 1
312 #define AC_OBJ_VERSION 2
313 #define AC_OBJ_HOLDER_ISSUER 5
314 #define AC_OBJ_HOLDER_SERIAL 6
315 #define AC_OBJ_ENTITY_NAME 10
316 #define AC_OBJ_ISSUER_NAME 19
317 #define AC_OBJ_ISSUER 23
318 #define AC_OBJ_SIG_ALG 35
319 #define AC_OBJ_SERIAL_NUMBER 36
320 #define AC_OBJ_NOT_BEFORE 38
321 #define AC_OBJ_NOT_AFTER 39
322 #define AC_OBJ_ATTRIBUTE_TYPE 42
323 #define AC_OBJ_ATTRIBUTE_VALUE 44
324 #define AC_OBJ_EXTN_ID 49
325 #define AC_OBJ_CRITICAL 50
326 #define AC_OBJ_EXTN_VALUE 51
327 #define AC_OBJ_ALGORITHM 53
328 #define AC_OBJ_SIGNATURE 54
329 #define AC_OBJ_ROOF 55
330
331 /**
332 * Implements x509ac_t.is_valid
333 */
334 static err_t is_valid(const private_x509ac_t *this, time_t *until)
335 {
336 time_t current_time = time(NULL);
337
338 DBG2(" not before : %T", &this->notBefore);
339 DBG2(" current time: %T", &current_time);
340 DBG2(" not after : %T", &this->notAfter);
341
342 if (until != NULL &&
343 (*until == UNDEFINED_TIME || this->notAfter < *until))
344 {
345 *until = this->notAfter;
346 }
347 if (current_time < this->notBefore)
348 {
349 return "is not valid yet";
350 }
351 if (current_time > this->notAfter)
352 {
353 return "has expired";
354 }
355 DBG2(" attribute certificate is valid");
356 return NULL;
357 }
358
359 /**
360 * parses a directoryName
361 */
362 static bool parse_directoryName(chunk_t blob, int level, bool implicit, identification_t **name)
363 {
364 bool has_directoryName;
365 linked_list_t *list = linked_list_create();
366
367 parse_generalNames(blob, level, implicit, list);
368 has_directoryName = list->get_count(list) > 0;
369
370 if (has_directoryName)
371 {
372 iterator_t *iterator = list->create_iterator(list, TRUE);
373 identification_t *directoryName;
374 bool first = TRUE;
375
376 while (iterator->iterate(iterator, (void**)&directoryName))
377 {
378 if (first)
379 {
380 *name = directoryName;
381 first = FALSE;
382 }
383 else
384 {
385 DBG1("more than one directory name - first selected");
386 directoryName->destroy(directoryName);
387 }
388 }
389 iterator->destroy(iterator);
390 }
391 else
392 {
393 DBG1("no directoryName found");
394 }
395
396 list->destroy(list);
397 return has_directoryName;
398 }
399
400 /**
401 * parses ietfAttrSyntax
402 */
403 static void parse_ietfAttrSyntax(chunk_t blob, int level0, linked_list_t *list)
404 {
405 asn1_ctx_t ctx;
406 chunk_t object;
407 u_int level;
408 int objectID = 0;
409
410 asn1_init(&ctx, blob, level0, FALSE, FALSE);
411
412 while (objectID < IETF_ATTR_ROOF)
413 {
414 if (!extract_object(ietfAttrSyntaxObjects, &objectID, &object, &level, &ctx))
415 {
416 return;
417 }
418
419 switch (objectID)
420 {
421 case IETF_ATTR_OCTETS:
422 case IETF_ATTR_OID:
423 case IETF_ATTR_STRING:
424 {
425 ietfAttribute_t kind = (objectID - IETF_ATTR_OCTETS) / 2;
426 ietfAttr_t *attr = ietfAttr_create(kind, object);
427 list->insert_last(list, (void *)attr);
428 }
429 break;
430 default:
431 break;
432 }
433 objectID++;
434 }
435 }
436
437 /**
438 * parses roleSyntax
439 */
440 static void parse_roleSyntax(chunk_t blob, int level0)
441 {
442 asn1_ctx_t ctx;
443 chunk_t object;
444 u_int level;
445 int objectID = 0;
446
447 asn1_init(&ctx, blob, level0, FALSE, FALSE);
448 while (objectID < ROLE_ROOF)
449 {
450 if (!extract_object(roleSyntaxObjects, &objectID, &object, &level, &ctx))
451 {
452 return;
453 }
454
455 switch (objectID)
456 {
457 default:
458 break;
459 }
460 objectID++;
461 }
462 }
463
464 /**
465 * Parses an X.509 attribute certificate
466 */
467 static bool parse_certificate(chunk_t blob, private_x509ac_t *this)
468 {
469 asn1_ctx_t ctx;
470 bool critical;
471 chunk_t object;
472 u_int level;
473 u_int type = OID_UNKNOWN;
474 u_int extn_oid = OID_UNKNOWN;
475 int objectID = 0;
476
477 asn1_init(&ctx, blob, 0, FALSE, FALSE);
478 while (objectID < AC_OBJ_ROOF)
479 {
480 if (!extract_object(acObjects, &objectID, &object, &level, &ctx))
481 {
482 return FALSE;
483 }
484
485 /* those objects which will parsed further need the next higher level */
486 level++;
487
488 switch (objectID)
489 {
490 case AC_OBJ_CERTIFICATE:
491 this->certificate = object;
492 break;
493 case AC_OBJ_CERTIFICATE_INFO:
494 this->certificateInfo = object;
495 break;
496 case AC_OBJ_VERSION:
497 this->version = (object.len) ? (1 + (u_int)*object.ptr) : 1;
498 DBG2(" v%d", this->version);
499 if (this->version != 2)
500 {
501 DBG1("v%d attribute certificates are not supported", this->version);
502 return FALSE;
503 }
504 break;
505 case AC_OBJ_HOLDER_ISSUER:
506 if (!parse_directoryName(object, level, FALSE, &this->holderIssuer))
507 {
508 return FALSE;
509 }
510 break;
511 case AC_OBJ_HOLDER_SERIAL:
512 this->holderSerial = object;
513 break;
514 case AC_OBJ_ENTITY_NAME:
515 if (!parse_directoryName(object, level, TRUE, &this->entityName))
516 {
517 return FALSE;
518 }
519 break;
520 case AC_OBJ_ISSUER_NAME:
521 if (!parse_directoryName(object, level, FALSE, &this->issuerName))
522 {
523 return FALSE;
524 }
525 break;
526 case AC_OBJ_SIG_ALG:
527 this->sigAlg = parse_algorithmIdentifier(object, level, NULL);
528 break;
529 case AC_OBJ_SERIAL_NUMBER:
530 this->serialNumber = object;
531 break;
532 case AC_OBJ_NOT_BEFORE:
533 this->notBefore = asn1totime(&object, ASN1_GENERALIZEDTIME);
534 break;
535 case AC_OBJ_NOT_AFTER:
536 this->notAfter = asn1totime(&object, ASN1_GENERALIZEDTIME);
537 break;
538 case AC_OBJ_ATTRIBUTE_TYPE:
539 type = known_oid(object);
540 break;
541 case AC_OBJ_ATTRIBUTE_VALUE:
542 {
543 switch (type)
544 {
545 case OID_AUTHENTICATION_INFO:
546 DBG2(" need to parse authenticationInfo");
547 break;
548 case OID_ACCESS_IDENTITY:
549 DBG2(" need to parse accessIdentity");
550 break;
551 case OID_CHARGING_IDENTITY:
552 parse_ietfAttrSyntax(object, level, this->charging);
553 break;
554 case OID_GROUP:
555 parse_ietfAttrSyntax(object, level, this->groups);
556 break;
557 case OID_ROLE:
558 parse_roleSyntax(object, level);
559 break;
560 default:
561 break;
562 }
563 }
564 break;
565 case AC_OBJ_EXTN_ID:
566 extn_oid = known_oid(object);
567 break;
568 case AC_OBJ_CRITICAL:
569 critical = object.len && *object.ptr;
570 DBG2(" %s",(critical)?"TRUE":"FALSE");
571 break;
572 case AC_OBJ_EXTN_VALUE:
573 {
574 switch (extn_oid)
575 {
576 case OID_CRL_DISTRIBUTION_POINTS:
577 DBG2(" need to parse crlDistributionPoints");
578 break;
579 case OID_AUTHORITY_KEY_ID:
580 parse_authorityKeyIdentifier(object, level,
581 &this->authKeyID, &this->authKeySerialNumber);
582 break;
583 case OID_TARGET_INFORMATION:
584 DBG2(" need to parse targetInformation");
585 break;
586 case OID_NO_REV_AVAIL:
587 this->noRevAvail = TRUE;
588 break;
589 default:
590 break;
591 }
592 }
593 break;
594 case AC_OBJ_ALGORITHM:
595 this->algorithm = parse_algorithmIdentifier(object, level, NULL);
596 break;
597 case AC_OBJ_SIGNATURE:
598 this->signature = object;
599 break;
600 default:
601 break;
602 }
603 objectID++;
604 }
605 this->installed = time(NULL);
606 return FALSE;
607 }
608
609 /**
610 * Implements x509ac_t.destroy
611 */
612 static void destroy(private_x509ac_t *this)
613 {
614 DESTROY_IF(this->holderIssuer);
615 DESTROY_IF(this->entityName);
616 DESTROY_IF(this->issuerName);
617 this->charging->destroy_offset(this->charging,
618 offsetof(ietfAttr_t, destroy));
619 this->groups->destroy_offset(this->groups,
620 offsetof(ietfAttr_t, destroy));
621 free(this->certificate.ptr);
622 free(this);
623 }
624
625 /**
626 * Described in header.
627 */
628 x509ac_t *x509ac_create_from_chunk(chunk_t chunk)
629 {
630 private_x509ac_t *this = malloc_thing(private_x509ac_t);
631
632 /* initialize */
633 this->holderIssuer = NULL;
634 this->entityName = NULL;
635 this->issuerName = NULL;
636 this->charging = linked_list_create();
637 this->groups = linked_list_create();
638
639 /* public functions */
640 this->public.is_valid = (err_t (*) (const x509ac_t*,time_t*))is_valid;
641 this->public.destroy = (void (*) (x509ac_t*))destroy;
642
643 if (!parse_certificate(chunk, this))
644 {
645 destroy(this);
646 return NULL;
647 }
648 return &this->public;
649 }
650
651 /**
652 * Described in header.
653 */
654 x509ac_t *x509ac_create_from_file(const char *filename)
655 {
656 bool pgp = FALSE;
657 chunk_t chunk = chunk_empty;
658
659 if (!pem_asn1_load_file(filename, NULL, "attribute certificate", &chunk, &pgp))
660 {
661 return NULL;
662 }
663 return x509ac_create_from_chunk(chunk);
664 }
665