Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto/krb5: Implement the Camellia enctypes from rfc6803

Implement the camellia128-cts-cmac and camellia256-cts-cmac enctypes from
rfc6803.

Note that the test vectors in rfc6803 for encryption are incomplete,
lacking the key usage number needed to derive Ke and Ki, and there are
errata for this:

https://www.rfc-editor.org/errata_search.php?rfc=6803

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Herbert Xu <herbert@gondor.apana.org.au>
cc: "David S. Miller" <davem@davemloft.net>
cc: Chuck Lever <chuck.lever@oracle.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Eric Dumazet <edumazet@google.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: linux-nfs@vger.kernel.org
cc: linux-crypto@vger.kernel.org
cc: netdev@vger.kernel.org

+252
+2
crypto/krb5/Kconfig
··· 6 6 select CRYPTO_SKCIPHER 7 7 select CRYPTO_HASH_INFO 8 8 select CRYPTO_HMAC 9 + select CRYPTO_CMAC 9 10 select CRYPTO_SHA1 10 11 select CRYPTO_SHA256 11 12 select CRYPTO_SHA512 12 13 select CRYPTO_CBC 13 14 select CRYPTO_CTS 14 15 select CRYPTO_AES 16 + select CRYPTO_CAMELLIA 15 17 help 16 18 Provide a library for provision of Kerberos-5-based crypto. This is 17 19 intended for network filesystems to use.
+1
crypto/krb5/Makefile
··· 8 8 krb5_api.o \ 9 9 rfc3961_simplified.o \ 10 10 rfc3962_aes.o \ 11 + rfc6803_camellia.o \ 11 12 rfc8009_aes2.o 12 13 13 14 obj-$(CONFIG_CRYPTO_KRB5) += krb5.o
+6
crypto/krb5/internal.h
··· 187 187 extern const struct krb5_enctype krb5_aes256_cts_hmac_sha1_96; 188 188 189 189 /* 190 + * rfc6803_camellia.c 191 + */ 192 + extern const struct krb5_enctype krb5_camellia128_cts_cmac; 193 + extern const struct krb5_enctype krb5_camellia256_cts_cmac; 194 + 195 + /* 190 196 * rfc8009_aes2.c 191 197 */ 192 198 extern const struct krb5_enctype krb5_aes128_cts_hmac_sha256_128;
+2
crypto/krb5/krb5_api.c
··· 21 21 &krb5_aes256_cts_hmac_sha1_96, 22 22 &krb5_aes128_cts_hmac_sha256_128, 23 23 &krb5_aes256_cts_hmac_sha384_192, 24 + &krb5_camellia128_cts_cmac, 25 + &krb5_camellia256_cts_cmac, 24 26 }; 25 27 26 28 /**
+237
crypto/krb5/rfc6803_camellia.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* rfc6803 Camellia Encryption for Kerberos 5 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/slab.h> 11 + #include "internal.h" 12 + 13 + /* 14 + * Calculate the key derivation function KDF-FEEDBACK_CMAC(key, constant) 15 + * 16 + * n = ceiling(k / 128) 17 + * K(0) = zeros 18 + * K(i) = CMAC(key, K(i-1) | i | constant | 0x00 | k) 19 + * DR(key, constant) = k-truncate(K(1) | K(2) | ... | K(n)) 20 + * KDF-FEEDBACK-CMAC(key, constant) = random-to-key(DR(key, constant)) 21 + * 22 + * [rfc6803 sec 3] 23 + */ 24 + static int rfc6803_calc_KDF_FEEDBACK_CMAC(const struct krb5_enctype *krb5, 25 + const struct krb5_buffer *key, 26 + const struct krb5_buffer *constant, 27 + struct krb5_buffer *result, 28 + gfp_t gfp) 29 + { 30 + struct crypto_shash *shash; 31 + struct krb5_buffer K, data; 32 + struct shash_desc *desc; 33 + __be32 tmp; 34 + size_t bsize, offset, seg; 35 + void *buffer; 36 + u32 i = 0, k = result->len * 8; 37 + u8 *p; 38 + int ret = -ENOMEM; 39 + 40 + shash = crypto_alloc_shash(krb5->cksum_name, 0, 0); 41 + if (IS_ERR(shash)) 42 + return (PTR_ERR(shash) == -ENOENT) ? -ENOPKG : PTR_ERR(shash); 43 + ret = crypto_shash_setkey(shash, key->data, key->len); 44 + if (ret < 0) 45 + goto error_shash; 46 + 47 + ret = -ENOMEM; 48 + K.len = crypto_shash_digestsize(shash); 49 + data.len = K.len + 4 + constant->len + 1 + 4; 50 + bsize = krb5_shash_size(shash) + 51 + krb5_digest_size(shash) + 52 + crypto_roundup(K.len) + 53 + crypto_roundup(data.len); 54 + buffer = kzalloc(bsize, GFP_NOFS); 55 + if (!buffer) 56 + goto error_shash; 57 + 58 + desc = buffer; 59 + desc->tfm = shash; 60 + 61 + K.data = buffer + 62 + krb5_shash_size(shash) + 63 + krb5_digest_size(shash); 64 + data.data = buffer + 65 + krb5_shash_size(shash) + 66 + krb5_digest_size(shash) + 67 + crypto_roundup(K.len); 68 + 69 + p = data.data + K.len + 4; 70 + memcpy(p, constant->data, constant->len); 71 + p += constant->len; 72 + *p++ = 0x00; 73 + tmp = htonl(k); 74 + memcpy(p, &tmp, 4); 75 + p += 4; 76 + 77 + ret = -EINVAL; 78 + if (WARN_ON(p - (u8 *)data.data != data.len)) 79 + goto error; 80 + 81 + offset = 0; 82 + do { 83 + i++; 84 + p = data.data; 85 + memcpy(p, K.data, K.len); 86 + p += K.len; 87 + *(__be32 *)p = htonl(i); 88 + 89 + ret = crypto_shash_init(desc); 90 + if (ret < 0) 91 + goto error; 92 + ret = crypto_shash_finup(desc, data.data, data.len, K.data); 93 + if (ret < 0) 94 + goto error; 95 + 96 + seg = min_t(size_t, result->len - offset, K.len); 97 + memcpy(result->data + offset, K.data, seg); 98 + offset += seg; 99 + } while (offset < result->len); 100 + 101 + error: 102 + kfree_sensitive(buffer); 103 + error_shash: 104 + crypto_free_shash(shash); 105 + return ret; 106 + } 107 + 108 + /* 109 + * Calculate the pseudo-random function, PRF(). 110 + * 111 + * Kp = KDF-FEEDBACK-CMAC(protocol-key, "prf") 112 + * PRF = CMAC(Kp, octet-string) 113 + * [rfc6803 sec 6] 114 + */ 115 + static int rfc6803_calc_PRF(const struct krb5_enctype *krb5, 116 + const struct krb5_buffer *protocol_key, 117 + const struct krb5_buffer *octet_string, 118 + struct krb5_buffer *result, 119 + gfp_t gfp) 120 + { 121 + static const struct krb5_buffer prfconstant = { 3, "prf" }; 122 + struct crypto_shash *shash; 123 + struct krb5_buffer Kp; 124 + struct shash_desc *desc; 125 + size_t bsize; 126 + void *buffer; 127 + int ret; 128 + 129 + Kp.len = krb5->prf_len; 130 + 131 + shash = crypto_alloc_shash(krb5->cksum_name, 0, 0); 132 + if (IS_ERR(shash)) 133 + return (PTR_ERR(shash) == -ENOENT) ? -ENOPKG : PTR_ERR(shash); 134 + 135 + ret = -EINVAL; 136 + if (result->len != crypto_shash_digestsize(shash)) 137 + goto out_shash; 138 + 139 + ret = -ENOMEM; 140 + bsize = krb5_shash_size(shash) + 141 + krb5_digest_size(shash) + 142 + crypto_roundup(Kp.len); 143 + buffer = kzalloc(bsize, GFP_NOFS); 144 + if (!buffer) 145 + goto out_shash; 146 + 147 + Kp.data = buffer + 148 + krb5_shash_size(shash) + 149 + krb5_digest_size(shash); 150 + 151 + ret = rfc6803_calc_KDF_FEEDBACK_CMAC(krb5, protocol_key, &prfconstant, 152 + &Kp, gfp); 153 + if (ret < 0) 154 + goto out; 155 + 156 + ret = crypto_shash_setkey(shash, Kp.data, Kp.len); 157 + if (ret < 0) 158 + goto out; 159 + 160 + desc = buffer; 161 + desc->tfm = shash; 162 + ret = crypto_shash_init(desc); 163 + if (ret < 0) 164 + goto out; 165 + 166 + ret = crypto_shash_finup(desc, octet_string->data, octet_string->len, result->data); 167 + if (ret < 0) 168 + goto out; 169 + 170 + out: 171 + kfree_sensitive(buffer); 172 + out_shash: 173 + crypto_free_shash(shash); 174 + return ret; 175 + } 176 + 177 + 178 + static const struct krb5_crypto_profile rfc6803_crypto_profile = { 179 + .calc_PRF = rfc6803_calc_PRF, 180 + .calc_Kc = rfc6803_calc_KDF_FEEDBACK_CMAC, 181 + .calc_Ke = rfc6803_calc_KDF_FEEDBACK_CMAC, 182 + .calc_Ki = rfc6803_calc_KDF_FEEDBACK_CMAC, 183 + .derive_encrypt_keys = authenc_derive_encrypt_keys, 184 + .load_encrypt_keys = authenc_load_encrypt_keys, 185 + .derive_checksum_key = rfc3961_derive_checksum_key, 186 + .load_checksum_key = rfc3961_load_checksum_key, 187 + .encrypt = krb5_aead_encrypt, 188 + .decrypt = krb5_aead_decrypt, 189 + .get_mic = rfc3961_get_mic, 190 + .verify_mic = rfc3961_verify_mic, 191 + }; 192 + 193 + const struct krb5_enctype krb5_camellia128_cts_cmac = { 194 + .etype = KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC, 195 + .ctype = KRB5_CKSUMTYPE_CMAC_CAMELLIA128, 196 + .name = "camellia128-cts-cmac", 197 + .encrypt_name = "krb5enc(cmac(camellia),cts(cbc(camellia)))", 198 + .cksum_name = "cmac(camellia)", 199 + .hash_name = NULL, 200 + .derivation_enc = "cts(cbc(camellia))", 201 + .key_bytes = 16, 202 + .key_len = 16, 203 + .Kc_len = 16, 204 + .Ke_len = 16, 205 + .Ki_len = 16, 206 + .block_len = 16, 207 + .conf_len = 16, 208 + .cksum_len = 16, 209 + .hash_len = 16, 210 + .prf_len = 16, 211 + .keyed_cksum = true, 212 + .random_to_key = NULL, /* Identity */ 213 + .profile = &rfc6803_crypto_profile, 214 + }; 215 + 216 + const struct krb5_enctype krb5_camellia256_cts_cmac = { 217 + .etype = KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC, 218 + .ctype = KRB5_CKSUMTYPE_CMAC_CAMELLIA256, 219 + .name = "camellia256-cts-cmac", 220 + .encrypt_name = "krb5enc(cmac(camellia),cts(cbc(camellia)))", 221 + .cksum_name = "cmac(camellia)", 222 + .hash_name = NULL, 223 + .derivation_enc = "cts(cbc(camellia))", 224 + .key_bytes = 32, 225 + .key_len = 32, 226 + .Kc_len = 32, 227 + .Ke_len = 32, 228 + .Ki_len = 32, 229 + .block_len = 16, 230 + .conf_len = 16, 231 + .cksum_len = 16, 232 + .hash_len = 16, 233 + .prf_len = 16, 234 + .keyed_cksum = true, 235 + .random_to_key = NULL, /* Identity */ 236 + .profile = &rfc6803_crypto_profile, 237 + };
+4
include/crypto/krb5.h
··· 35 35 #define KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192 0x0014 36 36 #define KRB5_ENCTYPE_ARCFOUR_HMAC 0x0017 37 37 #define KRB5_ENCTYPE_ARCFOUR_HMAC_EXP 0x0018 38 + #define KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC 0x0019 39 + #define KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC 0x001a 38 40 #define KRB5_ENCTYPE_UNKNOWN 0x01ff 39 41 40 42 #define KRB5_CKSUMTYPE_CRC32 0x0001 ··· 49 47 #define KRB5_CKSUMTYPE_HMAC_SHA1_DES3 0x000c 50 48 #define KRB5_CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f 51 49 #define KRB5_CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010 50 + #define KRB5_CKSUMTYPE_CMAC_CAMELLIA128 0x0011 51 + #define KRB5_CKSUMTYPE_CMAC_CAMELLIA256 0x0012 52 52 #define KRB5_CKSUMTYPE_HMAC_SHA256_128_AES128 0x0013 53 53 #define KRB5_CKSUMTYPE_HMAC_SHA384_192_AES256 0x0014 54 54 #define KRB5_CKSUMTYPE_HMAC_MD5_ARCFOUR -138 /* Microsoft md5 hmac cksumtype */