LCOV - code coverage report
Current view: top level - third_party/heimdal/lib/hx509 - cert.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 650 1811 35.9 %
Date: 2024-04-21 15:09:00 Functions: 68 115 59.1 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2004 - 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 "crypto-headers.h"
      36             : #include <rtbl.h>
      37             : 
      38             : /**
      39             :  * @page page_cert The basic certificate
      40             :  *
      41             :  * The basic hx509 cerificate object in hx509 is hx509_cert. The
      42             :  * hx509_cert object is representing one X509/PKIX certificate and
      43             :  * associated attributes; like private key, friendly name, etc.
      44             :  *
      45             :  * A hx509_cert object is usully found via the keyset interfaces (@ref
      46             :  * page_keyset), but its also possible to create a certificate
      47             :  * directly from a parsed object with hx509_cert_init() and
      48             :  * hx509_cert_init_data().
      49             :  *
      50             :  * See the library functions here: @ref hx509_cert
      51             :  */
      52             : 
      53             : struct hx509_verify_ctx_data {
      54             :     hx509_certs trust_anchors;
      55             :     int flags;
      56             : #define HX509_VERIFY_CTX_F_TIME_SET                     1
      57             : #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE      2
      58             : #define HX509_VERIFY_CTX_F_REQUIRE_RFC3280              4
      59             : #define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS          8
      60             : #define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS           16
      61             : #define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK         32
      62             :     time_t time_now;
      63             :     unsigned int max_depth;
      64             : #define HX509_VERIFY_MAX_DEPTH 30
      65             :     hx509_revoke_ctx revoke_ctx;
      66             : };
      67             : 
      68             : #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
      69             : #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
      70             : #define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
      71             : 
      72             : struct _hx509_cert_attrs {
      73             :     size_t len;
      74             :     hx509_cert_attribute *val;
      75             : };
      76             : 
      77             : struct hx509_cert_data {
      78             :     unsigned int ref;
      79             :     char *friendlyname;
      80             :     Certificate *data;
      81             :     hx509_private_key private_key;
      82             :     struct _hx509_cert_attrs attrs;
      83             :     hx509_name basename;
      84             :     _hx509_cert_release_func release;
      85             :     void *ctx;
      86             : };
      87             : 
      88             : typedef struct hx509_name_constraints {
      89             :     NameConstraints *val;
      90             :     size_t len;
      91             : } hx509_name_constraints;
      92             : 
      93             : #define GeneralSubtrees_SET(g,var) \
      94             :         (g)->len = (var)->len, (g)->val = (var)->val;
      95             : 
      96             : static void
      97       33851 : init_context_once(void *ignored)
      98             : {
      99             : 
     100       33851 :     ENGINE_add_conf_module();
     101       33851 :     OpenSSL_add_all_algorithms();
     102       33851 : }
     103             : 
     104             : /**
     105             :  * Return a cookie identifying this instance of a library.
     106             :  *
     107             :  * Inputs:
     108             :  *
     109             :  * @context     A krb5_context
     110             :  * @module      Our library name or a library we depend on
     111             :  *
     112             :  * Outputs:     The instance cookie
     113             :  *
     114             :  * @ingroup     krb5_support
     115             :  */
     116             : 
     117             : HX509_LIB_FUNCTION uintptr_t HX509_LIB_CALL
     118           0 : hx509_get_instance(const char *libname)
     119             : {
     120           0 :     static const char *instance = "libhx509";
     121             : 
     122           0 :     if (strcmp(libname, "hx509") == 0)
     123           0 :         return (uintptr_t)instance;
     124             : 
     125           0 :     return 0;
     126             : }
     127             : 
     128             : #ifndef PATH_SEP
     129             : # define PATH_SEP ":"
     130             : #endif
     131             : static const char *hx509_config_file =
     132             : "~/.hx509/config" PATH_SEP
     133             : SYSCONFDIR "/hx509.conf" PATH_SEP
     134             : #ifdef _WIN32
     135             : "%{COMMON_APPDATA}/Heimdal/hx509.conf" PATH_SEP
     136             : "%{WINDOWS}/hx509.ini"
     137             : #else /* _WIN32 */
     138             : "/etc/hx509.conf"
     139             : #endif /* _WIN32 */
     140             : ;
     141             : 
     142             : /**
     143             :  * Creates a hx509 context that most functions in the library
     144             :  * uses. The context is only allowed to be used by one thread at each
     145             :  * moment. Free the context with hx509_context_free().
     146             :  *
     147             :  * @param context Returns a pointer to new hx509 context.
     148             :  *
     149             :  * @return Returns an hx509 error code.
     150             :  *
     151             :  * @ingroup hx509
     152             :  */
     153             : 
     154             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     155      792004 : hx509_context_init(hx509_context *contextp)
     156             : {
     157       19510 :     static heim_base_once_t init_context = HEIM_BASE_ONCE_INIT;
     158       19510 :     heim_error_code ret;
     159       19510 :     hx509_context context;
     160       19510 :     const char *anchors;
     161      792004 :     char **files = NULL;
     162             : 
     163      792004 :     *contextp = NULL;
     164      792004 :     context = calloc(1, sizeof(*context));
     165      792004 :     if (context == NULL)
     166           0 :         return ENOMEM;
     167             : 
     168      792004 :     heim_base_once_f(&init_context, NULL, init_context_once);
     169             : 
     170      792004 :     if ((context->hcontext = heim_context_init()) == NULL) {
     171           0 :         free(context);
     172           0 :         return ENOMEM;
     173             :     }
     174             : 
     175      792004 :     if ((ret = heim_get_default_config_files(hx509_config_file,
     176             :                                              "HX509_CONFIG",
     177             :                                              &files))) {
     178           0 :         heim_context_free(&context->hcontext);
     179           0 :         free(context);
     180           0 :         return ret;
     181             :     }
     182             : 
     183             :     /* If there's no hx509 config, we continue, as we never needed it before */
     184      792004 :     if (files)
     185      792004 :         (void) heim_set_config_files(context->hcontext, files, &context->cf);
     186      792004 :     heim_free_config_files(files);
     187             : 
     188      792004 :     _hx509_ks_null_register(context);
     189      792004 :     _hx509_ks_mem_register(context);
     190      792004 :     _hx509_ks_file_register(context);
     191      792004 :     _hx509_ks_pkcs12_register(context);
     192      792004 :     _hx509_ks_pkcs11_register(context);
     193      792004 :     _hx509_ks_dir_register(context);
     194      792004 :     _hx509_ks_keychain_register(context);
     195             : 
     196      811514 :     context->ocsp_time_diff =
     197      792004 :         heim_config_get_time_default(context->hcontext, context->cf,
     198             :                                      HX509_DEFAULT_OCSP_TIME_DIFF,
     199             :                                      "libdefaults", "ocsp_time_dif", NULL);
     200             : 
     201      792004 :     initialize_hx_error_table_r(&context->et_list);
     202      792004 :     initialize_asn1_error_table_r(&context->et_list);
     203             : 
     204             : #ifdef HX509_DEFAULT_ANCHORS
     205             :     anchors = heim_config_get_string_default(context->hcontext, context->cf,
     206             :                                              HX509_DEFAULT_ANCHORS,
     207             :                                              "libdefaults", "anchors", NULL);
     208             : #else
     209      792004 :     anchors = heim_config_get_string(context->hcontext, context->cf,
     210             :                                      "libdefaults", "anchors", NULL);
     211             : #endif
     212      792004 :     if (anchors)
     213           0 :         (void)hx509_certs_init(context, anchors, 0, NULL,
     214             :                                &context->default_trust_anchors);
     215             : 
     216      792004 :     *contextp = context;
     217      792004 :     return 0;
     218             : }
     219             : 
     220             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     221           0 : hx509_set_log_dest(hx509_context context, heim_log_facility *fac)
     222             : {
     223           0 :     return heim_set_log_dest(context->hcontext, fac);
     224             : }
     225             : 
     226             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     227           0 : hx509_set_debug_dest(hx509_context context, heim_log_facility *fac)
     228             : {
     229           0 :     return heim_set_debug_dest(context->hcontext, fac);
     230             : }
     231             : 
     232             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     233           0 : hx509_set_warn_dest(hx509_context context, heim_log_facility *fac)
     234             : {
     235           0 :     return heim_set_warn_dest(context->hcontext, fac);
     236             : }
     237             : 
     238             : /**
     239             :  * Selects if the hx509_revoke_verify() function is going to require
     240             :  * the existence of a revocation method (OCSP, CRL) or not. Note that
     241             :  * hx509_verify_path(), hx509_cms_verify_signed(), and other functions
     242             :  * call hx509_revoke_verify().
     243             :  *
     244             :  * @param context hx509 context to change the flag for.
     245             :  * @param flag zero, revocation method required, non zero missing
     246             :  * revocation method ok
     247             :  *
     248             :  * @ingroup hx509_verify
     249             :  */
     250             : 
     251             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     252         124 : hx509_context_set_missing_revoke(hx509_context context, int flag)
     253             : {
     254         124 :     if (flag)
     255         124 :         context->flags |= HX509_CTX_VERIFY_MISSING_OK;
     256             :     else
     257           0 :         context->flags &= ~HX509_CTX_VERIFY_MISSING_OK;
     258         124 : }
     259             : 
     260             : /**
     261             :  * Free the context allocated by hx509_context_init().
     262             :  *
     263             :  * @param context context to be freed.
     264             :  *
     265             :  * @ingroup hx509
     266             :  */
     267             : 
     268             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     269      753173 : hx509_context_free(hx509_context *context)
     270             : {
     271      753173 :     if (!*context)
     272           0 :         return;
     273             : 
     274      753173 :     hx509_clear_error_string(*context);
     275      753173 :     if ((*context)->ks_ops) {
     276      753173 :         free((*context)->ks_ops);
     277      753173 :         (*context)->ks_ops = NULL;
     278             :     }
     279      753173 :     (*context)->ks_num_ops = 0;
     280      753173 :     free_error_table ((*context)->et_list);
     281      753173 :     if ((*context)->querystat)
     282           0 :         free((*context)->querystat);
     283      753173 :     hx509_certs_free(&(*context)->default_trust_anchors);
     284      753173 :     heim_config_file_free((*context)->hcontext, (*context)->cf);
     285      753173 :     heim_context_free(&(*context)->hcontext);
     286      753173 :     memset(*context, 0, sizeof(**context));
     287      753173 :     free(*context);
     288      753173 :     *context = NULL;
     289             : }
     290             : 
     291             : /*
     292             :  *
     293             :  */
     294             : 
     295             : HX509_LIB_FUNCTION Certificate * HX509_LIB_CALL
     296        2222 : _hx509_get_cert(hx509_cert cert)
     297             : {
     298        2222 :     return cert->data;
     299             : }
     300             : 
     301             : /*
     302             :  *
     303             :  */
     304             : 
     305             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     306         350 : _hx509_cert_get_version(const Certificate *t)
     307             : {
     308         350 :     return t->tbsCertificate.version ? *t->tbsCertificate.version + 1 : 1;
     309             : }
     310             : 
     311             : static hx509_cert
     312         323 : cert_init(hx509_context context, heim_error_t *error)
     313             : {
     314          16 :     hx509_cert cert;
     315             : 
     316         323 :     cert = malloc(sizeof(*cert));
     317         323 :     if (cert == NULL) {
     318           0 :         if (error)
     319           0 :             *error = heim_error_create_enomem();
     320           0 :         return NULL;
     321             :     }
     322         323 :     cert->ref = 1;
     323         323 :     cert->friendlyname = NULL;
     324         323 :     cert->attrs.len = 0;
     325         323 :     cert->attrs.val = NULL;
     326         323 :     cert->private_key = NULL;
     327         323 :     cert->basename = NULL;
     328         323 :     cert->release = NULL;
     329         323 :     cert->ctx = NULL;
     330         323 :     cert->data= NULL;
     331         323 :     return cert;
     332             : }
     333             : 
     334             : /**
     335             :  * Allocate and init an hx509 certificate object from the decoded
     336             :  * certificate `c´.
     337             :  *
     338             :  * @param context A hx509 context.
     339             :  * @param c
     340             :  * @param error
     341             :  *
     342             :  * @return Returns an hx509 certificate
     343             :  *
     344             :  * @ingroup hx509_cert
     345             :  */
     346             : 
     347             : HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
     348         323 : hx509_cert_init(hx509_context context, const Certificate *c, heim_error_t *error)
     349             : {
     350          16 :     hx509_cert cert;
     351          16 :     int ret;
     352             : 
     353         323 :     if ((cert = cert_init(context, error)) == NULL)
     354           0 :         return NULL;
     355             : 
     356         323 :     cert->data = calloc(1, sizeof(*(cert->data)));
     357         323 :     if (cert->data == NULL) {
     358           0 :         free(cert);
     359           0 :         if (error)
     360           0 :             *error = heim_error_create_enomem();
     361           0 :         return NULL;
     362             :     }
     363         323 :     ret = copy_Certificate(c, cert->data);
     364         323 :     if (ret) {
     365           0 :         free(cert->data);
     366           0 :         free(cert);
     367           0 :         cert = NULL;
     368             :     }
     369         307 :     return cert;
     370             : }
     371             : 
     372             : /**
     373             :  * Copy a certificate object, but drop any private key assignment.
     374             :  *
     375             :  * @param context A hx509 context.
     376             :  * @param src Certificate object
     377             :  * @param error
     378             :  *
     379             :  * @return Returns an hx509 certificate
     380             :  *
     381             :  * @ingroup hx509_cert
     382             :  */
     383             : 
     384             : HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
     385           0 : hx509_cert_copy_no_private_key(hx509_context context,
     386             :                                hx509_cert src,
     387             :                                heim_error_t *error)
     388             : {
     389           0 :     return hx509_cert_init(context, src->data, error);
     390             : }
     391             : 
     392             : /**
     393             :  * Allocate and init an hx509 certificate object containing only a private key
     394             :  * (but no Certificate).
     395             :  *
     396             :  * @param context A hx509 context.
     397             :  * @param key
     398             :  * @param error
     399             :  *
     400             :  * @return Returns an hx509 certificate
     401             :  *
     402             :  * @ingroup hx509_cert
     403             :  */
     404             : 
     405             : HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
     406           0 : hx509_cert_init_private_key(hx509_context context,
     407             :                             hx509_private_key key,
     408             :                             heim_error_t *error)
     409             : {
     410           0 :     hx509_cert cert;
     411             : 
     412           0 :     if ((cert = cert_init(context, error)))
     413           0 :         (void) _hx509_cert_assign_key(cert, key);
     414           0 :     return cert;
     415             : }
     416             : 
     417             : /**
     418             :  * Just like hx509_cert_init(), but instead of a decode certificate
     419             :  * takes an pointer and length to a memory region that contains a
     420             :  * DER/BER encoded certificate.
     421             :  *
     422             :  * If the memory region doesn't contain just the certificate and
     423             :  * nothing more the function will fail with
     424             :  * HX509_EXTRA_DATA_AFTER_STRUCTURE.
     425             :  *
     426             :  * @param context A hx509 context.
     427             :  * @param ptr pointer to memory region containing encoded certificate.
     428             :  * @param len length of memory region.
     429             :  * @param error possibly returns an error
     430             :  *
     431             :  * @return An hx509 certificate
     432             :  *
     433             :  * @ingroup hx509_cert
     434             :  */
     435             : 
     436             : HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
     437         323 : hx509_cert_init_data(hx509_context context,
     438             :                      const void *ptr,
     439             :                      size_t len,
     440             :                      heim_error_t *error)
     441             : {
     442          16 :     hx509_cert cert;
     443          16 :     Certificate t;
     444          16 :     size_t size;
     445          16 :     int ret;
     446             : 
     447         323 :     ret = decode_Certificate(ptr, len, &t, &size);
     448         323 :     if (ret) {
     449           0 :         if (error)
     450           0 :             *error = heim_error_create(ret, "Failed to decode certificate");
     451           0 :         errno = ret;
     452           0 :         return NULL;
     453             :     }
     454         323 :     if (size != len) {
     455           0 :         free_Certificate(&t);
     456           0 :         if (error)
     457           0 :             *error = heim_error_create(HX509_EXTRA_DATA_AFTER_STRUCTURE,
     458             :                                        "Extra data after certificate");
     459           0 :         errno = HX509_EXTRA_DATA_AFTER_STRUCTURE;
     460           0 :         return NULL;
     461             :     }
     462             : 
     463         323 :     cert = hx509_cert_init(context, &t, error);
     464         323 :     free_Certificate(&t);
     465         323 :     return cert;
     466             : }
     467             : 
     468             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     469           0 : _hx509_cert_set_release(hx509_cert cert,
     470             :                         _hx509_cert_release_func release,
     471             :                         void *ctx)
     472             : {
     473           0 :     cert->release = release;
     474           0 :     cert->ctx = ctx;
     475           0 : }
     476             : 
     477             : 
     478             : /* Doesn't make a copy of `private_key'. */
     479             : 
     480             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     481          74 : _hx509_cert_assign_key(hx509_cert cert, hx509_private_key private_key)
     482             : {
     483          74 :     if (cert->private_key)
     484           0 :         hx509_private_key_free(&cert->private_key);
     485          74 :     cert->private_key = _hx509_private_key_ref(private_key);
     486          74 :     return 0;
     487             : }
     488             : 
     489             : /**
     490             :  * Free reference to the hx509 certificate object, if the refcounter
     491             :  * reaches 0, the object if freed. Its allowed to pass in NULL.
     492             :  *
     493             :  * @param cert the cert to free.
     494             :  *
     495             :  * @ingroup hx509_cert
     496             :  */
     497             : 
     498             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     499        4849 : hx509_cert_free(hx509_cert cert)
     500             : {
     501         104 :     size_t i;
     502             : 
     503        4849 :     if (cert == NULL)
     504        1905 :         return;
     505             : 
     506        2904 :     if (cert->ref <= 0)
     507           0 :         _hx509_abort("cert refcount <= 0 on free");
     508        2904 :     if (--cert->ref > 0)
     509        2625 :         return;
     510             : 
     511         215 :     if (cert->release)
     512           0 :         (cert->release)(cert, cert->ctx);
     513             : 
     514         215 :     if (cert->private_key)
     515          20 :         hx509_private_key_free(&cert->private_key);
     516             : 
     517         215 :     if (cert->data)
     518         215 :         free_Certificate(cert->data);
     519         215 :     free(cert->data);
     520             : 
     521         215 :     for (i = 0; i < cert->attrs.len; i++) {
     522           0 :         der_free_octet_string(&cert->attrs.val[i]->data);
     523           0 :         der_free_oid(&cert->attrs.val[i]->oid);
     524           0 :         free(cert->attrs.val[i]);
     525             :     }
     526         215 :     free(cert->attrs.val);
     527         215 :     free(cert->friendlyname);
     528         215 :     if (cert->basename)
     529           0 :         hx509_name_free(&cert->basename);
     530         215 :     memset(cert, 0, sizeof(*cert));
     531         215 :     free(cert);
     532             : }
     533             : 
     534             : /**
     535             :  * Add a reference to a hx509 certificate object.
     536             :  *
     537             :  * @param cert a pointer to an hx509 certificate object.
     538             :  *
     539             :  * @return the same object as is passed in.
     540             :  *
     541             :  * @ingroup hx509_cert
     542             :  */
     543             : 
     544             : HX509_LIB_FUNCTION hx509_cert HX509_LIB_CALL
     545        2793 : hx509_cert_ref(hx509_cert cert)
     546             : {
     547        2793 :     if (cert == NULL)
     548         104 :         return NULL;
     549        2689 :     if (cert->ref <= 0)
     550           0 :         _hx509_abort("cert refcount <= 0");
     551        2689 :     cert->ref++;
     552        2689 :     if (cert->ref == 0)
     553           0 :         _hx509_abort("cert refcount == 0");
     554        2625 :     return cert;
     555             : }
     556             : 
     557             : /**
     558             :  * Allocate an verification context that is used to control the
     559             :  * verification process.
     560             :  *
     561             :  * @param context A hx509 context.
     562             :  * @param ctx returns a pointer to a hx509_verify_ctx object.
     563             :  *
     564             :  * @return An hx509 error code, see hx509_get_error_string().
     565             :  *
     566             :  * @ingroup hx509_verify
     567             :  */
     568             : 
     569             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     570         239 : hx509_verify_init_ctx(hx509_context context, hx509_verify_ctx *ctx)
     571             : {
     572           8 :     hx509_verify_ctx c;
     573             : 
     574         239 :     c = calloc(1, sizeof(*c));
     575         239 :     if (c == NULL)
     576           0 :         return ENOMEM;
     577             : 
     578         239 :     c->max_depth = HX509_VERIFY_MAX_DEPTH;
     579             : 
     580         239 :     *ctx = c;
     581             : 
     582         239 :     return 0;
     583             : }
     584             : 
     585             : /**
     586             :  * Free an hx509 verification context.
     587             :  *
     588             :  * @param ctx the context to be freed.
     589             :  *
     590             :  * @ingroup hx509_verify
     591             :  */
     592             : 
     593             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     594         224 : hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
     595             : {
     596         224 :     if (ctx) {
     597         185 :         hx509_certs_free(&ctx->trust_anchors);
     598         185 :         hx509_revoke_free(&ctx->revoke_ctx);
     599         185 :         memset(ctx, 0, sizeof(*ctx));
     600             :     }
     601         224 :     free(ctx);
     602         224 : }
     603             : 
     604             : /**
     605             :  * Set the trust anchors in the verification context, makes an
     606             :  * reference to the keyset, so the consumer can free the keyset
     607             :  * independent of the destruction of the verification context (ctx).
     608             :  * If there already is a keyset attached, it's released.
     609             :  *
     610             :  * @param ctx a verification context
     611             :  * @param set a keyset containing the trust anchors.
     612             :  *
     613             :  * @ingroup hx509_verify
     614             :  */
     615             : 
     616             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     617         239 : hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
     618             : {
     619         239 :     if (ctx->trust_anchors)
     620           0 :         hx509_certs_free(&ctx->trust_anchors);
     621         239 :     ctx->trust_anchors = hx509_certs_ref(set);
     622         239 : }
     623             : 
     624             : /**
     625             :  * Attach an revocation context to the verfication context, , makes an
     626             :  * reference to the revoke context, so the consumer can free the
     627             :  * revoke context independent of the destruction of the verification
     628             :  * context. If there is no revoke context, the verification process is
     629             :  * NOT going to check any verification status.
     630             :  *
     631             :  * @param ctx a verification context.
     632             :  * @param revoke_ctx a revoke context.
     633             :  *
     634             :  * @ingroup hx509_verify
     635             :  */
     636             : 
     637             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     638         239 : hx509_verify_attach_revoke(hx509_verify_ctx ctx, hx509_revoke_ctx revoke_ctx)
     639             : {
     640         239 :     if (ctx->revoke_ctx)
     641           0 :         hx509_revoke_free(&ctx->revoke_ctx);
     642         239 :     ctx->revoke_ctx = _hx509_revoke_ref(revoke_ctx);
     643         239 : }
     644             : 
     645             : /**
     646             :  * Set the clock time the the verification process is going to
     647             :  * use. Used to check certificate in the past and future time. If not
     648             :  * set the current time will be used.
     649             :  *
     650             :  * @param ctx a verification context.
     651             :  * @param t the time the verifiation is using.
     652             :  *
     653             :  *
     654             :  * @ingroup hx509_verify
     655             :  */
     656             : 
     657             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     658          61 : hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
     659             : {
     660          61 :     ctx->flags |= HX509_VERIFY_CTX_F_TIME_SET;
     661          61 :     ctx->time_now = t;
     662          61 : }
     663             : 
     664             : HX509_LIB_FUNCTION time_t HX509_LIB_CALL
     665          74 : _hx509_verify_get_time(hx509_verify_ctx ctx)
     666             : {
     667          74 :     return ctx->time_now;
     668             : }
     669             : 
     670             : /**
     671             :  * Set the maximum depth of the certificate chain that the path
     672             :  * builder is going to try.
     673             :  *
     674             :  * @param ctx a verification context
     675             :  * @param max_depth maxium depth of the certificate chain, include
     676             :  * trust anchor.
     677             :  *
     678             :  * @ingroup hx509_verify
     679             :  */
     680             : 
     681             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     682           0 : hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
     683             : {
     684           0 :     ctx->max_depth = max_depth;
     685           0 : }
     686             : 
     687             : /**
     688             :  * Allow or deny the use of proxy certificates
     689             :  *
     690             :  * @param ctx a verification context
     691             :  * @param boolean if non zero, allow proxy certificates.
     692             :  *
     693             :  * @ingroup hx509_verify
     694             :  */
     695             : 
     696             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     697           0 : hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
     698             : {
     699           0 :     if (boolean)
     700           0 :         ctx->flags |= HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
     701             :     else
     702           0 :         ctx->flags &= ~HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE;
     703           0 : }
     704             : 
     705             : /**
     706             :  * Select strict RFC3280 verification of certificiates. This means
     707             :  * checking key usage on CA certificates, this will make version 1
     708             :  * certificiates unuseable.
     709             :  *
     710             :  * @param ctx a verification context
     711             :  * @param boolean if non zero, use strict verification.
     712             :  *
     713             :  * @ingroup hx509_verify
     714             :  */
     715             : 
     716             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     717           0 : hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
     718             : {
     719           0 :     if (boolean)
     720           0 :         ctx->flags |= HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
     721             :     else
     722           0 :         ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
     723           0 : }
     724             : 
     725             : /**
     726             :  * Allow using the operating system builtin trust anchors if no other
     727             :  * trust anchors are configured.
     728             :  *
     729             :  * @param ctx a verification context
     730             :  * @param boolean if non zero, useing the operating systems builtin
     731             :  * trust anchors.
     732             :  *
     733             :  *
     734             :  * @return An hx509 error code, see hx509_get_error_string().
     735             :  *
     736             :  * @ingroup hx509_cert
     737             :  */
     738             : 
     739             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     740           0 : hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
     741             : {
     742           0 :     if (boolean)
     743           0 :         ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
     744             :     else
     745           0 :         ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
     746           0 : }
     747             : 
     748             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     749           0 : hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
     750             :                                                     int boolean)
     751             : {
     752           0 :     if (boolean)
     753           0 :         ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
     754             :     else
     755           0 :         ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
     756           0 : }
     757             : 
     758             : static const Extension *
     759        1214 : find_extension(const Certificate *cert, const heim_oid *oid, size_t *idx)
     760             : {
     761        1214 :     const TBSCertificate *c = &cert->tbsCertificate;
     762             : 
     763        1214 :     if (c->version == NULL || *c->version < 2 || c->extensions == NULL)
     764           0 :         return NULL;
     765             : 
     766        6690 :     for (;*idx < c->extensions->len; (*idx)++) {
     767        6281 :         if (der_heim_oid_cmp(&c->extensions->val[*idx].extnID, oid) == 0)
     768         805 :             return &c->extensions->val[(*idx)++];
     769             :     }
     770         409 :     return NULL;
     771             : }
     772             : 
     773             : static int
     774          74 : find_extension_auth_key_id(const Certificate *subject,
     775             :                            AuthorityKeyIdentifier *ai)
     776             : {
     777           0 :     const Extension *e;
     778           0 :     size_t size;
     779          74 :     size_t i = 0;
     780             : 
     781          74 :     memset(ai, 0, sizeof(*ai));
     782             : 
     783          74 :     e = find_extension(subject, &asn1_oid_id_x509_ce_authorityKeyIdentifier, &i);
     784          74 :     if (e == NULL)
     785          46 :         return HX509_EXTENSION_NOT_FOUND;
     786             : 
     787          28 :     return decode_AuthorityKeyIdentifier(e->extnValue.data,
     788          28 :                                          e->extnValue.length,
     789             :                                          ai, &size);
     790             : }
     791             : 
     792             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     793         234 : _hx509_find_extension_subject_key_id(const Certificate *issuer,
     794             :                                      SubjectKeyIdentifier *si)
     795             : {
     796           0 :     const Extension *e;
     797           0 :     size_t size;
     798         234 :     size_t i = 0;
     799             : 
     800         234 :     memset(si, 0, sizeof(*si));
     801             : 
     802         234 :     e = find_extension(issuer, &asn1_oid_id_x509_ce_subjectKeyIdentifier, &i);
     803         234 :     if (e == NULL)
     804           0 :         return HX509_EXTENSION_NOT_FOUND;
     805             : 
     806         234 :     return decode_SubjectKeyIdentifier(e->extnValue.data,
     807         234 :                                        e->extnValue.length,
     808             :                                        si, &size);
     809             : }
     810             : 
     811             : static int
     812         148 : find_extension_name_constraints(const Certificate *subject,
     813             :                                 NameConstraints *nc)
     814             : {
     815           0 :     const Extension *e;
     816           0 :     size_t size;
     817         148 :     size_t i = 0;
     818             : 
     819         148 :     memset(nc, 0, sizeof(*nc));
     820             : 
     821         148 :     e = find_extension(subject, &asn1_oid_id_x509_ce_nameConstraints, &i);
     822         148 :     if (e == NULL)
     823         148 :         return HX509_EXTENSION_NOT_FOUND;
     824             : 
     825           0 :     return decode_NameConstraints(e->extnValue.data,
     826           0 :                                   e->extnValue.length,
     827             :                                   nc, &size);
     828             : }
     829             : 
     830             : static int
     831         188 : find_extension_subject_alt_name(const Certificate *cert, size_t *i,
     832             :                                 GeneralNames *sa)
     833             : {
     834           0 :     const Extension *e;
     835           0 :     size_t size;
     836             : 
     837         188 :     memset(sa, 0, sizeof(*sa));
     838             : 
     839         188 :     e = find_extension(cert, &asn1_oid_id_x509_ce_subjectAltName, i);
     840         188 :     if (e == NULL)
     841          94 :         return HX509_EXTENSION_NOT_FOUND;
     842             : 
     843          94 :     return decode_GeneralNames(e->extnValue.data,
     844          94 :                                e->extnValue.length,
     845             :                                sa, &size);
     846             : }
     847             : 
     848             : static int
     849          99 : find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
     850             : {
     851           8 :     const Extension *e;
     852           8 :     size_t size;
     853          99 :     size_t i = 0;
     854             : 
     855          99 :     memset(eku, 0, sizeof(*eku));
     856             : 
     857          99 :     e = find_extension(cert, &asn1_oid_id_x509_ce_extKeyUsage, &i);
     858          99 :     if (e == NULL)
     859           0 :         return HX509_EXTENSION_NOT_FOUND;
     860             : 
     861          99 :     return decode_ExtKeyUsage(e->extnValue.data,
     862          99 :                               e->extnValue.length,
     863             :                               eku, &size);
     864             : }
     865             : 
     866             : static int
     867          47 : add_to_list(hx509_octet_string_list *list, const heim_octet_string *entry)
     868             : {
     869           0 :     void *p;
     870           0 :     int ret;
     871             : 
     872          47 :     p = realloc(list->val, (list->len + 1) * sizeof(list->val[0]));
     873          47 :     if (p == NULL)
     874           0 :         return ENOMEM;
     875          47 :     list->val = p;
     876          47 :     ret = der_copy_octet_string(entry, &list->val[list->len]);
     877          47 :     if (ret)
     878           0 :         return ret;
     879          47 :     list->len++;
     880          47 :     return 0;
     881             : }
     882             : 
     883             : /**
     884             :  * Free a list of octet strings returned by another hx509 library
     885             :  * function.
     886             :  *
     887             :  * @param list list to be freed.
     888             :  *
     889             :  * @ingroup hx509_misc
     890             :  */
     891             : 
     892             : HX509_LIB_FUNCTION void HX509_LIB_CALL
     893          94 : hx509_free_octet_string_list(hx509_octet_string_list *list)
     894             : {
     895           0 :     size_t i;
     896             : 
     897          94 :     if (list->val) {
     898          94 :         for (i = 0; i < list->len; i++)
     899          47 :             der_free_octet_string(&list->val[i]);
     900          47 :         free(list->val);
     901             :     }
     902          94 :     list->val = NULL;
     903          94 :     list->len = 0;
     904          94 : }
     905             : 
     906             : /**
     907             :  * Return a list of subjectAltNames specified by oid in the
     908             :  * certificate. On error the
     909             :  *
     910             :  * The returned list of octet string should be freed with
     911             :  * hx509_free_octet_string_list().
     912             :  *
     913             :  * @param context A hx509 context.
     914             :  * @param cert a hx509 certificate object.
     915             :  * @param oid an oid to for SubjectAltName.
     916             :  * @param list list of matching SubjectAltName.
     917             :  *
     918             :  * @return An hx509 error code, see hx509_get_error_string().
     919             :  *
     920             :  * @ingroup hx509_cert
     921             :  */
     922             : 
     923             : HX509_LIB_FUNCTION int HX509_LIB_CALL
     924          94 : hx509_cert_find_subjectAltName_otherName(hx509_context context,
     925             :                                          hx509_cert cert,
     926             :                                          const heim_oid *oid,
     927             :                                          hx509_octet_string_list *list)
     928             : {
     929           0 :     GeneralNames sa;
     930           0 :     int ret;
     931           0 :     size_t i, j;
     932             : 
     933          94 :     list->val = NULL;
     934          94 :     list->len = 0;
     935             : 
     936          94 :     i = 0;
     937           0 :     while (1) {
     938         188 :         ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
     939         188 :         i++;
     940         188 :         if (ret == HX509_EXTENSION_NOT_FOUND) {
     941          94 :             return 0;
     942          94 :         } else if (ret != 0) {
     943           0 :             hx509_set_error_string(context, 0, ret, "Error searching for SAN");
     944           0 :             hx509_free_octet_string_list(list);
     945           0 :             return ret;
     946             :         }
     947             : 
     948         218 :         for (j = 0; j < sa.len; j++) {
     949         218 :             if (sa.val[j].element == choice_GeneralName_otherName &&
     950          94 :                 der_heim_oid_cmp(&sa.val[j].u.otherName.type_id, oid) == 0)
     951             :             {
     952          47 :                 ret = add_to_list(list, &sa.val[j].u.otherName.value);
     953          47 :                 if (ret) {
     954           0 :                     hx509_set_error_string(context, 0, ret,
     955             :                                            "Error adding an extra SAN to "
     956             :                                            "return list");
     957           0 :                     hx509_free_octet_string_list(list);
     958           0 :                     free_GeneralNames(&sa);
     959           0 :                     return ret;
     960             :                 }
     961             :             }
     962             :         }
     963          94 :         free_GeneralNames(&sa);
     964             :     }
     965             : }
     966             : 
     967             : 
     968             : static int
     969         202 : check_key_usage(hx509_context context, const Certificate *cert,
     970             :                 unsigned flags, int req_present)
     971             : {
     972           0 :     const Extension *e;
     973           0 :     KeyUsage ku;
     974           0 :     size_t size;
     975           0 :     int ret;
     976         202 :     size_t i = 0;
     977           0 :     uint64_t ku_flags;
     978             : 
     979         202 :     if (_hx509_cert_get_version(cert) < 3)
     980           0 :         return 0;
     981             : 
     982         202 :     e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
     983         202 :     if (e == NULL) {
     984           0 :         if (req_present) {
     985           0 :             hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
     986             :                                    "Required extension key "
     987             :                                    "usage missing from certificate");
     988           0 :             return HX509_KU_CERT_MISSING;
     989             :         }
     990           0 :         return 0;
     991             :     }
     992             : 
     993         202 :     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, &ku, &size);
     994         202 :     if (ret)
     995           0 :         return ret;
     996         202 :     ku_flags = KeyUsage2int(ku);
     997         202 :     if ((ku_flags & flags) != flags) {
     998           0 :         uint64_t missing = (~ku_flags) & flags;
     999           0 :         char buf[256], *name;
    1000             : 
    1001           0 :         int result = unparse_flags(missing, asn1_KeyUsage_units(),
    1002             :                                    buf, sizeof(buf));
    1003           0 :         _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
    1004           0 :         hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
    1005             :                                "Key usage %s required but missing "
    1006             :                                "from certificate %s",
    1007             :                                (result > 0) ? buf : "<unknown>",
    1008           0 :                                name ? name : "<unknown>");
    1009           0 :         free(name);
    1010           0 :         return HX509_KU_CERT_MISSING;
    1011             :     }
    1012         202 :     return 0;
    1013             : }
    1014             : 
    1015             : /*
    1016             :  * Return 0 on matching key usage 'flags' for 'cert', otherwise return
    1017             :  * an error code. If 'req_present' the existence is required of the
    1018             :  * KeyUsage extension.
    1019             :  */
    1020             : 
    1021             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1022          14 : _hx509_check_key_usage(hx509_context context, hx509_cert cert,
    1023             :                        unsigned flags, int req_present)
    1024             : {
    1025          14 :     return check_key_usage(context, _hx509_get_cert(cert), flags, req_present);
    1026             : }
    1027             : 
    1028             : enum certtype { PROXY_CERT, EE_CERT, CA_CERT };
    1029             : 
    1030             : static int
    1031         148 : check_basic_constraints(hx509_context context, const Certificate *cert,
    1032             :                         enum certtype type, size_t depth)
    1033             : {
    1034           0 :     BasicConstraints bc;
    1035           0 :     const Extension *e;
    1036           0 :     size_t size;
    1037           0 :     int ret;
    1038         148 :     size_t i = 0;
    1039             : 
    1040         148 :     if (_hx509_cert_get_version(cert) < 3)
    1041           0 :         return 0;
    1042             : 
    1043         148 :     e = find_extension(cert, &asn1_oid_id_x509_ce_basicConstraints, &i);
    1044         148 :     if (e == NULL) {
    1045           0 :         switch(type) {
    1046           0 :         case PROXY_CERT:
    1047             :         case EE_CERT:
    1048           0 :             return 0;
    1049           0 :         case CA_CERT: {
    1050           0 :             char *name;
    1051           0 :             ret = _hx509_unparse_Name(&cert->tbsCertificate.subject, &name);
    1052           0 :             assert(ret == 0);
    1053           0 :             hx509_set_error_string(context, 0, HX509_EXTENSION_NOT_FOUND,
    1054             :                                    "basicConstraints missing from "
    1055             :                                    "CA certifiacte %s", name);
    1056           0 :             free(name);
    1057           0 :             return HX509_EXTENSION_NOT_FOUND;
    1058             :         }
    1059             :         }
    1060             :     }
    1061             : 
    1062         148 :     ret = decode_BasicConstraints(e->extnValue.data,
    1063         148 :                                   e->extnValue.length, &bc,
    1064             :                                   &size);
    1065         148 :     if (ret)
    1066           0 :         return ret;
    1067         148 :     switch(type) {
    1068           0 :     case PROXY_CERT:
    1069           0 :         if (bc.cA)
    1070           0 :             ret = HX509_PARENT_IS_CA;
    1071           0 :         break;
    1072          74 :     case EE_CERT:
    1073          74 :         ret = 0;
    1074          74 :         break;
    1075          74 :     case CA_CERT:
    1076          74 :         if (!bc.cA)
    1077           0 :             ret = HX509_PARENT_NOT_CA;
    1078          74 :         else if (bc.pathLenConstraint)
    1079           0 :             if (depth - 1 > *bc.pathLenConstraint)
    1080           0 :                 ret = HX509_CA_PATH_TOO_DEEP;
    1081          74 :         break;
    1082             :     }
    1083         148 :     free_BasicConstraints(&bc);
    1084         148 :     return ret;
    1085             : }
    1086             : 
    1087             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1088         168 : _hx509_cert_is_parent_cmp(const Certificate *subject,
    1089             :                           const Certificate *issuer,
    1090             :                           int allow_self_signed)
    1091             : {
    1092           0 :     int diff;
    1093           0 :     AuthorityKeyIdentifier ai;
    1094           0 :     SubjectKeyIdentifier si;
    1095           0 :     int ret_ai, ret_si, ret;
    1096             : 
    1097         168 :     ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
    1098             :                           &subject->tbsCertificate.issuer,
    1099             :                           &diff);
    1100         168 :     if (ret)
    1101           0 :         return ret;
    1102         168 :     if (diff)
    1103          94 :         return diff;
    1104             : 
    1105          74 :     memset(&ai, 0, sizeof(ai));
    1106          74 :     memset(&si, 0, sizeof(si));
    1107             : 
    1108             :     /*
    1109             :      * Try to find AuthorityKeyIdentifier, if it's not present in the
    1110             :      * subject certificate nor the parent.
    1111             :      */
    1112             : 
    1113          74 :     ret_ai = find_extension_auth_key_id(subject, &ai);
    1114          74 :     if (ret_ai && ret_ai != HX509_EXTENSION_NOT_FOUND)
    1115           0 :         return 1;
    1116          74 :     ret_si = _hx509_find_extension_subject_key_id(issuer, &si);
    1117          74 :     if (ret_si && ret_si != HX509_EXTENSION_NOT_FOUND)
    1118           0 :         return -1;
    1119             : 
    1120          74 :     if (ret_si && ret_ai)
    1121           0 :         goto out;
    1122          74 :     if (ret_ai)
    1123          46 :         goto out;
    1124          28 :     if (ret_si) {
    1125           0 :         if (allow_self_signed) {
    1126           0 :             diff = 0;
    1127           0 :             goto out;
    1128           0 :         } else if (ai.keyIdentifier) {
    1129           0 :             diff = -1;
    1130           0 :             goto out;
    1131             :         }
    1132             :     }
    1133             : 
    1134          28 :     if (ai.keyIdentifier == NULL) {
    1135           0 :         Name name;
    1136             : 
    1137           0 :         if (ai.authorityCertIssuer == NULL)
    1138           0 :             return -1;
    1139           0 :         if (ai.authorityCertSerialNumber == NULL)
    1140           0 :             return -1;
    1141             : 
    1142           0 :         diff = der_heim_integer_cmp(ai.authorityCertSerialNumber,
    1143           0 :                                     &issuer->tbsCertificate.serialNumber);
    1144           0 :         if (diff)
    1145           0 :             return diff;
    1146           0 :         if (ai.authorityCertIssuer->len != 1)
    1147           0 :             return -1;
    1148           0 :         if (ai.authorityCertIssuer->val[0].element != choice_GeneralName_directoryName)
    1149           0 :             return -1;
    1150             : 
    1151           0 :         name.element = (enum Name_enum)
    1152           0 :             ai.authorityCertIssuer->val[0].u.directoryName.element;
    1153           0 :         name.u.rdnSequence =
    1154           0 :             ai.authorityCertIssuer->val[0].u.directoryName.u.rdnSequence;
    1155             : 
    1156           0 :         ret = _hx509_name_cmp(&issuer->tbsCertificate.subject,
    1157             :                               &name,
    1158             :                               &diff);
    1159           0 :         if (ret)
    1160           0 :             return ret;
    1161           0 :         if (diff)
    1162           0 :             return diff;
    1163           0 :         diff = 0;
    1164             :     } else
    1165          28 :         diff = der_heim_octet_string_cmp(ai.keyIdentifier, &si);
    1166          28 :     if (diff)
    1167           0 :         goto out;
    1168             : 
    1169          28 :  out:
    1170          74 :     free_AuthorityKeyIdentifier(&ai);
    1171          74 :     free_SubjectKeyIdentifier(&si);
    1172          74 :     return diff;
    1173             : }
    1174             : 
    1175             : static int
    1176         213 : certificate_is_anchor(hx509_context context,
    1177             :                       hx509_certs trust_anchors,
    1178             :                       const hx509_cert cert)
    1179             : {
    1180           0 :     hx509_query q;
    1181           0 :     hx509_cert c;
    1182           0 :     int ret;
    1183             : 
    1184         213 :     if (trust_anchors == NULL)
    1185          52 :         return 0;
    1186             : 
    1187         161 :     _hx509_query_clear(&q);
    1188             : 
    1189         161 :     q.match = HX509_QUERY_MATCH_CERTIFICATE;
    1190         161 :     q.certificate = _hx509_get_cert(cert);
    1191             : 
    1192         161 :     ret = hx509_certs_find(context, trust_anchors, &q, &c);
    1193         161 :     if (ret == 0)
    1194          74 :         hx509_cert_free(c);
    1195         161 :     return ret == 0;
    1196             : }
    1197             : 
    1198             : static int
    1199         220 : certificate_is_self_signed(hx509_context context,
    1200             :                            const Certificate *cert,
    1201             :                            int *self_signed)
    1202             : {
    1203           0 :     int ret, diff;
    1204         220 :     ret = _hx509_name_cmp(&cert->tbsCertificate.subject,
    1205             :                           &cert->tbsCertificate.issuer, &diff);
    1206         220 :     *self_signed = (diff == 0);
    1207         220 :     if (ret) {
    1208           0 :         hx509_set_error_string(context, 0, ret,
    1209             :                                "Failed to check if self signed");
    1210         220 :     } else if (diff == 0)
    1211         146 :         ret = _hx509_self_signed_valid(context, &cert->signatureAlgorithm);
    1212             : 
    1213         220 :     return ret;
    1214             : }
    1215             : 
    1216             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1217           0 : hx509_cert_is_self_signed(hx509_context context,
    1218             :                           hx509_cert c,
    1219             :                           int *self_signed)
    1220             : {
    1221           0 :     return certificate_is_self_signed(context, c->data, self_signed);
    1222             : }
    1223             : 
    1224             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1225           0 : hx509_cert_is_ca(hx509_context context,
    1226             :                  hx509_cert c,
    1227             :                  int *is_ca)
    1228             : {
    1229           0 :     BasicConstraints bc;
    1230           0 :     const Extension *e;
    1231           0 :     size_t size;
    1232           0 :     size_t i = 0;
    1233           0 :     int ret = 0;
    1234             : 
    1235           0 :     *is_ca = 0;
    1236           0 :     if (_hx509_cert_get_version(c->data) < 3)
    1237           0 :         return certificate_is_self_signed(context, c->data, is_ca);
    1238             : 
    1239           0 :     e = find_extension(c->data, &asn1_oid_id_x509_ce_basicConstraints, &i);
    1240           0 :     if (e == NULL) {
    1241           0 :         *is_ca = 0;
    1242           0 :         return 0;
    1243             :     }
    1244             : 
    1245           0 :     ret = decode_BasicConstraints(e->extnValue.data,
    1246           0 :                                   e->extnValue.length, &bc,
    1247             :                                   &size);
    1248           0 :     if (ret)
    1249           0 :         return ret;
    1250             : 
    1251           0 :     *is_ca = bc.cA;
    1252           0 :     free_BasicConstraints(&bc);
    1253           0 :     return 0;
    1254             : }
    1255             : 
    1256             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1257           0 : hx509_cert_is_root(hx509_context context,
    1258             :                    hx509_cert c,
    1259             :                    int *is_root)
    1260             : {
    1261           0 :     int ret;
    1262             : 
    1263           0 :     *is_root = 0;
    1264           0 :     ret = hx509_cert_is_ca(context, c, is_root);
    1265           0 :     if (ret)
    1266           0 :         return ret;
    1267           0 :     if (*is_root == 0)
    1268             :         /* Not a CA certificate -> not a root certificate */
    1269           0 :         return 0;
    1270             : 
    1271             :     /* A CA certificate.  If it's self-signed, it's a root certificate. */
    1272           0 :     return hx509_cert_is_self_signed(context, c, is_root);
    1273             : }
    1274             : 
    1275             : /*
    1276             :  * The subjectName is "null" when it's empty set of relative DBs.
    1277             :  */
    1278             : 
    1279             : static int
    1280         139 : subject_null_p(const Certificate *c)
    1281             : {
    1282         139 :     return c->tbsCertificate.subject.u.rdnSequence.len == 0;
    1283             : }
    1284             : 
    1285             : 
    1286             : static int
    1287         139 : find_parent(hx509_context context,
    1288             :             time_t time_now,
    1289             :             hx509_certs trust_anchors,
    1290             :             hx509_path *path,
    1291             :             hx509_certs pool,
    1292             :             hx509_cert current,
    1293             :             hx509_cert *parent)
    1294             : {
    1295           0 :     AuthorityKeyIdentifier ai;
    1296           0 :     hx509_query q;
    1297           0 :     int ret;
    1298             : 
    1299         139 :     *parent = NULL;
    1300         139 :     memset(&ai, 0, sizeof(ai));
    1301             : 
    1302         139 :     _hx509_query_clear(&q);
    1303             : 
    1304         139 :     if (!subject_null_p(current->data)) {
    1305         139 :         q.match |= HX509_QUERY_FIND_ISSUER_CERT;
    1306         139 :         q.subject = _hx509_get_cert(current);
    1307             :     } else {
    1308           0 :         ret = find_extension_auth_key_id(current->data, &ai);
    1309           0 :         if (ret) {
    1310           0 :             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
    1311             :                                    "Subjectless certificate missing AuthKeyID");
    1312           0 :             return HX509_CERTIFICATE_MALFORMED;
    1313             :         }
    1314             : 
    1315           0 :         if (ai.keyIdentifier == NULL) {
    1316           0 :             free_AuthorityKeyIdentifier(&ai);
    1317           0 :             hx509_set_error_string(context, 0, HX509_CERTIFICATE_MALFORMED,
    1318             :                                    "Subjectless certificate missing keyIdentifier "
    1319             :                                    "inside AuthKeyID");
    1320           0 :             return HX509_CERTIFICATE_MALFORMED;
    1321             :         }
    1322             : 
    1323           0 :         q.subject_id = ai.keyIdentifier;
    1324           0 :         q.match = HX509_QUERY_MATCH_SUBJECT_KEY_ID;
    1325             :     }
    1326             : 
    1327         139 :     q.path = path;
    1328         139 :     q.match |= HX509_QUERY_NO_MATCH_PATH;
    1329             : 
    1330         139 :     if (pool) {
    1331         139 :         q.timenow = time_now;
    1332         139 :         q.match |= HX509_QUERY_MATCH_TIME;
    1333             : 
    1334         139 :         ret = hx509_certs_find(context, pool, &q, parent);
    1335         139 :         if (ret == 0) {
    1336           0 :             free_AuthorityKeyIdentifier(&ai);
    1337           0 :             return 0;
    1338             :         }
    1339         139 :         q.match &= ~HX509_QUERY_MATCH_TIME;
    1340             :     }
    1341             : 
    1342         139 :     if (trust_anchors) {
    1343          87 :         ret = hx509_certs_find(context, trust_anchors, &q, parent);
    1344          87 :         if (ret == 0) {
    1345          74 :             free_AuthorityKeyIdentifier(&ai);
    1346          74 :             return ret;
    1347             :         }
    1348             :     }
    1349          65 :     free_AuthorityKeyIdentifier(&ai);
    1350             : 
    1351             :     {
    1352           0 :         hx509_name name;
    1353           0 :         char *str;
    1354             : 
    1355          65 :         ret = hx509_cert_get_subject(current, &name);
    1356          65 :         if (ret) {
    1357           0 :             hx509_clear_error_string(context);
    1358           0 :             return HX509_ISSUER_NOT_FOUND;
    1359             :         }
    1360          65 :         ret = hx509_name_to_string(name, &str);
    1361          65 :         hx509_name_free(&name);
    1362          65 :         if (ret) {
    1363           0 :             hx509_clear_error_string(context);
    1364           0 :             return HX509_ISSUER_NOT_FOUND;
    1365             :         }
    1366             : 
    1367          65 :         hx509_set_error_string(context, 0, HX509_ISSUER_NOT_FOUND,
    1368             :                                "Failed to find issuer for "
    1369             :                                "certificate with subject: '%s'", str);
    1370          65 :         free(str);
    1371             :     }
    1372          65 :     return HX509_ISSUER_NOT_FOUND;
    1373             : }
    1374             : 
    1375             : /*
    1376             :  *
    1377             :  */
    1378             : 
    1379             : static int
    1380         121 : is_proxy_cert(hx509_context context,
    1381             :               const Certificate *cert,
    1382             :               ProxyCertInfo *rinfo)
    1383             : {
    1384           0 :     ProxyCertInfo info;
    1385           0 :     const Extension *e;
    1386           0 :     size_t size;
    1387           0 :     int ret;
    1388         121 :     size_t i = 0;
    1389             : 
    1390         121 :     if (rinfo)
    1391           0 :         memset(rinfo, 0, sizeof(*rinfo));
    1392             : 
    1393         121 :     e = find_extension(cert, &asn1_oid_id_pkix_pe_proxyCertInfo, &i);
    1394         121 :     if (e == NULL) {
    1395         121 :         hx509_clear_error_string(context);
    1396         121 :         return HX509_EXTENSION_NOT_FOUND;
    1397             :     }
    1398             : 
    1399           0 :     ret = decode_ProxyCertInfo(e->extnValue.data,
    1400           0 :                                e->extnValue.length,
    1401             :                                &info,
    1402             :                                &size);
    1403           0 :     if (ret) {
    1404           0 :         hx509_clear_error_string(context);
    1405           0 :         return ret;
    1406             :     }
    1407           0 :     if (size != e->extnValue.length) {
    1408           0 :         free_ProxyCertInfo(&info);
    1409           0 :         hx509_clear_error_string(context);
    1410           0 :         return HX509_EXTRA_DATA_AFTER_STRUCTURE;
    1411             :     }
    1412           0 :     if (rinfo == NULL)
    1413           0 :         free_ProxyCertInfo(&info);
    1414             :     else
    1415           0 :         *rinfo = info;
    1416             : 
    1417           0 :     return 0;
    1418             : }
    1419             : 
    1420             : /*
    1421             :  * Path operations are like MEMORY based keyset, but with exposed
    1422             :  * internal so we can do easy searches.
    1423             :  */
    1424             : 
    1425             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1426         213 : _hx509_path_append(hx509_context context, hx509_path *path, hx509_cert cert)
    1427             : {
    1428           0 :     hx509_cert *val;
    1429         213 :     val = realloc(path->val, (path->len + 1) * sizeof(path->val[0]));
    1430         213 :     if (val == NULL) {
    1431           0 :         hx509_set_error_string(context, 0, ENOMEM, "out of memory");
    1432           0 :         return ENOMEM;
    1433             :     }
    1434             : 
    1435         213 :     path->val = val;
    1436         213 :     path->val[path->len] = hx509_cert_ref(cert);
    1437         213 :     path->len++;
    1438             : 
    1439         213 :     return 0;
    1440             : }
    1441             : 
    1442             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    1443         139 : _hx509_path_free(hx509_path *path)
    1444             : {
    1445           0 :     unsigned i;
    1446             : 
    1447         352 :     for (i = 0; i < path->len; i++)
    1448         213 :         hx509_cert_free(path->val[i]);
    1449         139 :     free(path->val);
    1450         139 :     path->val = NULL;
    1451         139 :     path->len = 0;
    1452         139 : }
    1453             : 
    1454             : /*
    1455             :  * Find path by looking up issuer for the top certificate and continue
    1456             :  * until an anchor certificate is found or max limit is found. A
    1457             :  * certificate never included twice in the path.
    1458             :  *
    1459             :  * If the trust anchors are not given, calculate optimistic path, just
    1460             :  * follow the chain upward until we no longer find a parent or we hit
    1461             :  * the max path limit. In this case, a failure will always be returned
    1462             :  * depending on what error condition is hit first.
    1463             :  *
    1464             :  * The path includes a path from the top certificate to the anchor
    1465             :  * certificate.
    1466             :  *
    1467             :  * The caller needs to free `path´ both on successful built path and
    1468             :  * failure.
    1469             :  */
    1470             : 
    1471             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1472         139 : _hx509_calculate_path(hx509_context context,
    1473             :                       int flags,
    1474             :                       time_t time_now,
    1475             :                       hx509_certs anchors,
    1476             :                       unsigned int max_depth,
    1477             :                       hx509_cert cert,
    1478             :                       hx509_certs pool,
    1479             :                       hx509_path *path)
    1480             : {
    1481           0 :     hx509_cert parent, current;
    1482           0 :     int ret;
    1483             : 
    1484         139 :     if (max_depth == 0)
    1485          65 :         max_depth = HX509_VERIFY_MAX_DEPTH;
    1486             : 
    1487         139 :     ret = _hx509_path_append(context, path, cert);
    1488         139 :     if (ret)
    1489           0 :         return ret;
    1490             : 
    1491         139 :     current = hx509_cert_ref(cert);
    1492             : 
    1493         213 :     while (!certificate_is_anchor(context, anchors, current)) {
    1494             : 
    1495         139 :         ret = find_parent(context, time_now, anchors, path,
    1496             :                           pool, current, &parent);
    1497         139 :         hx509_cert_free(current);
    1498         139 :         if (ret)
    1499          65 :             return ret;
    1500             : 
    1501          74 :         ret = _hx509_path_append(context, path, parent);
    1502          74 :         if (ret)
    1503           0 :             return ret;
    1504          74 :         current = parent;
    1505             : 
    1506          74 :         if (path->len > max_depth) {
    1507           0 :             hx509_cert_free(current);
    1508           0 :             hx509_set_error_string(context, 0, HX509_PATH_TOO_LONG,
    1509             :                                    "Path too long while building "
    1510             :                                    "certificate chain");
    1511           0 :             return HX509_PATH_TOO_LONG;
    1512             :         }
    1513             :     }
    1514             : 
    1515          74 :     if ((flags & HX509_CALCULATE_PATH_NO_ANCHOR) &&
    1516           0 :         path->len > 0 &&
    1517           0 :         certificate_is_anchor(context, anchors, path->val[path->len - 1]))
    1518             :     {
    1519           0 :         hx509_cert_free(path->val[path->len - 1]);
    1520           0 :         path->len--;
    1521             :     }
    1522             : 
    1523          74 :     hx509_cert_free(current);
    1524          74 :     return 0;
    1525             : }
    1526             : 
    1527             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1528          74 : _hx509_AlgorithmIdentifier_cmp(const AlgorithmIdentifier *p,
    1529             :                                const AlgorithmIdentifier *q)
    1530             : {
    1531           0 :     int diff;
    1532          74 :     diff = der_heim_oid_cmp(&p->algorithm, &q->algorithm);
    1533          74 :     if (diff)
    1534           0 :         return diff;
    1535          74 :     if (p->parameters) {
    1536          74 :         if (q->parameters)
    1537          74 :             return heim_any_cmp(p->parameters,
    1538          74 :                                 q->parameters);
    1539             :         else
    1540           0 :             return 1;
    1541             :     } else {
    1542           0 :         if (q->parameters)
    1543           0 :             return -1;
    1544             :         else
    1545           0 :             return 0;
    1546             :     }
    1547             : }
    1548             : 
    1549             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1550         222 : _hx509_Certificate_cmp(const Certificate *p, const Certificate *q)
    1551             : {
    1552           0 :     int diff;
    1553         222 :     diff = der_heim_bit_string_cmp(&p->signatureValue, &q->signatureValue);
    1554         222 :     if (diff)
    1555         148 :         return diff;
    1556          74 :     diff = _hx509_AlgorithmIdentifier_cmp(&p->signatureAlgorithm,
    1557             :                                           &q->signatureAlgorithm);
    1558          74 :     if (diff)
    1559           0 :         return diff;
    1560          74 :     diff = der_heim_octet_string_cmp(&p->tbsCertificate._save,
    1561             :                                      &q->tbsCertificate._save);
    1562          74 :     return diff;
    1563             : }
    1564             : 
    1565             : /**
    1566             :  * Compare to hx509 certificate object, useful for sorting.
    1567             :  *
    1568             :  * @param p a hx509 certificate object.
    1569             :  * @param q a hx509 certificate object.
    1570             :  *
    1571             :  * @return 0 the objects are the same, returns > 0 is p is "larger"
    1572             :  * then q, < 0 if p is "smaller" then q.
    1573             :  *
    1574             :  * @ingroup hx509_cert
    1575             :  */
    1576             : 
    1577             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1578          74 : hx509_cert_cmp(hx509_cert p, hx509_cert q)
    1579             : {
    1580          74 :     return _hx509_Certificate_cmp(p->data, q->data);
    1581             : }
    1582             : 
    1583             : /**
    1584             :  * Return the name of the issuer of the hx509 certificate.
    1585             :  *
    1586             :  * @param p a hx509 certificate object.
    1587             :  * @param name a pointer to a hx509 name, should be freed by
    1588             :  * hx509_name_free().
    1589             :  *
    1590             :  * @return An hx509 error code, see hx509_get_error_string().
    1591             :  *
    1592             :  * @ingroup hx509_cert
    1593             :  */
    1594             : 
    1595             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1596         121 : hx509_cert_get_issuer(hx509_cert p, hx509_name *name)
    1597             : {
    1598         121 :     return _hx509_name_from_Name(&p->data->tbsCertificate.issuer, name);
    1599             : }
    1600             : 
    1601             : /**
    1602             :  * Return the name of the subject of the hx509 certificate.
    1603             :  *
    1604             :  * @param p a hx509 certificate object.
    1605             :  * @param name a pointer to a hx509 name, should be freed by
    1606             :  * hx509_name_free(). See also hx509_cert_get_base_subject().
    1607             :  *
    1608             :  * @return An hx509 error code, see hx509_get_error_string().
    1609             :  *
    1610             :  * @ingroup hx509_cert
    1611             :  */
    1612             : 
    1613             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1614         186 : hx509_cert_get_subject(hx509_cert p, hx509_name *name)
    1615             : {
    1616         186 :     return _hx509_name_from_Name(&p->data->tbsCertificate.subject, name);
    1617             : }
    1618             : 
    1619             : /**
    1620             :  * Return the name of the base subject of the hx509 certificate. If
    1621             :  * the certiicate is a verified proxy certificate, the this function
    1622             :  * return the base certificate (root of the proxy chain). If the proxy
    1623             :  * certificate is not verified with the base certificate
    1624             :  * HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED is returned.
    1625             :  *
    1626             :  * @param context a hx509 context.
    1627             :  * @param c a hx509 certificate object.
    1628             :  * @param name a pointer to a hx509 name, should be freed by
    1629             :  * hx509_name_free(). See also hx509_cert_get_subject().
    1630             :  *
    1631             :  * @return An hx509 error code, see hx509_get_error_string().
    1632             :  *
    1633             :  * @ingroup hx509_cert
    1634             :  */
    1635             : 
    1636             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1637          47 : hx509_cert_get_base_subject(hx509_context context, hx509_cert c,
    1638             :                             hx509_name *name)
    1639             : {
    1640          47 :     if (c->basename)
    1641           0 :         return hx509_name_copy(context, c->basename, name);
    1642          47 :     if (is_proxy_cert(context, c->data, NULL) == 0) {
    1643           0 :         int ret = HX509_PROXY_CERTIFICATE_NOT_CANONICALIZED;
    1644           0 :         hx509_set_error_string(context, 0, ret,
    1645             :                                "Proxy certificate has not been "
    1646             :                                "canonicalized yet: no base name");
    1647           0 :         return ret;
    1648             :     }
    1649          47 :     return _hx509_name_from_Name(&c->data->tbsCertificate.subject, name);
    1650             : }
    1651             : 
    1652             : /**
    1653             :  * Get serial number of the certificate.
    1654             :  *
    1655             :  * @param p a hx509 certificate object.
    1656             :  * @param i serial number, should be freed ith der_free_heim_integer().
    1657             :  *
    1658             :  * @return An hx509 error code, see hx509_get_error_string().
    1659             :  *
    1660             :  * @ingroup hx509_cert
    1661             :  */
    1662             : 
    1663             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1664         121 : hx509_cert_get_serialnumber(hx509_cert p, heim_integer *i)
    1665             : {
    1666         121 :     return der_copy_heim_integer(&p->data->tbsCertificate.serialNumber, i);
    1667             : }
    1668             : 
    1669             : /**
    1670             :  * Get notBefore time of the certificate.
    1671             :  *
    1672             :  * @param p a hx509 certificate object.
    1673             :  *
    1674             :  * @return return not before time
    1675             :  *
    1676             :  * @ingroup hx509_cert
    1677             :  */
    1678             : 
    1679             : HX509_LIB_FUNCTION time_t HX509_LIB_CALL
    1680           0 : hx509_cert_get_notBefore(hx509_cert p)
    1681             : {
    1682           0 :     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notBefore);
    1683             : }
    1684             : 
    1685             : /**
    1686             :  * Get notAfter time of the certificate.
    1687             :  *
    1688             :  * @param p a hx509 certificate object.
    1689             :  *
    1690             :  * @return return not after time.
    1691             :  *
    1692             :  * @ingroup hx509_cert
    1693             :  */
    1694             : 
    1695             : HX509_LIB_FUNCTION time_t HX509_LIB_CALL
    1696          47 : hx509_cert_get_notAfter(hx509_cert p)
    1697             : {
    1698          47 :     return _hx509_Time2time_t(&p->data->tbsCertificate.validity.notAfter);
    1699             : }
    1700             : 
    1701             : /**
    1702             :  * Get a maximum Kerberos credential lifetime from a Heimdal certificate
    1703             :  * extension.
    1704             :  *
    1705             :  * @param context hx509 context.
    1706             :  * @param cert Certificate.
    1707             :  * @param bound If larger than zero, return no more than this.
    1708             :  *
    1709             :  * @return maximum ticket lifetime.
    1710             :  */
    1711             : HX509_LIB_FUNCTION time_t HX509_LIB_CALL
    1712           0 : hx509_cert_get_pkinit_max_life(hx509_context context,
    1713             :                                hx509_cert cert,
    1714             :                                time_t bound)
    1715             : {
    1716           0 :     HeimPkinitPrincMaxLifeSecs r = 0;
    1717           0 :     size_t sz, i;
    1718           0 :     time_t b, e;
    1719           0 :     int ret;
    1720             : 
    1721           0 :     for (i = 0; i < cert->data->tbsCertificate.extensions->len; i++) {
    1722           0 :         Extension *ext = &cert->data->tbsCertificate.extensions->val[i];
    1723             : 
    1724           0 :         if (ext->_ioschoice_extnValue.element !=
    1725           0 :             choice_Extension_iosnumunknown &&
    1726           0 :             ext->_ioschoice_extnValue.element !=
    1727             :             choice_Extension_iosnum_id_heim_ce_pkinit_princ_max_life)
    1728           0 :             continue;
    1729           0 :         if (ext->_ioschoice_extnValue.element == choice_Extension_iosnumunknown &&
    1730           0 :             der_heim_oid_cmp(&asn1_oid_id_heim_ce_pkinit_princ_max_life, &ext->extnID))
    1731           0 :             continue;
    1732           0 :         if (ext->_ioschoice_extnValue.u.ext_HeimPkinitPrincMaxLife) {
    1733           0 :             r = *ext->_ioschoice_extnValue.u.ext_HeimPkinitPrincMaxLife;
    1734             :         } else {
    1735           0 :             ret = decode_HeimPkinitPrincMaxLifeSecs(ext->extnValue.data,
    1736             :                                                     ext->extnValue.length,
    1737             :                                                     &r, &sz);
    1738             :             /* No need to free_HeimPkinitPrincMaxLifeSecs(); it's an int */
    1739           0 :             if (ret || r < 1)
    1740           0 :                 return 0;
    1741             :         }
    1742           0 :         if (bound > 0 && r > bound)
    1743           0 :             return bound;
    1744           0 :         return r;
    1745             :     }
    1746           0 :     if (hx509_cert_check_eku(context, cert,
    1747             :                              &asn1_oid_id_heim_eku_pkinit_certlife_is_max_life, 0))
    1748           0 :         return 0;
    1749           0 :     b = hx509_cert_get_notBefore(cert);
    1750           0 :     e = hx509_cert_get_notAfter(cert);
    1751           0 :     if (e > b)
    1752           0 :         r = e - b;
    1753           0 :     if (bound > 0 && r > bound)
    1754           0 :         return bound;
    1755           0 :     return r;
    1756             : }
    1757             : 
    1758             : /**
    1759             :  * Get the SubjectPublicKeyInfo structure from the hx509 certificate.
    1760             :  *
    1761             :  * @param context a hx509 context.
    1762             :  * @param p a hx509 certificate object.
    1763             :  * @param spki SubjectPublicKeyInfo, should be freed with
    1764             :  * free_SubjectPublicKeyInfo().
    1765             :  *
    1766             :  * @return An hx509 error code, see hx509_get_error_string().
    1767             :  *
    1768             :  * @ingroup hx509_cert
    1769             :  */
    1770             : 
    1771             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1772           0 : hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *spki)
    1773             : {
    1774           0 :     int ret;
    1775             : 
    1776           0 :     ret = copy_SubjectPublicKeyInfo(&p->data->tbsCertificate.subjectPublicKeyInfo, spki);
    1777           0 :     if (ret)
    1778           0 :         hx509_set_error_string(context, 0, ret, "Failed to copy SPKI");
    1779           0 :     return ret;
    1780             : }
    1781             : 
    1782             : /**
    1783             :  * Get the AlgorithmIdentifier from the hx509 certificate.
    1784             :  *
    1785             :  * @param context a hx509 context.
    1786             :  * @param p a hx509 certificate object.
    1787             :  * @param alg AlgorithmIdentifier, should be freed with
    1788             :  *            free_AlgorithmIdentifier(). The algorithmidentifier is
    1789             :  *            typicly rsaEncryption, or id-ecPublicKey, or some other
    1790             :  *            public key mechanism.
    1791             :  *
    1792             :  * @return An hx509 error code, see hx509_get_error_string().
    1793             :  *
    1794             :  * @ingroup hx509_cert
    1795             :  */
    1796             : 
    1797             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1798          20 : hx509_cert_get_SPKI_AlgorithmIdentifier(hx509_context context,
    1799             :                                         hx509_cert p,
    1800             :                                         AlgorithmIdentifier *alg)
    1801             : {
    1802           0 :     int ret;
    1803             : 
    1804          20 :     ret = copy_AlgorithmIdentifier(&p->data->tbsCertificate.subjectPublicKeyInfo.algorithm, alg);
    1805          20 :     if (ret)
    1806           0 :         hx509_set_error_string(context, 0, ret,
    1807             :                                "Failed to copy SPKI AlgorithmIdentifier");
    1808          20 :     return ret;
    1809             : }
    1810             : 
    1811             : static int
    1812           0 : get_x_unique_id(hx509_context context, const char *name,
    1813             :                 const heim_bit_string *cert, heim_bit_string *subject)
    1814             : {
    1815           0 :     int ret;
    1816             : 
    1817           0 :     if (cert == NULL) {
    1818           0 :         ret = HX509_EXTENSION_NOT_FOUND;
    1819           0 :         hx509_set_error_string(context, 0, ret, "%s unique id doesn't exist", name);
    1820           0 :         return ret;
    1821             :     }
    1822           0 :     ret = der_copy_bit_string(cert, subject);
    1823           0 :     if (ret) {
    1824           0 :         hx509_set_error_string(context, 0, ret, "malloc out of memory", name);
    1825           0 :         return ret;
    1826             :     }
    1827           0 :     return 0;
    1828             : }
    1829             : 
    1830             : /**
    1831             :  * Get a copy of the Issuer Unique ID
    1832             :  *
    1833             :  * @param context a hx509_context
    1834             :  * @param p a hx509 certificate
    1835             :  * @param issuer the issuer id returned, free with der_free_bit_string()
    1836             :  *
    1837             :  * @return An hx509 error code, see hx509_get_error_string(). The
    1838             :  * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
    1839             :  * doesn't have a issuerUniqueID
    1840             :  *
    1841             :  * @ingroup hx509_cert
    1842             :  */
    1843             : 
    1844             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1845           0 : hx509_cert_get_issuer_unique_id(hx509_context context, hx509_cert p, heim_bit_string *issuer)
    1846             : {
    1847           0 :     return get_x_unique_id(context, "issuer", p->data->tbsCertificate.issuerUniqueID, issuer);
    1848             : }
    1849             : 
    1850             : /**
    1851             :  * Get a copy of the Subect Unique ID
    1852             :  *
    1853             :  * @param context a hx509_context
    1854             :  * @param p a hx509 certificate
    1855             :  * @param subject the subject id returned, free with der_free_bit_string()
    1856             :  *
    1857             :  * @return An hx509 error code, see hx509_get_error_string(). The
    1858             :  * error code HX509_EXTENSION_NOT_FOUND is returned if the certificate
    1859             :  * doesn't have a subjectUniqueID
    1860             :  *
    1861             :  * @ingroup hx509_cert
    1862             :  */
    1863             : 
    1864             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1865           0 : hx509_cert_get_subject_unique_id(hx509_context context, hx509_cert p, heim_bit_string *subject)
    1866             : {
    1867           0 :     return get_x_unique_id(context, "subject", p->data->tbsCertificate.subjectUniqueID, subject);
    1868             : }
    1869             : 
    1870             : 
    1871             : HX509_LIB_FUNCTION hx509_private_key HX509_LIB_CALL
    1872         493 : _hx509_cert_private_key(hx509_cert p)
    1873             : {
    1874         493 :     return p->private_key;
    1875             : }
    1876             : 
    1877             : /**
    1878             :  * Indicate whether a hx509_cert has a private key.
    1879             :  *
    1880             :  * @param p a hx509 certificate
    1881             :  *
    1882             :  * @return 1 if p has a private key, 0 otherwise.
    1883             :  *
    1884             :  * @ingroup hx509_cert
    1885             :  */
    1886             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1887           0 : hx509_cert_have_private_key(hx509_cert p)
    1888             : {
    1889           0 :     return p->private_key ? 1 : 0;
    1890             : }
    1891             : 
    1892             : /**
    1893             :  * Indicate whether a hx509_cert has a private key only (no certificate).
    1894             :  *
    1895             :  * @param p a hx509 certificate
    1896             :  *
    1897             :  * @return 1 if p has a private key only (no certificate), 0 otherwise.
    1898             :  *
    1899             :  * @ingroup hx509_cert
    1900             :  */
    1901             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1902           0 : hx509_cert_have_private_key_only(hx509_cert p)
    1903             : {
    1904           0 :     return p->private_key && !p->data ? 1 : 0;
    1905             : }
    1906             : 
    1907             : 
    1908             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1909           0 : _hx509_cert_private_key_exportable(hx509_cert p)
    1910             : {
    1911           0 :     if (p->private_key == NULL)
    1912           0 :         return 0;
    1913           0 :     return _hx509_private_key_exportable(p->private_key);
    1914             : }
    1915             : 
    1916             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1917           0 : _hx509_cert_private_decrypt(hx509_context context,
    1918             :                             const heim_octet_string *ciphertext,
    1919             :                             const heim_oid *encryption_oid,
    1920             :                             hx509_cert p,
    1921             :                             heim_octet_string *cleartext)
    1922             : {
    1923           0 :     cleartext->data = NULL;
    1924           0 :     cleartext->length = 0;
    1925             : 
    1926           0 :     if (p->private_key == NULL) {
    1927           0 :         hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
    1928             :                                "Private key missing");
    1929           0 :         return HX509_PRIVATE_KEY_MISSING;
    1930             :     }
    1931             : 
    1932           0 :     return hx509_private_key_private_decrypt(context,
    1933             :                                               ciphertext,
    1934             :                                               encryption_oid,
    1935             :                                               p->private_key,
    1936             :                                               cleartext);
    1937             : }
    1938             : 
    1939             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    1940          21 : hx509_cert_public_encrypt(hx509_context context,
    1941             :                            const heim_octet_string *cleartext,
    1942             :                            const hx509_cert p,
    1943             :                            heim_oid *encryption_oid,
    1944             :                            heim_octet_string *ciphertext)
    1945             : {
    1946          42 :     return _hx509_public_encrypt(context,
    1947          21 :                                  cleartext, p->data,
    1948             :                                  encryption_oid, ciphertext);
    1949             : }
    1950             : 
    1951             : /*
    1952             :  *
    1953             :  */
    1954             : 
    1955             : HX509_LIB_FUNCTION time_t HX509_LIB_CALL
    1956         359 : _hx509_Time2time_t(const Time *t)
    1957             : {
    1958         359 :     switch(t->element) {
    1959         359 :     case choice_Time_utcTime:
    1960         359 :         return t->u.utcTime;
    1961           0 :     case choice_Time_generalTime:
    1962           0 :         return t->u.generalTime;
    1963             :     }
    1964           0 :     return 0;
    1965             : }
    1966             : 
    1967             : /*
    1968             :  *
    1969             :  */
    1970             : 
    1971             : static int
    1972          74 : init_name_constraints(hx509_name_constraints *nc)
    1973             : {
    1974          74 :     memset(nc, 0, sizeof(*nc));
    1975          74 :     return 0;
    1976             : }
    1977             : 
    1978             : static int
    1979         148 : add_name_constraints(hx509_context context, const Certificate *c, int not_ca,
    1980             :                      hx509_name_constraints *nc)
    1981             : {
    1982           0 :     NameConstraints tnc;
    1983           0 :     int ret;
    1984             : 
    1985         148 :     ret = find_extension_name_constraints(c, &tnc);
    1986         148 :     if (ret == HX509_EXTENSION_NOT_FOUND)
    1987         148 :         return 0;
    1988           0 :     else if (ret) {
    1989           0 :         hx509_set_error_string(context, 0, ret, "Failed getting NameConstraints");
    1990           0 :         return ret;
    1991           0 :     } else if (not_ca) {
    1992           0 :         ret = HX509_VERIFY_CONSTRAINTS;
    1993           0 :         hx509_set_error_string(context, 0, ret, "Not a CA and "
    1994             :                                "have NameConstraints");
    1995             :     } else {
    1996           0 :         NameConstraints *val;
    1997           0 :         val = realloc(nc->val, sizeof(nc->val[0]) * (nc->len + 1));
    1998           0 :         if (val == NULL) {
    1999           0 :             hx509_clear_error_string(context);
    2000           0 :             ret = ENOMEM;
    2001           0 :             goto out;
    2002             :         }
    2003           0 :         nc->val = val;
    2004           0 :         ret = copy_NameConstraints(&tnc, &nc->val[nc->len]);
    2005           0 :         if (ret) {
    2006           0 :             hx509_clear_error_string(context);
    2007           0 :             goto out;
    2008             :         }
    2009           0 :         nc->len += 1;
    2010             :     }
    2011           0 : out:
    2012           0 :     free_NameConstraints(&tnc);
    2013           0 :     return ret;
    2014             : }
    2015             : 
    2016             : static int
    2017           0 : match_RDN(const RelativeDistinguishedName *c,
    2018             :           const RelativeDistinguishedName *n)
    2019             : {
    2020           0 :     size_t i;
    2021             : 
    2022           0 :     if (c->len != n->len)
    2023           0 :         return HX509_NAME_CONSTRAINT_ERROR;
    2024             : 
    2025           0 :     for (i = 0; i < n->len; i++) {
    2026           0 :         int diff, ret;
    2027             : 
    2028           0 :         if (der_heim_oid_cmp(&c->val[i].type, &n->val[i].type) != 0)
    2029           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2030           0 :         ret = _hx509_name_ds_cmp(&c->val[i].value, &n->val[i].value, &diff);
    2031           0 :         if (ret)
    2032           0 :             return ret;
    2033           0 :         if (diff != 0)
    2034           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2035             :     }
    2036           0 :     return 0;
    2037             : }
    2038             : 
    2039             : static int
    2040           0 : match_X501Name(const Name *c, const Name *n)
    2041             : {
    2042           0 :     size_t i;
    2043           0 :     int ret;
    2044             : 
    2045           0 :     if (c->element != choice_Name_rdnSequence
    2046           0 :         || n->element != choice_Name_rdnSequence)
    2047           0 :         return 0;
    2048           0 :     if (c->u.rdnSequence.len > n->u.rdnSequence.len)
    2049           0 :         return HX509_NAME_CONSTRAINT_ERROR;
    2050           0 :     for (i = 0; i < c->u.rdnSequence.len; i++) {
    2051           0 :         ret = match_RDN(&c->u.rdnSequence.val[i], &n->u.rdnSequence.val[i]);
    2052           0 :         if (ret)
    2053           0 :             return ret;
    2054             :     }
    2055           0 :     return 0;
    2056             : }
    2057             : 
    2058             : 
    2059             : static int
    2060           0 : match_general_name(const GeneralName *c, const GeneralName *n, int *match)
    2061             : {
    2062             :     /*
    2063             :      * Name constraints only apply to the same name type, see RFC3280,
    2064             :      * 4.2.1.11.
    2065             :      */
    2066           0 :     assert(c->element == n->element);
    2067             : 
    2068           0 :     switch(c->element) {
    2069           0 :     case choice_GeneralName_otherName:
    2070           0 :         if (der_heim_oid_cmp(&c->u.otherName.type_id,
    2071             :                          &n->u.otherName.type_id) != 0)
    2072           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2073           0 :         if (heim_any_cmp(&c->u.otherName.value,
    2074           0 :                          &n->u.otherName.value) != 0)
    2075           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2076           0 :         *match = 1;
    2077           0 :         return 0;
    2078           0 :     case choice_GeneralName_rfc822Name: {
    2079           0 :         const char *s;
    2080           0 :         size_t len1, len2;
    2081           0 :         s = memchr(c->u.rfc822Name.data, '@', c->u.rfc822Name.length);
    2082           0 :         if (s) {
    2083           0 :             if (der_printable_string_cmp(&c->u.rfc822Name, &n->u.rfc822Name) != 0)
    2084           0 :                 return HX509_NAME_CONSTRAINT_ERROR;
    2085             :         } else {
    2086           0 :             s = memchr(n->u.rfc822Name.data, '@', n->u.rfc822Name.length);
    2087           0 :             if (s == NULL)
    2088           0 :                 return HX509_NAME_CONSTRAINT_ERROR;
    2089           0 :             len1 = c->u.rfc822Name.length;
    2090           0 :             len2 = n->u.rfc822Name.length -
    2091           0 :                 (s - ((char *)n->u.rfc822Name.data));
    2092           0 :             if (len1 > len2)
    2093           0 :                 return HX509_NAME_CONSTRAINT_ERROR;
    2094           0 :             if (memcmp(s + 1 + len2 - len1, c->u.rfc822Name.data, len1) != 0)
    2095           0 :                 return HX509_NAME_CONSTRAINT_ERROR;
    2096           0 :             if (len1 < len2 && s[len2 - len1 + 1] != '.')
    2097           0 :                 return HX509_NAME_CONSTRAINT_ERROR;
    2098             :         }
    2099           0 :         *match = 1;
    2100           0 :         return 0;
    2101             :     }
    2102           0 :     case choice_GeneralName_dNSName: {
    2103           0 :         size_t lenc, lenn;
    2104           0 :         char *ptr;
    2105             : 
    2106           0 :         lenc = c->u.dNSName.length;
    2107           0 :         lenn = n->u.dNSName.length;
    2108           0 :         if (lenc > lenn)
    2109           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2110           0 :         ptr = n->u.dNSName.data;
    2111           0 :         if (memcmp(&ptr[lenn - lenc], c->u.dNSName.data, lenc) != 0)
    2112           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2113           0 :         if (lenn != lenc && ptr[lenn - lenc - 1] != '.')
    2114           0 :             return HX509_NAME_CONSTRAINT_ERROR;
    2115           0 :         *match = 1;
    2116           0 :         return 0;
    2117             :     }
    2118           0 :     case choice_GeneralName_directoryName: {
    2119           0 :         Name c_name, n_name;
    2120           0 :         int ret;
    2121             : 
    2122           0 :         c_name._save.data = NULL;
    2123           0 :         c_name._save.length = 0;
    2124           0 :         c_name.element = (enum Name_enum)c->u.directoryName.element;
    2125           0 :         c_name.u.rdnSequence = c->u.directoryName.u.rdnSequence;
    2126             : 
    2127           0 :         n_name._save.data = NULL;
    2128           0 :         n_name._save.length = 0;
    2129           0 :         n_name.element = (enum Name_enum)n->u.directoryName.element;
    2130           0 :         n_name.u.rdnSequence = n->u.directoryName.u.rdnSequence;
    2131             : 
    2132           0 :         ret = match_X501Name(&c_name, &n_name);
    2133           0 :         if (ret == 0)
    2134           0 :             *match = 1;
    2135           0 :         return ret;
    2136             :     }
    2137           0 :     case choice_GeneralName_uniformResourceIdentifier:
    2138             :     case choice_GeneralName_iPAddress:
    2139             :     case choice_GeneralName_registeredID:
    2140             :     default:
    2141           0 :         return HX509_NAME_CONSTRAINT_ERROR;
    2142             :     }
    2143             : }
    2144             : 
    2145             : static int
    2146           0 : match_alt_name(const GeneralName *n, const Certificate *c,
    2147             :                int *same, int *match)
    2148             : {
    2149           0 :     GeneralNames sa;
    2150           0 :     int ret = 0;
    2151           0 :     size_t i, j;
    2152             : 
    2153           0 :     i = 0;
    2154           0 :     do {
    2155           0 :         ret = find_extension_subject_alt_name(c, &i, &sa);
    2156           0 :         if (ret == HX509_EXTENSION_NOT_FOUND) {
    2157           0 :             ret = 0;
    2158           0 :             break;
    2159           0 :         } else if (ret != 0)
    2160           0 :             break;
    2161             : 
    2162           0 :         for (j = 0; j < sa.len; j++) {
    2163           0 :             if (n->element == sa.val[j].element) {
    2164           0 :                 *same = 1;
    2165           0 :                 match_general_name(n, &sa.val[j], match);
    2166             :             }
    2167             :         }
    2168           0 :         free_GeneralNames(&sa);
    2169             :     } while (1);
    2170           0 :     return ret;
    2171             : }
    2172             : 
    2173             : 
    2174             : static int
    2175           0 : match_tree(const GeneralSubtrees *t, const Certificate *c, int *match)
    2176             : {
    2177           0 :     int name, alt_name, same;
    2178           0 :     unsigned int i;
    2179           0 :     int ret = 0;
    2180             : 
    2181           0 :     name = alt_name = same = *match = 0;
    2182           0 :     for (i = 0; i < t->len; i++) {
    2183           0 :         if (t->val[i].minimum && t->val[i].maximum)
    2184           0 :             return HX509_RANGE;
    2185             : 
    2186             :         /*
    2187             :          * If the constraint apply to directoryNames, test is with
    2188             :          * subjectName of the certificate if the certificate have a
    2189             :          * non-null (empty) subjectName.
    2190             :          */
    2191             : 
    2192           0 :         if (t->val[i].base.element == choice_GeneralName_directoryName
    2193           0 :             && !subject_null_p(c))
    2194             :         {
    2195           0 :             GeneralName certname;
    2196             : 
    2197           0 :             memset(&certname, 0, sizeof(certname));
    2198           0 :             certname.element = choice_GeneralName_directoryName;
    2199           0 :             certname.u.directoryName.element = (enum Name_enum)
    2200           0 :                 c->tbsCertificate.subject.element;
    2201           0 :             certname.u.directoryName.u.rdnSequence =
    2202             :                 c->tbsCertificate.subject.u.rdnSequence;
    2203             : 
    2204           0 :             match_general_name(&t->val[i].base, &certname, &name);
    2205             :         }
    2206             : 
    2207             :         /* Handle subjectAltNames, this is icky since they
    2208             :          * restrictions only apply if the subjectAltName is of the
    2209             :          * same type. So if there have been a match of type, require
    2210             :          * altname to be set.
    2211             :          */
    2212           0 :         match_alt_name(&t->val[i].base, c, &same, &alt_name);
    2213             :     }
    2214           0 :     if (name && (!same || alt_name))
    2215           0 :         *match = 1;
    2216           0 :     return ret;
    2217             : }
    2218             : 
    2219             : static int
    2220          74 : check_name_constraints(hx509_context context,
    2221             :                        const hx509_name_constraints *nc,
    2222             :                        const Certificate *c)
    2223             : {
    2224           0 :     int match, ret;
    2225           0 :     size_t i;
    2226             : 
    2227          74 :     for (i = 0 ; i < nc->len; i++) {
    2228           0 :         GeneralSubtrees gs;
    2229             : 
    2230           0 :         if (nc->val[i].permittedSubtrees) {
    2231           0 :             GeneralSubtrees_SET(&gs, nc->val[i].permittedSubtrees);
    2232           0 :             ret = match_tree(&gs, c, &match);
    2233           0 :             if (ret) {
    2234           0 :                 hx509_clear_error_string(context);
    2235           0 :                 return ret;
    2236             :             }
    2237             :             /* allow null subjectNames, they wont matches anything */
    2238           0 :             if (match == 0 && !subject_null_p(c)) {
    2239           0 :                 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
    2240             :                                        "Error verifying constraints: "
    2241             :                                        "certificate didn't match any "
    2242             :                                        "permitted subtree");
    2243           0 :                 return HX509_VERIFY_CONSTRAINTS;
    2244             :             }
    2245             :         }
    2246           0 :         if (nc->val[i].excludedSubtrees) {
    2247           0 :             GeneralSubtrees_SET(&gs, nc->val[i].excludedSubtrees);
    2248           0 :             ret = match_tree(&gs, c, &match);
    2249           0 :             if (ret) {
    2250           0 :                 hx509_clear_error_string(context);
    2251           0 :                 return ret;
    2252             :             }
    2253           0 :             if (match) {
    2254           0 :                 hx509_set_error_string(context, 0, HX509_VERIFY_CONSTRAINTS,
    2255             :                                        "Error verifying constraints: "
    2256             :                                        "certificate included in excluded "
    2257             :                                        "subtree");
    2258           0 :                 return HX509_VERIFY_CONSTRAINTS;
    2259             :             }
    2260             :         }
    2261             :     }
    2262          74 :     return 0;
    2263             : }
    2264             : 
    2265             : static void
    2266          74 : free_name_constraints(hx509_name_constraints *nc)
    2267             : {
    2268           0 :     size_t i;
    2269             : 
    2270          74 :     for (i = 0 ; i < nc->len; i++)
    2271           0 :         free_NameConstraints(&nc->val[i]);
    2272          74 :     free(nc->val);
    2273          74 : }
    2274             : 
    2275             : /**
    2276             :  * Build and verify the path for the certificate to the trust anchor
    2277             :  * specified in the verify context. The path is constructed from the
    2278             :  * certificate, the pool and the trust anchors.
    2279             :  *
    2280             :  * @param context A hx509 context.
    2281             :  * @param ctx A hx509 verification context.
    2282             :  * @param cert the certificate to build the path from.
    2283             :  * @param pool A keyset of certificates to build the chain from.
    2284             :  *
    2285             :  * @return An hx509 error code, see hx509_get_error_string().
    2286             :  *
    2287             :  * @ingroup hx509_verify
    2288             :  */
    2289             : 
    2290             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2291          74 : hx509_verify_path(hx509_context context,
    2292             :                   hx509_verify_ctx ctx,
    2293             :                   hx509_cert cert,
    2294             :                   hx509_certs pool)
    2295             : {
    2296           0 :     hx509_name_constraints nc;
    2297           0 :     hx509_path path;
    2298           0 :     int ret, proxy_cert_depth, selfsigned_depth, diff;
    2299           0 :     size_t i, k;
    2300           0 :     enum certtype type;
    2301           0 :     Name proxy_issuer;
    2302          74 :     hx509_certs anchors = NULL;
    2303             : 
    2304          74 :     memset(&proxy_issuer, 0, sizeof(proxy_issuer));
    2305             : 
    2306         148 :     if ((ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE) == 0 &&
    2307          74 :         is_proxy_cert(context, cert->data, NULL) == 0)
    2308             :     {
    2309           0 :         ret = HX509_PROXY_CERT_INVALID;
    2310           0 :         hx509_set_error_string(context, 0, ret,
    2311             :                                "Proxy certificate is not allowed as an EE "
    2312             :                                "certificate if proxy certificate is disabled");
    2313           0 :         return ret;
    2314             :     }
    2315             : 
    2316          74 :     ret = init_name_constraints(&nc);
    2317          74 :     if (ret)
    2318           0 :         return ret;
    2319             : 
    2320          74 :     path.val = NULL;
    2321          74 :     path.len = 0;
    2322             : 
    2323          74 :     if ((ctx->flags & HX509_VERIFY_CTX_F_TIME_SET) == 0)
    2324          13 :         ctx->time_now = time(NULL);
    2325             : 
    2326             :     /*
    2327             :      *
    2328             :      */
    2329          74 :     if (ctx->trust_anchors)
    2330          74 :         anchors = hx509_certs_ref(ctx->trust_anchors);
    2331           0 :     else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
    2332           0 :         anchors = hx509_certs_ref(context->default_trust_anchors);
    2333             :     else {
    2334           0 :         ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
    2335           0 :         if (ret)
    2336           0 :             goto out;
    2337             :     }
    2338             : 
    2339             :     /*
    2340             :      * Calculate the path from the certificate user presented to the
    2341             :      * to an anchor.
    2342             :      */
    2343          74 :     ret = _hx509_calculate_path(context, 0, ctx->time_now,
    2344             :                                 anchors, ctx->max_depth,
    2345             :                                 cert, pool, &path);
    2346          74 :     if (ret)
    2347           0 :         goto out;
    2348             : 
    2349             :     /*
    2350             :      * Check CA and proxy certificate chain from the top of the
    2351             :      * certificate chain. Also check certificate is valid with respect
    2352             :      * to the current time.
    2353             :      *
    2354             :      */
    2355             : 
    2356          74 :     proxy_cert_depth = 0;
    2357          74 :     selfsigned_depth = 0;
    2358             : 
    2359          74 :     if (ctx->flags & HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE)
    2360           0 :         type = PROXY_CERT;
    2361             :     else
    2362          74 :         type = EE_CERT;
    2363             : 
    2364         222 :     for (i = 0; i < path.len; i++) {
    2365           0 :         Certificate *c;
    2366           0 :         time_t t;
    2367             : 
    2368         148 :         c = _hx509_get_cert(path.val[i]);
    2369             : 
    2370             :         /*
    2371             :          * Lets do some basic check on issuer like
    2372             :          * keyUsage.keyCertSign and basicConstraints.cA bit depending
    2373             :          * on what type of certificate this is.
    2374             :          */
    2375             : 
    2376         148 :         switch (type) {
    2377          74 :         case CA_CERT:
    2378             : 
    2379             :             /* XXX make constants for keyusage */
    2380          74 :             ret = check_key_usage(context, c, 1 << 5,
    2381          74 :                                   REQUIRE_RFC3280(ctx) ? TRUE : FALSE);
    2382          74 :             if (ret) {
    2383           0 :                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
    2384             :                                        "Key usage missing from CA certificate");
    2385           0 :                 goto out;
    2386             :             }
    2387             : 
    2388             :             /* self signed cert doesn't add to path length */
    2389          74 :             if (i + 1 != path.len) {
    2390           0 :                 int selfsigned;
    2391             : 
    2392           0 :                 ret = certificate_is_self_signed(context, c, &selfsigned);
    2393           0 :                 if (ret)
    2394           0 :                     goto out;
    2395           0 :                 if (selfsigned)
    2396           0 :                     selfsigned_depth++;
    2397             :             }
    2398             : 
    2399          74 :             break;
    2400           0 :         case PROXY_CERT: {
    2401           0 :             ProxyCertInfo info;
    2402             : 
    2403           0 :             if (is_proxy_cert(context, c, &info) == 0) {
    2404           0 :                 size_t j;
    2405             : 
    2406           0 :                 if (info.pCPathLenConstraint != NULL &&
    2407           0 :                     *info.pCPathLenConstraint < i)
    2408             :                 {
    2409           0 :                     free_ProxyCertInfo(&info);
    2410           0 :                     ret = HX509_PATH_TOO_LONG;
    2411           0 :                     hx509_set_error_string(context, 0, ret,
    2412             :                                            "Proxy certificate chain "
    2413             :                                            "longer than allowed");
    2414           0 :                     goto out;
    2415             :                 }
    2416             :                 /* XXX MUST check info.proxyPolicy */
    2417           0 :                 free_ProxyCertInfo(&info);
    2418             : 
    2419           0 :                 j = 0;
    2420           0 :                 if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) {
    2421           0 :                     ret = HX509_PROXY_CERT_INVALID;
    2422           0 :                     hx509_set_error_string(context, 0, ret,
    2423             :                                            "Proxy certificate has explicitly "
    2424             :                                            "forbidden subjectAltName");
    2425           0 :                     goto out;
    2426             :                 }
    2427             : 
    2428           0 :                 j = 0;
    2429           0 :                 if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) {
    2430           0 :                     ret = HX509_PROXY_CERT_INVALID;
    2431           0 :                     hx509_set_error_string(context, 0, ret,
    2432             :                                            "Proxy certificate has explicitly "
    2433             :                                            "forbidden issuerAltName");
    2434           0 :                     goto out;
    2435             :                 }
    2436             : 
    2437             :                 /*
    2438             :                  * The subject name of the proxy certificate should be
    2439             :                  * CN=XXX,<proxy issuer>. Prune off CN and check if it's
    2440             :                  * the same over the whole chain of proxy certs and
    2441             :                  * then check with the EE cert when we get to it.
    2442             :                  */
    2443             : 
    2444           0 :                 if (proxy_cert_depth) {
    2445           0 :                     ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.subject, &diff);
    2446           0 :                     if (ret) {
    2447           0 :                         hx509_set_error_string(context, 0, ret, "Out of memory");
    2448           0 :                         goto out;
    2449             :                     }
    2450           0 :                     if (diff) {
    2451           0 :                         ret = HX509_PROXY_CERT_NAME_WRONG;
    2452           0 :                         hx509_set_error_string(context, 0, ret,
    2453             :                                                "Base proxy name not right");
    2454           0 :                         goto out;
    2455             :                     }
    2456             :                 }
    2457             : 
    2458           0 :                 free_Name(&proxy_issuer);
    2459             : 
    2460           0 :                 ret = copy_Name(&c->tbsCertificate.subject, &proxy_issuer);
    2461           0 :                 if (ret) {
    2462           0 :                     hx509_clear_error_string(context);
    2463           0 :                     goto out;
    2464             :                 }
    2465             : 
    2466           0 :                 j = proxy_issuer.u.rdnSequence.len;
    2467           0 :                 if (proxy_issuer.u.rdnSequence.len < 2
    2468           0 :                     || proxy_issuer.u.rdnSequence.val[j - 1].len > 1
    2469           0 :                     || der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
    2470             :                                         &asn1_oid_id_at_commonName))
    2471             :                 {
    2472           0 :                     ret = HX509_PROXY_CERT_NAME_WRONG;
    2473           0 :                     hx509_set_error_string(context, 0, ret,
    2474             :                                            "Proxy name too short or "
    2475             :                                            "does not have Common name "
    2476             :                                            "at the top");
    2477           0 :                     goto out;
    2478             :                 }
    2479             : 
    2480           0 :                 free_RelativeDistinguishedName(&proxy_issuer.u.rdnSequence.val[j - 1]);
    2481           0 :                 proxy_issuer.u.rdnSequence.len -= 1;
    2482             : 
    2483           0 :                 ret = _hx509_name_cmp(&proxy_issuer, &c->tbsCertificate.issuer, &diff);
    2484           0 :                 if (ret) {
    2485           0 :                     hx509_set_error_string(context, 0, ret, "Out of memory");
    2486           0 :                     goto out;
    2487             :                 }
    2488           0 :                 if (diff != 0) {
    2489           0 :                     ret = HX509_PROXY_CERT_NAME_WRONG;
    2490           0 :                     hx509_set_error_string(context, 0, ret,
    2491             :                                            "Proxy issuer name not as expected");
    2492           0 :                     goto out;
    2493             :                 }
    2494             : 
    2495           0 :                 break;
    2496             :             } else {
    2497             :                 /*
    2498             :                  * Now we are done with the proxy certificates, this
    2499             :                  * cert was an EE cert and we will fall though to
    2500             :                  * EE checking below.
    2501             :                  */
    2502           0 :                 type = EE_CERT;
    2503             :             }
    2504             :         }
    2505           0 :         HEIM_FALLTHROUGH;
    2506             :         case EE_CERT:
    2507             :             /*
    2508             :              * If there were any proxy certificates in the chain
    2509             :              * (proxy_cert_depth > 0), check that the proxy issuer
    2510             :              * matched the proxy certificate's "base" subject.
    2511             :              */
    2512          74 :             if (proxy_cert_depth) {
    2513             : 
    2514           0 :                 ret = _hx509_name_cmp(&proxy_issuer,
    2515           0 :                                       &c->tbsCertificate.subject, &diff);
    2516           0 :                 if (ret) {
    2517           0 :                     hx509_set_error_string(context, 0, ret, "out of memory");
    2518           0 :                     goto out;
    2519             :                 }
    2520           0 :                 if (diff) {
    2521           0 :                     ret = HX509_PROXY_CERT_NAME_WRONG;
    2522           0 :                     hx509_clear_error_string(context);
    2523           0 :                     goto out;
    2524             :                 }
    2525           0 :                 if (cert->basename)
    2526           0 :                     hx509_name_free(&cert->basename);
    2527             : 
    2528           0 :                 ret = _hx509_name_from_Name(&proxy_issuer, &cert->basename);
    2529           0 :                 if (ret) {
    2530           0 :                     hx509_clear_error_string(context);
    2531           0 :                     goto out;
    2532             :                 }
    2533             :             }
    2534             : 
    2535          74 :             break;
    2536             :         }
    2537             : 
    2538         148 :         ret = check_basic_constraints(context, c, type,
    2539         148 :                                       i - proxy_cert_depth - selfsigned_depth);
    2540         148 :         if (ret)
    2541           0 :             goto out;
    2542             : 
    2543             :         /*
    2544             :          * Don't check the trust anchors expiration time since they
    2545             :          * are transported out of band, from RFC3820.
    2546             :          */
    2547         148 :         if (i + 1 != path.len || CHECK_TA(ctx)) {
    2548             : 
    2549          74 :             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
    2550          74 :             if (t > ctx->time_now) {
    2551           0 :                 ret = HX509_CERT_USED_BEFORE_TIME;
    2552           0 :                 hx509_clear_error_string(context);
    2553           0 :                 goto out;
    2554             :             }
    2555          74 :             t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
    2556          74 :             if (t < ctx->time_now) {
    2557           0 :                 ret = HX509_CERT_USED_AFTER_TIME;
    2558           0 :                 hx509_clear_error_string(context);
    2559           0 :                 goto out;
    2560             :             }
    2561             :         }
    2562             : 
    2563         148 :         if (type == EE_CERT)
    2564          74 :             type = CA_CERT;
    2565          74 :         else if (type == PROXY_CERT)
    2566           0 :             proxy_cert_depth++;
    2567             :     }
    2568             : 
    2569             :     /*
    2570             :      * Verify constraints, do this backward so path constraints are
    2571             :      * checked in the right order.
    2572             :      */
    2573             : 
    2574         222 :     for (ret = 0, k = path.len; k > 0; k--) {
    2575           0 :         Certificate *c;
    2576           0 :         int selfsigned;
    2577         148 :         i = k - 1;
    2578             : 
    2579         148 :         c = _hx509_get_cert(path.val[i]);
    2580             : 
    2581         148 :         ret = certificate_is_self_signed(context, c, &selfsigned);
    2582         148 :         if (ret)
    2583           0 :             goto out;
    2584             : 
    2585             :         /* verify name constraints, not for selfsigned and anchor */
    2586         148 :         if (!selfsigned || i + 1 != path.len) {
    2587          74 :             ret = check_name_constraints(context, &nc, c);
    2588          74 :             if (ret) {
    2589           0 :                 goto out;
    2590             :             }
    2591             :         }
    2592         148 :         ret = add_name_constraints(context, c, i == 0, &nc);
    2593         148 :         if (ret)
    2594           0 :             goto out;
    2595             : 
    2596             :         /* XXX verify all other silly constraints */
    2597             : 
    2598             :     }
    2599             : 
    2600             :     /*
    2601             :      * Verify that no certificates have been revoked.
    2602             :      */
    2603             : 
    2604          74 :     if (ctx->revoke_ctx) {
    2605           0 :         hx509_certs certs;
    2606             : 
    2607          61 :         ret = hx509_certs_init(context, "MEMORY:revoke-certs", 0,
    2608             :                                NULL, &certs);
    2609          61 :         if (ret)
    2610           2 :             goto out;
    2611             : 
    2612         183 :         for (i = 0; i < path.len; i++) {
    2613         122 :             ret = hx509_certs_add(context, certs, path.val[i]);
    2614         122 :             if (ret) {
    2615           0 :                 hx509_certs_free(&certs);
    2616           0 :                 goto out;
    2617             :             }
    2618             :         }
    2619          61 :         ret = hx509_certs_merge(context, certs, pool);
    2620          61 :         if (ret) {
    2621           0 :             hx509_certs_free(&certs);
    2622           0 :             goto out;
    2623             :         }
    2624             : 
    2625         120 :         for (i = 0; i < path.len - 1; i++) {
    2626          61 :             size_t parent = (i < path.len - 1) ? i + 1 : i;
    2627             : 
    2628          61 :             ret = hx509_revoke_verify(context,
    2629             :                                       ctx->revoke_ctx,
    2630             :                                       certs,
    2631             :                                       ctx->time_now,
    2632          61 :                                       path.val[i],
    2633          61 :                                       path.val[parent]);
    2634          61 :             if (ret) {
    2635           2 :                 hx509_certs_free(&certs);
    2636           2 :                 goto out;
    2637             :             }
    2638             :         }
    2639          59 :         hx509_certs_free(&certs);
    2640             :     }
    2641             : 
    2642             :     /*
    2643             :      * Verify signatures, do this backward so public key working
    2644             :      * parameter is passed up from the anchor up though the chain.
    2645             :      */
    2646             : 
    2647         216 :     for (k = path.len; k > 0; k--) {
    2648           0 :         hx509_cert signer;
    2649           0 :         Certificate *c;
    2650         144 :         i = k - 1;
    2651             : 
    2652         144 :         c = _hx509_get_cert(path.val[i]);
    2653             : 
    2654             :         /* is last in chain (trust anchor) */
    2655         144 :         if (i + 1 == path.len) {
    2656           0 :             int selfsigned;
    2657             : 
    2658          72 :             signer = path.val[i];
    2659             : 
    2660          72 :             ret = certificate_is_self_signed(context, signer->data, &selfsigned);
    2661          72 :             if (ret)
    2662           0 :                 goto out;
    2663             : 
    2664             :             /* if trust anchor is not self signed, don't check sig */
    2665          72 :             if (!selfsigned)
    2666           0 :                 continue;
    2667             :         } else {
    2668             :             /* take next certificate in chain */
    2669          72 :             signer = path.val[i + 1];
    2670             :         }
    2671             : 
    2672             :         /* verify signatureValue */
    2673         144 :         ret = _hx509_verify_signature_bitstring(context,
    2674             :                                                 signer,
    2675         144 :                                                 &c->signatureAlgorithm,
    2676         144 :                                                 &c->tbsCertificate._save,
    2677         144 :                                                 &c->signatureValue);
    2678         144 :         if (ret) {
    2679           0 :             hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
    2680             :                                    "Failed to verify signature of certificate");
    2681           0 :             goto out;
    2682             :         }
    2683             :         /*
    2684             :          * Verify that the signature algorithm is not weak. Ignore
    2685             :          * trust anchors since they are provisioned by the user.
    2686             :          */
    2687             : 
    2688         144 :         if (i + 1 != path.len && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
    2689          72 :             ret = _hx509_signature_is_weak(context, &c->signatureAlgorithm);
    2690          72 :             if (ret)
    2691           0 :                 goto out;
    2692             :         }
    2693             :     }
    2694             : 
    2695          72 : out:
    2696          74 :     hx509_certs_free(&anchors);
    2697          74 :     free_Name(&proxy_issuer);
    2698          74 :     free_name_constraints(&nc);
    2699          74 :     _hx509_path_free(&path);
    2700             : 
    2701          74 :     return ret;
    2702             : }
    2703             : 
    2704             : /**
    2705             :  * Verify a signature made using the private key of an certificate.
    2706             :  *
    2707             :  * @param context A hx509 context.
    2708             :  * @param signer the certificate that made the signature.
    2709             :  * @param alg algorthm that was used to sign the data.
    2710             :  * @param data the data that was signed.
    2711             :  * @param sig the signature to verify.
    2712             :  *
    2713             :  * @return An hx509 error code, see hx509_get_error_string().
    2714             :  *
    2715             :  * @ingroup hx509_crypto
    2716             :  */
    2717             : 
    2718             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2719          74 : hx509_verify_signature(hx509_context context,
    2720             :                        const hx509_cert signer,
    2721             :                        const AlgorithmIdentifier *alg,
    2722             :                        const heim_octet_string *data,
    2723             :                        const heim_octet_string *sig)
    2724             : {
    2725          74 :     return _hx509_verify_signature(context, signer, alg, data, sig);
    2726             : }
    2727             : 
    2728             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2729         151 : _hx509_verify_signature_bitstring(hx509_context context,
    2730             :                                   const hx509_cert signer,
    2731             :                                   const AlgorithmIdentifier *alg,
    2732             :                                   const heim_octet_string *data,
    2733             :                                   const heim_bit_string *sig)
    2734             : {
    2735           0 :     heim_octet_string os;
    2736             : 
    2737         151 :     if (sig->length & 7) {
    2738           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_SIG_INVALID_FORMAT,
    2739             :                                "signature not multiple of 8 bits");
    2740           0 :         return HX509_CRYPTO_SIG_INVALID_FORMAT;
    2741             :     }
    2742             : 
    2743         151 :     os.data = sig->data;
    2744         151 :     os.length = sig->length / 8;
    2745             : 
    2746         151 :     return _hx509_verify_signature(context, signer, alg, data, &os);
    2747             : }
    2748             : 
    2749             : 
    2750             : 
    2751             : /**
    2752             :  * Verify that the certificate is allowed to be used for the hostname
    2753             :  * and address.
    2754             :  *
    2755             :  * @param context A hx509 context.
    2756             :  * @param cert the certificate to match with
    2757             :  * @param flags Flags to modify the behavior:
    2758             :  * - HX509_VHN_F_ALLOW_NO_MATCH no match is ok
    2759             :  * @param type type of hostname:
    2760             :  * - HX509_HN_HOSTNAME for plain hostname.
    2761             :  * - HX509_HN_DNSSRV for DNS SRV names.
    2762             :  * @param hostname the hostname to check
    2763             :  * @param sa address of the host
    2764             :  * @param sa_size length of address
    2765             :  *
    2766             :  * @return An hx509 error code, see hx509_get_error_string().
    2767             :  *
    2768             :  * @ingroup hx509_cert
    2769             :  */
    2770             : 
    2771             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2772           0 : hx509_verify_hostname(hx509_context context,
    2773             :                       const hx509_cert cert,
    2774             :                       int flags,
    2775             :                       hx509_hostname_type type,
    2776             :                       const char *hostname,
    2777             :                       const struct sockaddr *sa,
    2778             :                       /* XXX krb5_socklen_t */ int sa_size)
    2779             : {
    2780           0 :     GeneralNames san;
    2781           0 :     const Name *name;
    2782           0 :     int ret;
    2783           0 :     size_t i, j, k;
    2784             : 
    2785           0 :     if (sa && sa_size <= 0)
    2786           0 :         return EINVAL;
    2787             : 
    2788           0 :     memset(&san, 0, sizeof(san));
    2789             : 
    2790           0 :     i = 0;
    2791           0 :     do {
    2792           0 :         ret = find_extension_subject_alt_name(cert->data, &i, &san);
    2793           0 :         if (ret == HX509_EXTENSION_NOT_FOUND)
    2794           0 :             break;
    2795           0 :         else if (ret != 0)
    2796           0 :             return HX509_PARSING_NAME_FAILED;
    2797             : 
    2798           0 :         for (j = 0; j < san.len; j++) {
    2799           0 :             switch (san.val[j].element) {
    2800           0 :             case choice_GeneralName_dNSName: {
    2801           0 :                 heim_printable_string hn;
    2802           0 :                 hn.data = rk_UNCONST(hostname);
    2803           0 :                 hn.length = strlen(hostname);
    2804             : 
    2805           0 :                 if (der_printable_string_cmp(&san.val[j].u.dNSName, &hn) == 0) {
    2806           0 :                     free_GeneralNames(&san);
    2807           0 :                     return 0;
    2808             :                 }
    2809           0 :                 break;
    2810             :             }
    2811           0 :             default:
    2812           0 :                 break;
    2813             :             }
    2814             :         }
    2815           0 :         free_GeneralNames(&san);
    2816             :     } while (1);
    2817             : 
    2818           0 :     name = &cert->data->tbsCertificate.subject;
    2819             : 
    2820             :     /* Find first CN= in the name, and try to match the hostname on that */
    2821           0 :     for (ret = 0, k = name->u.rdnSequence.len; ret == 0 && k > 0; k--) {
    2822           0 :         i = k - 1;
    2823           0 :         for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) {
    2824           0 :             AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j];
    2825             : 
    2826           0 :             if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
    2827           0 :                 DirectoryString *ds = &n->value;
    2828           0 :                 switch (ds->element) {
    2829           0 :                 case choice_DirectoryString_printableString: {
    2830           0 :                     heim_printable_string hn;
    2831           0 :                     hn.data = rk_UNCONST(hostname);
    2832           0 :                     hn.length = strlen(hostname);
    2833             : 
    2834           0 :                     if (der_printable_string_cmp(&ds->u.printableString, &hn) == 0)
    2835           0 :                         return 0;
    2836           0 :                     break;
    2837             :                 }
    2838           0 :                 case choice_DirectoryString_ia5String: {
    2839           0 :                     heim_ia5_string hn;
    2840           0 :                     hn.data = rk_UNCONST(hostname);
    2841           0 :                     hn.length = strlen(hostname);
    2842             : 
    2843           0 :                     if (der_ia5_string_cmp(&ds->u.ia5String, &hn) == 0)
    2844           0 :                         return 0;
    2845           0 :                     break;
    2846             :                 }
    2847           0 :                 case choice_DirectoryString_utf8String:
    2848           0 :                     if (strcasecmp(ds->u.utf8String, hostname) == 0)
    2849           0 :                         return 0;
    2850             :                 default:
    2851           0 :                     break;
    2852             :                 }
    2853           0 :                 ret = HX509_NAME_CONSTRAINT_ERROR;
    2854             :             }
    2855             :         }
    2856             :     }
    2857             : 
    2858           0 :     if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
    2859           0 :         ret = HX509_NAME_CONSTRAINT_ERROR;
    2860             : 
    2861           0 :     return ret;
    2862             : }
    2863             : 
    2864             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2865           0 : _hx509_set_cert_attribute(hx509_context context,
    2866             :                           hx509_cert cert,
    2867             :                           const heim_oid *oid,
    2868             :                           const heim_octet_string *attr)
    2869             : {
    2870           0 :     hx509_cert_attribute a;
    2871           0 :     void *d;
    2872           0 :     int ret;
    2873             : 
    2874             :     /*
    2875             :      * TODO: Rewrite this (and hx509_cert_attribute, and _hx509_cert_attrs) to
    2876             :      * use the add_AttributeValues() util generated by asn1_compile.
    2877             :      */
    2878             : 
    2879           0 :     if (hx509_cert_get_attribute(cert, oid) != NULL)
    2880           0 :         return 0;
    2881             : 
    2882           0 :     d = realloc(cert->attrs.val,
    2883           0 :                 sizeof(cert->attrs.val[0]) * (cert->attrs.len + 1));
    2884           0 :     if (d == NULL) {
    2885           0 :         hx509_clear_error_string(context);
    2886           0 :         return ENOMEM;
    2887             :     }
    2888           0 :     cert->attrs.val = d;
    2889             : 
    2890           0 :     a = malloc(sizeof(*a));
    2891           0 :     if (a == NULL)
    2892           0 :         return ENOMEM;
    2893             : 
    2894           0 :     ret = der_copy_octet_string(attr, &a->data);
    2895           0 :     if (ret == 0)
    2896           0 :         ret = der_copy_oid(oid, &a->oid);
    2897           0 :     if (ret == 0) {
    2898           0 :         cert->attrs.val[cert->attrs.len] = a;
    2899           0 :         cert->attrs.len++;
    2900             :     } else {
    2901           0 :         der_free_octet_string(&a->data);
    2902           0 :         free(a);
    2903             :     }
    2904             : 
    2905           0 :     return ret;
    2906             : }
    2907             : 
    2908             : /**
    2909             :  * Get an external attribute for the certificate, examples are
    2910             :  * friendly name and id.
    2911             :  *
    2912             :  * @param cert hx509 certificate object to search
    2913             :  * @param oid an oid to search for.
    2914             :  *
    2915             :  * @return an hx509_cert_attribute, only valid as long as the
    2916             :  * certificate is referenced.
    2917             :  *
    2918             :  * @ingroup hx509_cert
    2919             :  */
    2920             : 
    2921             : HX509_LIB_FUNCTION hx509_cert_attribute HX509_LIB_CALL
    2922           0 : hx509_cert_get_attribute(hx509_cert cert, const heim_oid *oid)
    2923             : {
    2924           0 :     size_t i;
    2925           0 :     for (i = 0; i < cert->attrs.len; i++)
    2926           0 :         if (der_heim_oid_cmp(oid, &cert->attrs.val[i]->oid) == 0)
    2927           0 :             return cert->attrs.val[i];
    2928           0 :     return NULL;
    2929             : }
    2930             : 
    2931             : /**
    2932             :  * Set the friendly name on the certificate.
    2933             :  *
    2934             :  * @param cert The certificate to set the friendly name on
    2935             :  * @param name Friendly name.
    2936             :  *
    2937             :  * @return An hx509 error code, see hx509_get_error_string().
    2938             :  *
    2939             :  * @ingroup hx509_cert
    2940             :  */
    2941             : 
    2942             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    2943           0 : hx509_cert_set_friendly_name(hx509_cert cert, const char *name)
    2944             : {
    2945           0 :     if (cert->friendlyname)
    2946           0 :         free(cert->friendlyname);
    2947           0 :     cert->friendlyname = strdup(name);
    2948           0 :     if (cert->friendlyname == NULL)
    2949           0 :         return ENOMEM;
    2950           0 :     return 0;
    2951             : }
    2952             : 
    2953             : /**
    2954             :  * Get friendly name of the certificate.
    2955             :  *
    2956             :  * @param cert cert to get the friendly name from.
    2957             :  *
    2958             :  * @return an friendly name or NULL if there is. The friendly name is
    2959             :  * only valid as long as the certificate is referenced.
    2960             :  *
    2961             :  * @ingroup hx509_cert
    2962             :  */
    2963             : 
    2964             : HX509_LIB_FUNCTION const char * HX509_LIB_CALL
    2965           0 : hx509_cert_get_friendly_name(hx509_cert cert)
    2966             : {
    2967           0 :     hx509_cert_attribute a;
    2968           0 :     PKCS9_friendlyName n;
    2969           0 :     size_t sz;
    2970           0 :     int ret;
    2971           0 :     size_t i;
    2972             : 
    2973           0 :     if (cert->friendlyname)
    2974           0 :         return cert->friendlyname;
    2975             : 
    2976           0 :     a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName);
    2977           0 :     if (a == NULL) {
    2978           0 :         hx509_name name;
    2979             : 
    2980           0 :         ret = hx509_cert_get_subject(cert, &name);
    2981           0 :         if (ret)
    2982           0 :             return NULL;
    2983           0 :         ret = hx509_name_to_string(name, &cert->friendlyname);
    2984           0 :         hx509_name_free(&name);
    2985           0 :         if (ret)
    2986           0 :             return NULL;
    2987           0 :         return cert->friendlyname;
    2988             :     }
    2989             : 
    2990           0 :     ret = decode_PKCS9_friendlyName(a->data.data, a->data.length, &n, &sz);
    2991           0 :     if (ret)
    2992           0 :         return NULL;
    2993             : 
    2994           0 :     if (n.len != 1) {
    2995           0 :         free_PKCS9_friendlyName(&n);
    2996           0 :         return NULL;
    2997             :     }
    2998             : 
    2999           0 :     cert->friendlyname = malloc(n.val[0].length + 1);
    3000           0 :     if (cert->friendlyname == NULL) {
    3001           0 :         free_PKCS9_friendlyName(&n);
    3002           0 :         return NULL;
    3003             :     }
    3004             : 
    3005           0 :     for (i = 0; i < n.val[0].length; i++) {
    3006           0 :         if (n.val[0].data[i] <= 0xff)
    3007           0 :             cert->friendlyname[i] = n.val[0].data[i] & 0xff;
    3008             :         else
    3009           0 :             cert->friendlyname[i] = 'X';
    3010             :     }
    3011           0 :     cert->friendlyname[i] = '\0';
    3012           0 :     free_PKCS9_friendlyName(&n);
    3013             : 
    3014           0 :     return cert->friendlyname;
    3015             : }
    3016             : 
    3017             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3018         381 : _hx509_query_clear(hx509_query *q)
    3019             : {
    3020         381 :     memset(q, 0, sizeof(*q));
    3021         381 : }
    3022             : 
    3023             : /**
    3024             :  * Allocate an query controller. Free using hx509_query_free().
    3025             :  *
    3026             :  * @param context A hx509 context.
    3027             :  * @param q return pointer to a hx509_query.
    3028             :  *
    3029             :  * @return An hx509 error code, see hx509_get_error_string().
    3030             :  *
    3031             :  * @ingroup hx509_cert
    3032             :  */
    3033             : 
    3034             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3035         134 : hx509_query_alloc(hx509_context context, hx509_query **q)
    3036             : {
    3037         134 :     *q = calloc(1, sizeof(**q));
    3038         134 :     if (*q == NULL)
    3039           0 :         return ENOMEM;
    3040         126 :     return 0;
    3041             : }
    3042             : 
    3043             : 
    3044             : /**
    3045             :  * Set match options for the hx509 query controller.
    3046             :  *
    3047             :  * @param q query controller.
    3048             :  * @param option options to control the query controller.
    3049             :  *
    3050             :  * @return An hx509 error code, see hx509_get_error_string().
    3051             :  *
    3052             :  * @ingroup hx509_cert
    3053             :  */
    3054             : 
    3055             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3056         139 : hx509_query_match_option(hx509_query *q, hx509_query_option option)
    3057             : {
    3058         139 :     switch(option) {
    3059         119 :     case HX509_QUERY_OPTION_PRIVATE_KEY:
    3060         119 :         q->match |= HX509_QUERY_PRIVATE_KEY;
    3061         119 :         break;
    3062           0 :     case HX509_QUERY_OPTION_KU_ENCIPHERMENT:
    3063           0 :         q->match |= HX509_QUERY_KU_ENCIPHERMENT;
    3064           0 :         break;
    3065          20 :     case HX509_QUERY_OPTION_KU_DIGITALSIGNATURE:
    3066          20 :         q->match |= HX509_QUERY_KU_DIGITALSIGNATURE;
    3067          20 :         break;
    3068           0 :     case HX509_QUERY_OPTION_KU_KEYCERTSIGN:
    3069           0 :         q->match |= HX509_QUERY_KU_KEYCERTSIGN;
    3070           0 :         break;
    3071           0 :     case HX509_QUERY_OPTION_END:
    3072             :     default:
    3073           0 :         break;
    3074             :     }
    3075         139 : }
    3076             : 
    3077             : /**
    3078             :  * Set the issuer and serial number of match in the query
    3079             :  * controller. The function make copies of the isser and serial number.
    3080             :  *
    3081             :  * @param q a hx509 query controller
    3082             :  * @param issuer issuer to search for
    3083             :  * @param serialNumber the serialNumber of the issuer.
    3084             :  *
    3085             :  * @return An hx509 error code, see hx509_get_error_string().
    3086             :  *
    3087             :  * @ingroup hx509_cert
    3088             :  */
    3089             : 
    3090             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3091          15 : hx509_query_match_issuer_serial(hx509_query *q,
    3092             :                                 const Name *issuer,
    3093             :                                 const heim_integer *serialNumber)
    3094             : {
    3095           0 :     int ret;
    3096          15 :     if (q->serial) {
    3097           0 :         der_free_heim_integer(q->serial);
    3098           0 :         free(q->serial);
    3099             :     }
    3100          15 :     q->serial = malloc(sizeof(*q->serial));
    3101          15 :     if (q->serial == NULL)
    3102           0 :         return ENOMEM;
    3103          15 :     ret = der_copy_heim_integer(serialNumber, q->serial);
    3104          15 :     if (ret) {
    3105           0 :         free(q->serial);
    3106           0 :         q->serial = NULL;
    3107           0 :         return ret;
    3108             :     }
    3109          15 :     if (q->issuer_name) {
    3110           0 :         free_Name(q->issuer_name);
    3111           0 :         free(q->issuer_name);
    3112             :     }
    3113          15 :     q->issuer_name = malloc(sizeof(*q->issuer_name));
    3114          15 :     if (q->issuer_name == NULL)
    3115           0 :         return ENOMEM;
    3116          15 :     ret = copy_Name(issuer, q->issuer_name);
    3117          15 :     if (ret) {
    3118           0 :         free(q->issuer_name);
    3119           0 :         q->issuer_name = NULL;
    3120           0 :         return ret;
    3121             :     }
    3122          15 :     q->match |= HX509_QUERY_MATCH_SERIALNUMBER|HX509_QUERY_MATCH_ISSUER_NAME;
    3123          15 :     return 0;
    3124             : }
    3125             : 
    3126             : /**
    3127             :  * Set the query controller to match on a friendly name
    3128             :  *
    3129             :  * @param q a hx509 query controller.
    3130             :  * @param name a friendly name to match on
    3131             :  *
    3132             :  * @return An hx509 error code, see hx509_get_error_string().
    3133             :  *
    3134             :  * @ingroup hx509_cert
    3135             :  */
    3136             : 
    3137             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3138           0 : hx509_query_match_friendly_name(hx509_query *q, const char *name)
    3139             : {
    3140           0 :     if (q->friendlyname)
    3141           0 :         free(q->friendlyname);
    3142           0 :     q->friendlyname = strdup(name);
    3143           0 :     if (q->friendlyname == NULL)
    3144           0 :         return ENOMEM;
    3145           0 :     q->match |= HX509_QUERY_MATCH_FRIENDLY_NAME;
    3146           0 :     return 0;
    3147             : }
    3148             : 
    3149             : /**
    3150             :  * Set the query controller to require an one specific EKU (extended
    3151             :  * key usage). Any previous EKU matching is overwitten. If NULL is
    3152             :  * passed in as the eku, the EKU requirement is reset.
    3153             :  *
    3154             :  * @param q a hx509 query controller.
    3155             :  * @param eku an EKU to match on.
    3156             :  *
    3157             :  * @return An hx509 error code, see hx509_get_error_string().
    3158             :  *
    3159             :  * @ingroup hx509_cert
    3160             :  */
    3161             : 
    3162             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3163          40 : hx509_query_match_eku(hx509_query *q, const heim_oid *eku)
    3164             : {
    3165           0 :     int ret;
    3166             : 
    3167          40 :     if (eku == NULL) {
    3168           0 :         if (q->eku) {
    3169           0 :             der_free_oid(q->eku);
    3170           0 :             free(q->eku);
    3171           0 :             q->eku = NULL;
    3172             :         }
    3173           0 :         q->match &= ~HX509_QUERY_MATCH_EKU;
    3174             :     } else {
    3175          40 :         if (q->eku) {
    3176          20 :             der_free_oid(q->eku);
    3177             :         } else {
    3178          20 :             q->eku = calloc(1, sizeof(*q->eku));
    3179          20 :             if (q->eku == NULL)
    3180           0 :                 return ENOMEM;
    3181             :         }
    3182          40 :         ret = der_copy_oid(eku, q->eku);
    3183          40 :         if (ret) {
    3184           0 :             free(q->eku);
    3185           0 :             q->eku = NULL;
    3186           0 :             return ret;
    3187             :         }
    3188          40 :         q->match |= HX509_QUERY_MATCH_EKU;
    3189             :     }
    3190          40 :     return 0;
    3191             : }
    3192             : 
    3193             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3194           0 : hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
    3195             : {
    3196           0 :     if (q->expr) {
    3197           0 :         _hx509_expr_free(q->expr);
    3198           0 :         q->expr = NULL;
    3199             :     }
    3200             : 
    3201           0 :     if (expr == NULL) {
    3202           0 :         q->match &= ~HX509_QUERY_MATCH_EXPR;
    3203           0 :         return 0;
    3204             :     }
    3205             : 
    3206           0 :     q->expr = _hx509_expr_parse(expr);
    3207           0 :     if (q->expr == NULL) {
    3208           0 :         const char *reason = _hx509_expr_parse_error();
    3209             : 
    3210           0 :         hx509_set_error_string(context, 0, EINVAL,
    3211             :                                "Invalid certificate query match expression: "
    3212             :                                "%s (%s)", expr,
    3213             :                                reason ? reason : "syntax error");
    3214           0 :         return EINVAL;
    3215             :     }
    3216             : 
    3217           0 :     q->match |= HX509_QUERY_MATCH_EXPR;
    3218           0 :     return 0;
    3219             : }
    3220             : 
    3221             : /**
    3222             :  * Set the query controller to match using a specific match function.
    3223             :  *
    3224             :  * @param q a hx509 query controller.
    3225             :  * @param func function to use for matching, if the argument is NULL,
    3226             :  * the match function is removed.
    3227             :  * @param ctx context passed to the function.
    3228             :  *
    3229             :  * @return An hx509 error code, see hx509_get_error_string().
    3230             :  *
    3231             :  * @ingroup hx509_cert
    3232             :  */
    3233             : 
    3234             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3235           0 : hx509_query_match_cmp_func(hx509_query *q,
    3236             :                            int (*func)(hx509_context, hx509_cert, void *),
    3237             :                            void *ctx)
    3238             : {
    3239           0 :     if (func)
    3240           0 :         q->match |= HX509_QUERY_MATCH_FUNCTION;
    3241             :     else
    3242           0 :         q->match &= ~HX509_QUERY_MATCH_FUNCTION;
    3243           0 :     q->cmp_func = func;
    3244           0 :     q->cmp_func_ctx = ctx;
    3245           0 :     return 0;
    3246             : }
    3247             : 
    3248             : /**
    3249             :  * Free the query controller.
    3250             :  *
    3251             :  * @param context A hx509 context.
    3252             :  * @param q a pointer to the query controller.
    3253             :  *
    3254             :  * @ingroup hx509_cert
    3255             :  */
    3256             : 
    3257             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3258         134 : hx509_query_free(hx509_context context, hx509_query *q)
    3259             : {
    3260         134 :     if (q == NULL)
    3261           0 :         return;
    3262             : 
    3263         134 :     if (q->serial) {
    3264          15 :         der_free_heim_integer(q->serial);
    3265          15 :         free(q->serial);
    3266             :     }
    3267         134 :     if (q->issuer_name) {
    3268          15 :         free_Name(q->issuer_name);
    3269          15 :         free(q->issuer_name);
    3270             :     }
    3271         134 :     if (q->eku) {
    3272          20 :         der_free_oid(q->eku);
    3273          20 :         free(q->eku);
    3274             :     }
    3275         134 :     if (q->friendlyname)
    3276           0 :         free(q->friendlyname);
    3277         134 :     if (q->expr)
    3278           0 :         _hx509_expr_free(q->expr);
    3279             : 
    3280         134 :     memset(q, 0, sizeof(*q));
    3281         134 :     free(q);
    3282             : }
    3283             : 
    3284             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3285         544 : _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert cert)
    3286             : {
    3287         544 :     Certificate *c = _hx509_get_cert(cert);
    3288           8 :     int ret, diff;
    3289             : 
    3290         544 :     _hx509_query_statistic(context, 1, q);
    3291             : 
    3292         712 :     if ((q->match & HX509_QUERY_FIND_ISSUER_CERT) &&
    3293         168 :         _hx509_cert_is_parent_cmp(q->subject, c, 0) != 0)
    3294          94 :         return 0;
    3295             : 
    3296         598 :     if ((q->match & HX509_QUERY_MATCH_CERTIFICATE) &&
    3297         148 :         _hx509_Certificate_cmp(q->certificate, c) != 0)
    3298          74 :         return 0;
    3299             : 
    3300         376 :     if ((q->match & HX509_QUERY_MATCH_SERIALNUMBER)
    3301          15 :         && der_heim_integer_cmp(&c->tbsCertificate.serialNumber, q->serial) != 0)
    3302          15 :         return 0;
    3303             : 
    3304         361 :     if (q->match & HX509_QUERY_MATCH_ISSUER_NAME) {
    3305           0 :         ret = _hx509_name_cmp(&c->tbsCertificate.issuer, q->issuer_name, &diff);
    3306           0 :         if (ret || diff)
    3307           0 :             return 0;
    3308             :     }
    3309             : 
    3310         361 :     if (q->match & HX509_QUERY_MATCH_SUBJECT_NAME) {
    3311           0 :         ret = _hx509_name_cmp(&c->tbsCertificate.subject, q->subject_name, &diff);
    3312           0 :         if (ret || diff)
    3313           0 :             return 0;
    3314             :     }
    3315             : 
    3316         361 :     if (q->match & HX509_QUERY_MATCH_SUBJECT_KEY_ID) {
    3317           0 :         SubjectKeyIdentifier si;
    3318             : 
    3319          74 :         ret = _hx509_find_extension_subject_key_id(c, &si);
    3320          74 :         if (ret == 0) {
    3321          74 :             if (der_heim_octet_string_cmp(&si, q->subject_id) != 0)
    3322           0 :                 ret = 1;
    3323          74 :             free_SubjectKeyIdentifier(&si);
    3324             :         }
    3325          74 :         if (ret)
    3326           0 :             return 0;
    3327             :     }
    3328         361 :     if ((q->match & HX509_QUERY_MATCH_ISSUER_ID))
    3329           0 :         return 0;
    3330         500 :     if ((q->match & HX509_QUERY_PRIVATE_KEY) &&
    3331         139 :         _hx509_cert_private_key(cert) == NULL)
    3332           0 :         return 0;
    3333             : 
    3334             :     {
    3335         361 :         unsigned ku = 0;
    3336         361 :         if (q->match & HX509_QUERY_KU_DIGITALSIGNATURE)
    3337         114 :             ku |= (1 << 0);
    3338         361 :         if (q->match & HX509_QUERY_KU_NONREPUDIATION)
    3339           0 :             ku |= (1 << 1);
    3340         361 :         if (q->match & HX509_QUERY_KU_ENCIPHERMENT)
    3341           0 :             ku |= (1 << 2);
    3342         361 :         if (q->match & HX509_QUERY_KU_DATAENCIPHERMENT)
    3343           0 :             ku |= (1 << 3);
    3344         361 :         if (q->match & HX509_QUERY_KU_KEYAGREEMENT)
    3345           0 :             ku |= (1 << 4);
    3346         361 :         if (q->match & HX509_QUERY_KU_KEYCERTSIGN)
    3347           0 :             ku |= (1 << 5);
    3348         361 :         if (q->match & HX509_QUERY_KU_CRLSIGN)
    3349           0 :             ku |= (1 << 6);
    3350         361 :         if (ku && check_key_usage(context, c, ku, TRUE))
    3351           0 :             return 0;
    3352             :     }
    3353         361 :     if ((q->match & HX509_QUERY_ANCHOR))
    3354           0 :         return 0;
    3355             : 
    3356         361 :     if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
    3357           0 :         hx509_cert_attribute a;
    3358             : 
    3359           0 :         a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId);
    3360           0 :         if (a == NULL)
    3361           0 :             return 0;
    3362           0 :         if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
    3363           0 :             return 0;
    3364             :     }
    3365             : 
    3366         361 :     if (q->match & HX509_QUERY_NO_MATCH_PATH) {
    3367             :         size_t i;
    3368             : 
    3369         148 :         for (i = 0; i < q->path->len; i++)
    3370          74 :             if (hx509_cert_cmp(q->path->val[i], cert) == 0)
    3371           0 :                 return 0;
    3372             :     }
    3373         361 :     if (q->match & HX509_QUERY_MATCH_FRIENDLY_NAME) {
    3374           0 :         const char *name = hx509_cert_get_friendly_name(cert);
    3375           0 :         if (name == NULL)
    3376           0 :             return 0;
    3377           0 :         if (strcasecmp(q->friendlyname, name) != 0)
    3378           0 :             return 0;
    3379             :     }
    3380         361 :     if (q->match & HX509_QUERY_MATCH_FUNCTION) {
    3381           0 :         ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
    3382           0 :         if (ret != 0)
    3383           0 :             return 0;
    3384             :     }
    3385             : 
    3386         361 :     if (q->match & HX509_QUERY_MATCH_KEY_HASH_SHA1) {
    3387           0 :         heim_octet_string os;
    3388             : 
    3389           0 :         os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
    3390           0 :         os.length =
    3391           0 :             c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
    3392             : 
    3393           0 :         ret = _hx509_verify_signature(context,
    3394             :                                       NULL,
    3395             :                                       hx509_signature_sha1(),
    3396             :                                       &os,
    3397           0 :                                       q->keyhash_sha1);
    3398           0 :         if (ret != 0)
    3399           0 :             return 0;
    3400             :     }
    3401             : 
    3402         361 :     if (q->match & HX509_QUERY_MATCH_TIME) {
    3403           0 :         time_t t;
    3404          74 :         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
    3405          74 :         if (t > q->timenow)
    3406           0 :             return 0;
    3407          74 :         t = _hx509_Time2time_t(&c->tbsCertificate.validity.notAfter);
    3408          74 :         if (t < q->timenow)
    3409           0 :             return 0;
    3410             :     }
    3411             : 
    3412             :     /* If an EKU is required, check the cert for it. */
    3413         401 :     if ((q->match & HX509_QUERY_MATCH_EKU) &&
    3414          40 :         hx509_cert_check_eku(context, cert, q->eku, 0))
    3415          20 :         return 0;
    3416             : 
    3417         341 :     if ((q->match & HX509_QUERY_MATCH_EXPR)) {
    3418           0 :         hx509_env env = NULL;
    3419             : 
    3420           0 :         ret = _hx509_cert_to_env(context, cert, &env);
    3421           0 :         if (ret)
    3422           0 :             return 0;
    3423             : 
    3424           0 :         ret = _hx509_expr_eval(context, env, q->expr);
    3425           0 :         hx509_env_free(&env);
    3426           0 :         if (ret == 0)
    3427           0 :             return 0;
    3428             :     }
    3429             : 
    3430         341 :     if (q->match & ~HX509_QUERY_MASK)
    3431           0 :         return 0;
    3432             : 
    3433         333 :     return 1;
    3434             : }
    3435             : 
    3436             : /**
    3437             :  * Set a statistic file for the query statistics.
    3438             :  *
    3439             :  * @param context A hx509 context.
    3440             :  * @param fn statistics file name
    3441             :  *
    3442             :  * @ingroup hx509_cert
    3443             :  */
    3444             : 
    3445             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3446           0 : hx509_query_statistic_file(hx509_context context, const char *fn)
    3447             : {
    3448           0 :     if (context->querystat)
    3449           0 :         free(context->querystat);
    3450           0 :     context->querystat = strdup(fn);
    3451           0 : }
    3452             : 
    3453             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3454        1159 : _hx509_query_statistic(hx509_context context, int type, const hx509_query *q)
    3455             : {
    3456          16 :     FILE *f;
    3457        1159 :     if (context->querystat == NULL)
    3458        1143 :         return;
    3459           0 :     f = fopen(context->querystat, "a");
    3460           0 :     if (f == NULL)
    3461           0 :         return;
    3462           0 :     rk_cloexec_file(f);
    3463           0 :     fprintf(f, "%d %d\n", type, q->match);
    3464           0 :     fclose(f);
    3465             : }
    3466             : 
    3467             : static const char *statname[] = {
    3468             :     "find issuer cert",
    3469             :     "match serialnumber",
    3470             :     "match issuer name",
    3471             :     "match subject name",
    3472             :     "match subject key id",
    3473             :     "match issuer id",
    3474             :     "private key",
    3475             :     "ku encipherment",
    3476             :     "ku digitalsignature",
    3477             :     "ku keycertsign",
    3478             :     "ku crlsign",
    3479             :     "ku nonrepudiation",
    3480             :     "ku keyagreement",
    3481             :     "ku dataencipherment",
    3482             :     "anchor",
    3483             :     "match certificate",
    3484             :     "match local key id",
    3485             :     "no match path",
    3486             :     "match friendly name",
    3487             :     "match function",
    3488             :     "match key hash sha1",
    3489             :     "match time"
    3490             : };
    3491             : 
    3492             : struct stat_el {
    3493             :     unsigned long stats;
    3494             :     unsigned int index;
    3495             : };
    3496             : 
    3497             : 
    3498             : static int
    3499           0 : stat_sort(const void *a, const void *b)
    3500             : {
    3501           0 :     const struct stat_el *ae = a;
    3502           0 :     const struct stat_el *be = b;
    3503           0 :     return be->stats - ae->stats;
    3504             : }
    3505             : 
    3506             : /**
    3507             :  * Unparse the statistics file and print the result on a FILE descriptor.
    3508             :  *
    3509             :  * @param context A hx509 context.
    3510             :  * @param printtype tyep to print
    3511             :  * @param out the FILE to write the data on.
    3512             :  *
    3513             :  * @ingroup hx509_cert
    3514             :  */
    3515             : 
    3516             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3517           0 : hx509_query_unparse_stats(hx509_context context, int printtype, FILE *out)
    3518             : {
    3519           0 :     rtbl_t t;
    3520           0 :     FILE *f;
    3521           0 :     int type, mask, num;
    3522           0 :     size_t i;
    3523           0 :     unsigned long multiqueries = 0, totalqueries = 0;
    3524           0 :     struct stat_el stats[32];
    3525             : 
    3526           0 :     if (context->querystat == NULL)
    3527           0 :         return;
    3528           0 :     f = fopen(context->querystat, "r");
    3529           0 :     if (f == NULL) {
    3530           0 :         fprintf(out, "No statistics file %s: %s.\n",
    3531           0 :                 context->querystat, strerror(errno));
    3532           0 :         return;
    3533             :     }
    3534           0 :     rk_cloexec_file(f);
    3535             : 
    3536           0 :     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
    3537           0 :         stats[i].index = i;
    3538           0 :         stats[i].stats = 0;
    3539             :     }
    3540             : 
    3541           0 :     while (fscanf(f, "%d %d\n", &type, &mask) == 2) {
    3542           0 :         if (type != printtype)
    3543           0 :             continue;
    3544           0 :         num = i = 0;
    3545           0 :         while (mask && i < sizeof(stats)/sizeof(stats[0])) {
    3546           0 :             if (mask & 1) {
    3547           0 :                 stats[i].stats++;
    3548           0 :                 num++;
    3549             :             }
    3550           0 :             mask = mask >>1 ;
    3551           0 :             i++;
    3552             :         }
    3553           0 :         if (num > 1)
    3554           0 :             multiqueries++;
    3555           0 :         totalqueries++;
    3556             :     }
    3557           0 :     fclose(f);
    3558             : 
    3559           0 :     qsort(stats, sizeof(stats)/sizeof(stats[0]), sizeof(stats[0]), stat_sort);
    3560             : 
    3561           0 :     t = rtbl_create();
    3562           0 :     if (t == NULL)
    3563           0 :         errx(1, "out of memory");
    3564             : 
    3565           0 :     rtbl_set_separator (t, "  ");
    3566             : 
    3567           0 :     rtbl_add_column_by_id (t, 0, "Name", 0);
    3568           0 :     rtbl_add_column_by_id (t, 1, "Counter", 0);
    3569             : 
    3570             : 
    3571           0 :     for (i = 0; i < sizeof(stats)/sizeof(stats[0]); i++) {
    3572           0 :         char str[10];
    3573             : 
    3574           0 :         if (stats[i].index < sizeof(statname)/sizeof(statname[0]))
    3575           0 :             rtbl_add_column_entry_by_id (t, 0, statname[stats[i].index]);
    3576             :         else {
    3577           0 :             snprintf(str, sizeof(str), "%d", stats[i].index);
    3578           0 :             rtbl_add_column_entry_by_id (t, 0, str);
    3579             :         }
    3580           0 :         snprintf(str, sizeof(str), "%lu", stats[i].stats);
    3581           0 :         rtbl_add_column_entry_by_id (t, 1, str);
    3582             :     }
    3583             : 
    3584           0 :     rtbl_format(t, out);
    3585           0 :     rtbl_destroy(t);
    3586             : 
    3587           0 :     fprintf(out, "\nQueries: multi %lu total %lu\n",
    3588             :             multiqueries, totalqueries);
    3589             : }
    3590             : 
    3591             : /**
    3592             :  * Check the extended key usage on the hx509 certificate.
    3593             :  *
    3594             :  * @param context A hx509 context.
    3595             :  * @param cert A hx509 context.
    3596             :  * @param eku the EKU to check for
    3597             :  * @param allow_any_eku if the any EKU is set, allow that to be a
    3598             :  * substitute.
    3599             :  *
    3600             :  * @return An hx509 error code, see hx509_get_error_string().
    3601             :  *
    3602             :  * @ingroup hx509_cert
    3603             :  */
    3604             : 
    3605             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3606          99 : hx509_cert_check_eku(hx509_context context, hx509_cert cert,
    3607             :                      const heim_oid *eku, int allow_any_eku)
    3608             : {
    3609           8 :     ExtKeyUsage e;
    3610           8 :     int ret;
    3611           8 :     size_t i;
    3612             : 
    3613          99 :     ret = find_extension_eku(_hx509_get_cert(cert), &e);
    3614          99 :     if (ret) {
    3615           0 :         hx509_clear_error_string(context);
    3616           0 :         return ret;
    3617             :     }
    3618             : 
    3619         277 :     for (i = 0; i < e.len; i++) {
    3620         257 :         if (der_heim_oid_cmp(eku, &e.val[i]) == 0) {
    3621          79 :             free_ExtKeyUsage(&e);
    3622          79 :             return 0;
    3623             :         }
    3624         178 :         if (allow_any_eku) {
    3625           0 :             if (der_heim_oid_cmp(&asn1_oid_id_x509_ce_anyExtendedKeyUsage,
    3626           0 :                                  &e.val[i]) == 0) {
    3627           0 :                 free_ExtKeyUsage(&e);
    3628           0 :                 return 0;
    3629             :             }
    3630             :         }
    3631             :     }
    3632          20 :     free_ExtKeyUsage(&e);
    3633          20 :     hx509_clear_error_string(context);
    3634          20 :     return HX509_CERTIFICATE_MISSING_EKU;
    3635             : }
    3636             : 
    3637             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3638           0 : _hx509_cert_get_keyusage(hx509_context context,
    3639             :                          hx509_cert c,
    3640             :                          KeyUsage *ku)
    3641             : {
    3642           0 :     Certificate *cert;
    3643           0 :     const Extension *e;
    3644           0 :     size_t size;
    3645           0 :     int ret;
    3646           0 :     size_t i = 0;
    3647             : 
    3648           0 :     memset(ku, 0, sizeof(*ku));
    3649             : 
    3650           0 :     cert = _hx509_get_cert(c);
    3651             : 
    3652           0 :     if (_hx509_cert_get_version(cert) < 3)
    3653           0 :         return 0;
    3654             : 
    3655           0 :     e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
    3656           0 :     if (e == NULL)
    3657           0 :         return HX509_KU_CERT_MISSING;
    3658             : 
    3659           0 :     ret = decode_KeyUsage(e->extnValue.data, e->extnValue.length, ku, &size);
    3660           0 :     if (ret)
    3661           0 :         return ret;
    3662           0 :     return 0;
    3663             : }
    3664             : 
    3665             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3666           0 : _hx509_cert_get_eku(hx509_context context,
    3667             :                     hx509_cert cert,
    3668             :                     ExtKeyUsage *e)
    3669             : {
    3670           0 :     int ret;
    3671             : 
    3672           0 :     memset(e, 0, sizeof(*e));
    3673             : 
    3674           0 :     ret = find_extension_eku(_hx509_get_cert(cert), e);
    3675           0 :     if (ret && ret != HX509_EXTENSION_NOT_FOUND) {
    3676           0 :         hx509_clear_error_string(context);
    3677           0 :         return ret;
    3678             :     }
    3679           0 :     return 0;
    3680             : }
    3681             : 
    3682             : /**
    3683             :  * Encodes the hx509 certificate as a DER encode binary.
    3684             :  *
    3685             :  * @param context A hx509 context.
    3686             :  * @param c the certificate to encode.
    3687             :  * @param os the encode certificate, set to NULL, 0 on case of
    3688             :  * error. Free the os->data with hx509_xfree().
    3689             :  *
    3690             :  * @return An hx509 error code, see hx509_get_error_string().
    3691             :  *
    3692             :  * @ingroup hx509_cert
    3693             :  */
    3694             : 
    3695             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3696          65 : hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
    3697             : {
    3698           0 :     size_t size;
    3699           0 :     int ret;
    3700             : 
    3701          65 :     os->data = NULL;
    3702          65 :     os->length = 0;
    3703             : 
    3704          65 :     ASN1_MALLOC_ENCODE(Certificate, os->data, os->length,
    3705             :                        _hx509_get_cert(c), &size, ret);
    3706          65 :     if (ret) {
    3707           0 :         os->data = NULL;
    3708           0 :         os->length = 0;
    3709           0 :         return ret;
    3710             :     }
    3711          65 :     if (os->length != size)
    3712           0 :         _hx509_abort("internal ASN.1 encoder error");
    3713          65 :     return ret;
    3714             : }
    3715             : 
    3716             : /*
    3717             :  * Last to avoid lost __attribute__s due to #undef.
    3718             :  */
    3719             : 
    3720             : #undef __attribute__
    3721             : #define __attribute__(X)
    3722             : 
    3723             : HX509_LIB_NORETURN_FUNCTION void HX509_LIB_CALL
    3724           0 : _hx509_abort(const char *fmt, ...)
    3725             :      __attribute__ ((__noreturn__, __format__ (__printf__, 1, 2)))
    3726             : {
    3727           0 :     va_list ap;
    3728           0 :     va_start(ap, fmt);
    3729           0 :     vprintf(fmt, ap);
    3730           0 :     va_end(ap);
    3731           0 :     printf("\n");
    3732           0 :     fflush(stdout);
    3733           0 :     abort();
    3734             : }
    3735             : 
    3736             : /**
    3737             :  * Free a data element allocated in the library.
    3738             :  *
    3739             :  * @param ptr data to be freed.
    3740             :  *
    3741             :  * @ingroup hx509_misc
    3742             :  */
    3743             : 
    3744             : HX509_LIB_FUNCTION void HX509_LIB_CALL
    3745           0 : hx509_xfree(void *ptr)
    3746             : {
    3747           0 :     free(ptr);
    3748           0 : }
    3749             : 
    3750             : /**
    3751             :  *
    3752             :  */
    3753             : 
    3754             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3755           0 : _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
    3756             : {
    3757           0 :     ExtKeyUsage eku;
    3758           0 :     hx509_name name;
    3759           0 :     char *buf;
    3760           0 :     int ret;
    3761           0 :     hx509_env envcert = NULL;
    3762             : 
    3763           0 :     *env = NULL;
    3764             : 
    3765             :     /* version */
    3766           0 :     ret = asprintf(&buf, "%d", _hx509_cert_get_version(_hx509_get_cert(cert)));
    3767           0 :     if (ret == -1)
    3768           0 :         goto out;
    3769           0 :     ret = hx509_env_add(context, &envcert, "version", buf);
    3770           0 :     free(buf);
    3771           0 :     if (ret)
    3772           0 :         goto out;
    3773             : 
    3774             :     /* subject */
    3775           0 :     ret = hx509_cert_get_subject(cert, &name);
    3776           0 :     if (ret)
    3777           0 :         goto out;
    3778             : 
    3779           0 :     ret = hx509_name_to_string(name, &buf);
    3780           0 :     hx509_name_free(&name);
    3781           0 :     if (ret)
    3782           0 :         goto out;
    3783             : 
    3784           0 :     ret = hx509_env_add(context, &envcert, "subject", buf);
    3785           0 :     hx509_xfree(buf);
    3786           0 :     if (ret)
    3787           0 :         goto out;
    3788             : 
    3789             :     /* issuer */
    3790           0 :     ret = hx509_cert_get_issuer(cert, &name);
    3791           0 :     if (ret)
    3792           0 :         goto out;
    3793             : 
    3794           0 :     ret = hx509_name_to_string(name, &buf);
    3795           0 :     hx509_name_free(&name);
    3796           0 :     if (ret)
    3797           0 :         goto out;
    3798             : 
    3799           0 :     ret = hx509_env_add(context, &envcert, "issuer", buf);
    3800           0 :     hx509_xfree(buf);
    3801           0 :     if (ret)
    3802           0 :         goto out;
    3803             : 
    3804             :     /* eku */
    3805             : 
    3806           0 :     ret = _hx509_cert_get_eku(context, cert, &eku);
    3807           0 :     if (ret == HX509_EXTENSION_NOT_FOUND)
    3808             :         ;
    3809           0 :     else if (ret != 0)
    3810           0 :         goto out;
    3811             :     else {
    3812           0 :         size_t i;
    3813           0 :         hx509_env enveku = NULL;
    3814             : 
    3815           0 :         for (i = 0; i < eku.len; i++) {
    3816             : 
    3817           0 :             ret = der_print_heim_oid(&eku.val[i], '.', &buf);
    3818           0 :             if (ret) {
    3819           0 :                 free_ExtKeyUsage(&eku);
    3820           0 :                 hx509_env_free(&enveku);
    3821           0 :                 goto out;
    3822             :             }
    3823           0 :             ret = hx509_env_add(context, &enveku, buf, "oid-name-here");
    3824           0 :             free(buf);
    3825           0 :             if (ret) {
    3826           0 :                 free_ExtKeyUsage(&eku);
    3827           0 :                 hx509_env_free(&enveku);
    3828           0 :                 goto out;
    3829             :             }
    3830             :         }
    3831           0 :         free_ExtKeyUsage(&eku);
    3832             : 
    3833           0 :         ret = hx509_env_add_binding(context, &envcert, "eku", enveku);
    3834           0 :         if (ret) {
    3835           0 :             hx509_env_free(&enveku);
    3836           0 :             goto out;
    3837             :         }
    3838             :     }
    3839             : 
    3840             :     {
    3841           0 :         Certificate *c = _hx509_get_cert(cert);
    3842           0 :         heim_octet_string os, sig;
    3843           0 :         hx509_env envhash = NULL;
    3844             : 
    3845           0 :         os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
    3846           0 :         os.length =
    3847           0 :           c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
    3848             : 
    3849           0 :         ret = _hx509_create_signature(context,
    3850             :                                       NULL,
    3851             :                                       hx509_signature_sha1(),
    3852             :                                       &os,
    3853             :                                       NULL,
    3854             :                                       &sig);
    3855           0 :         if (ret != 0)
    3856           0 :             goto out;
    3857             : 
    3858           0 :         ret = hex_encode(sig.data, sig.length, &buf);
    3859           0 :         der_free_octet_string(&sig);
    3860           0 :         if (ret < 0) {
    3861           0 :             ret = ENOMEM;
    3862           0 :             hx509_set_error_string(context, 0, ret,
    3863             :                                    "Out of memory");
    3864           0 :             goto out;
    3865             :         }
    3866             : 
    3867           0 :         ret = hx509_env_add(context, &envhash, "sha1", buf);
    3868           0 :         free(buf);
    3869           0 :         if (ret)
    3870           0 :             goto out;
    3871             : 
    3872           0 :         ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
    3873           0 :         if (ret) {
    3874           0 :           hx509_env_free(&envhash);
    3875           0 :           goto out;
    3876             :         }
    3877             :     }
    3878             : 
    3879           0 :     ret = hx509_env_add_binding(context, env, "certificate", envcert);
    3880           0 :     if (ret)
    3881           0 :         goto out;
    3882             : 
    3883           0 :     return 0;
    3884             : 
    3885           0 : out:
    3886           0 :     hx509_env_free(&envcert);
    3887           0 :     return ret;
    3888             : }
    3889             : 
    3890             : /**
    3891             :  * Print a simple representation of a certificate
    3892             :  *
    3893             :  * @param context A hx509 context, can be NULL
    3894             :  * @param cert certificate to print
    3895             :  * @param out the stdio output stream, if NULL, stdout is used
    3896             :  *
    3897             :  * @return An hx509 error code
    3898             :  *
    3899             :  * @ingroup hx509_cert
    3900             :  */
    3901             : 
    3902             : HX509_LIB_FUNCTION int HX509_LIB_CALL
    3903           0 : hx509_print_cert(hx509_context context, hx509_cert cert, FILE *out)
    3904             : {
    3905           0 :     hx509_name name;
    3906           0 :     char *str;
    3907           0 :     int ret;
    3908             : 
    3909           0 :     if (out == NULL)
    3910           0 :         out = stderr;
    3911             : 
    3912           0 :     ret = hx509_cert_get_issuer(cert, &name);
    3913           0 :     if (ret)
    3914           0 :         return ret;
    3915           0 :     hx509_name_to_string(name, &str);
    3916           0 :     hx509_name_free(&name);
    3917           0 :     fprintf(out, "    issuer:  \"%s\"\n", str);
    3918           0 :     free(str);
    3919             : 
    3920           0 :     ret = hx509_cert_get_subject(cert, &name);
    3921           0 :     if (ret)
    3922           0 :         return ret;
    3923           0 :     hx509_name_to_string(name, &str);
    3924           0 :     hx509_name_free(&name);
    3925           0 :     fprintf(out, "    subject: \"%s\"\n", str);
    3926           0 :     free(str);
    3927             : 
    3928             :     {
    3929           0 :         heim_integer serialNumber;
    3930             : 
    3931           0 :         ret = hx509_cert_get_serialnumber(cert, &serialNumber);
    3932           0 :         if (ret)
    3933           0 :             return ret;
    3934           0 :         ret = der_print_hex_heim_integer(&serialNumber, &str);
    3935           0 :         if (ret)
    3936           0 :             return ret;
    3937           0 :         der_free_heim_integer(&serialNumber);
    3938           0 :         fprintf(out, "    serial: %s\n", str);
    3939           0 :         free(str);
    3940             :     }
    3941             : 
    3942           0 :     fprintf(out, "    keyusage: ");
    3943           0 :     ret = hx509_cert_keyusage_print(context, cert, &str);
    3944           0 :     if (ret == 0) {
    3945           0 :         fprintf(out, "%s\n", str);
    3946           0 :         free(str);
    3947             :     } else
    3948           0 :         fprintf(out, "no");
    3949             : 
    3950           0 :     return 0;
    3951             : }

Generated by: LCOV version 1.14