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