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