- added ingorelist for builded files
[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
62 build_directoryName(asn1_t tag, chunk_t name)
63 {
64 return asn1_wrap(tag, "m"
65 , asn1_simple_object(ASN1_CONTEXT_C_4, name));
66 }
67
68 /*
69 * build holder
70 */
71 static chunk_t
72 build_holder(void)
73 {
74 return asn1_wrap(ASN1_SEQUENCE, "mm"
75 , asn1_wrap(ASN1_CONTEXT_C_0, "mm"
76 , build_directoryName(ASN1_SEQUENCE, user->issuer)
77 , asn1_simple_object(ASN1_INTEGER, user->serialNumber)
78 )
79 , build_directoryName(ASN1_CONTEXT_C_1, user->subject));
80 }
81
82 /*
83 * build v2Form
84 */
85 static chunk_t
86 build_v2_form(void)
87 {
88 return asn1_wrap(ASN1_CONTEXT_C_0, "m"
89 , build_directoryName(ASN1_SEQUENCE, signer->subject));
90 }
91
92 /*
93 * build attrCertValidityPeriod
94 */
95 static chunk_t
96 build_attr_cert_validity(void)
97 {
98 return asn1_wrap(ASN1_SEQUENCE, "mm"
99 , timetoasn1(&notBefore, ASN1_GENERALIZEDTIME)
100 , timetoasn1(&notAfter, ASN1_GENERALIZEDTIME));
101 }
102
103 /*
104 * build attributes
105 */
106 static chunk_t
107 build_ietfAttributes(ietfAttrList_t *list)
108 {
109 chunk_t ietfAttributes;
110 ietfAttrList_t *item = list;
111 size_t size = 0;
112 u_char *pos;
113
114 /* precalculate the total size of all values */
115 while (item != NULL)
116 {
117 size_t len = item->attr->value.len;
118
119 size += 1 + (len > 0) + (len >= 128) + (len >= 256) + (len >= 65536) + len;
120 item = item->next;
121 }
122 pos = build_asn1_object(&ietfAttributes, ASN1_SEQUENCE, size);
123
124 while (list != NULL)
125 {
126 ietfAttr_t *attr = list->attr;
127 asn1_t type = ASN1_NULL;
128
129 switch (attr->kind)
130 {
131 case IETF_ATTRIBUTE_OCTETS:
132 type = ASN1_OCTET_STRING;
133 break;
134 case IETF_ATTRIBUTE_STRING:
135 type = ASN1_UTF8STRING;
136 break;
137 case IETF_ATTRIBUTE_OID:
138 type = ASN1_OID;
139 break;
140 }
141 mv_chunk(&pos, asn1_simple_object(type, attr->value));
142
143 list = list->next;
144 }
145
146 return asn1_wrap(ASN1_SEQUENCE, "m", ietfAttributes);
147 }
148
149 /*
150 * build attribute type
151 */
152 static chunk_t
153 build_attribute_type(const chunk_t type, chunk_t content)
154 {
155 return asn1_wrap(ASN1_SEQUENCE, "cm"
156 , type
157 , asn1_wrap(ASN1_SET, "m", content));
158 }
159
160 /*
161 * build attributes
162 */
163 static chunk_t
164 build_attributes(void)
165 {
166 return asn1_wrap(ASN1_SEQUENCE, "m"
167 , build_attribute_type(ASN1_group_oid
168 , build_ietfAttributes(groups)));
169 }
170
171 /*
172 * build authorityKeyIdentifier
173 */
174 static chunk_t
175 build_authorityKeyID(x509cert_t *signer)
176 {
177 chunk_t keyIdentifier = (signer->subjectKeyID.ptr == NULL)
178 ? empty_chunk
179 : asn1_simple_object(ASN1_CONTEXT_S_0
180 , signer->subjectKeyID);
181
182 chunk_t authorityCertIssuer = build_directoryName(ASN1_CONTEXT_C_1
183 , signer->issuer);
184
185 chunk_t authorityCertSerialNumber = asn1_simple_object(ASN1_CONTEXT_S_2
186 , signer->serialNumber);
187
188 return asn1_wrap(ASN1_SEQUENCE, "cm"
189 , ASN1_authorityKeyIdentifier_oid
190 , asn1_wrap(ASN1_OCTET_STRING, "m"
191 , asn1_wrap(ASN1_SEQUENCE, "mmm"
192 , keyIdentifier
193 , authorityCertIssuer
194 , authorityCertSerialNumber
195 )
196 )
197 );
198 }
199
200 /*
201 * build extensions
202 */
203 static chunk_t
204 build_extensions(void)
205 {
206 return asn1_wrap(ASN1_SEQUENCE, "mc"
207 , build_authorityKeyID(signer)
208 , ASN1_noRevAvail_ext);
209 }
210
211 /*
212 * build attributeCertificateInfo
213 */
214 static chunk_t
215 build_attr_cert_info(void)
216 {
217 return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm"
218 , ASN1_INTEGER_1
219 , build_holder()
220 , build_v2_form()
221 , ASN1_sha1WithRSA_id
222 , asn1_simple_object(ASN1_INTEGER, serial)
223 , build_attr_cert_validity()
224 , build_attributes()
225 , build_extensions());
226 }
227
228 /*
229 * build an X.509 attribute certificate
230 */
231 chunk_t
232 build_attr_cert(void)
233 {
234 chunk_t attributeCertificateInfo = build_attr_cert_info();
235 chunk_t signatureValue = pkcs1_build_signature(attributeCertificateInfo
236 , OID_SHA1, signerkey, TRUE);
237
238 return asn1_wrap(ASN1_SEQUENCE, "mcm"
239 , attributeCertificateInfo
240 , ASN1_sha1WithRSA_id
241 , signatureValue);
242 }