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