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