LCOV - code coverage report
Current view: top level - source4/heimdal/lib/hx509 - ca.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 0 589 0.0 %
Date: 2021-09-23 10:06:22 Functions: 0 31 0.0 %

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

Generated by: LCOV version 1.13