xref: /freebsd/crypto/heimdal/lib/hx509/ca.c (revision 5ca8e32633c4ffbbcd6762e5888b6a4ba0708c6c)
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 
43 struct 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 
80 int
81 hx509_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 
98 void
99 hx509_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 
131 int
132 hx509_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 
152 int
153 hx509_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 
173 int
174 hx509_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 
181 static 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 
201 const struct units *
202 hx509_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 
221 int
222 hx509_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 
299 int
300 hx509_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 
323 int
324 hx509_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 
345 int
346 hx509_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 
367 int
368 hx509_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 
392 int
393 hx509_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 
417 int
418 hx509_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 
461 int
462 hx509_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 
546 out:
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 
566 int
567 hx509_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 
595 int
596 hx509_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);
674 out:
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 
686 static int
687 add_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);
713 out:
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 
730 int
731 hx509_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 
751 int
752 hx509_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 
776 int
777 hx509_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 
804 int
805 hx509_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 
831 int
832 hx509_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 
859 int
860 hx509_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 
899 int
900 hx509_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 
911 static int
912 add_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     }
948 out:
949     free_Extension(&ext);
950     return ret;
951 }
952 
953 static int
954 build_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 
982 static int
983 ca_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 
1419 out:
1420     free_Certificate(&c);
1421     return ret;
1422 }
1423 
1424 static int
1425 get_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     }
1506 out:
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 
1537 int
1538 hx509_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 
1562 out:
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 
1581 int
1582 hx509_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