1/*	$NetBSD: ca.c,v 1.1.1.1 2011/04/13 18:15:09 elric Exp $	*/
2
3/*
4 * Copyright (c) 2006 - 2010 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of the Institute nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include "hx_locl.h"
37#include <krb5/pkinit_asn1.h>
38
39/**
40 * @page page_ca Hx509 CA functions
41 *
42 * See the library functions here: @ref hx509_ca
43 */
44
45struct hx509_ca_tbs {
46    hx509_name subject;
47    SubjectPublicKeyInfo spki;
48    ExtKeyUsage eku;
49    GeneralNames san;
50    unsigned key_usage;
51    heim_integer serial;
52    struct {
53	unsigned int proxy:1;
54	unsigned int ca:1;
55	unsigned int key:1;
56	unsigned int serial:1;
57	unsigned int domaincontroller:1;
58	unsigned int xUniqueID:1;
59    } flags;
60    time_t notBefore;
61    time_t notAfter;
62    int pathLenConstraint; /* both for CA and Proxy */
63    CRLDistributionPoints crldp;
64    heim_bit_string subjectUniqueID;
65    heim_bit_string issuerUniqueID;
66
67};
68
69/**
70 * Allocate an to-be-signed certificate object that will be converted
71 * into an certificate.
72 *
73 * @param context A hx509 context.
74 * @param tbs returned to-be-signed certicate object, free with
75 * hx509_ca_tbs_free().
76 *
77 * @return An hx509 error code, see hx509_get_error_string().
78 *
79 * @ingroup hx509_ca
80 */
81
82int
83hx509_ca_tbs_init(hx509_context context, hx509_ca_tbs *tbs)
84{
85    *tbs = calloc(1, sizeof(**tbs));
86    if (*tbs == NULL)
87	return ENOMEM;
88
89    return 0;
90}
91
92/**
93 * Free an To Be Signed object.
94 *
95 * @param tbs object to free.
96 *
97 * @ingroup hx509_ca
98 */
99
100void
101hx509_ca_tbs_free(hx509_ca_tbs *tbs)
102{
103    if (tbs == NULL || *tbs == NULL)
104	return;
105
106    free_SubjectPublicKeyInfo(&(*tbs)->spki);
107    free_GeneralNames(&(*tbs)->san);
108    free_ExtKeyUsage(&(*tbs)->eku);
109    der_free_heim_integer(&(*tbs)->serial);
110    free_CRLDistributionPoints(&(*tbs)->crldp);
111    der_free_bit_string(&(*tbs)->subjectUniqueID);
112    der_free_bit_string(&(*tbs)->issuerUniqueID);
113    hx509_name_free(&(*tbs)->subject);
114
115    memset(*tbs, 0, sizeof(**tbs));
116    free(*tbs);
117    *tbs = NULL;
118}
119
120/**
121 * Set the absolute time when the certificate is valid from. If not
122 * set the current time will be used.
123 *
124 * @param context A hx509 context.
125 * @param tbs object to be signed.
126 * @param t time the certificated will start to be valid
127 *
128 * @return An hx509 error code, see hx509_get_error_string().
129 *
130 * @ingroup hx509_ca
131 */
132
133int
134hx509_ca_tbs_set_notBefore(hx509_context context,
135			   hx509_ca_tbs tbs,
136			   time_t t)
137{
138    tbs->notBefore = t;
139    return 0;
140}
141
142/**
143 * Set the absolute time when the certificate is valid to.
144 *
145 * @param context A hx509 context.
146 * @param tbs object to be signed.
147 * @param t time when the certificate will expire
148 *
149 * @return An hx509 error code, see hx509_get_error_string().
150 *
151 * @ingroup hx509_ca
152 */
153
154int
155hx509_ca_tbs_set_notAfter(hx509_context context,
156			   hx509_ca_tbs tbs,
157			   time_t t)
158{
159    tbs->notAfter = t;
160    return 0;
161}
162
163/**
164 * Set the relative time when the certificiate is going to expire.
165 *
166 * @param context A hx509 context.
167 * @param tbs object to be signed.
168 * @param delta seconds to the certificate is going to expire.
169 *
170 * @return An hx509 error code, see hx509_get_error_string().
171 *
172 * @ingroup hx509_ca
173 */
174
175int
176hx509_ca_tbs_set_notAfter_lifetime(hx509_context context,
177				   hx509_ca_tbs tbs,
178				   time_t delta)
179{
180    return hx509_ca_tbs_set_notAfter(context, tbs, time(NULL) + delta);
181}
182
183static const struct units templatebits[] = {
184    { "ExtendedKeyUsage", HX509_CA_TEMPLATE_EKU },
185    { "KeyUsage", HX509_CA_TEMPLATE_KU },
186    { "SPKI", HX509_CA_TEMPLATE_SPKI },
187    { "notAfter", HX509_CA_TEMPLATE_NOTAFTER },
188    { "notBefore", HX509_CA_TEMPLATE_NOTBEFORE },
189    { "serial", HX509_CA_TEMPLATE_SERIAL },
190    { "subject", HX509_CA_TEMPLATE_SUBJECT },
191    { NULL, 0 }
192};
193
194/**
195 * Make of template units, use to build flags argument to
196 * hx509_ca_tbs_set_template() with parse_units().
197 *
198 * @return an units structure.
199 *
200 * @ingroup hx509_ca
201 */
202
203const struct units *
204hx509_ca_tbs_template_units(void)
205{
206    return templatebits;
207}
208
209/**
210 * Initialize the to-be-signed certificate object from a template certifiate.
211 *
212 * @param context A hx509 context.
213 * @param tbs object to be signed.
214 * @param flags bit field selecting what to copy from the template
215 * certifiate.
216 * @param cert template certificate.
217 *
218 * @return An hx509 error code, see hx509_get_error_string().
219 *
220 * @ingroup hx509_ca
221 */
222
223int
224hx509_ca_tbs_set_template(hx509_context context,
225			  hx509_ca_tbs tbs,
226			  int flags,
227			  hx509_cert cert)
228{
229    int ret;
230
231    if (flags & HX509_CA_TEMPLATE_SUBJECT) {
232	if (tbs->subject)
233	    hx509_name_free(&tbs->subject);
234	ret = hx509_cert_get_subject(cert, &tbs->subject);
235	if (ret) {
236	    hx509_set_error_string(context, 0, ret,
237				   "Failed to get subject from template");
238	    return ret;
239	}
240    }
241    if (flags & HX509_CA_TEMPLATE_SERIAL) {
242	der_free_heim_integer(&tbs->serial);
243	ret = hx509_cert_get_serialnumber(cert, &tbs->serial);
244	tbs->flags.serial = !ret;
245	if (ret) {
246	    hx509_set_error_string(context, 0, ret,
247				   "Failed to copy serial number");
248	    return ret;
249	}
250    }
251    if (flags & HX509_CA_TEMPLATE_NOTBEFORE)
252	tbs->notBefore = hx509_cert_get_notBefore(cert);
253    if (flags & HX509_CA_TEMPLATE_NOTAFTER)
254	tbs->notAfter = hx509_cert_get_notAfter(cert);
255    if (flags & HX509_CA_TEMPLATE_SPKI) {
256	free_SubjectPublicKeyInfo(&tbs->spki);
257	ret = hx509_cert_get_SPKI(context, cert, &tbs->spki);
258	tbs->flags.key = !ret;
259	if (ret)
260	    return ret;
261    }
262    if (flags & HX509_CA_TEMPLATE_KU) {
263	KeyUsage ku;
264	ret = _hx509_cert_get_keyusage(context, cert, &ku);
265	if (ret)
266	    return ret;
267	tbs->key_usage = KeyUsage2int(ku);
268    }
269    if (flags & HX509_CA_TEMPLATE_EKU) {
270	ExtKeyUsage eku;
271	int i;
272	ret = _hx509_cert_get_eku(context, cert, &eku);
273	if (ret)
274	    return ret;
275	for (i = 0; i < eku.len; i++) {
276	    ret = hx509_ca_tbs_add_eku(context, tbs, &eku.val[i]);
277	    if (ret) {
278		free_ExtKeyUsage(&eku);
279		return ret;
280	    }
281	}
282	free_ExtKeyUsage(&eku);
283    }
284    return 0;
285}
286
287/**
288 * Make the to-be-signed certificate object a CA certificate. If the
289 * pathLenConstraint is negative path length constraint is used.
290 *
291 * @param context A hx509 context.
292 * @param tbs object to be signed.
293 * @param pathLenConstraint path length constraint, negative, no
294 * constraint.
295 *
296 * @return An hx509 error code, see hx509_get_error_string().
297 *
298 * @ingroup hx509_ca
299 */
300
301int
302hx509_ca_tbs_set_ca(hx509_context context,
303		    hx509_ca_tbs tbs,
304		    int pathLenConstraint)
305{
306    tbs->flags.ca = 1;
307    tbs->pathLenConstraint = pathLenConstraint;
308    return 0;
309}
310
311/**
312 * Make the to-be-signed certificate object a proxy certificate. If the
313 * pathLenConstraint is negative path length constraint is used.
314 *
315 * @param context A hx509 context.
316 * @param tbs object to be signed.
317 * @param pathLenConstraint path length constraint, negative, no
318 * constraint.
319 *
320 * @return An hx509 error code, see hx509_get_error_string().
321 *
322 * @ingroup hx509_ca
323 */
324
325int
326hx509_ca_tbs_set_proxy(hx509_context context,
327		       hx509_ca_tbs tbs,
328		       int pathLenConstraint)
329{
330    tbs->flags.proxy = 1;
331    tbs->pathLenConstraint = pathLenConstraint;
332    return 0;
333}
334
335
336/**
337 * Make the to-be-signed certificate object a windows domain controller certificate.
338 *
339 * @param context A hx509 context.
340 * @param tbs object to be signed.
341 *
342 * @return An hx509 error code, see hx509_get_error_string().
343 *
344 * @ingroup hx509_ca
345 */
346
347int
348hx509_ca_tbs_set_domaincontroller(hx509_context context,
349				  hx509_ca_tbs tbs)
350{
351    tbs->flags.domaincontroller = 1;
352    return 0;
353}
354
355/**
356 * Set the subject public key info (SPKI) in the to-be-signed certificate
357 * object. SPKI is the public key and key related parameters in the
358 * certificate.
359 *
360 * @param context A hx509 context.
361 * @param tbs object to be signed.
362 * @param spki subject public key info to use for the to-be-signed certificate object.
363 *
364 * @return An hx509 error code, see hx509_get_error_string().
365 *
366 * @ingroup hx509_ca
367 */
368
369int
370hx509_ca_tbs_set_spki(hx509_context context,
371		      hx509_ca_tbs tbs,
372		      const SubjectPublicKeyInfo *spki)
373{
374    int ret;
375    free_SubjectPublicKeyInfo(&tbs->spki);
376    ret = copy_SubjectPublicKeyInfo(spki, &tbs->spki);
377    tbs->flags.key = !ret;
378    return ret;
379}
380
381/**
382 * Set the serial number to use for to-be-signed certificate object.
383 *
384 * @param context A hx509 context.
385 * @param tbs object to be signed.
386 * @param serialNumber serial number to use for the to-be-signed
387 * certificate object.
388 *
389 * @return An hx509 error code, see hx509_get_error_string().
390 *
391 * @ingroup hx509_ca
392 */
393
394int
395hx509_ca_tbs_set_serialnumber(hx509_context context,
396			      hx509_ca_tbs tbs,
397			      const heim_integer *serialNumber)
398{
399    int ret;
400    der_free_heim_integer(&tbs->serial);
401    ret = der_copy_heim_integer(serialNumber, &tbs->serial);
402    tbs->flags.serial = !ret;
403    return ret;
404}
405
406/**
407 * An an extended key usage to the to-be-signed certificate object.
408 * Duplicates will detected and not added.
409 *
410 * @param context A hx509 context.
411 * @param tbs object to be signed.
412 * @param oid extended key usage to add.
413 *
414 * @return An hx509 error code, see hx509_get_error_string().
415 *
416 * @ingroup hx509_ca
417 */
418
419int
420hx509_ca_tbs_add_eku(hx509_context context,
421		     hx509_ca_tbs tbs,
422		     const heim_oid *oid)
423{
424    void *ptr;
425    int ret;
426    unsigned i;
427
428    /* search for duplicates */
429    for (i = 0; i < tbs->eku.len; i++) {
430	if (der_heim_oid_cmp(oid, &tbs->eku.val[i]) == 0)
431	    return 0;
432    }
433
434    ptr = realloc(tbs->eku.val, sizeof(tbs->eku.val[0]) * (tbs->eku.len + 1));
435    if (ptr == NULL) {
436	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
437	return ENOMEM;
438    }
439    tbs->eku.val = ptr;
440    ret = der_copy_oid(oid, &tbs->eku.val[tbs->eku.len]);
441    if (ret) {
442	hx509_set_error_string(context, 0, ret, "out of memory");
443	return ret;
444    }
445    tbs->eku.len += 1;
446    return 0;
447}
448
449/**
450 * Add CRL distribution point URI to the to-be-signed certificate
451 * object.
452 *
453 * @param context A hx509 context.
454 * @param tbs object to be signed.
455 * @param uri uri to the CRL.
456 * @param issuername name of the issuer.
457 *
458 * @return An hx509 error code, see hx509_get_error_string().
459 *
460 * @ingroup hx509_ca
461 */
462
463int
464hx509_ca_tbs_add_crl_dp_uri(hx509_context context,
465			    hx509_ca_tbs tbs,
466			    const char *uri,
467			    hx509_name issuername)
468{
469    DistributionPoint dp;
470    int ret;
471
472    memset(&dp, 0, sizeof(dp));
473
474    dp.distributionPoint = ecalloc(1, sizeof(*dp.distributionPoint));
475
476    {
477	DistributionPointName name;
478	GeneralName gn;
479	size_t size;
480
481	name.element = choice_DistributionPointName_fullName;
482	name.u.fullName.len = 1;
483	name.u.fullName.val = &gn;
484
485	gn.element = choice_GeneralName_uniformResourceIdentifier;
486	gn.u.uniformResourceIdentifier.data = rk_UNCONST(uri);
487	gn.u.uniformResourceIdentifier.length = strlen(uri);
488
489	ASN1_MALLOC_ENCODE(DistributionPointName,
490			   dp.distributionPoint->data,
491			   dp.distributionPoint->length,
492			   &name, &size, ret);
493	if (ret) {
494	    hx509_set_error_string(context, 0, ret,
495				   "Failed to encoded DistributionPointName");
496	    goto out;
497	}
498	if (dp.distributionPoint->length != size)
499	    _hx509_abort("internal ASN.1 encoder error");
500    }
501
502    if (issuername) {
503#if 1
504	/**
505	 * issuername not supported
506	 */
507	hx509_set_error_string(context, 0, EINVAL,
508			       "CRLDistributionPoints.name.issuername not yet supported");
509	return EINVAL;
510#else
511	GeneralNames *crlissuer;
512	GeneralName gn;
513	Name n;
514
515	crlissuer = calloc(1, sizeof(*crlissuer));
516	if (crlissuer == NULL) {
517	    return ENOMEM;
518	}
519	memset(&gn, 0, sizeof(gn));
520
521	gn.element = choice_GeneralName_directoryName;
522	ret = hx509_name_to_Name(issuername, &n);
523	if (ret) {
524	    hx509_set_error_string(context, 0, ret, "out of memory");
525	    goto out;
526	}
527
528	gn.u.directoryName.element = n.element;
529	gn.u.directoryName.u.rdnSequence = n.u.rdnSequence;
530
531	ret = add_GeneralNames(&crlissuer, &gn);
532	free_Name(&n);
533	if (ret) {
534	    hx509_set_error_string(context, 0, ret, "out of memory");
535	    goto out;
536	}
537
538	dp.cRLIssuer = &crlissuer;
539#endif
540    }
541
542    ret = add_CRLDistributionPoints(&tbs->crldp, &dp);
543    if (ret) {
544	hx509_set_error_string(context, 0, ret, "out of memory");
545	goto out;
546    }
547
548out:
549    free_DistributionPoint(&dp);
550
551    return ret;
552}
553
554/**
555 * Add Subject Alternative Name otherName to the to-be-signed
556 * certificate object.
557 *
558 * @param context A hx509 context.
559 * @param tbs object to be signed.
560 * @param oid the oid of the OtherName.
561 * @param os data in the other name.
562 *
563 * @return An hx509 error code, see hx509_get_error_string().
564 *
565 * @ingroup hx509_ca
566 */
567
568int
569hx509_ca_tbs_add_san_otherName(hx509_context context,
570			       hx509_ca_tbs tbs,
571			       const heim_oid *oid,
572			       const heim_octet_string *os)
573{
574    GeneralName gn;
575
576    memset(&gn, 0, sizeof(gn));
577    gn.element = choice_GeneralName_otherName;
578    gn.u.otherName.type_id = *oid;
579    gn.u.otherName.value = *os;
580
581    return add_GeneralNames(&tbs->san, &gn);
582}
583
584/**
585 * Add Kerberos Subject Alternative Name to the to-be-signed
586 * certificate object. The principal string is a UTF8 string.
587 *
588 * @param context A hx509 context.
589 * @param tbs object to be signed.
590 * @param principal Kerberos principal to add to the certificate.
591 *
592 * @return An hx509 error code, see hx509_get_error_string().
593 *
594 * @ingroup hx509_ca
595 */
596
597int
598hx509_ca_tbs_add_san_pkinit(hx509_context context,
599			    hx509_ca_tbs tbs,
600			    const char *principal)
601{
602    heim_octet_string os;
603    KRB5PrincipalName p;
604    size_t size;
605    int ret;
606    char *s = NULL;
607
608    memset(&p, 0, sizeof(p));
609
610    /* parse principal */
611    {
612	const char *str;
613	char *q;
614	int n;
615
616	/* count number of component */
617	n = 1;
618	for(str = principal; *str != '\0' && *str != '@'; str++){
619	    if(*str=='\\'){
620		if(str[1] == '\0' || str[1] == '@') {
621		    ret = HX509_PARSING_NAME_FAILED;
622		    hx509_set_error_string(context, 0, ret,
623					   "trailing \\ in principal name");
624		    goto out;
625		}
626		str++;
627	    } else if(*str == '/')
628		n++;
629	}
630	p.principalName.name_string.val =
631	    calloc(n, sizeof(*p.principalName.name_string.val));
632	if (p.principalName.name_string.val == NULL) {
633	    ret = ENOMEM;
634	    hx509_set_error_string(context, 0, ret, "malloc: out of memory");
635	    goto out;
636	}
637	p.principalName.name_string.len = n;
638
639	p.principalName.name_type = KRB5_NT_PRINCIPAL;
640	q = s = strdup(principal);
641	if (q == NULL) {
642	    ret = ENOMEM;
643	    hx509_set_error_string(context, 0, ret, "malloc: out of memory");
644	    goto out;
645	}
646	p.realm = strrchr(q, '@');
647	if (p.realm == NULL) {
648	    ret = HX509_PARSING_NAME_FAILED;
649	    hx509_set_error_string(context, 0, ret, "Missing @ in principal");
650	    goto out;
651	};
652	*p.realm++ = '\0';
653
654	n = 0;
655	while (q) {
656	    p.principalName.name_string.val[n++] = q;
657	    q = strchr(q, '/');
658	    if (q)
659		*q++ = '\0';
660	}
661    }
662
663    ASN1_MALLOC_ENCODE(KRB5PrincipalName, os.data, os.length, &p, &size, ret);
664    if (ret) {
665	hx509_set_error_string(context, 0, ret, "Out of memory");
666	goto out;
667    }
668    if (size != os.length)
669	_hx509_abort("internal ASN.1 encoder error");
670
671    ret = hx509_ca_tbs_add_san_otherName(context,
672					 tbs,
673					 &asn1_oid_id_pkinit_san,
674					 &os);
675    free(os.data);
676out:
677    if (p.principalName.name_string.val)
678	free (p.principalName.name_string.val);
679    if (s)
680	free(s);
681    return ret;
682}
683
684/*
685 *
686 */
687
688static int
689add_utf8_san(hx509_context context,
690	     hx509_ca_tbs tbs,
691	     const heim_oid *oid,
692	     const char *string)
693{
694    const PKIXXmppAddr ustring = (const PKIXXmppAddr)string;
695    heim_octet_string os;
696    size_t size;
697    int ret;
698
699    os.length = 0;
700    os.data = NULL;
701
702    ASN1_MALLOC_ENCODE(PKIXXmppAddr, os.data, os.length, &ustring, &size, ret);
703    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