243 lines
5.3 KiB
C
243 lines
5.3 KiB
C
/* 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 <http://www.fsf.org/copyleft/gpl.txt>.
|
|
*
|
|
* 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 <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <freeswan.h>
|
|
|
|
#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);
|
|
}
|