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