xref: /freebsd/crypto/heimdal/lib/hx509/ca.c (revision 6a068746777241722b2b32c5d0bc443a2a64d80b)
1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov  * Copyright (c) 2006 - 2010 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 <pkinit_asn1.h>
36c19800e8SDoug Rabson 
37c19800e8SDoug Rabson /**
38c19800e8SDoug Rabson  * @page page_ca Hx509 CA functions
39c19800e8SDoug Rabson  *
40c19800e8SDoug Rabson  * See the library functions here: @ref hx509_ca
41c19800e8SDoug Rabson  */
42c19800e8SDoug Rabson 
43c19800e8SDoug Rabson struct hx509_ca_tbs {
44c19800e8SDoug Rabson     hx509_name subject;
45c19800e8SDoug Rabson     SubjectPublicKeyInfo spki;
46c19800e8SDoug Rabson     ExtKeyUsage eku;
47c19800e8SDoug Rabson     GeneralNames san;
48c19800e8SDoug Rabson     unsigned key_usage;
49c19800e8SDoug Rabson     heim_integer serial;
50c19800e8SDoug Rabson     struct {
51c19800e8SDoug Rabson 	unsigned int proxy:1;
52c19800e8SDoug Rabson 	unsigned int ca:1;
53c19800e8SDoug Rabson 	unsigned int key:1;
54c19800e8SDoug Rabson 	unsigned int serial:1;
55c19800e8SDoug Rabson 	unsigned int domaincontroller:1;
56*ae771770SStanislav Sedov 	unsigned int xUniqueID:1;
57c19800e8SDoug Rabson     } flags;
58c19800e8SDoug Rabson     time_t notBefore;
59c19800e8SDoug Rabson     time_t notAfter;
60c19800e8SDoug Rabson     int pathLenConstraint; /* both for CA and Proxy */
61c19800e8SDoug Rabson     CRLDistributionPoints crldp;
62*ae771770SStanislav Sedov     heim_bit_string subjectUniqueID;
63*ae771770SStanislav Sedov     heim_bit_string issuerUniqueID;
64*ae771770SStanislav Sedov 
65c19800e8SDoug Rabson };
66c19800e8SDoug Rabson 
67c19800e8SDoug Rabson /**
68c19800e8SDoug Rabson  * Allocate an to-be-signed certificate object that will be converted
69c19800e8SDoug Rabson  * into an certificate.
70c19800e8SDoug Rabson  *
71c19800e8SDoug Rabson  * @param context A hx509 context.
72c19800e8SDoug Rabson  * @param tbs returned to-be-signed certicate object, free with
73c19800e8SDoug Rabson  * hx509_ca_tbs_free().
74c19800e8SDoug Rabson  *
75c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
76c19800e8SDoug Rabson  *
77c19800e8SDoug Rabson  * @ingroup hx509_ca
78c19800e8SDoug Rabson  */
79c19800e8SDoug Rabson 
80c19800e8SDoug Rabson int
hx509_ca_tbs_init(hx509_context context,hx509_ca_tbs * tbs)81c19800e8SDoug Rabson hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
82c19800e8SDoug Rabson {
83c19800e8SDoug Rabson     *tbs = calloc(1, sizeof(**tbs));
84c19800e8SDoug Rabson     if (*tbs == NULL)
85c19800e8SDoug Rabson 	return ENOMEM;
86c19800e8SDoug Rabson 
87c19800e8SDoug Rabson     return 0;
88c19800e8SDoug Rabson }
89c19800e8SDoug Rabson 
90c19800e8SDoug Rabson /**
91c19800e8SDoug Rabson  * Free an To Be Signed object.
92c19800e8SDoug Rabson  *
93c19800e8SDoug Rabson  * @param tbs object to free.
94c19800e8SDoug Rabson  *
95c19800e8SDoug Rabson  * @ingroup hx509_ca
96c19800e8SDoug Rabson  */
97c19800e8SDoug Rabson 
98c19800e8SDoug Rabson void
hx509_ca_tbs_free(hx509_ca_tbs * tbs)99c19800e8SDoug Rabson hx509_ca_tbs_free(hx509_ca_tbs *tbs)
100c19800e8SDoug Rabson {
101c19800e8SDoug Rabson     if (tbs == NULL || *tbs == NULL)
102c19800e8SDoug Rabson 	return;
103c19800e8SDoug Rabson 
104c19800e8SDoug Rabson     free_SubjectPublicKeyInfo(&(*tbs)->spki);
105c19800e8SDoug Rabson     free_GeneralNames(&(*tbs)->san);
106c19800e8SDoug Rabson     free_ExtKeyUsage(&(*tbs)->eku);
107c19800e8SDoug Rabson     der_free_heim_integer(&(*tbs)->serial);
108c19800e8SDoug Rabson     free_CRLDistributionPoints(&(*tbs)->crldp);
109*ae771770SStanislav Sedov     der_free_bit_string(&(*tbs)->subjectUniqueID);
110*ae771770SStanislav Sedov     der_free_bit_string(&(*tbs)->issuerUniqueID);
111c19800e8SDoug Rabson     hx509_name_free(&(*tbs)->subject);
112c19800e8SDoug Rabson 
113c19800e8SDoug Rabson     memset(*tbs, 0, sizeof(**tbs));
114c19800e8SDoug Rabson     free(*tbs);
115c19800e8SDoug Rabson     *tbs = NULL;
116c19800e8SDoug Rabson }
117c19800e8SDoug Rabson 
118c19800e8SDoug Rabson /**
119c19800e8SDoug Rabson  * Set the absolute time when the certificate is valid from. If not
120c19800e8SDoug Rabson  * set the current time will be used.
121c19800e8SDoug Rabson  *
122c19800e8SDoug Rabson  * @param context A hx509 context.
123c19800e8SDoug Rabson  * @param tbs object to be signed.
124c19800e8SDoug Rabson  * @param t time the certificated will start to be valid
125c19800e8SDoug Rabson  *
126c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
127c19800e8SDoug Rabson  *
128c19800e8SDoug Rabson  * @ingroup hx509_ca
129c19800e8SDoug Rabson  */
130c19800e8SDoug Rabson 
131c19800e8SDoug Rabson int
hx509_ca_tbs_set_notBefore(hx509_context context,hx509_ca_tbs tbs,time_t t)132c19800e8SDoug Rabson hx509_ca_tbs_set_notBefore(hx509_context context,
133c19800e8SDoug Rabson 			   hx509_ca_tbs tbs,
134c19800e8SDoug Rabson 			   time_t t)
135c19800e8SDoug Rabson {
136c19800e8SDoug Rabson     tbs->notBefore = t;
137c19800e8SDoug Rabson     return 0;
138c19800e8SDoug Rabson }
139c19800e8SDoug Rabson 
140c19800e8SDoug Rabson /**
141c19800e8SDoug Rabson  * Set the absolute time when the certificate is valid to.
142c19800e8SDoug Rabson  *
143c19800e8SDoug Rabson  * @param context A hx509 context.
144c19800e8SDoug Rabson  * @param tbs object to be signed.
145c19800e8SDoug Rabson  * @param t time when the certificate will expire
146c19800e8SDoug Rabson  *
147c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
148c19800e8SDoug Rabson  *
149c19800e8SDoug Rabson  * @ingroup hx509_ca
150c19800e8SDoug Rabson  */
151c19800e8SDoug Rabson 
152c19800e8SDoug Rabson int
hx509_ca_tbs_set_notAfter(hx509_context context,hx509_ca_tbs tbs,time_t t)153c19800e8SDoug Rabson hx509_ca_tbs_set_notAfter(hx509_context context,
154c19800e8SDoug Rabson 			   hx509_ca_tbs tbs,
155c19800e8SDoug Rabson 			   time_t t)
156c19800e8SDoug Rabson {
157c19800e8SDoug Rabson     tbs->notAfter = t;
158c19800e8SDoug Rabson     return 0;
159c19800e8SDoug Rabson }
160c19800e8SDoug Rabson 
161c19800e8SDoug Rabson /**
162c19800e8SDoug Rabson  * Set the relative time when the certificiate is going to expire.
163c19800e8SDoug Rabson  *
164c19800e8SDoug Rabson  * @param context A hx509 context.
165c19800e8SDoug Rabson  * @param tbs object to be signed.
166c19800e8SDoug Rabson  * @param delta seconds to the certificate is going to expire.
167c19800e8SDoug Rabson  *
168c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
169c19800e8SDoug Rabson  *
170c19800e8SDoug Rabson  * @ingroup hx509_ca
171c19800e8SDoug Rabson  */
172c19800e8SDoug Rabson 
173c19800e8SDoug Rabson int
hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,hx509_ca_tbs tbs,time_t delta)174c19800e8SDoug Rabson hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
175c19800e8SDoug Rabson 				   hx509_ca_tbs tbs,
176c19800e8SDoug Rabson 				   time_t delta)
177c19800e8SDoug Rabson {
178c19800e8SDoug Rabson     return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
179c19800e8SDoug Rabson }
180c19800e8SDoug Rabson 
181c19800e8SDoug Rabson static const struct units templatebits[] = {
182c19800e8SDoug Rabson     { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
183c19800e8SDoug Rabson     { "KeyUsage", HX509_CA_TEMPLATE_KU },
184c19800e8SDoug Rabson     { "SPKI", HX509_CA_TEMPLATE_SPKI },
185c19800e8SDoug Rabson     { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
186c19800e8SDoug Rabson     { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
187c19800e8SDoug Rabson     { "serial", HX509_CA_TEMPLATE_SERIAL },
188c19800e8SDoug Rabson     { "subject", HX509_CA_TEMPLATE_SUBJECT },
189c19800e8SDoug Rabson     { NULL, 0 }
190c19800e8SDoug Rabson };
191c19800e8SDoug Rabson 
192c19800e8SDoug Rabson /**
193c19800e8SDoug Rabson  * Make of template units, use to build flags argument to
194c19800e8SDoug Rabson  * hx509_ca_tbs_set_template() with parse_units().
195c19800e8SDoug Rabson  *
196c19800e8SDoug Rabson  * @return an units structure.
197c19800e8SDoug Rabson  *
198c19800e8SDoug Rabson  * @ingroup hx509_ca
199c19800e8SDoug Rabson  */
200c19800e8SDoug Rabson 
201c19800e8SDoug Rabson const struct units *
hx509_ca_tbs_template_units(void)202c19800e8SDoug Rabson hx509_ca_tbs_template_units(void)
203c19800e8SDoug Rabson {
204c19800e8SDoug Rabson     return templatebits;
205c19800e8SDoug Rabson }
206c19800e8SDoug Rabson 
207c19800e8SDoug Rabson /**
208c19800e8SDoug Rabson  * Initialize the to-be-signed certificate object from a template certifiate.
209c19800e8SDoug Rabson  *
210c19800e8SDoug Rabson  * @param context A hx509 context.
211c19800e8SDoug Rabson  * @param tbs object to be signed.
212c19800e8SDoug Rabson  * @param flags bit field selecting what to copy from the template
213c19800e8SDoug Rabson  * certifiate.
214c19800e8SDoug Rabson  * @param cert template certificate.
215c19800e8SDoug Rabson  *
216c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
217c19800e8SDoug Rabson  *
218c19800e8SDoug Rabson  * @ingroup hx509_ca
219c19800e8SDoug Rabson  */
220c19800e8SDoug Rabson 
221c19800e8SDoug Rabson int
hx509_ca_tbs_set_template(hx509_context context,hx509_ca_tbs tbs,int flags,hx509_cert cert)222c19800e8SDoug Rabson hx509_ca_tbs_set_template(hx509_context context,
223c19800e8SDoug Rabson 			  hx509_ca_tbs tbs,
224c19800e8SDoug Rabson 			  int flags,
225c19800e8SDoug Rabson 			  hx509_cert cert)
226c19800e8SDoug Rabson {
227c19800e8SDoug Rabson     int ret;
228c19800e8SDoug Rabson 
229c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_SUBJECT) {
230c19800e8SDoug Rabson 	if (tbs->subject)
231c19800e8SDoug Rabson 	    hx509_name_free(&tbs->subject);
232c19800e8SDoug Rabson 	ret = hx509_cert_get_subject(cert, &tbs->subject);
233c19800e8SDoug Rabson 	if (ret) {
234c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret,
235c19800e8SDoug Rabson 				   "Failed to get subject from template");
236c19800e8SDoug Rabson 	    return ret;
237c19800e8SDoug Rabson 	}
238c19800e8SDoug Rabson     }
239c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_SERIAL) {
240c19800e8SDoug Rabson 	der_free_heim_integer(&tbs->serial);
241c19800e8SDoug Rabson 	ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
242c19800e8SDoug Rabson 	tbs->flags.serial = !ret;
243c19800e8SDoug Rabson 	if (ret) {
244c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret,
245c19800e8SDoug Rabson 				   "Failed to copy serial number");
246c19800e8SDoug Rabson 	    return ret;
247c19800e8SDoug Rabson 	}
248c19800e8SDoug Rabson     }
249c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
250c19800e8SDoug Rabson 	tbs->notBefore = hx509_cert_get_notBefore(cert);
251c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_NOTAFTER)
252c19800e8SDoug Rabson 	tbs->notAfter = hx509_cert_get_notAfter(cert);
253c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_SPKI) {
254c19800e8SDoug Rabson 	free_SubjectPublicKeyInfo(&tbs->spki);
255c19800e8SDoug Rabson 	ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
256c19800e8SDoug Rabson 	tbs->flags.key = !ret;
257c19800e8SDoug Rabson 	if (ret)
258c19800e8SDoug Rabson 	    return ret;
259c19800e8SDoug Rabson     }
260c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_KU) {
261c19800e8SDoug Rabson 	KeyUsage ku;
262c19800e8SDoug Rabson 	ret = _hx509_cert_get_keyusage(context, cert, &ku);
263c19800e8SDoug Rabson 	if (ret)
264c19800e8SDoug Rabson 	    return ret;
265c19800e8SDoug Rabson 	tbs->key_usage = KeyUsage2int(ku);
266c19800e8SDoug Rabson     }
267c19800e8SDoug Rabson     if (flags & HX509_CA_TEMPLATE_EKU) {
268c19800e8SDoug Rabson 	ExtKeyUsage eku;
269*ae771770SStanislav Sedov 	size_t i;
270c19800e8SDoug Rabson 	ret = _hx509_cert_get_eku(context, cert, &eku);
271c19800e8SDoug Rabson 	if (ret)
272c19800e8SDoug Rabson 	    return ret;
273c19800e8SDoug Rabson 	for (i = 0; i < eku.len; i++) {
274c19800e8SDoug Rabson 	    ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
275c19800e8SDoug Rabson 	    if (ret) {
276c19800e8SDoug Rabson 		free_ExtKeyUsage(&eku);
277c19800e8SDoug Rabson 		return ret;
278c19800e8SDoug Rabson 	    }
279c19800e8SDoug Rabson 	}
280c19800e8SDoug Rabson 	free_ExtKeyUsage(&eku);
281c19800e8SDoug Rabson     }
282c19800e8SDoug Rabson     return 0;
283c19800e8SDoug Rabson }
284c19800e8SDoug Rabson 
285c19800e8SDoug Rabson /**
286c19800e8SDoug Rabson  * Make the to-be-signed certificate object a CA certificate. If the
287c19800e8SDoug Rabson  * pathLenConstraint is negative path length constraint is used.
288c19800e8SDoug Rabson  *
289c19800e8SDoug Rabson  * @param context A hx509 context.
290c19800e8SDoug Rabson  * @param tbs object to be signed.
291c19800e8SDoug Rabson  * @param pathLenConstraint path length constraint, negative, no
292c19800e8SDoug Rabson  * constraint.
293c19800e8SDoug Rabson  *
294c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
295c19800e8SDoug Rabson  *
296c19800e8SDoug Rabson  * @ingroup hx509_ca
297c19800e8SDoug Rabson  */
298c19800e8SDoug Rabson 
299c19800e8SDoug Rabson int
hx509_ca_tbs_set_ca(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)300c19800e8SDoug Rabson hx509_ca_tbs_set_ca(hx509_context context,
301c19800e8SDoug Rabson 		    hx509_ca_tbs tbs,
302c19800e8SDoug Rabson 		    int pathLenConstraint)
303c19800e8SDoug Rabson {
304c19800e8SDoug Rabson     tbs->flags.ca = 1;
305c19800e8SDoug Rabson     tbs->pathLenConstraint = pathLenConstraint;
306c19800e8SDoug Rabson     return 0;
307c19800e8SDoug Rabson }
308c19800e8SDoug Rabson 
309c19800e8SDoug Rabson /**
310c19800e8SDoug Rabson  * Make the to-be-signed certificate object a proxy certificate. If the
311c19800e8SDoug Rabson  * pathLenConstraint is negative path length constraint is used.
312c19800e8SDoug Rabson  *
313c19800e8SDoug Rabson  * @param context A hx509 context.
314c19800e8SDoug Rabson  * @param tbs object to be signed.
315c19800e8SDoug Rabson  * @param pathLenConstraint path length constraint, negative, no
316c19800e8SDoug Rabson  * constraint.
317c19800e8SDoug Rabson  *
318c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
319c19800e8SDoug Rabson  *
320c19800e8SDoug Rabson  * @ingroup hx509_ca
321c19800e8SDoug Rabson  */
322c19800e8SDoug Rabson 
323c19800e8SDoug Rabson int
hx509_ca_tbs_set_proxy(hx509_context context,hx509_ca_tbs tbs,int pathLenConstraint)324c19800e8SDoug Rabson hx509_ca_tbs_set_proxy(hx509_context context,
325c19800e8SDoug Rabson 		       hx509_ca_tbs tbs,
326c19800e8SDoug Rabson 		       int pathLenConstraint)
327c19800e8SDoug Rabson {
328c19800e8SDoug Rabson     tbs->flags.proxy = 1;
329c19800e8SDoug Rabson     tbs->pathLenConstraint = pathLenConstraint;
330c19800e8SDoug Rabson     return 0;
331c19800e8SDoug Rabson }
332c19800e8SDoug Rabson 
333c19800e8SDoug Rabson 
334c19800e8SDoug Rabson /**
335c19800e8SDoug Rabson  * Make the to-be-signed certificate object a windows domain controller certificate.
336c19800e8SDoug Rabson  *
337c19800e8SDoug Rabson  * @param context A hx509 context.
338c19800e8SDoug Rabson  * @param tbs object to be signed.
339c19800e8SDoug Rabson  *
340c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
341c19800e8SDoug Rabson  *
342c19800e8SDoug Rabson  * @ingroup hx509_ca
343c19800e8SDoug Rabson  */
344c19800e8SDoug Rabson 
345c19800e8SDoug Rabson int
hx509_ca_tbs_set_domaincontroller(hx509_context context,hx509_ca_tbs tbs)346c19800e8SDoug Rabson hx509_ca_tbs_set_domaincontroller(hx509_context context,
347c19800e8SDoug Rabson 				  hx509_ca_tbs tbs)
348c19800e8SDoug Rabson {
349c19800e8SDoug Rabson     tbs->flags.domaincontroller = 1;
350c19800e8SDoug Rabson     return 0;
351c19800e8SDoug Rabson }
352c19800e8SDoug Rabson 
353c19800e8SDoug Rabson /**
354c19800e8SDoug Rabson  * Set the subject public key info (SPKI) in the to-be-signed certificate
355c19800e8SDoug Rabson  * object. SPKI is the public key and key related parameters in the
356c19800e8SDoug Rabson  * certificate.
357c19800e8SDoug Rabson  *
358c19800e8SDoug Rabson  * @param context A hx509 context.
359c19800e8SDoug Rabson  * @param tbs object to be signed.
360c19800e8SDoug Rabson  * @param spki subject public key info to use for the to-be-signed certificate object.
361c19800e8SDoug Rabson  *
362c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
363c19800e8SDoug Rabson  *
364c19800e8SDoug Rabson  * @ingroup hx509_ca
365c19800e8SDoug Rabson  */
366c19800e8SDoug Rabson 
367c19800e8SDoug Rabson int
hx509_ca_tbs_set_spki(hx509_context context,hx509_ca_tbs tbs,const SubjectPublicKeyInfo * spki)368c19800e8SDoug Rabson hx509_ca_tbs_set_spki(hx509_context context,
369c19800e8SDoug Rabson 		      hx509_ca_tbs tbs,
370c19800e8SDoug Rabson 		      const SubjectPublicKeyInfo *spki)
371c19800e8SDoug Rabson {
372c19800e8SDoug Rabson     int ret;
373c19800e8SDoug Rabson     free_SubjectPublicKeyInfo(&tbs->spki);
374c19800e8SDoug Rabson     ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
375c19800e8SDoug Rabson     tbs->flags.key = !ret;
376c19800e8SDoug Rabson     return ret;
377c19800e8SDoug Rabson }
378c19800e8SDoug Rabson 
379c19800e8SDoug Rabson /**
380c19800e8SDoug Rabson  * Set the serial number to use for to-be-signed certificate object.
381c19800e8SDoug Rabson  *
382c19800e8SDoug Rabson  * @param context A hx509 context.
383c19800e8SDoug Rabson  * @param tbs object to be signed.
384c19800e8SDoug Rabson  * @param serialNumber serial number to use for the to-be-signed
385c19800e8SDoug Rabson  * certificate object.
386c19800e8SDoug Rabson  *
387c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
388c19800e8SDoug Rabson  *
389c19800e8SDoug Rabson  * @ingroup hx509_ca
390c19800e8SDoug Rabson  */
391c19800e8SDoug Rabson 
392c19800e8SDoug Rabson int
hx509_ca_tbs_set_serialnumber(hx509_context context,hx509_ca_tbs tbs,const heim_integer * serialNumber)393c19800e8SDoug Rabson hx509_ca_tbs_set_serialnumber(hx509_context context,
394c19800e8SDoug Rabson 			      hx509_ca_tbs tbs,
395c19800e8SDoug Rabson 			      const heim_integer *serialNumber)
396c19800e8SDoug Rabson {
397c19800e8SDoug Rabson     int ret;
398c19800e8SDoug Rabson     der_free_heim_integer(&tbs->serial);
399c19800e8SDoug Rabson     ret = der_copy_heim_integer(serialNumber, &tbs->serial);
400c19800e8SDoug Rabson     tbs->flags.serial = !ret;
401c19800e8SDoug Rabson     return ret;
402c19800e8SDoug Rabson }
403c19800e8SDoug Rabson 
404c19800e8SDoug Rabson /**
405c19800e8SDoug Rabson  * An an extended key usage to the to-be-signed certificate object.
406c19800e8SDoug Rabson  * Duplicates will detected and not added.
407c19800e8SDoug Rabson  *
408c19800e8SDoug Rabson  * @param context A hx509 context.
409c19800e8SDoug Rabson  * @param tbs object to be signed.
410c19800e8SDoug Rabson  * @param oid extended key usage to add.
411c19800e8SDoug Rabson  *
412c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
413c19800e8SDoug Rabson  *
414c19800e8SDoug Rabson  * @ingroup hx509_ca
415c19800e8SDoug Rabson  */
416c19800e8SDoug Rabson 
417c19800e8SDoug Rabson int
hx509_ca_tbs_add_eku(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid)418c19800e8SDoug Rabson hx509_ca_tbs_add_eku(hx509_context context,
419c19800e8SDoug Rabson 		     hx509_ca_tbs tbs,
420c19800e8SDoug Rabson 		     const heim_oid *oid)
421c19800e8SDoug Rabson {
422c19800e8SDoug Rabson     void *ptr;
423c19800e8SDoug Rabson     int ret;
424c19800e8SDoug Rabson     unsigned i;
425c19800e8SDoug Rabson 
426c19800e8SDoug Rabson     /* search for duplicates */
427c19800e8SDoug Rabson     for (i = 0; i < tbs->eku.len; i++) {
428c19800e8SDoug Rabson 	if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
429c19800e8SDoug Rabson 	    return 0;
430c19800e8SDoug Rabson     }
431c19800e8SDoug Rabson 
432c19800e8SDoug Rabson     ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
433c19800e8SDoug Rabson     if (ptr == NULL) {
434c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
435c19800e8SDoug Rabson 	return ENOMEM;
436c19800e8SDoug Rabson     }
437c19800e8SDoug Rabson     tbs->eku.val = ptr;
438c19800e8SDoug Rabson     ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
439c19800e8SDoug Rabson     if (ret) {
440c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "out of memory");
441c19800e8SDoug Rabson 	return ret;
442c19800e8SDoug Rabson     }
443c19800e8SDoug Rabson     tbs->eku.len += 1;
444c19800e8SDoug Rabson     return 0;
445c19800e8SDoug Rabson }
446c19800e8SDoug Rabson 
447c19800e8SDoug Rabson /**
448c19800e8SDoug Rabson  * Add CRL distribution point URI to the to-be-signed certificate
449c19800e8SDoug Rabson  * object.
450c19800e8SDoug Rabson  *
451c19800e8SDoug Rabson  * @param context A hx509 context.
452c19800e8SDoug Rabson  * @param tbs object to be signed.
453c19800e8SDoug Rabson  * @param uri uri to the CRL.
454c19800e8SDoug Rabson  * @param issuername name of the issuer.
455c19800e8SDoug Rabson  *
456c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
457c19800e8SDoug Rabson  *
458c19800e8SDoug Rabson  * @ingroup hx509_ca
459c19800e8SDoug Rabson  */
460c19800e8SDoug Rabson 
461c19800e8SDoug Rabson int
hx509_ca_tbs_add_crl_dp_uri(hx509_context context,hx509_ca_tbs tbs,const char * uri,hx509_name issuername)462c19800e8SDoug Rabson hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
463c19800e8SDoug Rabson 			    hx509_ca_tbs tbs,
464c19800e8SDoug Rabson 			    const char *uri,
465c19800e8SDoug Rabson 			    hx509_name issuername)
466c19800e8SDoug Rabson {
467c19800e8SDoug Rabson     DistributionPoint dp;
468c19800e8SDoug Rabson     int ret;
469c19800e8SDoug Rabson 
470c19800e8SDoug Rabson     memset(&dp, 0, sizeof(dp));
471c19800e8SDoug Rabson 
472c19800e8SDoug Rabson     dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
473c19800e8SDoug Rabson 
474c19800e8SDoug Rabson     {
475c19800e8SDoug Rabson 	DistributionPointName name;
476c19800e8SDoug Rabson 	GeneralName gn;
477c19800e8SDoug Rabson 	size_t size;
478c19800e8SDoug Rabson 
479c19800e8SDoug Rabson 	name.element = choice_DistributionPointName_fullName;
480c19800e8SDoug Rabson 	name.u.fullName.len = 1;
481c19800e8SDoug Rabson 	name.u.fullName.val = &gn;
482c19800e8SDoug Rabson 
483c19800e8SDoug Rabson 	gn.element = choice_GeneralName_uniformResourceIdentifier;
484*ae771770SStanislav Sedov 	gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
485*ae771770SStanislav Sedov 	gn.u.uniformResourceIdentifier.length = strlen(uri);
486c19800e8SDoug Rabson 
487c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(DistributionPointName,
488c19800e8SDoug Rabson 			   dp.distributionPoint->data,
489c19800e8SDoug Rabson 			   dp.distributionPoint->length,
490c19800e8SDoug Rabson 			   &name, &size, ret);
491c19800e8SDoug Rabson 	if (ret) {
492c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret,
493c19800e8SDoug Rabson 				   "Failed to encoded DistributionPointName");
494c19800e8SDoug Rabson 	    goto out;
495c19800e8SDoug Rabson 	}
496c19800e8SDoug Rabson 	if (dp.distributionPoint->length != size)
497c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
498c19800e8SDoug Rabson     }
499c19800e8SDoug Rabson 
500c19800e8SDoug Rabson     if (issuername) {
501c19800e8SDoug Rabson #if 1
502c19800e8SDoug Rabson 	/**
503c19800e8SDoug Rabson 	 * issuername not supported
504c19800e8SDoug Rabson 	 */
505c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, EINVAL,
506c19800e8SDoug Rabson 			       "CRLDistributionPoints.name.issuername not yet supported");
507c19800e8SDoug Rabson 	return EINVAL;
508c19800e8SDoug Rabson #else
509c19800e8SDoug Rabson 	GeneralNames *crlissuer;
510c19800e8SDoug Rabson 	GeneralName gn;
511c19800e8SDoug Rabson 	Name n;
512c19800e8SDoug Rabson 
513c19800e8SDoug Rabson 	crlissuer = calloc(1, sizeof(*crlissuer));
514c19800e8SDoug Rabson 	if (crlissuer == NULL) {
515c19800e8SDoug Rabson 	    return ENOMEM;
516c19800e8SDoug Rabson 	}
517c19800e8SDoug Rabson 	memset(&gn, 0, sizeof(gn));
518c19800e8SDoug Rabson 
519c19800e8SDoug Rabson 	gn.element = choice_GeneralName_directoryName;
520c19800e8SDoug Rabson 	ret = hx509_name_to_Name(issuername, &n);
521c19800e8SDoug Rabson 	if (ret) {
522c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "out of memory");
523c19800e8SDoug Rabson 	    goto out;
524c19800e8SDoug Rabson 	}
525c19800e8SDoug Rabson 
526c19800e8SDoug Rabson 	gn.u.directoryName.element = n.element;
527c19800e8SDoug Rabson 	gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
528c19800e8SDoug Rabson 
529c19800e8SDoug Rabson 	ret = add_GeneralNames(&crlissuer, &gn);
530c19800e8SDoug Rabson 	free_Name(&n);
531c19800e8SDoug Rabson 	if (ret) {
532c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "out of memory");
533c19800e8SDoug Rabson 	    goto out;
534c19800e8SDoug Rabson 	}
535c19800e8SDoug Rabson 
536c19800e8SDoug Rabson 	dp.cRLIssuer = &crlissuer;
537c19800e8SDoug Rabson #endif
538c19800e8SDoug Rabson     }
539c19800e8SDoug Rabson 
540c19800e8SDoug Rabson     ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
541c19800e8SDoug Rabson     if (ret) {
542c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "out of memory");
543c19800e8SDoug Rabson 	goto out;
544c19800e8SDoug Rabson     }
545c19800e8SDoug Rabson 
546c19800e8SDoug Rabson out:
547c19800e8SDoug Rabson     free_DistributionPoint(&dp);
548c19800e8SDoug Rabson 
549c19800e8SDoug Rabson     return ret;
550c19800e8SDoug Rabson }
551c19800e8SDoug Rabson 
552c19800e8SDoug Rabson /**
553c19800e8SDoug Rabson  * Add Subject Alternative Name otherName to the to-be-signed
554c19800e8SDoug Rabson  * certificate object.
555c19800e8SDoug Rabson  *
556c19800e8SDoug Rabson  * @param context A hx509 context.
557c19800e8SDoug Rabson  * @param tbs object to be signed.
558c19800e8SDoug Rabson  * @param oid the oid of the OtherName.
559c19800e8SDoug Rabson  * @param os data in the other name.
560c19800e8SDoug Rabson  *
561c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
562c19800e8SDoug Rabson  *
563c19800e8SDoug Rabson  * @ingroup hx509_ca
564c19800e8SDoug Rabson  */
565c19800e8SDoug Rabson 
566c19800e8SDoug Rabson int
hx509_ca_tbs_add_san_otherName(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const heim_octet_string * os)567c19800e8SDoug Rabson hx509_ca_tbs_add_san_otherName(hx509_context context,
568c19800e8SDoug Rabson 			       hx509_ca_tbs tbs,
569c19800e8SDoug Rabson 			       const heim_oid *oid,
570c19800e8SDoug Rabson 			       const heim_octet_string *os)
571c19800e8SDoug Rabson {
572c19800e8SDoug Rabson     GeneralName gn;
573c19800e8SDoug Rabson 
574c19800e8SDoug Rabson     memset(&gn, 0, sizeof(gn));
575c19800e8SDoug Rabson     gn.element = choice_GeneralName_otherName;
576c19800e8SDoug Rabson     gn.u.otherName.type_id = *oid;
577c19800e8SDoug Rabson     gn.u.otherName.value = *os;
578c19800e8SDoug Rabson 
579c19800e8SDoug Rabson     return add_GeneralNames(&tbs->san, &gn);
580c19800e8SDoug Rabson }
581c19800e8SDoug Rabson 
582c19800e8SDoug Rabson /**
583c19800e8SDoug Rabson  * Add Kerberos Subject Alternative Name to the to-be-signed
584c19800e8SDoug Rabson  * certificate object. The principal string is a UTF8 string.
585c19800e8SDoug Rabson  *
586c19800e8SDoug Rabson  * @param context A hx509 context.
587c19800e8SDoug Rabson  * @param tbs object to be signed.
588c19800e8SDoug Rabson  * @param principal Kerberos principal to add to the certificate.
589c19800e8SDoug Rabson  *
590c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
591c19800e8SDoug Rabson  *
592c19800e8SDoug Rabson  * @ingroup hx509_ca
593c19800e8SDoug Rabson  */
594c19800e8SDoug Rabson 
595c19800e8SDoug Rabson int
hx509_ca_tbs_add_san_pkinit(hx509_context context,hx509_ca_tbs tbs,const char * principal)596c19800e8SDoug Rabson hx509_ca_tbs_add_san_pkinit(hx509_context context,
597c19800e8SDoug Rabson 			    hx509_ca_tbs tbs,
598c19800e8SDoug Rabson 			    const char *principal)
599c19800e8SDoug Rabson {
600c19800e8SDoug Rabson     heim_octet_string os;
601c19800e8SDoug Rabson     KRB5PrincipalName p;
602c19800e8SDoug Rabson     size_t size;
603c19800e8SDoug Rabson     int ret;
604c19800e8SDoug Rabson     char *s = NULL;
605c19800e8SDoug Rabson 
606c19800e8SDoug Rabson     memset(&p, 0, sizeof(p));
607c19800e8SDoug Rabson 
608c19800e8SDoug Rabson     /* parse principal */
609c19800e8SDoug Rabson     {
610c19800e8SDoug Rabson 	const char *str;
611c19800e8SDoug Rabson 	char *q;
612c19800e8SDoug Rabson 	int n;
613c19800e8SDoug Rabson 
614c19800e8SDoug Rabson 	/* count number of component */
615c19800e8SDoug Rabson 	n = 1;
616c19800e8SDoug Rabson 	for(str = principal; *str != '\0' && *str != '@'; str++){
617c19800e8SDoug Rabson 	    if(*str=='\\'){
618c19800e8SDoug Rabson 		if(str[1] == '\0' || str[1] == '@') {
619c19800e8SDoug Rabson 		    ret = HX509_PARSING_NAME_FAILED;
620c19800e8SDoug Rabson 		    hx509_set_error_string(context, 0, ret,
621c19800e8SDoug Rabson 					   "trailing \\ in principal name");
622c19800e8SDoug Rabson 		    goto out;
623c19800e8SDoug Rabson 		}
624c19800e8SDoug Rabson 		str++;
625c19800e8SDoug Rabson 	    } else if(*str == '/')
626c19800e8SDoug Rabson 		n++;
627c19800e8SDoug Rabson 	}
628c19800e8SDoug Rabson 	p.principalName.name_string.val =
629c19800e8SDoug Rabson 	    calloc(n, sizeof(*p.principalName.name_string.val));
630c19800e8SDoug Rabson 	if (p.principalName.name_string.val == NULL) {
631c19800e8SDoug Rabson 	    ret = ENOMEM;
632c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "malloc: out of memory");
633c19800e8SDoug Rabson 	    goto out;
634c19800e8SDoug Rabson 	}
635c19800e8SDoug Rabson 	p.principalName.name_string.len = n;
636c19800e8SDoug Rabson 
637c19800e8SDoug Rabson 	p.principalName.name_type = KRB5_NT_PRINCIPAL;
638c19800e8SDoug Rabson 	q = s = strdup(principal);
639c19800e8SDoug Rabson 	if (q == NULL) {
640c19800e8SDoug Rabson 	    ret = ENOMEM;
641c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "malloc: out of memory");
642c19800e8SDoug Rabson 	    goto out;
643c19800e8SDoug Rabson 	}
644c19800e8SDoug Rabson 	p.realm = strrchr(q, '@');
645c19800e8SDoug Rabson 	if (p.realm == NULL) {
646c19800e8SDoug Rabson 	    ret = HX509_PARSING_NAME_FAILED;
647c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Missing @ in principal");
648c19800e8SDoug Rabson 	    goto out;
649c19800e8SDoug Rabson 	};
650c19800e8SDoug Rabson 	*p.realm++ = '\0';
651c19800e8SDoug Rabson 
652c19800e8SDoug Rabson 	n = 0;
653c19800e8SDoug Rabson 	while (q) {
654c19800e8SDoug Rabson 	    p.principalName.name_string.val[n++] = q;
655c19800e8SDoug Rabson 	    q = strchr(q, '/');
656c19800e8SDoug Rabson 	    if (q)
657c19800e8SDoug Rabson 		*q++ = '\0';
658c19800e8SDoug Rabson 	}
659c19800e8SDoug Rabson     }
660c19800e8SDoug Rabson 
661c19800e8SDoug Rabson     ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
662c19800e8SDoug Rabson     if (ret) {
663c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
664c19800e8SDoug Rabson 	goto out;
665c19800e8SDoug Rabson     }
666c19800e8SDoug Rabson     if (size != os.length)
667c19800e8SDoug Rabson 	_hx509_abort("internal ASN.1 encoder error");
668c19800e8SDoug Rabson 
669c19800e8SDoug Rabson     ret = hx509_ca_tbs_add_san_otherName(context,
670c19800e8SDoug Rabson 					 tbs,
671*ae771770SStanislav Sedov 					 &asn1_oid_id_pkinit_san,
672c19800e8SDoug Rabson 					 &os);
673c19800e8SDoug Rabson     free(os.data);
674c19800e8SDoug Rabson out:
675c19800e8SDoug Rabson     if (p.principalName.name_string.val)
676c19800e8SDoug Rabson 	free (p.principalName.name_string.val);
677c19800e8SDoug Rabson     if (s)
678c19800e8SDoug Rabson 	free(s);
679c19800e8SDoug Rabson     return ret;
680c19800e8SDoug Rabson }
681c19800e8SDoug Rabson 
682c19800e8SDoug Rabson /*
683c19800e8SDoug Rabson  *
684c19800e8SDoug Rabson  */
685c19800e8SDoug Rabson 
686c19800e8SDoug Rabson static int
add_utf8_san(hx509_context context,hx509_ca_tbs tbs,const heim_oid * oid,const char * string)687c19800e8SDoug Rabson add_utf8_san(hx509_context context,
688c19800e8SDoug Rabson 	     hx509_ca_tbs tbs,
689c19800e8SDoug Rabson 	     const heim_oid *oid,
690c19800e8SDoug Rabson 	     const char *string)
691c19800e8SDoug Rabson {
692*ae771770SStanislav Sedov     const PKIXXmppAddr ustring = (const PKIXXmppAddr)(intptr_t)string;
693c19800e8SDoug Rabson     heim_octet_string os;
694c19800e8SDoug Rabson     size_t size;
695c19800e8SDoug Rabson     int ret;
696c19800e8SDoug Rabson 
697c19800e8SDoug Rabson     os.length = 0;
698c19800e8SDoug Rabson     os.data = NULL;
699c19800e8SDoug Rabson 
700c19800e8SDoug Rabson     ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
701c19800e8SDoug Rabson     if (ret) {
702c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
703c19800e8SDoug Rabson 	goto out;
704c19800e8SDoug Rabson     }
705c19800e8SDoug Rabson     if (size != os.length)
706c19800e8SDoug Rabson 	_hx509_abort("internal ASN.1 encoder error");
707c19800e8SDoug Rabson 
708c19800e8SDoug Rabson     ret = hx509_ca_tbs_add_san_otherName(context,
709c19800e8SDoug Rabson 					 tbs,
710c19800e8SDoug Rabson 					 oid,
711c19800e8SDoug Rabson 					 &os);
712c19800e8SDoug Rabson     free(os.data);
713c19800e8SDoug Rabson out:
714c19800e8SDoug Rabson     return ret;
715c19800e8SDoug Rabson }
716c19800e8SDoug Rabson 
717c19800e8SDoug Rabson /**
718c19800e8SDoug Rabson  * Add Microsoft UPN Subject Alternative Name to the to-be-signed
719c19800e8SDoug Rabson  * certificate object. The principal string is a UTF8 string.
720c19800e8SDoug Rabson  *
721c19800e8SDoug Rabson  * @param context A hx509 context.
722c19800e8SDoug Rabson  * @param tbs object to be signed.
723c19800e8SDoug Rabson  * @param principal Microsoft UPN string.
724c19800e8SDoug Rabson  *
725c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
726c19800e8SDoug Rabson  *
727c19800e8SDoug Rabson  * @ingroup hx509_ca
728c19800e8SDoug Rabson  */
729c19800e8SDoug Rabson 
730c19800e8SDoug Rabson int
hx509_ca_tbs_add_san_ms_upn(hx509_context context,hx509_ca_tbs tbs,const char * principal)731c19800e8SDoug Rabson hx509_ca_tbs_add_san_ms_upn(hx509_context context,
732c19800e8SDoug Rabson 			    hx509_ca_tbs tbs,
733c19800e8SDoug Rabson 			    const char *principal)
734c19800e8SDoug Rabson {
735*ae771770SStanislav Sedov     return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
736c19800e8SDoug Rabson }
737c19800e8SDoug Rabson 
738c19800e8SDoug Rabson /**
739c19800e8SDoug Rabson  * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
740c19800e8SDoug Rabson  * certificate object. The jid is an UTF8 string.
741c19800e8SDoug Rabson  *
742c19800e8SDoug Rabson  * @param context A hx509 context.
743c19800e8SDoug Rabson  * @param tbs object to be signed.
744c19800e8SDoug Rabson  * @param jid string of an a jabber id in UTF8.
745c19800e8SDoug Rabson  *
746c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
747c19800e8SDoug Rabson  *
748c19800e8SDoug Rabson  * @ingroup hx509_ca
749c19800e8SDoug Rabson  */
750c19800e8SDoug Rabson 
751c19800e8SDoug Rabson int
hx509_ca_tbs_add_san_jid(hx509_context context,hx509_ca_tbs tbs,const char * jid)752c19800e8SDoug Rabson hx509_ca_tbs_add_san_jid(hx509_context context,
753c19800e8SDoug Rabson 			 hx509_ca_tbs tbs,
754c19800e8SDoug Rabson 			 const char *jid)
755c19800e8SDoug Rabson {
756*ae771770SStanislav Sedov     return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
757c19800e8SDoug Rabson }
758c19800e8SDoug Rabson 
759c19800e8SDoug Rabson 
760c19800e8SDoug Rabson /**
761c19800e8SDoug Rabson  * Add a Subject Alternative Name hostname to to-be-signed certificate
762c19800e8SDoug Rabson  * object. A domain match starts with ., an exact match does not.
763c19800e8SDoug Rabson  *
764c19800e8SDoug Rabson  * Example of a an domain match: .domain.se matches the hostname
765c19800e8SDoug Rabson  * host.domain.se.
766c19800e8SDoug Rabson  *
767c19800e8SDoug Rabson  * @param context A hx509 context.
768c19800e8SDoug Rabson  * @param tbs object to be signed.
769c19800e8SDoug Rabson  * @param dnsname a hostame.
770c19800e8SDoug Rabson  *
771c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
772c19800e8SDoug Rabson  *
773c19800e8SDoug Rabson  * @ingroup hx509_ca
774c19800e8SDoug Rabson  */
775c19800e8SDoug Rabson 
776c19800e8SDoug Rabson int
hx509_ca_tbs_add_san_hostname(hx509_context context,hx509_ca_tbs tbs,const char * dnsname)777c19800e8SDoug Rabson hx509_ca_tbs_add_san_hostname(hx509_context context,
778c19800e8SDoug Rabson 			      hx509_ca_tbs tbs,
779c19800e8SDoug Rabson 			      const char *dnsname)
780c19800e8SDoug Rabson {
781c19800e8SDoug Rabson     GeneralName gn;
782c19800e8SDoug Rabson 
783c19800e8SDoug Rabson     memset(&gn, 0, sizeof(gn));
784c19800e8SDoug Rabson     gn.element = choice_GeneralName_dNSName;
785*ae771770SStanislav Sedov     gn.u.dNSName.data = rk_UNCONST(dnsname);
786*ae771770SStanislav Sedov     gn.u.dNSName.length = strlen(dnsname);
787c19800e8SDoug Rabson 
788c19800e8SDoug Rabson     return add_GeneralNames(&tbs->san, &gn);
789c19800e8SDoug Rabson }
790c19800e8SDoug Rabson 
791c19800e8SDoug Rabson /**
792c19800e8SDoug Rabson  * Add a Subject Alternative Name rfc822 (email address) to
793c19800e8SDoug Rabson  * to-be-signed certificate object.
794c19800e8SDoug Rabson  *
795c19800e8SDoug Rabson  * @param context A hx509 context.
796c19800e8SDoug Rabson  * @param tbs object to be signed.
797c19800e8SDoug Rabson  * @param rfc822Name a string to a email address.
798c19800e8SDoug Rabson  *
799c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
800c19800e8SDoug Rabson  *
801c19800e8SDoug Rabson  * @ingroup hx509_ca
802c19800e8SDoug Rabson  */
803c19800e8SDoug Rabson 
804c19800e8SDoug Rabson int
hx509_ca_tbs_add_san_rfc822name(hx509_context context,hx509_ca_tbs tbs,const char * rfc822Name)805c19800e8SDoug Rabson hx509_ca_tbs_add_san_rfc822name(hx509_context context,
806c19800e8SDoug Rabson 				hx509_ca_tbs tbs,
807c19800e8SDoug Rabson 				const char *rfc822Name)
808c19800e8SDoug Rabson {
809c19800e8SDoug Rabson     GeneralName gn;
810c19800e8SDoug Rabson 
811c19800e8SDoug Rabson     memset(&gn, 0, sizeof(gn));
812c19800e8SDoug Rabson     gn.element = choice_GeneralName_rfc822Name;
813*ae771770SStanislav Sedov     gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
814*ae771770SStanislav Sedov     gn.u.rfc822Name.length = strlen(rfc822Name);
815c19800e8SDoug Rabson 
816c19800e8SDoug Rabson     return add_GeneralNames(&tbs->san, &gn);
817c19800e8SDoug Rabson }
818c19800e8SDoug Rabson 
819c19800e8SDoug Rabson /**
820c19800e8SDoug Rabson  * Set the subject name of a to-be-signed certificate object.
821c19800e8SDoug Rabson  *
822c19800e8SDoug Rabson  * @param context A hx509 context.
823c19800e8SDoug Rabson  * @param tbs object to be signed.
824c19800e8SDoug Rabson  * @param subject the name to set a subject.
825c19800e8SDoug Rabson  *
826c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
827c19800e8SDoug Rabson  *
828c19800e8SDoug Rabson  * @ingroup hx509_ca
829c19800e8SDoug Rabson  */
830c19800e8SDoug Rabson 
831c19800e8SDoug Rabson int
hx509_ca_tbs_set_subject(hx509_context context,hx509_ca_tbs tbs,hx509_name subject)832c19800e8SDoug Rabson hx509_ca_tbs_set_subject(hx509_context context,
833c19800e8SDoug Rabson 			 hx509_ca_tbs tbs,
834c19800e8SDoug Rabson 			 hx509_name subject)
835c19800e8SDoug Rabson {
836c19800e8SDoug Rabson     if (tbs->subject)
837c19800e8SDoug Rabson 	hx509_name_free(&tbs->subject);
838c19800e8SDoug Rabson     return hx509_name_copy(context, subject, &tbs->subject);
839c19800e8SDoug Rabson }
840c19800e8SDoug Rabson 
841c19800e8SDoug Rabson /**
842*ae771770SStanislav Sedov  * Set the issuerUniqueID and subjectUniqueID
843*ae771770SStanislav Sedov  *
844*ae771770SStanislav Sedov  * These are only supposed to be used considered with version 2
845*ae771770SStanislav Sedov  * certificates, replaced by the two extensions SubjectKeyIdentifier
846*ae771770SStanislav Sedov  * and IssuerKeyIdentifier. This function is to allow application
847*ae771770SStanislav Sedov  * using legacy protocol to issue them.
848*ae771770SStanislav Sedov  *
849*ae771770SStanislav Sedov  * @param context A hx509 context.
850*ae771770SStanislav Sedov  * @param tbs object to be signed.
851*ae771770SStanislav Sedov  * @param issuerUniqueID to be set
852*ae771770SStanislav Sedov  * @param subjectUniqueID to be set
853*ae771770SStanislav Sedov  *
854*ae771770SStanislav Sedov  * @return An hx509 error code, see hx509_get_error_string().
855*ae771770SStanislav Sedov  *
856*ae771770SStanislav Sedov  * @ingroup hx509_ca
857*ae771770SStanislav Sedov  */
858*ae771770SStanislav Sedov 
859*ae771770SStanislav Sedov int
hx509_ca_tbs_set_unique(hx509_context context,hx509_ca_tbs tbs,const heim_bit_string * subjectUniqueID,const heim_bit_string * issuerUniqueID)860*ae771770SStanislav Sedov hx509_ca_tbs_set_unique(hx509_context context,
861*ae771770SStanislav Sedov 			hx509_ca_tbs tbs,
862*ae771770SStanislav Sedov 			const heim_bit_string *subjectUniqueID,
863*ae771770SStanislav Sedov 			const heim_bit_string *issuerUniqueID)
864*ae771770SStanislav Sedov {
865*ae771770SStanislav Sedov     int ret;
866*ae771770SStanislav Sedov 
867*ae771770SStanislav Sedov     der_free_bit_string(&tbs->subjectUniqueID);
868*ae771770SStanislav Sedov     der_free_bit_string(&tbs->issuerUniqueID);
869*ae771770SStanislav Sedov 
870*ae771770SStanislav Sedov     if (subjectUniqueID) {
871*ae771770SStanislav Sedov 	ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
872*ae771770SStanislav Sedov 	if (ret)
873*ae771770SStanislav Sedov 	    return ret;
874*ae771770SStanislav Sedov     }
875*ae771770SStanislav Sedov 
876*ae771770SStanislav Sedov     if (issuerUniqueID) {
877*ae771770SStanislav Sedov 	ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
878*ae771770SStanislav Sedov 	if (ret)
879*ae771770SStanislav Sedov 	    return ret;
880*ae771770SStanislav Sedov     }
881*ae771770SStanislav Sedov 
882*ae771770SStanislav Sedov     return 0;
883*ae771770SStanislav Sedov }
884*ae771770SStanislav Sedov 
885*ae771770SStanislav Sedov /**
886c19800e8SDoug Rabson  * Expand the the subject name in the to-be-signed certificate object
887c19800e8SDoug Rabson  * using hx509_name_expand().
888c19800e8SDoug Rabson  *
889c19800e8SDoug Rabson  * @param context A hx509 context.
890c19800e8SDoug Rabson  * @param tbs object to be signed.
891c19800e8SDoug Rabson  * @param env enviroment variable to expand variables in the subject
892c19800e8SDoug Rabson  * name, see hx509_env_init().
893c19800e8SDoug Rabson  *
894c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
895c19800e8SDoug Rabson  *
896c19800e8SDoug Rabson  * @ingroup hx509_ca
897c19800e8SDoug Rabson  */
898c19800e8SDoug Rabson 
899c19800e8SDoug Rabson int
hx509_ca_tbs_subject_expand(hx509_context context,hx509_ca_tbs tbs,hx509_env env)900c19800e8SDoug Rabson hx509_ca_tbs_subject_expand(hx509_context context,
901c19800e8SDoug Rabson 			    hx509_ca_tbs tbs,
902c19800e8SDoug Rabson 			    hx509_env env)
903c19800e8SDoug Rabson {
904c19800e8SDoug Rabson     return hx509_name_expand(context, tbs->subject, env);
905c19800e8SDoug Rabson }
906c19800e8SDoug Rabson 
907*ae771770SStanislav Sedov /*
908*ae771770SStanislav Sedov  *
909*ae771770SStanislav Sedov  */
910*ae771770SStanislav Sedov 
911c19800e8SDoug Rabson static int
add_extension(hx509_context context,TBSCertificate * tbsc,int critical_flag,const heim_oid * oid,const heim_octet_string * data)912c19800e8SDoug Rabson add_extension(hx509_context context,
913c19800e8SDoug Rabson 	      TBSCertificate *tbsc,
914c19800e8SDoug Rabson 	      int critical_flag,
915c19800e8SDoug Rabson 	      const heim_oid *oid,
916c19800e8SDoug Rabson 	      const heim_octet_string *data)
917c19800e8SDoug Rabson {
918c19800e8SDoug Rabson     Extension ext;
919c19800e8SDoug Rabson     int ret;
920c19800e8SDoug Rabson 
921c19800e8SDoug Rabson     memset(&ext, 0, sizeof(ext));
922c19800e8SDoug Rabson 
923c19800e8SDoug Rabson     if (critical_flag) {
924c19800e8SDoug Rabson 	ext.critical = malloc(sizeof(*ext.critical));
925c19800e8SDoug Rabson 	if (ext.critical == NULL) {
926c19800e8SDoug Rabson 	    ret = ENOMEM;
927c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
928c19800e8SDoug Rabson 	    goto out;
929c19800e8SDoug Rabson 	}
930c19800e8SDoug Rabson 	*ext.critical = TRUE;
931c19800e8SDoug Rabson     }
932c19800e8SDoug Rabson 
933c19800e8SDoug Rabson     ret = der_copy_oid(oid, &ext.extnID);
934c19800e8SDoug Rabson     if (ret) {
935c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
936c19800e8SDoug Rabson 	goto out;
937c19800e8SDoug Rabson     }
938c19800e8SDoug Rabson     ret = der_copy_octet_string(data, &ext.extnValue);
939c19800e8SDoug Rabson     if (ret) {
940c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
941c19800e8SDoug Rabson 	goto out;
942c19800e8SDoug Rabson     }
943c19800e8SDoug Rabson     ret = add_Extensions(tbsc->extensions, &ext);
944c19800e8SDoug Rabson     if (ret) {
945c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
946c19800e8SDoug Rabson 	goto out;
947c19800e8SDoug Rabson     }
948c19800e8SDoug Rabson out:
949c19800e8SDoug Rabson     free_Extension(&ext);
950c19800e8SDoug Rabson     return ret;
951c19800e8SDoug Rabson }
952c19800e8SDoug Rabson 
953c19800e8SDoug Rabson static int
build_proxy_prefix(hx509_context context,const Name * issuer,Name * subject)954c19800e8SDoug Rabson build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
955c19800e8SDoug Rabson {
956c19800e8SDoug Rabson     char *tstr;
957c19800e8SDoug Rabson     time_t t;
958c19800e8SDoug Rabson     int ret;
959c19800e8SDoug Rabson 
960c19800e8SDoug Rabson     ret = copy_Name(issuer, subject);
961c19800e8SDoug Rabson     if (ret) {
962c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret,
963c19800e8SDoug Rabson 			       "Failed to copy subject name");
964c19800e8SDoug Rabson 	return ret;
965c19800e8SDoug Rabson     }
966c19800e8SDoug Rabson 
967c19800e8SDoug Rabson     t = time(NULL);
968c19800e8SDoug Rabson     asprintf(&tstr, "ts-%lu", (unsigned long)t);
969c19800e8SDoug Rabson     if (tstr == NULL) {
970c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM,
971c19800e8SDoug Rabson 			       "Failed to copy subject name");
972c19800e8SDoug Rabson 	return ENOMEM;
973c19800e8SDoug Rabson     }
974c19800e8SDoug Rabson     /* prefix with CN=<ts>,...*/
975*ae771770SStanislav Sedov     ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
976c19800e8SDoug Rabson     free(tstr);
977c19800e8SDoug Rabson     if (ret)
978c19800e8SDoug Rabson 	free_Name(subject);
979c19800e8SDoug Rabson     return ret;
980c19800e8SDoug Rabson }
981c19800e8SDoug Rabson 
982c19800e8SDoug Rabson static int
ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,const AuthorityKeyIdentifier * ai,const Name * issuername,hx509_cert * certificate)983c19800e8SDoug Rabson ca_sign(hx509_context context,
984c19800e8SDoug Rabson 	hx509_ca_tbs tbs,
985c19800e8SDoug Rabson 	hx509_private_key signer,
986c19800e8SDoug Rabson 	const AuthorityKeyIdentifier *ai,
987c19800e8SDoug Rabson 	const Name *issuername,
988c19800e8SDoug Rabson 	hx509_cert *certificate)
989c19800e8SDoug Rabson {
990c19800e8SDoug Rabson     heim_octet_string data;
991c19800e8SDoug Rabson     Certificate c;
992c19800e8SDoug Rabson     TBSCertificate *tbsc;
993c19800e8SDoug Rabson     size_t size;
994c19800e8SDoug Rabson     int ret;
995c19800e8SDoug Rabson     const AlgorithmIdentifier *sigalg;
996c19800e8SDoug Rabson     time_t notBefore;
997c19800e8SDoug Rabson     time_t notAfter;
998c19800e8SDoug Rabson     unsigned key_usage;
999c19800e8SDoug Rabson 
1000c19800e8SDoug Rabson     sigalg = _hx509_crypto_default_sig_alg;
1001c19800e8SDoug Rabson 
1002c19800e8SDoug Rabson     memset(&c, 0, sizeof(c));
1003c19800e8SDoug Rabson 
1004c19800e8SDoug Rabson     /*
1005c19800e8SDoug Rabson      * Default values are: Valid since 24h ago, valid one year into
1006c19800e8SDoug Rabson      * the future, KeyUsage digitalSignature and keyEncipherment set,
1007c19800e8SDoug Rabson      * and keyCertSign for CA certificates.
1008c19800e8SDoug Rabson      */
1009c19800e8SDoug Rabson     notBefore = tbs->notBefore;
1010c19800e8SDoug Rabson     if (notBefore == 0)
1011c19800e8SDoug Rabson 	notBefore = time(NULL) - 3600 * 24;
1012c19800e8SDoug Rabson     notAfter = tbs->notAfter;
1013c19800e8SDoug Rabson     if (notAfter == 0)
1014c19800e8SDoug Rabson 	notAfter = time(NULL) + 3600 * 24 * 365;
1015c19800e8SDoug Rabson 
1016c19800e8SDoug Rabson     key_usage = tbs->key_usage;
1017c19800e8SDoug Rabson     if (key_usage == 0) {
1018c19800e8SDoug Rabson 	KeyUsage ku;
1019c19800e8SDoug Rabson 	memset(&ku, 0, sizeof(ku));
1020c19800e8SDoug Rabson 	ku.digitalSignature = 1;
1021c19800e8SDoug Rabson 	ku.keyEncipherment = 1;
1022c19800e8SDoug Rabson 	key_usage = KeyUsage2int(ku);
1023c19800e8SDoug Rabson     }
1024c19800e8SDoug Rabson 
1025c19800e8SDoug Rabson     if (tbs->flags.ca) {
1026c19800e8SDoug Rabson 	KeyUsage ku;
1027c19800e8SDoug Rabson 	memset(&ku, 0, sizeof(ku));
1028c19800e8SDoug Rabson 	ku.keyCertSign = 1;
1029c19800e8SDoug Rabson 	ku.cRLSign = 1;
1030c19800e8SDoug Rabson 	key_usage |= KeyUsage2int(ku);
1031c19800e8SDoug Rabson     }
1032c19800e8SDoug Rabson 
1033c19800e8SDoug Rabson     /*
1034c19800e8SDoug Rabson      *
1035c19800e8SDoug Rabson      */
1036c19800e8SDoug Rabson 
1037c19800e8SDoug Rabson     tbsc = &c.tbsCertificate;
1038c19800e8SDoug Rabson 
1039c19800e8SDoug Rabson     if (tbs->flags.key == 0) {
1040c19800e8SDoug Rabson 	ret = EINVAL;
1041c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "No public key set");
1042c19800e8SDoug Rabson 	return ret;
1043c19800e8SDoug Rabson     }
1044c19800e8SDoug Rabson     /*
1045c19800e8SDoug Rabson      * Don't put restrictions on proxy certificate's subject name, it
1046c19800e8SDoug Rabson      * will be generated below.
1047c19800e8SDoug Rabson      */
1048c19800e8SDoug Rabson     if (!tbs->flags.proxy) {
1049c19800e8SDoug Rabson 	if (tbs->subject == NULL) {
1050c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1051c19800e8SDoug Rabson 	    return EINVAL;
1052c19800e8SDoug Rabson 	}
1053c19800e8SDoug Rabson 	if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1054c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, EINVAL,
1055c19800e8SDoug Rabson 				   "NULL subject and no SubjectAltNames");
1056c19800e8SDoug Rabson 	    return EINVAL;
1057c19800e8SDoug Rabson 	}
1058c19800e8SDoug Rabson     }
1059c19800e8SDoug Rabson     if (tbs->flags.ca && tbs->flags.proxy) {
1060c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1061c19800e8SDoug Rabson 			       "at the same time");
1062c19800e8SDoug Rabson 	return EINVAL;
1063c19800e8SDoug Rabson     }
1064c19800e8SDoug Rabson     if (tbs->flags.proxy) {
1065c19800e8SDoug Rabson 	if (tbs->san.len > 0) {
1066c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, EINVAL,
1067c19800e8SDoug Rabson 				   "Proxy certificate is not allowed "
1068c19800e8SDoug Rabson 				   "to have SubjectAltNames");
1069c19800e8SDoug Rabson 	    return EINVAL;
1070c19800e8SDoug Rabson 	}
1071c19800e8SDoug Rabson     }
1072c19800e8SDoug Rabson 
1073c19800e8SDoug Rabson     /* version         [0]  Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1074c19800e8SDoug Rabson     tbsc->version = calloc(1, sizeof(*tbsc->version));
1075c19800e8SDoug Rabson     if (tbsc->version == NULL) {
1076c19800e8SDoug Rabson 	ret = ENOMEM;
1077c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
1078c19800e8SDoug Rabson 	goto out;
1079c19800e8SDoug Rabson     }
1080c19800e8SDoug Rabson     *tbsc->version = rfc3280_version_3;
1081c19800e8SDoug Rabson     /* serialNumber         CertificateSerialNumber, */
1082c19800e8SDoug Rabson     if (tbs->flags.serial) {
1083c19800e8SDoug Rabson 	ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1084c19800e8SDoug Rabson 	if (ret) {
1085c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1086c19800e8SDoug Rabson 	    goto out;
1087c19800e8SDoug Rabson 	}
1088c19800e8SDoug Rabson     } else {
1089c19800e8SDoug Rabson 	tbsc->serialNumber.length = 20;
1090c19800e8SDoug Rabson 	tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1091c19800e8SDoug Rabson 	if (tbsc->serialNumber.data == NULL){
1092c19800e8SDoug Rabson 	    ret = ENOMEM;
1093c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1094c19800e8SDoug Rabson 	    goto out;
1095c19800e8SDoug Rabson 	}
1096c19800e8SDoug Rabson 	/* XXX diffrent */
1097c19800e8SDoug Rabson 	RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1098c19800e8SDoug Rabson 	((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1099c19800e8SDoug Rabson     }
1100c19800e8SDoug Rabson     /* signature            AlgorithmIdentifier, */
1101c19800e8SDoug Rabson     ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1102c19800e8SDoug Rabson     if (ret) {
1103c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1104c19800e8SDoug Rabson 	goto out;
1105c19800e8SDoug Rabson     }
1106c19800e8SDoug Rabson     /* issuer               Name, */
1107c19800e8SDoug Rabson     if (issuername)
1108c19800e8SDoug Rabson 	ret = copy_Name(issuername, &tbsc->issuer);
1109c19800e8SDoug Rabson     else
1110c19800e8SDoug Rabson 	ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1111c19800e8SDoug Rabson     if (ret) {
1112c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1113c19800e8SDoug Rabson 	goto out;
1114c19800e8SDoug Rabson     }
1115c19800e8SDoug Rabson     /* validity             Validity, */
1116c19800e8SDoug Rabson     tbsc->validity.notBefore.element = choice_Time_generalTime;
1117c19800e8SDoug Rabson     tbsc->validity.notBefore.u.generalTime = notBefore;
1118c19800e8SDoug Rabson     tbsc->validity.notAfter.element = choice_Time_generalTime;
1119c19800e8SDoug Rabson     tbsc->validity.notAfter.u.generalTime = notAfter;
1120c19800e8SDoug Rabson     /* subject              Name, */
1121c19800e8SDoug Rabson     if (tbs->flags.proxy) {
1122c19800e8SDoug Rabson 	ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1123c19800e8SDoug Rabson 	if (ret)
1124c19800e8SDoug Rabson 	    goto out;
1125c19800e8SDoug Rabson     } else {
1126c19800e8SDoug Rabson 	ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1127c19800e8SDoug Rabson 	if (ret) {
1128c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret,
1129c19800e8SDoug Rabson 				   "Failed to copy subject name");
1130c19800e8SDoug Rabson 	    goto out;
1131c19800e8SDoug Rabson 	}
1132c19800e8SDoug Rabson     }
1133c19800e8SDoug Rabson     /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1134c19800e8SDoug Rabson     ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1135c19800e8SDoug Rabson     if (ret) {
1136c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1137c19800e8SDoug Rabson 	goto out;
1138c19800e8SDoug Rabson     }
1139c19800e8SDoug Rabson     /* issuerUniqueID  [1]  IMPLICIT BIT STRING OPTIONAL */
1140*ae771770SStanislav Sedov     if (tbs->issuerUniqueID.length) {
1141*ae771770SStanislav Sedov 	tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1142*ae771770SStanislav Sedov 	if (tbsc->issuerUniqueID == NULL) {
1143*ae771770SStanislav Sedov 	    ret = ENOMEM;
1144*ae771770SStanislav Sedov 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1145*ae771770SStanislav Sedov 	    goto out;
1146*ae771770SStanislav Sedov 	}
1147*ae771770SStanislav Sedov 	ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1148*ae771770SStanislav Sedov 	if (ret) {
1149*ae771770SStanislav Sedov 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1150*ae771770SStanislav Sedov 	    goto out;
1151*ae771770SStanislav Sedov 	}
1152*ae771770SStanislav Sedov     }
1153c19800e8SDoug Rabson     /* subjectUniqueID [2]  IMPLICIT BIT STRING OPTIONAL */
1154*ae771770SStanislav Sedov     if (tbs->subjectUniqueID.length) {
1155*ae771770SStanislav Sedov 	tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1156*ae771770SStanislav Sedov 	if (tbsc->subjectUniqueID == NULL) {
1157*ae771770SStanislav Sedov 	    ret = ENOMEM;
1158*ae771770SStanislav Sedov 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1159*ae771770SStanislav Sedov 	    goto out;
1160*ae771770SStanislav Sedov 	}
1161*ae771770SStanislav Sedov 
1162*ae771770SStanislav Sedov 	ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1163*ae771770SStanislav Sedov 	if (ret) {
1164*ae771770SStanislav Sedov 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1165*ae771770SStanislav Sedov 	    goto out;
1166*ae771770SStanislav Sedov 	}
1167*ae771770SStanislav Sedov     }
1168*ae771770SStanislav Sedov 
1169c19800e8SDoug Rabson     /* extensions      [3]  EXPLICIT Extensions OPTIONAL */
1170c19800e8SDoug Rabson     tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1171c19800e8SDoug Rabson     if (tbsc->extensions == NULL) {
1172c19800e8SDoug Rabson 	ret = ENOMEM;
1173c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Out of memory");
1174c19800e8SDoug Rabson 	goto out;
1175c19800e8SDoug Rabson     }
1176c19800e8SDoug Rabson 
1177c19800e8SDoug Rabson     /* Add the text BMP string Domaincontroller to the cert */
1178c19800e8SDoug Rabson     if (tbs->flags.domaincontroller) {
1179c19800e8SDoug Rabson 	data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1180c19800e8SDoug Rabson 			       "\x00\x61\x00\x69\x00\x6e\x00\x43"
1181c19800e8SDoug Rabson 			       "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1182c19800e8SDoug Rabson 			       "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1183c19800e8SDoug Rabson 			       "\x00\x72");
1184c19800e8SDoug Rabson 	data.length = 34;
1185c19800e8SDoug Rabson 
1186c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 0,
1187*ae771770SStanislav Sedov 			    &asn1_oid_id_ms_cert_enroll_domaincontroller,
1188c19800e8SDoug Rabson 			    &data);
1189c19800e8SDoug Rabson 	if (ret)
1190c19800e8SDoug Rabson 	    goto out;
1191c19800e8SDoug Rabson     }
1192c19800e8SDoug Rabson 
1193c19800e8SDoug Rabson     /* add KeyUsage */
1194c19800e8SDoug Rabson     {
1195c19800e8SDoug Rabson 	KeyUsage ku;
1196c19800e8SDoug Rabson 
1197c19800e8SDoug Rabson 	ku = int2KeyUsage(key_usage);
1198c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1199c19800e8SDoug Rabson 	if (ret) {
1200c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1201c19800e8SDoug Rabson 	    goto out;
1202c19800e8SDoug Rabson 	}
1203c19800e8SDoug Rabson 	if (size != data.length)
1204c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1205c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 1,
1206*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_keyUsage, &data);
1207c19800e8SDoug Rabson 	free(data.data);
1208c19800e8SDoug Rabson 	if (ret)
1209c19800e8SDoug Rabson 	    goto out;
1210c19800e8SDoug Rabson     }
1211c19800e8SDoug Rabson 
1212c19800e8SDoug Rabson     /* add ExtendedKeyUsage */
1213c19800e8SDoug Rabson     if (tbs->eku.len > 0) {
1214c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1215c19800e8SDoug Rabson 			   &tbs->eku, &size, ret);
1216c19800e8SDoug Rabson 	if (ret) {
1217c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1218c19800e8SDoug Rabson 	    goto out;
1219c19800e8SDoug Rabson 	}
1220c19800e8SDoug Rabson 	if (size != data.length)
1221c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1222c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 0,
1223*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_extKeyUsage, &data);
1224c19800e8SDoug Rabson 	free(data.data);
1225c19800e8SDoug Rabson 	if (ret)
1226c19800e8SDoug Rabson 	    goto out;
1227c19800e8SDoug Rabson     }
1228c19800e8SDoug Rabson 
1229c19800e8SDoug Rabson     /* add Subject Alternative Name */
1230c19800e8SDoug Rabson     if (tbs->san.len > 0) {
1231c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1232c19800e8SDoug Rabson 			   &tbs->san, &size, ret);
1233c19800e8SDoug Rabson 	if (ret) {
1234c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1235c19800e8SDoug Rabson 	    goto out;
1236c19800e8SDoug Rabson 	}
1237c19800e8SDoug Rabson 	if (size != data.length)
1238c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1239c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 0,
1240*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_subjectAltName,
1241c19800e8SDoug Rabson 			    &data);
1242c19800e8SDoug Rabson 	free(data.data);
1243c19800e8SDoug Rabson 	if (ret)
1244c19800e8SDoug Rabson 	    goto out;
1245c19800e8SDoug Rabson     }
1246c19800e8SDoug Rabson 
1247c19800e8SDoug Rabson     /* Add Authority Key Identifier */
1248c19800e8SDoug Rabson     if (ai) {
1249c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1250c19800e8SDoug Rabson 			   ai, &size, ret);
1251c19800e8SDoug Rabson 	if (ret) {
1252c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1253c19800e8SDoug Rabson 	    goto out;
1254c19800e8SDoug Rabson 	}
1255c19800e8SDoug Rabson 	if (size != data.length)
1256c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1257c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 0,
1258*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1259c19800e8SDoug Rabson 			    &data);
1260c19800e8SDoug Rabson 	free(data.data);
1261c19800e8SDoug Rabson 	if (ret)
1262c19800e8SDoug Rabson 	    goto out;
1263c19800e8SDoug Rabson     }
1264c19800e8SDoug Rabson 
1265c19800e8SDoug Rabson     /* Add Subject Key Identifier */
1266c19800e8SDoug Rabson     {
1267c19800e8SDoug Rabson 	SubjectKeyIdentifier si;
1268c19800e8SDoug Rabson 	unsigned char hash[SHA_DIGEST_LENGTH];
1269c19800e8SDoug Rabson 
1270c19800e8SDoug Rabson 	{
1271*ae771770SStanislav Sedov 	    EVP_MD_CTX *ctx;
1272c19800e8SDoug Rabson 
1273*ae771770SStanislav Sedov 	    ctx = EVP_MD_CTX_create();
1274*ae771770SStanislav Sedov 	    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1275*ae771770SStanislav Sedov 	    EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1276c19800e8SDoug Rabson 			     tbs->spki.subjectPublicKey.length / 8);
1277*ae771770SStanislav Sedov 	    EVP_DigestFinal_ex(ctx, hash, NULL);
1278*ae771770SStanislav Sedov 	    EVP_MD_CTX_destroy(ctx);
1279c19800e8SDoug Rabson 	}
1280c19800e8SDoug Rabson 
1281c19800e8SDoug Rabson 	si.data = hash;
1282c19800e8SDoug Rabson 	si.length = sizeof(hash);
1283c19800e8SDoug Rabson 
1284c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1285c19800e8SDoug Rabson 			   &si, &size, ret);
1286c19800e8SDoug Rabson 	if (ret) {
1287c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1288c19800e8SDoug Rabson 	    goto out;
1289c19800e8SDoug Rabson 	}
1290c19800e8SDoug Rabson 	if (size != data.length)
1291c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1292c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 0,
1293*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1294c19800e8SDoug Rabson 			    &data);
1295c19800e8SDoug Rabson 	free(data.data);
1296c19800e8SDoug Rabson 	if (ret)
1297c19800e8SDoug Rabson 	    goto out;
1298c19800e8SDoug Rabson     }
1299c19800e8SDoug Rabson 
1300c19800e8SDoug Rabson     /* Add BasicConstraints */
1301c19800e8SDoug Rabson     {
1302c19800e8SDoug Rabson 	BasicConstraints bc;
1303c19800e8SDoug Rabson 	int aCA = 1;
1304*ae771770SStanislav Sedov 	unsigned int path;
1305c19800e8SDoug Rabson 
1306c19800e8SDoug Rabson 	memset(&bc, 0, sizeof(bc));
1307c19800e8SDoug Rabson 
1308c19800e8SDoug Rabson 	if (tbs->flags.ca) {
1309c19800e8SDoug Rabson 	    bc.cA = &aCA;
1310c19800e8SDoug Rabson 	    if (tbs->pathLenConstraint >= 0) {
1311c19800e8SDoug Rabson 		path = tbs->pathLenConstraint;
1312c19800e8SDoug Rabson 		bc.pathLenConstraint = &path;
1313c19800e8SDoug Rabson 	    }
1314c19800e8SDoug Rabson 	}
1315c19800e8SDoug Rabson 
1316c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1317c19800e8SDoug Rabson 			   &bc, &size, ret);
1318c19800e8SDoug Rabson 	if (ret) {
1319c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1320c19800e8SDoug Rabson 	    goto out;
1321c19800e8SDoug Rabson 	}
1322c19800e8SDoug Rabson 	if (size != data.length)
1323c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1324c19800e8SDoug Rabson 	/* Critical if this is a CA */
1325c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, tbs->flags.ca,
1326*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_basicConstraints,
1327c19800e8SDoug Rabson 			    &data);
1328c19800e8SDoug Rabson 	free(data.data);
1329c19800e8SDoug Rabson 	if (ret)
1330c19800e8SDoug Rabson 	    goto out;
1331c19800e8SDoug Rabson     }
1332c19800e8SDoug Rabson 
1333c19800e8SDoug Rabson     /* add Proxy */
1334c19800e8SDoug Rabson     if (tbs->flags.proxy) {
1335c19800e8SDoug Rabson 	ProxyCertInfo info;
1336c19800e8SDoug Rabson 
1337c19800e8SDoug Rabson 	memset(&info, 0, sizeof(info));
1338c19800e8SDoug Rabson 
1339c19800e8SDoug Rabson 	if (tbs->pathLenConstraint >= 0) {
1340c19800e8SDoug Rabson 	    info.pCPathLenConstraint =
1341c19800e8SDoug Rabson 		malloc(sizeof(*info.pCPathLenConstraint));
1342c19800e8SDoug Rabson 	    if (info.pCPathLenConstraint == NULL) {
1343c19800e8SDoug Rabson 		ret = ENOMEM;
1344c19800e8SDoug Rabson 		hx509_set_error_string(context, 0, ret, "Out of memory");
1345c19800e8SDoug Rabson 		goto out;
1346c19800e8SDoug Rabson 	    }
1347c19800e8SDoug Rabson 	    *info.pCPathLenConstraint = tbs->pathLenConstraint;
1348c19800e8SDoug Rabson 	}
1349c19800e8SDoug Rabson 
1350*ae771770SStanislav Sedov 	ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
1351c19800e8SDoug Rabson 			   &info.proxyPolicy.policyLanguage);
1352c19800e8SDoug Rabson 	if (ret) {
1353c19800e8SDoug Rabson 	    free_ProxyCertInfo(&info);
1354c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1355c19800e8SDoug Rabson 	    goto out;
1356c19800e8SDoug Rabson 	}
1357c19800e8SDoug Rabson 
1358c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1359c19800e8SDoug Rabson 			   &info, &size, ret);
1360c19800e8SDoug Rabson 	free_ProxyCertInfo(&info);
1361c19800e8SDoug Rabson 	if (ret) {
1362c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1363c19800e8SDoug Rabson 	    goto out;
1364c19800e8SDoug Rabson 	}
1365c19800e8SDoug Rabson 	if (size != data.length)
1366c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1367c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, 0,
1368*ae771770SStanislav Sedov 			    &asn1_oid_id_pkix_pe_proxyCertInfo,
1369c19800e8SDoug Rabson 			    &data);
1370c19800e8SDoug Rabson 	free(data.data);
1371c19800e8SDoug Rabson 	if (ret)
1372c19800e8SDoug Rabson 	    goto out;
1373c19800e8SDoug Rabson     }
1374c19800e8SDoug Rabson 
1375c19800e8SDoug Rabson     if (tbs->crldp.len) {
1376c19800e8SDoug Rabson 
1377c19800e8SDoug Rabson 	ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1378c19800e8SDoug Rabson 			   &tbs->crldp, &size, ret);
1379c19800e8SDoug Rabson 	if (ret) {
1380c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1381c19800e8SDoug Rabson 	    goto out;
1382c19800e8SDoug Rabson 	}
1383c19800e8SDoug Rabson 	if (size != data.length)
1384c19800e8SDoug Rabson 	    _hx509_abort("internal ASN.1 encoder error");
1385c19800e8SDoug Rabson 	ret = add_extension(context, tbsc, FALSE,
1386*ae771770SStanislav Sedov 			    &asn1_oid_id_x509_ce_cRLDistributionPoints,
1387c19800e8SDoug Rabson 			    &data);
1388c19800e8SDoug Rabson 	free(data.data);
1389c19800e8SDoug Rabson 	if (ret)
1390c19800e8SDoug Rabson 	    goto out;
1391c19800e8SDoug Rabson     }
1392c19800e8SDoug Rabson 
1393c19800e8SDoug Rabson     ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1394c19800e8SDoug Rabson     if (ret) {
1395c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "malloc out of memory");
1396c19800e8SDoug Rabson 	goto out;
1397c19800e8SDoug Rabson     }
1398c19800e8SDoug Rabson     if (data.length != size)
1399c19800e8SDoug Rabson 	_hx509_abort("internal ASN.1 encoder error");
1400c19800e8SDoug Rabson 
1401c19800e8SDoug Rabson     ret = _hx509_create_signature_bitstring(context,
1402c19800e8SDoug Rabson 					    signer,
1403c19800e8SDoug Rabson 					    sigalg,
1404c19800e8SDoug Rabson 					    &data,
1405c19800e8SDoug Rabson 					    &c.signatureAlgorithm,
1406c19800e8SDoug Rabson 					    &c.signatureValue);
1407c19800e8SDoug Rabson     free(data.data);
1408c19800e8SDoug Rabson     if (ret)
1409c19800e8SDoug Rabson 	goto out;
1410c19800e8SDoug Rabson 
1411c19800e8SDoug Rabson     ret = hx509_cert_init(context, &c, certificate);
1412c19800e8SDoug Rabson     if (ret)
1413c19800e8SDoug Rabson 	goto out;
1414c19800e8SDoug Rabson 
1415c19800e8SDoug Rabson     free_Certificate(&c);
1416c19800e8SDoug Rabson 
1417c19800e8SDoug Rabson     return 0;
1418c19800e8SDoug Rabson 
1419c19800e8SDoug Rabson out:
1420c19800e8SDoug Rabson     free_Certificate(&c);
1421c19800e8SDoug Rabson     return ret;
1422c19800e8SDoug Rabson }
1423c19800e8SDoug Rabson 
1424c19800e8SDoug Rabson static int
get_AuthorityKeyIdentifier(hx509_context context,const Certificate * certificate,AuthorityKeyIdentifier * ai)1425c19800e8SDoug Rabson get_AuthorityKeyIdentifier(hx509_context context,
1426c19800e8SDoug Rabson 			   const Certificate *certificate,
1427c19800e8SDoug Rabson 			   AuthorityKeyIdentifier *ai)
1428c19800e8SDoug Rabson {
1429c19800e8SDoug Rabson     SubjectKeyIdentifier si;
1430c19800e8SDoug Rabson     int ret;
1431c19800e8SDoug Rabson 
1432c19800e8SDoug Rabson     ret = _hx509_find_extension_subject_key_id(certificate, &si);
1433c19800e8SDoug Rabson     if (ret == 0) {
1434c19800e8SDoug Rabson 	ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1435c19800e8SDoug Rabson 	if (ai->keyIdentifier == NULL) {
1436c19800e8SDoug Rabson 	    free_SubjectKeyIdentifier(&si);
1437c19800e8SDoug Rabson 	    ret = ENOMEM;
1438c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1439c19800e8SDoug Rabson 	    goto out;
1440c19800e8SDoug Rabson 	}
1441c19800e8SDoug Rabson 	ret = der_copy_octet_string(&si, ai->keyIdentifier);
1442c19800e8SDoug Rabson 	free_SubjectKeyIdentifier(&si);
1443c19800e8SDoug Rabson 	if (ret) {
1444c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1445c19800e8SDoug Rabson 	    goto out;
1446c19800e8SDoug Rabson 	}
1447c19800e8SDoug Rabson     } else {
1448c19800e8SDoug Rabson 	GeneralNames gns;
1449c19800e8SDoug Rabson 	GeneralName gn;
1450c19800e8SDoug Rabson 	Name name;
1451c19800e8SDoug Rabson 
1452c19800e8SDoug Rabson 	memset(&gn, 0, sizeof(gn));
1453c19800e8SDoug Rabson 	memset(&gns, 0, sizeof(gns));
1454c19800e8SDoug Rabson 	memset(&name, 0, sizeof(name));
1455c19800e8SDoug Rabson 
1456c19800e8SDoug Rabson 	ai->authorityCertIssuer =
1457c19800e8SDoug Rabson 	    calloc(1, sizeof(*ai->authorityCertIssuer));
1458c19800e8SDoug Rabson 	if (ai->authorityCertIssuer == NULL) {
1459c19800e8SDoug Rabson 	    ret = ENOMEM;
1460c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1461c19800e8SDoug Rabson 	    goto out;
1462c19800e8SDoug Rabson 	}
1463c19800e8SDoug Rabson 	ai->authorityCertSerialNumber =
1464c19800e8SDoug Rabson 	    calloc(1, sizeof(*ai->authorityCertSerialNumber));
1465c19800e8SDoug Rabson 	if (ai->authorityCertSerialNumber == NULL) {
1466c19800e8SDoug Rabson 	    ret = ENOMEM;
1467c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1468c19800e8SDoug Rabson 	    goto out;
1469c19800e8SDoug Rabson 	}
1470c19800e8SDoug Rabson 
1471c19800e8SDoug Rabson 	/*
1472c19800e8SDoug Rabson 	 * XXX unbreak when asn1 compiler handle IMPLICIT
1473c19800e8SDoug Rabson 	 *
1474c19800e8SDoug Rabson 	 * This is so horrible.
1475c19800e8SDoug Rabson 	 */
1476c19800e8SDoug Rabson 
1477c19800e8SDoug Rabson 	ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1478*ae771770SStanislav Sedov 	if (ret) {
1479c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1480c19800e8SDoug Rabson 	    goto out;
1481c19800e8SDoug Rabson 	}
1482c19800e8SDoug Rabson 
1483c19800e8SDoug Rabson 	memset(&gn, 0, sizeof(gn));
1484c19800e8SDoug Rabson 	gn.element = choice_GeneralName_directoryName;
1485c19800e8SDoug Rabson 	gn.u.directoryName.element =
1486c19800e8SDoug Rabson 	    choice_GeneralName_directoryName_rdnSequence;
1487c19800e8SDoug Rabson 	gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1488c19800e8SDoug Rabson 
1489c19800e8SDoug Rabson 	ret = add_GeneralNames(&gns, &gn);
1490c19800e8SDoug Rabson 	if (ret) {
1491c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1492c19800e8SDoug Rabson 	    goto out;
1493c19800e8SDoug Rabson 	}
1494c19800e8SDoug Rabson 
1495c19800e8SDoug Rabson 	ai->authorityCertIssuer->val = gns.val;
1496c19800e8SDoug Rabson 	ai->authorityCertIssuer->len = gns.len;
1497c19800e8SDoug Rabson 
1498c19800e8SDoug Rabson 	ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1499c19800e8SDoug Rabson 				    ai->authorityCertSerialNumber);
1500c19800e8SDoug Rabson 	if (ai->authorityCertSerialNumber == NULL) {
1501c19800e8SDoug Rabson 	    ret = ENOMEM;
1502c19800e8SDoug Rabson 	    hx509_set_error_string(context, 0, ret, "Out of memory");
1503c19800e8SDoug Rabson 	    goto out;
1504c19800e8SDoug Rabson 	}
1505c19800e8SDoug Rabson     }
1506c19800e8SDoug Rabson out:
1507c19800e8SDoug Rabson     if (ret)
1508c19800e8SDoug Rabson 	free_AuthorityKeyIdentifier(ai);
1509c19800e8SDoug Rabson     return ret;
1510c19800e8SDoug Rabson }
1511c19800e8SDoug Rabson 
1512c19800e8SDoug Rabson 
1513c19800e8SDoug Rabson /**
1514c19800e8SDoug Rabson  * Sign a to-be-signed certificate object with a issuer certificate.
1515c19800e8SDoug Rabson  *
1516c19800e8SDoug Rabson  * The caller needs to at least have called the following functions on the
1517c19800e8SDoug Rabson  * to-be-signed certificate object:
1518c19800e8SDoug Rabson  * - hx509_ca_tbs_init()
1519c19800e8SDoug Rabson  * - hx509_ca_tbs_set_subject()
1520c19800e8SDoug Rabson  * - hx509_ca_tbs_set_spki()
1521c19800e8SDoug Rabson  *
1522c19800e8SDoug Rabson  * When done the to-be-signed certificate object should be freed with
1523c19800e8SDoug Rabson  * hx509_ca_tbs_free().
1524c19800e8SDoug Rabson  *
1525c19800e8SDoug Rabson  * When creating self-signed certificate use hx509_ca_sign_self() instead.
1526c19800e8SDoug Rabson  *
1527c19800e8SDoug Rabson  * @param context A hx509 context.
1528c19800e8SDoug Rabson  * @param tbs object to be signed.
1529c19800e8SDoug Rabson  * @param signer the CA certificate object to sign with (need private key).
1530c19800e8SDoug Rabson  * @param certificate return cerificate, free with hx509_cert_free().
1531c19800e8SDoug Rabson  *
1532c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
1533c19800e8SDoug Rabson  *
1534c19800e8SDoug Rabson  * @ingroup hx509_ca
1535c19800e8SDoug Rabson  */
1536c19800e8SDoug Rabson 
1537c19800e8SDoug Rabson int
hx509_ca_sign(hx509_context context,hx509_ca_tbs tbs,hx509_cert signer,hx509_cert * certificate)1538c19800e8SDoug Rabson hx509_ca_sign(hx509_context context,
1539c19800e8SDoug Rabson 	      hx509_ca_tbs tbs,
1540c19800e8SDoug Rabson 	      hx509_cert signer,
1541c19800e8SDoug Rabson 	      hx509_cert *certificate)
1542c19800e8SDoug Rabson {
1543c19800e8SDoug Rabson     const Certificate *signer_cert;
1544c19800e8SDoug Rabson     AuthorityKeyIdentifier ai;
1545c19800e8SDoug Rabson     int ret;
1546c19800e8SDoug Rabson 
1547c19800e8SDoug Rabson     memset(&ai, 0, sizeof(ai));
1548c19800e8SDoug Rabson 
1549c19800e8SDoug Rabson     signer_cert = _hx509_get_cert(signer);
1550c19800e8SDoug Rabson 
1551c19800e8SDoug Rabson     ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1552c19800e8SDoug Rabson     if (ret)
1553c19800e8SDoug Rabson 	goto out;
1554c19800e8SDoug Rabson 
1555c19800e8SDoug Rabson     ret = ca_sign(context,
1556c19800e8SDoug Rabson 		  tbs,
1557c19800e8SDoug Rabson 		  _hx509_cert_private_key(signer),
1558c19800e8SDoug Rabson 		  &ai,
1559c19800e8SDoug Rabson 		  &signer_cert->tbsCertificate.subject,
1560c19800e8SDoug Rabson 		  certificate);
1561c19800e8SDoug Rabson 
1562c19800e8SDoug Rabson out:
1563c19800e8SDoug Rabson     free_AuthorityKeyIdentifier(&ai);
1564c19800e8SDoug Rabson 
1565c19800e8SDoug Rabson     return ret;
1566c19800e8SDoug Rabson }
1567c19800e8SDoug Rabson 
1568c19800e8SDoug Rabson /**
1569c19800e8SDoug Rabson  * Work just like hx509_ca_sign() but signs it-self.
1570c19800e8SDoug Rabson  *
1571c19800e8SDoug Rabson  * @param context A hx509 context.
1572c19800e8SDoug Rabson  * @param tbs object to be signed.
1573c19800e8SDoug Rabson  * @param signer private key to sign with.
1574c19800e8SDoug Rabson  * @param certificate return cerificate, free with hx509_cert_free().
1575c19800e8SDoug Rabson  *
1576c19800e8SDoug Rabson  * @return An hx509 error code, see hx509_get_error_string().
1577c19800e8SDoug Rabson  *
1578c19800e8SDoug Rabson  * @ingroup hx509_ca
1579c19800e8SDoug Rabson  */
1580c19800e8SDoug Rabson 
1581c19800e8SDoug Rabson int
hx509_ca_sign_self(hx509_context context,hx509_ca_tbs tbs,hx509_private_key signer,hx509_cert * certificate)1582c19800e8SDoug Rabson hx509_ca_sign_self(hx509_context context,
1583c19800e8SDoug Rabson 		   hx509_ca_tbs tbs,
1584c19800e8SDoug Rabson 		   hx509_private_key signer,
1585c19800e8SDoug Rabson 		   hx509_cert *certificate)
1586c19800e8SDoug Rabson {
1587c19800e8SDoug Rabson     return ca_sign(context,
1588c19800e8SDoug Rabson 		   tbs,
1589c19800e8SDoug Rabson 		   signer,
1590c19800e8SDoug Rabson 		   NULL,
1591c19800e8SDoug Rabson 		   NULL,
1592c19800e8SDoug Rabson 		   certificate);
1593c19800e8SDoug Rabson }
1594