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