xref: /linux/crypto/krb5/krb5_api.c (revision 68993ced0f618e36cf33388f1e50223e5e6e78cc)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Kerberos 5 crypto library.
3  *
4  * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 
10 #include <linux/module.h>
11 #include <linux/export.h>
12 #include <linux/kernel.h>
13 #include "internal.h"
14 
15 MODULE_DESCRIPTION("Kerberos 5 crypto");
16 MODULE_AUTHOR("Red Hat, Inc.");
17 MODULE_LICENSE("GPL");
18 
19 static const struct krb5_enctype *const krb5_supported_enctypes[] = {
20 	&krb5_aes128_cts_hmac_sha1_96,
21 	&krb5_aes256_cts_hmac_sha1_96,
22 	&krb5_aes128_cts_hmac_sha256_128,
23 	&krb5_aes256_cts_hmac_sha384_192,
24 	&krb5_camellia128_cts_cmac,
25 	&krb5_camellia256_cts_cmac,
26 };
27 
28 /**
29  * crypto_krb5_find_enctype - Find the handler for a Kerberos5 encryption type
30  * @enctype: The standard Kerberos encryption type number
31  *
32  * Look up a Kerberos encryption type by number.  If successful, returns a
33  * pointer to the type tables; returns NULL otherwise.
34  */
crypto_krb5_find_enctype(u32 enctype)35 const struct krb5_enctype *crypto_krb5_find_enctype(u32 enctype)
36 {
37 	const struct krb5_enctype *krb5;
38 	size_t i;
39 
40 	for (i = 0; i < ARRAY_SIZE(krb5_supported_enctypes); i++) {
41 		krb5 = krb5_supported_enctypes[i];
42 		if (krb5->etype == enctype)
43 			return krb5;
44 	}
45 
46 	return NULL;
47 }
48 EXPORT_SYMBOL(crypto_krb5_find_enctype);
49 
50 /**
51  * crypto_krb5_how_much_buffer - Work out how much buffer is required for an amount of data
52  * @krb5: The encoding to use.
53  * @mode: The mode in which to operated (checksum/encrypt)
54  * @data_size: How much data we want to allow for
55  * @_offset: Where to place the offset into the buffer
56  *
57  * Calculate how much buffer space is required to wrap a given amount of data.
58  * This allows for a confounder, padding and checksum as appropriate.  The
59  * amount of buffer required is returned and the offset into the buffer at
60  * which the data will start is placed in *_offset.
61  */
crypto_krb5_how_much_buffer(const struct krb5_enctype * krb5,enum krb5_crypto_mode mode,size_t data_size,size_t * _offset)62 size_t crypto_krb5_how_much_buffer(const struct krb5_enctype *krb5,
63 				   enum krb5_crypto_mode mode,
64 				   size_t data_size, size_t *_offset)
65 {
66 	switch (mode) {
67 	case KRB5_CHECKSUM_MODE:
68 		*_offset = krb5->cksum_len;
69 		return krb5->cksum_len + data_size;
70 
71 	case KRB5_ENCRYPT_MODE:
72 		*_offset = krb5->conf_len;
73 		return krb5->conf_len + data_size + krb5->cksum_len;
74 
75 	default:
76 		WARN_ON(1);
77 		*_offset = 0;
78 		return 0;
79 	}
80 }
81 EXPORT_SYMBOL(crypto_krb5_how_much_buffer);
82 
83 /**
84  * crypto_krb5_how_much_data - Work out how much data can fit in an amount of buffer
85  * @krb5: The encoding to use.
86  * @mode: The mode in which to operated (checksum/encrypt)
87  * @_buffer_size: How much buffer we want to allow for (may be reduced)
88  * @_offset: Where to place the offset into the buffer
89  *
90  * Calculate how much data can be fitted into given amount of buffer.  This
91  * allows for a confounder, padding and checksum as appropriate.  The amount of
92  * data that will fit is returned, the amount of buffer required is shrunk to
93  * allow for alignment and the offset into the buffer at which the data will
94  * start is placed in *_offset.
95  */
crypto_krb5_how_much_data(const struct krb5_enctype * krb5,enum krb5_crypto_mode mode,size_t * _buffer_size,size_t * _offset)96 size_t crypto_krb5_how_much_data(const struct krb5_enctype *krb5,
97 				 enum krb5_crypto_mode mode,
98 				 size_t *_buffer_size, size_t *_offset)
99 {
100 	size_t buffer_size = *_buffer_size, data_size;
101 
102 	switch (mode) {
103 	case KRB5_CHECKSUM_MODE:
104 		if (WARN_ON(buffer_size < krb5->cksum_len + 1))
105 			goto bad;
106 		*_offset = krb5->cksum_len;
107 		return buffer_size - krb5->cksum_len;
108 
109 	case KRB5_ENCRYPT_MODE:
110 		if (WARN_ON(buffer_size < krb5->conf_len + 1 + krb5->cksum_len))
111 			goto bad;
112 		data_size = buffer_size - krb5->cksum_len;
113 		*_offset = krb5->conf_len;
114 		return data_size - krb5->conf_len;
115 
116 	default:
117 		WARN_ON(1);
118 		goto bad;
119 	}
120 
121 bad:
122 	*_offset = 0;
123 	return 0;
124 }
125 EXPORT_SYMBOL(crypto_krb5_how_much_data);
126 
127 /**
128  * crypto_krb5_where_is_the_data - Find the data in a decrypted message
129  * @krb5: The encoding to use.
130  * @mode: Mode of operation
131  * @_offset: Offset of the secure blob in the buffer; updated to data offset.
132  * @_len: The length of the secure blob; updated to data length.
133  *
134  * Find the offset and size of the data in a secure message so that this
135  * information can be used in the metadata buffer which will get added to the
136  * digest by crypto_krb5_verify_mic().
137  *
138  * Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if
139  * the mode is unsupported.
140  */
crypto_krb5_where_is_the_data(const struct krb5_enctype * krb5,enum krb5_crypto_mode mode,size_t * _offset,size_t * _len)141 int crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
142 				  enum krb5_crypto_mode mode,
143 				  size_t *_offset, size_t *_len)
144 {
145 	switch (mode) {
146 	case KRB5_CHECKSUM_MODE:
147 		if (*_len < krb5->cksum_len)
148 			return -EBADMSG;
149 		*_offset += krb5->cksum_len;
150 		*_len -= krb5->cksum_len;
151 		return 0;
152 	case KRB5_ENCRYPT_MODE:
153 		if (*_len < krb5->conf_len + krb5->cksum_len)
154 			return -EBADMSG;
155 		*_offset += krb5->conf_len;
156 		*_len -= krb5->conf_len + krb5->cksum_len;
157 		return 0;
158 	default:
159 		WARN_ON_ONCE(1);
160 		return -EINVAL;
161 	}
162 }
163 EXPORT_SYMBOL(crypto_krb5_where_is_the_data);
164 
165 /**
166  * crypto_krb5_check_data_len - Check a message is big enough
167  * @krb5: The encoding to use.
168  * @mode: Mode of operation.
169  * @len: The length of the secure blob.
170  * @min_content: Minimum length of the content inside the blob.
171  *
172  * Check that a message is large enough to hold whatever bits the encryption
173  * type wants to glue on (nonce, checksum) plus a minimum amount of content.
174  *
175  * Return: 0 if successful, -EBADMSG if the message is too short or -EINVAL if
176  * the mode is unsupported.
177  */
crypto_krb5_check_data_len(const struct krb5_enctype * krb5,enum krb5_crypto_mode mode,size_t len,size_t min_content)178 int crypto_krb5_check_data_len(const struct krb5_enctype *krb5,
179 			       enum krb5_crypto_mode mode,
180 			       size_t len, size_t min_content)
181 {
182 	switch (mode) {
183 	case KRB5_CHECKSUM_MODE:
184 		if (len < krb5->cksum_len ||
185 		    len - krb5->cksum_len < min_content)
186 			return -EBADMSG;
187 		return 0;
188 	case KRB5_ENCRYPT_MODE:
189 		if (len < krb5->conf_len + krb5->cksum_len ||
190 		    len - (krb5->conf_len + krb5->cksum_len) < min_content)
191 			return -EBADMSG;
192 		return 0;
193 	default:
194 		WARN_ON_ONCE(1);
195 		return -EINVAL;
196 	}
197 }
198 EXPORT_SYMBOL(crypto_krb5_check_data_len);
199 
200 /*
201  * Prepare the encryption with derived key data.
202  */
krb5_prepare_encryption(const struct krb5_enctype * krb5,const struct krb5_buffer * keys,gfp_t gfp)203 struct crypto_aead *krb5_prepare_encryption(const struct krb5_enctype *krb5,
204 					    const struct krb5_buffer *keys,
205 					    gfp_t gfp)
206 {
207 	struct crypto_aead *ci = NULL;
208 	int ret = -ENOMEM;
209 
210 	ci = crypto_alloc_aead(krb5->encrypt_name, 0, 0);
211 	if (IS_ERR(ci)) {
212 		ret = PTR_ERR(ci);
213 		if (ret == -ENOENT)
214 			ret = -ENOPKG;
215 		goto err;
216 	}
217 
218 	ret = crypto_aead_setkey(ci, keys->data, keys->len);
219 	if (ret < 0) {
220 		pr_err("Couldn't set AEAD key %s: %d\n", krb5->encrypt_name, ret);
221 		goto err_ci;
222 	}
223 
224 	ret = crypto_aead_setauthsize(ci, krb5->cksum_len);
225 	if (ret < 0) {
226 		pr_err("Couldn't set AEAD authsize %s: %d\n", krb5->encrypt_name, ret);
227 		goto err_ci;
228 	}
229 
230 	return ci;
231 err_ci:
232 	crypto_free_aead(ci);
233 err:
234 	return ERR_PTR(ret);
235 }
236 
237 /**
238  * crypto_krb5_prepare_encryption - Prepare AEAD crypto object for encryption-mode
239  * @krb5: The encoding to use.
240  * @TK: The transport key to use.
241  * @usage: The usage constant for key derivation.
242  * @gfp: Allocation flags.
243  *
244  * Allocate a crypto object that does all the necessary crypto, key it and set
245  * its parameters and return the crypto handle to it.  This can then be used to
246  * dispatch encrypt and decrypt operations.
247  */
crypto_krb5_prepare_encryption(const struct krb5_enctype * krb5,const struct krb5_buffer * TK,u32 usage,gfp_t gfp)248 struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *krb5,
249 						   const struct krb5_buffer *TK,
250 						   u32 usage, gfp_t gfp)
251 {
252 	struct crypto_aead *ci = NULL;
253 	struct krb5_buffer keys = {};
254 	int ret;
255 
256 	ret = krb5->profile->derive_encrypt_keys(krb5, TK, usage, &keys, gfp);
257 	if (ret < 0)
258 		goto err;
259 
260 	ci = krb5_prepare_encryption(krb5, &keys, gfp);
261 	if (IS_ERR(ci)) {
262 		ret = PTR_ERR(ci);
263 		goto err;
264 	}
265 
266 	kfree(keys.data);
267 	return ci;
268 err:
269 	kfree(keys.data);
270 	return ERR_PTR(ret);
271 }
272 EXPORT_SYMBOL(crypto_krb5_prepare_encryption);
273 
274 /*
275  * Prepare the checksum with derived key data.
276  */
krb5_prepare_checksum(const struct krb5_enctype * krb5,const struct krb5_buffer * Kc,gfp_t gfp)277 struct crypto_shash *krb5_prepare_checksum(const struct krb5_enctype *krb5,
278 					   const struct krb5_buffer *Kc,
279 					   gfp_t gfp)
280 {
281 	struct crypto_shash *ci = NULL;
282 	int ret = -ENOMEM;
283 
284 	ci = crypto_alloc_shash(krb5->cksum_name, 0, 0);
285 	if (IS_ERR(ci)) {
286 		ret = PTR_ERR(ci);
287 		if (ret == -ENOENT)
288 			ret = -ENOPKG;
289 		goto err;
290 	}
291 
292 	ret = crypto_shash_setkey(ci, Kc->data, Kc->len);
293 	if (ret < 0) {
294 		pr_err("Couldn't set shash key %s: %d\n", krb5->cksum_name, ret);
295 		goto err_ci;
296 	}
297 
298 	return ci;
299 err_ci:
300 	crypto_free_shash(ci);
301 err:
302 	return ERR_PTR(ret);
303 }
304 
305 /**
306  * crypto_krb5_prepare_checksum - Prepare AEAD crypto object for checksum-mode
307  * @krb5: The encoding to use.
308  * @TK: The transport key to use.
309  * @usage: The usage constant for key derivation.
310  * @gfp: Allocation flags.
311  *
312  * Allocate a crypto object that does all the necessary crypto, key it and set
313  * its parameters and return the crypto handle to it.  This can then be used to
314  * dispatch get_mic and verify_mic operations.
315  */
crypto_krb5_prepare_checksum(const struct krb5_enctype * krb5,const struct krb5_buffer * TK,u32 usage,gfp_t gfp)316 struct crypto_shash *crypto_krb5_prepare_checksum(const struct krb5_enctype *krb5,
317 						  const struct krb5_buffer *TK,
318 						  u32 usage, gfp_t gfp)
319 {
320 	struct crypto_shash *ci = NULL;
321 	struct krb5_buffer keys = {};
322 	int ret;
323 
324 	ret = krb5->profile->derive_checksum_key(krb5, TK, usage, &keys, gfp);
325 	if (ret < 0) {
326 		pr_err("get_Kc failed %d\n", ret);
327 		goto err;
328 	}
329 
330 	ci = krb5_prepare_checksum(krb5, &keys, gfp);
331 	if (IS_ERR(ci)) {
332 		ret = PTR_ERR(ci);
333 		goto err;
334 	}
335 
336 	kfree(keys.data);
337 	return ci;
338 err:
339 	kfree(keys.data);
340 	return ERR_PTR(ret);
341 }
342 EXPORT_SYMBOL(crypto_krb5_prepare_checksum);
343 
344 /**
345  * crypto_krb5_encrypt - Apply Kerberos encryption and integrity.
346  * @krb5: The encoding to use.
347  * @aead: The keyed crypto object to use.
348  * @sg: Scatterlist defining the crypto buffer.
349  * @nr_sg: The number of elements in @sg.
350  * @sg_len: The size of the buffer.
351  * @data_offset: The offset of the data in the @sg buffer.
352  * @data_len: The length of the data.
353  * @preconfounded: True if the confounder is already inserted.
354  *
355  * Using the specified Kerberos encoding, insert a confounder and padding as
356  * needed, encrypt this and the data in place and insert an integrity checksum
357  * into the buffer.
358  *
359  * The buffer must include space for the confounder, the checksum and any
360  * padding required.  The caller can preinsert the confounder into the buffer
361  * (for testing, for example).
362  *
363  * The resulting secured blob may be less than the size of the buffer.
364  *
365  * Returns the size of the secure blob if successful, -ENOMEM on an allocation
366  * failure, -EFAULT if there is insufficient space, -EMSGSIZE if the confounder
367  * is too short or the data is misaligned.  Other errors may also be returned
368  * from the crypto layer.
369  */
crypto_krb5_encrypt(const struct krb5_enctype * krb5,struct crypto_aead * aead,struct scatterlist * sg,unsigned int nr_sg,size_t sg_len,size_t data_offset,size_t data_len,bool preconfounded)370 ssize_t crypto_krb5_encrypt(const struct krb5_enctype *krb5,
371 			    struct crypto_aead *aead,
372 			    struct scatterlist *sg, unsigned int nr_sg,
373 			    size_t sg_len,
374 			    size_t data_offset, size_t data_len,
375 			    bool preconfounded)
376 {
377 	if (WARN_ON(data_offset > sg_len ||
378 		    data_len > sg_len ||
379 		    data_offset > sg_len - data_len))
380 		return -EMSGSIZE;
381 	return krb5->profile->encrypt(krb5, aead, sg, nr_sg, sg_len,
382 				      data_offset, data_len, preconfounded);
383 }
384 EXPORT_SYMBOL(crypto_krb5_encrypt);
385 
386 /**
387  * crypto_krb5_decrypt - Validate and remove Kerberos encryption and integrity.
388  * @krb5: The encoding to use.
389  * @aead: The keyed crypto object to use.
390  * @sg: Scatterlist defining the crypto buffer.
391  * @nr_sg: The number of elements in @sg.
392  * @_offset: Offset of the secure blob in the buffer; updated to data offset.
393  * @_len: The length of the secure blob; updated to data length.
394  *
395  * Using the specified Kerberos encoding, check and remove the integrity
396  * checksum and decrypt the secure region, stripping off the confounder.
397  *
398  * If successful, @_offset and @_len are updated to outline the region in which
399  * the data plus the trailing padding are stored.  The caller is responsible
400  * for working out how much padding there is and removing it.
401  *
402  * Returns the 0 if successful, -ENOMEM on an allocation failure; sets
403  * *_error_code and returns -EPROTO if the data cannot be parsed, or -EBADMSG
404  * if the integrity checksum doesn't match).  Other errors may also be returned
405  * from the crypto layer.
406  */
crypto_krb5_decrypt(const struct krb5_enctype * krb5,struct crypto_aead * aead,struct scatterlist * sg,unsigned int nr_sg,size_t * _offset,size_t * _len)407 int crypto_krb5_decrypt(const struct krb5_enctype *krb5,
408 			struct crypto_aead *aead,
409 			struct scatterlist *sg, unsigned int nr_sg,
410 			size_t *_offset, size_t *_len)
411 {
412 	return krb5->profile->decrypt(krb5, aead, sg, nr_sg, _offset, _len);
413 }
414 EXPORT_SYMBOL(crypto_krb5_decrypt);
415 
416 /**
417  * crypto_krb5_get_mic - Apply Kerberos integrity checksum.
418  * @krb5: The encoding to use.
419  * @shash: The keyed hash to use.
420  * @metadata: Metadata to add into the hash before adding the data.
421  * @sg: Scatterlist defining the crypto buffer.
422  * @nr_sg: The number of elements in @sg.
423  * @sg_len: The size of the buffer.
424  * @data_offset: The offset of the data in the @sg buffer.
425  * @data_len: The length of the data.
426  *
427  * Using the specified Kerberos encoding, calculate and insert an integrity
428  * checksum into the buffer.
429  *
430  * The buffer must include space for the checksum at the front.
431  *
432  * Returns the size of the secure blob if successful, -ENOMEM on an allocation
433  * failure, -EFAULT if there is insufficient space, -EMSGSIZE if the gap for
434  * the checksum is too short.  Other errors may also be returned from the
435  * crypto layer.
436  */
crypto_krb5_get_mic(const struct krb5_enctype * krb5,struct crypto_shash * shash,const struct krb5_buffer * metadata,struct scatterlist * sg,unsigned int nr_sg,size_t sg_len,size_t data_offset,size_t data_len)437 ssize_t crypto_krb5_get_mic(const struct krb5_enctype *krb5,
438 			    struct crypto_shash *shash,
439 			    const struct krb5_buffer *metadata,
440 			    struct scatterlist *sg, unsigned int nr_sg,
441 			    size_t sg_len,
442 			    size_t data_offset, size_t data_len)
443 {
444 	if (WARN_ON(data_offset > sg_len ||
445 		    data_len > sg_len ||
446 		    data_offset > sg_len - data_len))
447 		return -EMSGSIZE;
448 	return krb5->profile->get_mic(krb5, shash, metadata, sg, nr_sg, sg_len,
449 				      data_offset, data_len);
450 }
451 EXPORT_SYMBOL(crypto_krb5_get_mic);
452 
453 /**
454  * crypto_krb5_verify_mic - Validate and remove Kerberos integrity checksum.
455  * @krb5: The encoding to use.
456  * @shash: The keyed hash to use.
457  * @metadata: Metadata to add into the hash before adding the data.
458  * @sg: Scatterlist defining the crypto buffer.
459  * @nr_sg: The number of elements in @sg.
460  * @_offset: Offset of the secure blob in the buffer; updated to data offset.
461  * @_len: The length of the secure blob; updated to data length.
462  *
463  * Using the specified Kerberos encoding, check and remove the integrity
464  * checksum.
465  *
466  * If successful, @_offset and @_len are updated to outline the region in which
467  * the data is stored.
468  *
469  * Returns the 0 if successful, -ENOMEM on an allocation failure; sets
470  * *_error_code and returns -EPROTO if the data cannot be parsed, or -EBADMSG
471  * if the checksum doesn't match).  Other errors may also be returned from the
472  * crypto layer.
473  */
crypto_krb5_verify_mic(const struct krb5_enctype * krb5,struct crypto_shash * shash,const struct krb5_buffer * metadata,struct scatterlist * sg,unsigned int nr_sg,size_t * _offset,size_t * _len)474 int crypto_krb5_verify_mic(const struct krb5_enctype *krb5,
475 			   struct crypto_shash *shash,
476 			   const struct krb5_buffer *metadata,
477 			   struct scatterlist *sg, unsigned int nr_sg,
478 			   size_t *_offset, size_t *_len)
479 {
480 	return krb5->profile->verify_mic(krb5, shash, metadata, sg, nr_sg,
481 					 _offset, _len);
482 }
483 EXPORT_SYMBOL(crypto_krb5_verify_mic);
484 
crypto_krb5_init(void)485 static int __init crypto_krb5_init(void)
486 {
487 	return krb5_selftest();
488 }
489 module_init(crypto_krb5_init);
490 
crypto_krb5_exit(void)491 static void __exit crypto_krb5_exit(void)
492 {
493 }
494 module_exit(crypto_krb5_exit);
495