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