1 // SPDX-License-Identifier: BSD-3-Clause 2 /* rfc3961 Kerberos 5 simplified crypto profile. 3 * 4 * Parts borrowed from net/sunrpc/auth_gss/. 5 */ 6 /* 7 * COPYRIGHT (c) 2008 8 * The Regents of the University of Michigan 9 * ALL RIGHTS RESERVED 10 * 11 * Permission is granted to use, copy, create derivative works 12 * and redistribute this software and such derivative works 13 * for any purpose, so long as the name of The University of 14 * Michigan is not used in any advertising or publicity 15 * pertaining to the use of distribution of this software 16 * without specific, written prior authorization. If the 17 * above copyright notice or any other identification of the 18 * University of Michigan is included in any copy of any 19 * portion of this software, then the disclaimer below must 20 * also be included. 21 * 22 * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION 23 * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY 24 * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF 25 * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING 26 * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE 28 * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE 29 * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR 30 * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING 31 * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN 32 * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGES. 34 */ 35 36 /* 37 * Copyright (C) 1998 by the FundsXpress, INC. 38 * 39 * All rights reserved. 40 * 41 * Export of this software from the United States of America may require 42 * a specific license from the United States Government. It is the 43 * responsibility of any person or organization contemplating export to 44 * obtain such a license before exporting. 45 * 46 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 47 * distribute this software and its documentation for any purpose and 48 * without fee is hereby granted, provided that the above copyright 49 * notice appear in all copies and that both that copyright notice and 50 * this permission notice appear in supporting documentation, and that 51 * the name of FundsXpress. not be used in advertising or publicity pertaining 52 * to distribution of the software without specific, written prior 53 * permission. FundsXpress makes no representations about the suitability of 54 * this software for any purpose. It is provided "as is" without express 55 * or implied warranty. 56 * 57 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 58 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 59 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 60 */ 61 62 /* 63 * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. 64 * Written by David Howells (dhowells@redhat.com) 65 */ 66 67 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 68 69 #include <linux/random.h> 70 #include <linux/scatterlist.h> 71 #include <linux/skbuff.h> 72 #include <linux/slab.h> 73 #include <linux/lcm.h> 74 #include <linux/rtnetlink.h> 75 #include <crypto/authenc.h> 76 #include <crypto/skcipher.h> 77 #include <crypto/hash.h> 78 #include "internal.h" 79 80 /* Maximum blocksize for the supported crypto algorithms */ 81 #define KRB5_MAX_BLOCKSIZE (16) 82 83 int crypto_shash_update_sg(struct shash_desc *desc, struct scatterlist *sg, 84 size_t offset, size_t len) 85 { 86 struct sg_mapping_iter miter; 87 size_t i, n; 88 int ret = 0; 89 90 sg_miter_start(&miter, sg, sg_nents(sg), 91 SG_MITER_FROM_SG | SG_MITER_LOCAL); 92 sg_miter_skip(&miter, offset); 93 for (i = 0; i < len; i += n) { 94 sg_miter_next(&miter); 95 n = min(miter.length, len - i); 96 ret = crypto_shash_update(desc, miter.addr, n); 97 if (ret < 0) 98 break; 99 } 100 sg_miter_stop(&miter); 101 return ret; 102 } 103 104 static int rfc3961_do_encrypt(struct crypto_sync_skcipher *tfm, void *iv, 105 const struct krb5_buffer *in, struct krb5_buffer *out) 106 { 107 struct scatterlist sg[1]; 108 u8 local_iv[KRB5_MAX_BLOCKSIZE] __aligned(KRB5_MAX_BLOCKSIZE) = {0}; 109 SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 110 int ret; 111 112 if (WARN_ON(in->len != out->len)) 113 return -EINVAL; 114 if (out->len % crypto_sync_skcipher_blocksize(tfm) != 0) 115 return -EINVAL; 116 117 if (crypto_sync_skcipher_ivsize(tfm) > KRB5_MAX_BLOCKSIZE) 118 return -EINVAL; 119 120 if (iv) 121 memcpy(local_iv, iv, crypto_sync_skcipher_ivsize(tfm)); 122 123 memcpy(out->data, in->data, out->len); 124 sg_init_one(sg, out->data, out->len); 125 126 skcipher_request_set_sync_tfm(req, tfm); 127 skcipher_request_set_callback(req, 0, NULL, NULL); 128 skcipher_request_set_crypt(req, sg, sg, out->len, local_iv); 129 130 ret = crypto_skcipher_encrypt(req); 131 skcipher_request_zero(req); 132 return ret; 133 } 134 135 /* 136 * Calculate an unkeyed basic hash. 137 */ 138 static int rfc3961_calc_H(const struct krb5_enctype *krb5, 139 const struct krb5_buffer *data, 140 struct krb5_buffer *digest, 141 gfp_t gfp) 142 { 143 struct crypto_shash *tfm; 144 struct shash_desc *desc; 145 size_t desc_size; 146 int ret = -ENOMEM; 147 148 tfm = crypto_alloc_shash(krb5->hash_name, 0, 0); 149 if (IS_ERR(tfm)) 150 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 151 152 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 153 154 desc = kzalloc(desc_size, gfp); 155 if (!desc) 156 goto error_tfm; 157 158 digest->len = crypto_shash_digestsize(tfm); 159 digest->data = kzalloc(digest->len, gfp); 160 if (!digest->data) 161 goto error_desc; 162 163 desc->tfm = tfm; 164 ret = crypto_shash_init(desc); 165 if (ret < 0) 166 goto error_digest; 167 168 ret = crypto_shash_finup(desc, data->data, data->len, digest->data); 169 if (ret < 0) 170 goto error_digest; 171 172 goto error_desc; 173 174 error_digest: 175 kfree_sensitive(digest->data); 176 error_desc: 177 kfree_sensitive(desc); 178 error_tfm: 179 crypto_free_shash(tfm); 180 return ret; 181 } 182 183 /* 184 * This is the n-fold function as described in rfc3961, sec 5.1 185 * Taken from MIT Kerberos and modified. 186 */ 187 static void rfc3961_nfold(const struct krb5_buffer *source, struct krb5_buffer *result) 188 { 189 const u8 *in = source->data; 190 u8 *out = result->data; 191 unsigned long ulcm; 192 unsigned int inbits, outbits; 193 int byte, i, msbit; 194 195 /* the code below is more readable if I make these bytes instead of bits */ 196 inbits = source->len; 197 outbits = result->len; 198 199 /* first compute lcm(n,k) */ 200 ulcm = lcm(inbits, outbits); 201 202 /* now do the real work */ 203 memset(out, 0, outbits); 204 byte = 0; 205 206 /* this will end up cycling through k lcm(k,n)/k times, which 207 * is correct. 208 */ 209 for (i = ulcm-1; i >= 0; i--) { 210 /* compute the msbit in k which gets added into this byte */ 211 msbit = ( 212 /* first, start with the msbit in the first, 213 * unrotated byte 214 */ 215 ((inbits << 3) - 1) + 216 /* then, for each byte, shift to the right 217 * for each repetition 218 */ 219 (((inbits << 3) + 13) * (i/inbits)) + 220 /* last, pick out the correct byte within 221 * that shifted repetition 222 */ 223 ((inbits - (i % inbits)) << 3) 224 ) % (inbits << 3); 225 226 /* pull out the byte value itself */ 227 byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8) | 228 (in[((inbits) - (msbit >> 3)) % inbits])) 229 >> ((msbit & 7) + 1)) & 0xff; 230 231 /* do the addition */ 232 byte += out[i % outbits]; 233 out[i % outbits] = byte & 0xff; 234 235 /* keep around the carry bit, if any */ 236 byte >>= 8; 237 } 238 239 /* if there's a carry bit left over, add it back in */ 240 if (byte) { 241 for (i = outbits - 1; i >= 0; i--) { 242 /* do the addition */ 243 byte += out[i]; 244 out[i] = byte & 0xff; 245 246 /* keep around the carry bit, if any */ 247 byte >>= 8; 248 } 249 } 250 } 251 252 /* 253 * Calculate a derived key, DK(Base Key, Well-Known Constant) 254 * 255 * DK(Key, Constant) = random-to-key(DR(Key, Constant)) 256 * DR(Key, Constant) = k-truncate(E(Key, Constant, initial-cipher-state)) 257 * K1 = E(Key, n-fold(Constant), initial-cipher-state) 258 * K2 = E(Key, K1, initial-cipher-state) 259 * K3 = E(Key, K2, initial-cipher-state) 260 * K4 = ... 261 * DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...) 262 * [rfc3961 sec 5.1] 263 */ 264 static int rfc3961_calc_DK(const struct krb5_enctype *krb5, 265 const struct krb5_buffer *inkey, 266 const struct krb5_buffer *in_constant, 267 struct krb5_buffer *result, 268 gfp_t gfp) 269 { 270 unsigned int blocksize, keybytes, keylength, n; 271 struct krb5_buffer inblock, outblock, rawkey; 272 struct crypto_sync_skcipher *cipher; 273 int ret = -EINVAL; 274 275 blocksize = krb5->block_len; 276 keybytes = krb5->key_bytes; 277 keylength = krb5->key_len; 278 279 if (inkey->len != keylength || result->len != keylength) 280 return -EINVAL; 281 if (!krb5->random_to_key && result->len != keybytes) 282 return -EINVAL; 283 284 cipher = crypto_alloc_sync_skcipher(krb5->derivation_enc, 0, 0); 285 if (IS_ERR(cipher)) { 286 ret = (PTR_ERR(cipher) == -ENOENT) ? -ENOPKG : PTR_ERR(cipher); 287 goto err_return; 288 } 289 ret = crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len); 290 if (ret < 0) 291 goto err_free_cipher; 292 293 ret = -ENOMEM; 294 inblock.data = kzalloc(blocksize * 2 + keybytes, gfp); 295 if (!inblock.data) 296 goto err_free_cipher; 297 298 inblock.len = blocksize; 299 outblock.data = inblock.data + blocksize; 300 outblock.len = blocksize; 301 rawkey.data = outblock.data + blocksize; 302 rawkey.len = keybytes; 303 304 /* initialize the input block */ 305 306 if (in_constant->len == inblock.len) 307 memcpy(inblock.data, in_constant->data, inblock.len); 308 else 309 rfc3961_nfold(in_constant, &inblock); 310 311 /* loop encrypting the blocks until enough key bytes are generated */ 312 n = 0; 313 while (n < rawkey.len) { 314 rfc3961_do_encrypt(cipher, NULL, &inblock, &outblock); 315 316 if (keybytes - n <= outblock.len) { 317 memcpy(rawkey.data + n, outblock.data, keybytes - n); 318 break; 319 } 320 321 memcpy(rawkey.data + n, outblock.data, outblock.len); 322 memcpy(inblock.data, outblock.data, outblock.len); 323 n += outblock.len; 324 } 325 326 /* postprocess the key */ 327 if (!krb5->random_to_key) { 328 /* Identity random-to-key function. */ 329 memcpy(result->data, rawkey.data, rawkey.len); 330 ret = 0; 331 } else { 332 ret = krb5->random_to_key(krb5, &rawkey, result); 333 } 334 335 kfree_sensitive(inblock.data); 336 err_free_cipher: 337 crypto_free_sync_skcipher(cipher); 338 err_return: 339 return ret; 340 } 341 342 /* 343 * Calculate single encryption, E() 344 * 345 * E(Key, octets) 346 */ 347 static int rfc3961_calc_E(const struct krb5_enctype *krb5, 348 const struct krb5_buffer *key, 349 const struct krb5_buffer *in_data, 350 struct krb5_buffer *result, 351 gfp_t gfp) 352 { 353 struct crypto_sync_skcipher *cipher; 354 int ret; 355 356 cipher = crypto_alloc_sync_skcipher(krb5->derivation_enc, 0, 0); 357 if (IS_ERR(cipher)) { 358 ret = (PTR_ERR(cipher) == -ENOENT) ? -ENOPKG : PTR_ERR(cipher); 359 goto err; 360 } 361 362 ret = crypto_sync_skcipher_setkey(cipher, key->data, key->len); 363 if (ret < 0) 364 goto err_free; 365 366 ret = rfc3961_do_encrypt(cipher, NULL, in_data, result); 367 368 err_free: 369 crypto_free_sync_skcipher(cipher); 370 err: 371 return ret; 372 } 373 374 /* 375 * Calculate the pseudo-random function, PRF(). 376 * 377 * tmp1 = H(octet-string) 378 * tmp2 = truncate tmp1 to multiple of m 379 * PRF = E(DK(protocol-key, prfconstant), tmp2, initial-cipher-state) 380 * 381 * The "prfconstant" used in the PRF operation is the three-octet string 382 * "prf". 383 * [rfc3961 sec 5.3] 384 */ 385 static int rfc3961_calc_PRF(const struct krb5_enctype *krb5, 386 const struct krb5_buffer *protocol_key, 387 const struct krb5_buffer *octet_string, 388 struct krb5_buffer *result, 389 gfp_t gfp) 390 { 391 static const struct krb5_buffer prfconstant = { 3, "prf" }; 392 struct krb5_buffer derived_key; 393 struct krb5_buffer tmp1, tmp2; 394 unsigned int m = krb5->block_len; 395 void *buffer; 396 int ret; 397 398 if (result->len != krb5->prf_len) 399 return -EINVAL; 400 401 tmp1.len = krb5->hash_len; 402 derived_key.len = krb5->key_bytes; 403 buffer = kzalloc(round16(tmp1.len) + round16(derived_key.len), gfp); 404 if (!buffer) 405 return -ENOMEM; 406 407 tmp1.data = buffer; 408 derived_key.data = buffer + round16(tmp1.len); 409 410 ret = rfc3961_calc_H(krb5, octet_string, &tmp1, gfp); 411 if (ret < 0) 412 goto err; 413 414 tmp2.len = tmp1.len & ~(m - 1); 415 tmp2.data = tmp1.data; 416 417 ret = rfc3961_calc_DK(krb5, protocol_key, &prfconstant, &derived_key, gfp); 418 if (ret < 0) 419 goto err; 420 421 ret = rfc3961_calc_E(krb5, &derived_key, &tmp2, result, gfp); 422 423 err: 424 kfree_sensitive(buffer); 425 return ret; 426 } 427 428 /* 429 * Derive the Ke and Ki keys and package them into a key parameter that can be 430 * given to the setkey of a authenc AEAD crypto object. 431 */ 432 int authenc_derive_encrypt_keys(const struct krb5_enctype *krb5, 433 const struct krb5_buffer *TK, 434 unsigned int usage, 435 struct krb5_buffer *setkey, 436 gfp_t gfp) 437 { 438 struct crypto_authenc_key_param *param; 439 struct krb5_buffer Ke, Ki; 440 struct rtattr *rta; 441 int ret; 442 443 Ke.len = krb5->Ke_len; 444 Ki.len = krb5->Ki_len; 445 setkey->len = RTA_LENGTH(sizeof(*param)) + Ke.len + Ki.len; 446 setkey->data = kzalloc(setkey->len, GFP_KERNEL); 447 if (!setkey->data) 448 return -ENOMEM; 449 450 rta = setkey->data; 451 rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; 452 rta->rta_len = RTA_LENGTH(sizeof(*param)); 453 param = RTA_DATA(rta); 454 param->enckeylen = htonl(Ke.len); 455 456 Ki.data = (void *)(param + 1); 457 Ke.data = Ki.data + Ki.len; 458 459 ret = krb5_derive_Ke(krb5, TK, usage, &Ke, gfp); 460 if (ret < 0) { 461 pr_err("get_Ke failed %d\n", ret); 462 return ret; 463 } 464 ret = krb5_derive_Ki(krb5, TK, usage, &Ki, gfp); 465 if (ret < 0) 466 pr_err("get_Ki failed %d\n", ret); 467 return ret; 468 } 469 470 /* 471 * Package predefined Ke and Ki keys and into a key parameter that can be given 472 * to the setkey of an authenc AEAD crypto object. 473 */ 474 int authenc_load_encrypt_keys(const struct krb5_enctype *krb5, 475 const struct krb5_buffer *Ke, 476 const struct krb5_buffer *Ki, 477 struct krb5_buffer *setkey, 478 gfp_t gfp) 479 { 480 struct crypto_authenc_key_param *param; 481 struct rtattr *rta; 482 483 setkey->len = RTA_LENGTH(sizeof(*param)) + Ke->len + Ki->len; 484 setkey->data = kzalloc(setkey->len, GFP_KERNEL); 485 if (!setkey->data) 486 return -ENOMEM; 487 488 rta = setkey->data; 489 rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; 490 rta->rta_len = RTA_LENGTH(sizeof(*param)); 491 param = RTA_DATA(rta); 492 param->enckeylen = htonl(Ke->len); 493 memcpy((void *)(param + 1), Ki->data, Ki->len); 494 memcpy((void *)(param + 1) + Ki->len, Ke->data, Ke->len); 495 return 0; 496 } 497 498 /* 499 * Derive the Kc key for checksum-only mode and package it into a key parameter 500 * that can be given to the setkey of a hash crypto object. 501 */ 502 int rfc3961_derive_checksum_key(const struct krb5_enctype *krb5, 503 const struct krb5_buffer *TK, 504 unsigned int usage, 505 struct krb5_buffer *setkey, 506 gfp_t gfp) 507 { 508 int ret; 509 510 setkey->len = krb5->Kc_len; 511 setkey->data = kzalloc(setkey->len, GFP_KERNEL); 512 if (!setkey->data) 513 return -ENOMEM; 514 515 ret = krb5_derive_Kc(krb5, TK, usage, setkey, gfp); 516 if (ret < 0) 517 pr_err("get_Kc failed %d\n", ret); 518 return ret; 519 } 520 521 /* 522 * Package a predefined Kc key for checksum-only mode into a key parameter that 523 * can be given to the setkey of a hash crypto object. 524 */ 525 int rfc3961_load_checksum_key(const struct krb5_enctype *krb5, 526 const struct krb5_buffer *Kc, 527 struct krb5_buffer *setkey, 528 gfp_t gfp) 529 { 530 setkey->len = krb5->Kc_len; 531 setkey->data = kmemdup(Kc->data, Kc->len, GFP_KERNEL); 532 if (!setkey->data) 533 return -ENOMEM; 534 return 0; 535 } 536 537 /* 538 * Apply encryption and checksumming functions to part of a scatterlist. 539 */ 540 ssize_t krb5_aead_encrypt(const struct krb5_enctype *krb5, 541 struct crypto_aead *aead, 542 struct scatterlist *sg, unsigned int nr_sg, size_t sg_len, 543 size_t data_offset, size_t data_len, 544 bool preconfounded) 545 { 546 struct aead_request *req; 547 ssize_t ret, done; 548 size_t bsize, base_len, secure_offset, secure_len, pad_len, cksum_offset; 549 void *buffer; 550 u8 *iv; 551 552 if (WARN_ON(data_offset != krb5->conf_len)) 553 return -EINVAL; /* Data is in wrong place */ 554 555 secure_offset = 0; 556 base_len = krb5->conf_len + data_len; 557 pad_len = 0; 558 secure_len = base_len + pad_len; 559 cksum_offset = secure_len; 560 if (WARN_ON(cksum_offset + krb5->cksum_len > sg_len)) 561 return -EFAULT; 562 563 bsize = krb5_aead_size(aead) + 564 krb5_aead_ivsize(aead); 565 buffer = kzalloc(bsize, GFP_NOFS); 566 if (!buffer) 567 return -ENOMEM; 568 569 /* Insert the confounder into the buffer */ 570 ret = -EFAULT; 571 if (!preconfounded) { 572 get_random_bytes(buffer, krb5->conf_len); 573 done = sg_pcopy_from_buffer(sg, nr_sg, buffer, krb5->conf_len, 574 secure_offset); 575 if (done != krb5->conf_len) 576 goto error; 577 } 578 579 /* We may need to pad out to the crypto blocksize. */ 580 if (pad_len) { 581 done = sg_zero_buffer(sg, nr_sg, pad_len, data_offset + data_len); 582 if (done != pad_len) 583 goto error; 584 } 585 586 /* Hash and encrypt the message. */ 587 req = buffer; 588 iv = buffer + krb5_aead_size(aead); 589 590 aead_request_set_tfm(req, aead); 591 aead_request_set_callback(req, 0, NULL, NULL); 592 aead_request_set_crypt(req, sg, sg, secure_len, iv); 593 ret = crypto_aead_encrypt(req); 594 if (ret < 0) 595 goto error; 596 597 ret = secure_len + krb5->cksum_len; 598 599 error: 600 kfree_sensitive(buffer); 601 return ret; 602 } 603 604 /* 605 * Apply decryption and checksumming functions to a message. The offset and 606 * length are updated to reflect the actual content of the encrypted region. 607 */ 608 int krb5_aead_decrypt(const struct krb5_enctype *krb5, 609 struct crypto_aead *aead, 610 struct scatterlist *sg, unsigned int nr_sg, 611 size_t *_offset, size_t *_len) 612 { 613 struct aead_request *req; 614 size_t bsize; 615 void *buffer; 616 int ret; 617 u8 *iv; 618 619 if (WARN_ON(*_offset != 0)) 620 return -EINVAL; /* Can't set offset on aead */ 621 622 if (*_len < krb5->conf_len + krb5->cksum_len) 623 return -EPROTO; 624 625 bsize = krb5_aead_size(aead) + 626 krb5_aead_ivsize(aead); 627 buffer = kzalloc(bsize, GFP_NOFS); 628 if (!buffer) 629 return -ENOMEM; 630 631 /* Decrypt the message and verify its checksum. */ 632 req = buffer; 633 iv = buffer + krb5_aead_size(aead); 634 635 aead_request_set_tfm(req, aead); 636 aead_request_set_callback(req, 0, NULL, NULL); 637 aead_request_set_crypt(req, sg, sg, *_len, iv); 638 ret = crypto_aead_decrypt(req); 639 if (ret < 0) 640 goto error; 641 642 /* Adjust the boundaries of the data. */ 643 *_offset += krb5->conf_len; 644 *_len -= krb5->conf_len + krb5->cksum_len; 645 ret = 0; 646 647 error: 648 kfree_sensitive(buffer); 649 return ret; 650 } 651 652 /* 653 * Generate a checksum over some metadata and part of an skbuff and insert the 654 * MIC into the skbuff immediately prior to the data. 655 */ 656 ssize_t rfc3961_get_mic(const struct krb5_enctype *krb5, 657 struct crypto_shash *shash, 658 const struct krb5_buffer *metadata, 659 struct scatterlist *sg, unsigned int nr_sg, size_t sg_len, 660 size_t data_offset, size_t data_len) 661 { 662 struct shash_desc *desc; 663 ssize_t ret, done; 664 size_t bsize; 665 void *buffer, *digest; 666 667 if (WARN_ON(data_offset != krb5->cksum_len)) 668 return -EMSGSIZE; 669 670 bsize = krb5_shash_size(shash) + 671 krb5_digest_size(shash); 672 buffer = kzalloc(bsize, GFP_NOFS); 673 if (!buffer) 674 return -ENOMEM; 675 676 /* Calculate the MIC with key Kc and store it into the skb */ 677 desc = buffer; 678 desc->tfm = shash; 679 ret = crypto_shash_init(desc); 680 if (ret < 0) 681 goto error; 682 683 if (metadata) { 684 ret = crypto_shash_update(desc, metadata->data, metadata->len); 685 if (ret < 0) 686 goto error; 687 } 688 689 ret = crypto_shash_update_sg(desc, sg, data_offset, data_len); 690 if (ret < 0) 691 goto error; 692 693 digest = buffer + krb5_shash_size(shash); 694 ret = crypto_shash_final(desc, digest); 695 if (ret < 0) 696 goto error; 697 698 ret = -EFAULT; 699 done = sg_pcopy_from_buffer(sg, nr_sg, digest, krb5->cksum_len, 700 data_offset - krb5->cksum_len); 701 if (done != krb5->cksum_len) 702 goto error; 703 704 ret = krb5->cksum_len + data_len; 705 706 error: 707 kfree_sensitive(buffer); 708 return ret; 709 } 710 711 /* 712 * Check the MIC on a region of an skbuff. The offset and length are updated 713 * to reflect the actual content of the secure region. 714 */ 715 int rfc3961_verify_mic(const struct krb5_enctype *krb5, 716 struct crypto_shash *shash, 717 const struct krb5_buffer *metadata, 718 struct scatterlist *sg, unsigned int nr_sg, 719 size_t *_offset, size_t *_len) 720 { 721 struct shash_desc *desc; 722 ssize_t done; 723 size_t bsize, data_offset, data_len, offset = *_offset, len = *_len; 724 void *buffer = NULL; 725 int ret; 726 u8 *cksum, *cksum2; 727 728 if (len < krb5->cksum_len) 729 return -EPROTO; 730 data_offset = offset + krb5->cksum_len; 731 data_len = len - krb5->cksum_len; 732 733 bsize = krb5_shash_size(shash) + 734 krb5_digest_size(shash) * 2; 735 buffer = kzalloc(bsize, GFP_NOFS); 736 if (!buffer) 737 return -ENOMEM; 738 739 cksum = buffer + 740 krb5_shash_size(shash); 741 cksum2 = buffer + 742 krb5_shash_size(shash) + 743 krb5_digest_size(shash); 744 745 /* Calculate the MIC */ 746 desc = buffer; 747 desc->tfm = shash; 748 ret = crypto_shash_init(desc); 749 if (ret < 0) 750 goto error; 751 752 if (metadata) { 753 ret = crypto_shash_update(desc, metadata->data, metadata->len); 754 if (ret < 0) 755 goto error; 756 } 757 758 crypto_shash_update_sg(desc, sg, data_offset, data_len); 759 crypto_shash_final(desc, cksum); 760 761 ret = -EFAULT; 762 done = sg_pcopy_to_buffer(sg, nr_sg, cksum2, krb5->cksum_len, offset); 763 if (done != krb5->cksum_len) 764 goto error; 765 766 if (memcmp(cksum, cksum2, krb5->cksum_len) != 0) { 767 ret = -EBADMSG; 768 goto error; 769 } 770 771 *_offset += krb5->cksum_len; 772 *_len -= krb5->cksum_len; 773 ret = 0; 774 775 error: 776 kfree_sensitive(buffer); 777 return ret; 778 } 779 780 const struct krb5_crypto_profile rfc3961_simplified_profile = { 781 .calc_PRF = rfc3961_calc_PRF, 782 .calc_Kc = rfc3961_calc_DK, 783 .calc_Ke = rfc3961_calc_DK, 784 .calc_Ki = rfc3961_calc_DK, 785 .derive_encrypt_keys = authenc_derive_encrypt_keys, 786 .load_encrypt_keys = authenc_load_encrypt_keys, 787 .derive_checksum_key = rfc3961_derive_checksum_key, 788 .load_checksum_key = rfc3961_load_checksum_key, 789 .encrypt = krb5_aead_encrypt, 790 .decrypt = krb5_aead_decrypt, 791 .get_mic = rfc3961_get_mic, 792 .verify_mic = rfc3961_verify_mic, 793 }; 794