Home | History | Annotate | Line # | Download | only in krb5
      1  1.4  christos /*	$NetBSD: pkinit.c,v 1.6 2023/06/19 21:41:44 christos Exp $	*/
      2  1.1     elric 
      3  1.1     elric /*
      4  1.2  christos  * Copyright (c) 2003 - 2016 Kungliga Tekniska Hgskolan
      5  1.1     elric  * (Royal Institute of Technology, Stockholm, Sweden).
      6  1.1     elric  * All rights reserved.
      7  1.1     elric  *
      8  1.1     elric  * Portions Copyright (c) 2009 Apple Inc. All rights reserved.
      9  1.1     elric  *
     10  1.1     elric  * Redistribution and use in source and binary forms, with or without
     11  1.1     elric  * modification, are permitted provided that the following conditions
     12  1.1     elric  * are met:
     13  1.1     elric  *
     14  1.1     elric  * 1. Redistributions of source code must retain the above copyright
     15  1.1     elric  *    notice, this list of conditions and the following disclaimer.
     16  1.1     elric  *
     17  1.1     elric  * 2. Redistributions in binary form must reproduce the above copyright
     18  1.1     elric  *    notice, this list of conditions and the following disclaimer in the
     19  1.1     elric  *    documentation and/or other materials provided with the distribution.
     20  1.1     elric  *
     21  1.1     elric  * 3. Neither the name of the Institute nor the names of its contributors
     22  1.1     elric  *    may be used to endorse or promote products derived from this software
     23  1.1     elric  *    without specific prior written permission.
     24  1.1     elric  *
     25  1.1     elric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     26  1.1     elric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  1.1     elric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  1.1     elric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     29  1.1     elric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  1.1     elric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  1.1     elric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  1.1     elric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  1.1     elric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  1.1     elric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  1.1     elric  * SUCH DAMAGE.
     36  1.1     elric  */
     37  1.1     elric 
     38  1.1     elric #include "krb5_locl.h"
     39  1.1     elric 
     40  1.1     elric struct krb5_dh_moduli {
     41  1.1     elric     char *name;
     42  1.1     elric     unsigned long bits;
     43  1.1     elric     heim_integer p;
     44  1.1     elric     heim_integer g;
     45  1.1     elric     heim_integer q;
     46  1.1     elric };
     47  1.1     elric 
     48  1.1     elric #ifdef PKINIT
     49  1.1     elric 
     50  1.1     elric #include <krb5/cms_asn1.h>
     51  1.1     elric #include <krb5/pkcs8_asn1.h>
     52  1.1     elric #include <krb5/pkcs9_asn1.h>
     53  1.1     elric #include <krb5/pkcs12_asn1.h>
     54  1.1     elric #include <krb5/pkinit_asn1.h>
     55  1.1     elric #include <krb5/asn1_err.h>
     56  1.1     elric 
     57  1.1     elric #include <krb5/der.h>
     58  1.1     elric 
     59  1.1     elric struct krb5_pk_cert {
     60  1.1     elric     hx509_cert cert;
     61  1.1     elric };
     62  1.1     elric 
     63  1.1     elric static void
     64  1.1     elric pk_copy_error(krb5_context context,
     65  1.1     elric 	      hx509_context hx509ctx,
     66  1.1     elric 	      int hxret,
     67  1.1     elric 	      const char *fmt,
     68  1.1     elric 	      ...)
     69  1.2  christos     __attribute__ ((__format__ (__printf__, 4, 5)));
     70  1.1     elric 
     71  1.1     elric /*
     72  1.1     elric  *
     73  1.1     elric  */
     74  1.1     elric 
     75  1.1     elric KRB5_LIB_FUNCTION void KRB5_LIB_CALL
     76  1.1     elric _krb5_pk_cert_free(struct krb5_pk_cert *cert)
     77  1.1     elric {
     78  1.1     elric     if (cert->cert) {
     79  1.1     elric 	hx509_cert_free(cert->cert);
     80  1.1     elric     }
     81  1.1     elric     free(cert);
     82  1.1     elric }
     83  1.1     elric 
     84  1.1     elric static krb5_error_code
     85  1.4  christos BN_to_integer(krb5_context context, const BIGNUM *bn, heim_integer *integer)
     86  1.1     elric {
     87  1.1     elric     integer->length = BN_num_bytes(bn);
     88  1.1     elric     integer->data = malloc(integer->length);
     89  1.1     elric     if (integer->data == NULL) {
     90  1.1     elric 	krb5_clear_error_message(context);
     91  1.1     elric 	return ENOMEM;
     92  1.1     elric     }
     93  1.1     elric     BN_bn2bin(bn, integer->data);
     94  1.1     elric     integer->negative = BN_is_negative(bn);
     95  1.1     elric     return 0;
     96  1.1     elric }
     97  1.1     elric 
     98  1.1     elric static BIGNUM *
     99  1.1     elric integer_to_BN(krb5_context context, const char *field, const heim_integer *f)
    100  1.1     elric {
    101  1.1     elric     BIGNUM *bn;
    102  1.1     elric 
    103  1.1     elric     bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL);
    104  1.1     elric     if (bn == NULL) {
    105  1.1     elric 	krb5_set_error_message(context, ENOMEM,
    106  1.1     elric 			       N_("PKINIT: parsing BN failed %s", ""), field);
    107  1.1     elric 	return NULL;
    108  1.1     elric     }
    109  1.1     elric     BN_set_negative(bn, f->negative);
    110  1.1     elric     return bn;
    111  1.1     elric }
    112  1.1     elric 
    113  1.1     elric static krb5_error_code
    114  1.1     elric select_dh_group(krb5_context context, DH *dh, unsigned long bits,
    115  1.1     elric 		struct krb5_dh_moduli **moduli)
    116  1.1     elric {
    117  1.1     elric     const struct krb5_dh_moduli *m;
    118  1.1     elric 
    119  1.1     elric     if (bits == 0) {
    120  1.1     elric 	m = moduli[1]; /* XXX */
    121  1.1     elric 	if (m == NULL)
    122  1.1     elric 	    m = moduli[0]; /* XXX */
    123  1.1     elric     } else {
    124  1.1     elric 	int i;
    125  1.1     elric 	for (i = 0; moduli[i] != NULL; i++) {
    126  1.1     elric 	    if (bits < moduli[i]->bits)
    127  1.1     elric 		break;
    128  1.1     elric 	}
    129  1.1     elric 	if (moduli[i] == NULL) {
    130  1.1     elric 	    krb5_set_error_message(context, EINVAL,
    131  1.1     elric 				   N_("Did not find a DH group parameter "
    132  1.1     elric 				      "matching requirement of %lu bits", ""),
    133  1.1     elric 				   bits);
    134  1.1     elric 	    return EINVAL;
    135  1.1     elric 	}
    136  1.1     elric 	m = moduli[i];
    137  1.1     elric     }
    138  1.1     elric 
    139  1.3  christos     BIGNUM *p = integer_to_BN(context, "p", &m->p);
    140  1.3  christos     if (p == NULL)
    141  1.1     elric 	return ENOMEM;
    142  1.3  christos     BIGNUM *g = integer_to_BN(context, "g", &m->g);
    143  1.3  christos     if (g == NULL)
    144  1.1     elric 	return ENOMEM;
    145  1.3  christos     BIGNUM *q = integer_to_BN(context, "q", &m->q);
    146  1.3  christos     if (q == NULL)
    147  1.1     elric 	return ENOMEM;
    148  1.3  christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL
    149  1.3  christos     dh->p = p;
    150  1.3  christos     dh->q = q;
    151  1.3  christos     dh->g = g;
    152  1.3  christos #else
    153  1.3  christos     DH_set0_pqg(dh, p, q, g);
    154  1.3  christos #endif
    155  1.1     elric 
    156  1.1     elric     return 0;
    157  1.1     elric }
    158  1.1     elric 
    159  1.1     elric struct certfind {
    160  1.1     elric     const char *type;
    161  1.1     elric     const heim_oid *oid;
    162  1.1     elric };
    163  1.1     elric 
    164  1.1     elric /*
    165  1.1     elric  * Try searchin the key by to use by first looking for for PK-INIT
    166  1.1     elric  * EKU, then the Microsoft smart card EKU and last, no special EKU at all.
    167  1.1     elric  */
    168  1.1     elric 
    169  1.1     elric static krb5_error_code
    170  1.1     elric find_cert(krb5_context context, struct krb5_pk_identity *id,
    171  1.1     elric 	  hx509_query *q, hx509_cert *cert)
    172  1.1     elric {
    173  1.1     elric     struct certfind cf[4] = {
    174  1.2  christos 	{ "MobileMe EKU", NULL },
    175  1.2  christos 	{ "PKINIT EKU", NULL },
    176  1.2  christos 	{ "MS EKU", NULL },
    177  1.2  christos 	{ "any (or no)", NULL }
    178  1.1     elric     };
    179  1.2  christos     int ret = HX509_CERT_NOT_FOUND;
    180  1.2  christos     size_t i, start = 1;
    181  1.1     elric     unsigned oids[] = { 1, 2, 840, 113635, 100, 3, 2, 1 };
    182  1.1     elric     const heim_oid mobileMe = { sizeof(oids)/sizeof(oids[0]), oids };
    183  1.1     elric 
    184  1.1     elric 
    185  1.1     elric     if (id->flags & PKINIT_BTMM)
    186  1.1     elric 	start = 0;
    187  1.1     elric 
    188  1.1     elric     cf[0].oid = &mobileMe;
    189  1.1     elric     cf[1].oid = &asn1_oid_id_pkekuoid;
    190  1.1     elric     cf[2].oid = &asn1_oid_id_pkinit_ms_eku;
    191  1.1     elric     cf[3].oid = NULL;
    192  1.1     elric 
    193  1.1     elric     for (i = start; i < sizeof(cf)/sizeof(cf[0]); i++) {
    194  1.1     elric 	ret = hx509_query_match_eku(q, cf[i].oid);
    195  1.1     elric 	if (ret) {
    196  1.1     elric 	    pk_copy_error(context, context->hx509ctx, ret,
    197  1.1     elric 			  "Failed setting %s OID", cf[i].type);
    198  1.1     elric 	    return ret;
    199  1.1     elric 	}
    200  1.1     elric 
    201  1.1     elric 	ret = hx509_certs_find(context->hx509ctx, id->certs, q, cert);
    202  1.1     elric 	if (ret == 0)
    203  1.1     elric 	    break;
    204  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
    205  1.1     elric 		      "Failed finding certificate with %s OID", cf[i].type);
    206  1.1     elric     }
    207  1.1     elric     return ret;
    208  1.1     elric }
    209  1.1     elric 
    210  1.1     elric 
    211  1.1     elric static krb5_error_code
    212  1.1     elric create_signature(krb5_context context,
    213  1.1     elric 		 const heim_oid *eContentType,
    214  1.1     elric 		 krb5_data *eContent,
    215  1.1     elric 		 struct krb5_pk_identity *id,
    216  1.1     elric 		 hx509_peer_info peer,
    217  1.1     elric 		 krb5_data *sd_data)
    218  1.1     elric {
    219  1.1     elric     int ret, flags = 0;
    220  1.1     elric 
    221  1.1     elric     if (id->cert == NULL)
    222  1.1     elric 	flags |= HX509_CMS_SIGNATURE_NO_SIGNER;
    223  1.1     elric 
    224  1.1     elric     ret = hx509_cms_create_signed_1(context->hx509ctx,
    225  1.1     elric 				    flags,
    226  1.1     elric 				    eContentType,
    227  1.1     elric 				    eContent->data,
    228  1.1     elric 				    eContent->length,
    229  1.1     elric 				    NULL,
    230  1.1     elric 				    id->cert,
    231  1.1     elric 				    peer,
    232  1.1     elric 				    NULL,
    233  1.1     elric 				    id->certs,
    234  1.1     elric 				    sd_data);
    235  1.1     elric     if (ret) {
    236  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
    237  1.1     elric 		      "Create CMS signedData");
    238  1.1     elric 	return ret;
    239  1.1     elric     }
    240  1.1     elric 
    241  1.1     elric     return 0;
    242  1.1     elric }
    243  1.1     elric 
    244  1.1     elric static int
    245  1.1     elric cert2epi(hx509_context context, void *ctx, hx509_cert c)
    246  1.1     elric {
    247  1.1     elric     ExternalPrincipalIdentifiers *ids = ctx;
    248  1.1     elric     ExternalPrincipalIdentifier id;
    249  1.1     elric     hx509_name subject = NULL;
    250  1.1     elric     void *p;
    251  1.1     elric     int ret;
    252  1.1     elric 
    253  1.1     elric     if (ids->len > 10)
    254  1.1     elric 	return 0;
    255  1.1     elric 
    256  1.1     elric     memset(&id, 0, sizeof(id));
    257  1.1     elric 
    258  1.1     elric     ret = hx509_cert_get_subject(c, &subject);
    259  1.1     elric     if (ret)
    260  1.1     elric 	return ret;
    261  1.1     elric 
    262  1.1     elric     if (hx509_name_is_null_p(subject) != 0) {
    263  1.1     elric 
    264  1.1     elric 	id.subjectName = calloc(1, sizeof(*id.subjectName));
    265  1.1     elric 	if (id.subjectName == NULL) {
    266  1.1     elric 	    hx509_name_free(&subject);
    267  1.1     elric 	    free_ExternalPrincipalIdentifier(&id);
    268  1.1     elric 	    return ENOMEM;
    269  1.1     elric 	}
    270  1.1     elric 
    271  1.1     elric 	ret = hx509_name_binary(subject, id.subjectName);
    272  1.1     elric 	if (ret) {
    273  1.1     elric 	    hx509_name_free(&subject);
    274  1.1     elric 	    free_ExternalPrincipalIdentifier(&id);
    275  1.1     elric 	    return ret;
    276  1.1     elric 	}
    277  1.1     elric     }
    278  1.1     elric     hx509_name_free(&subject);
    279  1.1     elric 
    280  1.1     elric 
    281  1.1     elric     id.issuerAndSerialNumber = calloc(1, sizeof(*id.issuerAndSerialNumber));
    282  1.1     elric     if (id.issuerAndSerialNumber == NULL) {
    283  1.1     elric 	free_ExternalPrincipalIdentifier(&id);
    284  1.1     elric 	return ENOMEM;
    285  1.1     elric     }
    286  1.1     elric 
    287  1.1     elric     {
    288  1.1     elric 	IssuerAndSerialNumber iasn;
    289  1.1     elric 	hx509_name issuer;
    290  1.2  christos 	size_t size = 0;
    291  1.2  christos 
    292  1.1     elric 	memset(&iasn, 0, sizeof(iasn));
    293  1.1     elric 
    294  1.1     elric 	ret = hx509_cert_get_issuer(c, &issuer);
    295  1.1     elric 	if (ret) {
    296  1.1     elric 	    free_ExternalPrincipalIdentifier(&id);
    297  1.1     elric 	    return ret;
    298  1.1     elric 	}
    299  1.1     elric 
    300  1.1     elric 	ret = hx509_name_to_Name(issuer, &iasn.issuer);
    301  1.1     elric 	hx509_name_free(&issuer);
    302  1.1     elric 	if (ret) {
    303  1.1     elric 	    free_ExternalPrincipalIdentifier(&id);
    304  1.1     elric 	    return ret;
    305  1.1     elric 	}
    306  1.2  christos 
    307  1.1     elric 	ret = hx509_cert_get_serialnumber(c, &iasn.serialNumber);
    308  1.1     elric 	if (ret) {
    309  1.1     elric 	    free_IssuerAndSerialNumber(&iasn);
    310  1.1     elric 	    free_ExternalPrincipalIdentifier(&id);
    311  1.1     elric 	    return ret;
    312  1.1     elric 	}
    313  1.1     elric 
    314  1.1     elric 	ASN1_MALLOC_ENCODE(IssuerAndSerialNumber,
    315  1.1     elric 			   id.issuerAndSerialNumber->data,
    316  1.1     elric 			   id.issuerAndSerialNumber->length,
    317  1.1     elric 			   &iasn, &size, ret);
    318  1.1     elric 	free_IssuerAndSerialNumber(&iasn);
    319  1.2  christos 	if (ret) {
    320  1.2  christos             free_ExternalPrincipalIdentifier(&id);
    321  1.1     elric 	    return ret;
    322  1.2  christos         }
    323  1.1     elric 	if (id.issuerAndSerialNumber->length != size)
    324  1.1     elric 	    abort();
    325  1.1     elric     }
    326  1.1     elric 
    327  1.1     elric     id.subjectKeyIdentifier = NULL;
    328  1.1     elric 
    329  1.1     elric     p = realloc(ids->val, sizeof(ids->val[0]) * (ids->len + 1));
    330  1.1     elric     if (p == NULL) {
    331  1.1     elric 	free_ExternalPrincipalIdentifier(&id);
    332  1.1     elric 	return ENOMEM;
    333  1.1     elric     }
    334  1.1     elric 
    335  1.1     elric     ids->val = p;
    336  1.1     elric     ids->val[ids->len] = id;
    337  1.1     elric     ids->len++;
    338  1.1     elric 
    339  1.1     elric     return 0;
    340  1.1     elric }
    341  1.1     elric 
    342  1.1     elric static krb5_error_code
    343  1.1     elric build_edi(krb5_context context,
    344  1.1     elric 	  hx509_context hx509ctx,
    345  1.1     elric 	  hx509_certs certs,
    346  1.1     elric 	  ExternalPrincipalIdentifiers *ids)
    347  1.1     elric {
    348  1.1     elric     return hx509_certs_iter_f(hx509ctx, certs, cert2epi, ids);
    349  1.1     elric }
    350  1.1     elric 
    351  1.1     elric static krb5_error_code
    352  1.1     elric build_auth_pack(krb5_context context,
    353  1.1     elric 		unsigned nonce,
    354  1.1     elric 		krb5_pk_init_ctx ctx,
    355  1.1     elric 		const KDC_REQ_BODY *body,
    356  1.1     elric 		AuthPack *a)
    357  1.1     elric {
    358  1.2  christos     size_t buf_size, len = 0;
    359  1.1     elric     krb5_error_code ret;
    360  1.1     elric     void *buf;
    361  1.1     elric     krb5_timestamp sec;
    362  1.1     elric     int32_t usec;
    363  1.1     elric     Checksum checksum;
    364  1.1     elric 
    365  1.1     elric     krb5_clear_error_message(context);
    366  1.1     elric 
    367  1.1     elric     memset(&checksum, 0, sizeof(checksum));
    368  1.1     elric 
    369  1.1     elric     krb5_us_timeofday(context, &sec, &usec);
    370  1.1     elric     a->pkAuthenticator.ctime = sec;
    371  1.1     elric     a->pkAuthenticator.nonce = nonce;
    372  1.1     elric 
    373  1.1     elric     ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
    374  1.1     elric     if (ret)
    375  1.1     elric 	return ret;
    376  1.1     elric     if (buf_size != len)
    377  1.1     elric 	krb5_abortx(context, "internal error in ASN.1 encoder");
    378  1.1     elric 
    379  1.1     elric     ret = krb5_create_checksum(context,
    380  1.1     elric 			       NULL,
    381  1.1     elric 			       0,
    382  1.1     elric 			       CKSUMTYPE_SHA1,
    383  1.1     elric 			       buf,
    384  1.1     elric 			       len,
    385  1.1     elric 			       &checksum);
    386  1.1     elric     free(buf);
    387  1.1     elric     if (ret)
    388  1.1     elric 	return ret;
    389  1.1     elric 
    390  1.1     elric     ALLOC(a->pkAuthenticator.paChecksum, 1);
    391  1.1     elric     if (a->pkAuthenticator.paChecksum == NULL) {
    392  1.2  christos 	return krb5_enomem(context);
    393  1.1     elric     }
    394  1.1     elric 
    395  1.1     elric     ret = krb5_data_copy(a->pkAuthenticator.paChecksum,
    396  1.1     elric 			 checksum.checksum.data, checksum.checksum.length);
    397  1.1     elric     free_Checksum(&checksum);
    398  1.1     elric     if (ret)
    399  1.1     elric 	return ret;
    400  1.1     elric 
    401  1.1     elric     if (ctx->keyex == USE_DH || ctx->keyex == USE_ECDH) {
    402  1.1     elric 	const char *moduli_file;
    403  1.1     elric 	unsigned long dh_min_bits;
    404  1.1     elric 	krb5_data dhbuf;
    405  1.2  christos 	size_t size = 0;
    406  1.1     elric 
    407  1.1     elric 	krb5_data_zero(&dhbuf);
    408  1.1     elric 
    409  1.1     elric 
    410  1.1     elric 
    411  1.1     elric 	moduli_file = krb5_config_get_string(context, NULL,
    412  1.1     elric 					     "libdefaults",
    413  1.1     elric 					     "moduli",
    414  1.1     elric 					     NULL);
    415  1.1     elric 
    416  1.1     elric 	dh_min_bits =
    417  1.1     elric 	    krb5_config_get_int_default(context, NULL, 0,
    418  1.1     elric 					"libdefaults",
    419  1.1     elric 					"pkinit_dh_min_bits",
    420  1.1     elric 					NULL);
    421  1.1     elric 
    422  1.1     elric 	ret = _krb5_parse_moduli(context, moduli_file, &ctx->m);
    423  1.1     elric 	if (ret)
    424  1.1     elric 	    return ret;
    425  1.2  christos 
    426  1.1     elric 	ctx->u.dh = DH_new();
    427  1.2  christos 	if (ctx->u.dh == NULL)
    428  1.2  christos 	    return krb5_enomem(context);
    429  1.1     elric 
    430  1.1     elric 	ret = select_dh_group(context, ctx->u.dh, dh_min_bits, ctx->m);
    431  1.1     elric 	if (ret)
    432  1.1     elric 	    return ret;
    433  1.1     elric 
    434  1.1     elric 	if (DH_generate_key(ctx->u.dh) != 1) {
    435  1.1     elric 	    krb5_set_error_message(context, ENOMEM,
    436  1.1     elric 				   N_("pkinit: failed to generate DH key", ""));
    437  1.1     elric 	    return ENOMEM;
    438  1.1     elric 	}
    439  1.1     elric 
    440  1.1     elric 
    441  1.1     elric 	if (1 /* support_cached_dh */) {
    442  1.1     elric 	    ALLOC(a->clientDHNonce, 1);
    443  1.1     elric 	    if (a->clientDHNonce == NULL) {
    444  1.1     elric 		krb5_clear_error_message(context);
    445  1.1     elric 		return ENOMEM;
    446  1.1     elric 	    }
    447  1.1     elric 	    ret = krb5_data_alloc(a->clientDHNonce, 40);
    448  1.1     elric 	    if (a->clientDHNonce == NULL) {
    449  1.1     elric 		krb5_clear_error_message(context);
    450  1.1     elric 		return ret;
    451  1.1     elric 	    }
    452  1.1     elric 	    RAND_bytes(a->clientDHNonce->data, a->clientDHNonce->length);
    453  1.1     elric 	    ret = krb5_copy_data(context, a->clientDHNonce,
    454  1.1     elric 				 &ctx->clientDHNonce);
    455  1.1     elric 	    if (ret)
    456  1.1     elric 		return ret;
    457  1.1     elric 	}
    458  1.1     elric 
    459  1.1     elric 	ALLOC(a->clientPublicValue, 1);
    460  1.1     elric 	if (a->clientPublicValue == NULL)
    461  1.1     elric 	    return ENOMEM;
    462  1.1     elric 
    463  1.1     elric 	if (ctx->keyex == USE_DH) {
    464  1.1     elric 	    DH *dh = ctx->u.dh;
    465  1.3  christos 	    const BIGNUM *p, *q, *g;
    466  1.1     elric 	    DomainParameters dp;
    467  1.1     elric 	    heim_integer dh_pub_key;
    468  1.1     elric 
    469  1.1     elric 	    ret = der_copy_oid(&asn1_oid_id_dhpublicnumber,
    470  1.1     elric 			       &a->clientPublicValue->algorithm.algorithm);
    471  1.1     elric 	    if (ret)
    472  1.1     elric 		return ret;
    473  1.2  christos 
    474  1.1     elric 	    memset(&dp, 0, sizeof(dp));
    475  1.3  christos 
    476  1.3  christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL
    477  1.3  christos 	    p = dh->p;
    478  1.3  christos 	    q = dh->q;
    479  1.3  christos 	    g = dh->g;
    480  1.3  christos #else
    481  1.3  christos 	    DH_get0_pqg(dh, &p, &q, &g);
    482  1.3  christos #endif
    483  1.2  christos 
    484  1.4  christos 	    ret = BN_to_integer(context, p, &dp.p);
    485  1.1     elric 	    if (ret) {
    486  1.1     elric 		free_DomainParameters(&dp);
    487  1.1     elric 		return ret;
    488  1.1     elric 	    }
    489  1.4  christos 	    ret = BN_to_integer(context, g, &dp.g);
    490  1.1     elric 	    if (ret) {
    491  1.1     elric 		free_DomainParameters(&dp);
    492  1.1     elric 		return ret;
    493  1.1     elric 	    }
    494  1.2  christos 	    dp.q = calloc(1, sizeof(*dp.q));
    495  1.2  christos 	    if (dp.q == NULL) {
    496  1.2  christos 		free_DomainParameters(&dp);
    497  1.2  christos 		return ENOMEM;
    498  1.2  christos 	    }
    499  1.4  christos 	    ret = BN_to_integer(context, q, dp.q);
    500  1.1     elric 	    if (ret) {
    501  1.1     elric 		free_DomainParameters(&dp);
    502  1.1     elric 		return ret;
    503  1.1     elric 	    }
    504  1.1     elric 	    dp.j = NULL;
    505  1.1     elric 	    dp.validationParms = NULL;
    506  1.2  christos 
    507  1.1     elric 	    a->clientPublicValue->algorithm.parameters =
    508  1.1     elric 		malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
    509  1.1     elric 	    if (a->clientPublicValue->algorithm.parameters == NULL) {
    510  1.1     elric 		free_DomainParameters(&dp);
    511  1.1     elric 		return ret;
    512  1.1     elric 	    }
    513  1.2  christos 
    514  1.1     elric 	    ASN1_MALLOC_ENCODE(DomainParameters,
    515  1.1     elric 			       a->clientPublicValue->algorithm.parameters->data,
    516  1.1     elric 			       a->clientPublicValue->algorithm.parameters->length,
    517  1.1     elric 			       &dp, &size, ret);
    518  1.1     elric 	    free_DomainParameters(&dp);
    519  1.1     elric 	    if (ret)
    520  1.1     elric 		return ret;
    521  1.1     elric 	    if (size != a->clientPublicValue->algorithm.parameters->length)
    522  1.1     elric 		krb5_abortx(context, "Internal ASN1 encoder error");
    523  1.2  christos 
    524  1.3  christos 	    const BIGNUM *pub_key;
    525  1.3  christos #if OPENSSL_VERSION_NUMBER < 0x10100000UL
    526  1.3  christos 	    pub_key = dh->pub_key;
    527  1.3  christos #else
    528  1.3  christos 	    DH_get0_key(dh, &pub_key, NULL);
    529  1.3  christos #endif
    530  1.4  christos 	    ret = BN_to_integer(context, pub_key, &dh_pub_key);
    531  1.1     elric 	    if (ret)
    532  1.1     elric 		return ret;
    533  1.2  christos 
    534  1.1     elric 	    ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
    535  1.1     elric 			       &dh_pub_key, &size, ret);
    536  1.1     elric 	    der_free_heim_integer(&dh_pub_key);
    537  1.1     elric 	    if (ret)
    538  1.1     elric 		return ret;
    539  1.1     elric 	    if (size != dhbuf.length)
    540  1.1     elric 		krb5_abortx(context, "asn1 internal error");
    541  1.2  christos             a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
    542  1.2  christos             a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
    543  1.1     elric 	} else if (ctx->keyex == USE_ECDH) {
    544  1.2  christos             ret = _krb5_build_authpack_subjectPK_EC(context, ctx, a);
    545  1.2  christos             if (ret)
    546  1.2  christos                 return ret;
    547  1.1     elric 	} else
    548  1.1     elric 	    krb5_abortx(context, "internal error");
    549  1.1     elric     }
    550  1.2  christos 
    551  1.1     elric     {
    552  1.1     elric 	a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes));
    553  1.1     elric 	if (a->supportedCMSTypes == NULL)
    554  1.1     elric 	    return ENOMEM;
    555  1.1     elric 
    556  1.2  christos 	ret = hx509_crypto_available(context->hx509ctx, HX509_SELECT_ALL,
    557  1.2  christos 				     ctx->id->cert,
    558  1.1     elric 				     &a->supportedCMSTypes->val,
    559  1.1     elric 				     &a->supportedCMSTypes->len);
    560  1.1     elric 	if (ret)
    561  1.1     elric 	    return ret;
    562  1.1     elric     }
    563  1.1     elric 
    564  1.1     elric     return ret;
    565  1.1     elric }
    566  1.1     elric 
    567  1.1     elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    568  1.1     elric _krb5_pk_mk_ContentInfo(krb5_context context,
    569  1.1     elric 			const krb5_data *buf,
    570  1.1     elric 			const heim_oid *oid,
    571  1.1     elric 			struct ContentInfo *content_info)
    572  1.1     elric {
    573  1.1     elric     krb5_error_code ret;
    574  1.1     elric 
    575  1.1     elric     ret = der_copy_oid(oid, &content_info->contentType);
    576  1.1     elric     if (ret)
    577  1.1     elric 	return ret;
    578  1.1     elric     ALLOC(content_info->content, 1);
    579  1.1     elric     if (content_info->content == NULL)
    580  1.1     elric 	return ENOMEM;
    581  1.1     elric     content_info->content->data = malloc(buf->length);
    582  1.1     elric     if (content_info->content->data == NULL)
    583  1.1     elric 	return ENOMEM;
    584  1.1     elric     memcpy(content_info->content->data, buf->data, buf->length);
    585  1.1     elric     content_info->content->length = buf->length;
    586  1.1     elric     return 0;
    587  1.1     elric }
    588  1.1     elric 
    589  1.1     elric static krb5_error_code
    590  1.1     elric pk_mk_padata(krb5_context context,
    591  1.1     elric 	     krb5_pk_init_ctx ctx,
    592  1.1     elric 	     const KDC_REQ_BODY *req_body,
    593  1.1     elric 	     unsigned nonce,
    594  1.1     elric 	     METHOD_DATA *md)
    595  1.1     elric {
    596  1.1     elric     struct ContentInfo content_info;
    597  1.1     elric     krb5_error_code ret;
    598  1.2  christos     const heim_oid *oid = NULL;
    599  1.2  christos     size_t size = 0;
    600  1.1     elric     krb5_data buf, sd_buf;
    601  1.2  christos     int pa_type = -1;
    602  1.1     elric 
    603  1.1     elric     krb5_data_zero(&buf);
    604  1.1     elric     krb5_data_zero(&sd_buf);
    605  1.1     elric     memset(&content_info, 0, sizeof(content_info));
    606  1.1     elric 
    607  1.1     elric     if (ctx->type == PKINIT_WIN2K) {
    608  1.1     elric 	AuthPack_Win2k ap;
    609  1.1     elric 	krb5_timestamp sec;
    610  1.1     elric 	int32_t usec;
    611  1.1     elric 
    612  1.1     elric 	memset(&ap, 0, sizeof(ap));
    613  1.1     elric 
    614  1.1     elric 	/* fill in PKAuthenticator */
    615  1.1     elric 	ret = copy_PrincipalName(req_body->sname, &ap.pkAuthenticator.kdcName);
    616  1.1     elric 	if (ret) {
    617  1.1     elric 	    free_AuthPack_Win2k(&ap);
    618  1.1     elric 	    krb5_clear_error_message(context);
    619  1.1     elric 	    goto out;
    620  1.1     elric 	}
    621  1.1     elric 	ret = copy_Realm(&req_body->realm, &ap.pkAuthenticator.kdcRealm);
    622  1.1     elric 	if (ret) {
    623  1.1     elric 	    free_AuthPack_Win2k(&ap);
    624  1.1     elric 	    krb5_clear_error_message(context);
    625  1.1     elric 	    goto out;
    626  1.1     elric 	}
    627  1.1     elric 
    628  1.1     elric 	krb5_us_timeofday(context, &sec, &usec);
    629  1.1     elric 	ap.pkAuthenticator.ctime = sec;
    630  1.1     elric 	ap.pkAuthenticator.cusec = usec;
    631  1.1     elric 	ap.pkAuthenticator.nonce = nonce;
    632  1.1     elric 
    633  1.1     elric 	ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length,
    634  1.1     elric 			   &ap, &size, ret);
    635  1.1     elric 	free_AuthPack_Win2k(&ap);
    636  1.1     elric 	if (ret) {
    637  1.1     elric 	    krb5_set_error_message(context, ret,
    638  1.1     elric 				   N_("Failed encoding AuthPackWin: %d", ""),
    639  1.1     elric 				   (int)ret);
    640  1.1     elric 	    goto out;
    641  1.1     elric 	}
    642  1.1     elric 	if (buf.length != size)
    643  1.1     elric 	    krb5_abortx(context, "internal ASN1 encoder error");
    644  1.1     elric 
    645  1.1     elric 	oid = &asn1_oid_id_pkcs7_data;
    646  1.1     elric     } else if (ctx->type == PKINIT_27) {
    647  1.1     elric 	AuthPack ap;
    648  1.2  christos 
    649  1.1     elric 	memset(&ap, 0, sizeof(ap));
    650  1.1     elric 
    651  1.1     elric 	ret = build_auth_pack(context, nonce, ctx, req_body, &ap);
    652  1.1     elric 	if (ret) {
    653  1.1     elric 	    free_AuthPack(&ap);
    654  1.1     elric 	    goto out;
    655  1.1     elric 	}
    656  1.1     elric 
    657  1.1     elric 	ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret);
    658  1.1     elric 	free_AuthPack(&ap);
    659  1.1     elric 	if (ret) {
    660  1.1     elric 	    krb5_set_error_message(context, ret,
    661  1.1     elric 				   N_("Failed encoding AuthPack: %d", ""),
    662  1.1     elric 				   (int)ret);
    663  1.1     elric 	    goto out;
    664  1.1     elric 	}
    665  1.1     elric 	if (buf.length != size)
    666  1.1     elric 	    krb5_abortx(context, "internal ASN1 encoder error");
    667  1.1     elric 
    668  1.1     elric 	oid = &asn1_oid_id_pkauthdata;
    669  1.1     elric     } else
    670  1.1     elric 	krb5_abortx(context, "internal pkinit error");
    671  1.1     elric 
    672  1.1     elric     ret = create_signature(context, oid, &buf, ctx->id,
    673  1.1     elric 			   ctx->peer, &sd_buf);
    674  1.1     elric     krb5_data_free(&buf);
    675  1.1     elric     if (ret)
    676  1.1     elric 	goto out;
    677  1.1     elric 
    678  1.1     elric     ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &sd_buf, &buf);
    679  1.1     elric     krb5_data_free(&sd_buf);
    680  1.1     elric     if (ret) {
    681  1.1     elric 	krb5_set_error_message(context, ret,
    682  1.1     elric 			       N_("ContentInfo wrapping of signedData failed",""));
    683  1.1     elric 	goto out;
    684  1.1     elric     }
    685  1.1     elric 
    686  1.1     elric     if (ctx->type == PKINIT_WIN2K) {
    687  1.1     elric 	PA_PK_AS_REQ_Win2k winreq;
    688  1.1     elric 
    689  1.1     elric 	pa_type = KRB5_PADATA_PK_AS_REQ_WIN;
    690  1.1     elric 
    691  1.1     elric 	memset(&winreq, 0, sizeof(winreq));
    692  1.1     elric 
    693  1.1     elric 	winreq.signed_auth_pack = buf;
    694  1.1     elric 
    695  1.1     elric 	ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length,
    696  1.1     elric 			   &winreq, &size, ret);
    697  1.1     elric 	free_PA_PK_AS_REQ_Win2k(&winreq);
    698  1.1     elric 
    699  1.1     elric     } else if (ctx->type == PKINIT_27) {
    700  1.1     elric 	PA_PK_AS_REQ req;
    701  1.1     elric 
    702  1.1     elric 	pa_type = KRB5_PADATA_PK_AS_REQ;
    703  1.1     elric 
    704  1.1     elric 	memset(&req, 0, sizeof(req));
    705  1.2  christos 	req.signedAuthPack = buf;
    706  1.1     elric 
    707  1.1     elric 	if (ctx->trustedCertifiers) {
    708  1.1     elric 
    709  1.1     elric 	    req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers));
    710  1.1     elric 	    if (req.trustedCertifiers == NULL) {
    711  1.2  christos 		ret = krb5_enomem(context);
    712  1.1     elric 		free_PA_PK_AS_REQ(&req);
    713  1.1     elric 		goto out;
    714  1.1     elric 	    }
    715  1.1     elric 	    ret = build_edi(context, context->hx509ctx,
    716  1.1     elric 			    ctx->id->anchors, req.trustedCertifiers);
    717  1.1     elric 	    if (ret) {
    718  1.1     elric 		krb5_set_error_message(context, ret,
    719  1.1     elric 				       N_("pk-init: failed to build "
    720  1.1     elric 					  "trustedCertifiers", ""));
    721  1.1     elric 		free_PA_PK_AS_REQ(&req);
    722  1.1     elric 		goto out;
    723  1.1     elric 	    }
    724  1.1     elric 	}
    725  1.1     elric 	req.kdcPkId = NULL;
    726  1.1     elric 
    727  1.1     elric 	ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length,
    728  1.1     elric 			   &req, &size, ret);
    729  1.1     elric 
    730  1.1     elric 	free_PA_PK_AS_REQ(&req);
    731  1.1     elric 
    732  1.1     elric     } else
    733  1.1     elric 	krb5_abortx(context, "internal pkinit error");
    734  1.1     elric     if (ret) {
    735  1.1     elric 	krb5_set_error_message(context, ret, "PA-PK-AS-REQ %d", (int)ret);
    736  1.1     elric 	goto out;
    737  1.1     elric     }
    738  1.1     elric     if (buf.length != size)
    739  1.1     elric 	krb5_abortx(context, "Internal ASN1 encoder error");
    740  1.1     elric 
    741  1.1     elric     ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length);
    742  1.1     elric     if (ret)
    743  1.1     elric 	free(buf.data);
    744  1.1     elric 
    745  1.1     elric     if (ret == 0)
    746  1.1     elric     	krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
    747  1.1     elric 
    748  1.1     elric  out:
    749  1.1     elric     free_ContentInfo(&content_info);
    750  1.1     elric 
    751  1.1     elric     return ret;
    752  1.1     elric }
    753  1.1     elric 
    754  1.1     elric 
    755  1.1     elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
    756  1.1     elric _krb5_pk_mk_padata(krb5_context context,
    757  1.1     elric 		   void *c,
    758  1.1     elric 		   int ic_flags,
    759  1.1     elric 		   int win2k,
    760  1.1     elric 		   const KDC_REQ_BODY *req_body,
    761  1.1     elric 		   unsigned nonce,
    762  1.1     elric 		   METHOD_DATA *md)
    763  1.1     elric {
    764  1.1     elric     krb5_pk_init_ctx ctx = c;
    765  1.1     elric     int win2k_compat;
    766  1.1     elric 
    767  1.1     elric     if (ctx->id->certs == NULL && ctx->anonymous == 0) {
    768  1.1     elric 	krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
    769  1.1     elric 			       N_("PKINIT: No user certificate given", ""));
    770  1.1     elric 	return HEIM_PKINIT_NO_PRIVATE_KEY;
    771  1.1     elric     }
    772  1.1     elric 
    773  1.1     elric     win2k_compat = krb5_config_get_bool_default(context, NULL,
    774  1.1     elric 						win2k,
    775  1.1     elric 						"realms",
    776  1.1     elric 						req_body->realm,
    777  1.1     elric 						"pkinit_win2k",
    778  1.1     elric 						NULL);
    779  1.1     elric 
    780  1.1     elric     if (win2k_compat) {
    781  1.1     elric 	ctx->require_binding =
    782  1.1     elric 	    krb5_config_get_bool_default(context, NULL,
    783  1.1     elric 					 TRUE,
    784  1.1     elric 					 "realms",
    785  1.1     elric 					 req_body->realm,
    786  1.1     elric 					 "pkinit_win2k_require_binding",
    787  1.1     elric 					 NULL);
    788  1.1     elric 	ctx->type = PKINIT_WIN2K;
    789  1.1     elric     } else
    790  1.1     elric 	ctx->type = PKINIT_27;
    791  1.1     elric 
    792  1.1     elric     ctx->require_eku =
    793  1.1     elric 	krb5_config_get_bool_default(context, NULL,
    794  1.1     elric 				     TRUE,
    795  1.1     elric 				     "realms",
    796  1.1     elric 				     req_body->realm,
    797  1.1     elric 				     "pkinit_require_eku",
    798  1.1     elric 				     NULL);
    799  1.1     elric     if (ic_flags & KRB5_INIT_CREDS_NO_C_NO_EKU_CHECK)
    800  1.1     elric 	ctx->require_eku = 0;
    801  1.1     elric     if (ctx->id->flags & PKINIT_BTMM)
    802  1.1     elric 	ctx->require_eku = 0;
    803  1.1     elric 
    804  1.1     elric     ctx->require_krbtgt_otherName =
    805  1.1     elric 	krb5_config_get_bool_default(context, NULL,
    806  1.1     elric 				     TRUE,
    807  1.1     elric 				     "realms",
    808  1.1     elric 				     req_body->realm,
    809  1.1     elric 				     "pkinit_require_krbtgt_otherName",
    810  1.1     elric 				     NULL);
    811  1.5  christos     if (ic_flags & KRB5_INIT_CREDS_PKINIT_NO_KRBTGT_OTHERNAME_CHECK)
    812  1.5  christos 	ctx->require_krbtgt_otherName = FALSE;
    813  1.1     elric 
    814  1.1     elric     ctx->require_hostname_match =
    815  1.1     elric 	krb5_config_get_bool_default(context, NULL,
    816  1.1     elric 				     FALSE,
    817  1.1     elric 				     "realms",
    818  1.1     elric 				     req_body->realm,
    819  1.1     elric 				     "pkinit_require_hostname_match",
    820  1.1     elric 				     NULL);
    821  1.1     elric 
    822  1.1     elric     ctx->trustedCertifiers =
    823  1.1     elric 	krb5_config_get_bool_default(context, NULL,
    824  1.1     elric 				     TRUE,
    825  1.1     elric 				     "realms",
    826  1.1     elric 				     req_body->realm,
    827  1.1     elric 				     "pkinit_trustedCertifiers",
    828  1.1     elric 				     NULL);
    829  1.1     elric 
    830  1.1     elric     return pk_mk_padata(context, ctx, req_body, nonce, md);
    831  1.1     elric }
    832  1.1     elric 
    833  1.1     elric static krb5_error_code
    834  1.1     elric pk_verify_sign(krb5_context context,
    835  1.1     elric 	       const void *data,
    836  1.1     elric 	       size_t length,
    837  1.1     elric 	       struct krb5_pk_identity *id,
    838  1.1     elric 	       heim_oid *contentType,
    839  1.1     elric 	       krb5_data *content,
    840  1.1     elric 	       struct krb5_pk_cert **signer)
    841  1.1     elric {
    842  1.1     elric     hx509_certs signer_certs;
    843  1.1     elric     int ret, flags = 0;
    844  1.1     elric 
    845  1.1     elric     /* BTMM is broken in Leo and SnowLeo */
    846  1.1     elric     if (id->flags & PKINIT_BTMM) {
    847  1.1     elric 	flags |= HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH;
    848  1.1     elric 	flags |= HX509_CMS_VS_NO_KU_CHECK;
    849  1.1     elric 	flags |= HX509_CMS_VS_NO_VALIDATE;
    850  1.1     elric     }
    851  1.1     elric 
    852  1.1     elric     *signer = NULL;
    853  1.1     elric 
    854  1.1     elric     ret = hx509_cms_verify_signed(context->hx509ctx,
    855  1.1     elric 				  id->verify_ctx,
    856  1.1     elric 				  flags,
    857  1.1     elric 				  data,
    858  1.1     elric 				  length,
    859  1.1     elric 				  NULL,
    860  1.1     elric 				  id->certpool,
    861  1.1     elric 				  contentType,
    862  1.1     elric 				  content,
    863  1.1     elric 				  &signer_certs);
    864  1.1     elric     if (ret) {
    865  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
    866  1.1     elric 		      "CMS verify signed failed");
    867  1.1     elric 	return ret;
    868  1.1     elric     }
    869  1.1     elric 
    870  1.1     elric     *signer = calloc(1, sizeof(**signer));
    871  1.1     elric     if (*signer == NULL) {
    872  1.1     elric 	krb5_clear_error_message(context);
    873  1.1     elric 	ret = ENOMEM;
    874  1.1     elric 	goto out;
    875  1.1     elric     }
    876  1.2  christos 
    877  1.1     elric     ret = hx509_get_one_cert(context->hx509ctx, signer_certs, &(*signer)->cert);
    878  1.1     elric     if (ret) {
    879  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
    880  1.1     elric 		      "Failed to get on of the signer certs");
    881  1.1     elric 	goto out;
    882  1.1     elric     }
    883  1.1     elric 
    884  1.1     elric  out:
    885  1.1     elric     hx509_certs_free(&signer_certs);
    886  1.1     elric     if (ret) {
    887  1.1     elric 	if (*signer) {
    888  1.1     elric 	    hx509_cert_free((*signer)->cert);
    889  1.1     elric 	    free(*signer);
    890  1.1     elric 	    *signer = NULL;
    891  1.1     elric 	}
    892  1.1     elric     }
    893  1.1     elric 
    894  1.1     elric     return ret;
    895  1.1     elric }
    896  1.1     elric 
    897  1.1     elric static krb5_error_code
    898  1.1     elric get_reply_key_win(krb5_context context,
    899  1.1     elric 		  const krb5_data *content,
    900  1.1     elric 		  unsigned nonce,
    901  1.1     elric 		  krb5_keyblock **key)
    902  1.1     elric {
    903  1.1     elric     ReplyKeyPack_Win2k key_pack;
    904  1.1     elric     krb5_error_code ret;
    905  1.1     elric     size_t size;
    906  1.1     elric 
    907  1.1     elric     ret = decode_ReplyKeyPack_Win2k(content->data,
    908  1.1     elric 				    content->length,
    909  1.1     elric 				    &key_pack,
    910  1.1     elric 				    &size);
    911  1.1     elric     if (ret) {
    912  1.1     elric 	krb5_set_error_message(context, ret,
    913  1.1     elric 			       N_("PKINIT decoding reply key failed", ""));
    914  1.1     elric 	free_ReplyKeyPack_Win2k(&key_pack);
    915  1.1     elric 	return ret;
    916  1.1     elric     }
    917  1.1     elric 
    918  1.2  christos     if ((unsigned)key_pack.nonce != nonce) {
    919  1.1     elric 	krb5_set_error_message(context, ret,
    920  1.1     elric 			       N_("PKINIT enckey nonce is wrong", ""));
    921  1.1     elric 	free_ReplyKeyPack_Win2k(&key_pack);
    922  1.1     elric 	return KRB5KRB_AP_ERR_MODIFIED;
    923  1.1     elric     }
    924  1.1     elric 
    925  1.1     elric     *key = malloc (sizeof (**key));
    926  1.1     elric     if (*key == NULL) {
    927  1.1     elric 	free_ReplyKeyPack_Win2k(&key_pack);
    928  1.2  christos 	return krb5_enomem(context);
    929  1.1     elric     }
    930  1.1     elric 
    931  1.1     elric     ret = copy_EncryptionKey(&key_pack.replyKey, *key);
    932  1.1     elric     free_ReplyKeyPack_Win2k(&key_pack);
    933  1.1     elric     if (ret) {
    934  1.1     elric 	krb5_set_error_message(context, ret,
    935  1.1     elric 			       N_("PKINIT failed copying reply key", ""));
    936  1.1     elric 	free(*key);
    937  1.1     elric 	*key = NULL;
    938  1.1     elric     }
    939  1.1     elric 
    940  1.1     elric     return ret;
    941  1.1     elric }
    942  1.1     elric 
    943  1.1     elric static krb5_error_code
    944  1.1     elric get_reply_key(krb5_context context,
    945  1.1     elric 	      const krb5_data *content,
    946  1.1     elric 	      const krb5_data *req_buffer,
    947  1.1     elric 	      krb5_keyblock **key)
    948  1.1     elric {
    949  1.1     elric     ReplyKeyPack key_pack;
    950  1.1     elric     krb5_error_code ret;
    951  1.1     elric     size_t size;
    952  1.1     elric 
    953  1.1     elric     ret = decode_ReplyKeyPack(content->data,
    954  1.1     elric 			      content->length,
    955  1.1     elric 			      &key_pack,
    956  1.1     elric 			      &size);
    957  1.1     elric     if (ret) {
    958  1.1     elric 	krb5_set_error_message(context, ret,
    959  1.1     elric 			       N_("PKINIT decoding reply key failed", ""));
    960  1.1     elric 	free_ReplyKeyPack(&key_pack);
    961  1.1     elric 	return ret;
    962  1.1     elric     }
    963  1.1     elric 
    964  1.1     elric     {
    965  1.1     elric 	krb5_crypto crypto;
    966  1.1     elric 
    967  1.1     elric 	/*
    968  1.1     elric 	 * XXX Verify kp.replyKey is a allowed enctype in the
    969  1.1     elric 	 * configuration file
    970  1.1     elric 	 */
    971  1.1     elric 
    972  1.1     elric 	ret = krb5_crypto_init(context, &key_pack.replyKey, 0, &crypto);
    973  1.1     elric 	if (ret) {
    974  1.1     elric 	    free_ReplyKeyPack(&key_pack);
    975  1.1     elric 	    return ret;
    976  1.1     elric 	}
    977  1.1     elric 
    978  1.1     elric 	ret = krb5_verify_checksum(context, crypto, 6,
    979  1.1     elric 				   req_buffer->data, req_buffer->length,
    980  1.1     elric 				   &key_pack.asChecksum);
    981  1.1     elric 	krb5_crypto_destroy(context, crypto);
    982  1.1     elric 	if (ret) {
    983  1.1     elric 	    free_ReplyKeyPack(&key_pack);
    984  1.1     elric 	    return ret;
    985  1.1     elric 	}
    986  1.1     elric     }
    987  1.1     elric 
    988  1.1     elric     *key = malloc (sizeof (**key));
    989  1.1     elric     if (*key == NULL) {
    990  1.1     elric 	free_ReplyKeyPack(&key_pack);
    991  1.2  christos 	return krb5_enomem(context);
    992  1.1     elric     }
    993  1.1     elric 
    994  1.1     elric     ret = copy_EncryptionKey(&key_pack.replyKey, *key);
    995  1.1     elric     free_ReplyKeyPack(&key_pack);
    996  1.1     elric     if (ret) {
    997  1.1     elric 	krb5_set_error_message(context, ret,
    998  1.1     elric 			       N_("PKINIT failed copying reply key", ""));
    999  1.1     elric 	free(*key);
   1000  1.1     elric 	*key = NULL;
   1001  1.1     elric     }
   1002  1.1     elric 
   1003  1.1     elric     return ret;
   1004  1.1     elric }
   1005  1.1     elric 
   1006  1.1     elric 
   1007  1.1     elric static krb5_error_code
   1008  1.1     elric pk_verify_host(krb5_context context,
   1009  1.1     elric 	       const char *realm,
   1010  1.1     elric 	       const krb5_krbhst_info *hi,
   1011  1.1     elric 	       struct krb5_pk_init_ctx_data *ctx,
   1012  1.1     elric 	       struct krb5_pk_cert *host)
   1013  1.1     elric {
   1014  1.1     elric     krb5_error_code ret = 0;
   1015  1.1     elric 
   1016  1.1     elric     if (ctx->require_eku) {
   1017  1.1     elric 	ret = hx509_cert_check_eku(context->hx509ctx, host->cert,
   1018  1.1     elric 				   &asn1_oid_id_pkkdcekuoid, 0);
   1019  1.1     elric 	if (ret) {
   1020  1.1     elric 	    krb5_set_error_message(context, ret,
   1021  1.1     elric 				   N_("No PK-INIT KDC EKU in kdc certificate", ""));
   1022  1.1     elric 	    return ret;
   1023  1.1     elric 	}
   1024  1.1     elric     }
   1025  1.1     elric     if (ctx->require_krbtgt_otherName) {
   1026  1.1     elric 	hx509_octet_string_list list;
   1027  1.2  christos 	size_t i;
   1028  1.2  christos 	int matched = 0;
   1029  1.1     elric 
   1030  1.1     elric 	ret = hx509_cert_find_subjectAltName_otherName(context->hx509ctx,
   1031  1.1     elric 						       host->cert,
   1032  1.1     elric 						       &asn1_oid_id_pkinit_san,
   1033  1.1     elric 						       &list);
   1034  1.1     elric 	if (ret) {
   1035  1.1     elric 	    krb5_set_error_message(context, ret,
   1036  1.1     elric 				   N_("Failed to find the PK-INIT "
   1037  1.1     elric 				      "subjectAltName in the KDC "
   1038  1.1     elric 				      "certificate", ""));
   1039  1.1     elric 
   1040  1.1     elric 	    return ret;
   1041  1.1     elric 	}
   1042  1.1     elric 
   1043  1.2  christos 	/*
   1044  1.2  christos 	 * subjectAltNames are multi-valued, and a single KDC may serve
   1045  1.2  christos 	 * multiple realms. The SAN validation here must accept
   1046  1.2  christos 	 * the KDC's cert if *any* of the SANs match the expected KDC.
   1047  1.2  christos 	 * It is OK for *some* of the SANs to not match, provided at least
   1048  1.2  christos 	 * one does.
   1049  1.2  christos 	 */
   1050  1.2  christos 	for (i = 0; matched == 0 && i < list.len; i++) {
   1051  1.1     elric 	    KRB5PrincipalName r;
   1052  1.1     elric 
   1053  1.1     elric 	    ret = decode_KRB5PrincipalName(list.val[i].data,
   1054  1.1     elric 					   list.val[i].length,
   1055  1.1     elric 					   &r,
   1056  1.1     elric 					   NULL);
   1057  1.1     elric 	    if (ret) {
   1058  1.1     elric 		krb5_set_error_message(context, ret,
   1059  1.1     elric 				       N_("Failed to decode the PK-INIT "
   1060  1.1     elric 					  "subjectAltName in the "
   1061  1.1     elric 					  "KDC certificate", ""));
   1062  1.1     elric 
   1063  1.1     elric 		break;
   1064  1.1     elric 	    }
   1065  1.1     elric 
   1066  1.2  christos 	    if (r.principalName.name_string.len == 2 &&
   1067  1.2  christos 		strcmp(r.principalName.name_string.val[0], KRB5_TGS_NAME) == 0
   1068  1.2  christos 		&& strcmp(r.principalName.name_string.val[1], realm) == 0
   1069  1.2  christos 		&& strcmp(r.realm, realm) == 0)
   1070  1.2  christos 		matched = 1;
   1071  1.1     elric 
   1072  1.1     elric 	    free_KRB5PrincipalName(&r);
   1073  1.1     elric 	}
   1074  1.1     elric 	hx509_free_octet_string_list(&list);
   1075  1.2  christos 	if (matched == 0) {
   1076  1.2  christos 	    ret = KRB5_KDC_ERR_INVALID_CERTIFICATE;
   1077  1.2  christos 	    /* XXX: Lost in translation... */
   1078  1.2  christos 	    krb5_set_error_message(context, ret,
   1079  1.2  christos 				   N_("KDC have wrong realm name in "
   1080  1.2  christos 				      "the certificate", ""));
   1081  1.2  christos 	}
   1082  1.1     elric     }
   1083  1.1     elric     if (ret)
   1084  1.1     elric 	return ret;
   1085  1.1     elric 
   1086  1.1     elric     if (hi) {
   1087  1.1     elric 	ret = hx509_verify_hostname(context->hx509ctx, host->cert,
   1088  1.1     elric 				    ctx->require_hostname_match,
   1089  1.1     elric 				    HX509_HN_HOSTNAME,
   1090  1.1     elric 				    hi->hostname,
   1091  1.1     elric 				    hi->ai->ai_addr, hi->ai->ai_addrlen);
   1092  1.1     elric 
   1093  1.1     elric 	if (ret)
   1094  1.1     elric 	    krb5_set_error_message(context, ret,
   1095  1.1     elric 				   N_("Address mismatch in "
   1096  1.1     elric 				      "the KDC certificate", ""));
   1097  1.1     elric     }
   1098  1.1     elric     return ret;
   1099  1.1     elric }
   1100  1.1     elric 
   1101  1.1     elric static krb5_error_code
   1102  1.1     elric pk_rd_pa_reply_enckey(krb5_context context,
   1103  1.1     elric 		      int type,
   1104  1.1     elric 		      const heim_octet_string *indata,
   1105  1.1     elric 		      const heim_oid *dataType,
   1106  1.1     elric 		      const char *realm,
   1107  1.1     elric 		      krb5_pk_init_ctx ctx,
   1108  1.1     elric 		      krb5_enctype etype,
   1109  1.1     elric 		      const krb5_krbhst_info *hi,
   1110  1.1     elric 	       	      unsigned nonce,
   1111  1.1     elric 		      const krb5_data *req_buffer,
   1112  1.1     elric 	       	      PA_DATA *pa,
   1113  1.1     elric 	       	      krb5_keyblock **key)
   1114  1.1     elric {
   1115  1.1     elric     krb5_error_code ret;
   1116  1.1     elric     struct krb5_pk_cert *host = NULL;
   1117  1.1     elric     krb5_data content;
   1118  1.1     elric     heim_oid contentType = { 0, NULL };
   1119  1.1     elric     int flags = HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT;
   1120  1.1     elric 
   1121  1.1     elric     if (der_heim_oid_cmp(&asn1_oid_id_pkcs7_envelopedData, dataType)) {
   1122  1.1     elric 	krb5_set_error_message(context, EINVAL,
   1123  1.1     elric 			       N_("PKINIT: Invalid content type", ""));
   1124  1.1     elric 	return EINVAL;
   1125  1.1     elric     }
   1126  1.1     elric 
   1127  1.1     elric     if (ctx->type == PKINIT_WIN2K)
   1128  1.1     elric 	flags |= HX509_CMS_UE_ALLOW_WEAK;
   1129  1.1     elric 
   1130  1.1     elric     ret = hx509_cms_unenvelope(context->hx509ctx,
   1131  1.1     elric 			       ctx->id->certs,
   1132  1.1     elric 			       flags,
   1133  1.1     elric 			       indata->data,
   1134  1.1     elric 			       indata->length,
   1135  1.1     elric 			       NULL,
   1136  1.1     elric 			       0,
   1137  1.1     elric 			       &contentType,
   1138  1.1     elric 			       &content);
   1139  1.1     elric     if (ret) {
   1140  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   1141  1.1     elric 		      "Failed to unenvelope CMS data in PK-INIT reply");
   1142  1.1     elric 	return ret;
   1143  1.1     elric     }
   1144  1.1     elric     der_free_oid(&contentType);
   1145  1.1     elric 
   1146  1.1     elric     /* win2k uses ContentInfo */
   1147  1.1     elric     if (type == PKINIT_WIN2K) {
   1148  1.1     elric 	heim_oid type2;
   1149  1.1     elric 	heim_octet_string out;
   1150  1.1     elric 
   1151  1.1     elric 	ret = hx509_cms_unwrap_ContentInfo(&content, &type2, &out, NULL);
   1152  1.1     elric 	if (ret) {
   1153  1.1     elric 	    /* windows LH with interesting CMS packets */
   1154  1.1     elric 	    size_t ph = 1 + der_length_len(content.length);
   1155  1.1     elric 	    unsigned char *ptr = malloc(content.length + ph);
   1156  1.1     elric 	    size_t l;
   1157  1.2  christos 
   1158  1.1     elric 	    memcpy(ptr + ph, content.data, content.length);
   1159  1.2  christos 
   1160  1.1     elric 	    ret = der_put_length_and_tag (ptr + ph - 1, ph, content.length,
   1161  1.1     elric 					  ASN1_C_UNIV, CONS, UT_Sequence, &l);
   1162  1.2  christos 	    if (ret) {
   1163  1.2  christos                 free(ptr);
   1164  1.1     elric 		return ret;
   1165  1.2  christos             }
   1166  1.1     elric 	    free(content.data);
   1167  1.1     elric 	    content.data = ptr;
   1168  1.1     elric 	    content.length += ph;
   1169  1.1     elric 
   1170  1.1     elric 	    ret = hx509_cms_unwrap_ContentInfo(&content, &type2, &out, NULL);
   1171  1.1     elric 	    if (ret)
   1172  1.1     elric 		goto out;
   1173  1.1     elric 	}
   1174  1.1     elric 	if (der_heim_oid_cmp(&type2, &asn1_oid_id_pkcs7_signedData)) {
   1175  1.1     elric 	    ret = EINVAL; /* XXX */
   1176  1.1     elric 	    krb5_set_error_message(context, ret,
   1177  1.1     elric 				   N_("PKINIT: Invalid content type", ""));
   1178  1.1     elric 	    der_free_oid(&type2);
   1179  1.1     elric 	    der_free_octet_string(&out);
   1180  1.1     elric 	    goto out;
   1181  1.1     elric 	}
   1182  1.1     elric 	der_free_oid(&type2);
   1183  1.1     elric 	krb5_data_free(&content);
   1184  1.1     elric 	ret = krb5_data_copy(&content, out.data, out.length);
   1185  1.1     elric 	der_free_octet_string(&out);
   1186  1.1     elric 	if (ret) {
   1187  1.1     elric 	    krb5_set_error_message(context, ret,
   1188  1.1     elric 				   N_("malloc: out of memory", ""));
   1189  1.1     elric 	    goto out;
   1190  1.1     elric 	}
   1191  1.1     elric     }
   1192  1.1     elric 
   1193  1.1     elric     ret = pk_verify_sign(context,
   1194  1.1     elric 			 content.data,
   1195  1.1     elric 			 content.length,
   1196  1.1     elric 			 ctx->id,
   1197  1.1     elric 			 &contentType,
   1198  1.1     elric 			 &content,
   1199  1.1     elric 			 &host);
   1200  1.1     elric     if (ret)
   1201  1.1     elric 	goto out;
   1202  1.1     elric 
   1203  1.1     elric     /* make sure that it is the kdc's certificate */
   1204  1.1     elric     ret = pk_verify_host(context, realm, hi, ctx, host);
   1205  1.1     elric     if (ret) {
   1206  1.1     elric 	goto out;
   1207  1.1     elric     }
   1208  1.1     elric 
   1209  1.1     elric #if 0
   1210  1.1     elric     if (type == PKINIT_WIN2K) {
   1211  1.1     elric 	if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) != 0) {
   1212  1.1     elric 	    ret = KRB5KRB_AP_ERR_MSG_TYPE;
   1213  1.1     elric 	    krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid");
   1214  1.1     elric 	    goto out;
   1215  1.1     elric 	}
   1216  1.1     elric     } else {
   1217  1.1     elric 	if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkrkeydata) != 0) {
   1218  1.1     elric 	    ret = KRB5KRB_AP_ERR_MSG_TYPE;
   1219  1.1     elric 	    krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid");
   1220  1.1     elric 	    goto out;
   1221  1.1     elric 	}
   1222  1.1     elric     }
   1223  1.1     elric #endif
   1224  1.1     elric 
   1225  1.1     elric     switch(type) {
   1226  1.1     elric     case PKINIT_WIN2K:
   1227  1.1     elric 	ret = get_reply_key(context, &content, req_buffer, key);
   1228  1.1     elric 	if (ret != 0 && ctx->require_binding == 0)
   1229  1.1     elric 	    ret = get_reply_key_win(context, &content, nonce, key);
   1230  1.1     elric 	break;
   1231  1.1     elric     case PKINIT_27:
   1232  1.1     elric 	ret = get_reply_key(context, &content, req_buffer, key);
   1233  1.1     elric 	break;
   1234  1.1     elric     }
   1235  1.1     elric     if (ret)
   1236  1.1     elric 	goto out;
   1237  1.1     elric 
   1238  1.1     elric     /* XXX compare given etype with key->etype */
   1239  1.1     elric 
   1240  1.1     elric  out:
   1241  1.1     elric     if (host)
   1242  1.1     elric 	_krb5_pk_cert_free(host);
   1243  1.1     elric     der_free_oid(&contentType);
   1244  1.1     elric     krb5_data_free(&content);
   1245  1.1     elric 
   1246  1.1     elric     return ret;
   1247  1.1     elric }
   1248  1.1     elric 
   1249  1.5  christos /*
   1250  1.5  christos  * RFC 8062 section 7:
   1251  1.5  christos  *
   1252  1.5  christos  *  The client then decrypts the KDC contribution key and verifies that
   1253  1.5  christos  *  the ticket session key in the returned ticket is the combined key of
   1254  1.5  christos  *  the KDC contribution key and the reply key.
   1255  1.5  christos  */
   1256  1.5  christos KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   1257  1.5  christos _krb5_pk_kx_confirm(krb5_context context,
   1258  1.5  christos 		    krb5_pk_init_ctx ctx,
   1259  1.5  christos 		    krb5_keyblock *reply_key,
   1260  1.5  christos 		    krb5_keyblock *session_key,
   1261  1.5  christos 		    PA_DATA *pa_pkinit_kx)
   1262  1.5  christos {
   1263  1.5  christos     krb5_error_code ret;
   1264  1.5  christos     EncryptedData ed;
   1265  1.5  christos     krb5_keyblock ck, sk_verify;
   1266  1.5  christos     krb5_crypto ck_crypto = NULL;
   1267  1.5  christos     krb5_crypto rk_crypto = NULL;
   1268  1.5  christos     size_t len;
   1269  1.5  christos     krb5_data data;
   1270  1.5  christos     krb5_data p1 = { sizeof("PKINIT") - 1, "PKINIT" };
   1271  1.5  christos     krb5_data p2 = { sizeof("KEYEXCHANGE") - 1, "KEYEXCHANGE" };
   1272  1.5  christos 
   1273  1.5  christos     heim_assert(ctx != NULL, "PKINIT context is non-NULL");
   1274  1.5  christos     heim_assert(reply_key != NULL, "reply key is non-NULL");
   1275  1.5  christos     heim_assert(session_key != NULL, "session key is non-NULL");
   1276  1.5  christos 
   1277  1.5  christos     /* PA-PKINIT-KX is optional unless anonymous */
   1278  1.5  christos     if (pa_pkinit_kx == NULL)
   1279  1.5  christos 	return ctx->anonymous ? KRB5_KDCREP_MODIFIED : 0;
   1280  1.5  christos 
   1281  1.5  christos     memset(&ed, 0, sizeof(ed));
   1282  1.5  christos     krb5_keyblock_zero(&ck);
   1283  1.5  christos     krb5_keyblock_zero(&sk_verify);
   1284  1.5  christos     krb5_data_zero(&data);
   1285  1.5  christos 
   1286  1.5  christos     ret = decode_EncryptedData(pa_pkinit_kx->padata_value.data,
   1287  1.5  christos 			       pa_pkinit_kx->padata_value.length,
   1288  1.5  christos 			       &ed, &len);
   1289  1.5  christos     if (ret)
   1290  1.5  christos 	goto out;
   1291  1.5  christos 
   1292  1.5  christos     if (len != pa_pkinit_kx->padata_value.length) {
   1293  1.5  christos 	ret = KRB5_KDCREP_MODIFIED;
   1294  1.5  christos 	goto out;
   1295  1.5  christos     }
   1296  1.5  christos 
   1297  1.5  christos     ret = krb5_crypto_init(context, reply_key, 0, &rk_crypto);
   1298  1.5  christos     if (ret)
   1299  1.5  christos 	goto out;
   1300  1.5  christos 
   1301  1.5  christos     ret = krb5_decrypt_EncryptedData(context, rk_crypto,
   1302  1.5  christos 				     KRB5_KU_PA_PKINIT_KX,
   1303  1.5  christos 				     &ed, &data);
   1304  1.5  christos     if (ret)
   1305  1.5  christos 	goto out;
   1306  1.5  christos 
   1307  1.5  christos     ret = decode_EncryptionKey(data.data, data.length,
   1308  1.5  christos 			       &ck, &len);
   1309  1.5  christos     if (ret)
   1310  1.5  christos 	goto out;
   1311  1.5  christos 
   1312  1.5  christos     ret = krb5_crypto_init(context, &ck, 0, &ck_crypto);
   1313  1.5  christos     if (ret)
   1314  1.5  christos 	goto out;
   1315  1.5  christos 
   1316  1.5  christos     ret = krb5_crypto_fx_cf2(context, ck_crypto, rk_crypto,
   1317  1.5  christos 			     &p1, &p2, session_key->keytype,
   1318  1.5  christos 			     &sk_verify);
   1319  1.5  christos     if (ret)
   1320  1.5  christos 	goto out;
   1321  1.5  christos 
   1322  1.5  christos     if (sk_verify.keytype != session_key->keytype ||
   1323  1.5  christos 	krb5_data_ct_cmp(&sk_verify.keyvalue, &session_key->keyvalue) != 0) {
   1324  1.5  christos 	ret = KRB5_KDCREP_MODIFIED;
   1325  1.5  christos 	goto out;
   1326  1.5  christos     }
   1327  1.5  christos 
   1328  1.5  christos out:
   1329  1.5  christos     free_EncryptedData(&ed);
   1330  1.5  christos     krb5_free_keyblock_contents(context, &ck);
   1331  1.5  christos     krb5_free_keyblock_contents(context, &sk_verify);
   1332  1.5  christos     if (ck_crypto)
   1333  1.5  christos 	krb5_crypto_destroy(context, ck_crypto);
   1334  1.5  christos     if (rk_crypto)
   1335  1.5  christos 	krb5_crypto_destroy(context, rk_crypto);
   1336  1.5  christos     krb5_data_free(&data);
   1337  1.5  christos 
   1338  1.5  christos     return ret;
   1339  1.5  christos }
   1340  1.5  christos 
   1341  1.1     elric static krb5_error_code
   1342  1.1     elric pk_rd_pa_reply_dh(krb5_context context,
   1343  1.1     elric 		  const heim_octet_string *indata,
   1344  1.1     elric 		  const heim_oid *dataType,
   1345  1.1     elric 		  const char *realm,
   1346  1.1     elric 		  krb5_pk_init_ctx ctx,
   1347  1.1     elric 		  krb5_enctype etype,
   1348  1.1     elric 		  const krb5_krbhst_info *hi,
   1349  1.1     elric 		  const DHNonce *c_n,
   1350  1.1     elric 		  const DHNonce *k_n,
   1351  1.1     elric                   unsigned nonce,
   1352  1.1     elric                   PA_DATA *pa,
   1353  1.1     elric                   krb5_keyblock **key)
   1354  1.1     elric {
   1355  1.1     elric     const unsigned char *p;
   1356  1.1     elric     unsigned char *dh_gen_key = NULL;
   1357  1.1     elric     struct krb5_pk_cert *host = NULL;
   1358  1.1     elric     BIGNUM *kdc_dh_pubkey = NULL;
   1359  1.1     elric     KDCDHKeyInfo kdc_dh_info;
   1360  1.1     elric     heim_oid contentType = { 0, NULL };
   1361  1.1     elric     krb5_data content;
   1362  1.1     elric     krb5_error_code ret;
   1363  1.1     elric     int dh_gen_keylen = 0;
   1364  1.1     elric     size_t size;
   1365  1.1     elric 
   1366  1.1     elric     krb5_data_zero(&content);
   1367  1.1     elric     memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
   1368  1.1     elric 
   1369  1.1     elric     if (der_heim_oid_cmp(&asn1_oid_id_pkcs7_signedData, dataType)) {
   1370  1.1     elric 	krb5_set_error_message(context, EINVAL,
   1371  1.1     elric 			       N_("PKINIT: Invalid content type", ""));
   1372  1.1     elric 	return EINVAL;
   1373  1.1     elric     }
   1374  1.1     elric 
   1375  1.1     elric     ret = pk_verify_sign(context,
   1376  1.1     elric 			 indata->data,
   1377  1.1     elric 			 indata->length,
   1378  1.1     elric 			 ctx->id,
   1379  1.1     elric 			 &contentType,
   1380  1.1     elric 			 &content,
   1381  1.1     elric 			 &host);
   1382  1.1     elric     if (ret)
   1383  1.1     elric 	goto out;
   1384  1.1     elric 
   1385  1.1     elric     /* make sure that it is the kdc's certificate */
   1386  1.1     elric     ret = pk_verify_host(context, realm, hi, ctx, host);
   1387  1.1     elric     if (ret)
   1388  1.1     elric 	goto out;
   1389  1.1     elric 
   1390  1.1     elric     if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkdhkeydata)) {
   1391  1.1     elric 	ret = KRB5KRB_AP_ERR_MSG_TYPE;
   1392  1.1     elric 	krb5_set_error_message(context, ret,
   1393  1.1     elric 			       N_("pkinit - dh reply contains wrong oid", ""));
   1394  1.1     elric 	goto out;
   1395  1.1     elric     }
   1396  1.1     elric 
   1397  1.1     elric     ret = decode_KDCDHKeyInfo(content.data,
   1398  1.1     elric 			      content.length,
   1399  1.1     elric 			      &kdc_dh_info,
   1400  1.1     elric 			      &size);
   1401  1.1     elric 
   1402  1.1     elric     if (ret) {
   1403  1.1     elric 	krb5_set_error_message(context, ret,
   1404  1.1     elric 			       N_("pkinit - failed to decode "
   1405  1.1     elric 				  "KDC DH Key Info", ""));
   1406  1.1     elric 	goto out;
   1407  1.1     elric     }
   1408  1.1     elric 
   1409  1.1     elric     if (kdc_dh_info.nonce != nonce) {
   1410  1.1     elric 	ret = KRB5KRB_AP_ERR_MODIFIED;
   1411  1.1     elric 	krb5_set_error_message(context, ret,
   1412  1.1     elric 			       N_("PKINIT: DH nonce is wrong", ""));
   1413  1.1     elric 	goto out;
   1414  1.1     elric     }
   1415  1.1     elric 
   1416  1.1     elric     if (kdc_dh_info.dhKeyExpiration) {
   1417  1.1     elric 	if (k_n == NULL) {
   1418  1.1     elric 	    ret = KRB5KRB_ERR_GENERIC;
   1419  1.1     elric 	    krb5_set_error_message(context, ret,
   1420  1.1     elric 				   N_("pkinit; got key expiration "
   1421  1.1     elric 				      "without server nonce", ""));
   1422  1.1     elric 	    goto out;
   1423  1.1     elric 	}
   1424  1.1     elric 	if (c_n == NULL) {
   1425  1.1     elric 	    ret = KRB5KRB_ERR_GENERIC;
   1426  1.1     elric 	    krb5_set_error_message(context, ret,
   1427  1.1     elric 				   N_("pkinit; got DH reuse but no "
   1428  1.1     elric 				      "client nonce", ""));
   1429  1.1     elric 	    goto out;
   1430  1.1     elric 	}
   1431  1.1     elric     } else {
   1432  1.1     elric 	if (k_n) {
   1433  1.1     elric 	    ret = KRB5KRB_ERR_GENERIC;
   1434  1.1     elric 	    krb5_set_error_message(context, ret,
   1435  1.1     elric 				   N_("pkinit: got server nonce "
   1436  1.1     elric 				      "without key expiration", ""));
   1437  1.1     elric 	    goto out;
   1438  1.1     elric 	}
   1439  1.1     elric 	c_n = NULL;
   1440  1.1     elric     }
   1441  1.1     elric 
   1442  1.1     elric 
   1443  1.1     elric     p = kdc_dh_info.subjectPublicKey.data;
   1444  1.1     elric     size = (kdc_dh_info.subjectPublicKey.length + 7) / 8;
   1445  1.1     elric 
   1446  1.1     elric     if (ctx->keyex == USE_DH) {
   1447  1.1     elric 	DHPublicKey k;
   1448  1.1     elric 	ret = decode_DHPublicKey(p, size, &k, NULL);
   1449  1.1     elric 	if (ret) {
   1450  1.1     elric 	    krb5_set_error_message(context, ret,
   1451  1.1     elric 				   N_("pkinit: can't decode "
   1452  1.1     elric 				      "without key expiration", ""));
   1453  1.1     elric 	    goto out;
   1454  1.1     elric 	}
   1455  1.1     elric 
   1456  1.1     elric 	kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k);
   1457  1.1     elric 	free_DHPublicKey(&k);
   1458  1.1     elric 	if (kdc_dh_pubkey == NULL) {
   1459  1.1     elric 	    ret = ENOMEM;
   1460  1.1     elric 	    goto out;
   1461  1.1     elric 	}
   1462  1.1     elric 
   1463  1.1     elric 
   1464  1.1     elric 	size = DH_size(ctx->u.dh);
   1465  1.1     elric 
   1466  1.1     elric 	dh_gen_key = malloc(size);
   1467  1.1     elric 	if (dh_gen_key == NULL) {
   1468  1.2  christos 	    ret = krb5_enomem(context);
   1469  1.1     elric 	    goto out;
   1470  1.1     elric 	}
   1471  1.2  christos 
   1472  1.1     elric 	dh_gen_keylen = DH_compute_key(dh_gen_key, kdc_dh_pubkey, ctx->u.dh);
   1473  1.1     elric 	if (dh_gen_keylen == -1) {
   1474  1.1     elric 	    ret = KRB5KRB_ERR_GENERIC;
   1475  1.1     elric 	    dh_gen_keylen = 0;
   1476  1.1     elric 	    krb5_set_error_message(context, ret,
   1477  1.1     elric 				   N_("PKINIT: Can't compute Diffie-Hellman key", ""));
   1478  1.1     elric 	    goto out;
   1479  1.1     elric 	}
   1480  1.2  christos 	if (dh_gen_keylen < (int)size) {
   1481  1.1     elric 	    size -= dh_gen_keylen;
   1482  1.1     elric 	    memmove(dh_gen_key + size, dh_gen_key, dh_gen_keylen);
   1483  1.1     elric 	    memset(dh_gen_key, 0, size);
   1484  1.1     elric 	}
   1485  1.1     elric 
   1486  1.1     elric     } else {
   1487  1.2  christos         ret = _krb5_pk_rd_pa_reply_ecdh_compute_key(context, ctx, p,
   1488  1.2  christos                                                     size, &dh_gen_key,
   1489  1.2  christos                                                     &dh_gen_keylen);
   1490  1.2  christos         if (ret)
   1491  1.2  christos           goto out;
   1492  1.2  christos     }
   1493  1.1     elric 
   1494  1.1     elric     if (dh_gen_keylen <= 0) {
   1495  1.1     elric 	ret = EINVAL;
   1496  1.1     elric 	krb5_set_error_message(context, ret,
   1497  1.1     elric 			       N_("PKINIT: resulting DH key <= 0", ""));
   1498  1.1     elric 	dh_gen_keylen = 0;
   1499  1.1     elric 	goto out;
   1500  1.1     elric     }
   1501  1.1     elric 
   1502  1.1     elric     *key = malloc (sizeof (**key));
   1503  1.1     elric     if (*key == NULL) {
   1504  1.2  christos 	ret = krb5_enomem(context);
   1505  1.1     elric 	goto out;
   1506  1.1     elric     }
   1507  1.1     elric 
   1508  1.1     elric     ret = _krb5_pk_octetstring2key(context,
   1509  1.1     elric 				   etype,
   1510  1.1     elric 				   dh_gen_key, dh_gen_keylen,
   1511  1.1     elric 				   c_n, k_n,
   1512  1.1     elric 				   *key);
   1513  1.1     elric     if (ret) {
   1514  1.1     elric 	krb5_set_error_message(context, ret,
   1515  1.1     elric 			       N_("PKINIT: can't create key from DH key", ""));
   1516  1.1     elric 	free(*key);
   1517  1.1     elric 	*key = NULL;
   1518  1.1     elric 	goto out;
   1519  1.1     elric     }
   1520  1.1     elric 
   1521  1.1     elric  out:
   1522  1.1     elric     if (kdc_dh_pubkey)
   1523  1.1     elric 	BN_free(kdc_dh_pubkey);
   1524  1.1     elric     if (dh_gen_key) {
   1525  1.1     elric 	memset(dh_gen_key, 0, dh_gen_keylen);
   1526  1.1     elric 	free(dh_gen_key);
   1527  1.1     elric     }
   1528  1.1     elric     if (host)
   1529  1.1     elric 	_krb5_pk_cert_free(host);
   1530  1.1     elric     if (content.data)
   1531  1.1     elric 	krb5_data_free(&content);
   1532  1.1     elric     der_free_oid(&contentType);
   1533  1.1     elric     free_KDCDHKeyInfo(&kdc_dh_info);
   1534  1.1     elric 
   1535  1.1     elric     return ret;
   1536  1.1     elric }
   1537  1.1     elric 
   1538  1.1     elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   1539  1.1     elric _krb5_pk_rd_pa_reply(krb5_context context,
   1540  1.1     elric 		     const char *realm,
   1541  1.1     elric 		     void *c,
   1542  1.1     elric 		     krb5_enctype etype,
   1543  1.1     elric 		     const krb5_krbhst_info *hi,
   1544  1.1     elric 		     unsigned nonce,
   1545  1.1     elric 		     const krb5_data *req_buffer,
   1546  1.1     elric 		     PA_DATA *pa,
   1547  1.1     elric 		     krb5_keyblock **key)
   1548  1.1     elric {
   1549  1.1     elric     krb5_pk_init_ctx ctx = c;
   1550  1.1     elric     krb5_error_code ret;
   1551  1.1     elric     size_t size;
   1552  1.1     elric 
   1553  1.1     elric     /* Check for IETF PK-INIT first */
   1554  1.1     elric     if (ctx->type == PKINIT_27) {
   1555  1.1     elric 	PA_PK_AS_REP rep;
   1556  1.1     elric 	heim_octet_string os, data;
   1557  1.1     elric 	heim_oid oid;
   1558  1.2  christos 
   1559  1.1     elric 	if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
   1560  1.1     elric 	    krb5_set_error_message(context, EINVAL,
   1561  1.1     elric 				   N_("PKINIT: wrong padata recv", ""));
   1562  1.1     elric 	    return EINVAL;
   1563  1.1     elric 	}
   1564  1.1     elric 
   1565  1.1     elric 	ret = decode_PA_PK_AS_REP(pa->padata_value.data,
   1566  1.1     elric 				  pa->padata_value.length,
   1567  1.1     elric 				  &rep,
   1568  1.1     elric 				  &size);
   1569  1.1     elric 	if (ret) {
   1570  1.1     elric 	    krb5_set_error_message(context, ret,
   1571  1.1     elric 				   N_("Failed to decode pkinit AS rep", ""));
   1572  1.1     elric 	    return ret;
   1573  1.1     elric 	}
   1574  1.1     elric 
   1575  1.1     elric 	switch (rep.element) {
   1576  1.1     elric 	case choice_PA_PK_AS_REP_dhInfo:
   1577  1.1     elric 	    _krb5_debug(context, 5, "krb5_get_init_creds: using pkinit dh");
   1578  1.1     elric 	    os = rep.u.dhInfo.dhSignedData;
   1579  1.1     elric 	    break;
   1580  1.1     elric 	case choice_PA_PK_AS_REP_encKeyPack:
   1581  1.1     elric 	    _krb5_debug(context, 5, "krb5_get_init_creds: using kinit enc reply key");
   1582  1.1     elric 	    os = rep.u.encKeyPack;
   1583  1.1     elric 	    break;
   1584  1.1     elric 	default: {
   1585  1.1     elric 	    PA_PK_AS_REP_BTMM btmm;
   1586  1.1     elric 	    free_PA_PK_AS_REP(&rep);
   1587  1.1     elric 	    memset(&rep, 0, sizeof(rep));
   1588  1.2  christos 
   1589  1.1     elric 	    _krb5_debug(context, 5, "krb5_get_init_creds: using BTMM kinit enc reply key");
   1590  1.1     elric 
   1591  1.1     elric 	    ret = decode_PA_PK_AS_REP_BTMM(pa->padata_value.data,
   1592  1.1     elric 					   pa->padata_value.length,
   1593  1.1     elric 					   &btmm,
   1594  1.1     elric 					   &size);
   1595  1.1     elric 	    if (ret) {
   1596  1.1     elric 		krb5_set_error_message(context, EINVAL,
   1597  1.1     elric 				       N_("PKINIT: -27 reply "
   1598  1.1     elric 					  "invalid content type", ""));
   1599  1.1     elric 		return EINVAL;
   1600  1.1     elric 	    }
   1601  1.1     elric 
   1602  1.1     elric 	    if (btmm.dhSignedData || btmm.encKeyPack == NULL) {
   1603  1.1     elric 		free_PA_PK_AS_REP_BTMM(&btmm);
   1604  1.1     elric 		ret = EINVAL;
   1605  1.1     elric 		krb5_set_error_message(context, ret,
   1606  1.1     elric 				       N_("DH mode not supported for BTMM mode", ""));
   1607  1.1     elric 		return ret;
   1608  1.1     elric 	    }
   1609  1.1     elric 
   1610  1.1     elric 	    /*
   1611  1.1     elric 	     * Transform to IETF style PK-INIT reply so that free works below
   1612  1.1     elric 	     */
   1613  1.1     elric 
   1614  1.1     elric 	    rep.element = choice_PA_PK_AS_REP_encKeyPack;
   1615  1.1     elric 	    rep.u.encKeyPack.data = btmm.encKeyPack->data;
   1616  1.1     elric 	    rep.u.encKeyPack.length = btmm.encKeyPack->length;
   1617  1.1     elric 	    btmm.encKeyPack->data = NULL;
   1618  1.1     elric 	    btmm.encKeyPack->length = 0;
   1619  1.1     elric 	    free_PA_PK_AS_REP_BTMM(&btmm);
   1620  1.1     elric 	    os = rep.u.encKeyPack;
   1621  1.1     elric 	}
   1622  1.1     elric 	}
   1623  1.1     elric 
   1624  1.1     elric 	ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
   1625  1.1     elric 	if (ret) {
   1626  1.1     elric 	    free_PA_PK_AS_REP(&rep);
   1627  1.1     elric 	    krb5_set_error_message(context, ret,
   1628  1.1     elric 				   N_("PKINIT: failed to unwrap CI", ""));
   1629  1.1     elric 	    return ret;
   1630  1.1     elric 	}
   1631  1.1     elric 
   1632  1.1     elric 	switch (rep.element) {
   1633  1.1     elric 	case choice_PA_PK_AS_REP_dhInfo:
   1634  1.1     elric 	    ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi,
   1635  1.1     elric 				    ctx->clientDHNonce,
   1636  1.1     elric 				    rep.u.dhInfo.serverDHNonce,
   1637  1.1     elric 				    nonce, pa, key);
   1638  1.1     elric 	    break;
   1639  1.1     elric 	case choice_PA_PK_AS_REP_encKeyPack:
   1640  1.1     elric 	    ret = pk_rd_pa_reply_enckey(context, PKINIT_27, &data, &oid, realm,
   1641  1.1     elric 					ctx, etype, hi, nonce, req_buffer, pa, key);
   1642  1.1     elric 	    break;
   1643  1.1     elric 	default:
   1644  1.1     elric 	    krb5_abortx(context, "pk-init as-rep case not possible to happen");
   1645  1.1     elric 	}
   1646  1.1     elric 	der_free_octet_string(&data);
   1647  1.1     elric 	der_free_oid(&oid);
   1648  1.1     elric 	free_PA_PK_AS_REP(&rep);
   1649  1.1     elric 
   1650  1.1     elric     } else if (ctx->type == PKINIT_WIN2K) {
   1651  1.1     elric 	PA_PK_AS_REP_Win2k w2krep;
   1652  1.1     elric 
   1653  1.1     elric 	/* Check for Windows encoding of the AS-REP pa data */
   1654  1.1     elric 
   1655  1.1     elric #if 0 /* should this be ? */
   1656  1.1     elric 	if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
   1657  1.1     elric 	    krb5_set_error_message(context, EINVAL,
   1658  1.1     elric 				   "PKINIT: wrong padata recv");
   1659  1.1     elric 	    return EINVAL;
   1660  1.1     elric 	}
   1661  1.1     elric #endif
   1662  1.1     elric 
   1663  1.1     elric 	memset(&w2krep, 0, sizeof(w2krep));
   1664  1.2  christos 
   1665  1.1     elric 	ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data,
   1666  1.1     elric 					pa->padata_value.length,
   1667  1.1     elric 					&w2krep,
   1668  1.1     elric 					&size);
   1669  1.1     elric 	if (ret) {
   1670  1.1     elric 	    krb5_set_error_message(context, ret,
   1671  1.1     elric 				   N_("PKINIT: Failed decoding windows "
   1672  1.1     elric 				      "pkinit reply %d", ""), (int)ret);
   1673  1.1     elric 	    return ret;
   1674  1.1     elric 	}
   1675  1.1     elric 
   1676  1.1     elric 	krb5_clear_error_message(context);
   1677  1.2  christos 
   1678  1.1     elric 	switch (w2krep.element) {
   1679  1.1     elric 	case choice_PA_PK_AS_REP_Win2k_encKeyPack: {
   1680  1.1     elric 	    heim_octet_string data;
   1681  1.1     elric 	    heim_oid oid;
   1682  1.2  christos 
   1683  1.1     elric 	    ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack,
   1684  1.1     elric 					       &oid, &data, NULL);
   1685  1.1     elric 	    free_PA_PK_AS_REP_Win2k(&w2krep);
   1686  1.1     elric 	    if (ret) {
   1687  1.1     elric 		krb5_set_error_message(context, ret,
   1688  1.1     elric 				       N_("PKINIT: failed to unwrap CI", ""));
   1689  1.1     elric 		return ret;
   1690  1.1     elric 	    }
   1691  1.1     elric 
   1692  1.1     elric 	    ret = pk_rd_pa_reply_enckey(context, PKINIT_WIN2K, &data, &oid, realm,
   1693  1.1     elric 					ctx, etype, hi, nonce, req_buffer, pa, key);
   1694  1.1     elric 	    der_free_octet_string(&data);
   1695  1.1     elric 	    der_free_oid(&oid);
   1696  1.1     elric 
   1697  1.1     elric 	    break;
   1698  1.1     elric 	}
   1699  1.1     elric 	default:
   1700  1.1     elric 	    free_PA_PK_AS_REP_Win2k(&w2krep);
   1701  1.1     elric 	    ret = EINVAL;
   1702  1.1     elric 	    krb5_set_error_message(context, ret,
   1703  1.1     elric 				   N_("PKINIT: win2k reply invalid "
   1704  1.1     elric 				      "content type", ""));
   1705  1.1     elric 	    break;
   1706  1.1     elric 	}
   1707  1.1     elric 
   1708  1.1     elric     } else {
   1709  1.1     elric 	ret = EINVAL;
   1710  1.1     elric 	krb5_set_error_message(context, ret,
   1711  1.1     elric 			       N_("PKINIT: unknown reply type", ""));
   1712  1.1     elric     }
   1713  1.1     elric 
   1714  1.1     elric     return ret;
   1715  1.1     elric }
   1716  1.1     elric 
   1717  1.1     elric struct prompter {
   1718  1.1     elric     krb5_context context;
   1719  1.1     elric     krb5_prompter_fct prompter;
   1720  1.1     elric     void *prompter_data;
   1721  1.1     elric };
   1722  1.1     elric 
   1723  1.1     elric static int
   1724  1.1     elric hx_pass_prompter(void *data, const hx509_prompt *prompter)
   1725  1.1     elric {
   1726  1.1     elric     krb5_error_code ret;
   1727  1.1     elric     krb5_prompt prompt;
   1728  1.1     elric     krb5_data password_data;
   1729  1.1     elric     struct prompter *p = data;
   1730  1.1     elric 
   1731  1.1     elric     password_data.data   = prompter->reply.data;
   1732  1.1     elric     password_data.length = prompter->reply.length;
   1733  1.1     elric 
   1734  1.1     elric     prompt.prompt = prompter->prompt;
   1735  1.1     elric     prompt.hidden = hx509_prompt_hidden(prompter->type);
   1736  1.1     elric     prompt.reply  = &password_data;
   1737  1.1     elric 
   1738  1.1     elric     switch (prompter->type) {
   1739  1.1     elric     case HX509_PROMPT_TYPE_INFO:
   1740  1.1     elric 	prompt.type   = KRB5_PROMPT_TYPE_INFO;
   1741  1.1     elric 	break;
   1742  1.1     elric     case HX509_PROMPT_TYPE_PASSWORD:
   1743  1.1     elric     case HX509_PROMPT_TYPE_QUESTION:
   1744  1.1     elric     default:
   1745  1.1     elric 	prompt.type   = KRB5_PROMPT_TYPE_PASSWORD;
   1746  1.1     elric 	break;
   1747  1.2  christos     }
   1748  1.1     elric 
   1749  1.1     elric     ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt);
   1750  1.1     elric     if (ret) {
   1751  1.1     elric 	memset (prompter->reply.data, 0, prompter->reply.length);
   1752  1.1     elric 	return 1;
   1753  1.1     elric     }
   1754  1.1     elric     return 0;
   1755  1.1     elric }
   1756  1.1     elric 
   1757  1.1     elric static krb5_error_code
   1758  1.1     elric _krb5_pk_set_user_id(krb5_context context,
   1759  1.1     elric 		     krb5_principal principal,
   1760  1.1     elric 		     krb5_pk_init_ctx ctx,
   1761  1.1     elric 		     struct hx509_certs_data *certs)
   1762  1.1     elric {
   1763  1.1     elric     hx509_certs c = hx509_certs_ref(certs);
   1764  1.1     elric     hx509_query *q = NULL;
   1765  1.1     elric     int ret;
   1766  1.1     elric 
   1767  1.1     elric     if (ctx->id->certs)
   1768  1.1     elric 	hx509_certs_free(&ctx->id->certs);
   1769  1.1     elric     if (ctx->id->cert) {
   1770  1.1     elric 	hx509_cert_free(ctx->id->cert);
   1771  1.1     elric 	ctx->id->cert = NULL;
   1772  1.1     elric     }
   1773  1.1     elric 
   1774  1.1     elric     ctx->id->certs = c;
   1775  1.1     elric     ctx->anonymous = 0;
   1776  1.1     elric 
   1777  1.1     elric     ret = hx509_query_alloc(context->hx509ctx, &q);
   1778  1.1     elric     if (ret) {
   1779  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   1780  1.1     elric 		      "Allocate query to find signing certificate");
   1781  1.1     elric 	return ret;
   1782  1.1     elric     }
   1783  1.2  christos 
   1784  1.1     elric     hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
   1785  1.1     elric     hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
   1786  1.2  christos 
   1787  1.1     elric     if (principal && strncmp("LKDC:SHA1.", krb5_principal_get_realm(context, principal), 9) == 0) {
   1788  1.1     elric 	ctx->id->flags |= PKINIT_BTMM;
   1789  1.1     elric     }
   1790  1.1     elric 
   1791  1.1     elric     ret = find_cert(context, ctx->id, q, &ctx->id->cert);
   1792  1.1     elric     hx509_query_free(context->hx509ctx, q);
   1793  1.1     elric 
   1794  1.1     elric     if (ret == 0 && _krb5_have_debug(context, 2)) {
   1795  1.1     elric 	hx509_name name;
   1796  1.1     elric 	char *str, *sn;
   1797  1.1     elric 	heim_integer i;
   1798  1.1     elric 
   1799  1.1     elric 	ret = hx509_cert_get_subject(ctx->id->cert, &name);
   1800  1.1     elric 	if (ret)
   1801  1.1     elric 	    goto out;
   1802  1.2  christos 
   1803  1.1     elric 	ret = hx509_name_to_string(name, &str);
   1804  1.1     elric 	hx509_name_free(&name);
   1805  1.1     elric 	if (ret)
   1806  1.1     elric 	    goto out;
   1807  1.1     elric 
   1808  1.1     elric 	ret = hx509_cert_get_serialnumber(ctx->id->cert, &i);
   1809  1.1     elric 	if (ret) {
   1810  1.1     elric 	    free(str);
   1811  1.1     elric 	    goto out;
   1812  1.1     elric 	}
   1813  1.1     elric 
   1814  1.1     elric 	ret = der_print_hex_heim_integer(&i, &sn);
   1815  1.1     elric 	der_free_heim_integer(&i);
   1816  1.1     elric 	if (ret) {
   1817  1.1     elric 	    free(name);
   1818  1.1     elric 	    goto out;
   1819  1.1     elric 	}
   1820  1.1     elric 
   1821  1.1     elric 	_krb5_debug(context, 2, "using cert: subject: %s sn: %s", str, sn);
   1822  1.1     elric 	free(str);
   1823  1.1     elric 	free(sn);
   1824  1.1     elric     }
   1825  1.1     elric  out:
   1826  1.1     elric 
   1827  1.1     elric     return ret;
   1828  1.1     elric }
   1829  1.1     elric 
   1830  1.1     elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   1831  1.1     elric _krb5_pk_load_id(krb5_context context,
   1832  1.1     elric 		 struct krb5_pk_identity **ret_id,
   1833  1.1     elric 		 const char *user_id,
   1834  1.1     elric 		 const char *anchor_id,
   1835  1.1     elric 		 char * const *chain_list,
   1836  1.1     elric 		 char * const *revoke_list,
   1837  1.1     elric 		 krb5_prompter_fct prompter,
   1838  1.1     elric 		 void *prompter_data,
   1839  1.1     elric 		 char *password)
   1840  1.1     elric {
   1841  1.1     elric     struct krb5_pk_identity *id = NULL;
   1842  1.1     elric     struct prompter p;
   1843  1.1     elric     int ret;
   1844  1.1     elric 
   1845  1.1     elric     *ret_id = NULL;
   1846  1.1     elric 
   1847  1.1     elric     if (anchor_id == NULL) {
   1848  1.1     elric 	krb5_set_error_message(context, HEIM_PKINIT_NO_VALID_CA,
   1849  1.1     elric 			       N_("PKINIT: No anchor given", ""));
   1850  1.1     elric 	return HEIM_PKINIT_NO_VALID_CA;
   1851  1.1     elric     }
   1852  1.1     elric 
   1853  1.1     elric     /* load cert */
   1854  1.1     elric 
   1855  1.1     elric     id = calloc(1, sizeof(*id));
   1856  1.2  christos     if (id == NULL)
   1857  1.2  christos 	return krb5_enomem(context);
   1858  1.1     elric 
   1859  1.1     elric     if (user_id) {
   1860  1.1     elric 	hx509_lock lock;
   1861  1.1     elric 
   1862  1.1     elric 	ret = hx509_lock_init(context->hx509ctx, &lock);
   1863  1.1     elric 	if (ret) {
   1864  1.1     elric 	    pk_copy_error(context, context->hx509ctx, ret, "Failed init lock");
   1865  1.1     elric 	    goto out;
   1866  1.1     elric 	}
   1867  1.2  christos 
   1868  1.1     elric 	if (password && password[0])
   1869  1.1     elric 	    hx509_lock_add_password(lock, password);
   1870  1.2  christos 
   1871  1.1     elric 	if (prompter) {
   1872  1.1     elric 	    p.context = context;
   1873  1.1     elric 	    p.prompter = prompter;
   1874  1.1     elric 	    p.prompter_data = prompter_data;
   1875  1.2  christos 
   1876  1.1     elric 	    ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p);
   1877  1.1     elric 	    if (ret) {
   1878  1.1     elric 		hx509_lock_free(lock);
   1879  1.1     elric 		goto out;
   1880  1.1     elric 	    }
   1881  1.1     elric 	}
   1882  1.1     elric 
   1883  1.1     elric 	ret = hx509_certs_init(context->hx509ctx, user_id, 0, lock, &id->certs);
   1884  1.1     elric         hx509_lock_free(lock);
   1885  1.1     elric 	if (ret) {
   1886  1.1     elric 	    pk_copy_error(context, context->hx509ctx, ret,
   1887  1.1     elric 			  "Failed to init cert certs");
   1888  1.1     elric 	    goto out;
   1889  1.1     elric 	}
   1890  1.1     elric     } else {
   1891  1.1     elric 	id->certs = NULL;
   1892  1.1     elric     }
   1893  1.1     elric 
   1894  1.1     elric     ret = hx509_certs_init(context->hx509ctx, anchor_id, 0, NULL, &id->anchors);
   1895  1.1     elric     if (ret) {
   1896  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   1897  1.1     elric 		      "Failed to init anchors");
   1898  1.1     elric 	goto out;
   1899  1.1     elric     }
   1900  1.1     elric 
   1901  1.1     elric     ret = hx509_certs_init(context->hx509ctx, "MEMORY:pkinit-cert-chain",
   1902  1.1     elric 			   0, NULL, &id->certpool);
   1903  1.1     elric     if (ret) {
   1904  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   1905  1.1     elric 		      "Failed to init chain");
   1906  1.1     elric 	goto out;
   1907  1.1     elric     }
   1908  1.1     elric 
   1909  1.1     elric     while (chain_list && *chain_list) {
   1910  1.1     elric 	ret = hx509_certs_append(context->hx509ctx, id->certpool,
   1911  1.1     elric 				 NULL, *chain_list);
   1912  1.1     elric 	if (ret) {
   1913  1.1     elric 	    pk_copy_error(context, context->hx509ctx, ret,
   1914  1.1     elric 			  "Failed to laod chain %s",
   1915  1.1     elric 			  *chain_list);
   1916  1.1     elric 	    goto out;
   1917  1.1     elric 	}
   1918  1.1     elric 	chain_list++;
   1919  1.1     elric     }
   1920  1.1     elric 
   1921  1.1     elric     if (revoke_list) {
   1922  1.1     elric 	ret = hx509_revoke_init(context->hx509ctx, &id->revokectx);
   1923  1.1     elric 	if (ret) {
   1924  1.1     elric 	    pk_copy_error(context, context->hx509ctx, ret,
   1925  1.1     elric 			  "Failed init revoke list");
   1926  1.1     elric 	    goto out;
   1927  1.1     elric 	}
   1928  1.1     elric 
   1929  1.1     elric 	while (*revoke_list) {
   1930  1.1     elric 	    ret = hx509_revoke_add_crl(context->hx509ctx,
   1931  1.1     elric 				       id->revokectx,
   1932  1.1     elric 				       *revoke_list);
   1933  1.1     elric 	    if (ret) {
   1934  1.1     elric 		pk_copy_error(context, context->hx509ctx, ret,
   1935  1.1     elric 			      "Failed load revoke list");
   1936  1.1     elric 		goto out;
   1937  1.1     elric 	    }
   1938  1.1     elric 	    revoke_list++;
   1939  1.1     elric 	}
   1940  1.1     elric     } else
   1941  1.1     elric 	hx509_context_set_missing_revoke(context->hx509ctx, 1);
   1942  1.1     elric 
   1943  1.1     elric     ret = hx509_verify_init_ctx(context->hx509ctx, &id->verify_ctx);
   1944  1.1     elric     if (ret) {
   1945  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   1946  1.1     elric 		      "Failed init verify context");
   1947  1.1     elric 	goto out;
   1948  1.1     elric     }
   1949  1.1     elric 
   1950  1.1     elric     hx509_verify_attach_anchors(id->verify_ctx, id->anchors);
   1951  1.1     elric     hx509_verify_attach_revoke(id->verify_ctx, id->revokectx);
   1952  1.1     elric 
   1953  1.1     elric  out:
   1954  1.1     elric     if (ret) {
   1955  1.1     elric 	hx509_verify_destroy_ctx(id->verify_ctx);
   1956  1.1     elric 	hx509_certs_free(&id->certs);
   1957  1.1     elric 	hx509_certs_free(&id->anchors);
   1958  1.1     elric 	hx509_certs_free(&id->certpool);
   1959  1.1     elric 	hx509_revoke_free(&id->revokectx);
   1960  1.1     elric 	free(id);
   1961  1.1     elric     } else
   1962  1.1     elric 	*ret_id = id;
   1963  1.1     elric 
   1964  1.1     elric     return ret;
   1965  1.1     elric }
   1966  1.1     elric 
   1967  1.1     elric /*
   1968  1.1     elric  *
   1969  1.1     elric  */
   1970  1.1     elric 
   1971  1.1     elric static void
   1972  1.1     elric pk_copy_error(krb5_context context,
   1973  1.1     elric 	      hx509_context hx509ctx,
   1974  1.1     elric 	      int hxret,
   1975  1.1     elric 	      const char *fmt,
   1976  1.1     elric 	      ...)
   1977  1.1     elric {
   1978  1.1     elric     va_list va;
   1979  1.1     elric     char *s, *f;
   1980  1.1     elric     int ret;
   1981  1.1     elric 
   1982  1.1     elric     va_start(va, fmt);
   1983  1.1     elric     ret = vasprintf(&f, fmt, va);
   1984  1.1     elric     va_end(va);
   1985  1.1     elric     if (ret == -1 || f == NULL) {
   1986  1.1     elric 	krb5_clear_error_message(context);
   1987  1.1     elric 	return;
   1988  1.1     elric     }
   1989  1.1     elric 
   1990  1.1     elric     s = hx509_get_error_string(hx509ctx, hxret);
   1991  1.1     elric     if (s == NULL) {
   1992  1.1     elric 	krb5_clear_error_message(context);
   1993  1.1     elric 	free(f);
   1994  1.1     elric 	return;
   1995  1.1     elric     }
   1996  1.1     elric     krb5_set_error_message(context, hxret, "%s: %s", f, s);
   1997  1.1     elric     free(s);
   1998  1.1     elric     free(f);
   1999  1.1     elric }
   2000  1.1     elric 
   2001  1.1     elric static int
   2002  1.1     elric parse_integer(krb5_context context, char **p, const char *file, int lineno,
   2003  1.1     elric 	      const char *name, heim_integer *integer)
   2004  1.1     elric {
   2005  1.1     elric     int ret;
   2006  1.1     elric     char *p1;
   2007  1.1     elric     p1 = strsep(p, " \t");
   2008  1.1     elric     if (p1 == NULL) {
   2009  1.1     elric 	krb5_set_error_message(context, EINVAL,
   2010  1.1     elric 			       N_("moduli file %s missing %s on line %d", ""),
   2011  1.1     elric 			       file, name, lineno);
   2012  1.1     elric 	return EINVAL;
   2013  1.1     elric     }
   2014  1.1     elric     ret = der_parse_hex_heim_integer(p1, integer);
   2015  1.1     elric     if (ret) {
   2016  1.1     elric 	krb5_set_error_message(context, ret,
   2017  1.1     elric 			       N_("moduli file %s failed parsing %s "
   2018  1.1     elric 				  "on line %d", ""),
   2019  1.1     elric 			       file, name, lineno);
   2020  1.1     elric 	return ret;
   2021  1.1     elric     }
   2022  1.1     elric 
   2023  1.1     elric     return 0;
   2024  1.1     elric }
   2025  1.1     elric 
   2026  1.2  christos KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   2027  1.1     elric _krb5_parse_moduli_line(krb5_context context,
   2028  1.1     elric 			const char *file,
   2029  1.1     elric 			int lineno,
   2030  1.1     elric 			char *p,
   2031  1.1     elric 			struct krb5_dh_moduli **m)
   2032  1.1     elric {
   2033  1.1     elric     struct krb5_dh_moduli *m1;
   2034  1.1     elric     char *p1;
   2035  1.1     elric     int ret;
   2036  1.1     elric 
   2037  1.1     elric     *m = NULL;
   2038  1.1     elric 
   2039  1.1     elric     m1 = calloc(1, sizeof(*m1));
   2040  1.2  christos     if (m1 == NULL)
   2041  1.2  christos 	return krb5_enomem(context);
   2042  1.1     elric 
   2043  1.1     elric     while (isspace((unsigned char)*p))
   2044  1.1     elric 	p++;
   2045  1.1     elric     if (*p  == '#') {
   2046  1.1     elric         free(m1);
   2047  1.1     elric 	return 0;
   2048  1.1     elric     }
   2049  1.1     elric     ret = EINVAL;
   2050  1.1     elric 
   2051  1.1     elric     p1 = strsep(&p, " \t");
   2052  1.1     elric     if (p1 == NULL) {
   2053  1.1     elric 	krb5_set_error_message(context, ret,
   2054  1.1     elric 			       N_("moduli file %s missing name on line %d", ""),
   2055  1.1     elric 			       file, lineno);
   2056  1.1     elric 	goto out;
   2057  1.1     elric     }
   2058  1.1     elric     m1->name = strdup(p1);
   2059  1.1     elric     if (m1->name == NULL) {
   2060  1.2  christos 	ret = krb5_enomem(context);
   2061  1.1     elric 	goto out;
   2062  1.1     elric     }
   2063  1.1     elric 
   2064  1.1     elric     p1 = strsep(&p, " \t");
   2065  1.1     elric     if (p1 == NULL) {
   2066  1.1     elric 	krb5_set_error_message(context, ret,
   2067  1.1     elric 			       N_("moduli file %s missing bits on line %d", ""),
   2068  1.1     elric 			       file, lineno);
   2069  1.1     elric 	goto out;
   2070  1.1     elric     }
   2071  1.1     elric 
   2072  1.1     elric     m1->bits = atoi(p1);
   2073  1.1     elric     if (m1->bits == 0) {
   2074  1.1     elric 	krb5_set_error_message(context, ret,
   2075  1.1     elric 			       N_("moduli file %s have un-parsable "
   2076  1.1     elric 				  "bits on line %d", ""), file, lineno);
   2077  1.1     elric 	goto out;
   2078  1.1     elric     }
   2079  1.2  christos 
   2080  1.1     elric     ret = parse_integer(context, &p, file, lineno, "p", &m1->p);
   2081  1.1     elric     if (ret)
   2082  1.1     elric 	goto out;
   2083  1.1     elric     ret = parse_integer(context, &p, file, lineno, "g", &m1->g);
   2084  1.1     elric     if (ret)
   2085  1.1     elric 	goto out;
   2086  1.1     elric     ret = parse_integer(context, &p, file, lineno, "q", &m1->q);
   2087  1.1     elric     if (ret)
   2088  1.1     elric 	goto out;
   2089  1.1     elric 
   2090  1.1     elric     *m = m1;
   2091  1.1     elric 
   2092  1.1     elric     return 0;
   2093  1.1     elric  out:
   2094  1.1     elric     free(m1->name);
   2095  1.1     elric     der_free_heim_integer(&m1->p);
   2096  1.1     elric     der_free_heim_integer(&m1->g);
   2097  1.1     elric     der_free_heim_integer(&m1->q);
   2098  1.1     elric     free(m1);
   2099  1.1     elric     return ret;
   2100  1.1     elric }
   2101  1.1     elric 
   2102  1.2  christos KRB5_LIB_FUNCTION void KRB5_LIB_CALL
   2103  1.1     elric _krb5_free_moduli(struct krb5_dh_moduli **moduli)
   2104  1.1     elric {
   2105  1.1     elric     int i;
   2106  1.1     elric     for (i = 0; moduli[i] != NULL; i++) {
   2107  1.1     elric 	free(moduli[i]->name);
   2108  1.1     elric 	der_free_heim_integer(&moduli[i]->p);
   2109  1.1     elric 	der_free_heim_integer(&moduli[i]->g);
   2110  1.1     elric 	der_free_heim_integer(&moduli[i]->q);
   2111  1.1     elric 	free(moduli[i]);
   2112  1.1     elric     }
   2113  1.1     elric     free(moduli);
   2114  1.1     elric }
   2115  1.1     elric 
   2116  1.1     elric static const char *default_moduli_RFC2412_MODP_group2 =
   2117  1.1     elric     /* name */
   2118  1.1     elric     "RFC2412-MODP-group2 "
   2119  1.1     elric     /* bits */
   2120  1.1     elric     "1024 "
   2121  1.1     elric     /* p */
   2122  1.1     elric     "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
   2123  1.1     elric     "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
   2124  1.1     elric     "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
   2125  1.1     elric     "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
   2126  1.1     elric     "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
   2127  1.1     elric     "FFFFFFFF" "FFFFFFFF "
   2128  1.1     elric     /* g */
   2129  1.1     elric     "02 "
   2130  1.1     elric     /* q */
   2131  1.1     elric     "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
   2132  1.1     elric     "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
   2133  1.1     elric     "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
   2134  1.1     elric     "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
   2135  1.1     elric     "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0"
   2136  1.1     elric     "FFFFFFFF" "FFFFFFFF";
   2137  1.1     elric 
   2138  1.1     elric static const char *default_moduli_rfc3526_MODP_group14 =
   2139  1.1     elric     /* name */
   2140  1.1     elric     "rfc3526-MODP-group14 "
   2141  1.1     elric     /* bits */
   2142  1.1     elric     "1760 "
   2143  1.1     elric     /* p */
   2144  1.1     elric     "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
   2145  1.1     elric     "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
   2146  1.1     elric     "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
   2147  1.1     elric     "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
   2148  1.1     elric     "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D"
   2149  1.1     elric     "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F"
   2150  1.1     elric     "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D"
   2151  1.1     elric     "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B"
   2152  1.1     elric     "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9"
   2153  1.1     elric     "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510"
   2154  1.1     elric     "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF "
   2155  1.1     elric     /* g */
   2156  1.1     elric     "02 "
   2157  1.1     elric     /* q */
   2158  1.1     elric     "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
   2159  1.1     elric     "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
   2160  1.1     elric     "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
   2161  1.1     elric     "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
   2162  1.1     elric     "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F6722D9E"
   2163  1.1     elric     "E1003E5C" "50B1DF82" "CC6D241B" "0E2AE9CD" "348B1FD4" "7E9267AF"
   2164  1.1     elric     "C1B2AE91" "EE51D6CB" "0E3179AB" "1042A95D" "CF6A9483" "B84B4B36"
   2165  1.1     elric     "B3861AA7" "255E4C02" "78BA3604" "650C10BE" "19482F23" "171B671D"
   2166  1.1     elric     "F1CF3B96" "0C074301" "CD93C1D1" "7603D147" "DAE2AEF8" "37A62964"
   2167  1.1     elric     "EF15E5FB" "4AAC0B8C" "1CCAA4BE" "754AB572" "8AE9130C" "4C7D0288"
   2168  1.1     elric     "0AB9472D" "45565534" "7FFFFFFF" "FFFFFFFF";
   2169  1.1     elric 
   2170  1.2  christos KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   2171  1.1     elric _krb5_parse_moduli(krb5_context context, const char *file,
   2172  1.1     elric 		   struct krb5_dh_moduli ***moduli)
   2173  1.1     elric {
   2174  1.1     elric     /* name bits P G Q */
   2175  1.1     elric     krb5_error_code ret;
   2176  1.1     elric     struct krb5_dh_moduli **m = NULL, **m2;
   2177  1.1     elric     char buf[4096];
   2178  1.1     elric     FILE *f;
   2179  1.1     elric     int lineno = 0, n = 0;
   2180  1.1     elric 
   2181  1.1     elric     *moduli = NULL;
   2182  1.1     elric 
   2183  1.1     elric     m = calloc(1, sizeof(m[0]) * 3);
   2184  1.2  christos     if (m == NULL)
   2185  1.2  christos 	return krb5_enomem(context);
   2186  1.1     elric 
   2187  1.1     elric     strlcpy(buf, default_moduli_rfc3526_MODP_group14, sizeof(buf));
   2188  1.1     elric     ret = _krb5_parse_moduli_line(context, "builtin", 1, buf,  &m[0]);
   2189  1.1     elric     if (ret) {
   2190  1.1     elric 	_krb5_free_moduli(m);
   2191  1.1     elric 	return ret;
   2192  1.1     elric     }
   2193  1.1     elric     n++;
   2194  1.1     elric 
   2195  1.1     elric     strlcpy(buf, default_moduli_RFC2412_MODP_group2, sizeof(buf));
   2196  1.1     elric     ret = _krb5_parse_moduli_line(context, "builtin", 1, buf,  &m[1]);
   2197  1.1     elric     if (ret) {
   2198  1.1     elric 	_krb5_free_moduli(m);
   2199  1.1     elric 	return ret;
   2200  1.1     elric     }
   2201  1.1     elric     n++;
   2202  1.1     elric 
   2203  1.1     elric 
   2204  1.1     elric     if (file == NULL)
   2205  1.1     elric 	file = MODULI_FILE;
   2206  1.1     elric 
   2207  1.1     elric #ifdef KRB5_USE_PATH_TOKENS
   2208  1.1     elric     {
   2209  1.1     elric         char * exp_file;
   2210  1.1     elric 
   2211  1.2  christos 	if (_krb5_expand_path_tokens(context, file, 1, &exp_file) == 0) {
   2212  1.1     elric             f = fopen(exp_file, "r");
   2213  1.1     elric             krb5_xfree(exp_file);
   2214  1.1     elric         } else {
   2215  1.1     elric             f = NULL;
   2216  1.1     elric         }
   2217  1.1     elric     }
   2218  1.1     elric #else
   2219  1.1     elric     f = fopen(file, "r");
   2220  1.1     elric #endif
   2221  1.1     elric 
   2222  1.1     elric     if (f == NULL) {
   2223  1.1     elric 	*moduli = m;
   2224  1.1     elric 	return 0;
   2225  1.1     elric     }
   2226  1.1     elric     rk_cloexec_file(f);
   2227  1.1     elric 
   2228  1.1     elric     while(fgets(buf, sizeof(buf), f) != NULL) {
   2229  1.1     elric 	struct krb5_dh_moduli *element;
   2230  1.1     elric 
   2231  1.1     elric 	buf[strcspn(buf, "\n")] = '\0';
   2232  1.1     elric 	lineno++;
   2233  1.1     elric 
   2234  1.1     elric 	m2 = realloc(m, (n + 2) * sizeof(m[0]));
   2235  1.1     elric 	if (m2 == NULL) {
   2236  1.1     elric 	    _krb5_free_moduli(m);
   2237  1.2  christos 	    return krb5_enomem(context);
   2238  1.1     elric 	}
   2239  1.1     elric 	m = m2;
   2240  1.2  christos 
   2241  1.1     elric 	m[n] = NULL;
   2242  1.1     elric 
   2243  1.1     elric 	ret = _krb5_parse_moduli_line(context, file, lineno, buf,  &element);
   2244  1.1     elric 	if (ret) {
   2245  1.1     elric 	    _krb5_free_moduli(m);
   2246  1.1     elric 	    return ret;
   2247  1.1     elric 	}
   2248  1.1     elric 	if (element == NULL)
   2249  1.1     elric 	    continue;
   2250  1.1     elric 
   2251  1.1     elric 	m[n] = element;
   2252  1.1     elric 	m[n + 1] = NULL;
   2253  1.1     elric 	n++;
   2254  1.1     elric     }
   2255  1.1     elric     *moduli = m;
   2256  1.1     elric     return 0;
   2257  1.1     elric }
   2258  1.1     elric 
   2259  1.2  christos KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   2260  1.1     elric _krb5_dh_group_ok(krb5_context context, unsigned long bits,
   2261  1.1     elric 		  heim_integer *p, heim_integer *g, heim_integer *q,
   2262  1.1     elric 		  struct krb5_dh_moduli **moduli,
   2263  1.1     elric 		  char **name)
   2264  1.1     elric {
   2265  1.1     elric     int i;
   2266  1.1     elric 
   2267  1.1     elric     if (name)
   2268  1.1     elric 	*name = NULL;
   2269  1.1     elric 
   2270  1.1     elric     for (i = 0; moduli[i] != NULL; i++) {
   2271  1.1     elric 	if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 &&
   2272  1.1     elric 	    der_heim_integer_cmp(&moduli[i]->p, p) == 0 &&
   2273  1.1     elric 	    (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0))
   2274  1.1     elric 	    {
   2275  1.1     elric 		if (bits && bits > moduli[i]->bits) {
   2276  1.1     elric 		    krb5_set_error_message(context,
   2277  1.1     elric 					   KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED,
   2278  1.1     elric 					   N_("PKINIT: DH group parameter %s "
   2279  1.1     elric 					      "no accepted, not enough bits "
   2280  1.1     elric 					      "generated", ""),
   2281  1.1     elric 					   moduli[i]->name);
   2282  1.1     elric 		    return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
   2283  1.1     elric 		}
   2284  1.1     elric 		if (name)
   2285  1.1     elric 		    *name = strdup(moduli[i]->name);
   2286  1.1     elric 		return 0;
   2287  1.1     elric 	    }
   2288  1.1     elric     }
   2289  1.1     elric     krb5_set_error_message(context,
   2290  1.1     elric 			   KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED,
   2291  1.1     elric 			   N_("PKINIT: DH group parameter no ok", ""));
   2292  1.1     elric     return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
   2293  1.1     elric }
   2294  1.1     elric #endif /* PKINIT */
   2295  1.1     elric 
   2296  1.1     elric KRB5_LIB_FUNCTION void KRB5_LIB_CALL
   2297  1.1     elric _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
   2298  1.1     elric {
   2299  1.1     elric #ifdef PKINIT
   2300  1.1     elric     krb5_pk_init_ctx ctx;
   2301  1.1     elric 
   2302  1.1     elric     if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL)
   2303  1.1     elric 	return;
   2304  1.1     elric     ctx = opt->opt_private->pk_init_ctx;
   2305  1.1     elric     switch (ctx->keyex) {
   2306  1.1     elric     case USE_DH:
   2307  1.1     elric 	if (ctx->u.dh)
   2308  1.1     elric 	    DH_free(ctx->u.dh);
   2309  1.1     elric 	break;
   2310  1.1     elric     case USE_RSA:
   2311  1.1     elric 	break;
   2312  1.2  christos     case USE_ECDH:
   2313  1.1     elric 	if (ctx->u.eckey)
   2314  1.2  christos             _krb5_pk_eckey_free(ctx->u.eckey);
   2315  1.1     elric 	break;
   2316  1.1     elric     }
   2317  1.1     elric     if (ctx->id) {
   2318  1.1     elric 	hx509_verify_destroy_ctx(ctx->id->verify_ctx);
   2319  1.1     elric 	hx509_certs_free(&ctx->id->certs);
   2320  1.1     elric 	hx509_cert_free(ctx->id->cert);
   2321  1.1     elric 	hx509_certs_free(&ctx->id->anchors);
   2322  1.1     elric 	hx509_certs_free(&ctx->id->certpool);
   2323  1.1     elric 
   2324  1.1     elric 	if (ctx->clientDHNonce) {
   2325  1.1     elric 	    krb5_free_data(NULL, ctx->clientDHNonce);
   2326  1.1     elric 	    ctx->clientDHNonce = NULL;
   2327  1.1     elric 	}
   2328  1.1     elric 	if (ctx->m)
   2329  1.1     elric 	    _krb5_free_moduli(ctx->m);
   2330  1.1     elric 	free(ctx->id);
   2331  1.1     elric 	ctx->id = NULL;
   2332  1.1     elric     }
   2333  1.1     elric     free(opt->opt_private->pk_init_ctx);
   2334  1.1     elric     opt->opt_private->pk_init_ctx = NULL;
   2335  1.1     elric #endif
   2336  1.1     elric }
   2337  1.1     elric 
   2338  1.1     elric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
   2339  1.1     elric krb5_get_init_creds_opt_set_pkinit(krb5_context context,
   2340  1.1     elric 				   krb5_get_init_creds_opt *opt,
   2341  1.1     elric 				   krb5_principal principal,
   2342  1.1     elric 				   const char *user_id,
   2343  1.1     elric 				   const char *x509_anchors,
   2344  1.1     elric 				   char * const * pool,
   2345  1.1     elric 				   char * const * pki_revoke,
   2346  1.1     elric 				   int flags,
   2347  1.1     elric 				   krb5_prompter_fct prompter,
   2348  1.1     elric 				   void *prompter_data,
   2349  1.1     elric 				   char *password)
   2350  1.1     elric {
   2351  1.1     elric #ifdef PKINIT
   2352  1.1     elric     krb5_error_code ret;
   2353  1.1     elric     char *anchors = NULL;
   2354  1.1     elric 
   2355  1.1     elric     if (opt->opt_private == NULL) {
   2356  1.1     elric 	krb5_set_error_message(context, EINVAL,
   2357  1.1     elric 			       N_("PKINIT: on non extendable opt", ""));
   2358  1.1     elric 	return EINVAL;
   2359  1.1     elric     }
   2360  1.1     elric 
   2361  1.1     elric     opt->opt_private->pk_init_ctx =
   2362  1.1     elric 	calloc(1, sizeof(*opt->opt_private->pk_init_ctx));
   2363  1.2  christos     if (opt->opt_private->pk_init_ctx == NULL)
   2364  1.2  christos 	return krb5_enomem(context);
   2365  1.1     elric     opt->opt_private->pk_init_ctx->require_binding = 0;
   2366  1.1     elric     opt->opt_private->pk_init_ctx->require_eku = 1;
   2367  1.1     elric     opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1;
   2368  1.1     elric     opt->opt_private->pk_init_ctx->peer = NULL;
   2369  1.1     elric 
   2370  1.1     elric     /* XXX implement krb5_appdefault_strings  */
   2371  1.1     elric     if (pool == NULL)
   2372  1.1     elric 	pool = krb5_config_get_strings(context, NULL,
   2373  1.1     elric 				       "appdefaults",
   2374  1.1     elric 				       "pkinit_pool",
   2375  1.1     elric 				       NULL);
   2376  1.1     elric 
   2377  1.1     elric     if (pki_revoke == NULL)
   2378  1.1     elric 	pki_revoke = krb5_config_get_strings(context, NULL,
   2379  1.1     elric 					     "appdefaults",
   2380  1.1     elric 					     "pkinit_revoke",
   2381  1.1     elric 					     NULL);
   2382  1.1     elric 
   2383  1.1     elric     if (x509_anchors == NULL) {
   2384  1.1     elric 	krb5_appdefault_string(context, "kinit",
   2385  1.1     elric 			       krb5_principal_get_realm(context, principal),
   2386  1.1     elric 			       "pkinit_anchors", NULL, &anchors);
   2387  1.1     elric 	x509_anchors = anchors;
   2388  1.1     elric     }
   2389  1.1     elric 
   2390  1.5  christos     if (flags & KRB5_GIC_OPT_PKINIT_ANONYMOUS)
   2391  1.1     elric 	opt->opt_private->pk_init_ctx->anonymous = 1;
   2392  1.1     elric 
   2393  1.1     elric     ret = _krb5_pk_load_id(context,
   2394  1.1     elric 			   &opt->opt_private->pk_init_ctx->id,
   2395  1.1     elric 			   user_id,
   2396  1.1     elric 			   x509_anchors,
   2397  1.1     elric 			   pool,
   2398  1.1     elric 			   pki_revoke,
   2399  1.1     elric 			   prompter,
   2400  1.1     elric 			   prompter_data,
   2401  1.1     elric 			   password);
   2402  1.1     elric     if (ret) {
   2403  1.1     elric 	free(opt->opt_private->pk_init_ctx);
   2404  1.1     elric 	opt->opt_private->pk_init_ctx = NULL;
   2405  1.1     elric 	return ret;
   2406  1.1     elric     }
   2407  1.5  christos     if (flags & KRB5_GIC_OPT_PKINIT_BTMM)
   2408  1.5  christos 	opt->opt_private->pk_init_ctx->id->flags |= PKINIT_BTMM;
   2409  1.5  christos 
   2410  1.5  christos     if (principal && krb5_principal_is_lkdc(context, principal))
   2411  1.5  christos 	opt->opt_private->pk_init_ctx->id->flags |= PKINIT_BTMM;
   2412  1.1     elric 
   2413  1.1     elric     if (opt->opt_private->pk_init_ctx->id->certs) {
   2414  1.1     elric 	_krb5_pk_set_user_id(context,
   2415  1.1     elric 			     principal,
   2416  1.1     elric 			     opt->opt_private->pk_init_ctx,
   2417  1.1     elric 			     opt->opt_private->pk_init_ctx->id->certs);
   2418  1.1     elric     } else
   2419  1.1     elric 	opt->opt_private->pk_init_ctx->id->cert = NULL;
   2420  1.1     elric 
   2421  1.5  christos     if ((flags & KRB5_GIC_OPT_PKINIT_USE_ENCKEY) == 0) {
   2422  1.1     elric 	hx509_context hx509ctx = context->hx509ctx;
   2423  1.1     elric 	hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert;
   2424  1.1     elric 
   2425  1.1     elric 	opt->opt_private->pk_init_ctx->keyex = USE_DH;
   2426  1.1     elric 
   2427  1.1     elric 	/*
   2428  1.1     elric 	 * If its a ECDSA certs, lets select ECDSA as the keyex algorithm.
   2429  1.1     elric 	 */
   2430  1.1     elric 	if (cert) {
   2431  1.1     elric 	    AlgorithmIdentifier alg;
   2432  1.1     elric 
   2433  1.1     elric 	    ret = hx509_cert_get_SPKI_AlgorithmIdentifier(hx509ctx, cert, &alg);
   2434  1.1     elric 	    if (ret == 0) {
   2435  1.1     elric 		if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_ecPublicKey) == 0)
   2436  1.1     elric 		    opt->opt_private->pk_init_ctx->keyex = USE_ECDH;
   2437  1.1     elric 		free_AlgorithmIdentifier(&alg);
   2438  1.1     elric 	    }
   2439  1.1     elric 	}
   2440  1.1     elric 
   2441  1.1     elric     } else {
   2442  1.1     elric 	opt->opt_private->pk_init_ctx->keyex = USE_RSA;
   2443  1.1     elric 
   2444  1.1     elric 	if (opt->opt_private->pk_init_ctx->id->certs == NULL) {
   2445  1.1     elric 	    krb5_set_error_message(context, EINVAL,
   2446  1.1     elric 				   N_("No anonymous pkinit support in RSA mode", ""));
   2447  1.1     elric 	    return EINVAL;
   2448  1.2  christos 	}
   2449  1.1     elric     }
   2450  1.1     elric 
   2451  1.1     elric     return 0;
   2452  1.1     elric #else
   2453  1.1     elric     krb5_set_error_message(context, EINVAL,
   2454  1.1     elric 			   N_("no support for PKINIT compiled in", ""));
   2455  1.1     elric     return EINVAL;
   2456  1.1     elric #endif
   2457  1.1     elric }
   2458  1.1     elric 
   2459  1.1     elric krb5_error_code KRB5_LIB_FUNCTION
   2460  1.1     elric krb5_get_init_creds_opt_set_pkinit_user_certs(krb5_context context,
   2461  1.1     elric 					      krb5_get_init_creds_opt *opt,
   2462  1.1     elric 					      struct hx509_certs_data *certs)
   2463  1.1     elric {
   2464  1.1     elric #ifdef PKINIT
   2465  1.1     elric     if (opt->opt_private == NULL) {
   2466  1.1     elric 	krb5_set_error_message(context, EINVAL,
   2467  1.1     elric 			       N_("PKINIT: on non extendable opt", ""));
   2468  1.1     elric 	return EINVAL;
   2469  1.1     elric     }
   2470  1.1     elric     if (opt->opt_private->pk_init_ctx == NULL) {
   2471  1.1     elric 	krb5_set_error_message(context, EINVAL,
   2472  1.1     elric 			       N_("PKINIT: on pkinit context", ""));
   2473  1.1     elric 	return EINVAL;
   2474  1.1     elric     }
   2475  1.2  christos 
   2476  1.1     elric     _krb5_pk_set_user_id(context, NULL, opt->opt_private->pk_init_ctx, certs);
   2477  1.1     elric 
   2478  1.1     elric     return 0;
   2479  1.1     elric #else
   2480  1.1     elric     krb5_set_error_message(context, EINVAL,
   2481  1.1     elric 			   N_("no support for PKINIT compiled in", ""));
   2482  1.1     elric     return EINVAL;
   2483  1.1     elric #endif
   2484  1.1     elric }
   2485  1.1     elric 
   2486  1.1     elric #ifdef PKINIT
   2487  1.1     elric 
   2488  1.1     elric static int
   2489  1.1     elric get_ms_san(hx509_context context, hx509_cert cert, char **upn)
   2490  1.1     elric {
   2491  1.1     elric     hx509_octet_string_list list;
   2492  1.1     elric     int ret;
   2493  1.1     elric 
   2494  1.1     elric     *upn = NULL;
   2495  1.1     elric 
   2496  1.1     elric     ret = hx509_cert_find_subjectAltName_otherName(context,
   2497  1.1     elric 						   cert,
   2498  1.1     elric 						   &asn1_oid_id_pkinit_ms_san,
   2499  1.1     elric 						   &list);
   2500  1.1     elric     if (ret)
   2501  1.1     elric 	return 0;
   2502  1.1     elric 
   2503  1.1     elric     if (list.len > 0 && list.val[0].length > 0)
   2504  1.1     elric 	ret = decode_MS_UPN_SAN(list.val[0].data, list.val[0].length,
   2505  1.1     elric 				upn, NULL);
   2506  1.1     elric     else
   2507  1.1     elric 	ret = 1;
   2508  1.2  christos     hx509_free_octet_string_list(&list);
   2509  1.1     elric 
   2510  1.1     elric     return ret;
   2511  1.1     elric }
   2512  1.1     elric 
   2513  1.1     elric static int
   2514  1.1     elric find_ms_san(hx509_context context, hx509_cert cert, void *ctx)
   2515  1.1     elric {
   2516  1.1     elric     char *upn;
   2517  1.1     elric     int ret;
   2518  1.1     elric 
   2519  1.1     elric     ret = get_ms_san(context, cert, &upn);
   2520  1.1     elric     if (ret == 0)
   2521  1.1     elric 	free(upn);
   2522  1.1     elric     return ret;
   2523  1.1     elric }
   2524  1.1     elric 
   2525  1.1     elric 
   2526  1.1     elric 
   2527  1.1     elric #endif
   2528  1.1     elric 
   2529  1.1     elric /*
   2530  1.1     elric  * Private since it need to be redesigned using krb5_get_init_creds()
   2531  1.1     elric  */
   2532  1.1     elric 
   2533  1.1     elric KRB5_LIB_FUNCTION krb5_error_code  KRB5_LIB_CALL
   2534  1.1     elric krb5_pk_enterprise_cert(krb5_context context,
   2535  1.1     elric 			const char *user_id,
   2536  1.1     elric 			krb5_const_realm realm,
   2537  1.1     elric 			krb5_principal *principal,
   2538  1.1     elric 			struct hx509_certs_data **res)
   2539  1.1     elric {
   2540  1.1     elric #ifdef PKINIT
   2541  1.1     elric     krb5_error_code ret;
   2542  1.1     elric     hx509_certs certs, result;
   2543  1.2  christos     hx509_cert cert = NULL;
   2544  1.1     elric     hx509_query *q;
   2545  1.1     elric     char *name;
   2546  1.1     elric 
   2547  1.1     elric     *principal = NULL;
   2548  1.1     elric     if (res)
   2549  1.1     elric 	*res = NULL;
   2550  1.2  christos 
   2551  1.1     elric     if (user_id == NULL) {
   2552  1.1     elric 	krb5_set_error_message(context, ENOENT, "no user id");
   2553  1.1     elric 	return ENOENT;
   2554  1.1     elric     }
   2555  1.1     elric 
   2556  1.1     elric     ret = hx509_certs_init(context->hx509ctx, user_id, 0, NULL, &certs);
   2557  1.1     elric     if (ret) {
   2558  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   2559  1.1     elric 		      "Failed to init cert certs");
   2560  1.1     elric 	goto out;
   2561  1.1     elric     }
   2562  1.1     elric 
   2563  1.1     elric     ret = hx509_query_alloc(context->hx509ctx, &q);
   2564  1.1     elric     if (ret) {
   2565  1.1     elric 	krb5_set_error_message(context, ret, "out of memory");
   2566  1.1     elric 	hx509_certs_free(&certs);
   2567  1.1     elric 	goto out;
   2568  1.1     elric     }
   2569  1.1     elric 
   2570  1.1     elric     hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
   2571  1.1     elric     hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
   2572  1.1     elric     hx509_query_match_eku(q, &asn1_oid_id_pkinit_ms_eku);
   2573  1.1     elric     hx509_query_match_cmp_func(q, find_ms_san, NULL);
   2574  1.1     elric 
   2575  1.1     elric     ret = hx509_certs_filter(context->hx509ctx, certs, q, &result);
   2576  1.1     elric     hx509_query_free(context->hx509ctx, q);
   2577  1.1     elric     hx509_certs_free(&certs);
   2578  1.1     elric     if (ret) {
   2579  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   2580  1.1     elric 		      "Failed to find PKINIT certificate");
   2581  1.1     elric 	return ret;
   2582  1.1     elric     }
   2583  1.2  christos 
   2584  1.1     elric     ret = hx509_get_one_cert(context->hx509ctx, result, &cert);
   2585  1.1     elric     hx509_certs_free(&result);
   2586  1.1     elric     if (ret) {
   2587  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   2588  1.1     elric 		      "Failed to get one cert");
   2589  1.1     elric 	goto out;
   2590  1.1     elric     }
   2591  1.1     elric 
   2592  1.1     elric     ret = get_ms_san(context->hx509ctx, cert, &name);
   2593  1.1     elric     if (ret) {
   2594  1.1     elric 	pk_copy_error(context, context->hx509ctx, ret,
   2595  1.1     elric 		      "Failed to get MS SAN");
   2596  1.1     elric 	goto out;
   2597  1.1     elric     }
   2598  1.1     elric 
   2599  1.1     elric     ret = krb5_make_principal(context, principal, realm, name, NULL);
   2600  1.1     elric     free(name);
   2601  1.1     elric     if (ret)
   2602  1.1     elric 	goto out;
   2603  1.1     elric 
   2604  1.1     elric     krb5_principal_set_type(context, *principal, KRB5_NT_ENTERPRISE_PRINCIPAL);
   2605  1.1     elric 
   2606  1.1     elric     if (res) {
   2607  1.1     elric 	ret = hx509_certs_init(context->hx509ctx, "MEMORY:", 0, NULL, res);
   2608  1.2  christos 	if (ret)
   2609  1.1     elric 	    goto out;
   2610  1.2  christos 
   2611  1.1     elric 	ret = hx509_certs_add(context->hx509ctx, *res, cert);
   2612  1.1     elric 	if (ret) {
   2613  1.1     elric 	    hx509_certs_free(res);
   2614  1.1     elric 	    goto out;
   2615  1.1     elric 	}
   2616  1.1     elric     }
   2617  1.1     elric 
   2618  1.1     elric  out:
   2619  1.1     elric     hx509_cert_free(cert);
   2620  1.1     elric 
   2621  1.1     elric     return ret;
   2622  1.1     elric #else
   2623  1.1     elric     krb5_set_error_message(context, EINVAL,
   2624  1.1     elric 			   N_("no support for PKINIT compiled in", ""));
   2625  1.1     elric     return EINVAL;
   2626  1.1     elric #endif
   2627  1.1     elric }
   2628