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