xref: /freebsd/crypto/heimdal/lib/hx509/ca.c (revision aa0a1e58)
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>
36 RCSID("$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 
44 struct 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 
77 int
78 hx509_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 
104 void
105 hx509_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 
136 int
137 hx509_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 
157 int
158 hx509_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 
178 int
179 hx509_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 
186 static 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 
206 const struct units *
207 hx509_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 
226 int
227 hx509_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 
304 int
305 hx509_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 
328 int
329 hx509_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 
350 int
351 hx509_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 
372 int
373 hx509_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 
397 int
398 hx509_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 
422 int
423 hx509_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 
466 int
467 hx509_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 
550 out:
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 
570 int
571 hx509_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 
599 int
600 hx509_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);
678 out:
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 
690 static int
691 add_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);
717 out:
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 
734 int
735 hx509_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 
755 int
756 hx509_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 
780 int
781 hx509_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 
807 int
808 hx509_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 
833 int
834 hx509_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 
857 int
858 hx509_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 
865 static int
866 add_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     }
902 out:
903     free_Extension(&ext);
904     return ret;
905 }
906 
907 static int
908 build_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 
936 static int
937 ca_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 
1343 out:
1344     free_Certificate(&c);
1345     return ret;
1346 }
1347 
1348 static int
1349 get_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     }
1431 out:
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 
1462 int
1463 hx509_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 
1487 out:
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 
1506 int
1507 hx509_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