/* Build a X.509 attribute certificate * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2004 Andreas Steffen * Zuercher Hochschule Winterthur, Switzerland * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * RCSID $Id: build.c,v 1.14 2005/09/06 11:47:57 as Exp $ */ #include #include #include #include "../pluto/constants.h" #include "../pluto/defs.h" #include "../pluto/oid.h" #include "../pluto/asn1.h" #include "../pluto/x509.h" #include "../pluto/log.h" #include "build.h" static u_char ASN1_group_oid_str[] = { 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a ,0x04 }; static const chunk_t ASN1_group_oid = strchunk(ASN1_group_oid_str); static u_char ASN1_authorityKeyIdentifier_oid_str[] = { 0x06, 0x03, 0x55, 0x1d, 0x23 }; static const chunk_t ASN1_authorityKeyIdentifier_oid = strchunk(ASN1_authorityKeyIdentifier_oid_str); static u_char ASN1_noRevAvail_ext_str[] = { 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x38, 0x04, 0x02, 0x05, 0x00 }; static const chunk_t ASN1_noRevAvail_ext = strchunk(ASN1_noRevAvail_ext_str); /* * build directoryName */ static chunk_t build_directoryName(asn1_t tag, chunk_t name) { return asn1_wrap(tag, "m" , asn1_simple_object(ASN1_CONTEXT_C_4, name)); } /* * build holder */ static chunk_t build_holder(void) { return asn1_wrap(ASN1_SEQUENCE, "mm" , asn1_wrap(ASN1_CONTEXT_C_0, "mm" , build_directoryName(ASN1_SEQUENCE, user->issuer) , asn1_simple_object(ASN1_INTEGER, user->serialNumber) ) , build_directoryName(ASN1_CONTEXT_C_1, user->subject)); } /* * build v2Form */ static chunk_t build_v2_form(void) { return asn1_wrap(ASN1_CONTEXT_C_0, "m" , build_directoryName(ASN1_SEQUENCE, signer->subject)); } /* * build attrCertValidityPeriod */ static chunk_t build_attr_cert_validity(void) { return asn1_wrap(ASN1_SEQUENCE, "mm" , timetoasn1(¬Before, ASN1_GENERALIZEDTIME) , timetoasn1(¬After, ASN1_GENERALIZEDTIME)); } /* * build attributes */ static chunk_t build_ietfAttributes(ietfAttrList_t *list) { chunk_t ietfAttributes; ietfAttrList_t *item = list; size_t size = 0; u_char *pos; /* precalculate the total size of all values */ while (item != NULL) { size_t len = item->attr->value.len; size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len; item = item->next; } pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size); while (list != NULL) { ietfAttr_t *attr = list->attr; asn1_t type = ASN1_NULL; switch (attr->kind) { case IETF_ATTRIBUTE_OCTETS: type = ASN1_OCTET_STRING; break; case IETF_ATTRIBUTE_STRING: type = ASN1_UTF8STRING; break; case IETF_ATTRIBUTE_OID: type = ASN1_OID; break; } mv_chunk(&pos, asn1_simple_object(type, attr->value)); list = list->next; } return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes); } /* * build attribute type */ static chunk_t build_attribute_type(const chunk_t type, chunk_t content) { return asn1_wrap(ASN1_SEQUENCE, "cm" , type , asn1_wrap(ASN1_SET, "m", content)); } /* * build attributes */ static chunk_t build_attributes(void) { return asn1_wrap(ASN1_SEQUENCE, "m" , build_attribute_type(ASN1_group_oid , build_ietfAttributes(groups))); } /* * build authorityKeyIdentifier */ static chunk_t build_authorityKeyID(x509cert_t *signer) { chunk_t keyIdentifier = (signer->subjectKeyID.ptr == NULL) ? empty_chunk : asn1_simple_object(ASN1_CONTEXT_S_0 , signer->subjectKeyID); chunk_t authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1 , signer->issuer); chunk_t authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2 , signer->serialNumber); return asn1_wrap(ASN1_SEQUENCE, "cm" , ASN1_authorityKeyIdentifier_oid , asn1_wrap(ASN1_OCTET_STRING, "m" , asn1_wrap(ASN1_SEQUENCE, "mmm" , keyIdentifier , authorityCertIssuer , authorityCertSerialNumber ) ) ); } /* * build extensions */ static chunk_t build_extensions(void) { return asn1_wrap(ASN1_SEQUENCE, "mc" , build_authorityKeyID(signer) , ASN1_noRevAvail_ext); } /* * build attributeCertificateInfo */ static chunk_t build_attr_cert_info(void) { return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm" , ASN1_INTEGER_1 , build_holder() , build_v2_form() , ASN1_sha1WithRSA_id , asn1_simple_object(ASN1_INTEGER, serial) , build_attr_cert_validity() , build_attributes() , build_extensions()); } /* * build an X.509 attribute certificate */ chunk_t build_attr_cert(void) { chunk_t attributeCertificateInfo = build_attr_cert_info(); chunk_t signatureValue = pkcs1_build_signature(attributeCertificateInfo , OID_SHA1, signerkey, TRUE); return asn1_wrap(ASN1_SEQUENCE, "mcm" , attributeCertificateInfo , ASN1_sha1WithRSA_id , signatureValue); }