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