1/* $NetBSD: crypto.c,v 1.2 2017/01/28 21:31:49 christos Exp $ */ 2 3/* 4 * Copyright (c) 1997 - 2008 Kungliga Tekniska H��gskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36#include "krb5_locl.h" 37 38struct _krb5_key_usage { 39 unsigned usage; 40 struct _krb5_key_data key; 41}; 42 43 44#ifndef HEIMDAL_SMALLER 45#define DES3_OLD_ENCTYPE 1 46#endif 47 48static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, 49 unsigned, struct _krb5_key_data**); 50static struct _krb5_key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); 51 52static void free_key_schedule(krb5_context, 53 struct _krb5_key_data *, 54 struct _krb5_encryption_type *); 55 56/* 57 * Converts etype to a user readable string and sets as a side effect 58 * the krb5_error_message containing this string. Returns 59 * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in 60 * which case the error code of the etype convesion is returned. 61 */ 62 63static krb5_error_code 64unsupported_enctype(krb5_context context, krb5_enctype etype) 65{ 66 krb5_error_code ret; 67 char *name; 68 69 ret = krb5_enctype_to_string(context, etype, &name); 70 if (ret) 71 return ret; 72 73 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 74 N_("Encryption type %s not supported", ""), 75 name); 76 free(name); 77 return KRB5_PROG_ETYPE_NOSUPP; 78} 79 80/* 81 * 82 */ 83 84KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 85krb5_enctype_keysize(krb5_context context, 86 krb5_enctype type, 87 size_t *keysize) 88{ 89 struct _krb5_encryption_type *et = _krb5_find_enctype(type); 90 if(et == NULL) { 91 return unsupported_enctype (context, type); 92 } 93 *keysize = et->keytype->size; 94 return 0; 95} 96 97KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 98krb5_enctype_keybits(krb5_context context, 99 krb5_enctype type, 100 size_t *keybits) 101{ 102 struct _krb5_encryption_type *et = _krb5_find_enctype(type); 103 if(et == NULL) { 104 return unsupported_enctype (context, type); 105 } 106 *keybits = et->keytype->bits; 107 return 0; 108} 109 110KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 111krb5_generate_random_keyblock(krb5_context context, 112 krb5_enctype type, 113 krb5_keyblock *key) 114{ 115 krb5_error_code ret; 116 struct _krb5_encryption_type *et = _krb5_find_enctype(type); 117 if(et == NULL) { 118 return unsupported_enctype (context, type); 119 } 120 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 121 if(ret) 122 return ret; 123 key->keytype = type; 124 if(et->keytype->random_key) 125 (*et->keytype->random_key)(context, key); 126 else 127 krb5_generate_random_block(key->keyvalue.data, 128 key->keyvalue.length); 129 return 0; 130} 131 132static krb5_error_code 133_key_schedule(krb5_context context, 134 struct _krb5_key_data *key) 135{ 136 krb5_error_code ret; 137 struct _krb5_encryption_type *et = _krb5_find_enctype(key->key->keytype); 138 struct _krb5_key_type *kt; 139 140 if (et == NULL) { 141 return unsupported_enctype (context, 142 key->key->keytype); 143 } 144 145 kt = et->keytype; 146 147 if(kt->schedule == NULL) 148 return 0; 149 if (key->schedule != NULL) 150 return 0; 151 ALLOC(key->schedule, 1); 152 if (key->schedule == NULL) 153 return krb5_enomem(context); 154 ret = krb5_data_alloc(key->schedule, kt->schedule_size); 155 if(ret) { 156 free(key->schedule); 157 key->schedule = NULL; 158 return ret; 159 } 160 (*kt->schedule)(context, kt, key); 161 return 0; 162} 163 164/************************************************************ 165 * * 166 ************************************************************/ 167 168static krb5_error_code 169SHA1_checksum(krb5_context context, 170 struct _krb5_key_data *key, 171 const void *data, 172 size_t len, 173 unsigned usage, 174 Checksum *C) 175{ 176 if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1) 177 krb5_abortx(context, "sha1 checksum failed"); 178 return 0; 179} 180 181/* HMAC according to RFC2104 */ 182KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 183_krb5_internal_hmac(krb5_context context, 184 struct _krb5_checksum_type *cm, 185 const void *data, 186 size_t len, 187 unsigned usage, 188 struct _krb5_key_data *keyblock, 189 Checksum *result) 190{ 191 unsigned char *ipad, *opad; 192 unsigned char *key; 193 size_t key_len; 194 size_t i; 195 196 ipad = malloc(cm->blocksize + len); 197 if (ipad == NULL) 198 return ENOMEM; 199 opad = malloc(cm->blocksize + cm->checksumsize); 200 if (opad == NULL) { 201 free(ipad); 202 return ENOMEM; 203 } 204 memset(ipad, 0x36, cm->blocksize); 205 memset(opad, 0x5c, cm->blocksize); 206 207 if(keyblock->key->keyvalue.length > cm->blocksize){ 208 (*cm->checksum)(context, 209 keyblock, 210 keyblock->key->keyvalue.data, 211 keyblock->key->keyvalue.length, 212 usage, 213 result); 214 key = result->checksum.data; 215 key_len = result->checksum.length; 216 } else { 217 key = keyblock->key->keyvalue.data; 218 key_len = keyblock->key->keyvalue.length; 219 } 220 for(i = 0; i < key_len; i++){ 221 ipad[i] ^= key[i]; 222 opad[i] ^= key[i]; 223 } 224 memcpy(ipad + cm->blocksize, data, len); 225 (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, 226 usage, result); 227 memcpy(opad + cm->blocksize, result->checksum.data, 228 result->checksum.length); 229 (*cm->checksum)(context, keyblock, opad, 230 cm->blocksize + cm->checksumsize, usage, result); 231 memset(ipad, 0, cm->blocksize + len); 232 free(ipad); 233 memset(opad, 0, cm->blocksize + cm->checksumsize); 234 free(opad); 235 236 return 0; 237} 238 239KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 240krb5_hmac(krb5_context context, 241 krb5_cksumtype cktype, 242 const void *data, 243 size_t len, 244 unsigned usage, 245 krb5_keyblock *key, 246 Checksum *result) 247{ 248 struct _krb5_checksum_type *c = _krb5_find_checksum(cktype); 249 struct _krb5_key_data kd; 250 krb5_error_code ret; 251 252 if (c == NULL) { 253 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 254 N_("checksum type %d not supported", ""), 255 cktype); 256 return KRB5_PROG_SUMTYPE_NOSUPP; 257 } 258 259 kd.key = key; 260 kd.schedule = NULL; 261 262 ret = _krb5_internal_hmac(context, c, data, len, usage, &kd, result); 263 264 if (kd.schedule) 265 krb5_free_data(context, kd.schedule); 266 267 return ret; 268} 269 270krb5_error_code 271_krb5_SP_HMAC_SHA1_checksum(krb5_context context, 272 struct _krb5_key_data *key, 273 const void *data, 274 size_t len, 275 unsigned usage, 276 Checksum *result) 277{ 278 struct _krb5_checksum_type *c = _krb5_find_checksum(CKSUMTYPE_SHA1); 279 Checksum res; 280 char sha1_data[20]; 281 krb5_error_code ret; 282 283 res.checksum.data = sha1_data; 284 res.checksum.length = sizeof(sha1_data); 285 286 ret = _krb5_internal_hmac(context, c, data, len, usage, key, &res); 287 if (ret) 288 krb5_abortx(context, "hmac failed"); 289 memcpy(result->checksum.data, res.checksum.data, result->checksum.length); 290 return 0; 291} 292 293struct _krb5_checksum_type _krb5_checksum_sha1 = { 294 CKSUMTYPE_SHA1, 295 "sha1", 296 64, 297 20, 298 F_CPROOF, 299 SHA1_checksum, 300 NULL 301}; 302 303KRB5_LIB_FUNCTION struct _krb5_checksum_type * KRB5_LIB_CALL 304_krb5_find_checksum(krb5_cksumtype type) 305{ 306 int i; 307 for(i = 0; i < _krb5_num_checksums; i++) 308 if(_krb5_checksum_types[i]->type == type) 309 return _krb5_checksum_types[i]; 310 return NULL; 311} 312 313static krb5_error_code 314get_checksum_key(krb5_context context, 315 krb5_crypto crypto, 316 unsigned usage, /* not krb5_key_usage */ 317 struct _krb5_checksum_type *ct, 318 struct _krb5_key_data **key) 319{ 320 krb5_error_code ret = 0; 321 322 if(ct->flags & F_DERIVED) 323 ret = _get_derived_key(context, crypto, usage, key); 324 else if(ct->flags & F_VARIANT) { 325 size_t i; 326 327 *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); 328 if (*key == NULL) 329 return krb5_enomem(context); 330 ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); 331 if(ret) 332 return ret; 333 for(i = 0; i < (*key)->key->keyvalue.length; i++) 334 ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; 335 } else { 336 *key = &crypto->key; 337 } 338 if(ret == 0) 339 ret = _key_schedule(context, *key); 340 return ret; 341} 342 343static krb5_error_code 344create_checksum (krb5_context context, 345 struct _krb5_checksum_type *ct, 346 krb5_crypto crypto, 347 unsigned usage, 348 void *data, 349 size_t len, 350 Checksum *result) 351{ 352 krb5_error_code ret; 353 struct _krb5_key_data *dkey; 354 int keyed_checksum; 355 356 if (ct->flags & F_DISABLED) { 357 krb5_clear_error_message (context); 358 return KRB5_PROG_SUMTYPE_NOSUPP; 359 } 360 keyed_checksum = (ct->flags & F_KEYED) != 0; 361 if(keyed_checksum && crypto == NULL) { 362 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 363 N_("Checksum type %s is keyed but no " 364 "crypto context (key) was passed in", ""), 365 ct->name); 366 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 367 } 368 if(keyed_checksum) { 369 ret = get_checksum_key(context, crypto, usage, ct, &dkey); 370 if (ret) 371 return ret; 372 } else 373 dkey = NULL; 374 result->cksumtype = ct->type; 375 ret = krb5_data_alloc(&result->checksum, ct->checksumsize); 376 if (ret) 377 return (ret); 378 return (*ct->checksum)(context, dkey, data, len, usage, result); 379} 380 381static int 382arcfour_checksum_p(struct _krb5_checksum_type *ct, krb5_crypto crypto) 383{ 384 return (ct->type == CKSUMTYPE_HMAC_MD5) && 385 (crypto->key.key->keytype == KEYTYPE_ARCFOUR); 386} 387 388KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 389krb5_create_checksum(krb5_context context, 390 krb5_crypto crypto, 391 krb5_key_usage usage, 392 int type, 393 void *data, 394 size_t len, 395 Checksum *result) 396{ 397 struct _krb5_checksum_type *ct = NULL; 398 unsigned keyusage; 399 400 /* type 0 -> pick from crypto */ 401 if (type) { 402 ct = _krb5_find_checksum(type); 403 } else if (crypto) { 404 ct = crypto->et->keyed_checksum; 405 if (ct == NULL) 406 ct = crypto->et->checksum; 407 } 408 409 if(ct == NULL) { 410 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 411 N_("checksum type %d not supported", ""), 412 type); 413 return KRB5_PROG_SUMTYPE_NOSUPP; 414 } 415 416 if (arcfour_checksum_p(ct, crypto)) { 417 keyusage = usage; 418 _krb5_usage2arcfour(context, &keyusage); 419 } else 420 keyusage = CHECKSUM_USAGE(usage); 421 422 return create_checksum(context, ct, crypto, keyusage, 423 data, len, result); 424} 425 426static krb5_error_code 427verify_checksum(krb5_context context, 428 krb5_crypto crypto, 429 unsigned usage, /* not krb5_key_usage */ 430 void *data, 431 size_t len, 432 Checksum *cksum) 433{ 434 krb5_error_code ret; 435 struct _krb5_key_data *dkey; 436 int keyed_checksum; 437 Checksum c; 438 struct _krb5_checksum_type *ct; 439 440 ct = _krb5_find_checksum(cksum->cksumtype); 441 if (ct == NULL || (ct->flags & F_DISABLED)) { 442 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 443 N_("checksum type %d not supported", ""), 444 cksum->cksumtype); 445 return KRB5_PROG_SUMTYPE_NOSUPP; 446 } 447 if(ct->checksumsize != cksum->checksum.length) { 448 krb5_clear_error_message (context); 449 krb5_set_error_message(context, KRB5KRB_AP_ERR_BAD_INTEGRITY, 450 N_("Decrypt integrity check failed for checksum type %s, " 451 "length was %u, expected %u", ""), 452 ct->name, (unsigned)cksum->checksum.length, 453 (unsigned)ct->checksumsize); 454 455 return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ 456 } 457 keyed_checksum = (ct->flags & F_KEYED) != 0; 458 if(keyed_checksum) { 459 struct _krb5_checksum_type *kct; 460 if (crypto == NULL) { 461 krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP, 462 N_("Checksum type %s is keyed but no " 463 "crypto context (key) was passed in", ""), 464 ct->name); 465 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 466 } 467 kct = crypto->et->keyed_checksum; 468 if (kct == NULL || kct->type != ct->type) { 469 krb5_set_error_message(context, KRB5_PROG_SUMTYPE_NOSUPP, 470 N_("Checksum type %s is keyed, but " 471 "the key type %s passed didnt have that checksum " 472 "type as the keyed type", ""), 473 ct->name, crypto->et->name); 474 return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ 475 } 476 477 ret = get_checksum_key(context, crypto, usage, ct, &dkey); 478 if (ret) 479 return ret; 480 } else 481 dkey = NULL; 482 483 /* 484 * If checksum have a verify function, lets use that instead of 485 * calling ->checksum and then compare result. 486 */ 487 488 if(ct->verify) { 489 ret = (*ct->verify)(context, dkey, data, len, usage, cksum); 490 if (ret) 491 krb5_set_error_message(context, ret, 492 N_("Decrypt integrity check failed for checksum " 493 "type %s, key type %s", ""), 494 ct->name, (crypto != NULL)? crypto->et->name : "(none)"); 495 return ret; 496 } 497 498 ret = krb5_data_alloc (&c.checksum, ct->checksumsize); 499 if (ret) 500 return ret; 501 502 ret = (*ct->checksum)(context, dkey, data, len, usage, &c); 503 if (ret) { 504 krb5_data_free(&c.checksum); 505 return ret; 506 } 507 508 if(krb5_data_ct_cmp(&c.checksum, &cksum->checksum) != 0) { 509 ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; 510 krb5_set_error_message(context, ret, 511 N_("Decrypt integrity check failed for checksum " 512 "type %s, key type %s", ""), 513 ct->name, crypto ? crypto->et->name : "(unkeyed)"); 514 } else { 515 ret = 0; 516 } 517 krb5_data_free (&c.checksum); 518 return ret; 519} 520 521KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 522krb5_verify_checksum(krb5_context context, 523 krb5_crypto crypto, 524 krb5_key_usage usage, 525 void *data, 526 size_t len, 527 Checksum *cksum) 528{ 529 struct _krb5_checksum_type *ct; 530 unsigned keyusage; 531 532 ct = _krb5_find_checksum(cksum->cksumtype); 533 if(ct == NULL) { 534 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 535 N_("checksum type %d not supported", ""), 536 cksum->cksumtype); 537 return KRB5_PROG_SUMTYPE_NOSUPP; 538 } 539 540 if (arcfour_checksum_p(ct, crypto)) { 541 keyusage = usage; 542 _krb5_usage2arcfour(context, &keyusage); 543 } else 544 keyusage = CHECKSUM_USAGE(usage); 545 546 return verify_checksum(context, crypto, keyusage, 547 data, len, cksum); 548} 549 550KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 551krb5_crypto_get_checksum_type(krb5_context context, 552 krb5_crypto crypto, 553 krb5_cksumtype *type) 554{ 555 struct _krb5_checksum_type *ct = NULL; 556 557 if (crypto != NULL) { 558 ct = crypto->et->keyed_checksum; 559 if (ct == NULL) 560 ct = crypto->et->checksum; 561 } 562 563 if (ct == NULL) { 564 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 565 N_("checksum type not found", "")); 566 return KRB5_PROG_SUMTYPE_NOSUPP; 567 } 568 569 *type = ct->type; 570 571 return 0; 572} 573 574 575KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 576krb5_checksumsize(krb5_context context, 577 krb5_cksumtype type, 578 size_t *size) 579{ 580 struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 581 if(ct == NULL) { 582 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 583 N_("checksum type %d not supported", ""), 584 type); 585 return KRB5_PROG_SUMTYPE_NOSUPP; 586 } 587 *size = ct->checksumsize; 588 return 0; 589} 590 591KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 592krb5_checksum_is_keyed(krb5_context context, 593 krb5_cksumtype type) 594{ 595 struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 596 if(ct == NULL) { 597 if (context) 598 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 599 N_("checksum type %d not supported", ""), 600 type); 601 return KRB5_PROG_SUMTYPE_NOSUPP; 602 } 603 return ct->flags & F_KEYED; 604} 605 606KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 607krb5_checksum_is_collision_proof(krb5_context context, 608 krb5_cksumtype type) 609{ 610 struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 611 if(ct == NULL) { 612 if (context) 613 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 614 N_("checksum type %d not supported", ""), 615 type); 616 return KRB5_PROG_SUMTYPE_NOSUPP; 617 } 618 return ct->flags & F_CPROOF; 619} 620 621KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 622krb5_checksum_disable(krb5_context context, 623 krb5_cksumtype type) 624{ 625 struct _krb5_checksum_type *ct = _krb5_find_checksum(type); 626 if(ct == NULL) { 627 if (context) 628 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 629 N_("checksum type %d not supported", ""), 630 type); 631 return KRB5_PROG_SUMTYPE_NOSUPP; 632 } 633 ct->flags |= F_DISABLED; 634 return 0; 635} 636 637/************************************************************ 638 * * 639 ************************************************************/ 640 641KRB5_LIB_FUNCTION struct _krb5_encryption_type * KRB5_LIB_CALL 642_krb5_find_enctype(krb5_enctype type) 643{ 644 int i; 645 for(i = 0; i < _krb5_num_etypes; i++) 646 if(_krb5_etypes[i]->type == type) 647 return _krb5_etypes[i]; 648 return NULL; 649} 650 651 652KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 653krb5_enctype_to_string(krb5_context context, 654 krb5_enctype etype, 655 char **string) 656{ 657 struct _krb5_encryption_type *e; 658 e = _krb5_find_enctype(etype); 659 if(e == NULL) { 660 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 661 N_("encryption type %d not supported", ""), 662 etype); 663 *string = NULL; 664 return KRB5_PROG_ETYPE_NOSUPP; 665 } 666 *string = strdup(e->name); 667 if (*string == NULL) 668 return krb5_enomem(context); 669 return 0; 670} 671 672KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 673krb5_string_to_enctype(krb5_context context, 674 const char *string, 675 krb5_enctype *etype) 676{ 677 int i; 678 for(i = 0; i < _krb5_num_etypes; i++) { 679 if(strcasecmp(_krb5_etypes[i]->name, string) == 0){ 680 *etype = _krb5_etypes[i]->type; 681 return 0; 682 } 683 if(_krb5_etypes[i]->alias != NULL && 684 strcasecmp(_krb5_etypes[i]->alias, string) == 0){ 685 *etype = _krb5_etypes[i]->type; 686 return 0; 687 } 688 } 689 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 690 N_("encryption type %s not supported", ""), 691 string); 692 return KRB5_PROG_ETYPE_NOSUPP; 693} 694 695KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 696krb5_enctype_to_keytype(krb5_context context, 697 krb5_enctype etype, 698 krb5_keytype *keytype) 699{ 700 struct _krb5_encryption_type *e = _krb5_find_enctype(etype); 701 if(e == NULL) { 702 return unsupported_enctype (context, etype); 703 } 704 *keytype = e->keytype->type; /* XXX */ 705 return 0; 706} 707 708/** 709 * Check if a enctype is valid, return 0 if it is. 710 * 711 * @param context Kerberos context 712 * @param etype enctype to check if its valid or not 713 * 714 * @return Return an error code for an failure or 0 on success (enctype valid). 715 * @ingroup krb5_crypto 716 */ 717 718KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 719krb5_enctype_valid(krb5_context context, 720 krb5_enctype etype) 721{ 722 struct _krb5_encryption_type *e = _krb5_find_enctype(etype); 723 if(e && (e->flags & F_DISABLED) == 0) 724 return 0; 725 if (context == NULL) 726 return KRB5_PROG_ETYPE_NOSUPP; 727 if(e == NULL) { 728 return unsupported_enctype (context, etype); 729 } 730 /* Must be (e->flags & F_DISABLED) */ 731 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 732 N_("encryption type %s is disabled", ""), 733 e->name); 734 return KRB5_PROG_ETYPE_NOSUPP; 735} 736 737/** 738 * Return the coresponding encryption type for a checksum type. 739 * 740 * @param context Kerberos context 741 * @param ctype The checksum type to get the result enctype for 742 * @param etype The returned encryption, when the matching etype is 743 * not found, etype is set to ETYPE_NULL. 744 * 745 * @return Return an error code for an failure or 0 on success. 746 * @ingroup krb5_crypto 747 */ 748 749 750KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 751krb5_cksumtype_to_enctype(krb5_context context, 752 krb5_cksumtype ctype, 753 krb5_enctype *etype) 754{ 755 int i; 756 757 *etype = ETYPE_NULL; 758 759 for(i = 0; i < _krb5_num_etypes; i++) { 760 if(_krb5_etypes[i]->keyed_checksum && 761 _krb5_etypes[i]->keyed_checksum->type == ctype) 762 { 763 *etype = _krb5_etypes[i]->type; 764 return 0; 765 } 766 } 767 768 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 769 N_("checksum type %d not supported", ""), 770 (int)ctype); 771 return KRB5_PROG_SUMTYPE_NOSUPP; 772} 773 774 775KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 776krb5_cksumtype_valid(krb5_context context, 777 krb5_cksumtype ctype) 778{ 779 struct _krb5_checksum_type *c = _krb5_find_checksum(ctype); 780 if (c == NULL) { 781 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 782 N_("checksum type %d not supported", ""), 783 ctype); 784 return KRB5_PROG_SUMTYPE_NOSUPP; 785 } 786 if (c->flags & F_DISABLED) { 787 krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, 788 N_("checksum type %s is disabled", ""), 789 c->name); 790 return KRB5_PROG_SUMTYPE_NOSUPP; 791 } 792 return 0; 793} 794 795static krb5_boolean 796derived_crypto(krb5_context context, 797 krb5_crypto crypto) 798{ 799 return (crypto->et->flags & F_DERIVED) != 0; 800} 801 802#define CHECKSUMSIZE(C) ((C)->checksumsize) 803#define CHECKSUMTYPE(C) ((C)->type) 804 805static krb5_error_code 806encrypt_internal_derived(krb5_context context, 807 krb5_crypto crypto, 808 unsigned usage, 809 const void *data, 810 size_t len, 811 krb5_data *result, 812 void *ivec) 813{ 814 size_t sz, block_sz, checksum_sz, total_sz; 815 Checksum cksum; 816 unsigned char *p, *q; 817 krb5_error_code ret; 818 struct _krb5_key_data *dkey; 819 const struct _krb5_encryption_type *et = crypto->et; 820 821 checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 822 823 sz = et->confoundersize + len; 824 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 825 total_sz = block_sz + checksum_sz; 826 p = calloc(1, total_sz); 827 if (p == NULL) 828 return krb5_enomem(context); 829 830 q = p; 831 krb5_generate_random_block(q, et->confoundersize); /* XXX */ 832 q += et->confoundersize; 833 memcpy(q, data, len); 834 835 ret = create_checksum(context, 836 et->keyed_checksum, 837 crypto, 838 INTEGRITY_USAGE(usage), 839 p, 840 block_sz, 841 &cksum); 842 if(ret == 0 && cksum.checksum.length != checksum_sz) { 843 free_Checksum (&cksum); 844 krb5_clear_error_message (context); 845 ret = KRB5_CRYPTO_INTERNAL; 846 } 847 if(ret) 848 goto fail; 849 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); 850 free_Checksum (&cksum); 851 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 852 if(ret) 853 goto fail; 854 ret = _key_schedule(context, dkey); 855 if(ret) 856 goto fail; 857 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 858 if (ret) 859 goto fail; 860 result->data = p; 861 result->length = total_sz; 862 return 0; 863 fail: 864 memset(p, 0, total_sz); 865 free(p); 866 return ret; 867} 868 869static krb5_error_code 870encrypt_internal_enc_then_cksum(krb5_context context, 871 krb5_crypto crypto, 872 unsigned usage, 873 const void *data, 874 size_t len, 875 krb5_data *result, 876 void *ivec) 877{ 878 size_t sz, block_sz, checksum_sz, total_sz; 879 Checksum cksum; 880 unsigned char *p, *q, *ivc = NULL; 881 krb5_error_code ret; 882 struct _krb5_key_data *dkey; 883 const struct _krb5_encryption_type *et = crypto->et; 884 885 checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 886 887 sz = et->confoundersize + len; 888 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 889 total_sz = block_sz + checksum_sz; 890 p = calloc(1, total_sz); 891 if (p == NULL) 892 return krb5_enomem(context); 893 894 q = p; 895 krb5_generate_random_block(q, et->confoundersize); /* XXX */ 896 q += et->confoundersize; 897 memcpy(q, data, len); 898 899 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 900 if(ret) 901 goto fail; 902 ret = _key_schedule(context, dkey); 903 if(ret) 904 goto fail; 905 906 /* XXX EVP style update API would avoid needing to allocate here */ 907 ivc = malloc(et->blocksize + block_sz); 908 if (ivc == NULL) { 909 ret = krb5_enomem(context); 910 goto fail; 911 } 912 if (ivec) 913 memcpy(ivc, ivec, et->blocksize); 914 else 915 memset(ivc, 0, et->blocksize); 916 917 ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); 918 if (ret) 919 goto fail; 920 memcpy(&ivc[et->blocksize], p, block_sz); 921 922 ret = create_checksum(context, 923 et->keyed_checksum, 924 crypto, 925 INTEGRITY_USAGE(usage), 926 ivc, 927 et->blocksize + block_sz, 928 &cksum); 929 if(ret == 0 && cksum.checksum.length != checksum_sz) { 930 free_Checksum (&cksum); 931 krb5_clear_error_message (context); 932 ret = KRB5_CRYPTO_INTERNAL; 933 } 934 if(ret) 935 goto fail; 936 memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); 937 free_Checksum (&cksum); 938 result->data = p; 939 result->length = total_sz; 940 free(ivc); 941 return 0; 942 fail: 943 memset_s(p, total_sz, 0, total_sz); 944 free(p); 945 free(ivc); 946 return ret; 947} 948 949static krb5_error_code 950encrypt_internal(krb5_context context, 951 krb5_crypto crypto, 952 const void *data, 953 size_t len, 954 krb5_data *result, 955 void *ivec) 956{ 957 size_t sz, block_sz, checksum_sz; 958 Checksum cksum; 959 unsigned char *p, *q; 960 krb5_error_code ret; 961 const struct _krb5_encryption_type *et = crypto->et; 962 963 checksum_sz = CHECKSUMSIZE(et->checksum); 964 965 sz = et->confoundersize + checksum_sz + len; 966 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 967 p = calloc(1, block_sz); 968 if (p == NULL) 969 return krb5_enomem(context); 970 971 q = p; 972 krb5_generate_random_block(q, et->confoundersize); /* XXX */ 973 q += et->confoundersize; 974 memset(q, 0, checksum_sz); 975 q += checksum_sz; 976 memcpy(q, data, len); 977 978 ret = create_checksum(context, 979 et->checksum, 980 crypto, 981 0, 982 p, 983 block_sz, 984 &cksum); 985 if(ret == 0 && cksum.checksum.length != checksum_sz) { 986 krb5_clear_error_message (context); 987 free_Checksum(&cksum); 988 ret = KRB5_CRYPTO_INTERNAL; 989 } 990 if(ret) 991 goto fail; 992 memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); 993 free_Checksum(&cksum); 994 ret = _key_schedule(context, &crypto->key); 995 if(ret) 996 goto fail; 997 ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); 998 if (ret) { 999 memset(p, 0, block_sz); 1000 free(p); 1001 return ret; 1002 } 1003 result->data = p; 1004 result->length = block_sz; 1005 return 0; 1006 fail: 1007 memset(p, 0, block_sz); 1008 free(p); 1009 return ret; 1010} 1011 1012static krb5_error_code 1013encrypt_internal_special(krb5_context context, 1014 krb5_crypto crypto, 1015 int usage, 1016 const void *data, 1017 size_t len, 1018 krb5_data *result, 1019 void *ivec) 1020{ 1021 struct _krb5_encryption_type *et = crypto->et; 1022 size_t cksum_sz = CHECKSUMSIZE(et->checksum); 1023 size_t sz = len + cksum_sz + et->confoundersize; 1024 char *tmp, *p; 1025 krb5_error_code ret; 1026 1027 tmp = malloc (sz); 1028 if (tmp == NULL) 1029 return krb5_enomem(context); 1030 p = tmp; 1031 memset (p, 0, cksum_sz); 1032 p += cksum_sz; 1033 krb5_generate_random_block(p, et->confoundersize); 1034 p += et->confoundersize; 1035 memcpy (p, data, len); 1036 ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); 1037 if (ret) { 1038 memset(tmp, 0, sz); 1039 free(tmp); 1040 return ret; 1041 } 1042 result->data = tmp; 1043 result->length = sz; 1044 return 0; 1045} 1046 1047static krb5_error_code 1048decrypt_internal_derived(krb5_context context, 1049 krb5_crypto crypto, 1050 unsigned usage, 1051 void *data, 1052 size_t len, 1053 krb5_data *result, 1054 void *ivec) 1055{ 1056 size_t checksum_sz; 1057 Checksum cksum; 1058 unsigned char *p; 1059 krb5_error_code ret; 1060 struct _krb5_key_data *dkey; 1061 struct _krb5_encryption_type *et = crypto->et; 1062 unsigned long l; 1063 1064 checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 1065 if (len < checksum_sz + et->confoundersize) { 1066 krb5_set_error_message(context, KRB5_BAD_MSIZE, 1067 N_("Encrypted data shorter then " 1068 "checksum + confunder", "")); 1069 return KRB5_BAD_MSIZE; 1070 } 1071 1072 if (((len - checksum_sz) % et->padsize) != 0) { 1073 krb5_clear_error_message(context); 1074 return KRB5_BAD_MSIZE; 1075 } 1076 1077 p = malloc(len); 1078 if (len != 0 && p == NULL) 1079 return krb5_enomem(context); 1080 memcpy(p, data, len); 1081 1082 len -= checksum_sz; 1083 1084 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1085 if(ret) { 1086 free(p); 1087 return ret; 1088 } 1089 ret = _key_schedule(context, dkey); 1090 if(ret) { 1091 free(p); 1092 return ret; 1093 } 1094 ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); 1095 if (ret) { 1096 free(p); 1097 return ret; 1098 } 1099 1100 cksum.checksum.data = p + len; 1101 cksum.checksum.length = checksum_sz; 1102 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1103 1104 ret = verify_checksum(context, 1105 crypto, 1106 INTEGRITY_USAGE(usage), 1107 p, 1108 len, 1109 &cksum); 1110 if(ret) { 1111 free(p); 1112 return ret; 1113 } 1114 l = len - et->confoundersize; 1115 memmove(p, p + et->confoundersize, l); 1116 result->data = realloc(p, l); 1117 if(result->data == NULL && l != 0) { 1118 free(p); 1119 return krb5_enomem(context); 1120 } 1121 result->length = l; 1122 return 0; 1123} 1124 1125static krb5_error_code 1126decrypt_internal_enc_then_cksum(krb5_context context, 1127 krb5_crypto crypto, 1128 unsigned usage, 1129 void *data, 1130 size_t len, 1131 krb5_data *result, 1132 void *ivec) 1133{ 1134 size_t checksum_sz; 1135 Checksum cksum; 1136 unsigned char *p; 1137 krb5_error_code ret; 1138 struct _krb5_key_data *dkey; 1139 struct _krb5_encryption_type *et = crypto->et; 1140 unsigned long l; 1141 1142 checksum_sz = CHECKSUMSIZE(et->keyed_checksum); 1143 if (len < checksum_sz + et->confoundersize) { 1144 krb5_set_error_message(context, KRB5_BAD_MSIZE, 1145 N_("Encrypted data shorter then " 1146 "checksum + confunder", "")); 1147 return KRB5_BAD_MSIZE; 1148 } 1149 1150 if (((len - checksum_sz) % et->padsize) != 0) { 1151 krb5_clear_error_message(context); 1152 return KRB5_BAD_MSIZE; 1153 } 1154 1155 len -= checksum_sz; 1156 1157 p = malloc(et->blocksize + len); 1158 if (p == NULL) 1159 return krb5_enomem(context); 1160 1161 if (ivec) 1162 memcpy(p, ivec, et->blocksize); 1163 else 1164 memset(p, 0, et->blocksize); 1165 memcpy(&p[et->blocksize], data, len); 1166 1167 cksum.checksum.data = (unsigned char *)data + len; 1168 cksum.checksum.length = checksum_sz; 1169 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1170 1171 ret = verify_checksum(context, 1172 crypto, 1173 INTEGRITY_USAGE(usage), 1174 p, 1175 et->blocksize + len, 1176 &cksum); 1177 if(ret) { 1178 free(p); 1179 return ret; 1180 } 1181 1182 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1183 if(ret) { 1184 free(p); 1185 return ret; 1186 } 1187 ret = _key_schedule(context, dkey); 1188 if(ret) { 1189 free(p); 1190 return ret; 1191 } 1192 ret = (*et->encrypt)(context, dkey, &p[et->blocksize], len, 0, usage, ivec); 1193 if (ret) { 1194 free(p); 1195 return ret; 1196 } 1197 1198 l = len - et->confoundersize; 1199 memmove(p, p + et->blocksize + et->confoundersize, l); 1200 result->data = realloc(p, l); 1201 if(result->data == NULL && l != 0) { 1202 free(p); 1203 return krb5_enomem(context); 1204 } 1205 result->length = l; 1206 return 0; 1207} 1208 1209static krb5_error_code 1210decrypt_internal(krb5_context context, 1211 krb5_crypto crypto, 1212 void *data, 1213 size_t len, 1214 krb5_data *result, 1215 void *ivec) 1216{ 1217 krb5_error_code ret; 1218 unsigned char *p; 1219 Checksum cksum; 1220 size_t checksum_sz, l; 1221 struct _krb5_encryption_type *et = crypto->et; 1222 1223 if ((len % et->padsize) != 0) { 1224 krb5_clear_error_message(context); 1225 return KRB5_BAD_MSIZE; 1226 } 1227 checksum_sz = CHECKSUMSIZE(et->checksum); 1228 if (len < checksum_sz + et->confoundersize) { 1229 krb5_set_error_message(context, KRB5_BAD_MSIZE, 1230 N_("Encrypted data shorter then " 1231 "checksum + confunder", "")); 1232 return KRB5_BAD_MSIZE; 1233 } 1234 1235 p = malloc(len); 1236 if (len != 0 && p == NULL) 1237 return krb5_enomem(context); 1238 memcpy(p, data, len); 1239 1240 ret = _key_schedule(context, &crypto->key); 1241 if(ret) { 1242 free(p); 1243 return ret; 1244 } 1245 ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); 1246 if (ret) { 1247 free(p); 1248 return ret; 1249 } 1250 ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); 1251 if(ret) { 1252 free(p); 1253 return ret; 1254 } 1255 memset(p + et->confoundersize, 0, checksum_sz); 1256 cksum.cksumtype = CHECKSUMTYPE(et->checksum); 1257 ret = verify_checksum(context, NULL, 0, p, len, &cksum); 1258 free_Checksum(&cksum); 1259 if(ret) { 1260 free(p); 1261 return ret; 1262 } 1263 l = len - et->confoundersize - checksum_sz; 1264 memmove(p, p + et->confoundersize + checksum_sz, l); 1265 result->data = realloc(p, l); 1266 if(result->data == NULL && l != 0) { 1267 free(p); 1268 return krb5_enomem(context); 1269 } 1270 result->length = l; 1271 return 0; 1272} 1273 1274static krb5_error_code 1275decrypt_internal_special(krb5_context context, 1276 krb5_crypto crypto, 1277 int usage, 1278 void *data, 1279 size_t len, 1280 krb5_data *result, 1281 void *ivec) 1282{ 1283 struct _krb5_encryption_type *et = crypto->et; 1284 size_t cksum_sz = CHECKSUMSIZE(et->checksum); 1285 size_t sz = len - cksum_sz - et->confoundersize; 1286 unsigned char *p; 1287 krb5_error_code ret; 1288 1289 if ((len % et->padsize) != 0) { 1290 krb5_clear_error_message(context); 1291 return KRB5_BAD_MSIZE; 1292 } 1293 if (len < cksum_sz + et->confoundersize) { 1294 krb5_set_error_message(context, KRB5_BAD_MSIZE, 1295 N_("Encrypted data shorter then " 1296 "checksum + confunder", "")); 1297 return KRB5_BAD_MSIZE; 1298 } 1299 1300 p = malloc (len); 1301 if (p == NULL) 1302 return krb5_enomem(context); 1303 memcpy(p, data, len); 1304 1305 ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec); 1306 if (ret) { 1307 free(p); 1308 return ret; 1309 } 1310 1311 memmove (p, p + cksum_sz + et->confoundersize, sz); 1312 result->data = realloc(p, sz); 1313 if(result->data == NULL && sz != 0) { 1314 free(p); 1315 return krb5_enomem(context); 1316 } 1317 result->length = sz; 1318 return 0; 1319} 1320 1321static krb5_crypto_iov * 1322iov_find(krb5_crypto_iov *data, size_t num_data, unsigned type) 1323{ 1324 size_t i; 1325 for (i = 0; i < num_data; i++) 1326 if (data[i].flags == type) 1327 return &data[i]; 1328 return NULL; 1329} 1330 1331static size_t 1332iov_enc_data_len(krb5_crypto_iov *data, int num_data) 1333{ 1334 size_t i, len; 1335 1336 for (len = 0, i = 0; i < num_data; i++) { 1337 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1338 continue; 1339 len += data[i].data.length; 1340 } 1341 1342 return len; 1343} 1344 1345static size_t 1346iov_sign_data_len(krb5_crypto_iov *data, int num_data) 1347{ 1348 size_t i, len; 1349 1350 for (len = 0, i = 0; i < num_data; i++) { 1351 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1352 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1353 continue; 1354 len += data[i].data.length; 1355 } 1356 1357 return len; 1358} 1359 1360static krb5_error_code 1361iov_coalesce(krb5_context context, 1362 krb5_data *prefix, 1363 krb5_crypto_iov *data, 1364 int num_data, 1365 krb5_boolean inc_sign_data, 1366 krb5_data *out) 1367{ 1368 unsigned char *p, *q; 1369 krb5_crypto_iov *hiv, *piv; 1370 size_t len; 1371 unsigned int i; 1372 1373 hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER); 1374 1375 piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING); 1376 1377 len = 0; 1378 if (prefix) 1379 len += prefix->length; 1380 len += hiv->data.length; 1381 if (inc_sign_data) 1382 len += iov_sign_data_len(data, num_data); 1383 else 1384 len += iov_enc_data_len(data, num_data); 1385 if (piv) 1386 len += piv->data.length; 1387 1388 p = q = malloc(len); 1389 if (p == NULL) 1390 return krb5_enomem(context); 1391 1392 if (prefix) { 1393 memcpy(q, prefix->data, prefix->length); 1394 q += prefix->length; 1395 } 1396 memcpy(q, hiv->data.data, hiv->data.length); 1397 q += hiv->data.length; 1398 for (i = 0; i < num_data; i++) { 1399 if (data[i].flags == KRB5_CRYPTO_TYPE_DATA || 1400 (inc_sign_data && data[i].flags == KRB5_CRYPTO_TYPE_SIGN_ONLY)) { 1401 memcpy(q, data[i].data.data, data[i].data.length); 1402 q += data[i].data.length; 1403 } 1404 } 1405 if (piv) 1406 memset(q, 0, piv->data.length); 1407 1408 out->length = len; 1409 out->data = p; 1410 1411 return 0; 1412} 1413 1414static krb5_error_code 1415iov_uncoalesce(krb5_context context, 1416 krb5_data *enc_data, 1417 krb5_crypto_iov *data, 1418 int num_data) 1419{ 1420 unsigned char *q = enc_data->data; 1421 krb5_crypto_iov *hiv, *piv; 1422 unsigned int i; 1423 1424 hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER); 1425 1426 piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING); 1427 1428 memcpy(hiv->data.data, q, hiv->data.length); 1429 q += hiv->data.length; 1430 1431 for (i = 0; i < num_data; i++) { 1432 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) 1433 continue; 1434 memcpy(data[i].data.data, q, data[i].data.length); 1435 q += data[i].data.length; 1436 } 1437 if (piv) 1438 memcpy(piv->data.data, q, piv->data.length); 1439 1440 return 0; 1441} 1442 1443static krb5_error_code 1444iov_pad_validate(const struct _krb5_encryption_type *et, 1445 krb5_crypto_iov *data, 1446 int num_data, 1447 krb5_crypto_iov **ppiv) 1448{ 1449 krb5_crypto_iov *piv; 1450 size_t sz, headersz, block_sz, pad_sz, len; 1451 1452 len = iov_enc_data_len(data, num_data); 1453 1454 headersz = et->confoundersize; 1455 1456 sz = headersz + len; 1457 block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ 1458 1459 pad_sz = block_sz - sz; 1460 1461 piv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_PADDING); 1462 /* its ok to have no TYPE_PADDING if there is no padding */ 1463 if (piv == NULL && pad_sz != 0) 1464 return KRB5_BAD_MSIZE; 1465 if (piv) { 1466 if (piv->data.length < pad_sz) 1467 return KRB5_BAD_MSIZE; 1468 piv->data.length = pad_sz; 1469 if (pad_sz) 1470 memset(piv->data.data, pad_sz, pad_sz); 1471 else 1472 piv = NULL; 1473 } 1474 1475 *ppiv = piv; 1476 return 0; 1477} 1478 1479/** 1480 * Inline encrypt a kerberos message 1481 * 1482 * @param context Kerberos context 1483 * @param crypto Kerberos crypto context 1484 * @param usage Key usage for this buffer 1485 * @param data array of buffers to process 1486 * @param num_data length of array 1487 * @param ivec initial cbc/cts vector 1488 * 1489 * @return Return an error code or 0. 1490 * @ingroup krb5_crypto 1491 * 1492 * Kerberos encrypted data look like this: 1493 * 1494 * 1. KRB5_CRYPTO_TYPE_HEADER 1495 * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...] 1496 * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver 1497 * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is 1498 * commonly used headers and trailers. 1499 * 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1 1500 * 4. KRB5_CRYPTO_TYPE_TRAILER 1501 */ 1502 1503KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1504krb5_encrypt_iov_ivec(krb5_context context, 1505 krb5_crypto crypto, 1506 unsigned usage, 1507 krb5_crypto_iov *data, 1508 int num_data, 1509 void *ivec) 1510{ 1511 size_t headersz, trailersz; 1512 Checksum cksum; 1513 krb5_data enc_data, sign_data; 1514 krb5_error_code ret; 1515 struct _krb5_key_data *dkey; 1516 const struct _krb5_encryption_type *et = crypto->et; 1517 krb5_crypto_iov *tiv, *piv, *hiv; 1518 1519 if (num_data < 0) { 1520 krb5_clear_error_message(context); 1521 return KRB5_CRYPTO_INTERNAL; 1522 } 1523 1524 if(!derived_crypto(context, crypto)) { 1525 krb5_clear_error_message(context); 1526 return KRB5_CRYPTO_INTERNAL; 1527 } 1528 1529 krb5_data_zero(&enc_data); 1530 krb5_data_zero(&sign_data); 1531 1532 headersz = et->confoundersize; 1533 trailersz = CHECKSUMSIZE(et->keyed_checksum); 1534 1535 /* header */ 1536 hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER); 1537 if (hiv == NULL || hiv->data.length != headersz) 1538 return KRB5_BAD_MSIZE; 1539 krb5_generate_random_block(hiv->data.data, hiv->data.length); 1540 1541 /* padding */ 1542 ret = iov_pad_validate(et, data, num_data, &piv); 1543 if(ret) 1544 goto cleanup; 1545 1546 /* trailer */ 1547 tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); 1548 if (tiv == NULL || tiv->data.length != trailersz) { 1549 ret = KRB5_BAD_MSIZE; 1550 goto cleanup; 1551 } 1552 1553 if (et->flags & F_ENC_THEN_CKSUM) { 1554 unsigned char old_ivec[EVP_MAX_IV_LENGTH]; 1555 krb5_data ivec_data; 1556 1557 ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data); 1558 if(ret) 1559 goto cleanup; 1560 1561 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1562 if(ret) 1563 goto cleanup; 1564 1565 ret = _key_schedule(context, dkey); 1566 if(ret) 1567 goto cleanup; 1568 1569 heim_assert(et->blocksize <= sizeof(old_ivec), 1570 "blocksize too big for ivec buffer"); 1571 1572 if (ivec) 1573 memcpy(old_ivec, ivec, et->blocksize); 1574 else 1575 memset(old_ivec, 0, et->blocksize); 1576 1577 ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length, 1578 1, usage, ivec); 1579 if(ret) 1580 goto cleanup; 1581 1582 ret = iov_uncoalesce(context, &enc_data, data, num_data); 1583 if(ret) 1584 goto cleanup; 1585 1586 ivec_data.length = et->blocksize; 1587 ivec_data.data = old_ivec; 1588 1589 ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data); 1590 if(ret) 1591 goto cleanup; 1592 } else { 1593 ret = iov_coalesce(context, NULL, data, num_data, TRUE, &sign_data); 1594 if(ret) 1595 goto cleanup; 1596 } 1597 1598 ret = create_checksum(context, 1599 et->keyed_checksum, 1600 crypto, 1601 INTEGRITY_USAGE(usage), 1602 sign_data.data, 1603 sign_data.length, 1604 &cksum); 1605 if(ret == 0 && cksum.checksum.length != trailersz) { 1606 free_Checksum (&cksum); 1607 krb5_clear_error_message (context); 1608 ret = KRB5_CRYPTO_INTERNAL; 1609 } 1610 if(ret) 1611 goto cleanup; 1612 1613 /* save cksum at end */ 1614 memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length); 1615 free_Checksum (&cksum); 1616 1617 if (!(et->flags & F_ENC_THEN_CKSUM)) { 1618 ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data); 1619 if(ret) 1620 goto cleanup; 1621 1622 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1623 if(ret) 1624 goto cleanup; 1625 1626 ret = _key_schedule(context, dkey); 1627 if(ret) 1628 goto cleanup; 1629 1630 ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length, 1631 1, usage, ivec); 1632 if(ret) 1633 goto cleanup; 1634 1635 ret = iov_uncoalesce(context, &enc_data, data, num_data); 1636 if(ret) 1637 goto cleanup; 1638 } 1639 1640cleanup: 1641 if (enc_data.data) { 1642 memset_s(enc_data.data, enc_data.length, 0, enc_data.length); 1643 krb5_data_free(&enc_data); 1644 } 1645 if (sign_data.data) { 1646 memset_s(sign_data.data, sign_data.length, 0, sign_data.length); 1647 krb5_data_free(&sign_data); 1648 } 1649 return ret; 1650} 1651 1652/** 1653 * Inline decrypt a Kerberos message. 1654 * 1655 * @param context Kerberos context 1656 * @param crypto Kerberos crypto context 1657 * @param usage Key usage for this buffer 1658 * @param data array of buffers to process 1659 * @param num_data length of array 1660 * @param ivec initial cbc/cts vector 1661 * 1662 * @return Return an error code or 0. 1663 * @ingroup krb5_crypto 1664 * 1665 * 1. KRB5_CRYPTO_TYPE_HEADER 1666 * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in 1667 * any order, however the receiver have to aware of the 1668 * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted 1669 * protocol headers and trailers. The output data will be of same 1670 * size as the input data or shorter. 1671 */ 1672 1673KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1674krb5_decrypt_iov_ivec(krb5_context context, 1675 krb5_crypto crypto, 1676 unsigned usage, 1677 krb5_crypto_iov *data, 1678 unsigned int num_data, 1679 void *ivec) 1680{ 1681 Checksum cksum; 1682 krb5_data enc_data, sign_data; 1683 krb5_error_code ret; 1684 struct _krb5_key_data *dkey; 1685 struct _krb5_encryption_type *et = crypto->et; 1686 krb5_crypto_iov *tiv, *hiv; 1687 1688 if(!derived_crypto(context, crypto)) { 1689 krb5_clear_error_message(context); 1690 return KRB5_CRYPTO_INTERNAL; 1691 } 1692 1693 /* header */ 1694 hiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_HEADER); 1695 if (hiv == NULL || hiv->data.length != et->confoundersize) 1696 return KRB5_BAD_MSIZE; 1697 1698 /* trailer */ 1699 tiv = iov_find(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); 1700 if (tiv->data.length != CHECKSUMSIZE(et->keyed_checksum)) 1701 return KRB5_BAD_MSIZE; 1702 1703 /* padding */ 1704 if ((iov_enc_data_len(data, num_data) % et->padsize) != 0) { 1705 krb5_clear_error_message(context); 1706 return KRB5_BAD_MSIZE; 1707 } 1708 1709 krb5_data_zero(&enc_data); 1710 krb5_data_zero(&sign_data); 1711 1712 if (!(et->flags & F_ENC_THEN_CKSUM)) { 1713 ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data); 1714 if(ret) 1715 goto cleanup; 1716 1717 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1718 if(ret) 1719 goto cleanup; 1720 1721 ret = _key_schedule(context, dkey); 1722 if(ret) 1723 goto cleanup; 1724 1725 ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length, 1726 0, usage, ivec); 1727 if(ret) 1728 goto cleanup; 1729 1730 ret = iov_uncoalesce(context, &enc_data, data, num_data); 1731 if(ret) 1732 goto cleanup; 1733 1734 ret = iov_coalesce(context, NULL, data, num_data, TRUE, &sign_data); 1735 if(ret) 1736 goto cleanup; 1737 } else { 1738 krb5_data ivec_data; 1739 static unsigned char zero_ivec[EVP_MAX_IV_LENGTH]; 1740 1741 heim_assert(et->blocksize <= sizeof(zero_ivec), 1742 "blocksize too big for ivec buffer"); 1743 1744 ivec_data.length = et->blocksize; 1745 ivec_data.data = ivec ? ivec : zero_ivec; 1746 1747 ret = iov_coalesce(context, &ivec_data, data, num_data, TRUE, &sign_data); 1748 if(ret) 1749 goto cleanup; 1750 } 1751 1752 cksum.checksum.data = tiv->data.data; 1753 cksum.checksum.length = tiv->data.length; 1754 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1755 1756 ret = verify_checksum(context, 1757 crypto, 1758 INTEGRITY_USAGE(usage), 1759 sign_data.data, 1760 sign_data.length, 1761 &cksum); 1762 if(ret) 1763 goto cleanup; 1764 1765 if (et->flags & F_ENC_THEN_CKSUM) { 1766 ret = iov_coalesce(context, NULL, data, num_data, FALSE, &enc_data); 1767 if(ret) 1768 goto cleanup; 1769 1770 ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); 1771 if(ret) 1772 goto cleanup; 1773 1774 ret = _key_schedule(context, dkey); 1775 if(ret) 1776 goto cleanup; 1777 1778 ret = (*et->encrypt)(context, dkey, enc_data.data, enc_data.length, 1779 0, usage, ivec); 1780 if(ret) 1781 goto cleanup; 1782 1783 ret = iov_uncoalesce(context, &enc_data, data, num_data); 1784 if(ret) 1785 goto cleanup; 1786 } 1787 1788cleanup: 1789 if (enc_data.data) { 1790 memset_s(enc_data.data, enc_data.length, 0, enc_data.length); 1791 krb5_data_free(&enc_data); 1792 } 1793 if (sign_data.data) { 1794 memset_s(sign_data.data, sign_data.length, 0, sign_data.length); 1795 krb5_data_free(&sign_data); 1796 } 1797 return ret; 1798} 1799 1800/** 1801 * Create a Kerberos message checksum. 1802 * 1803 * @param context Kerberos context 1804 * @param crypto Kerberos crypto context 1805 * @param usage Key usage for this buffer 1806 * @param data array of buffers to process 1807 * @param num_data length of array 1808 * @param type output data 1809 * 1810 * @return Return an error code or 0. 1811 * @ingroup krb5_crypto 1812 */ 1813 1814KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1815krb5_create_checksum_iov(krb5_context context, 1816 krb5_crypto crypto, 1817 unsigned usage, 1818 krb5_crypto_iov *data, 1819 unsigned int num_data, 1820 krb5_cksumtype *type) 1821{ 1822 Checksum cksum; 1823 krb5_crypto_iov *civ; 1824 krb5_error_code ret; 1825 size_t i; 1826 size_t len; 1827 char *p, *q; 1828 1829 if(!derived_crypto(context, crypto)) { 1830 krb5_clear_error_message(context); 1831 return KRB5_CRYPTO_INTERNAL; 1832 } 1833 1834 civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); 1835 if (civ == NULL) 1836 return KRB5_BAD_MSIZE; 1837 1838 len = 0; 1839 for (i = 0; i < num_data; i++) { 1840 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1841 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1842 continue; 1843 len += data[i].data.length; 1844 } 1845 1846 p = q = malloc(len); 1847 1848 for (i = 0; i < num_data; i++) { 1849 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1850 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1851 continue; 1852 memcpy(q, data[i].data.data, data[i].data.length); 1853 q += data[i].data.length; 1854 } 1855 1856 ret = krb5_create_checksum(context, crypto, usage, 0, p, len, &cksum); 1857 free(p); 1858 if (ret) 1859 return ret; 1860 1861 if (type) 1862 *type = cksum.cksumtype; 1863 1864 if (cksum.checksum.length > civ->data.length) { 1865 krb5_set_error_message(context, KRB5_BAD_MSIZE, 1866 N_("Checksum larger then input buffer", "")); 1867 free_Checksum(&cksum); 1868 return KRB5_BAD_MSIZE; 1869 } 1870 1871 civ->data.length = cksum.checksum.length; 1872 memcpy(civ->data.data, cksum.checksum.data, civ->data.length); 1873 free_Checksum(&cksum); 1874 1875 return 0; 1876} 1877 1878/** 1879 * Verify a Kerberos message checksum. 1880 * 1881 * @param context Kerberos context 1882 * @param crypto Kerberos crypto context 1883 * @param usage Key usage for this buffer 1884 * @param data array of buffers to process 1885 * @param num_data length of array 1886 * @param type return checksum type if not NULL 1887 * 1888 * @return Return an error code or 0. 1889 * @ingroup krb5_crypto 1890 */ 1891 1892KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1893krb5_verify_checksum_iov(krb5_context context, 1894 krb5_crypto crypto, 1895 unsigned usage, 1896 krb5_crypto_iov *data, 1897 unsigned int num_data, 1898 krb5_cksumtype *type) 1899{ 1900 struct _krb5_encryption_type *et = crypto->et; 1901 Checksum cksum; 1902 krb5_crypto_iov *civ; 1903 krb5_error_code ret; 1904 size_t i; 1905 size_t len; 1906 char *p, *q; 1907 1908 if(!derived_crypto(context, crypto)) { 1909 krb5_clear_error_message(context); 1910 return KRB5_CRYPTO_INTERNAL; 1911 } 1912 1913 civ = iov_find(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM); 1914 if (civ == NULL) 1915 return KRB5_BAD_MSIZE; 1916 1917 len = 0; 1918 for (i = 0; i < num_data; i++) { 1919 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1920 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1921 continue; 1922 len += data[i].data.length; 1923 } 1924 1925 p = q = malloc(len); 1926 1927 for (i = 0; i < num_data; i++) { 1928 if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && 1929 data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) 1930 continue; 1931 memcpy(q, data[i].data.data, data[i].data.length); 1932 q += data[i].data.length; 1933 } 1934 1935 cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); 1936 cksum.checksum.length = civ->data.length; 1937 cksum.checksum.data = civ->data.data; 1938 1939 ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum); 1940 free(p); 1941 1942 if (ret == 0 && type) 1943 *type = cksum.cksumtype; 1944 1945 return ret; 1946} 1947 1948 1949KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1950krb5_crypto_length(krb5_context context, 1951 krb5_crypto crypto, 1952 int type, 1953 size_t *len) 1954{ 1955 if (!derived_crypto(context, crypto)) { 1956 krb5_set_error_message(context, EINVAL, "not a derived crypto"); 1957 return EINVAL; 1958 } 1959 1960 switch(type) { 1961 case KRB5_CRYPTO_TYPE_EMPTY: 1962 *len = 0; 1963 return 0; 1964 case KRB5_CRYPTO_TYPE_HEADER: 1965 *len = crypto->et->blocksize; 1966 return 0; 1967 case KRB5_CRYPTO_TYPE_DATA: 1968 case KRB5_CRYPTO_TYPE_SIGN_ONLY: 1969 /* len must already been filled in */ 1970 return 0; 1971 case KRB5_CRYPTO_TYPE_PADDING: 1972 if (crypto->et->padsize > 1) 1973 *len = crypto->et->padsize; 1974 else 1975 *len = 0; 1976 return 0; 1977 case KRB5_CRYPTO_TYPE_TRAILER: 1978 *len = CHECKSUMSIZE(crypto->et->keyed_checksum); 1979 return 0; 1980 case KRB5_CRYPTO_TYPE_CHECKSUM: 1981 if (crypto->et->keyed_checksum) 1982 *len = CHECKSUMSIZE(crypto->et->keyed_checksum); 1983 else 1984 *len = CHECKSUMSIZE(crypto->et->checksum); 1985 return 0; 1986 } 1987 krb5_set_error_message(context, EINVAL, 1988 "%d not a supported type", type); 1989 return EINVAL; 1990} 1991 1992 1993KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 1994krb5_crypto_length_iov(krb5_context context, 1995 krb5_crypto crypto, 1996 krb5_crypto_iov *data, 1997 unsigned int num_data) 1998{ 1999 krb5_error_code ret; 2000 size_t i; 2001 2002 for (i = 0; i < num_data; i++) { 2003 ret = krb5_crypto_length(context, crypto, 2004 data[i].flags, 2005 &data[i].data.length); 2006 if (ret) 2007 return ret; 2008 } 2009 return 0; 2010} 2011 2012 2013KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2014krb5_encrypt_ivec(krb5_context context, 2015 krb5_crypto crypto, 2016 unsigned usage, 2017 const void *data, 2018 size_t len, 2019 krb5_data *result, 2020 void *ivec) 2021{ 2022 krb5_error_code ret; 2023 2024 switch (crypto->et->flags & F_CRYPTO_MASK) { 2025 case F_RFC3961_ENC: 2026 ret = encrypt_internal_derived(context, crypto, usage, 2027 data, len, result, ivec); 2028 break; 2029 case F_SPECIAL: 2030 ret = encrypt_internal_special (context, crypto, usage, 2031 data, len, result, ivec); 2032 break; 2033 case F_ENC_THEN_CKSUM: 2034 ret = encrypt_internal_enc_then_cksum(context, crypto, usage, 2035 data, len, result, ivec); 2036 break; 2037 default: 2038 ret = encrypt_internal(context, crypto, data, len, result, ivec); 2039 break; 2040 } 2041 2042 return ret; 2043} 2044 2045KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2046krb5_encrypt(krb5_context context, 2047 krb5_crypto crypto, 2048 unsigned usage, 2049 const void *data, 2050 size_t len, 2051 krb5_data *result) 2052{ 2053 return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); 2054} 2055 2056KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2057krb5_encrypt_EncryptedData(krb5_context context, 2058 krb5_crypto crypto, 2059 unsigned usage, 2060 void *data, 2061 size_t len, 2062 int kvno, 2063 EncryptedData *result) 2064{ 2065 result->etype = CRYPTO_ETYPE(crypto); 2066 if(kvno){ 2067 ALLOC(result->kvno, 1); 2068 *result->kvno = kvno; 2069 }else 2070 result->kvno = NULL; 2071 return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); 2072} 2073 2074KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2075krb5_decrypt_ivec(krb5_context context, 2076 krb5_crypto crypto, 2077 unsigned usage, 2078 void *data, 2079 size_t len, 2080 krb5_data *result, 2081 void *ivec) 2082{ 2083 krb5_error_code ret; 2084 2085 switch (crypto->et->flags & F_CRYPTO_MASK) { 2086 case F_RFC3961_ENC: 2087 ret = decrypt_internal_derived(context, crypto, usage, 2088 data, len, result, ivec); 2089 break; 2090 case F_SPECIAL: 2091 ret = decrypt_internal_special(context, crypto, usage, 2092 data, len, result, ivec); 2093 break; 2094 case F_ENC_THEN_CKSUM: 2095 ret = decrypt_internal_enc_then_cksum(context, crypto, usage, 2096 data, len, result, ivec); 2097 break; 2098 default: 2099 ret = decrypt_internal(context, crypto, data, len, result, ivec); 2100 break; 2101 } 2102 2103 return ret; 2104} 2105 2106KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2107krb5_decrypt(krb5_context context, 2108 krb5_crypto crypto, 2109 unsigned usage, 2110 void *data, 2111 size_t len, 2112 krb5_data *result) 2113{ 2114 return krb5_decrypt_ivec (context, crypto, usage, data, len, result, 2115 NULL); 2116} 2117 2118KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2119krb5_decrypt_EncryptedData(krb5_context context, 2120 krb5_crypto crypto, 2121 unsigned usage, 2122 const EncryptedData *e, 2123 krb5_data *result) 2124{ 2125 return krb5_decrypt(context, crypto, usage, 2126 e->cipher.data, e->cipher.length, result); 2127} 2128 2129/************************************************************ 2130 * * 2131 ************************************************************/ 2132 2133static krb5_error_code 2134derive_key_rfc3961(krb5_context context, 2135 struct _krb5_encryption_type *et, 2136 struct _krb5_key_data *key, 2137 const void *constant, 2138 size_t len) 2139{ 2140 2141 unsigned char *k = NULL; 2142 unsigned int nblocks = 0, i; 2143 krb5_error_code ret = 0; 2144 struct _krb5_key_type *kt = et->keytype; 2145 2146 if(et->blocksize * 8 < kt->bits || len != et->blocksize) { 2147 nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); 2148 k = malloc(nblocks * et->blocksize); 2149 if(k == NULL) { 2150 ret = krb5_enomem(context); 2151 goto out; 2152 } 2153 ret = _krb5_n_fold(constant, len, k, et->blocksize); 2154 if (ret) { 2155 krb5_enomem(context); 2156 goto out; 2157 } 2158 2159 for(i = 0; i < nblocks; i++) { 2160 if(i > 0) 2161 memcpy(k + i * et->blocksize, 2162 k + (i - 1) * et->blocksize, 2163 et->blocksize); 2164 (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, 2165 1, 0, NULL); 2166 } 2167 } else { 2168 /* this case is probably broken, but won't be run anyway */ 2169 void *c = malloc(len); 2170 size_t res_len = (kt->bits + 7) / 8; 2171 2172 if(len != 0 && c == NULL) { 2173 ret = krb5_enomem(context); 2174 goto out; 2175 } 2176 memcpy(c, constant, len); 2177 (*et->encrypt)(context, key, c, len, 1, 0, NULL); 2178 k = malloc(res_len); 2179 if(res_len != 0 && k == NULL) { 2180 free(c); 2181 ret = krb5_enomem(context); 2182 goto out; 2183 } 2184 ret = _krb5_n_fold(c, len, k, res_len); 2185 free(c); 2186 if (ret) { 2187 krb5_enomem(context); 2188 goto out; 2189 } 2190 } 2191 2192 if (kt->type == KRB5_ENCTYPE_OLD_DES3_CBC_SHA1) 2193 _krb5_DES3_random_to_key(context, key->key, k, nblocks * et->blocksize); 2194 else 2195 memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); 2196 2197 out: 2198 if (k) { 2199 memset_s(k, nblocks * et->blocksize, 0, nblocks * et->blocksize); 2200 free(k); 2201 } 2202 return ret; 2203} 2204 2205static krb5_error_code 2206derive_key_sp800_hmac(krb5_context context, 2207 struct _krb5_encryption_type *et, 2208 struct _krb5_key_data *key, 2209 const void *constant, 2210 size_t len) 2211{ 2212 krb5_error_code ret; 2213 struct _krb5_key_type *kt = et->keytype; 2214 krb5_data label; 2215 const EVP_MD *md = NULL; 2216 const unsigned char *c = constant; 2217 size_t key_len; 2218 krb5_data K1; 2219 2220 ret = _krb5_aes_sha2_md_for_enctype(context, kt->type, &md); 2221 if (ret) 2222 return ret; 2223 2224 /* 2225 * PRF usage: not handled here (output cannot be longer) 2226 * Integrity usage: truncated hash (half length) 2227 * Encryption usage: base key length 2228 */ 2229 if (len == 5 && (c[4] == 0x99 || c[4] == 0x55)) 2230 key_len = EVP_MD_size(md) / 2; 2231 else 2232 key_len = kt->size; 2233 2234 ret = krb5_data_alloc(&K1, key_len); 2235 if (ret) 2236 return ret; 2237 2238 label.data = (void *)constant; 2239 label.length = len; 2240 2241 ret = _krb5_SP800_108_HMAC_KDF(context, &key->key->keyvalue, 2242 &label, NULL, md, &K1); 2243 if (ret == 0) { 2244 if (key->key->keyvalue.length > key_len) 2245 key->key->keyvalue.length = key_len; 2246 memcpy(key->key->keyvalue.data, K1.data, key_len); 2247 } 2248 2249 memset_s(K1.data, K1.length, 0, K1.length); 2250 krb5_data_free(&K1); 2251 2252 return ret; 2253} 2254 2255KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2256_krb5_derive_key(krb5_context context, 2257 struct _krb5_encryption_type *et, 2258 struct _krb5_key_data *key, 2259 const void *constant, 2260 size_t len) 2261{ 2262 krb5_error_code ret; 2263 2264 ret = _key_schedule(context, key); 2265 if(ret) 2266 return ret; 2267 2268 switch (et->flags & F_KDF_MASK) { 2269 case F_RFC3961_KDF: 2270 ret = derive_key_rfc3961(context, et, key, constant, len); 2271 break; 2272 case F_SP800_108_HMAC_KDF: 2273 ret = derive_key_sp800_hmac(context, et, key, constant, len); 2274 break; 2275 default: 2276 ret = KRB5_CRYPTO_INTERNAL; 2277 krb5_set_error_message(context, ret, 2278 N_("derive_key() called with unknown keytype (%u)", ""), 2279 et->keytype->type); 2280 break; 2281 } 2282 2283 if (key->schedule) { 2284 free_key_schedule(context, key, et); 2285 key->schedule = NULL; 2286 } 2287 2288 return ret; 2289} 2290 2291static struct _krb5_key_data * 2292_new_derived_key(krb5_crypto crypto, unsigned usage) 2293{ 2294 struct _krb5_key_usage *d = crypto->key_usage; 2295 d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); 2296 if(d == NULL) 2297 return NULL; 2298 crypto->key_usage = d; 2299 d += crypto->num_key_usage++; 2300 memset(d, 0, sizeof(*d)); 2301 d->usage = usage; 2302 return &d->key; 2303} 2304 2305KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2306krb5_derive_key(krb5_context context, 2307 const krb5_keyblock *key, 2308 krb5_enctype etype, 2309 const void *constant, 2310 size_t constant_len, 2311 krb5_keyblock **derived_key) 2312{ 2313 krb5_error_code ret; 2314 struct _krb5_encryption_type *et; 2315 struct _krb5_key_data d; 2316 2317 *derived_key = NULL; 2318 2319 et = _krb5_find_enctype (etype); 2320 if (et == NULL) { 2321 return unsupported_enctype (context, etype); 2322 } 2323 2324 ret = krb5_copy_keyblock(context, key, &d.key); 2325 if (ret) 2326 return ret; 2327 2328 d.schedule = NULL; 2329 ret = _krb5_derive_key(context, et, &d, constant, constant_len); 2330 if (ret == 0) 2331 ret = krb5_copy_keyblock(context, d.key, derived_key); 2332 _krb5_free_key_data(context, &d, et); 2333 return ret; 2334} 2335 2336static krb5_error_code 2337_get_derived_key(krb5_context context, 2338 krb5_crypto crypto, 2339 unsigned usage, 2340 struct _krb5_key_data **key) 2341{ 2342 int i; 2343 struct _krb5_key_data *d; 2344 unsigned char constant[5]; 2345 2346 *key = NULL; 2347 for(i = 0; i < crypto->num_key_usage; i++) 2348 if(crypto->key_usage[i].usage == usage) { 2349 *key = &crypto->key_usage[i].key; 2350 return 0; 2351 } 2352 d = _new_derived_key(crypto, usage); 2353 if (d == NULL) 2354 return krb5_enomem(context); 2355 *key = d; 2356 krb5_copy_keyblock(context, crypto->key.key, &d->key); 2357 _krb5_put_int(constant, usage, sizeof(constant)); 2358 return _krb5_derive_key(context, crypto->et, d, constant, sizeof(constant)); 2359} 2360 2361/** 2362 * Create a crypto context used for all encryption and signature 2363 * operation. The encryption type to use is taken from the key, but 2364 * can be overridden with the enctype parameter. This can be useful 2365 * for encryptions types which is compatiable (DES for example). 2366 * 2367 * To free the crypto context, use krb5_crypto_destroy(). 2368 * 2369 * @param context Kerberos context 2370 * @param key the key block information with all key data 2371 * @param etype the encryption type 2372 * @param crypto the resulting crypto context 2373 * 2374 * @return Return an error code or 0. 2375 * 2376 * @ingroup krb5_crypto 2377 */ 2378 2379KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2380krb5_crypto_init(krb5_context context, 2381 const krb5_keyblock *key, 2382 krb5_enctype etype, 2383 krb5_crypto *crypto) 2384{ 2385 krb5_error_code ret; 2386 ALLOC(*crypto, 1); 2387 if (*crypto == NULL) 2388 return krb5_enomem(context); 2389 if(etype == (krb5_enctype)ETYPE_NULL) 2390 etype = key->keytype; 2391 (*crypto)->et = _krb5_find_enctype(etype); 2392 if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { 2393 free(*crypto); 2394 *crypto = NULL; 2395 return unsupported_enctype(context, etype); 2396 } 2397 if((*crypto)->et->keytype->size != key->keyvalue.length) { 2398 free(*crypto); 2399 *crypto = NULL; 2400 krb5_set_error_message (context, KRB5_BAD_KEYSIZE, 2401 "encryption key has bad length"); 2402 return KRB5_BAD_KEYSIZE; 2403 } 2404 ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); 2405 if(ret) { 2406 free(*crypto); 2407 *crypto = NULL; 2408 return ret; 2409 } 2410 (*crypto)->key.schedule = NULL; 2411 (*crypto)->num_key_usage = 0; 2412 (*crypto)->key_usage = NULL; 2413 return 0; 2414} 2415 2416static void 2417free_key_schedule(krb5_context context, 2418 struct _krb5_key_data *key, 2419 struct _krb5_encryption_type *et) 2420{ 2421 if (et->keytype->cleanup) 2422 (*et->keytype->cleanup)(context, key); 2423 memset(key->schedule->data, 0, key->schedule->length); 2424 krb5_free_data(context, key->schedule); 2425} 2426 2427KRB5_LIB_FUNCTION void KRB5_LIB_CALL 2428_krb5_free_key_data(krb5_context context, struct _krb5_key_data *key, 2429 struct _krb5_encryption_type *et) 2430{ 2431 krb5_free_keyblock(context, key->key); 2432 if(key->schedule) { 2433 free_key_schedule(context, key, et); 2434 key->schedule = NULL; 2435 } 2436} 2437 2438static void 2439free_key_usage(krb5_context context, struct _krb5_key_usage *ku, 2440 struct _krb5_encryption_type *et) 2441{ 2442 _krb5_free_key_data(context, &ku->key, et); 2443} 2444 2445/** 2446 * Free a crypto context created by krb5_crypto_init(). 2447 * 2448 * @param context Kerberos context 2449 * @param crypto crypto context to free 2450 * 2451 * @return Return an error code or 0. 2452 * 2453 * @ingroup krb5_crypto 2454 */ 2455 2456KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2457krb5_crypto_destroy(krb5_context context, 2458 krb5_crypto crypto) 2459{ 2460 int i; 2461 2462 for(i = 0; i < crypto->num_key_usage; i++) 2463 free_key_usage(context, &crypto->key_usage[i], crypto->et); 2464 free(crypto->key_usage); 2465 _krb5_free_key_data(context, &crypto->key, crypto->et); 2466 free (crypto); 2467 return 0; 2468} 2469 2470/** 2471 * Return the blocksize used algorithm referenced by the crypto context 2472 * 2473 * @param context Kerberos context 2474 * @param crypto crypto context to query 2475 * @param blocksize the resulting blocksize 2476 * 2477 * @return Return an error code or 0. 2478 * 2479 * @ingroup krb5_crypto 2480 */ 2481 2482KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2483krb5_crypto_getblocksize(krb5_context context, 2484 krb5_crypto crypto, 2485 size_t *blocksize) 2486{ 2487 *blocksize = crypto->et->blocksize; 2488 return 0; 2489} 2490 2491/** 2492 * Return the encryption type used by the crypto context 2493 * 2494 * @param context Kerberos context 2495 * @param crypto crypto context to query 2496 * @param enctype the resulting encryption type 2497 * 2498 * @return Return an error code or 0. 2499 * 2500 * @ingroup krb5_crypto 2501 */ 2502 2503KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2504krb5_crypto_getenctype(krb5_context context, 2505 krb5_crypto crypto, 2506 krb5_enctype *enctype) 2507{ 2508 *enctype = crypto->et->type; 2509 return 0; 2510} 2511 2512/** 2513 * Return the padding size used by the crypto context 2514 * 2515 * @param context Kerberos context 2516 * @param crypto crypto context to query 2517 * @param padsize the return padding size 2518 * 2519 * @return Return an error code or 0. 2520 * 2521 * @ingroup krb5_crypto 2522 */ 2523 2524KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2525krb5_crypto_getpadsize(krb5_context context, 2526 krb5_crypto crypto, 2527 size_t *padsize) 2528{ 2529 *padsize = crypto->et->padsize; 2530 return 0; 2531} 2532 2533/** 2534 * Return the confounder size used by the crypto context 2535 * 2536 * @param context Kerberos context 2537 * @param crypto crypto context to query 2538 * @param confoundersize the returned confounder size 2539 * 2540 * @return Return an error code or 0. 2541 * 2542 * @ingroup krb5_crypto 2543 */ 2544 2545KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2546krb5_crypto_getconfoundersize(krb5_context context, 2547 krb5_crypto crypto, 2548 size_t *confoundersize) 2549{ 2550 *confoundersize = crypto->et->confoundersize; 2551 return 0; 2552} 2553 2554 2555/** 2556 * Disable encryption type 2557 * 2558 * @param context Kerberos 5 context 2559 * @param enctype encryption type to disable 2560 * 2561 * @return Return an error code or 0. 2562 * 2563 * @ingroup krb5_crypto 2564 */ 2565 2566KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2567krb5_enctype_disable(krb5_context context, 2568 krb5_enctype enctype) 2569{ 2570 struct _krb5_encryption_type *et = _krb5_find_enctype(enctype); 2571 if(et == NULL) { 2572 if (context) 2573 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 2574 N_("encryption type %d not supported", ""), 2575 enctype); 2576 return KRB5_PROG_ETYPE_NOSUPP; 2577 } 2578 et->flags |= F_DISABLED; 2579 return 0; 2580} 2581 2582/** 2583 * Enable encryption type 2584 * 2585 * @param context Kerberos 5 context 2586 * @param enctype encryption type to enable 2587 * 2588 * @return Return an error code or 0. 2589 * 2590 * @ingroup krb5_crypto 2591 */ 2592 2593KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2594krb5_enctype_enable(krb5_context context, 2595 krb5_enctype enctype) 2596{ 2597 struct _krb5_encryption_type *et = _krb5_find_enctype(enctype); 2598 if(et == NULL) { 2599 if (context) 2600 krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, 2601 N_("encryption type %d not supported", ""), 2602 enctype); 2603 return KRB5_PROG_ETYPE_NOSUPP; 2604 } 2605 et->flags &= ~F_DISABLED; 2606 return 0; 2607} 2608 2609/** 2610 * Enable or disable all weak encryption types 2611 * 2612 * @param context Kerberos 5 context 2613 * @param enable true to enable, false to disable 2614 * 2615 * @return Return an error code or 0. 2616 * 2617 * @ingroup krb5_crypto 2618 */ 2619 2620KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2621krb5_allow_weak_crypto(krb5_context context, 2622 krb5_boolean enable) 2623{ 2624 int i; 2625 2626 for(i = 0; i < _krb5_num_etypes; i++) 2627 if(_krb5_etypes[i]->flags & F_WEAK) { 2628 if(enable) 2629 _krb5_etypes[i]->flags &= ~F_DISABLED; 2630 else 2631 _krb5_etypes[i]->flags |= F_DISABLED; 2632 } 2633 return 0; 2634} 2635 2636/** 2637 * Returns is the encryption is strong or weak 2638 * 2639 * @param context Kerberos 5 context 2640 * @param enctype encryption type to probe 2641 * 2642 * @return Returns true if encryption type is weak or is not supported. 2643 * 2644 * @ingroup krb5_crypto 2645 */ 2646 2647KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 2648krb5_is_enctype_weak(krb5_context context, krb5_enctype enctype) 2649{ 2650 struct _krb5_encryption_type *et = _krb5_find_enctype(enctype); 2651 if(et == NULL || (et->flags & F_WEAK)) 2652 return TRUE; 2653 return FALSE; 2654} 2655 2656/** 2657 * Returns whether the encryption type should use randomly generated salts 2658 * 2659 * @param context Kerberos 5 context 2660 * @param enctype encryption type to probe 2661 * 2662 * @return Returns true if generated salts should have random component 2663 * 2664 * @ingroup krb5_crypto 2665 */ 2666KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 2667_krb5_enctype_requires_random_salt(krb5_context context, 2668 krb5_enctype enctype) 2669{ 2670 struct _krb5_encryption_type *et; 2671 2672 et = _krb5_find_enctype (enctype); 2673 2674 return et && (et->flags & F_SP800_108_HMAC_KDF); 2675} 2676 2677static size_t 2678wrapped_length (krb5_context context, 2679 krb5_crypto crypto, 2680 size_t data_len) 2681{ 2682 struct _krb5_encryption_type *et = crypto->et; 2683 size_t padsize = et->padsize; 2684 size_t checksumsize = CHECKSUMSIZE(et->checksum); 2685 size_t res; 2686 2687 res = et->confoundersize + checksumsize + data_len; 2688 res = (res + padsize - 1) / padsize * padsize; 2689 return res; 2690} 2691 2692static size_t 2693wrapped_length_dervied (krb5_context context, 2694 krb5_crypto crypto, 2695 size_t data_len) 2696{ 2697 struct _krb5_encryption_type *et = crypto->et; 2698 size_t padsize = et->padsize; 2699 size_t res; 2700 2701 res = et->confoundersize + data_len; 2702 res = (res + padsize - 1) / padsize * padsize; 2703 if (et->keyed_checksum) 2704 res += et->keyed_checksum->checksumsize; 2705 else 2706 res += et->checksum->checksumsize; 2707 return res; 2708} 2709 2710/* 2711 * Return the size of an encrypted packet of length `data_len' 2712 */ 2713 2714KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL 2715krb5_get_wrapped_length (krb5_context context, 2716 krb5_crypto crypto, 2717 size_t data_len) 2718{ 2719 if (derived_crypto (context, crypto)) 2720 return wrapped_length_dervied (context, crypto, data_len); 2721 else 2722 return wrapped_length (context, crypto, data_len); 2723} 2724 2725/* 2726 * Return the size of an encrypted packet of length `data_len' 2727 */ 2728 2729static size_t 2730crypto_overhead (krb5_context context, 2731 krb5_crypto crypto) 2732{ 2733 struct _krb5_encryption_type *et = crypto->et; 2734 size_t res; 2735 2736 res = CHECKSUMSIZE(et->checksum); 2737 res += et->confoundersize; 2738 if (et->padsize > 1) 2739 res += et->padsize; 2740 return res; 2741} 2742 2743static size_t 2744crypto_overhead_dervied (krb5_context context, 2745 krb5_crypto crypto) 2746{ 2747 struct _krb5_encryption_type *et = crypto->et; 2748 size_t res; 2749 2750 if (et->keyed_checksum) 2751 res = CHECKSUMSIZE(et->keyed_checksum); 2752 else 2753 res = CHECKSUMSIZE(et->checksum); 2754 res += et->confoundersize; 2755 if (et->padsize > 1) 2756 res += et->padsize; 2757 return res; 2758} 2759 2760KRB5_LIB_FUNCTION size_t KRB5_LIB_CALL 2761krb5_crypto_overhead (krb5_context context, krb5_crypto crypto) 2762{ 2763 if (derived_crypto (context, crypto)) 2764 return crypto_overhead_dervied (context, crypto); 2765 else 2766 return crypto_overhead (context, crypto); 2767} 2768 2769/** 2770 * Converts the random bytestring to a protocol key according to 2771 * Kerberos crypto frame work. It may be assumed that all the bits of 2772 * the input string are equally random, even though the entropy 2773 * present in the random source may be limited. 2774 * 2775 * @param context Kerberos 5 context 2776 * @param type the enctype resulting key will be of 2777 * @param data input random data to convert to a key 2778 * @param size size of input random data, at least krb5_enctype_keysize() long 2779 * @param key key, output key, free with krb5_free_keyblock_contents() 2780 * 2781 * @return Return an error code or 0. 2782 * 2783 * @ingroup krb5_crypto 2784 */ 2785 2786KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2787krb5_random_to_key(krb5_context context, 2788 krb5_enctype type, 2789 const void *data, 2790 size_t size, 2791 krb5_keyblock *key) 2792{ 2793 krb5_error_code ret; 2794 struct _krb5_encryption_type *et = _krb5_find_enctype(type); 2795 if(et == NULL) { 2796 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2797 N_("encryption type %d not supported", ""), 2798 type); 2799 return KRB5_PROG_ETYPE_NOSUPP; 2800 } 2801 if ((et->keytype->bits + 7) / 8 > size) { 2802 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2803 N_("encryption key %s needs %d bytes " 2804 "of random to make an encryption key " 2805 "out of it", ""), 2806 et->name, (int)et->keytype->size); 2807 return KRB5_PROG_ETYPE_NOSUPP; 2808 } 2809 ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); 2810 if(ret) 2811 return ret; 2812 key->keytype = type; 2813 if (et->keytype->random_to_key) 2814 (*et->keytype->random_to_key)(context, key, data, size); 2815 else 2816 memcpy(key->keyvalue.data, data, et->keytype->size); 2817 2818 return 0; 2819} 2820 2821 2822 2823KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2824krb5_crypto_prf_length(krb5_context context, 2825 krb5_enctype type, 2826 size_t *length) 2827{ 2828 struct _krb5_encryption_type *et = _krb5_find_enctype(type); 2829 2830 if(et == NULL || et->prf_length == 0) { 2831 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2832 N_("encryption type %d not supported", ""), 2833 type); 2834 return KRB5_PROG_ETYPE_NOSUPP; 2835 } 2836 2837 *length = et->prf_length; 2838 return 0; 2839} 2840 2841KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2842krb5_crypto_prf(krb5_context context, 2843 const krb5_crypto crypto, 2844 const krb5_data *input, 2845 krb5_data *output) 2846{ 2847 struct _krb5_encryption_type *et = crypto->et; 2848 2849 krb5_data_zero(output); 2850 2851 if(et->prf == NULL) { 2852 krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, 2853 "kerberos prf for %s not supported", 2854 et->name); 2855 return KRB5_PROG_ETYPE_NOSUPP; 2856 } 2857 2858 return (*et->prf)(context, crypto, input, output); 2859} 2860 2861static krb5_error_code 2862krb5_crypto_prfplus(krb5_context context, 2863 const krb5_crypto crypto, 2864 const krb5_data *input, 2865 size_t length, 2866 krb5_data *output) 2867{ 2868 krb5_error_code ret; 2869 krb5_data input2; 2870 unsigned char i = 1; 2871 unsigned char *p; 2872 2873 krb5_data_zero(&input2); 2874 krb5_data_zero(output); 2875 2876 krb5_clear_error_message(context); 2877 2878 ret = krb5_data_alloc(output, length); 2879 if (ret) goto out; 2880 ret = krb5_data_alloc(&input2, input->length + 1); 2881 if (ret) goto out; 2882 2883 krb5_clear_error_message(context); 2884 2885 memcpy(((unsigned char *)input2.data) + 1, input->data, input->length); 2886 2887 p = output->data; 2888 2889 while (length) { 2890 krb5_data block; 2891 2892 ((unsigned char *)input2.data)[0] = i++; 2893 2894 ret = krb5_crypto_prf(context, crypto, &input2, &block); 2895 if (ret) 2896 goto out; 2897 2898 if (block.length < length) { 2899 memcpy(p, block.data, block.length); 2900 length -= block.length; 2901 } else { 2902 memcpy(p, block.data, length); 2903 length = 0; 2904 } 2905 p += block.length; 2906 krb5_data_free(&block); 2907 } 2908 2909 out: 2910 krb5_data_free(&input2); 2911 if (ret) 2912 krb5_data_free(output); 2913 return ret; 2914} 2915 2916/** 2917 * The FX-CF2 key derivation function, used in FAST and preauth framework. 2918 * 2919 * @param context Kerberos 5 context 2920 * @param crypto1 first key to combine 2921 * @param crypto2 second key to combine 2922 * @param pepper1 factor to combine with first key to garante uniqueness 2923 * @param pepper2 factor to combine with second key to garante uniqueness 2924 * @param enctype the encryption type of the resulting key 2925 * @param res allocated key, free with krb5_free_keyblock_contents() 2926 * 2927 * @return Return an error code or 0. 2928 * 2929 * @ingroup krb5_crypto 2930 */ 2931 2932KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2933krb5_crypto_fx_cf2(krb5_context context, 2934 const krb5_crypto crypto1, 2935 const krb5_crypto crypto2, 2936 krb5_data *pepper1, 2937 krb5_data *pepper2, 2938 krb5_enctype enctype, 2939 krb5_keyblock *res) 2940{ 2941 krb5_error_code ret; 2942 krb5_data os1, os2; 2943 size_t i, keysize; 2944 2945 memset(res, 0, sizeof(*res)); 2946 krb5_data_zero(&os1); 2947 krb5_data_zero(&os2); 2948 2949 ret = krb5_enctype_keybits(context, enctype, &keysize); 2950 if (ret) 2951 return ret; 2952 keysize = (keysize + 7) / 8; 2953 2954 ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1); 2955 if (ret) 2956 goto out; 2957 ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2); 2958 if (ret) 2959 goto out; 2960 2961 res->keytype = enctype; 2962 { 2963 unsigned char *p1 = os1.data, *p2 = os2.data; 2964 for (i = 0; i < keysize; i++) 2965 p1[i] ^= p2[i]; 2966 } 2967 ret = krb5_random_to_key(context, enctype, os1.data, keysize, res); 2968 out: 2969 krb5_data_free(&os1); 2970 krb5_data_free(&os2); 2971 2972 return ret; 2973} 2974 2975 2976 2977#ifndef HEIMDAL_SMALLER 2978 2979/** 2980 * Deprecated: keytypes doesn't exists, they are really enctypes. 2981 * 2982 * @ingroup krb5_deprecated 2983 */ 2984 2985KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL 2986krb5_keytype_to_enctypes (krb5_context context, 2987 krb5_keytype keytype, 2988 unsigned *len, 2989 krb5_enctype **val) 2990 KRB5_DEPRECATED_FUNCTION("Use X instead") 2991{ 2992 int i; 2993 unsigned n = 0; 2994 krb5_enctype *ret; 2995 2996 for (i = _krb5_num_etypes - 1; i >= 0; --i) { 2997 if (_krb5_etypes[i]->keytype->type == keytype 2998 && !(_krb5_etypes[i]->flags & F_PSEUDO) 2999 && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0) 3000 ++n; 3001 } 3002 if (n == 0) { 3003 krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, 3004 "Keytype have no mapping"); 3005 return KRB5_PROG_KEYTYPE_NOSUPP; 3006 } 3007 3008 ret = malloc(n * sizeof(*ret)); 3009 if (ret == NULL && n != 0) 3010 return krb5_enomem(context); 3011 n = 0; 3012 for (i = _krb5_num_etypes - 1; i >= 0; --i) { 3013 if (_krb5_etypes[i]->keytype->type == keytype 3014 && !(_krb5_etypes[i]->flags & F_PSEUDO) 3015 && krb5_enctype_valid(context, _krb5_etypes[i]->type) == 0) 3016 ret[n++] = _krb5_etypes[i]->type; 3017 } 3018 *len = n; 3019 *val = ret; 3020 return 0; 3021} 3022 3023/** 3024 * Deprecated: keytypes doesn't exists, they are really enctypes. 3025 * 3026 * @ingroup krb5_deprecated 3027 */ 3028 3029/* if two enctypes have compatible keys */ 3030KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL 3031krb5_enctypes_compatible_keys(krb5_context context, 3032 krb5_enctype etype1, 3033 krb5_enctype etype2) 3034 KRB5_DEPRECATED_FUNCTION("Use X instead") 3035{ 3036 struct _krb5_encryption_type *e1 = _krb5_find_enctype(etype1); 3037 struct _krb5_encryption_type *e2 = _krb5_find_enctype(etype2); 3038 return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; 3039} 3040 3041#endif /* HEIMDAL_SMALLER */ 3042