root/source4/heimdal/lib/hx509/ca.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hx509_ca_tbs_init
  2. hx509_ca_tbs_free
  3. hx509_ca_tbs_set_notBefore
  4. hx509_ca_tbs_set_notAfter
  5. hx509_ca_tbs_set_notAfter_lifetime
  6. hx509_ca_tbs_template_units
  7. hx509_ca_tbs_set_template
  8. hx509_ca_tbs_set_ca
  9. hx509_ca_tbs_set_proxy
  10. hx509_ca_tbs_set_domaincontroller
  11. hx509_ca_tbs_set_spki
  12. hx509_ca_tbs_set_serialnumber
  13. hx509_ca_tbs_add_eku
  14. hx509_ca_tbs_add_crl_dp_uri
  15. hx509_ca_tbs_add_san_otherName
  16. hx509_ca_tbs_add_san_pkinit
  17. add_utf8_san
  18. hx509_ca_tbs_add_san_ms_upn
  19. hx509_ca_tbs_add_san_jid
  20. hx509_ca_tbs_add_san_hostname
  21. hx509_ca_tbs_add_san_rfc822name
  22. hx509_ca_tbs_set_subject
  23. hx509_ca_tbs_subject_expand
  24. add_extension
  25. build_proxy_prefix
  26. ca_sign
  27. get_AuthorityKeyIdentifier
  28. hx509_ca_sign
  29. hx509_ca_sign_self

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

/* [<][>][^][v][top][bottom][index][help] */