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