0c6a2be3b14b6ac6711ba0382cded8352278b007
[strongswan.git] / src / openac / build.c
1 /* Build a X.509 attribute certificate
2 * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler
3 * Copyright (C) 2004 Andreas Steffen
4 * Zuercher Hochschule Winterthur, Switzerland
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * RCSID $Id: build.c,v 1.14 2005/09/06 11:47:57 as Exp $
17 */
18
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include <freeswan.h>
23
24 #include "../pluto/constants.h"
25 #include "../pluto/defs.h"
26 #include "../pluto/oid.h"
27 #include "../pluto/asn1.h"
28 #include "../pluto/x509.h"
29 #include "../pluto/log.h"
30
31 #include "build.h"
32
33 static u_char ASN1_group_oid_str[] = {
34 0x06, 0x08,
35 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a ,0x04
36 };
37
38 static const chunk_t ASN1_group_oid = strchunk(ASN1_group_oid_str);
39
40 static u_char ASN1_authorityKeyIdentifier_oid_str[] = {
41 0x06, 0x03,
42 0x55, 0x1d, 0x23
43 };
44
45 static const chunk_t ASN1_authorityKeyIdentifier_oid
46 = strchunk(ASN1_authorityKeyIdentifier_oid_str);
47
48 static u_char ASN1_noRevAvail_ext_str[] = {
49 0x30, 0x09,
50 0x06, 0x03,
51 0x55, 0x1d, 0x38,
52 0x04, 0x02,
53 0x05, 0x00
54 };
55
56 static const chunk_t ASN1_noRevAvail_ext = strchunk(ASN1_noRevAvail_ext_str);
57
58 /**
59 * build directoryName
60 */
61 static chunk_t build_directoryName(asn1_t tag, chunk_t name)
62 {
63 return asn1_wrap(tag, "m",
64 asn1_simple_object(ASN1_CONTEXT_C_4, name));
65 }
66
67 /**
68 * build holder
69 */
70 static chunk_t build_holder(void)
71 {
72 return asn1_wrap(ASN1_SEQUENCE, "mm",
73 asn1_wrap(ASN1_CONTEXT_C_0, "mm",
74 build_directoryName(ASN1_SEQUENCE, user->issuer),
75 asn1_simple_object(ASN1_INTEGER, user->serialNumber)
76 ),
77 build_directoryName(ASN1_CONTEXT_C_1, user->subject));
78 }
79
80 /**
81 * build v2Form
82 */
83 static chunk_t build_v2_form(void)
84 {
85 return asn1_wrap(ASN1_CONTEXT_C_0, "m",
86 build_directoryName(ASN1_SEQUENCE, signer->subject));
87 }
88
89 /**
90 * build attrCertValidityPeriod
91 */
92 static chunk_t build_attr_cert_validity(void)
93 {
94 return asn1_wrap(ASN1_SEQUENCE, "mm",
95 timetoasn1(&notBefore, ASN1_GENERALIZEDTIME),
96 timetoasn1(&notAfter, ASN1_GENERALIZEDTIME));
97 }
98
99 /**
100 * build attributes
101 */
102 static chunk_t build_ietfAttributes(ietfAttrList_t *list)
103 {
104 chunk_t ietfAttributes;
105 ietfAttrList_t *item = list;
106 size_t size = 0;
107 u_char *pos;
108
109 /* precalculate the total size of all values */
110 while (item != NULL)
111 {
112 size_t len = item->attr->value.len;
113
114 size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
115 item = item->next;
116 }
117 pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size);
118
119 while (list != NULL)
120 {
121 ietfAttr_t *attr = list->attr;
122 asn1_t type = ASN1_NULL;
123
124 switch (attr->kind)
125 {
126 case IETF_ATTRIBUTE_OCTETS:
127 type = ASN1_OCTET_STRING;
128 break;
129 case IETF_ATTRIBUTE_STRING:
130 type = ASN1_UTF8STRING;
131 break;
132 case IETF_ATTRIBUTE_OID:
133 type = ASN1_OID;
134 break;
135 }
136 mv_chunk(&pos, asn1_simple_object(type, attr->value));
137
138 list = list->next;
139 }
140
141 return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes);
142 }
143
144 /**
145 * build attribute type
146 */
147 static chunk_t build_attribute_type(const chunk_t type, chunk_t content)
148 {
149 return asn1_wrap(ASN1_SEQUENCE, "cm",
150 type,
151 asn1_wrap(ASN1_SET, "m", content));
152 }
153
154 /**
155 * build attributes
156 */
157 static chunk_t build_attributes(void)
158 {
159 return asn1_wrap(ASN1_SEQUENCE, "m",
160 build_attribute_type(ASN1_group_oid,
161 build_ietfAttributes(groups)));
162 }
163
164 /**
165 * build authorityKeyIdentifier
166 */
167 static chunk_t build_authorityKeyID(x509cert_t *signer)
168 {
169 chunk_t keyIdentifier = (signer->subjectKeyID.ptr == NULL)
170 ? empty_chunk
171 : asn1_simple_object(ASN1_CONTEXT_S_0,
172 signer->subjectKeyID);
173
174 chunk_t authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1,
175 signer->issuer);
176
177 chunk_t authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2,
178 signer->serialNumber);
179
180 return asn1_wrap(ASN1_SEQUENCE, "cm",
181 ASN1_authorityKeyIdentifier_oid,
182 asn1_wrap(ASN1_OCTET_STRING, "m",
183 asn1_wrap(ASN1_SEQUENCE, "mmm",
184 keyIdentifier,
185 authorityCertIssuer,
186 authorityCertSerialNumber
187 )
188 )
189 );
190 }
191
192 /**
193 * build extensions
194 */
195 static chunk_t build_extensions(void)
196 {
197 return asn1_wrap(ASN1_SEQUENCE, "mc",
198 build_authorityKeyID(signer),
199 ASN1_noRevAvail_ext);
200 }
201
202 /**
203 * build attributeCertificateInfo
204 */
205 static chunk_t build_attr_cert_info(void)
206 {
207 return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm",
208 ASN1_INTEGER_1,
209 build_holder(),
210 build_v2_form(),
211 ASN1_sha1WithRSA_id,
212 asn1_simple_object(ASN1_INTEGER, serial),
213 build_attr_cert_validity(),
214 build_attributes(),
215 build_extensions());
216 }
217
218 /**
219 * build an X.509 attribute certificate
220 */
221 chunk_t build_attr_cert(void)
222 {
223 chunk_t attributeCertificateInfo = build_attr_cert_info();
224 chunk_t signatureValue = pkcs1_build_signature(attributeCertificateInfo,
225 OID_SHA1, signerkey, TRUE);
226
227 return asn1_wrap(ASN1_SEQUENCE, "mcm",
228 attributeCertificateInfo,
229 ASN1_sha1WithRSA_id,
230 signatureValue);
231 }