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
7 * HSR Hochschule fuer Technik Rapperswil
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>.
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
25 #include <utils/debug.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>
34 extern chunk_t
x509_parse_authorityKeyIdentifier(chunk_t blob
,
35 int level0
, chunk_t
*authKeySerialNumber
);
37 typedef struct private_x509_ac_t private_x509_ac_t
;
40 * private data of x509_ac_t object
42 struct private_x509_ac_t
{
50 * X.509 attribute certificate encoding in ASN.1 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
;
90 * Start time of certificate validity
95 * End time of certificate validity
100 * List of group attributes, as group_t
102 linked_list_t
*groups
;
105 * Authority Key Identifier
107 chunk_t authKeyIdentifier
;
110 * Authority Key Serial Number
112 chunk_t authKeySerialNumber
;
115 * No revocation information available
120 * Signature algorithm
132 certificate_t
*holderCert
;
137 certificate_t
*signerCert
;
140 * Signer private key;
142 private_key_t
*signerKey
;
151 * Group definition, an IETF attribute
154 /** Attribute type */
155 ac_group_type_t type
;
156 /* attribute value */
161 * Clean up a group entry
163 static void group_destroy(group_t
*group
)
165 free(group
->value
.ptr
);
169 static chunk_t ASN1_noRevAvail_ext
= chunk_from_chars(
178 * declaration of function implemented in x509_cert.c
180 extern void x509_parse_generalNames(chunk_t blob
, int level0
, bool implicit
,
181 linked_list_t
*list
);
183 * parses a directoryName
185 static bool parse_directoryName(chunk_t blob
, int level
, bool implicit
,
186 identification_t
**name
)
188 identification_t
*directoryName
;
189 enumerator_t
*enumerator
;
193 list
= linked_list_create();
194 x509_parse_generalNames(blob
, level
, implicit
, list
);
196 enumerator
= list
->create_enumerator(list
);
197 while (enumerator
->enumerate(enumerator
, &directoryName
))
201 *name
= directoryName
;
206 DBG1(DBG_ASN
, "more than one directory name - first selected");
207 directoryName
->destroy(directoryName
);
211 enumerator
->destroy(enumerator
);
216 DBG1(DBG_ASN
, "no directoryName found");
223 * ASN.1 definition of roleSyntax
225 static const asn1Object_t roleSyntaxObjects
[] =
227 { 0, "roleSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
228 { 1, "roleAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
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
}
238 static void parse_roleSyntax(chunk_t blob
, int level0
)
240 asn1_parser_t
*parser
;
244 parser
= asn1_parser_create(roleSyntaxObjects
, blob
);
245 parser
->set_top_level(parser
, level0
);
247 while (parser
->iterate(parser
, &objectID
, &object
))
255 parser
->destroy(parser
);
259 * ASN.1 definition of ietfAttrSyntax
261 static const asn1Object_t ietfAttrSyntaxObjects
[] =
263 { 0, "ietfAttrSyntax", ASN1_SEQUENCE
, ASN1_NONE
}, /* 0 */
264 { 1, "policyAuthority", ASN1_CONTEXT_C_0
, ASN1_OPT
|
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
|
270 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 5 */
271 { 2, "oid", ASN1_OID
, ASN1_OPT
|
273 { 2, "end choice", ASN1_EOC
, ASN1_END
}, /* 7 */
274 { 2, "string", ASN1_UTF8STRING
, ASN1_OPT
|
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
}
280 #define IETF_ATTR_OCTETS 4
281 #define IETF_ATTR_OID 6
282 #define IETF_ATTR_STRING 8
285 * Parse group memberships, IETF attributes
287 static bool parse_groups(private_x509_ac_t
*this, chunk_t encoded
, int level0
)
289 ac_group_type_t type
;
291 asn1_parser_t
*parser
;
296 parser
= asn1_parser_create(ietfAttrSyntaxObjects
, encoded
);
297 parser
->set_top_level(parser
, level0
);
298 while (parser
->iterate(parser
, &objectID
, &object
))
302 case IETF_ATTR_OCTETS
:
303 type
= AC_GROUP_TYPE_OCTETS
;
306 type
= AC_GROUP_TYPE_OID
;
308 case IETF_ATTR_STRING
:
309 type
= AC_GROUP_TYPE_STRING
;
316 .value
= chunk_clone(object
),
318 this->groups
->insert_last(this->groups
, group
);
320 success
= parser
->success(parser
);
321 parser
->destroy(parser
);
327 * ASN.1 definition of an X509 attribute certificate
329 static const asn1Object_t acObjects
[] =
331 { 0, "AttributeCertificate", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 0 */
332 { 1, "AttributeCertificateInfo", ASN1_SEQUENCE
, ASN1_OBJ
}, /* 1 */
333 { 2, "version", ASN1_INTEGER
, ASN1_DEF
|
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
|
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
|
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
|
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
}
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
416 * Parses an X.509 attribute certificate
418 static bool parse_certificate(private_x509_ac_t
*this)
420 asn1_parser_t
*parser
;
423 int type
= OID_UNKNOWN
;
424 int extn_oid
= OID_UNKNOWN
;
425 int sig_alg
= OID_UNKNOWN
;
426 bool success
= FALSE
;
429 parser
= asn1_parser_create(acObjects
, this->encoding
);
431 while (parser
->iterate(parser
, &objectID
, &object
))
433 u_int level
= parser
->get_level(parser
)+1;
437 case AC_OBJ_CERTIFICATE_INFO
:
438 this->certificateInfo
= object
;
441 this->version
= (object
.len
) ?
(1 + (u_int
)*object
.ptr
) : 1;
442 DBG2(DBG_ASN
, " v%d", this->version
);
443 if (this->version
!= 2)
445 DBG1(DBG_ASN
, "v%d attribute certificates are not "
446 "supported", this->version
);
450 case AC_OBJ_HOLDER_ISSUER
:
451 if (!parse_directoryName(object
, level
, FALSE
,
452 &this->holderIssuer
))
457 case AC_OBJ_HOLDER_SERIAL
:
458 this->holderSerial
= object
;
460 case AC_OBJ_ENTITY_NAME
:
461 if (!parse_directoryName(object
, level
, TRUE
,
467 case AC_OBJ_ISSUER_NAME
:
468 if (!parse_directoryName(object
, level
, FALSE
,
475 sig_alg
= asn1_parse_algorithmIdentifier(object
, level
, NULL
);
477 case AC_OBJ_SERIAL_NUMBER
:
478 this->serialNumber
= chunk_clone(object
);
480 case AC_OBJ_NOT_BEFORE
:
481 this->notBefore
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
483 case AC_OBJ_NOT_AFTER
:
484 this->notAfter
= asn1_to_time(&object
, ASN1_GENERALIZEDTIME
);
486 case AC_OBJ_ATTRIBUTE_TYPE
:
487 type
= asn1_known_oid(object
);
489 case AC_OBJ_ATTRIBUTE_VALUE
:
493 case OID_AUTHENTICATION_INFO
:
494 DBG2(DBG_ASN
, " need to parse authenticationInfo");
496 case OID_ACCESS_IDENTITY
:
497 DBG2(DBG_ASN
, " need to parse accessIdentity");
499 case OID_CHARGING_IDENTITY
:
500 DBG2(DBG_ASN
, " need to parse chargingIdentity");
503 DBG2(DBG_ASN
, "-- > --");
504 if (!parse_groups(this, object
, level
))
508 DBG2(DBG_ASN
, "-- < --");
511 parse_roleSyntax(object
, level
);
519 extn_oid
= asn1_known_oid(object
);
521 case AC_OBJ_CRITICAL
:
522 critical
= object
.len
&& *object
.ptr
;
523 DBG2(DBG_ASN
, " %s",(critical
)?
"TRUE":"FALSE");
525 case AC_OBJ_EXTN_VALUE
:
529 case OID_CRL_DISTRIBUTION_POINTS
:
530 DBG2(DBG_ASN
, " need to parse crlDistributionPoints");
532 case OID_AUTHORITY_KEY_ID
:
533 this->authKeyIdentifier
=
534 x509_parse_authorityKeyIdentifier(object
,
535 level
, &this->authKeySerialNumber
);
537 case OID_TARGET_INFORMATION
:
538 DBG2(DBG_ASN
, " need to parse targetInformation");
540 case OID_NO_REV_AVAIL
:
541 this->noRevAvail
= TRUE
;
548 case AC_OBJ_ALGORITHM
:
549 this->algorithm
= asn1_parse_algorithmIdentifier(object
, level
,
551 if (this->algorithm
!= sig_alg
)
553 DBG1(DBG_ASN
, " signature algorithms do not agree");
558 case AC_OBJ_SIGNATURE
:
559 this->signature
= object
;
565 success
= parser
->success(parser
);
568 parser
->destroy(parser
);
573 * build directoryName
575 static chunk_t
build_directoryName(asn1_t tag
, chunk_t name
)
577 return asn1_wrap(tag
, "m",
578 asn1_simple_object(ASN1_CONTEXT_C_4
, name
));
584 static chunk_t
build_holder(private_x509_ac_t
*this)
586 x509_t
* x509
= (x509_t
*)this->holderCert
;
587 identification_t
*issuer
, *subject
;
589 issuer
= this->holderCert
->get_issuer(this->holderCert
);
590 subject
= this->holderCert
->get_subject(this->holderCert
);
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
)));
602 static chunk_t
build_v2_form(private_x509_ac_t
*this)
604 identification_t
*subject
;
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
)));
613 * build attrCertValidityPeriod
615 static chunk_t
build_attr_cert_validity(private_x509_ac_t
*this)
617 return asn1_wrap(ASN1_SEQUENCE
, "mm",
618 asn1_from_time(&this->notBefore
, ASN1_GENERALIZEDTIME
),
619 asn1_from_time(&this->notAfter
, ASN1_GENERALIZEDTIME
));
623 * build attribute type
625 static chunk_t
build_attribute_type(int type
, chunk_t content
)
627 return asn1_wrap(ASN1_SEQUENCE
, "mm",
628 asn1_build_known_oid(type
),
629 asn1_wrap(ASN1_SET
, "m", content
));
635 static chunk_t
build_attributes(private_x509_ac_t
*this)
637 enumerator_t
*enumerator
;
640 size_t size
= 0, len
;
643 /* precalculate the total size of all values */
644 enumerator
= this->groups
->create_enumerator(this->groups
);
645 while (enumerator
->enumerate(enumerator
, &group
))
647 len
= group
->value
.len
;
648 size
+= 1 + (len
> 0) + (len
>= 128) +
649 (len
>= 256) + (len
>= 65536) + len
;
651 enumerator
->destroy(enumerator
);
653 pos
= asn1_build_object(&values
, ASN1_SEQUENCE
, size
);
655 enumerator
= this->groups
->create_enumerator(this->groups
);
656 while (enumerator
->enumerate(enumerator
, &group
))
663 case AC_GROUP_TYPE_OCTETS
:
664 type
= ASN1_OCTET_STRING
;
666 case AC_GROUP_TYPE_STRING
:
667 type
= ASN1_UTF8STRING
;
669 case AC_GROUP_TYPE_OID
:
675 attr
= asn1_simple_object(type
, group
->value
);
677 memcpy(pos
, attr
.ptr
, attr
.len
);
681 enumerator
->destroy(enumerator
);
683 return asn1_wrap(ASN1_SEQUENCE
, "m",
684 build_attribute_type(OID_GROUP
,
685 asn1_wrap(ASN1_SEQUENCE
, "m", values
)));
689 * build authorityKeyIdentifier
691 static chunk_t
build_authorityKeyIdentifier(private_x509_ac_t
*this)
693 chunk_t keyIdentifier
= chunk_empty
;
694 chunk_t authorityCertIssuer
;
695 chunk_t authorityCertSerialNumber
;
696 identification_t
*issuer
;
697 public_key_t
*public;
700 x509
= (x509_t
*)this->signerCert
;
701 issuer
= this->signerCert
->get_issuer(this->signerCert
);
702 public = this->signerCert
->get_public_key(this->signerCert
);
705 if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1
, &keyIdentifier
))
707 this->authKeyIdentifier
= chunk_clone(keyIdentifier
);
709 public->destroy(public);
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",
721 authorityCertSerialNumber
730 static chunk_t
build_extensions(private_x509_ac_t
*this)
732 return asn1_wrap(ASN1_SEQUENCE
, "mc",
733 build_authorityKeyIdentifier(this),
734 ASN1_noRevAvail_ext
);
738 * build attributeCertificateInfo
740 static chunk_t
build_attr_cert_info(private_x509_ac_t
*this)
742 return asn1_wrap(ASN1_SEQUENCE
, "cmmmmmmm",
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));
754 * build an X.509 attribute certificate
756 static chunk_t
build_ac(private_x509_ac_t
*this)
758 chunk_t signatureValue
, attributeCertificateInfo
;
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
));
769 METHOD(ac_t
, get_serial
, chunk_t
,
770 private_x509_ac_t
*this)
772 return this->serialNumber
;
775 METHOD(ac_t
, get_holderSerial
, chunk_t
,
776 private_x509_ac_t
*this)
778 return this->holderSerial
;
781 METHOD(ac_t
, get_holderIssuer
, identification_t
*,
782 private_x509_ac_t
*this)
784 return this->holderIssuer
;
787 METHOD(ac_t
, get_authKeyIdentifier
, chunk_t
,
788 private_x509_ac_t
*this)
790 return this->authKeyIdentifier
;
794 * Filter function for attribute enumeration
796 static bool attr_filter(void *null
, group_t
**in
, ac_group_type_t
*type
,
797 void *in2
, chunk_t
*out
)
799 if ((*in
)->type
== AC_GROUP_TYPE_STRING
&&
800 !chunk_printable((*in
)->value
, NULL
, 0))
801 { /* skip non-printable strings */
809 METHOD(ac_t
, create_group_enumerator
, enumerator_t
*,
810 private_x509_ac_t
*this)
812 return enumerator_create_filter(
813 this->groups
->create_enumerator(this->groups
),
814 (void*)attr_filter
, NULL
, NULL
);
817 METHOD(certificate_t
, get_type
, certificate_type_t
,
818 private_x509_ac_t
*this)
823 METHOD(certificate_t
, get_subject
, identification_t
*,
824 private_x509_ac_t
*this)
826 return this->entityName
;
829 METHOD(certificate_t
, get_issuer
, identification_t
*,
830 private_x509_ac_t
*this)
832 return this->issuerName
;
835 METHOD(certificate_t
, has_subject
, id_match_t
,
836 private_x509_ac_t
*this, identification_t
*subject
)
838 return ID_MATCH_NONE
;
841 METHOD(certificate_t
, has_issuer
, id_match_t
,
842 private_x509_ac_t
*this, identification_t
*issuer
)
844 if (issuer
->get_type(issuer
) == ID_KEY_ID
&&
845 this->authKeyIdentifier
.ptr
&&
846 chunk_equals(this->authKeyIdentifier
, issuer
->get_encoding(issuer
)))
848 return ID_MATCH_PERFECT
;
850 return this->issuerName
->matches(this->issuerName
, issuer
);
853 METHOD(certificate_t
, issued_by
, bool,
854 private_x509_ac_t
*this, certificate_t
*issuer
, signature_scheme_t
*schemep
)
857 signature_scheme_t scheme
;
859 x509_t
*x509
= (x509_t
*)issuer
;
861 /* check if issuer is an X.509 AA certificate */
862 if (issuer
->get_type(issuer
) != CERT_X509
)
866 if (!(x509
->get_flags(x509
) & X509_AA
))
871 /* get the public key of the issuer */
872 key
= issuer
->get_public_key(issuer
);
874 /* compare keyIdentifiers if available, otherwise use DNs */
875 if (this->authKeyIdentifier
.ptr
&& key
)
879 if (!key
->get_fingerprint(key
, KEYID_PUBKEY_SHA1
, &fingerprint
) ||
880 !chunk_equals(fingerprint
, this->authKeyIdentifier
))
887 if (!this->issuerName
->equals(this->issuerName
,
888 issuer
->get_subject(issuer
)))
894 /* determine signature scheme */
895 scheme
= signature_scheme_from_oid(this->algorithm
);
897 if (scheme
== SIGN_UNKNOWN
|| key
== NULL
)
901 valid
= key
->verify(key
, scheme
, this->certificateInfo
, this->signature
);
903 if (valid
&& schemep
)
910 METHOD(certificate_t
, get_public_key
, public_key_t
*,
911 private_x509_ac_t
*this)
916 METHOD(certificate_t
, get_ref
, certificate_t
*,
917 private_x509_ac_t
*this)
920 return &this->public.interface
.certificate
;
923 METHOD(certificate_t
, get_validity
, bool,
924 private_x509_ac_t
*this, time_t *when
, time_t *not_before
, time_t *not_after
)
926 time_t t
= when ?
*when
: time(NULL
);
930 *not_before
= this->notBefore
;
934 *not_after
= this->notAfter
;
936 return (t
>= this->notBefore
&& t
<= this->notAfter
);
939 METHOD(certificate_t
, get_encoding
, bool,
940 private_x509_ac_t
*this, cred_encoding_type_t type
, chunk_t
*encoding
)
942 if (type
== CERT_ASN1_DER
)
944 *encoding
= chunk_clone(this->encoding
);
947 return lib
->encoding
->encode(lib
->encoding
, type
, NULL
, encoding
,
948 CRED_PART_X509_AC_ASN1_DER
, this->encoding
, CRED_PART_END
);
951 METHOD(certificate_t
, equals
, bool,
952 private_x509_ac_t
*this, certificate_t
*other
)
957 if ((certificate_t
*)this == other
)
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
);
966 if (!other
->get_encoding(other
, CERT_ASN1_DER
, &encoding
))
970 equal
= chunk_equals(this->encoding
, encoding
);
975 METHOD(certificate_t
, destroy
, void,
976 private_x509_ac_t
*this)
978 if (ref_put(&this->ref
))
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
);
995 * create an empty but initialized X.509 attribute certificate
997 static private_x509_ac_t
*create_empty(void)
999 private_x509_ac_t
*this;
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
,
1015 .get_ref
= _get_ref
,
1016 .destroy
= _destroy
,
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
,
1025 .groups
= linked_list_create(),
1035 x509_ac_t
*x509_ac_load(certificate_type_t type
, va_list args
)
1037 chunk_t blob
= chunk_empty
;
1041 switch (va_arg(args
, builder_part_t
))
1043 case BUILD_BLOB_ASN1_DER
:
1044 blob
= va_arg(args
, chunk_t
);
1055 private_x509_ac_t
*ac
= create_empty();
1057 ac
->encoding
= chunk_clone(blob
);
1058 if (parse_certificate(ac
))
1068 * Parse a comma separated group list into AC group memberships
1070 static void add_groups_from_string(private_x509_ac_t
*this, char *str
)
1072 enumerator_t
*enumerator
;
1076 enumerator
= enumerator_create_token(str
, ",", " ");
1077 while (enumerator
->enumerate(enumerator
, &name
))
1080 .type
= AC_GROUP_TYPE_STRING
,
1081 .value
= chunk_clone(chunk_from_str(name
)),
1083 this->groups
->insert_last(this->groups
, group
);
1085 enumerator
->destroy(enumerator
);
1091 x509_ac_t
*x509_ac_gen(certificate_type_t type
, va_list args
)
1093 private_x509_ac_t
*ac
;
1095 ac
= create_empty();
1098 switch (va_arg(args
, builder_part_t
))
1100 case BUILD_NOT_BEFORE_TIME
:
1101 ac
->notBefore
= va_arg(args
, time_t);
1103 case BUILD_NOT_AFTER_TIME
:
1104 ac
->notAfter
= va_arg(args
, time_t);
1107 ac
->serialNumber
= chunk_clone(va_arg(args
, chunk_t
));
1109 case BUILD_IETF_GROUP_ATTR
:
1110 add_groups_from_string(ac
, va_arg(args
, char*));
1113 ac
->holderCert
= va_arg(args
, certificate_t
*);
1114 ac
->holderCert
->get_ref(ac
->holderCert
);
1116 case BUILD_SIGNING_CERT
:
1117 ac
->signerCert
= va_arg(args
, certificate_t
*);
1118 ac
->signerCert
->get_ref(ac
->signerCert
);
1120 case BUILD_SIGNING_KEY
:
1121 ac
->signerKey
= va_arg(args
, private_key_t
*);
1122 ac
->signerKey
->get_ref(ac
->signerKey
);
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
)
1137 ac
->encoding
= build_ac(ac
);