/* 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); }