Skip to content

Commit b7cc142

Browse files
committed
libceph: add support for CEPH_CRYPTO_AES256KRB5
This is based on AES256-CTS-HMAC384-192 crypto algorithm per RFC 8009 (i.e. Kerberos 5, hence the name) with custom-defined key usage numbers. The implementation allows a given key to have/be linked to between one and three usage numbers. The existing CEPH_CRYPTO_AES remains in place and unchanged. The usage_slot parameter that needed to be added to ceph_crypt() and its wrappers is simply ignored there. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
1 parent 6cec0b6 commit b7cc142

6 files changed

Lines changed: 257 additions & 48 deletions

File tree

include/linux/ceph/ceph_fs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,9 @@ struct ceph_dir_layout {
8989
} __attribute__ ((packed));
9090

9191
/* crypto algorithms */
92-
#define CEPH_CRYPTO_NONE 0x0
93-
#define CEPH_CRYPTO_AES 0x1
92+
#define CEPH_CRYPTO_NONE 0x0
93+
#define CEPH_CRYPTO_AES 0x1
94+
#define CEPH_CRYPTO_AES256KRB5 0x2 /* AES256-CTS-HMAC384-192 */
9495

9596
#define CEPH_AES_IV "cephsageyudagreg"
9697

net/ceph/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ config CEPH_LIB
66
select CRYPTO_AES
77
select CRYPTO_CBC
88
select CRYPTO_GCM
9+
select CRYPTO_KRB5
910
select CRYPTO_LIB_SHA256
1011
select CRYPTO
1112
select KEYS

net/ceph/auth_x.c

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,22 @@
1717
#include "auth_x.h"
1818
#include "auth_x_protocol.h"
1919

20+
static const u32 ticket_key_usages[] = {
21+
CEPHX_KEY_USAGE_TICKET_SESSION_KEY,
22+
CEPHX_KEY_USAGE_TICKET_BLOB,
23+
CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET
24+
};
25+
26+
static const u32 authorizer_key_usages[] = {
27+
CEPHX_KEY_USAGE_AUTHORIZE,
28+
CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE,
29+
CEPHX_KEY_USAGE_AUTHORIZE_REPLY
30+
};
31+
32+
static const u32 client_key_usages[] = {
33+
CEPHX_KEY_USAGE_TICKET_SESSION_KEY
34+
};
35+
2036
static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed);
2137

2238
static int ceph_x_is_authenticated(struct ceph_auth_client *ac)
@@ -57,6 +73,7 @@ static int ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
5773

5874
/*
5975
* AES: ciphertext_len | hdr | data... | padding
76+
* AES256KRB5: ciphertext_len | confounder | hdr | data... | hmac
6077
*/
6178
static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key,
6279
int data_len)
@@ -65,19 +82,19 @@ static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key,
6582
return sizeof(u32) + ceph_crypt_buflen(key, encrypt_len);
6683
}
6784

68-
static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
69-
int buf_len, int plaintext_len)
85+
static int ceph_x_encrypt(const struct ceph_crypto_key *key, int usage_slot,
86+
void *buf, int buf_len, int plaintext_len)
7087
{
7188
struct ceph_x_encrypt_header *hdr;
7289
int ciphertext_len;
7390
int ret;
7491

75-
hdr = buf + sizeof(u32) + ceph_crypt_data_offset(secret);
92+
hdr = buf + sizeof(u32) + ceph_crypt_data_offset(key);
7693
hdr->struct_v = 1;
7794
hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC);
7895

79-
ret = ceph_crypt(secret, true, buf + sizeof(u32), buf_len - sizeof(u32),
80-
plaintext_len + sizeof(struct ceph_x_encrypt_header),
96+
ret = ceph_crypt(key, usage_slot, true, buf + sizeof(u32),
97+
buf_len - sizeof(u32), plaintext_len + sizeof(*hdr),
8198
&ciphertext_len);
8299
if (ret)
83100
return ret;
@@ -86,19 +103,19 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
86103
return sizeof(u32) + ciphertext_len;
87104
}
88105

89-
static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
90-
int ciphertext_len)
106+
static int __ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot,
107+
void *p, int ciphertext_len)
91108
{
92109
struct ceph_x_encrypt_header *hdr;
93110
int plaintext_len;
94111
int ret;
95112

96-
ret = ceph_crypt(secret, false, p, ciphertext_len, ciphertext_len,
97-
&plaintext_len);
113+
ret = ceph_crypt(key, usage_slot, false, p, ciphertext_len,
114+
ciphertext_len, &plaintext_len);
98115
if (ret)
99116
return ret;
100117

101-
hdr = p + ceph_crypt_data_offset(secret);
118+
hdr = p + ceph_crypt_data_offset(key);
102119
if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) {
103120
pr_err("%s bad magic\n", __func__);
104121
return -EINVAL;
@@ -107,15 +124,16 @@ static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
107124
return plaintext_len - sizeof(*hdr);
108125
}
109126

110-
static int ceph_x_decrypt(struct ceph_crypto_key *secret, void **p, void *end)
127+
static int ceph_x_decrypt(const struct ceph_crypto_key *key, int usage_slot,
128+
void **p, void *end)
111129
{
112130
int ciphertext_len;
113131
int ret;
114132

115133
ceph_decode_32_safe(p, end, ciphertext_len, e_inval);
116134
ceph_decode_need(p, end, ciphertext_len, e_inval);
117135

118-
ret = __ceph_x_decrypt(secret, *p, ciphertext_len);
136+
ret = __ceph_x_decrypt(key, usage_slot, *p, ciphertext_len);
119137
if (ret < 0)
120138
return ret;
121139

@@ -207,7 +225,9 @@ static int process_one_ticket(struct ceph_auth_client *ac,
207225

208226
/* blob for me */
209227
dp = *p + ceph_x_encrypt_offset(secret);
210-
ret = ceph_x_decrypt(secret, p, end);
228+
ret = ceph_x_decrypt(secret,
229+
0 /* CEPHX_KEY_USAGE_TICKET_SESSION_KEY */,
230+
p, end);
211231
if (ret < 0)
212232
goto out;
213233
dout(" decrypted %d bytes\n", ret);
@@ -221,7 +241,8 @@ static int process_one_ticket(struct ceph_auth_client *ac,
221241
if (ret)
222242
goto out;
223243

224-
ret = ceph_crypto_key_prepare(&new_session_key);
244+
ret = ceph_crypto_key_prepare(&new_session_key, ticket_key_usages,
245+
ARRAY_SIZE(ticket_key_usages));
225246
if (ret)
226247
goto out;
227248

@@ -238,7 +259,9 @@ static int process_one_ticket(struct ceph_auth_client *ac,
238259
if (is_enc) {
239260
/* encrypted */
240261
tp = *p + ceph_x_encrypt_offset(&th->session_key);
241-
ret = ceph_x_decrypt(&th->session_key, p, end);
262+
ret = ceph_x_decrypt(&th->session_key,
263+
1 /* CEPHX_KEY_USAGE_TICKET_BLOB */,
264+
p, end);
242265
if (ret < 0)
243266
goto out;
244267
dout(" encrypted ticket, decrypted %d bytes\n", ret);
@@ -341,7 +364,9 @@ static int encrypt_authorizer(struct ceph_x_authorizer *au,
341364
msg_b->server_challenge_plus_one = 0;
342365
}
343366

344-
ret = ceph_x_encrypt(&au->session_key, p, end - p, sizeof(*msg_b));
367+
ret = ceph_x_encrypt(&au->session_key,
368+
0 /* CEPHX_KEY_USAGE_AUTHORIZE */,
369+
p, end - p, sizeof(*msg_b));
345370
if (ret < 0)
346371
return ret;
347372

@@ -384,7 +409,8 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
384409
if (ret)
385410
goto out_au;
386411

387-
ret = ceph_crypto_key_prepare(&au->session_key);
412+
ret = ceph_crypto_key_prepare(&au->session_key, authorizer_key_usages,
413+
ARRAY_SIZE(authorizer_key_usages));
388414
if (ret)
389415
goto out_au;
390416

@@ -542,7 +568,8 @@ static int ceph_x_build_request(struct ceph_auth_client *ac,
542568
get_random_bytes(&auth->client_challenge, sizeof(u64));
543569
blob->client_challenge = auth->client_challenge;
544570
blob->server_challenge = cpu_to_le64(xi->server_challenge);
545-
ret = ceph_x_encrypt(&xi->secret, enc_buf, CEPHX_AU_ENC_BUF_LEN,
571+
ret = ceph_x_encrypt(&xi->secret, 0 /* dummy */,
572+
enc_buf, CEPHX_AU_ENC_BUF_LEN,
546573
sizeof(*blob));
547574
if (ret < 0)
548575
return ret;
@@ -656,7 +683,9 @@ static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
656683
dout("%s connection secret blob len %d\n", __func__, len);
657684
if (len > 0) {
658685
dp = *p + ceph_x_encrypt_offset(&th->session_key);
659-
ret = ceph_x_decrypt(&th->session_key, p, *p + len);
686+
ret = ceph_x_decrypt(&th->session_key,
687+
2 /* CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET */,
688+
p, *p + len);
660689
if (ret < 0)
661690
return ret;
662691

@@ -820,7 +849,9 @@ static int decrypt_authorizer_challenge(struct ceph_crypto_key *secret,
820849
int ret;
821850

822851
/* no leading len */
823-
ret = __ceph_x_decrypt(secret, challenge, challenge_len);
852+
ret = __ceph_x_decrypt(secret,
853+
1 /* CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE */,
854+
challenge, challenge_len);
824855
if (ret < 0)
825856
return ret;
826857

@@ -873,7 +904,8 @@ static int decrypt_authorizer_reply(struct ceph_crypto_key *secret,
873904
int ret;
874905

875906
dp = *p + ceph_x_encrypt_offset(secret);
876-
ret = ceph_x_decrypt(secret, p, end);
907+
ret = ceph_x_decrypt(secret, 2 /* CEPHX_KEY_USAGE_AUTHORIZE_REPLY */,
908+
p, end);
877909
if (ret < 0)
878910
return ret;
879911

@@ -1004,8 +1036,9 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
10041036
sigblock->middle_crc = msg->footer.middle_crc;
10051037
sigblock->data_crc = msg->footer.data_crc;
10061038

1007-
ret = ceph_x_encrypt(&au->session_key, enc_buf,
1008-
CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock));
1039+
ret = ceph_x_encrypt(&au->session_key, 0 /* dummy */,
1040+
enc_buf, CEPHX_AU_ENC_BUF_LEN,
1041+
sizeof(*sigblock));
10091042
if (ret < 0)
10101043
return ret;
10111044

@@ -1036,9 +1069,9 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
10361069
sigblock->seq_lower_word = *(__le32 *)&msg->hdr.seq;
10371070

10381071
/* no leading len, no ceph_x_encrypt_header */
1039-
ret = ceph_crypt(&au->session_key, true, enc_buf,
1040-
CEPHX_AU_ENC_BUF_LEN, sizeof(*sigblock),
1041-
&ciphertext_len);
1072+
ret = ceph_crypt(&au->session_key, 0 /* dummy */,
1073+
true, enc_buf, CEPHX_AU_ENC_BUF_LEN,
1074+
sizeof(*sigblock), &ciphertext_len);
10421075
if (ret)
10431076
return ret;
10441077

@@ -1130,7 +1163,8 @@ int ceph_x_init(struct ceph_auth_client *ac)
11301163
goto err_xi;
11311164
}
11321165

1133-
ret = ceph_crypto_key_prepare(&xi->secret);
1166+
ret = ceph_crypto_key_prepare(&xi->secret, client_key_usages,
1167+
ARRAY_SIZE(client_key_usages));
11341168
if (ret) {
11351169
pr_err("cannot prepare key: %d\n", ret);
11361170
goto err_secret;

net/ceph/auth_x_protocol.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,44 @@
66
#define CEPHX_GET_PRINCIPAL_SESSION_KEY 0x0200
77
#define CEPHX_GET_ROTATING_KEY 0x0400
88

9+
/* Client <-> AuthMonitor */
10+
/*
11+
* The AUTH session's connection secret: encrypted with the AUTH
12+
* ticket session key
13+
*/
14+
#define CEPHX_KEY_USAGE_AUTH_CONNECTION_SECRET 0x03
15+
/*
16+
* The ticket's blob for the client ("blob for me", contains the
17+
* session key): encrypted with the client's secret key in case of
18+
* the AUTH ticket and the AUTH ticket session key in case of other
19+
* service tickets
20+
*/
21+
#define CEPHX_KEY_USAGE_TICKET_SESSION_KEY 0x04
22+
/*
23+
* The ticket's blob for the service (ceph_x_ticket_blob): possibly
24+
* encrypted with the old AUTH ticket session key in case of the AUTH
25+
* ticket and not encrypted in case of other service tickets
26+
*/
27+
#define CEPHX_KEY_USAGE_TICKET_BLOB 0x05
28+
29+
/* Client <-> Service */
30+
/*
31+
* The client's authorization request (ceph_x_authorize_b):
32+
* encrypted with the service ticket session key
33+
*/
34+
#define CEPHX_KEY_USAGE_AUTHORIZE 0x10
35+
/*
36+
* The service's challenge (ceph_x_authorize_challenge):
37+
* encrypted with the service ticket session key
38+
*/
39+
#define CEPHX_KEY_USAGE_AUTHORIZE_CHALLENGE 0x11
40+
/*
41+
* The service's final reply (ceph_x_authorize_reply + the service
42+
* session's connection secret): encrypted with the service ticket
43+
* session key
44+
*/
45+
#define CEPHX_KEY_USAGE_AUTHORIZE_REPLY 0x12
46+
947
/* common bits */
1048
struct ceph_x_ticket_blob {
1149
__u8 struct_v;

0 commit comments

Comments
 (0)