1 /* 2 * COPYRIGHT (c) 2008 3 * The Regents of the University of Michigan 4 * ALL RIGHTS RESERVED 5 * 6 * Permission is granted to use, copy, create derivative works 7 * and redistribute this software and such derivative works 8 * for any purpose, so long as the name of The University of 9 * Michigan is not used in any advertising or publicity 10 * pertaining to the use of distribution of this software 11 * without specific, written prior authorization. If the 12 * above copyright notice or any other identification of the 13 * University of Michigan is included in any copy of any 14 * portion of this software, then the disclaimer below must 15 * also be included. 16 * 17 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 18 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 19 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 20 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 21 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 23 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 24 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 25 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 26 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 27 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGES. 29 */ 30 31 /* 32 * Copyright (C) 1998 by the FundsXpress, INC. 33 * 34 * All rights reserved. 35 * 36 * Export of this software from the United States of America may require 37 * a specific license from the United States Government. It is the 38 * responsibility of any person or organization contemplating export to 39 * obtain such a license before exporting. 40 * 41 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 42 * distribute this software and its documentation for any purpose and 43 * without fee is hereby granted, provided that the above copyright 44 * notice appear in all copies and that both that copyright notice and 45 * this permission notice appear in supporting documentation, and that 46 * the name of FundsXpress. not be used in advertising or publicity pertaining 47 * to distribution of the software without specific, written prior 48 * permission. FundsXpress makes no representations about the suitability of 49 * this software for any purpose. It is provided "as is" without express 50 * or implied warranty. 51 * 52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 53 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 54 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 55 */ 56 57 #include <crypto/skcipher.h> 58 #include <linux/err.h> 59 #include <linux/types.h> 60 #include <linux/sunrpc/gss_krb5.h> 61 #include <linux/sunrpc/xdr.h> 62 #include <linux/lcm.h> 63 #include <crypto/hash.h> 64 #include <kunit/visibility.h> 65 66 #include "gss_krb5_internal.h" 67 68 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) 69 # define RPCDBG_FACILITY RPCDBG_AUTH 70 #endif 71 72 /** 73 * krb5_nfold - n-fold function 74 * @inbits: number of bits in @in 75 * @in: buffer containing input to fold 76 * @outbits: number of bits in the output buffer 77 * @out: buffer to hold the result 78 * 79 * This is the n-fold function as described in rfc3961, sec 5.1 80 * Taken from MIT Kerberos and modified. 81 */ 82 VISIBLE_IF_KUNIT 83 void krb5_nfold(u32 inbits, const u8 *in, u32 outbits, u8 *out) 84 { 85 unsigned long ulcm; 86 int byte, i, msbit; 87 88 /* the code below is more readable if I make these bytes 89 instead of bits */ 90 91 inbits >>= 3; 92 outbits >>= 3; 93 94 /* first compute lcm(n,k) */ 95 ulcm = lcm(inbits, outbits); 96 97 /* now do the real work */ 98 99 memset(out, 0, outbits); 100 byte = 0; 101 102 /* this will end up cycling through k lcm(k,n)/k times, which 103 is correct */ 104 for (i = ulcm-1; i >= 0; i--) { 105 /* compute the msbit in k which gets added into this byte */ 106 msbit = ( 107 /* first, start with the msbit in the first, 108 * unrotated byte */ 109 ((inbits << 3) - 1) 110 /* then, for each byte, shift to the right 111 * for each repetition */ 112 + (((inbits << 3) + 13) * (i/inbits)) 113 /* last, pick out the correct byte within 114 * that shifted repetition */ 115 + ((inbits - (i % inbits)) << 3) 116 ) % (inbits << 3); 117 118 /* pull out the byte value itself */ 119 byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8)| 120 (in[((inbits) - (msbit >> 3)) % inbits])) 121 >> ((msbit & 7) + 1)) & 0xff; 122 123 /* do the addition */ 124 byte += out[i % outbits]; 125 out[i % outbits] = byte & 0xff; 126 127 /* keep around the carry bit, if any */ 128 byte >>= 8; 129 130 } 131 132 /* if there's a carry bit left over, add it back in */ 133 if (byte) { 134 for (i = outbits - 1; i >= 0; i--) { 135 /* do the addition */ 136 byte += out[i]; 137 out[i] = byte & 0xff; 138 139 /* keep around the carry bit, if any */ 140 byte >>= 8; 141 } 142 } 143 } 144 EXPORT_SYMBOL_IF_KUNIT(krb5_nfold); 145 146 /* 147 * This is the DK (derive_key) function as described in rfc3961, sec 5.1 148 * Taken from MIT Kerberos and modified. 149 */ 150 static int krb5_DK(const struct gss_krb5_enctype *gk5e, 151 const struct xdr_netobj *inkey, u8 *rawkey, 152 const struct xdr_netobj *in_constant, gfp_t gfp_mask) 153 { 154 size_t blocksize, keybytes, keylength, n; 155 unsigned char *inblockdata, *outblockdata; 156 struct xdr_netobj inblock, outblock; 157 struct crypto_sync_skcipher *cipher; 158 int ret = -EINVAL; 159 160 keybytes = gk5e->keybytes; 161 keylength = gk5e->keylength; 162 163 if (inkey->len != keylength) 164 goto err_return; 165 166 cipher = crypto_alloc_sync_skcipher(gk5e->encrypt_name, 0, 0); 167 if (IS_ERR(cipher)) 168 goto err_return; 169 blocksize = crypto_sync_skcipher_blocksize(cipher); 170 if (crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len)) 171 goto err_return; 172 173 ret = -ENOMEM; 174 inblockdata = kmalloc(blocksize, gfp_mask); 175 if (inblockdata == NULL) 176 goto err_free_cipher; 177 178 outblockdata = kmalloc(blocksize, gfp_mask); 179 if (outblockdata == NULL) 180 goto err_free_in; 181 182 inblock.data = (char *) inblockdata; 183 inblock.len = blocksize; 184 185 outblock.data = (char *) outblockdata; 186 outblock.len = blocksize; 187 188 /* initialize the input block */ 189 190 if (in_constant->len == inblock.len) { 191 memcpy(inblock.data, in_constant->data, inblock.len); 192 } else { 193 krb5_nfold(in_constant->len * 8, in_constant->data, 194 inblock.len * 8, inblock.data); 195 } 196 197 /* loop encrypting the blocks until enough key bytes are generated */ 198 199 n = 0; 200 while (n < keybytes) { 201 krb5_encrypt(cipher, NULL, inblock.data, outblock.data, 202 inblock.len); 203 204 if ((keybytes - n) <= outblock.len) { 205 memcpy(rawkey + n, outblock.data, (keybytes - n)); 206 break; 207 } 208 209 memcpy(rawkey + n, outblock.data, outblock.len); 210 memcpy(inblock.data, outblock.data, outblock.len); 211 n += outblock.len; 212 } 213 214 ret = 0; 215 216 kfree_sensitive(outblockdata); 217 err_free_in: 218 kfree_sensitive(inblockdata); 219 err_free_cipher: 220 crypto_free_sync_skcipher(cipher); 221 err_return: 222 return ret; 223 } 224 225 #define smask(step) ((1<<step)-1) 226 #define pstep(x, step) (((x)&smask(step))^(((x)>>step)&smask(step))) 227 #define parity_char(x) pstep(pstep(pstep((x), 4), 2), 1) 228 229 static void mit_des_fixup_key_parity(u8 key[8]) 230 { 231 int i; 232 for (i = 0; i < 8; i++) { 233 key[i] &= 0xfe; 234 key[i] |= 1^parity_char(key[i]); 235 } 236 } 237 238 static int krb5_random_to_key_v1(const struct gss_krb5_enctype *gk5e, 239 struct xdr_netobj *randombits, 240 struct xdr_netobj *key) 241 { 242 int i, ret = -EINVAL; 243 244 if (key->len != 24) { 245 dprintk("%s: key->len is %d\n", __func__, key->len); 246 goto err_out; 247 } 248 if (randombits->len != 21) { 249 dprintk("%s: randombits->len is %d\n", 250 __func__, randombits->len); 251 goto err_out; 252 } 253 254 /* take the seven bytes, move them around into the top 7 bits of the 255 8 key bytes, then compute the parity bits. Do this three times. */ 256 257 for (i = 0; i < 3; i++) { 258 memcpy(key->data + i*8, randombits->data + i*7, 7); 259 key->data[i*8+7] = (((key->data[i*8]&1)<<1) | 260 ((key->data[i*8+1]&1)<<2) | 261 ((key->data[i*8+2]&1)<<3) | 262 ((key->data[i*8+3]&1)<<4) | 263 ((key->data[i*8+4]&1)<<5) | 264 ((key->data[i*8+5]&1)<<6) | 265 ((key->data[i*8+6]&1)<<7)); 266 267 mit_des_fixup_key_parity(key->data + i*8); 268 } 269 ret = 0; 270 err_out: 271 return ret; 272 } 273 274 /** 275 * krb5_derive_key_v1 - Derive a subkey for an RFC 3961 enctype 276 * @gk5e: Kerberos 5 enctype profile 277 * @inkey: base protocol key 278 * @outkey: OUT: derived key 279 * @label: subkey usage label 280 * @gfp_mask: memory allocation control flags 281 * 282 * Caller sets @outkey->len to the desired length of the derived key. 283 * 284 * On success, returns 0 and fills in @outkey. A negative errno value 285 * is returned on failure. 286 */ 287 int krb5_derive_key_v1(const struct gss_krb5_enctype *gk5e, 288 const struct xdr_netobj *inkey, 289 struct xdr_netobj *outkey, 290 const struct xdr_netobj *label, 291 gfp_t gfp_mask) 292 { 293 struct xdr_netobj inblock; 294 int ret; 295 296 inblock.len = gk5e->keybytes; 297 inblock.data = kmalloc(inblock.len, gfp_mask); 298 if (!inblock.data) 299 return -ENOMEM; 300 301 ret = krb5_DK(gk5e, inkey, inblock.data, label, gfp_mask); 302 if (!ret) 303 ret = krb5_random_to_key_v1(gk5e, &inblock, outkey); 304 305 kfree_sensitive(inblock.data); 306 return ret; 307 } 308 309 /* 310 * This is the identity function, with some sanity checking. 311 */ 312 static int krb5_random_to_key_v2(const struct gss_krb5_enctype *gk5e, 313 struct xdr_netobj *randombits, 314 struct xdr_netobj *key) 315 { 316 int ret = -EINVAL; 317 318 if (key->len != 16 && key->len != 32) { 319 dprintk("%s: key->len is %d\n", __func__, key->len); 320 goto err_out; 321 } 322 if (randombits->len != 16 && randombits->len != 32) { 323 dprintk("%s: randombits->len is %d\n", 324 __func__, randombits->len); 325 goto err_out; 326 } 327 if (randombits->len != key->len) { 328 dprintk("%s: randombits->len is %d, key->len is %d\n", 329 __func__, randombits->len, key->len); 330 goto err_out; 331 } 332 memcpy(key->data, randombits->data, key->len); 333 ret = 0; 334 err_out: 335 return ret; 336 } 337 338 /** 339 * krb5_derive_key_v2 - Derive a subkey for an RFC 3962 enctype 340 * @gk5e: Kerberos 5 enctype profile 341 * @inkey: base protocol key 342 * @outkey: OUT: derived key 343 * @label: subkey usage label 344 * @gfp_mask: memory allocation control flags 345 * 346 * Caller sets @outkey->len to the desired length of the derived key. 347 * 348 * On success, returns 0 and fills in @outkey. A negative errno value 349 * is returned on failure. 350 */ 351 int krb5_derive_key_v2(const struct gss_krb5_enctype *gk5e, 352 const struct xdr_netobj *inkey, 353 struct xdr_netobj *outkey, 354 const struct xdr_netobj *label, 355 gfp_t gfp_mask) 356 { 357 struct xdr_netobj inblock; 358 int ret; 359 360 inblock.len = gk5e->keybytes; 361 inblock.data = kmalloc(inblock.len, gfp_mask); 362 if (!inblock.data) 363 return -ENOMEM; 364 365 ret = krb5_DK(gk5e, inkey, inblock.data, label, gfp_mask); 366 if (!ret) 367 ret = krb5_random_to_key_v2(gk5e, &inblock, outkey); 368 369 kfree_sensitive(inblock.data); 370 return ret; 371 } 372 373 /* 374 * K(i) = CMAC(key, K(i-1) | i | constant | 0x00 | k) 375 * 376 * i: A block counter is used with a length of 4 bytes, represented 377 * in big-endian order. 378 * 379 * constant: The label input to the KDF is the usage constant supplied 380 * to the key derivation function 381 * 382 * k: The length of the output key in bits, represented as a 4-byte 383 * string in big-endian order. 384 * 385 * Caller fills in K(i-1) in @step, and receives the result K(i) 386 * in the same buffer. 387 */ 388 static int 389 krb5_cmac_Ki(struct crypto_shash *tfm, const struct xdr_netobj *constant, 390 u32 outlen, u32 count, struct xdr_netobj *step) 391 { 392 __be32 k = cpu_to_be32(outlen * 8); 393 SHASH_DESC_ON_STACK(desc, tfm); 394 __be32 i = cpu_to_be32(count); 395 u8 zero = 0; 396 int ret; 397 398 desc->tfm = tfm; 399 ret = crypto_shash_init(desc); 400 if (ret) 401 goto out_err; 402 403 ret = crypto_shash_update(desc, step->data, step->len); 404 if (ret) 405 goto out_err; 406 ret = crypto_shash_update(desc, (u8 *)&i, sizeof(i)); 407 if (ret) 408 goto out_err; 409 ret = crypto_shash_update(desc, constant->data, constant->len); 410 if (ret) 411 goto out_err; 412 ret = crypto_shash_update(desc, &zero, sizeof(zero)); 413 if (ret) 414 goto out_err; 415 ret = crypto_shash_update(desc, (u8 *)&k, sizeof(k)); 416 if (ret) 417 goto out_err; 418 ret = crypto_shash_final(desc, step->data); 419 if (ret) 420 goto out_err; 421 422 out_err: 423 shash_desc_zero(desc); 424 return ret; 425 } 426 427 /** 428 * krb5_kdf_feedback_cmac - Derive a subkey for a Camellia/CMAC-based enctype 429 * @gk5e: Kerberos 5 enctype parameters 430 * @inkey: base protocol key 431 * @outkey: OUT: derived key 432 * @constant: subkey usage label 433 * @gfp_mask: memory allocation control flags 434 * 435 * RFC 6803 Section 3: 436 * 437 * "We use a key derivation function from the family specified in 438 * [SP800-108], Section 5.2, 'KDF in Feedback Mode'." 439 * 440 * n = ceiling(k / 128) 441 * K(0) = zeros 442 * K(i) = CMAC(key, K(i-1) | i | constant | 0x00 | k) 443 * DR(key, constant) = k-truncate(K(1) | K(2) | ... | K(n)) 444 * KDF-FEEDBACK-CMAC(key, constant) = random-to-key(DR(key, constant)) 445 * 446 * Caller sets @outkey->len to the desired length of the derived key (k). 447 * 448 * On success, returns 0 and fills in @outkey. A negative errno value 449 * is returned on failure. 450 */ 451 int 452 krb5_kdf_feedback_cmac(const struct gss_krb5_enctype *gk5e, 453 const struct xdr_netobj *inkey, 454 struct xdr_netobj *outkey, 455 const struct xdr_netobj *constant, 456 gfp_t gfp_mask) 457 { 458 struct xdr_netobj step = { .data = NULL }; 459 struct xdr_netobj DR = { .data = NULL }; 460 unsigned int blocksize, offset; 461 struct crypto_shash *tfm; 462 int n, count, ret; 463 464 /* 465 * This implementation assumes the CMAC used for an enctype's 466 * key derivation is the same as the CMAC used for its 467 * checksumming. This happens to be true for enctypes that 468 * are currently supported by this implementation. 469 */ 470 tfm = crypto_alloc_shash(gk5e->cksum_name, 0, 0); 471 if (IS_ERR(tfm)) { 472 ret = PTR_ERR(tfm); 473 goto out; 474 } 475 ret = crypto_shash_setkey(tfm, inkey->data, inkey->len); 476 if (ret) 477 goto out_free_tfm; 478 479 blocksize = crypto_shash_digestsize(tfm); 480 n = (outkey->len + blocksize - 1) / blocksize; 481 482 /* K(0) is all zeroes */ 483 ret = -ENOMEM; 484 step.len = blocksize; 485 step.data = kzalloc(step.len, gfp_mask); 486 if (!step.data) 487 goto out_free_tfm; 488 489 DR.len = blocksize * n; 490 DR.data = kmalloc(DR.len, gfp_mask); 491 if (!DR.data) 492 goto out_free_tfm; 493 494 /* XXX: Does not handle partial-block key sizes */ 495 for (offset = 0, count = 1; count <= n; count++) { 496 ret = krb5_cmac_Ki(tfm, constant, outkey->len, count, &step); 497 if (ret) 498 goto out_free_tfm; 499 500 memcpy(DR.data + offset, step.data, blocksize); 501 offset += blocksize; 502 } 503 504 /* k-truncate and random-to-key */ 505 memcpy(outkey->data, DR.data, outkey->len); 506 ret = 0; 507 508 out_free_tfm: 509 crypto_free_shash(tfm); 510 out: 511 kfree_sensitive(step.data); 512 kfree_sensitive(DR.data); 513 return ret; 514 } 515 516 /* 517 * K1 = HMAC-SHA(key, 0x00000001 | label | 0x00 | k) 518 * 519 * key: The source of entropy from which subsequent keys are derived. 520 * 521 * label: An octet string describing the intended usage of the 522 * derived key. 523 * 524 * k: Length in bits of the key to be outputted, expressed in 525 * big-endian binary representation in 4 bytes. 526 */ 527 static int 528 krb5_hmac_K1(struct crypto_shash *tfm, const struct xdr_netobj *label, 529 u32 outlen, struct xdr_netobj *K1) 530 { 531 __be32 k = cpu_to_be32(outlen * 8); 532 SHASH_DESC_ON_STACK(desc, tfm); 533 __be32 one = cpu_to_be32(1); 534 u8 zero = 0; 535 int ret; 536 537 desc->tfm = tfm; 538 ret = crypto_shash_init(desc); 539 if (ret) 540 goto out_err; 541 ret = crypto_shash_update(desc, (u8 *)&one, sizeof(one)); 542 if (ret) 543 goto out_err; 544 ret = crypto_shash_update(desc, label->data, label->len); 545 if (ret) 546 goto out_err; 547 ret = crypto_shash_update(desc, &zero, sizeof(zero)); 548 if (ret) 549 goto out_err; 550 ret = crypto_shash_update(desc, (u8 *)&k, sizeof(k)); 551 if (ret) 552 goto out_err; 553 ret = crypto_shash_final(desc, K1->data); 554 if (ret) 555 goto out_err; 556 557 out_err: 558 shash_desc_zero(desc); 559 return ret; 560 } 561 562 /** 563 * krb5_kdf_hmac_sha2 - Derive a subkey for an AES/SHA2-based enctype 564 * @gk5e: Kerberos 5 enctype policy parameters 565 * @inkey: base protocol key 566 * @outkey: OUT: derived key 567 * @label: subkey usage label 568 * @gfp_mask: memory allocation control flags 569 * 570 * RFC 8009 Section 3: 571 * 572 * "We use a key derivation function from Section 5.1 of [SP800-108], 573 * which uses the HMAC algorithm as the PRF." 574 * 575 * function KDF-HMAC-SHA2(key, label, [context,] k): 576 * k-truncate(K1) 577 * 578 * Caller sets @outkey->len to the desired length of the derived key. 579 * 580 * On success, returns 0 and fills in @outkey. A negative errno value 581 * is returned on failure. 582 */ 583 int 584 krb5_kdf_hmac_sha2(const struct gss_krb5_enctype *gk5e, 585 const struct xdr_netobj *inkey, 586 struct xdr_netobj *outkey, 587 const struct xdr_netobj *label, 588 gfp_t gfp_mask) 589 { 590 struct crypto_shash *tfm; 591 struct xdr_netobj K1 = { 592 .data = NULL, 593 }; 594 int ret; 595 596 /* 597 * This implementation assumes the HMAC used for an enctype's 598 * key derivation is the same as the HMAC used for its 599 * checksumming. This happens to be true for enctypes that 600 * are currently supported by this implementation. 601 */ 602 tfm = crypto_alloc_shash(gk5e->cksum_name, 0, 0); 603 if (IS_ERR(tfm)) { 604 ret = PTR_ERR(tfm); 605 goto out; 606 } 607 ret = crypto_shash_setkey(tfm, inkey->data, inkey->len); 608 if (ret) 609 goto out_free_tfm; 610 611 K1.len = crypto_shash_digestsize(tfm); 612 K1.data = kmalloc(K1.len, gfp_mask); 613 if (!K1.data) { 614 ret = -ENOMEM; 615 goto out_free_tfm; 616 } 617 618 ret = krb5_hmac_K1(tfm, label, outkey->len, &K1); 619 if (ret) 620 goto out_free_tfm; 621 622 /* k-truncate and random-to-key */ 623 memcpy(outkey->data, K1.data, outkey->len); 624 625 out_free_tfm: 626 kfree_sensitive(K1.data); 627 crypto_free_shash(tfm); 628 out: 629 return ret; 630 } 631