/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- _hx509_request_init
- _hx509_request_free
- _hx509_request_set_name
- _hx509_request_get_name
- _hx509_request_set_SubjectPublicKeyInfo
- _hx509_request_get_SubjectPublicKeyInfo
- _hx509_request_add_eku
- _hx509_request_add_dns_name
- _hx509_request_add_email
- _hx509_request_to_pkcs10
- _hx509_request_parse
- _hx509_request_print
1 /*
2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include "hx_locl.h"
35 #include <pkcs10_asn1.h>
36 RCSID("$Id$");
37
38 struct hx509_request_data {
39 hx509_name name;
40 SubjectPublicKeyInfo key;
41 ExtKeyUsage eku;
42 GeneralNames san;
43 };
44
45 /*
46 *
47 */
48
49 int
50 _hx509_request_init(hx509_context context, hx509_request *req)
/* [<][>][^][v][top][bottom][index][help] */
51 {
52 *req = calloc(1, sizeof(**req));
53 if (*req == NULL)
54 return ENOMEM;
55
56 return 0;
57 }
58
59 void
60 _hx509_request_free(hx509_request *req)
/* [<][>][^][v][top][bottom][index][help] */
61 {
62 if ((*req)->name)
63 hx509_name_free(&(*req)->name);
64 free_SubjectPublicKeyInfo(&(*req)->key);
65 free_ExtKeyUsage(&(*req)->eku);
66 free_GeneralNames(&(*req)->san);
67 memset(*req, 0, sizeof(**req));
68 free(*req);
69 *req = NULL;
70 }
71
72 int
73 _hx509_request_set_name(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
74 hx509_request req,
75 hx509_name name)
76 {
77 if (req->name)
78 hx509_name_free(&req->name);
79 if (name) {
80 int ret = hx509_name_copy(context, name, &req->name);
81 if (ret)
82 return ret;
83 }
84 return 0;
85 }
86
87 int
88 _hx509_request_get_name(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
89 hx509_request req,
90 hx509_name *name)
91 {
92 if (req->name == NULL) {
93 hx509_set_error_string(context, 0, EINVAL, "Request have no name");
94 return EINVAL;
95 }
96 return hx509_name_copy(context, req->name, name);
97 }
98
99 int
100 _hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
101 hx509_request req,
102 const SubjectPublicKeyInfo *key)
103 {
104 free_SubjectPublicKeyInfo(&req->key);
105 return copy_SubjectPublicKeyInfo(key, &req->key);
106 }
107
108 int
109 _hx509_request_get_SubjectPublicKeyInfo(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
110 hx509_request req,
111 SubjectPublicKeyInfo *key)
112 {
113 return copy_SubjectPublicKeyInfo(&req->key, key);
114 }
115
116 int
117 _hx509_request_add_eku(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
118 hx509_request req,
119 const heim_oid *oid)
120 {
121 void *val;
122 int ret;
123
124 val = realloc(req->eku.val, sizeof(req->eku.val[0]) * (req->eku.len + 1));
125 if (val == NULL)
126 return ENOMEM;
127 req->eku.val = val;
128
129 ret = der_copy_oid(oid, &req->eku.val[req->eku.len]);
130 if (ret)
131 return ret;
132
133 req->eku.len += 1;
134
135 return 0;
136 }
137
138 int
139 _hx509_request_add_dns_name(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
140 hx509_request req,
141 const char *hostname)
142 {
143 GeneralName name;
144
145 memset(&name, 0, sizeof(name));
146 name.element = choice_GeneralName_dNSName;
147 name.u.dNSName = rk_UNCONST(hostname);
148
149 return add_GeneralNames(&req->san, &name);
150 }
151
152 int
153 _hx509_request_add_email(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
154 hx509_request req,
155 const char *email)
156 {
157 GeneralName name;
158
159 memset(&name, 0, sizeof(name));
160 name.element = choice_GeneralName_rfc822Name;
161 name.u.dNSName = rk_UNCONST(email);
162
163 return add_GeneralNames(&req->san, &name);
164 }
165
166
167
168 int
169 _hx509_request_to_pkcs10(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
170 const hx509_request req,
171 const hx509_private_key signer,
172 heim_octet_string *request)
173 {
174 CertificationRequest r;
175 heim_octet_string data, os;
176 int ret;
177 size_t size;
178
179 if (req->name == NULL) {
180 hx509_set_error_string(context, 0, EINVAL,
181 "PKCS10 needs to have a subject");
182 return EINVAL;
183 }
184
185 memset(&r, 0, sizeof(r));
186 memset(request, 0, sizeof(*request));
187
188 r.certificationRequestInfo.version = pkcs10_v1;
189
190 ret = copy_Name(&req->name->der_name,
191 &r.certificationRequestInfo.subject);
192 if (ret)
193 goto out;
194 ret = copy_SubjectPublicKeyInfo(&req->key,
195 &r.certificationRequestInfo.subjectPKInfo);
196 if (ret)
197 goto out;
198 r.certificationRequestInfo.attributes =
199 calloc(1, sizeof(*r.certificationRequestInfo.attributes));
200 if (r.certificationRequestInfo.attributes == NULL) {
201 ret = ENOMEM;
202 goto out;
203 }
204
205 ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length,
206 &r.certificationRequestInfo, &size, ret);
207 if (ret)
208 goto out;
209 if (data.length != size)
210 abort();
211
212 ret = _hx509_create_signature(context,
213 signer,
214 _hx509_crypto_default_sig_alg,
215 &data,
216 &r.signatureAlgorithm,
217 &os);
218 free(data.data);
219 if (ret)
220 goto out;
221 r.signature.data = os.data;
222 r.signature.length = os.length * 8;
223
224 ASN1_MALLOC_ENCODE(CertificationRequest, data.data, data.length,
225 &r, &size, ret);
226 if (ret)
227 goto out;
228 if (data.length != size)
229 abort();
230
231 *request = data;
232
233 out:
234 free_CertificationRequest(&r);
235
236 return ret;
237 }
238
239 int
240 _hx509_request_parse(hx509_context context,
/* [<][>][^][v][top][bottom][index][help] */
241 const char *path,
242 hx509_request *req)
243 {
244 CertificationRequest r;
245 CertificationRequestInfo *rinfo;
246 hx509_name subject;
247 size_t len, size;
248 void *p;
249 int ret;
250
251 if (strncmp(path, "PKCS10:", 7) != 0) {
252 hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
253 "unsupport type in %s", path);
254 return HX509_UNSUPPORTED_OPERATION;
255 }
256 path += 7;
257
258 /* XXX PEM request */
259
260 ret = rk_undumpdata(path, &p, &len);
261 if (ret) {
262 hx509_set_error_string(context, 0, ret, "Failed to map file %s", path);
263 return ret;
264 }
265
266 ret = decode_CertificationRequest(p, len, &r, &size);
267 rk_xfree(p);
268 if (ret) {
269 hx509_set_error_string(context, 0, ret, "Failed to decode %s", path);
270 return ret;
271 }
272
273 ret = _hx509_request_init(context, req);
274 if (ret) {
275 free_CertificationRequest(&r);
276 return ret;
277 }
278
279 rinfo = &r.certificationRequestInfo;
280
281 ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req,
282 &rinfo->subjectPKInfo);
283 if (ret) {
284 free_CertificationRequest(&r);
285 _hx509_request_free(req);
286 return ret;
287 }
288
289 ret = _hx509_name_from_Name(&rinfo->subject, &subject);
290 if (ret) {
291 free_CertificationRequest(&r);
292 _hx509_request_free(req);
293 return ret;
294 }
295 ret = _hx509_request_set_name(context, *req, subject);
296 hx509_name_free(&subject);
297 free_CertificationRequest(&r);
298 if (ret) {
299 _hx509_request_free(req);
300 return ret;
301 }
302
303 return 0;
304 }
305
306
307 int
308 _hx509_request_print(hx509_context context, hx509_request req, FILE *f)
/* [<][>][^][v][top][bottom][index][help] */
309 {
310 int ret;
311
312 if (req->name) {
313 char *subject;
314 ret = hx509_name_to_string(req->name, &subject);
315 if (ret) {
316 hx509_set_error_string(context, 0, ret, "Failed to print name");
317 return ret;
318 }
319 fprintf(f, "name: %s\n", subject);
320 free(subject);
321 }
322
323 return 0;
324 }
325