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