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