4 * @brief Implementation of x509ac_t.
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
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>.
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
27 #include <asn1/asn1.h>
28 #include <utils/identification.h>
29 #include <utils/linked_list.h>
33 typedef struct private_x509ac_t private_x509ac_t
;
36 * Private data of a x509ac_t object.
38 struct private_x509ac_t
{
40 * Public interface for this attribute certificate.
45 * Time when attribute certificate was installed
50 * X.509 attribute certificate in DER format
55 * X.509 attribute certificate body over which signature is computed
57 chunk_t certificateInfo
;
60 * Version of the X.509 attribute certificate
65 * Serial number of the X.509 attribute certificate
70 * ID representing the issuer of the holder certificate
72 identification_t
*holderIssuer
;
75 * Serial number of the holder certificate
80 * ID representing the holder
82 identification_t
*entityName
;
85 * ID representing the attribute certificate issuer
87 identification_t
*issuerName
;
95 * Start time of certificate validity
100 * End time of certificate validity
105 * List of charging attributes
107 linked_list_t
*charging
;
110 * List of groub attributes
112 linked_list_t
*groups
;
115 * Authority Key Identifier
120 * Authority Key Serial Number
122 chunk_t authKeySerialNumber
;
125 * No revocation information available
130 * Signature algorithm (must be identical to sigAlg)
141 * definition of ietfAttribute kinds
144 IETF_ATTRIBUTE_OCTETS
= 0,
145 IETF_ATTRIBUTE_OID
= 1,
146 IETF_ATTRIBUTE_STRING
= 2
150 * access structure for an ietfAttribute
152 typedef struct ietfAttr_t ietfAttr_t
;
156 * Time when attribute was first installed
166 * IETF attribute kind
168 ietfAttribute_t kind
;
171 * IETF attribute valuse
177 * Destroys an ietfAttribute_t object
179 static void ietfAttr_destroy(ietfAttr_t
*this)
181 free(this->value
.ptr
);
186 * ASN.1 definition of ietfAttrSyntax
188 static const asn1Object_t ietfAttrSyntaxObjects
[] =
190 { 0, "ietfAttrSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
191 { 1, "policyAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
193 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 2 */
194 { 1, "values", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 3 */
195 { 2, "octets", ASN1_OCTET_STRING
, ASN1_OPT
|
197 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 5 */
198 { 2, "oid", ASN1_OID
, ASN1_OPT
|
200 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 7 */
201 { 2, "string", ASN1_UTF8STRING
, ASN1_OPT
|
203 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 9 */
204 { 1, "end loop", ASN1_EOC
, ASN1_END
} /* 10 */
207 #define IETF_ATTR_OCTETS 4
208 #define IETF_ATTR_OID 6
209 #define IETF_ATTR_STRING 8
210 #define IETF_ATTR_ROOF 11
213 * ASN.1 definition of roleSyntax
215 static const asn1Object_t roleSyntaxObjects
[] =
217 { 0, "roleSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
218 { 1, "roleAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
220 { 1, "end opt", ASN1_EOC
, ASN1_END
}, /* 2 */
221 { 1, "roleName", ASN1_CONTEXT_C_1
, ASN1_OBJ
} /* 3 */
227 * ASN.1 definition of an X509 attribute certificate
229 static const asn1Object_t acObjects
[] =
231 { 0, "AttributeCertificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
232 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
233 { 2, "version", ASN1_INTEGER
, ASN1_DEF
|
235 { 2, "holder", ASN1_SEQUENCE
, ASN1_NONE
}, /* 3 */
236 { 3, "baseCertificateID", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 4 */
237 { 4, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 5 */
238 { 4, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 6 */
239 { 4, "issuerUID", ASN1_BIT_STRING
, ASN1_OPT
|
241 { 4, "end opt", ASN1_EOC
, ASN1_END
}, /* 8 */
242 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 9 */
243 { 3, "entityName", ASN1_CONTEXT_C_1
, ASN1_OPT
|
245 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 11 */
246 { 3, "objectDigestInfo", ASN1_CONTEXT_C_2
, ASN1_OPT
}, /* 12 */
247 { 4, "digestedObjectType", ASN1_ENUMERATED
, ASN1_BODY
}, /* 13*/
248 { 4, "otherObjectTypeID", ASN1_OID
, ASN1_OPT
|
249 ASN1_BODY
}, /* 14 */
250 { 4, "end opt", ASN1_EOC
, ASN1_END
}, /* 15*/
251 { 4, "digestAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 16 */
252 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 17 */
253 { 2, "v2Form", ASN1_CONTEXT_C_0
, ASN1_NONE
}, /* 18 */
254 { 3, "issuerName", ASN1_SEQUENCE
, ASN1_OPT
|
256 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 20 */
257 { 3, "baseCertificateID", ASN1_CONTEXT_C_0
, ASN1_OPT
}, /* 21 */
258 { 4, "issuerSerial", ASN1_SEQUENCE
, ASN1_NONE
}, /* 22 */
259 { 5, "issuer", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 23 */
260 { 5, "serial", ASN1_INTEGER
, ASN1_BODY
}, /* 24 */
261 { 5, "issuerUID", ASN1_BIT_STRING
, ASN1_OPT
|
262 ASN1_BODY
}, /* 25 */
263 { 5, "end opt", ASN1_EOC
, ASN1_END
}, /* 26 */
264 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 27 */
265 { 3, "objectDigestInfo", ASN1_CONTEXT_C_1
, ASN1_OPT
}, /* 28 */
266 { 4, "digestInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 29 */
267 { 5, "digestedObjectType", ASN1_ENUMERATED
, ASN1_BODY
}, /* 30 */
268 { 5, "otherObjectTypeID", ASN1_OID
, ASN1_OPT
|
269 ASN1_BODY
}, /* 31 */
270 { 5, "end opt", ASN1_EOC
, ASN1_END
}, /* 32 */
271 { 5, "digestAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 33 */
272 { 3, "end opt", ASN1_EOC
, ASN1_END
}, /* 34 */
273 { 2, "signature", ASN1_EOC
, ASN1_RAW
}, /* 35 */
274 { 2, "serialNumber", ASN1_INTEGER
, ASN1_BODY
}, /* 36 */
275 { 2, "attrCertValidityPeriod", ASN1_SEQUENCE
, ASN1_NONE
}, /* 37 */
276 { 3, "notBeforeTime", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 38 */
277 { 3, "notAfterTime", ASN1_GENERALIZEDTIME
, ASN1_BODY
}, /* 39 */
278 { 2, "attributes", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 40 */
279 { 3, "attribute", ASN1_SEQUENCE
, ASN1_NONE
}, /* 41 */
280 { 4, "type", ASN1_OID
, ASN1_BODY
}, /* 42 */
281 { 4, "values", ASN1_SET
, ASN1_LOOP
}, /* 43 */
282 { 5, "value", ASN1_EOC
, ASN1_RAW
}, /* 44 */
283 { 4, "end loop", ASN1_EOC
, ASN1_END
}, /* 45 */
284 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 46 */
285 { 2, "extensions", ASN1_SEQUENCE
, ASN1_LOOP
}, /* 47 */
286 { 3, "extension", ASN1_SEQUENCE
, ASN1_NONE
}, /* 48 */
287 { 4, "extnID", ASN1_OID
, ASN1_BODY
}, /* 49 */
288 { 4, "critical", ASN1_BOOLEAN
, ASN1_DEF
|
289 ASN1_BODY
}, /* 50 */
290 { 4, "extnValue", ASN1_OCTET_STRING
, ASN1_BODY
}, /* 51 */
291 { 2, "end loop", ASN1_EOC
, ASN1_END
}, /* 52 */
292 { 1, "signatureAlgorithm", ASN1_EOC
, ASN1_RAW
}, /* 53 */
293 { 1, "signatureValue", ASN1_BIT_STRING
, ASN1_BODY
} /* 54 */
296 #define AC_OBJ_CERTIFICATE 0
297 #define AC_OBJ_CERTIFICATE_INFO 1
298 #define AC_OBJ_VERSION 2
299 #define AC_OBJ_HOLDER_ISSUER 5
300 #define AC_OBJ_HOLDER_SERIAL 6
301 #define AC_OBJ_ENTITY_NAME 10
302 #define AC_OBJ_ISSUER_NAME 19
303 #define AC_OBJ_ISSUER 23
304 #define AC_OBJ_SIG_ALG 35
305 #define AC_OBJ_SERIAL_NUMBER 36
306 #define AC_OBJ_NOT_BEFORE 38
307 #define AC_OBJ_NOT_AFTER 39
308 #define AC_OBJ_ATTRIBUTE_TYPE 42
309 #define AC_OBJ_ATTRIBUTE_VALUE 44
310 #define AC_OBJ_EXTN_ID 49
311 #define AC_OBJ_CRITICAL 50
312 #define AC_OBJ_EXTN_VALUE 51
313 #define AC_OBJ_ALGORITHM 53
314 #define AC_OBJ_SIGNATURE 54
315 #define AC_OBJ_ROOF 55
318 * Implements x509ac_t.is_valid
320 static err_t
is_valid(const private_x509ac_t
*this, time_t *until
)
322 time_t current_time
= time(NULL
);
324 DBG2(" not before : %T", &this->notBefore
);
325 DBG2(" current time: %T", ¤t_time
);
326 DBG2(" not after : %T", &this->notAfter
);
329 (*until
== UNDEFINED_TIME
|| this->notAfter
< *until
))
331 *until
= this->notAfter
;
333 if (current_time
< this->notBefore
)
335 return "is not valid yet";
337 if (current_time
> this->notAfter
)
339 return "has expired";
341 DBG2(" attribute certificate is valid");
346 * parses a directoryName
348 static bool parse_directoryName(chunk_t blob
, int level
, bool implicit
, identification_t
**name
)
350 bool has_directoryName
;
351 linked_list_t
*list
= linked_list_create();
353 parse_generalNames(blob
, level
, implicit
, list
);
354 has_directoryName
= list
->get_count(list
) > 0;
356 if (has_directoryName
)
358 iterator_t
*iterator
= list
->create_iterator(list
, TRUE
);
359 identification_t
*directoryName
;
362 while (iterator
->iterate(iterator
, (void**)&directoryName
))
366 *name
= directoryName
;
371 DBG1("more than one directory name - first selected");
372 directoryName
->destroy(directoryName
);
375 iterator
->destroy(iterator
);
379 DBG1("no directoryName found");
383 return has_directoryName
;
387 * parses ietfAttrSyntax
389 static void parse_ietfAttrSyntax(chunk_t blob
, int level0
, linked_list_t
*list
)
397 static void parse_roleSyntax(chunk_t blob
, int level0
)
404 asn1_init(&ctx
, blob
, level0
, FALSE
, FALSE
);
405 while (objectID
< ROLE_ROOF
)
407 if (!extract_object(roleSyntaxObjects
, &objectID
, &object
, &level
, &ctx
))
422 * Parses an X.509 attribute certificate
424 static bool parse_certificate(chunk_t blob
, private_x509ac_t
*this)
430 u_int type
= OID_UNKNOWN
;
431 u_int extn_oid
= OID_UNKNOWN
;
434 asn1_init(&ctx
, blob
, 0, FALSE
, FALSE
);
435 while (objectID
< AC_OBJ_ROOF
)
437 if (!extract_object(acObjects
, &objectID
, &object
, &level
, &ctx
))
442 /* those objects which will parsed further need the next higher level */
447 case AC_OBJ_CERTIFICATE
:
448 this->certificate
= object
;
450 case AC_OBJ_CERTIFICATE_INFO
:
451 this->certificateInfo
= object
;
454 this->version
= (object
.len
) ?
(1 + (u_int
)*object
.ptr
) : 1;
455 DBG2(" v%d", this->version
);
456 if (this->version
!= 2)
458 DBG1("v%d attribute certificates are not supported", this->version
);
462 case AC_OBJ_HOLDER_ISSUER
:
463 if (!parse_directoryName(object
, level
, FALSE
, &this->holderIssuer
))
468 case AC_OBJ_HOLDER_SERIAL
:
469 this->holderSerial
= object
;
471 case AC_OBJ_ENTITY_NAME
:
472 if (!parse_directoryName(object
, level
, TRUE
, &this->entityName
))
477 case AC_OBJ_ISSUER_NAME
:
478 if (!parse_directoryName(object
, level
, FALSE
, &this->issuerName
))
484 this->sigAlg
= parse_algorithmIdentifier(object
, level
, NULL
);
486 case AC_OBJ_SERIAL_NUMBER
:
487 this->serialNumber
= object
;
489 case AC_OBJ_NOT_BEFORE
:
490 this->notBefore
= asn1totime(&object
, ASN1_GENERALIZEDTIME
);
492 case AC_OBJ_NOT_AFTER
:
493 this->notAfter
= asn1totime(&object
, ASN1_GENERALIZEDTIME
);
495 case AC_OBJ_ATTRIBUTE_TYPE
:
496 type
= known_oid(object
);
498 case AC_OBJ_ATTRIBUTE_VALUE
:
502 case OID_AUTHENTICATION_INFO
:
503 DBG2(" need to parse authenticationInfo");
505 case OID_ACCESS_IDENTITY
:
506 DBG2(" need to parse accessIdentity");
508 case OID_CHARGING_IDENTITY
:
509 parse_ietfAttrSyntax(object
, level
, this->charging
);
512 parse_ietfAttrSyntax(object
, level
, this->groups
);
515 parse_roleSyntax(object
, level
);
523 extn_oid
= known_oid(object
);
525 case AC_OBJ_CRITICAL
:
526 critical
= object
.len
&& *object
.ptr
;
527 DBG2(" %s",(critical
)?
"TRUE":"FALSE");
529 case AC_OBJ_EXTN_VALUE
:
533 case OID_CRL_DISTRIBUTION_POINTS
:
534 DBG2(" need to parse crlDistributionPoints");
536 case OID_AUTHORITY_KEY_ID
:
537 parse_authorityKeyIdentifier(object
, level
,
538 &this->authKeyID
, &this->authKeySerialNumber
);
540 case OID_TARGET_INFORMATION
:
541 DBG2(" need to parse targetInformation");
543 case OID_NO_REV_AVAIL
:
544 this->noRevAvail
= TRUE
;
551 case AC_OBJ_ALGORITHM
:
552 this->algorithm
= parse_algorithmIdentifier(object
, level
, NULL
);
554 case AC_OBJ_SIGNATURE
:
555 this->signature
= object
;
562 this->installed
= time(NULL
);
567 * Implements x509ac_t.destroy
569 static void destroy(private_x509ac_t
*this)
571 DESTROY_IF(this->holderIssuer
);
572 DESTROY_IF(this->entityName
);
573 DESTROY_IF(this->issuerName
);
574 free(this->certificate
.ptr
);
579 * Described in header.
581 x509ac_t
*x509ac_create_from_chunk(chunk_t chunk
)
583 private_x509ac_t
*this = malloc_thing(private_x509ac_t
);
586 this->holderIssuer
= NULL
;
587 this->entityName
= NULL
;
588 this->issuerName
= NULL
;
590 /* public functions */
591 this->public.is_valid
= (err_t (*) (const x509ac_t
*,time_t*))is_valid
;
592 this->public.destroy
= (void (*) (x509ac_t
*))destroy
;
594 if (!parse_certificate(chunk
, this))
599 return &this->public;
603 * Described in header.
605 x509ac_t
*x509ac_create_from_file(const char *filename
)
608 chunk_t chunk
= chunk_empty
;
610 if (!pem_asn1_load_file(filename
, NULL
, "attribute certificate", &chunk
, &pgp
))
614 return x509ac_create_from_chunk(chunk
);