File Index
Files and directories
Sign in
FILE

krb5_api.c

File preview with syntax highlighting.

linux-6.19.14/crypto/krb5/krb5_api.c C
  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
 15MODULE_DESCRIPTION("Kerberos 5 crypto");
 16MODULE_AUTHOR("Red Hat, Inc.");
 17MODULE_LICENSE("GPL");
 18
 19static 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 */
 35const 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}
 48EXPORT_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 */
 62size_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}
 81EXPORT_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 */
 96size_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
121bad:
122	*_offset = 0;
123	return 0;
124}
125EXPORT_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 */
138void crypto_krb5_where_is_the_data(const struct krb5_enctype *krb5,
139				   enum krb5_crypto_mode mode,
140				   size_t *_offset, size_t *_len)
141{
142	switch (mode) {
143	case KRB5_CHECKSUM_MODE:
144		*_offset += krb5->cksum_len;
145		*_len -= krb5->cksum_len;
146		return;
147	case KRB5_ENCRYPT_MODE:
148		*_offset += krb5->conf_len;
149		*_len -= krb5->conf_len + krb5->cksum_len;
150		return;
151	default:
152		WARN_ON_ONCE(1);
153		return;
154	}
155}
156EXPORT_SYMBOL(crypto_krb5_where_is_the_data);
157
158/*
159 * Prepare the encryption with derived key data.
160 */
161struct crypto_aead *krb5_prepare_encryption(const struct krb5_enctype *krb5,
162					    const struct krb5_buffer *keys,
163					    gfp_t gfp)
164{
165	struct crypto_aead *ci = NULL;
166	int ret = -ENOMEM;
167
168	ci = crypto_alloc_aead(krb5->encrypt_name, 0, 0);
169	if (IS_ERR(ci)) {
170		ret = PTR_ERR(ci);
171		if (ret == -ENOENT)
172			ret = -ENOPKG;
173		goto err;
174	}
175
176	ret = crypto_aead_setkey(ci, keys->data, keys->len);
177	if (ret < 0) {
178		pr_err("Couldn't set AEAD key %s: %d\n", krb5->encrypt_name, ret);
179		goto err_ci;
180	}
181
182	ret = crypto_aead_setauthsize(ci, krb5->cksum_len);
183	if (ret < 0) {
184		pr_err("Couldn't set AEAD authsize %s: %d\n", krb5->encrypt_name, ret);
185		goto err_ci;
186	}
187
188	return ci;
189err_ci:
190	crypto_free_aead(ci);
191err:
192	return ERR_PTR(ret);
193}
194
195/**
196 * crypto_krb5_prepare_encryption - Prepare AEAD crypto object for encryption-mode
197 * @krb5: The encoding to use.
198 * @TK: The transport key to use.
199 * @usage: The usage constant for key derivation.
200 * @gfp: Allocation flags.
201 *
202 * Allocate a crypto object that does all the necessary crypto, key it and set
203 * its parameters and return the crypto handle to it.  This can then be used to
204 * dispatch encrypt and decrypt operations.
205 */
206struct crypto_aead *crypto_krb5_prepare_encryption(const struct krb5_enctype *krb5,
207						   const struct krb5_buffer *TK,
208						   u32 usage, gfp_t gfp)
209{
210	struct crypto_aead *ci = NULL;
211	struct krb5_buffer keys = {};
212	int ret;
213
214	ret = krb5->profile->derive_encrypt_keys(krb5, TK, usage, &keys, gfp);
215	if (ret < 0)
216		goto err;
217
218	ci = krb5_prepare_encryption(krb5, &keys, gfp);
219	if (IS_ERR(ci)) {
220		ret = PTR_ERR(ci);
221		goto err;
222	}
223
224	kfree(keys.data);
225	return ci;
226err:
227	kfree(keys.data);
228	return ERR_PTR(ret);
229}
230EXPORT_SYMBOL(crypto_krb5_prepare_encryption);
231
232/*
233 * Prepare the checksum with derived key data.
234 */
235struct crypto_shash *krb5_prepare_checksum(const struct krb5_enctype *krb5,
236					   const struct krb5_buffer *Kc,
237					   gfp_t gfp)
238{
239	struct crypto_shash *ci = NULL;
240	int ret = -ENOMEM;
241
242	ci = crypto_alloc_shash(krb5->cksum_name, 0, 0);
243	if (IS_ERR(ci)) {
244		ret = PTR_ERR(ci);
245		if (ret == -ENOENT)
246			ret = -ENOPKG;
247		goto err;
248	}
249
250	ret = crypto_shash_setkey(ci, Kc->data, Kc->len);
251	if (ret < 0) {
252		pr_err("Couldn't set shash key %s: %d\n", krb5->cksum_name, ret);
253		goto err_ci;
254	}
255
256	return ci;
257err_ci:
258	crypto_free_shash(ci);
259err:
260	return ERR_PTR(ret);
261}
262
263/**
264 * crypto_krb5_prepare_checksum - Prepare AEAD crypto object for checksum-mode
265 * @krb5: The encoding to use.
266 * @TK: The transport key to use.
267 * @usage: The usage constant for key derivation.
268 * @gfp: Allocation flags.
269 *
270 * Allocate a crypto object that does all the necessary crypto, key it and set
271 * its parameters and return the crypto handle to it.  This can then be used to
272 * dispatch get_mic and verify_mic operations.
273 */
274struct crypto_shash *crypto_krb5_prepare_checksum(const struct krb5_enctype *krb5,
275						  const struct krb5_buffer *TK,
276						  u32 usage, gfp_t gfp)
277{
278	struct crypto_shash *ci = NULL;
279	struct krb5_buffer keys = {};
280	int ret;
281
282	ret = krb5->profile->derive_checksum_key(krb5, TK, usage, &keys, gfp);
283	if (ret < 0) {
284		pr_err("get_Kc failed %d\n", ret);
285		goto err;
286	}
287
288	ci = krb5_prepare_checksum(krb5, &keys, gfp);
289	if (IS_ERR(ci)) {
290		ret = PTR_ERR(ci);
291		goto err;
292	}
293
294	kfree(keys.data);
295	return ci;
296err:
297	kfree(keys.data);
298	return ERR_PTR(ret);
299}
300EXPORT_SYMBOL(crypto_krb5_prepare_checksum);
301
302/**
303 * crypto_krb5_encrypt - Apply Kerberos encryption and integrity.
304 * @krb5: The encoding to use.
305 * @aead: The keyed crypto object to use.
306 * @sg: Scatterlist defining the crypto buffer.
307 * @nr_sg: The number of elements in @sg.
308 * @sg_len: The size of the buffer.
309 * @data_offset: The offset of the data in the @sg buffer.
310 * @data_len: The length of the data.
311 * @preconfounded: True if the confounder is already inserted.
312 *
313 * Using the specified Kerberos encoding, insert a confounder and padding as
314 * needed, encrypt this and the data in place and insert an integrity checksum
315 * into the buffer.
316 *
317 * The buffer must include space for the confounder, the checksum and any
318 * padding required.  The caller can preinsert the confounder into the buffer
319 * (for testing, for example).
320 *
321 * The resulting secured blob may be less than the size of the buffer.
322 *
323 * Returns the size of the secure blob if successful, -ENOMEM on an allocation
324 * failure, -EFAULT if there is insufficient space, -EMSGSIZE if the confounder
325 * is too short or the data is misaligned.  Other errors may also be returned
326 * from the crypto layer.
327 */
328ssize_t crypto_krb5_encrypt(const struct krb5_enctype *krb5,
329			    struct crypto_aead *aead,
330			    struct scatterlist *sg, unsigned int nr_sg,
331			    size_t sg_len,
332			    size_t data_offset, size_t data_len,
333			    bool preconfounded)
334{
335	if (WARN_ON(data_offset > sg_len ||
336		    data_len > sg_len ||
337		    data_offset > sg_len - data_len))
338		return -EMSGSIZE;
339	return krb5->profile->encrypt(krb5, aead, sg, nr_sg, sg_len,
340				      data_offset, data_len, preconfounded);
341}
342EXPORT_SYMBOL(crypto_krb5_encrypt);
343
344/**
345 * crypto_krb5_decrypt - Validate and remove 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 * @_offset: Offset of the secure blob in the buffer; updated to data offset.
351 * @_len: The length of the secure blob; updated to data length.
352 *
353 * Using the specified Kerberos encoding, check and remove the integrity
354 * checksum and decrypt the secure region, stripping off the confounder.
355 *
356 * If successful, @_offset and @_len are updated to outline the region in which
357 * the data plus the trailing padding are stored.  The caller is responsible
358 * for working out how much padding there is and removing it.
359 *
360 * Returns the 0 if successful, -ENOMEM on an allocation failure; sets
361 * *_error_code and returns -EPROTO if the data cannot be parsed, or -EBADMSG
362 * if the integrity checksum doesn't match).  Other errors may also be returned
363 * from the crypto layer.
364 */
365int crypto_krb5_decrypt(const struct krb5_enctype *krb5,
366			struct crypto_aead *aead,
367			struct scatterlist *sg, unsigned int nr_sg,
368			size_t *_offset, size_t *_len)
369{
370	return krb5->profile->decrypt(krb5, aead, sg, nr_sg, _offset, _len);
371}
372EXPORT_SYMBOL(crypto_krb5_decrypt);
373
374/**
375 * crypto_krb5_get_mic - Apply Kerberos integrity checksum.
376 * @krb5: The encoding to use.
377 * @shash: The keyed hash to use.
378 * @metadata: Metadata to add into the hash before adding the data.
379 * @sg: Scatterlist defining the crypto buffer.
380 * @nr_sg: The number of elements in @sg.
381 * @sg_len: The size of the buffer.
382 * @data_offset: The offset of the data in the @sg buffer.
383 * @data_len: The length of the data.
384 *
385 * Using the specified Kerberos encoding, calculate and insert an integrity
386 * checksum into the buffer.
387 *
388 * The buffer must include space for the checksum at the front.
389 *
390 * Returns the size of the secure blob if successful, -ENOMEM on an allocation
391 * failure, -EFAULT if there is insufficient space, -EMSGSIZE if the gap for
392 * the checksum is too short.  Other errors may also be returned from the
393 * crypto layer.
394 */
395ssize_t crypto_krb5_get_mic(const struct krb5_enctype *krb5,
396			    struct crypto_shash *shash,
397			    const struct krb5_buffer *metadata,
398			    struct scatterlist *sg, unsigned int nr_sg,
399			    size_t sg_len,
400			    size_t data_offset, size_t data_len)
401{
402	if (WARN_ON(data_offset > sg_len ||
403		    data_len > sg_len ||
404		    data_offset > sg_len - data_len))
405		return -EMSGSIZE;
406	return krb5->profile->get_mic(krb5, shash, metadata, sg, nr_sg, sg_len,
407				      data_offset, data_len);
408}
409EXPORT_SYMBOL(crypto_krb5_get_mic);
410
411/**
412 * crypto_krb5_verify_mic - Validate and remove Kerberos integrity checksum.
413 * @krb5: The encoding to use.
414 * @shash: The keyed hash to use.
415 * @metadata: Metadata to add into the hash before adding the data.
416 * @sg: Scatterlist defining the crypto buffer.
417 * @nr_sg: The number of elements in @sg.
418 * @_offset: Offset of the secure blob in the buffer; updated to data offset.
419 * @_len: The length of the secure blob; updated to data length.
420 *
421 * Using the specified Kerberos encoding, check and remove the integrity
422 * checksum.
423 *
424 * If successful, @_offset and @_len are updated to outline the region in which
425 * the data is stored.
426 *
427 * Returns the 0 if successful, -ENOMEM on an allocation failure; sets
428 * *_error_code and returns -EPROTO if the data cannot be parsed, or -EBADMSG
429 * if the checksum doesn't match).  Other errors may also be returned from the
430 * crypto layer.
431 */
432int crypto_krb5_verify_mic(const struct krb5_enctype *krb5,
433			   struct crypto_shash *shash,
434			   const struct krb5_buffer *metadata,
435			   struct scatterlist *sg, unsigned int nr_sg,
436			   size_t *_offset, size_t *_len)
437{
438	return krb5->profile->verify_mic(krb5, shash, metadata, sg, nr_sg,
439					 _offset, _len);
440}
441EXPORT_SYMBOL(crypto_krb5_verify_mic);
442
443static int __init crypto_krb5_init(void)
444{
445	return krb5_selftest();
446}
447module_init(crypto_krb5_init);
448
449static void __exit crypto_krb5_exit(void)
450{
451}
452module_exit(crypto_krb5_exit);
~/ Read-only file preview.