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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 485 static int __init crypto_krb5_init(void) 486 { 487 return krb5_selftest(); 488 } 489 module_init(crypto_krb5_init); 490 491 static void __exit crypto_krb5_exit(void) 492 { 493 } 494 module_exit(crypto_krb5_exit); 495