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 void 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 } 156 EXPORT_SYMBOL(crypto_krb5_where_is_the_data); 157 158 /* 159 * Prepare the encryption with derived key data. 160 */ 161 struct 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; 189 err_ci: 190 crypto_free_aead(ci); 191 err: 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 */ 206 struct 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; 226 err: 227 kfree(keys.data); 228 return ERR_PTR(ret); 229 } 230 EXPORT_SYMBOL(crypto_krb5_prepare_encryption); 231 232 /* 233 * Prepare the checksum with derived key data. 234 */ 235 struct 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; 257 err_ci: 258 crypto_free_shash(ci); 259 err: 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 */ 274 struct 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; 296 err: 297 kfree(keys.data); 298 return ERR_PTR(ret); 299 } 300 EXPORT_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 */ 328 ssize_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 } 342 EXPORT_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 */ 365 int 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 } 372 EXPORT_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 */ 395 ssize_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 } 409 EXPORT_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 */ 432 int 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 } 441 EXPORT_SYMBOL(crypto_krb5_verify_mic); 442 443 static int __init crypto_krb5_init(void) 444 { 445 return krb5_selftest(); 446 } 447 module_init(crypto_krb5_init); 448 449 static void __exit crypto_krb5_exit(void) 450 { 451 } 452 module_exit(crypto_krb5_exit); 453