Skip to content

Commit 742e38d

Browse files
committed
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
1 parent 6c3c0e8 commit 742e38d

6 files changed

Lines changed: 252 additions & 0 deletions

File tree

crypto/krb5/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ config CRYPTO_KRB5
66
select CRYPTO_SKCIPHER
77
select CRYPTO_HASH_INFO
88
select CRYPTO_HMAC
9+
select CRYPTO_CMAC
910
select CRYPTO_SHA1
1011
select CRYPTO_SHA256
1112
select CRYPTO_SHA512
1213
select CRYPTO_CBC
1314
select CRYPTO_CTS
1415
select CRYPTO_AES
16+
select CRYPTO_CAMELLIA
1517
help
1618
Provide a library for provision of Kerberos-5-based crypto. This is
1719
intended for network filesystems to use.

crypto/krb5/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ krb5-y += \
88
krb5_api.o \
99
rfc3961_simplified.o \
1010
rfc3962_aes.o \
11+
rfc6803_camellia.o \
1112
rfc8009_aes2.o
1213

1314
obj-$(CONFIG_CRYPTO_KRB5) += krb5.o

crypto/krb5/internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,12 @@ int rfc3961_verify_mic(const struct krb5_enctype *krb5,
186186
extern const struct krb5_enctype krb5_aes128_cts_hmac_sha1_96;
187187
extern const struct krb5_enctype krb5_aes256_cts_hmac_sha1_96;
188188

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+
189195
/*
190196
* rfc8009_aes2.c
191197
*/

crypto/krb5/krb5_api.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ static const struct krb5_enctype *const krb5_supported_enctypes[] = {
2121
&krb5_aes256_cts_hmac_sha1_96,
2222
&krb5_aes128_cts_hmac_sha256_128,
2323
&krb5_aes256_cts_hmac_sha384_192,
24+
&krb5_camellia128_cts_cmac,
25+
&krb5_camellia256_cts_cmac,
2426
};
2527

2628
/**

crypto/krb5/rfc6803_camellia.c

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
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+
};

include/crypto/krb5.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ struct scatterlist;
3535
#define KRB5_ENCTYPE_AES256_CTS_HMAC_SHA384_192 0x0014
3636
#define KRB5_ENCTYPE_ARCFOUR_HMAC 0x0017
3737
#define KRB5_ENCTYPE_ARCFOUR_HMAC_EXP 0x0018
38+
#define KRB5_ENCTYPE_CAMELLIA128_CTS_CMAC 0x0019
39+
#define KRB5_ENCTYPE_CAMELLIA256_CTS_CMAC 0x001a
3840
#define KRB5_ENCTYPE_UNKNOWN 0x01ff
3941

4042
#define KRB5_CKSUMTYPE_CRC32 0x0001
@@ -47,6 +49,8 @@ struct scatterlist;
4749
#define KRB5_CKSUMTYPE_HMAC_SHA1_DES3 0x000c
4850
#define KRB5_CKSUMTYPE_HMAC_SHA1_96_AES128 0x000f
4951
#define KRB5_CKSUMTYPE_HMAC_SHA1_96_AES256 0x0010
52+
#define KRB5_CKSUMTYPE_CMAC_CAMELLIA128 0x0011
53+
#define KRB5_CKSUMTYPE_CMAC_CAMELLIA256 0x0012
5054
#define KRB5_CKSUMTYPE_HMAC_SHA256_128_AES128 0x0013
5155
#define KRB5_CKSUMTYPE_HMAC_SHA384_192_AES256 0x0014
5256
#define KRB5_CKSUMTYPE_HMAC_MD5_ARCFOUR -138 /* Microsoft md5 hmac cksumtype */

0 commit comments

Comments
 (0)