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