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/skbuff.h> 71 #include <linux/slab.h> 72 #include <linux/highmem.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 do { 87 int ret; 88 89 if (offset < sg->length) { 90 struct page *page = sg_page(sg); 91 void *p = kmap_local_page(page); 92 void *q = p + sg->offset + offset; 93 size_t seg = min_t(size_t, len, sg->length - offset); 94 95 ret = crypto_shash_update(desc, q, seg); 96 kunmap_local(p); 97 if (ret < 0) 98 return ret; 99 len -= seg; 100 offset = 0; 101 } else { 102 offset -= sg->length; 103 } 104 } while (len > 0 && (sg = sg_next(sg))); 105 return 0; 106 } 107 108 static int rfc3961_do_encrypt(struct crypto_sync_skcipher *tfm, void *iv, 109 const struct krb5_buffer *in, struct krb5_buffer *out) 110 { 111 struct scatterlist sg[1]; 112 u8 local_iv[KRB5_MAX_BLOCKSIZE] __aligned(KRB5_MAX_BLOCKSIZE) = {0}; 113 SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); 114 int ret; 115 116 if (WARN_ON(in->len != out->len)) 117 return -EINVAL; 118 if (out->len % crypto_sync_skcipher_blocksize(tfm) != 0) 119 return -EINVAL; 120 121 if (crypto_sync_skcipher_ivsize(tfm) > KRB5_MAX_BLOCKSIZE) 122 return -EINVAL; 123 124 if (iv) 125 memcpy(local_iv, iv, crypto_sync_skcipher_ivsize(tfm)); 126 127 memcpy(out->data, in->data, out->len); 128 sg_init_one(sg, out->data, out->len); 129 130 skcipher_request_set_sync_tfm(req, tfm); 131 skcipher_request_set_callback(req, 0, NULL, NULL); 132 skcipher_request_set_crypt(req, sg, sg, out->len, local_iv); 133 134 ret = crypto_skcipher_encrypt(req); 135 skcipher_request_zero(req); 136 return ret; 137 } 138 139 /* 140 * Calculate an unkeyed basic hash. 141 */ 142 static int rfc3961_calc_H(const struct krb5_enctype *krb5, 143 const struct krb5_buffer *data, 144 struct krb5_buffer *digest, 145 gfp_t gfp) 146 { 147 struct crypto_shash *tfm; 148 struct shash_desc *desc; 149 size_t desc_size; 150 int ret = -ENOMEM; 151 152 tfm = crypto_alloc_shash(krb5->hash_name, 0, 0); 153 if (IS_ERR(tfm)) 154 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 155 156 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 157 158 desc = kzalloc(desc_size, gfp); 159 if (!desc) 160 goto error_tfm; 161 162 digest->len = crypto_shash_digestsize(tfm); 163 digest->data = kzalloc(digest->len, gfp); 164 if (!digest->data) 165 goto error_desc; 166 167 desc->tfm = tfm; 168 ret = crypto_shash_init(desc); 169 if (ret < 0) 170 goto error_digest; 171 172 ret = crypto_shash_finup(desc, data->data, data->len, digest->data); 173 if (ret < 0) 174 goto error_digest; 175 176 goto error_desc; 177 178 error_digest: 179 kfree_sensitive(digest->data); 180 error_desc: 181 kfree_sensitive(desc); 182 error_tfm: 183 crypto_free_shash(tfm); 184 return ret; 185 } 186 187 /* 188 * This is the n-fold function as described in rfc3961, sec 5.1 189 * Taken from MIT Kerberos and modified. 190 */ 191 static void rfc3961_nfold(const struct krb5_buffer *source, struct krb5_buffer *result) 192 { 193 const u8 *in = source->data; 194 u8 *out = result->data; 195 unsigned long ulcm; 196 unsigned int inbits, outbits; 197 int byte, i, msbit; 198 199 /* the code below is more readable if I make these bytes instead of bits */ 200 inbits = source->len; 201 outbits = result->len; 202 203 /* first compute lcm(n,k) */ 204 ulcm = lcm(inbits, outbits); 205 206 /* now do the real work */ 207 memset(out, 0, outbits); 208 byte = 0; 209 210 /* this will end up cycling through k lcm(k,n)/k times, which 211 * is correct. 212 */ 213 for (i = ulcm-1; i >= 0; i--) { 214 /* compute the msbit in k which gets added into this byte */ 215 msbit = ( 216 /* first, start with the msbit in the first, 217 * unrotated byte 218 */ 219 ((inbits << 3) - 1) + 220 /* then, for each byte, shift to the right 221 * for each repetition 222 */ 223 (((inbits << 3) + 13) * (i/inbits)) + 224 /* last, pick out the correct byte within 225 * that shifted repetition 226 */ 227 ((inbits - (i % inbits)) << 3) 228 ) % (inbits << 3); 229 230 /* pull out the byte value itself */ 231 byte += (((in[((inbits - 1) - (msbit >> 3)) % inbits] << 8) | 232 (in[((inbits) - (msbit >> 3)) % inbits])) 233 >> ((msbit & 7) + 1)) & 0xff; 234 235 /* do the addition */ 236 byte += out[i % outbits]; 237 out[i % outbits] = byte & 0xff; 238 239 /* keep around the carry bit, if any */ 240 byte >>= 8; 241 } 242 243 /* if there's a carry bit left over, add it back in */ 244 if (byte) { 245 for (i = outbits - 1; i >= 0; i--) { 246 /* do the addition */ 247 byte += out[i]; 248 out[i] = byte & 0xff; 249 250 /* keep around the carry bit, if any */ 251 byte >>= 8; 252 } 253 } 254 } 255 256 /* 257 * Calculate a derived key, DK(Base Key, Well-Known Constant) 258 * 259 * DK(Key, Constant) = random-to-key(DR(Key, Constant)) 260 * DR(Key, Constant) = k-truncate(E(Key, Constant, initial-cipher-state)) 261 * K1 = E(Key, n-fold(Constant), initial-cipher-state) 262 * K2 = E(Key, K1, initial-cipher-state) 263 * K3 = E(Key, K2, initial-cipher-state) 264 * K4 = ... 265 * DR(Key, Constant) = k-truncate(K1 | K2 | K3 | K4 ...) 266 * [rfc3961 sec 5.1] 267 */ 268 static int rfc3961_calc_DK(const struct krb5_enctype *krb5, 269 const struct krb5_buffer *inkey, 270 const struct krb5_buffer *in_constant, 271 struct krb5_buffer *result, 272 gfp_t gfp) 273 { 274 unsigned int blocksize, keybytes, keylength, n; 275 struct krb5_buffer inblock, outblock, rawkey; 276 struct crypto_sync_skcipher *cipher; 277 int ret = -EINVAL; 278 279 blocksize = krb5->block_len; 280 keybytes = krb5->key_bytes; 281 keylength = krb5->key_len; 282 283 if (inkey->len != keylength || result->len != keylength) 284 return -EINVAL; 285 if (!krb5->random_to_key && result->len != keybytes) 286 return -EINVAL; 287 288 cipher = crypto_alloc_sync_skcipher(krb5->derivation_enc, 0, 0); 289 if (IS_ERR(cipher)) { 290 ret = (PTR_ERR(cipher) == -ENOENT) ? -ENOPKG : PTR_ERR(cipher); 291 goto err_return; 292 } 293 ret = crypto_sync_skcipher_setkey(cipher, inkey->data, inkey->len); 294 if (ret < 0) 295 goto err_free_cipher; 296 297 ret = -ENOMEM; 298 inblock.data = kzalloc(blocksize * 2 + keybytes, gfp); 299 if (!inblock.data) 300 goto err_free_cipher; 301 302 inblock.len = blocksize; 303 outblock.data = inblock.data + blocksize; 304 outblock.len = blocksize; 305 rawkey.data = outblock.data + blocksize; 306 rawkey.len = keybytes; 307 308 /* initialize the input block */ 309 310 if (in_constant->len == inblock.len) 311 memcpy(inblock.data, in_constant->data, inblock.len); 312 else 313 rfc3961_nfold(in_constant, &inblock); 314 315 /* loop encrypting the blocks until enough key bytes are generated */ 316 n = 0; 317 while (n < rawkey.len) { 318 rfc3961_do_encrypt(cipher, NULL, &inblock, &outblock); 319 320 if (keybytes - n <= outblock.len) { 321 memcpy(rawkey.data + n, outblock.data, keybytes - n); 322 break; 323 } 324 325 memcpy(rawkey.data + n, outblock.data, outblock.len); 326 memcpy(inblock.data, outblock.data, outblock.len); 327 n += outblock.len; 328 } 329 330 /* postprocess the key */ 331 if (!krb5->random_to_key) { 332 /* Identity random-to-key function. */ 333 memcpy(result->data, rawkey.data, rawkey.len); 334 ret = 0; 335 } else { 336 ret = krb5->random_to_key(krb5, &rawkey, result); 337 } 338 339 kfree_sensitive(inblock.data); 340 err_free_cipher: 341 crypto_free_sync_skcipher(cipher); 342 err_return: 343 return ret; 344 } 345 346 /* 347 * Calculate single encryption, E() 348 * 349 * E(Key, octets) 350 */ 351 static int rfc3961_calc_E(const struct krb5_enctype *krb5, 352 const struct krb5_buffer *key, 353 const struct krb5_buffer *in_data, 354 struct krb5_buffer *result, 355 gfp_t gfp) 356 { 357 struct crypto_sync_skcipher *cipher; 358 int ret; 359 360 cipher = crypto_alloc_sync_skcipher(krb5->derivation_enc, 0, 0); 361 if (IS_ERR(cipher)) { 362 ret = (PTR_ERR(cipher) == -ENOENT) ? -ENOPKG : PTR_ERR(cipher); 363 goto err; 364 } 365 366 ret = crypto_sync_skcipher_setkey(cipher, key->data, key->len); 367 if (ret < 0) 368 goto err_free; 369 370 ret = rfc3961_do_encrypt(cipher, NULL, in_data, result); 371 372 err_free: 373 crypto_free_sync_skcipher(cipher); 374 err: 375 return ret; 376 } 377 378 /* 379 * Calculate the pseudo-random function, PRF(). 380 * 381 * tmp1 = H(octet-string) 382 * tmp2 = truncate tmp1 to multiple of m 383 * PRF = E(DK(protocol-key, prfconstant), tmp2, initial-cipher-state) 384 * 385 * The "prfconstant" used in the PRF operation is the three-octet string 386 * "prf". 387 * [rfc3961 sec 5.3] 388 */ 389 static int rfc3961_calc_PRF(const struct krb5_enctype *krb5, 390 const struct krb5_buffer *protocol_key, 391 const struct krb5_buffer *octet_string, 392 struct krb5_buffer *result, 393 gfp_t gfp) 394 { 395 static const struct krb5_buffer prfconstant = { 3, "prf" }; 396 struct krb5_buffer derived_key; 397 struct krb5_buffer tmp1, tmp2; 398 unsigned int m = krb5->block_len; 399 void *buffer; 400 int ret; 401 402 if (result->len != krb5->prf_len) 403 return -EINVAL; 404 405 tmp1.len = krb5->hash_len; 406 derived_key.len = krb5->key_bytes; 407 buffer = kzalloc(round16(tmp1.len) + round16(derived_key.len), gfp); 408 if (!buffer) 409 return -ENOMEM; 410 411 tmp1.data = buffer; 412 derived_key.data = buffer + round16(tmp1.len); 413 414 ret = rfc3961_calc_H(krb5, octet_string, &tmp1, gfp); 415 if (ret < 0) 416 goto err; 417 418 tmp2.len = tmp1.len & ~(m - 1); 419 tmp2.data = tmp1.data; 420 421 ret = rfc3961_calc_DK(krb5, protocol_key, &prfconstant, &derived_key, gfp); 422 if (ret < 0) 423 goto err; 424 425 ret = rfc3961_calc_E(krb5, &derived_key, &tmp2, result, gfp); 426 427 err: 428 kfree_sensitive(buffer); 429 return ret; 430 } 431 432 /* 433 * Derive the Ke and Ki keys and package them into a key parameter that can be 434 * given to the setkey of a authenc AEAD crypto object. 435 */ 436 int authenc_derive_encrypt_keys(const struct krb5_enctype *krb5, 437 const struct krb5_buffer *TK, 438 unsigned int usage, 439 struct krb5_buffer *setkey, 440 gfp_t gfp) 441 { 442 struct crypto_authenc_key_param *param; 443 struct krb5_buffer Ke, Ki; 444 struct rtattr *rta; 445 int ret; 446 447 Ke.len = krb5->Ke_len; 448 Ki.len = krb5->Ki_len; 449 setkey->len = RTA_LENGTH(sizeof(*param)) + Ke.len + Ki.len; 450 setkey->data = kzalloc(setkey->len, GFP_KERNEL); 451 if (!setkey->data) 452 return -ENOMEM; 453 454 rta = setkey->data; 455 rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; 456 rta->rta_len = RTA_LENGTH(sizeof(*param)); 457 param = RTA_DATA(rta); 458 param->enckeylen = htonl(Ke.len); 459 460 Ki.data = (void *)(param + 1); 461 Ke.data = Ki.data + Ki.len; 462 463 ret = krb5_derive_Ke(krb5, TK, usage, &Ke, gfp); 464 if (ret < 0) { 465 pr_err("get_Ke failed %d\n", ret); 466 return ret; 467 } 468 ret = krb5_derive_Ki(krb5, TK, usage, &Ki, gfp); 469 if (ret < 0) 470 pr_err("get_Ki failed %d\n", ret); 471 return ret; 472 } 473 474 /* 475 * Package predefined Ke and Ki keys and into a key parameter that can be given 476 * to the setkey of an authenc AEAD crypto object. 477 */ 478 int authenc_load_encrypt_keys(const struct krb5_enctype *krb5, 479 const struct krb5_buffer *Ke, 480 const struct krb5_buffer *Ki, 481 struct krb5_buffer *setkey, 482 gfp_t gfp) 483 { 484 struct crypto_authenc_key_param *param; 485 struct rtattr *rta; 486 487 setkey->len = RTA_LENGTH(sizeof(*param)) + Ke->len + Ki->len; 488 setkey->data = kzalloc(setkey->len, GFP_KERNEL); 489 if (!setkey->data) 490 return -ENOMEM; 491 492 rta = setkey->data; 493 rta->rta_type = CRYPTO_AUTHENC_KEYA_PARAM; 494 rta->rta_len = RTA_LENGTH(sizeof(*param)); 495 param = RTA_DATA(rta); 496 param->enckeylen = htonl(Ke->len); 497 memcpy((void *)(param + 1), Ki->data, Ki->len); 498 memcpy((void *)(param + 1) + Ki->len, Ke->data, Ke->len); 499 return 0; 500 } 501 502 /* 503 * Derive the Kc key for checksum-only mode and package it into a key parameter 504 * that can be given to the setkey of a hash crypto object. 505 */ 506 int rfc3961_derive_checksum_key(const struct krb5_enctype *krb5, 507 const struct krb5_buffer *TK, 508 unsigned int usage, 509 struct krb5_buffer *setkey, 510 gfp_t gfp) 511 { 512 int ret; 513 514 setkey->len = krb5->Kc_len; 515 setkey->data = kzalloc(setkey->len, GFP_KERNEL); 516 if (!setkey->data) 517 return -ENOMEM; 518 519 ret = krb5_derive_Kc(krb5, TK, usage, setkey, gfp); 520 if (ret < 0) 521 pr_err("get_Kc failed %d\n", ret); 522 return ret; 523 } 524 525 /* 526 * Package a predefined Kc key for checksum-only mode into a key parameter that 527 * can be given to the setkey of a hash crypto object. 528 */ 529 int rfc3961_load_checksum_key(const struct krb5_enctype *krb5, 530 const struct krb5_buffer *Kc, 531 struct krb5_buffer *setkey, 532 gfp_t gfp) 533 { 534 setkey->len = krb5->Kc_len; 535 setkey->data = kmemdup(Kc->data, Kc->len, GFP_KERNEL); 536 if (!setkey->data) 537 return -ENOMEM; 538 return 0; 539 } 540 541 /* 542 * Apply encryption and checksumming functions to part of a scatterlist. 543 */ 544 ssize_t krb5_aead_encrypt(const struct krb5_enctype *krb5, 545 struct crypto_aead *aead, 546 struct scatterlist *sg, unsigned int nr_sg, size_t sg_len, 547 size_t data_offset, size_t data_len, 548 bool preconfounded) 549 { 550 struct aead_request *req; 551 ssize_t ret, done; 552 size_t bsize, base_len, secure_offset, secure_len, pad_len, cksum_offset; 553 void *buffer; 554 u8 *iv; 555 556 if (WARN_ON(data_offset != krb5->conf_len)) 557 return -EINVAL; /* Data is in wrong place */ 558 559 secure_offset = 0; 560 base_len = krb5->conf_len + data_len; 561 pad_len = 0; 562 secure_len = base_len + pad_len; 563 cksum_offset = secure_len; 564 if (WARN_ON(cksum_offset + krb5->cksum_len > sg_len)) 565 return -EFAULT; 566 567 bsize = krb5_aead_size(aead) + 568 krb5_aead_ivsize(aead); 569 buffer = kzalloc(bsize, GFP_NOFS); 570 if (!buffer) 571 return -ENOMEM; 572 573 /* Insert the confounder into the buffer */ 574 ret = -EFAULT; 575 if (!preconfounded) { 576 get_random_bytes(buffer, krb5->conf_len); 577 done = sg_pcopy_from_buffer(sg, nr_sg, buffer, krb5->conf_len, 578 secure_offset); 579 if (done != krb5->conf_len) 580 goto error; 581 } 582 583 /* We may need to pad out to the crypto blocksize. */ 584 if (pad_len) { 585 done = sg_zero_buffer(sg, nr_sg, pad_len, data_offset + data_len); 586 if (done != pad_len) 587 goto error; 588 } 589 590 /* Hash and encrypt the message. */ 591 req = buffer; 592 iv = buffer + krb5_aead_size(aead); 593 594 aead_request_set_tfm(req, aead); 595 aead_request_set_callback(req, 0, NULL, NULL); 596 aead_request_set_crypt(req, sg, sg, secure_len, iv); 597 ret = crypto_aead_encrypt(req); 598 if (ret < 0) 599 goto error; 600 601 ret = secure_len + krb5->cksum_len; 602 603 error: 604 kfree_sensitive(buffer); 605 return ret; 606 } 607 608 /* 609 * Apply decryption and checksumming functions to a message. The offset and 610 * length are updated to reflect the actual content of the encrypted region. 611 */ 612 int krb5_aead_decrypt(const struct krb5_enctype *krb5, 613 struct crypto_aead *aead, 614 struct scatterlist *sg, unsigned int nr_sg, 615 size_t *_offset, size_t *_len) 616 { 617 struct aead_request *req; 618 size_t bsize; 619 void *buffer; 620 int ret; 621 u8 *iv; 622 623 if (WARN_ON(*_offset != 0)) 624 return -EINVAL; /* Can't set offset on aead */ 625 626 if (*_len < krb5->conf_len + krb5->cksum_len) 627 return -EPROTO; 628 629 bsize = krb5_aead_size(aead) + 630 krb5_aead_ivsize(aead); 631 buffer = kzalloc(bsize, GFP_NOFS); 632 if (!buffer) 633 return -ENOMEM; 634 635 /* Decrypt the message and verify its checksum. */ 636 req = buffer; 637 iv = buffer + krb5_aead_size(aead); 638 639 aead_request_set_tfm(req, aead); 640 aead_request_set_callback(req, 0, NULL, NULL); 641 aead_request_set_crypt(req, sg, sg, *_len, iv); 642 ret = crypto_aead_decrypt(req); 643 if (ret < 0) 644 goto error; 645 646 /* Adjust the boundaries of the data. */ 647 *_offset += krb5->conf_len; 648 *_len -= krb5->conf_len + krb5->cksum_len; 649 ret = 0; 650 651 error: 652 kfree_sensitive(buffer); 653 return ret; 654 } 655 656 /* 657 * Generate a checksum over some metadata and part of an skbuff and insert the 658 * MIC into the skbuff immediately prior to the data. 659 */ 660 ssize_t rfc3961_get_mic(const struct krb5_enctype *krb5, 661 struct crypto_shash *shash, 662 const struct krb5_buffer *metadata, 663 struct scatterlist *sg, unsigned int nr_sg, size_t sg_len, 664 size_t data_offset, size_t data_len) 665 { 666 struct shash_desc *desc; 667 ssize_t ret, done; 668 size_t bsize; 669 void *buffer, *digest; 670 671 if (WARN_ON(data_offset != krb5->cksum_len)) 672 return -EMSGSIZE; 673 674 bsize = krb5_shash_size(shash) + 675 krb5_digest_size(shash); 676 buffer = kzalloc(bsize, GFP_NOFS); 677 if (!buffer) 678 return -ENOMEM; 679 680 /* Calculate the MIC with key Kc and store it into the skb */ 681 desc = buffer; 682 desc->tfm = shash; 683 ret = crypto_shash_init(desc); 684 if (ret < 0) 685 goto error; 686 687 if (metadata) { 688 ret = crypto_shash_update(desc, metadata->data, metadata->len); 689 if (ret < 0) 690 goto error; 691 } 692 693 ret = crypto_shash_update_sg(desc, sg, data_offset, data_len); 694 if (ret < 0) 695 goto error; 696 697 digest = buffer + krb5_shash_size(shash); 698 ret = crypto_shash_final(desc, digest); 699 if (ret < 0) 700 goto error; 701 702 ret = -EFAULT; 703 done = sg_pcopy_from_buffer(sg, nr_sg, digest, krb5->cksum_len, 704 data_offset - krb5->cksum_len); 705 if (done != krb5->cksum_len) 706 goto error; 707 708 ret = krb5->cksum_len + data_len; 709 710 error: 711 kfree_sensitive(buffer); 712 return ret; 713 } 714 715 /* 716 * Check the MIC on a region of an skbuff. The offset and length are updated 717 * to reflect the actual content of the secure region. 718 */ 719 int rfc3961_verify_mic(const struct krb5_enctype *krb5, 720 struct crypto_shash *shash, 721 const struct krb5_buffer *metadata, 722 struct scatterlist *sg, unsigned int nr_sg, 723 size_t *_offset, size_t *_len) 724 { 725 struct shash_desc *desc; 726 ssize_t done; 727 size_t bsize, data_offset, data_len, offset = *_offset, len = *_len; 728 void *buffer = NULL; 729 int ret; 730 u8 *cksum, *cksum2; 731 732 if (len < krb5->cksum_len) 733 return -EPROTO; 734 data_offset = offset + krb5->cksum_len; 735 data_len = len - krb5->cksum_len; 736 737 bsize = krb5_shash_size(shash) + 738 krb5_digest_size(shash) * 2; 739 buffer = kzalloc(bsize, GFP_NOFS); 740 if (!buffer) 741 return -ENOMEM; 742 743 cksum = buffer + 744 krb5_shash_size(shash); 745 cksum2 = buffer + 746 krb5_shash_size(shash) + 747 krb5_digest_size(shash); 748 749 /* Calculate the MIC */ 750 desc = buffer; 751 desc->tfm = shash; 752 ret = crypto_shash_init(desc); 753 if (ret < 0) 754 goto error; 755 756 if (metadata) { 757 ret = crypto_shash_update(desc, metadata->data, metadata->len); 758 if (ret < 0) 759 goto error; 760 } 761 762 crypto_shash_update_sg(desc, sg, data_offset, data_len); 763 crypto_shash_final(desc, cksum); 764 765 ret = -EFAULT; 766 done = sg_pcopy_to_buffer(sg, nr_sg, cksum2, krb5->cksum_len, offset); 767 if (done != krb5->cksum_len) 768 goto error; 769 770 if (memcmp(cksum, cksum2, krb5->cksum_len) != 0) { 771 ret = -EBADMSG; 772 goto error; 773 } 774 775 *_offset += krb5->cksum_len; 776 *_len -= krb5->cksum_len; 777 ret = 0; 778 779 error: 780 kfree_sensitive(buffer); 781 return ret; 782 } 783 784 const struct krb5_crypto_profile rfc3961_simplified_profile = { 785 .calc_PRF = rfc3961_calc_PRF, 786 .calc_Kc = rfc3961_calc_DK, 787 .calc_Ke = rfc3961_calc_DK, 788 .calc_Ki = rfc3961_calc_DK, 789 .derive_encrypt_keys = authenc_derive_encrypt_keys, 790 .load_encrypt_keys = authenc_load_encrypt_keys, 791 .derive_checksum_key = rfc3961_derive_checksum_key, 792 .load_checksum_key = rfc3961_load_checksum_key, 793 .encrypt = krb5_aead_encrypt, 794 .decrypt = krb5_aead_decrypt, 795 .get_mic = rfc3961_get_mic, 796 .verify_mic = rfc3961_verify_mic, 797 }; 798