1193323Sed/*	$NetBSD$	*/
2193323Sed
3193323Sed/*
4193323Sed * Copyright (c) 2006 - 2010 Kungliga Tekniska H��gskolan
5193323Sed * (Royal Institute of Technology, Stockholm, Sweden).
6193323Sed * All rights reserved.
7193323Sed *
8193323Sed * Redistribution and use in source and binary forms, with or without
9193323Sed * modification, are permitted provided that the following conditions
10193323Sed * are met:
11193323Sed *
12193323Sed * 1. Redistributions of source code must retain the above copyright
13193323Sed *    notice, this list of conditions and the following disclaimer.
14193323Sed *
15193323Sed * 2. Redistributions in binary form must reproduce the above copyright
16193323Sed *    notice, this list of conditions and the following disclaimer in the
17193323Sed *    documentation and/or other materials provided with the distribution.
18193323Sed *
19224145Sdim * 3. Neither the name of the Institute nor the names of its contributors
20221345Sdim *    may be used to endorse or promote products derived from this software
21193323Sed *    without specific prior written permission.
22193323Sed *
23193323Sed * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24210299Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26193323Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27203954Srdivacky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28218893Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29203954Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31224145Sdim * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32193323Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33193323Sed * SUCH DAMAGE.
34193323Sed */
35193323Sed
36198090Srdivacky#include "hx_locl.h"
37193323Sed#include <krb5/pkinit_asn1.h>
38193323Sed
39193323Sed/**
40193323Sed * @page page_ca Hx509 CA functions
41193323Sed *
42193323Sed * See the library functions here: @ref hx509_ca
43193323Sed */
44193323Sed
45193323Sedstruct hx509_ca_tbs {
46193323Sed    hx509_name subject;
47193323Sed    SubjectPublicKeyInfo spki;
48193323Sed    ExtKeyUsage eku;
49193323Sed    GeneralNames san;
50193323Sed    unsigned key_usage;
51193323Sed    heim_integer serial;
52193323Sed    struct {
53193323Sed	unsigned int proxy:1;
54193323Sed	unsigned int ca:1;
55193323Sed	unsigned int key:1;
56193323Sed	unsigned int serial:1;
57193323Sed	unsigned int domaincontroller:1;
58193323Sed	unsigned int xUniqueID:1;
59193323Sed    } flags;
60193323Sed    time_t notBefore;
61193323Sed    time_t notAfter;
62193323Sed    int pathLenConstraint; /* both for CA and Proxy */
63193323Sed    CRLDistributionPoints crldp;
64193323Sed    heim_bit_string subjectUniqueID;
65193323Sed    heim_bit_string issuerUniqueID;
66193323Sed
67193323Sed};
68224145Sdim
69193323Sed/**
70193323Sed * Allocate an to-be-signed certificate object that will be converted
71193323Sed * into an certificate.
72193323Sed *
73193323Sed * @param context A hx509 context.
74224145Sdim * @param tbs returned to-be-signed certicate object, free with
75224145Sdim * hx509_ca_tbs_free().
76224145Sdim *
77224145Sdim * @return An hx509 error code, see hx509_get_error_string().
78224145Sdim *
79224145Sdim * @ingroup hx509_ca
80234353Sdim */
81224145Sdim
82193323Sedint
83193323Sedhx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84193323Sed{
85193323Sed    *tbs = calloc(1, sizeof(**tbs));
86193323Sed    if (*tbs == NULL)
87193323Sed	return ENOMEM;
88234353Sdim
89193323Sed    return 0;
90234353Sdim}
91193323Sed
92193323Sed/**
93193323Sed * Free an To Be Signed object.
94193323Sed *
95198892Srdivacky * @param tbs object to free.
96198892Srdivacky *
97198892Srdivacky * @ingroup hx509_ca
98198892Srdivacky */
99193323Sed
100193323Sedvoid
101193323Sedhx509_ca_tbs_free(hx509_ca_tbs *tbs)
102193323Sed{
103193323Sed    if (tbs == NULL || *tbs == NULL)
104193323Sed	return;
105193323Sed
106193323Sed    free_SubjectPublicKeyInfo(&(*tbs)->spki);
107193323Sed    free_GeneralNames(&(*tbs)->san);
108193323Sed    free_ExtKeyUsage(&(*tbs)->eku);
109193323Sed    der_free_heim_integer(&(*tbs)->serial);
110193323Sed    free_CRLDistributionPoints(&(*tbs)->crldp);
111199989Srdivacky    der_free_bit_string(&(*tbs)->subjectUniqueID);
112199989Srdivacky    der_free_bit_string(&(*tbs)->issuerUniqueID);
113193323Sed    hx509_name_free(&(*tbs)->subject);
114193323Sed
115193323Sed    memset(*tbs, 0, sizeof(**tbs));
116199989Srdivacky    free(*tbs);
117199989Srdivacky    *tbs = NULL;
118199989Srdivacky}
119199989Srdivacky
120234353Sdim/**
121234353Sdim * Set the absolute time when the certificate is valid from. If not
122234353Sdim * set the current time will be used.
123234353Sdim *
124198892Srdivacky * @param context A hx509 context.
125198892Srdivacky * @param tbs object to be signed.
126198892Srdivacky * @param t time the certificated will start to be valid
127198892Srdivacky *
128198892Srdivacky * @return An hx509 error code, see hx509_get_error_string().
129198892Srdivacky *
130198892Srdivacky * @ingroup hx509_ca
131198892Srdivacky */
132193323Sed
133193323Sedint
134193323Sedhx509_ca_tbs_set_notBefore(hx509_context context,
135193323Sed			   hx509_ca_tbs tbs,
136193323Sed			   time_t t)
137193323Sed{
138234353Sdim    tbs->notBefore = t;
139234353Sdim    return 0;
140234353Sdim}
141234353Sdim
142234353Sdim/**
143234353Sdim * Set the absolute time when the certificate is valid to.
144234353Sdim *
145234353Sdim * @param context A hx509 context.
146239462Sdim * @param tbs object to be signed.
147234353Sdim * @param t time when the certificate will expire
148234353Sdim *
149234353Sdim * @return An hx509 error code, see hx509_get_error_string().
150234353Sdim *
151234353Sdim * @ingroup hx509_ca
152234353Sdim */
153234353Sdim
154234353Sdimint
155234353Sdimhx509_ca_tbs_set_notAfter(hx509_context context,
156239462Sdim			   hx509_ca_tbs tbs,
157239462Sdim			   time_t t)
158239462Sdim{
159239462Sdim    tbs->notAfter = t;
160234353Sdim    return 0;
161234353Sdim}
162234353Sdim
163234353Sdim/**
164234353Sdim * Set the relative time when the certificiate is going to expire.
165234353Sdim *
166234353Sdim * @param context A hx509 context.
167234353Sdim * @param tbs object to be signed.
168234353Sdim * @param delta seconds to the certificate is going to expire.
169234353Sdim *
170234353Sdim * @return An hx509 error code, see hx509_get_error_string().
171234353Sdim *
172234353Sdim * @ingroup hx509_ca
173234353Sdim */
174234353Sdim
175234353Sdimint
176239462Sdimhx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
177239462Sdim				   hx509_ca_tbs tbs,
178234353Sdim				   time_t delta)
179234353Sdim{
180234353Sdim    return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
181239462Sdim}
182239462Sdim
183239462Sdimstatic const struct units templatebits[] = {
184234353Sdim    { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
185234353Sdim    { "KeyUsage", HX509_CA_TEMPLATE_KU },
186234353Sdim    { "SPKI", HX509_CA_TEMPLATE_SPKI },
187234353Sdim    { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
188239462Sdim    { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
189234353Sdim    { "serial", HX509_CA_TEMPLATE_SERIAL },
190234353Sdim    { "subject", HX509_CA_TEMPLATE_SUBJECT },
191234353Sdim    { NULL, 0 }
192234353Sdim};
193239462Sdim
194234353Sdim/**
195234353Sdim * Make of template units, use to build flags argument to
196234353Sdim * hx509_ca_tbs_set_template() with parse_units().
197234353Sdim *
198234353Sdim * @return an units structure.
199234353Sdim *
200234353Sdim * @ingroup hx509_ca
201234353Sdim */
202234353Sdim
203234353Sdimconst struct units *
204234353Sdimhx509_ca_tbs_template_units(void)
205234353Sdim{
206234353Sdim    return templatebits;
207234353Sdim}
208234353Sdim
209234353Sdim/**
210234353Sdim * Initialize the to-be-signed certificate object from a template certifiate.
211234353Sdim *
212234353Sdim * @param context A hx509 context.
213234353Sdim * @param tbs object to be signed.
214234353Sdim * @param flags bit field selecting what to copy from the template
215234353Sdim * certifiate.
216193323Sed * @param cert template certificate.
217193323Sed *
218193323Sed * @return An hx509 error code, see hx509_get_error_string().
219193323Sed *
220193323Sed * @ingroup hx509_ca
221193323Sed */
222193323Sed
223193323Sedint
224234353Sdimhx509_ca_tbs_set_template(hx509_context context,
225234353Sdim			  hx509_ca_tbs tbs,
226234353Sdim			  int flags,
227234353Sdim			  hx509_cert cert)
228234353Sdim{
229234353Sdim    int ret;
230234353Sdim
231234353Sdim    if (flags & HX509_CA_TEMPLATE_SUBJECT) {
232234353Sdim	if (tbs->subject)
233239462Sdim	    hx509_name_free(&tbs->subject);
234239462Sdim	ret = hx509_cert_get_subject(cert, &tbs->subject);
235239462Sdim	if (ret) {
236239462Sdim	    hx509_set_error_string(context, 0, ret,
237239462Sdim				   "Failed to get subject from template");
238239462Sdim	    return ret;
239239462Sdim	}
240239462Sdim    }
241193323Sed    if (flags & HX509_CA_TEMPLATE_SERIAL) {
242234353Sdim	der_free_heim_integer(&tbs->serial);
243193323Sed	ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
244193323Sed	tbs->flags.serial = !ret;
245193323Sed	if (ret) {
246193323Sed	    hx509_set_error_string(context, 0, ret,
247193323Sed				   "Failed to copy serial number");
248193323Sed	    return ret;
249193323Sed	}
250193323Sed    }
251193323Sed    if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
252193323Sed	tbs->notBefore = hx509_cert_get_notBefore(cert);
253193323Sed    if (flags & HX509_CA_TEMPLATE_NOTAFTER)
254193323Sed	tbs->notAfter = hx509_cert_get_notAfter(cert);
255193323Sed    if (flags & HX509_CA_TEMPLATE_SPKI) {
256193323Sed	free_SubjectPublicKeyInfo(&tbs->spki);
257193323Sed	ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
258193323Sed	tbs->flags.key = !ret;
259193323Sed	if (ret)
260193323Sed	    return ret;
261193323Sed    }
262193323Sed    if (flags & HX509_CA_TEMPLATE_KU) {
263193323Sed	KeyUsage ku;
264193323Sed	ret = _hx509_cert_get_keyusage(context, cert, &ku);
265193323Sed	if (ret)
266193323Sed	    return ret;
267193323Sed	tbs->key_usage = KeyUsage2int(ku);
268193323Sed    }
269193323Sed    if (flags & HX509_CA_TEMPLATE_EKU) {
270193323Sed	ExtKeyUsage eku;
271193323Sed	int i;
272193323Sed	ret = _hx509_cert_get_eku(context, cert, &eku);
273193323Sed	if (ret)
274193323Sed	    return ret;
275193323Sed	for (i = 0; i < eku.len; i++) {
276193323Sed	    ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
277193323Sed	    if (ret) {
278193323Sed		free_ExtKeyUsage(&eku);
279193323Sed		return ret;
280193323Sed	    }
281193323Sed	}
282193323Sed	free_ExtKeyUsage(&eku);
283193323Sed    }
284193323Sed    return 0;
285193323Sed}
286193323Sed
287193323Sed/**
288193323Sed * Make the to-be-signed certificate object a CA certificate. If the
289193323Sed * pathLenConstraint is negative path length constraint is used.
290193323Sed *
291193323Sed * @param context A hx509 context.
292193323Sed * @param tbs object to be signed.
293193323Sed * @param pathLenConstraint path length constraint, negative, no
294193323Sed * constraint.
295193323Sed *
296193323Sed * @return An hx509 error code, see hx509_get_error_string().
297193323Sed *
298193323Sed * @ingroup hx509_ca
299193323Sed */
300193323Sed
301193323Sedint
302193323Sedhx509_ca_tbs_set_ca(hx509_context context,
303193323Sed		    hx509_ca_tbs tbs,
304193323Sed		    int pathLenConstraint)
305193323Sed{
306207618Srdivacky    tbs->flags.ca = 1;
307207618Srdivacky    tbs->pathLenConstraint = pathLenConstraint;
308207618Srdivacky    return 0;
309193323Sed}
310193323Sed
311193323Sed/**
312234353Sdim * Make the to-be-signed certificate object a proxy certificate. If the
313193323Sed * pathLenConstraint is negative path length constraint is used.
314193323Sed *
315193323Sed * @param context A hx509 context.
316193323Sed * @param tbs object to be signed.
317234353Sdim * @param pathLenConstraint path length constraint, negative, no
318193323Sed * constraint.
319193323Sed *
320193323Sed * @return An hx509 error code, see hx509_get_error_string().
321193323Sed *
322193323Sed * @ingroup hx509_ca
323193323Sed */
324193323Sed
325193323Sedint
326193323Sedhx509_ca_tbs_set_proxy(hx509_context context,
327226633Sdim		       hx509_ca_tbs tbs,
328193323Sed		       int pathLenConstraint)
329218893Sdim{
330218893Sdim    tbs->flags.proxy = 1;
331218893Sdim    tbs->pathLenConstraint = pathLenConstraint;
332218893Sdim    return 0;
333193323Sed}
334234353Sdim
335193323Sed
336193323Sed/**
337193323Sed * Make the to-be-signed certificate object a windows domain controller certificate.
338193323Sed *
339193323Sed * @param context A hx509 context.
340199481Srdivacky * @param tbs object to be signed.
341199481Srdivacky *
342199481Srdivacky * @return An hx509 error code, see hx509_get_error_string().
343199481Srdivacky *
344199481Srdivacky * @ingroup hx509_ca
345199481Srdivacky */
346199481Srdivacky
347193323Sedint
348224145Sdimhx509_ca_tbs_set_domaincontroller(hx509_context context,
349193323Sed				  hx509_ca_tbs tbs)
350224145Sdim{
351224145Sdim    tbs->flags.domaincontroller = 1;
352224145Sdim    return 0;
353193323Sed}
354243830Sdim
355243830Sdim/**
356224145Sdim * Set the subject public key info (SPKI) in the to-be-signed certificate
357193323Sed * object. SPKI is the public key and key related parameters in the
358193323Sed * certificate.
359193323Sed *
360193323Sed * @param context A hx509 context.
361193323Sed * @param tbs object to be signed.
362193323Sed * @param spki subject public key info to use for the to-be-signed certificate object.
363193323Sed *
364193323Sed * @return An hx509 error code, see hx509_get_error_string().
365193323Sed *
366193323Sed * @ingroup hx509_ca
367193323Sed */
368224145Sdim
369224145Sdimint
370224145Sdimhx509_ca_tbs_set_spki(hx509_context context,
371224145Sdim		      hx509_ca_tbs tbs,
372224145Sdim		      const SubjectPublicKeyInfo *spki)
373224145Sdim{
374193323Sed    int ret;
375193323Sed    free_SubjectPublicKeyInfo(&tbs->spki);
376199481Srdivacky    ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
377193323Sed    tbs->flags.key = !ret;
378210299Sed    return ret;
379210299Sed}
380210299Sed
381210299Sed/**
382210299Sed * Set the serial number to use for to-be-signed certificate object.
383234353Sdim *
384239462Sdim * @param context A hx509 context.
385239462Sdim * @param tbs object to be signed.
386239462Sdim * @param serialNumber serial number to use for the to-be-signed
387239462Sdim * certificate object.
388193323Sed *
389193323Sed * @return An hx509 error code, see hx509_get_error_string().
390193323Sed *
391193323Sed * @ingroup hx509_ca
392193323Sed */
393193323Sed
394193323Sedint
395193323Sedhx509_ca_tbs_set_serialnumber(hx509_context context,
396193323Sed			      hx509_ca_tbs tbs,
397193323Sed			      const heim_integer *serialNumber)
398193323Sed{
399199989Srdivacky    int ret;
400199989Srdivacky    der_free_heim_integer(&tbs->serial);
401199989Srdivacky    ret = der_copy_heim_integer(serialNumber, &tbs->serial);
402199989Srdivacky    tbs->flags.serial = !ret;
403199989Srdivacky    return ret;
404199989Srdivacky}
405234353Sdim
406210299Sed/**
407210299Sed * An an extended key usage to the to-be-signed certificate object.
408210299Sed * Duplicates will detected and not added.
409210299Sed *
410210299Sed * @param context A hx509 context.
411210299Sed * @param tbs object to be signed.
412218893Sdim * @param oid extended key usage to add.
413218893Sdim *
414218893Sdim * @return An hx509 error code, see hx509_get_error_string().
415218893Sdim *
416218893Sdim * @ingroup hx509_ca
417193323Sed */
418193323Sed
419193323Sedint
420193323Sedhx509_ca_tbs_add_eku(hx509_context context,
421234353Sdim		     hx509_ca_tbs tbs,
422193323Sed		     const heim_oid *oid)
423234353Sdim{
424234353Sdim    void *ptr;
425234353Sdim    int ret;
426221345Sdim    unsigned i;
427218893Sdim
428218893Sdim    /* search for duplicates */
429218893Sdim    for (i = 0; i < tbs->eku.len; i++) {
430234353Sdim	if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
431218893Sdim	    return 0;
432210299Sed    }
433210299Sed
434210299Sed    ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
435210299Sed    if (ptr == NULL) {
436210299Sed	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
437210299Sed	return ENOMEM;
438210299Sed    }
439210299Sed    tbs->eku.val = ptr;
440193323Sed    ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
441193323Sed    if (ret) {
442193323Sed	hx509_set_error_string(context, 0, ret, "out of memory");
443234353Sdim	return ret;
444193323Sed    }
445234353Sdim    tbs->eku.len += 1;
446234353Sdim    return 0;
447218893Sdim}
448234353Sdim
449234353Sdim/**
450234353Sdim * Add CRL distribution point URI to the to-be-signed certificate
451234353Sdim * object.
452234353Sdim *
453234353Sdim * @param context A hx509 context.
454193323Sed * @param tbs object to be signed.
455234353Sdim * @param uri uri to the CRL.
456234353Sdim * @param issuername name of the issuer.
457234353Sdim *
458234353Sdim * @return An hx509 error code, see hx509_get_error_string().
459234353Sdim *
460234353Sdim * @ingroup hx509_ca
461234353Sdim */
462234353Sdim
463234353Sdimint
464234353Sdimhx509_ca_tbs_add_crl_dp_uri(hx509_context context,
465193323Sed			    hx509_ca_tbs tbs,
466234353Sdim			    const char *uri,
467234353Sdim			    hx509_name issuername)
468234353Sdim{
469234353Sdim    DistributionPoint dp;
470234353Sdim    int ret;
471234353Sdim
472234353Sdim    memset(&dp, 0, sizeof(dp));
473234353Sdim
474234353Sdim    dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
475234353Sdim
476234353Sdim    {
477234353Sdim	DistributionPointName name;
478234353Sdim	GeneralName gn;
479234353Sdim	size_t size;
480234353Sdim
481234353Sdim	name.element = choice_DistributionPointName_fullName;
482234353Sdim	name.u.fullName.len = 1;
483234353Sdim	name.u.fullName.val = &gn;
484234353Sdim
485234353Sdim	gn.element = choice_GeneralName_uniformResourceIdentifier;
486234353Sdim	gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
487234353Sdim	gn.u.uniformResourceIdentifier.length = strlen(uri);
488234353Sdim
489234353Sdim	ASN1_MALLOC_ENCODE(DistributionPointName,
490234353Sdim			   dp.distributionPoint->data,
491234353Sdim			   dp.distributionPoint->length,
492234353Sdim			   &name, &size, ret);
493234353Sdim	if (ret) {
494234353Sdim	    hx509_set_error_string(context, 0, ret,
495234353Sdim				   "Failed to encoded DistributionPointName");
496234353Sdim	    goto out;
497234353Sdim	}
498234353Sdim	if (dp.distributionPoint->length != size)
499234353Sdim	    _hx509_abort("internal ASN.1 encoder error");
500234353Sdim    }
501193323Sed
502193323Sed    if (issuername) {
503234353Sdim#if 1
504234353Sdim	/**
505193323Sed	 * issuername not supported
506193323Sed	 */
507234353Sdim	hx509_set_error_string(context, 0, EINVAL,
508193323Sed			       "CRLDistributionPoints.name.issuername not yet supported");
509193323Sed	return EINVAL;
510193323Sed#else
511234353Sdim	GeneralNames *crlissuer;
512234353Sdim	GeneralName gn;
513234353Sdim	Name n;
514234353Sdim
515193323Sed	crlissuer = calloc(1, sizeof(*crlissuer));
516193323Sed	if (crlissuer == NULL) {
517234353Sdim	    return ENOMEM;
518234353Sdim	}
519193323Sed	memset(&gn, 0, sizeof(gn));
520193323Sed
521193323Sed	gn.element = choice_GeneralName_directoryName;
522193323Sed	ret = hx509_name_to_Name(issuername, &n);
523193323Sed	if (ret) {
524234353Sdim	    hx509_set_error_string(context, 0, ret, "out of memory");
525193323Sed	    goto out;
526193323Sed	}
527193323Sed
528193323Sed	gn.u.directoryName.element = n.element;
529193323Sed	gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
530193323Sed
531193323Sed	ret = add_GeneralNames(&crlissuer, &gn);
532193323Sed	free_Name(&n);
533193323Sed	if (ret) {
534193323Sed	    hx509_set_error_string(context, 0, ret, "out of memory");
535193323Sed	    goto out;
536193323Sed	}
537193323Sed
538193323Sed	dp.cRLIssuer = &crlissuer;
539193323Sed#endif
540193323Sed    }
541193323Sed
542193323Sed    ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
543202878Srdivacky    if (ret) {
544203954Srdivacky	hx509_set_error_string(context, 0, ret, "out of memory");
545234353Sdim	goto out;
546234353Sdim    }
547234353Sdim
548234353Sdimout:
549202878Srdivacky    free_DistributionPoint(&dp);
550243830Sdim
551243830Sdim    return ret;
552243830Sdim}
553243830Sdim
554243830Sdim/**
555243830Sdim * Add Subject Alternative Name otherName to the to-be-signed
556243830Sdim * certificate object.
557243830Sdim *
558243830Sdim * @param context A hx509 context.
559243830Sdim * @param tbs object to be signed.
560243830Sdim * @param oid the oid of the OtherName.
561243830Sdim * @param os data in the other name.
562243830Sdim *
563243830Sdim * @return An hx509 error code, see hx509_get_error_string().
564243830Sdim *
565243830Sdim * @ingroup hx509_ca
566243830Sdim */
567243830Sdim
568243830Sdimint
569243830Sdimhx509_ca_tbs_add_san_otherName(hx509_context context,
570243830Sdim			       hx509_ca_tbs tbs,
571243830Sdim			       const heim_oid *oid,
572193323Sed			       const heim_octet_string *os)
573193323Sed{
574218893Sdim    GeneralName gn;
575193323Sed
576193323Sed    memset(&gn, 0, sizeof(gn));
577193323Sed    gn.element = choice_GeneralName_otherName;
578193323Sed    gn.u.otherName.type_id = *oid;
579193323Sed    gn.u.otherName.value = *os;
580193323Sed
581193323Sed    return add_GeneralNames(&tbs->san, &gn);
582193323Sed}
583203954Srdivacky
584203954Srdivacky/**
585205218Srdivacky * Add Kerberos Subject Alternative Name to the to-be-signed
586224145Sdim * certificate object. The principal string is a UTF8 string.
587224145Sdim *
588224145Sdim * @param context A hx509 context.
589224145Sdim * @param tbs object to be signed.
590224145Sdim * @param principal Kerberos principal to add to the certificate.
591224145Sdim *
592234353Sdim * @return An hx509 error code, see hx509_get_error_string().
593224145Sdim *
594224145Sdim * @ingroup hx509_ca
595224145Sdim */
596224145Sdim
597224145Sdimint
598224145Sdimhx509_ca_tbs_add_san_pkinit(hx509_context context,
599243830Sdim			    hx509_ca_tbs tbs,
600224145Sdim			    const char *principal)
601224145Sdim{
602224145Sdim    heim_octet_string os;
603193323Sed    KRB5PrincipalName p;
604193323Sed    size_t size;
605193323Sed    int ret;
606193323Sed    char *s = NULL;
607193323Sed
608193323Sed    memset(&p, 0, sizeof(p));
609193323Sed
610193323Sed    /* parse principal */
611193323Sed    {
612193323Sed	const char *str;
613193323Sed	char *q;
614193323Sed	int n;
615193323Sed
616193323Sed	/* count number of component */
617193323Sed	n = 1;
618193323Sed	for(str = principal; *str != '\0' && *str != '@'; str++){
619193323Sed	    if(*str=='\\'){
620193323Sed		if(str[1] == '\0' || str[1] == '@') {
621198090Srdivacky		    ret = HX509_PARSING_NAME_FAILED;
622193323Sed		    hx509_set_error_string(context, 0, ret,
623199481Srdivacky					   "trailing \\ in principal name");
624199481Srdivacky		    goto out;
625221345Sdim		}
626221345Sdim		str++;
627221345Sdim	    } else if(*str == '/')
628221345Sdim		n++;
629221345Sdim	}
630221345Sdim	p.principalName.name_string.val =
631221345Sdim	    calloc(n, sizeof(*p.principalName.name_string.val));
632221345Sdim	if (p.principalName.name_string.val == NULL) {
633193323Sed	    ret = ENOMEM;
634193323Sed	    hx509_set_error_string(context, 0, ret, "malloc: out of memory");
635193323Sed	    goto out;
636193323Sed	}
637193323Sed	p.principalName.name_string.len = n;
638193323Sed
639193323Sed	p.principalName.name_type = KRB5_NT_PRINCIPAL;
640193323Sed	q = s = strdup(principal);
641193323Sed	if (q == NULL) {
642193323Sed	    ret = ENOMEM;
643193323Sed	    hx509_set_error_string(context, 0, ret, "malloc: out of memory");
644193323Sed	    goto out;
645193323Sed	}
646193323Sed	p.realm = strrchr(q, '@');
647193323Sed	if (p.realm == NULL) {
648193323Sed	    ret = HX509_PARSING_NAME_FAILED;
649193323Sed	    hx509_set_error_string(context, 0, ret, "Missing @ in principal");
650193323Sed	    goto out;
651193323Sed	};
652193323Sed	*p.realm++ = '\0';
653193323Sed
654193323Sed	n = 0;
655193323Sed	while (q) {
656193323Sed	    p.principalName.name_string.val[n++] = q;
657193323Sed	    q = strchr(q, '/');
658193323Sed	    if (q)
659193323Sed		*q++ = '\0';
660193323Sed	}
661193323Sed    }
662193323Sed
663193323Sed    ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
664193323Sed    if (ret) {
665193323Sed	hx509_set_error_string(context, 0, ret, "Out of memory");
666193323Sed	goto out;
667193323Sed    }
668193323Sed    if (size != os.length)
669193323Sed	_hx509_abort("internal ASN.1 encoder error");
670193323Sed
671193323Sed    ret = hx509_ca_tbs_add_san_otherName(context,
672193323Sed					 tbs,
673193323Sed					 &asn1_oid_id_pkinit_san,
674193323Sed					 &os);
675193323Sed    free(os.data);
676193323Sedout:
677193323Sed    if (p.principalName.name_string.val)
678193323Sed	free (p.principalName.name_string.val);
679193323Sed    if (s)
680193323Sed	free(s);
681193323Sed    return ret;
682193323Sed}
683193323Sed
684193323Sed/*
685193323Sed *
686193323Sed */
687193323Sed
688193323Sedstatic int
689193323Sedadd_utf8_san(hx509_context context,
690193323Sed	     hx509_ca_tbs tbs,
691193323Sed	     const heim_oid *oid,
692193323Sed	     const char *string)
693193323Sed{
694193323Sed    const PKIXXmppAddr ustring = (const PKIXXmppAddr)string;
695193323Sed    heim_octet_string os;
696193323Sed    size_t size;
697193323Sed    int ret;
698193323Sed
699193323Sed    os.length = 0;
700193323Sed    os.data = NULL;
701193323Sed
702193323Sed    ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
703193323Sed    if (ret) {
704	hx509_set_error_string(context, 0, ret, "Out of memory");
705	goto out;
706    }
707    if (size != os.length)
708	_hx509_abort("internal ASN.1 encoder error");
709
710    ret = hx509_ca_tbs_add_san_otherName(context,
711					 tbs,
712					 oid,
713					 &os);
714    free(os.data);
715out:
716    return ret;
717}
718
719/**
720 * Add Microsoft UPN Subject Alternative Name to the to-be-signed
721 * certificate object. The principal string is a UTF8 string.
722 *
723 * @param context A hx509 context.
724 * @param tbs object to be signed.
725 * @param principal Microsoft UPN string.
726 *
727 * @return An hx509 error code, see hx509_get_error_string().
728 *
729 * @ingroup hx509_ca
730 */
731
732int
733hx509_ca_tbs_add_san_ms_upn(hx509_context context,
734			    hx509_ca_tbs tbs,
735			    const char *principal)
736{
737    return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
738}
739
740/**
741 * Add a Jabber/XMPP jid Subject Alternative Name to the to-be-signed
742 * certificate object. The jid is an UTF8 string.
743 *
744 * @param context A hx509 context.
745 * @param tbs object to be signed.
746 * @param jid string of an a jabber id in UTF8.
747 *
748 * @return An hx509 error code, see hx509_get_error_string().
749 *
750 * @ingroup hx509_ca
751 */
752
753int
754hx509_ca_tbs_add_san_jid(hx509_context context,
755			 hx509_ca_tbs tbs,
756			 const char *jid)
757{
758    return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
759}
760
761
762/**
763 * Add a Subject Alternative Name hostname to to-be-signed certificate
764 * object. A domain match starts with ., an exact match does not.
765 *
766 * Example of a an domain match: .domain.se matches the hostname
767 * host.domain.se.
768 *
769 * @param context A hx509 context.
770 * @param tbs object to be signed.
771 * @param dnsname a hostame.
772 *
773 * @return An hx509 error code, see hx509_get_error_string().
774 *
775 * @ingroup hx509_ca
776 */
777
778int
779hx509_ca_tbs_add_san_hostname(hx509_context context,
780			      hx509_ca_tbs tbs,
781			      const char *dnsname)
782{
783    GeneralName gn;
784
785    memset(&gn, 0, sizeof(gn));
786    gn.element = choice_GeneralName_dNSName;
787    gn.u.dNSName.data = rk_UNCONST(dnsname);
788    gn.u.dNSName.length = strlen(dnsname);
789
790    return add_GeneralNames(&tbs->san, &gn);
791}
792
793/**
794 * Add a Subject Alternative Name rfc822 (email address) to
795 * to-be-signed certificate object.
796 *
797 * @param context A hx509 context.
798 * @param tbs object to be signed.
799 * @param rfc822Name a string to a email address.
800 *
801 * @return An hx509 error code, see hx509_get_error_string().
802 *
803 * @ingroup hx509_ca
804 */
805
806int
807hx509_ca_tbs_add_san_rfc822name(hx509_context context,
808				hx509_ca_tbs tbs,
809				const char *rfc822Name)
810{
811    GeneralName gn;
812
813    memset(&gn, 0, sizeof(gn));
814    gn.element = choice_GeneralName_rfc822Name;
815    gn.u.rfc822Name.data = rk_UNCONST(rfc822Name);
816    gn.u.rfc822Name.length = strlen(rfc822Name);
817
818    return add_GeneralNames(&tbs->san, &gn);
819}
820
821/**
822 * Set the subject name of a to-be-signed certificate object.
823 *
824 * @param context A hx509 context.
825 * @param tbs object to be signed.
826 * @param subject the name to set a subject.
827 *
828 * @return An hx509 error code, see hx509_get_error_string().
829 *
830 * @ingroup hx509_ca
831 */
832
833int
834hx509_ca_tbs_set_subject(hx509_context context,
835			 hx509_ca_tbs tbs,
836			 hx509_name subject)
837{
838    if (tbs->subject)
839	hx509_name_free(&tbs->subject);
840    return hx509_name_copy(context, subject, &tbs->subject);
841}
842
843/**
844 * Set the issuerUniqueID and subjectUniqueID
845 *
846 * These are only supposed to be used considered with version 2
847 * certificates, replaced by the two extensions SubjectKeyIdentifier
848 * and IssuerKeyIdentifier. This function is to allow application
849 * using legacy protocol to issue them.
850 *
851 * @param context A hx509 context.
852 * @param tbs object to be signed.
853 * @param issuerUniqueID to be set
854 * @param subjectUniqueID to be set
855 *
856 * @return An hx509 error code, see hx509_get_error_string().
857 *
858 * @ingroup hx509_ca
859 */
860
861int
862hx509_ca_tbs_set_unique(hx509_context context,
863			hx509_ca_tbs tbs,
864			const heim_bit_string *subjectUniqueID,
865			const heim_bit_string *issuerUniqueID)
866{
867    int ret;
868
869    der_free_bit_string(&tbs->subjectUniqueID);
870    der_free_bit_string(&tbs->issuerUniqueID);
871
872    if (subjectUniqueID) {
873	ret = der_copy_bit_string(subjectUniqueID, &tbs->subjectUniqueID);
874	if (ret)
875	    return ret;
876    }
877
878    if (issuerUniqueID) {
879	ret = der_copy_bit_string(issuerUniqueID, &tbs->issuerUniqueID);
880	if (ret)
881	    return ret;
882    }
883
884    return 0;
885}
886
887/**
888 * Expand the the subject name in the to-be-signed certificate object
889 * using hx509_name_expand().
890 *
891 * @param context A hx509 context.
892 * @param tbs object to be signed.
893 * @param env enviroment variable to expand variables in the subject
894 * name, see hx509_env_init().
895 *
896 * @return An hx509 error code, see hx509_get_error_string().
897 *
898 * @ingroup hx509_ca
899 */
900
901int
902hx509_ca_tbs_subject_expand(hx509_context context,
903			    hx509_ca_tbs tbs,
904			    hx509_env env)
905{
906    return hx509_name_expand(context, tbs->subject, env);
907}
908
909/*
910 *
911 */
912
913static int
914add_extension(hx509_context context,
915	      TBSCertificate *tbsc,
916	      int critical_flag,
917	      const heim_oid *oid,
918	      const heim_octet_string *data)
919{
920    Extension ext;
921    int ret;
922
923    memset(&ext, 0, sizeof(ext));
924
925    if (critical_flag) {
926	ext.critical = malloc(sizeof(*ext.critical));
927	if (ext.critical == NULL) {
928	    ret = ENOMEM;
929	    hx509_set_error_string(context, 0, ret, "Out of memory");
930	    goto out;
931	}
932	*ext.critical = TRUE;
933    }
934
935    ret = der_copy_oid(oid, &ext.extnID);
936    if (ret) {
937	hx509_set_error_string(context, 0, ret, "Out of memory");
938	goto out;
939    }
940    ret = der_copy_octet_string(data, &ext.extnValue);
941    if (ret) {
942	hx509_set_error_string(context, 0, ret, "Out of memory");
943	goto out;
944    }
945    ret = add_Extensions(tbsc->extensions, &ext);
946    if (ret) {
947	hx509_set_error_string(context, 0, ret, "Out of memory");
948	goto out;
949    }
950out:
951    free_Extension(&ext);
952    return ret;
953}
954
955static int
956build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
957{
958    char *tstr;
959    time_t t;
960    int ret;
961
962    ret = copy_Name(issuer, subject);
963    if (ret) {
964	hx509_set_error_string(context, 0, ret,
965			       "Failed to copy subject name");
966	return ret;
967    }
968
969    t = time(NULL);
970    asprintf(&tstr, "ts-%lu", (unsigned long)t);
971    if (tstr == NULL) {
972	hx509_set_error_string(context, 0, ENOMEM,
973			       "Failed to copy subject name");
974	return ENOMEM;
975    }
976    /* prefix with CN=<ts>,...*/
977    ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
978    free(tstr);
979    if (ret)
980	free_Name(subject);
981    return ret;
982}
983
984static int
985ca_sign(hx509_context context,
986	hx509_ca_tbs tbs,
987	hx509_private_key signer,
988	const AuthorityKeyIdentifier *ai,
989	const Name *issuername,
990	hx509_cert *certificate)
991{
992    heim_octet_string data;
993    Certificate c;
994    TBSCertificate *tbsc;
995    size_t size;
996    int ret;
997    const AlgorithmIdentifier *sigalg;
998    time_t notBefore;
999    time_t notAfter;
1000    unsigned key_usage;
1001
1002    sigalg = _hx509_crypto_default_sig_alg;
1003
1004    memset(&c, 0, sizeof(c));
1005
1006    /*
1007     * Default values are: Valid since 24h ago, valid one year into
1008     * the future, KeyUsage digitalSignature and keyEncipherment set,
1009     * and keyCertSign for CA certificates.
1010     */
1011    notBefore = tbs->notBefore;
1012    if (notBefore == 0)
1013	notBefore = time(NULL) - 3600 * 24;
1014    notAfter = tbs->notAfter;
1015    if (notAfter == 0)
1016	notAfter = time(NULL) + 3600 * 24 * 365;
1017
1018    key_usage = tbs->key_usage;
1019    if (key_usage == 0) {
1020	KeyUsage ku;
1021	memset(&ku, 0, sizeof(ku));
1022	ku.digitalSignature = 1;
1023	ku.keyEncipherment = 1;
1024	key_usage = KeyUsage2int(ku);
1025    }
1026
1027    if (tbs->flags.ca) {
1028	KeyUsage ku;
1029	memset(&ku, 0, sizeof(ku));
1030	ku.keyCertSign = 1;
1031	ku.cRLSign = 1;
1032	key_usage |= KeyUsage2int(ku);
1033    }
1034
1035    /*
1036     *
1037     */
1038
1039    tbsc = &c.tbsCertificate;
1040
1041    if (tbs->flags.key == 0) {
1042	ret = EINVAL;
1043	hx509_set_error_string(context, 0, ret, "No public key set");
1044	return ret;
1045    }
1046    /*
1047     * Don't put restrictions on proxy certificate's subject name, it
1048     * will be generated below.
1049     */
1050    if (!tbs->flags.proxy) {
1051	if (tbs->subject == NULL) {
1052	    hx509_set_error_string(context, 0, EINVAL, "No subject name set");
1053	    return EINVAL;
1054	}
1055	if (hx509_name_is_null_p(tbs->subject) && tbs->san.len == 0) {
1056	    hx509_set_error_string(context, 0, EINVAL,
1057				   "NULL subject and no SubjectAltNames");
1058	    return EINVAL;
1059	}
1060    }
1061    if (tbs->flags.ca && tbs->flags.proxy) {
1062	hx509_set_error_string(context, 0, EINVAL, "Can't be proxy and CA "
1063			       "at the same time");
1064	return EINVAL;
1065    }
1066    if (tbs->flags.proxy) {
1067	if (tbs->san.len > 0) {
1068	    hx509_set_error_string(context, 0, EINVAL,
1069				   "Proxy certificate is not allowed "
1070				   "to have SubjectAltNames");
1071	    return EINVAL;
1072	}
1073    }
1074
1075    /* version         [0]  Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, */
1076    tbsc->version = calloc(1, sizeof(*tbsc->version));
1077    if (tbsc->version == NULL) {
1078	ret = ENOMEM;
1079	hx509_set_error_string(context, 0, ret, "Out of memory");
1080	goto out;
1081    }
1082    *tbsc->version = rfc3280_version_3;
1083    /* serialNumber         CertificateSerialNumber, */
1084    if (tbs->flags.serial) {
1085	ret = der_copy_heim_integer(&tbs->serial, &tbsc->serialNumber);
1086	if (ret) {
1087	    hx509_set_error_string(context, 0, ret, "Out of memory");
1088	    goto out;
1089	}
1090    } else {
1091	tbsc->serialNumber.length = 20;
1092	tbsc->serialNumber.data = malloc(tbsc->serialNumber.length);
1093	if (tbsc->serialNumber.data == NULL){
1094	    ret = ENOMEM;
1095	    hx509_set_error_string(context, 0, ret, "Out of memory");
1096	    goto out;
1097	}
1098	/* XXX diffrent */
1099	RAND_bytes(tbsc->serialNumber.data, tbsc->serialNumber.length);
1100	((unsigned char *)tbsc->serialNumber.data)[0] &= 0x7f;
1101    }
1102    /* signature            AlgorithmIdentifier, */
1103    ret = copy_AlgorithmIdentifier(sigalg, &tbsc->signature);
1104    if (ret) {
1105	hx509_set_error_string(context, 0, ret, "Failed to copy sigature alg");
1106	goto out;
1107    }
1108    /* issuer               Name, */
1109    if (issuername)
1110	ret = copy_Name(issuername, &tbsc->issuer);
1111    else
1112	ret = hx509_name_to_Name(tbs->subject, &tbsc->issuer);
1113    if (ret) {
1114	hx509_set_error_string(context, 0, ret, "Failed to copy issuer name");
1115	goto out;
1116    }
1117    /* validity             Validity, */
1118    tbsc->validity.notBefore.element = choice_Time_generalTime;
1119    tbsc->validity.notBefore.u.generalTime = notBefore;
1120    tbsc->validity.notAfter.element = choice_Time_generalTime;
1121    tbsc->validity.notAfter.u.generalTime = notAfter;
1122    /* subject              Name, */
1123    if (tbs->flags.proxy) {
1124	ret = build_proxy_prefix(context, &tbsc->issuer, &tbsc->subject);
1125	if (ret)
1126	    goto out;
1127    } else {
1128	ret = hx509_name_to_Name(tbs->subject, &tbsc->subject);
1129	if (ret) {
1130	    hx509_set_error_string(context, 0, ret,
1131				   "Failed to copy subject name");
1132	    goto out;
1133	}
1134    }
1135    /* subjectPublicKeyInfo SubjectPublicKeyInfo, */
1136    ret = copy_SubjectPublicKeyInfo(&tbs->spki, &tbsc->subjectPublicKeyInfo);
1137    if (ret) {
1138	hx509_set_error_string(context, 0, ret, "Failed to copy spki");
1139	goto out;
1140    }
1141    /* issuerUniqueID  [1]  IMPLICIT BIT STRING OPTIONAL */
1142    if (tbs->issuerUniqueID.length) {
1143	tbsc->issuerUniqueID = calloc(1, sizeof(*tbsc->issuerUniqueID));
1144	if (tbsc->issuerUniqueID == NULL) {
1145	    ret = ENOMEM;
1146	    hx509_set_error_string(context, 0, ret, "Out of memory");
1147	    goto out;
1148	}
1149	ret = der_copy_bit_string(&tbs->issuerUniqueID, tbsc->issuerUniqueID);
1150	if (ret) {
1151	    hx509_set_error_string(context, 0, ret, "Out of memory");
1152	    goto out;
1153	}
1154    }
1155    /* subjectUniqueID [2]  IMPLICIT BIT STRING OPTIONAL */
1156    if (tbs->subjectUniqueID.length) {
1157	tbsc->subjectUniqueID = calloc(1, sizeof(*tbsc->subjectUniqueID));
1158	if (tbsc->subjectUniqueID == NULL) {
1159	    ret = ENOMEM;
1160	    hx509_set_error_string(context, 0, ret, "Out of memory");
1161	    goto out;
1162	}
1163
1164	ret = der_copy_bit_string(&tbs->subjectUniqueID, tbsc->subjectUniqueID);
1165	if (ret) {
1166	    hx509_set_error_string(context, 0, ret, "Out of memory");
1167	    goto out;
1168	}
1169    }
1170
1171    /* extensions      [3]  EXPLICIT Extensions OPTIONAL */
1172    tbsc->extensions = calloc(1, sizeof(*tbsc->extensions));
1173    if (tbsc->extensions == NULL) {
1174	ret = ENOMEM;
1175	hx509_set_error_string(context, 0, ret, "Out of memory");
1176	goto out;
1177    }
1178
1179    /* Add the text BMP string Domaincontroller to the cert */
1180    if (tbs->flags.domaincontroller) {
1181	data.data = rk_UNCONST("\x1e\x20\x00\x44\x00\x6f\x00\x6d"
1182			       "\x00\x61\x00\x69\x00\x6e\x00\x43"
1183			       "\x00\x6f\x00\x6e\x00\x74\x00\x72"
1184			       "\x00\x6f\x00\x6c\x00\x6c\x00\x65"
1185			       "\x00\x72");
1186	data.length = 34;
1187
1188	ret = add_extension(context, tbsc, 0,
1189			    &asn1_oid_id_ms_cert_enroll_domaincontroller,
1190			    &data);
1191	if (ret)
1192	    goto out;
1193    }
1194
1195    /* add KeyUsage */
1196    {
1197	KeyUsage ku;
1198
1199	ku = int2KeyUsage(key_usage);
1200	ASN1_MALLOC_ENCODE(KeyUsage, data.data, data.length, &ku, &size, ret);
1201	if (ret) {
1202	    hx509_set_error_string(context, 0, ret, "Out of memory");
1203	    goto out;
1204	}
1205	if (size != data.length)
1206	    _hx509_abort("internal ASN.1 encoder error");
1207	ret = add_extension(context, tbsc, 1,
1208			    &asn1_oid_id_x509_ce_keyUsage, &data);
1209	free(data.data);
1210	if (ret)
1211	    goto out;
1212    }
1213
1214    /* add ExtendedKeyUsage */
1215    if (tbs->eku.len > 0) {
1216	ASN1_MALLOC_ENCODE(ExtKeyUsage, data.data, data.length,
1217			   &tbs->eku, &size, ret);
1218	if (ret) {
1219	    hx509_set_error_string(context, 0, ret, "Out of memory");
1220	    goto out;
1221	}
1222	if (size != data.length)
1223	    _hx509_abort("internal ASN.1 encoder error");
1224	ret = add_extension(context, tbsc, 0,
1225			    &asn1_oid_id_x509_ce_extKeyUsage, &data);
1226	free(data.data);
1227	if (ret)
1228	    goto out;
1229    }
1230
1231    /* add Subject Alternative Name */
1232    if (tbs->san.len > 0) {
1233	ASN1_MALLOC_ENCODE(GeneralNames, data.data, data.length,
1234			   &tbs->san, &size, ret);
1235	if (ret) {
1236	    hx509_set_error_string(context, 0, ret, "Out of memory");
1237	    goto out;
1238	}
1239	if (size != data.length)
1240	    _hx509_abort("internal ASN.1 encoder error");
1241	ret = add_extension(context, tbsc, 0,
1242			    &asn1_oid_id_x509_ce_subjectAltName,
1243			    &data);
1244	free(data.data);
1245	if (ret)
1246	    goto out;
1247    }
1248
1249    /* Add Authority Key Identifier */
1250    if (ai) {
1251	ASN1_MALLOC_ENCODE(AuthorityKeyIdentifier, data.data, data.length,
1252			   ai, &size, ret);
1253	if (ret) {
1254	    hx509_set_error_string(context, 0, ret, "Out of memory");
1255	    goto out;
1256	}
1257	if (size != data.length)
1258	    _hx509_abort("internal ASN.1 encoder error");
1259	ret = add_extension(context, tbsc, 0,
1260			    &asn1_oid_id_x509_ce_authorityKeyIdentifier,
1261			    &data);
1262	free(data.data);
1263	if (ret)
1264	    goto out;
1265    }
1266
1267    /* Add Subject Key Identifier */
1268    {
1269	SubjectKeyIdentifier si;
1270	unsigned char hash[SHA_DIGEST_LENGTH];
1271
1272	{
1273	    EVP_MD_CTX *ctx;
1274
1275	    ctx = EVP_MD_CTX_create();
1276	    EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
1277	    EVP_DigestUpdate(ctx, tbs->spki.subjectPublicKey.data,
1278			     tbs->spki.subjectPublicKey.length / 8);
1279	    EVP_DigestFinal_ex(ctx, hash, NULL);
1280	    EVP_MD_CTX_destroy(ctx);
1281	}
1282
1283	si.data = hash;
1284	si.length = sizeof(hash);
1285
1286	ASN1_MALLOC_ENCODE(SubjectKeyIdentifier, data.data, data.length,
1287			   &si, &size, ret);
1288	if (ret) {
1289	    hx509_set_error_string(context, 0, ret, "Out of memory");
1290	    goto out;
1291	}
1292	if (size != data.length)
1293	    _hx509_abort("internal ASN.1 encoder error");
1294	ret = add_extension(context, tbsc, 0,
1295			    &asn1_oid_id_x509_ce_subjectKeyIdentifier,
1296			    &data);
1297	free(data.data);
1298	if (ret)
1299	    goto out;
1300    }
1301
1302    /* Add BasicConstraints */
1303    {
1304	BasicConstraints bc;
1305	int aCA = 1;
1306	unsigned int path;
1307
1308	memset(&bc, 0, sizeof(bc));
1309
1310	if (tbs->flags.ca) {
1311	    bc.cA = &aCA;
1312	    if (tbs->pathLenConstraint >= 0) {
1313		path = tbs->pathLenConstraint;
1314		bc.pathLenConstraint = &path;
1315	    }
1316	}
1317
1318	ASN1_MALLOC_ENCODE(BasicConstraints, data.data, data.length,
1319			   &bc, &size, ret);
1320	if (ret) {
1321	    hx509_set_error_string(context, 0, ret, "Out of memory");
1322	    goto out;
1323	}
1324	if (size != data.length)
1325	    _hx509_abort("internal ASN.1 encoder error");
1326	/* Critical if this is a CA */
1327	ret = add_extension(context, tbsc, tbs->flags.ca,
1328			    &asn1_oid_id_x509_ce_basicConstraints,
1329			    &data);
1330	free(data.data);
1331	if (ret)
1332	    goto out;
1333    }
1334
1335    /* add Proxy */
1336    if (tbs->flags.proxy) {
1337	ProxyCertInfo info;
1338
1339	memset(&info, 0, sizeof(info));
1340
1341	if (tbs->pathLenConstraint >= 0) {
1342	    info.pCPathLenConstraint =
1343		malloc(sizeof(*info.pCPathLenConstraint));
1344	    if (info.pCPathLenConstraint == NULL) {
1345		ret = ENOMEM;
1346		hx509_set_error_string(context, 0, ret, "Out of memory");
1347		goto out;
1348	    }
1349	    *info.pCPathLenConstraint = tbs->pathLenConstraint;
1350	}
1351
1352	ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
1353			   &info.proxyPolicy.policyLanguage);
1354	if (ret) {
1355	    free_ProxyCertInfo(&info);
1356	    hx509_set_error_string(context, 0, ret, "Out of memory");
1357	    goto out;
1358	}
1359
1360	ASN1_MALLOC_ENCODE(ProxyCertInfo, data.data, data.length,
1361			   &info, &size, ret);
1362	free_ProxyCertInfo(&info);
1363	if (ret) {
1364	    hx509_set_error_string(context, 0, ret, "Out of memory");
1365	    goto out;
1366	}
1367	if (size != data.length)
1368	    _hx509_abort("internal ASN.1 encoder error");
1369	ret = add_extension(context, tbsc, 0,
1370			    &asn1_oid_id_pkix_pe_proxyCertInfo,
1371			    &data);
1372	free(data.data);
1373	if (ret)
1374	    goto out;
1375    }
1376
1377    if (tbs->crldp.len) {
1378
1379	ASN1_MALLOC_ENCODE(CRLDistributionPoints, data.data, data.length,
1380			   &tbs->crldp, &size, ret);
1381	if (ret) {
1382	    hx509_set_error_string(context, 0, ret, "Out of memory");
1383	    goto out;
1384	}
1385	if (size != data.length)
1386	    _hx509_abort("internal ASN.1 encoder error");
1387	ret = add_extension(context, tbsc, FALSE,
1388			    &asn1_oid_id_x509_ce_cRLDistributionPoints,
1389			    &data);
1390	free(data.data);
1391	if (ret)
1392	    goto out;
1393    }
1394
1395    ASN1_MALLOC_ENCODE(TBSCertificate, data.data, data.length,tbsc, &size, ret);
1396    if (ret) {
1397	hx509_set_error_string(context, 0, ret, "malloc out of memory");
1398	goto out;
1399    }
1400    if (data.length != size)
1401	_hx509_abort("internal ASN.1 encoder error");
1402
1403    ret = _hx509_create_signature_bitstring(context,
1404					    signer,
1405					    sigalg,
1406					    &data,
1407					    &c.signatureAlgorithm,
1408					    &c.signatureValue);
1409    free(data.data);
1410    if (ret)
1411	goto out;
1412
1413    ret = hx509_cert_init(context, &c, certificate);
1414    if (ret)
1415	goto out;
1416
1417    free_Certificate(&c);
1418
1419    return 0;
1420
1421out:
1422    free_Certificate(&c);
1423    return ret;
1424}
1425
1426static int
1427get_AuthorityKeyIdentifier(hx509_context context,
1428			   const Certificate *certificate,
1429			   AuthorityKeyIdentifier *ai)
1430{
1431    SubjectKeyIdentifier si;
1432    int ret;
1433
1434    ret = _hx509_find_extension_subject_key_id(certificate, &si);
1435    if (ret == 0) {
1436	ai->keyIdentifier = calloc(1, sizeof(*ai->keyIdentifier));
1437	if (ai->keyIdentifier == NULL) {
1438	    free_SubjectKeyIdentifier(&si);
1439	    ret = ENOMEM;
1440	    hx509_set_error_string(context, 0, ret, "Out of memory");
1441	    goto out;
1442	}
1443	ret = der_copy_octet_string(&si, ai->keyIdentifier);
1444	free_SubjectKeyIdentifier(&si);
1445	if (ret) {
1446	    hx509_set_error_string(context, 0, ret, "Out of memory");
1447	    goto out;
1448	}
1449    } else {
1450	GeneralNames gns;
1451	GeneralName gn;
1452	Name name;
1453
1454	memset(&gn, 0, sizeof(gn));
1455	memset(&gns, 0, sizeof(gns));
1456	memset(&name, 0, sizeof(name));
1457
1458	ai->authorityCertIssuer =
1459	    calloc(1, sizeof(*ai->authorityCertIssuer));
1460	if (ai->authorityCertIssuer == NULL) {
1461	    ret = ENOMEM;
1462	    hx509_set_error_string(context, 0, ret, "Out of memory");
1463	    goto out;
1464	}
1465	ai->authorityCertSerialNumber =
1466	    calloc(1, sizeof(*ai->authorityCertSerialNumber));
1467	if (ai->authorityCertSerialNumber == NULL) {
1468	    ret = ENOMEM;
1469	    hx509_set_error_string(context, 0, ret, "Out of memory");
1470	    goto out;
1471	}
1472
1473	/*
1474	 * XXX unbreak when asn1 compiler handle IMPLICIT
1475	 *
1476	 * This is so horrible.
1477	 */
1478
1479	ret = copy_Name(&certificate->tbsCertificate.subject, &name);
1480	if (ret) {
1481	    hx509_set_error_string(context, 0, ret, "Out of memory");
1482	    goto out;
1483	}
1484
1485	memset(&gn, 0, sizeof(gn));
1486	gn.element = choice_GeneralName_directoryName;
1487	gn.u.directoryName.element =
1488	    choice_GeneralName_directoryName_rdnSequence;
1489	gn.u.directoryName.u.rdnSequence = name.u.rdnSequence;
1490
1491	ret = add_GeneralNames(&gns, &gn);
1492	if (ret) {
1493	    hx509_set_error_string(context, 0, ret, "Out of memory");
1494	    goto out;
1495	}
1496
1497	ai->authorityCertIssuer->val = gns.val;
1498	ai->authorityCertIssuer->len = gns.len;
1499
1500	ret = der_copy_heim_integer(&certificate->tbsCertificate.serialNumber,
1501				    ai->authorityCertSerialNumber);
1502	if (ai->authorityCertSerialNumber == NULL) {
1503	    ret = ENOMEM;
1504	    hx509_set_error_string(context, 0, ret, "Out of memory");
1505	    goto out;
1506	}
1507    }
1508out:
1509    if (ret)
1510	free_AuthorityKeyIdentifier(ai);
1511    return ret;
1512}
1513
1514
1515/**
1516 * Sign a to-be-signed certificate object with a issuer certificate.
1517 *
1518 * The caller needs to at least have called the following functions on the
1519 * to-be-signed certificate object:
1520 * - hx509_ca_tbs_init()
1521 * - hx509_ca_tbs_set_subject()
1522 * - hx509_ca_tbs_set_spki()
1523 *
1524 * When done the to-be-signed certificate object should be freed with
1525 * hx509_ca_tbs_free().
1526 *
1527 * When creating self-signed certificate use hx509_ca_sign_self() instead.
1528 *
1529 * @param context A hx509 context.
1530 * @param tbs object to be signed.
1531 * @param signer the CA certificate object to sign with (need private key).
1532 * @param certificate return cerificate, free with hx509_cert_free().
1533 *
1534 * @return An hx509 error code, see hx509_get_error_string().
1535 *
1536 * @ingroup hx509_ca
1537 */
1538
1539int
1540hx509_ca_sign(hx509_context context,
1541	      hx509_ca_tbs tbs,
1542	      hx509_cert signer,
1543	      hx509_cert *certificate)
1544{
1545    const Certificate *signer_cert;
1546    AuthorityKeyIdentifier ai;
1547    int ret;
1548
1549    memset(&ai, 0, sizeof(ai));
1550
1551    signer_cert = _hx509_get_cert(signer);
1552
1553    ret = get_AuthorityKeyIdentifier(context, signer_cert, &ai);
1554    if (ret)
1555	goto out;
1556
1557    ret = ca_sign(context,
1558		  tbs,
1559		  _hx509_cert_private_key(signer),
1560		  &ai,
1561		  &signer_cert->tbsCertificate.subject,
1562		  certificate);
1563
1564out:
1565    free_AuthorityKeyIdentifier(&ai);
1566
1567    return ret;
1568}
1569
1570/**
1571 * Work just like hx509_ca_sign() but signs it-self.
1572 *
1573 * @param context A hx509 context.
1574 * @param tbs object to be signed.
1575 * @param signer private key to sign with.
1576 * @param certificate return cerificate, free with hx509_cert_free().
1577 *
1578 * @return An hx509 error code, see hx509_get_error_string().
1579 *
1580 * @ingroup hx509_ca
1581 */
1582
1583int
1584hx509_ca_sign_self(hx509_context context,
1585		   hx509_ca_tbs tbs,
1586		   hx509_private_key signer,
1587		   hx509_cert *certificate)
1588{
1589    return ca_sign(context,
1590		   tbs,
1591		   signer,
1592		   NULL,
1593		   NULL,
1594		   certificate);
1595}
1596