Skip to content

Commit 0ee8bcc

Browse files
committed
libceph: generalize ceph_x_encrypt_offset() and ceph_x_encrypt_buflen()
- introduce the notion of a data offset for ceph_x_encrypt_offset() to allow for e.g. confounder to be prepended before the encryption header in the future. For CEPH_CRYPTO_AES, the data offset is 0 (i.e. nothing is prepended). - adjust ceph_x_encrypt_buflen() accordingly and make it account for PKCS#7 padding that is used by CEPH_CRYPTO_AES precisely instead of just always adding 16. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
1 parent ac431d5 commit 0ee8bcc

3 files changed

Lines changed: 56 additions & 15 deletions

File tree

net/ceph/auth_x.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,35 @@ static int ceph_x_should_authenticate(struct ceph_auth_client *ac)
4444
return !!need;
4545
}
4646

47-
static int ceph_x_encrypt_offset(void)
47+
static int __ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
4848
{
49-
return sizeof(u32) + sizeof(struct ceph_x_encrypt_header);
49+
return ceph_crypt_data_offset(key) +
50+
sizeof(struct ceph_x_encrypt_header);
5051
}
5152

52-
static int ceph_x_encrypt_buflen(int ilen)
53+
static int ceph_x_encrypt_offset(const struct ceph_crypto_key *key)
5354
{
54-
return ceph_x_encrypt_offset() + ilen + 16;
55+
return sizeof(u32) + __ceph_x_encrypt_offset(key);
56+
}
57+
58+
/*
59+
* AES: ciphertext_len | hdr | data... | padding
60+
*/
61+
static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key,
62+
int data_len)
63+
{
64+
int encrypt_len = sizeof(struct ceph_x_encrypt_header) + data_len;
65+
return sizeof(u32) + ceph_crypt_buflen(key, encrypt_len);
5566
}
5667

5768
static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
5869
int buf_len, int plaintext_len)
5970
{
60-
struct ceph_x_encrypt_header *hdr = buf + sizeof(u32);
71+
struct ceph_x_encrypt_header *hdr;
6172
int ciphertext_len;
6273
int ret;
6374

75+
hdr = buf + sizeof(u32) + ceph_crypt_data_offset(secret);
6476
hdr->struct_v = 1;
6577
hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC);
6678

@@ -77,7 +89,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf,
7789
static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
7890
int ciphertext_len)
7991
{
80-
struct ceph_x_encrypt_header *hdr = p;
92+
struct ceph_x_encrypt_header *hdr;
8193
int plaintext_len;
8294
int ret;
8395

@@ -86,6 +98,7 @@ static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p,
8698
if (ret)
8799
return ret;
88100

101+
hdr = p + ceph_crypt_data_offset(secret);
89102
if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) {
90103
pr_err("%s bad magic\n", __func__);
91104
return -EINVAL;
@@ -193,7 +206,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
193206
}
194207

195208
/* blob for me */
196-
dp = *p + ceph_x_encrypt_offset();
209+
dp = *p + ceph_x_encrypt_offset(secret);
197210
ret = ceph_x_decrypt(secret, p, end);
198211
if (ret < 0)
199212
goto out;
@@ -220,7 +233,7 @@ static int process_one_ticket(struct ceph_auth_client *ac,
220233
ceph_decode_8_safe(p, end, is_enc, bad);
221234
if (is_enc) {
222235
/* encrypted */
223-
tp = *p + ceph_x_encrypt_offset();
236+
tp = *p + ceph_x_encrypt_offset(&th->session_key);
224237
ret = ceph_x_decrypt(&th->session_key, p, end);
225238
if (ret < 0)
226239
goto out;
@@ -312,7 +325,7 @@ static int encrypt_authorizer(struct ceph_x_authorizer *au,
312325
p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len);
313326
end = au->buf->vec.iov_base + au->buf->vec.iov_len;
314327

315-
msg_b = p + ceph_x_encrypt_offset();
328+
msg_b = p + ceph_x_encrypt_offset(&au->session_key);
316329
msg_b->struct_v = 2;
317330
msg_b->nonce = cpu_to_le64(au->nonce);
318331
if (server_challenge) {
@@ -368,7 +381,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac,
368381
goto out_au;
369382

370383
maxlen = sizeof(*msg_a) + ticket_blob_len +
371-
ceph_x_encrypt_buflen(sizeof(*msg_b));
384+
ceph_x_encrypt_buflen(&au->session_key, sizeof(*msg_b));
372385
dout(" need len %d\n", maxlen);
373386
if (au->buf && au->buf->alloc_len < maxlen) {
374387
ceph_buffer_put(au->buf);
@@ -507,7 +520,7 @@ static int ceph_x_build_request(struct ceph_auth_client *ac,
507520
struct ceph_x_authenticate *auth = (void *)(head + 1);
508521
void *enc_buf = xi->auth_authorizer.enc_buf;
509522
struct ceph_x_challenge_blob *blob = enc_buf +
510-
ceph_x_encrypt_offset();
523+
ceph_x_encrypt_offset(&xi->secret);
511524
u64 *u;
512525

513526
p = auth + 1;
@@ -634,7 +647,7 @@ static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id,
634647
ceph_decode_need(p, end, len, e_inval);
635648
dout("%s connection secret blob len %d\n", __func__, len);
636649
if (len > 0) {
637-
dp = *p + ceph_x_encrypt_offset();
650+
dp = *p + ceph_x_encrypt_offset(&th->session_key);
638651
ret = ceph_x_decrypt(&th->session_key, p, *p + len);
639652
if (ret < 0)
640653
return ret;
@@ -804,7 +817,7 @@ static int decrypt_authorizer_challenge(struct ceph_crypto_key *secret,
804817
return ret;
805818

806819
dout("%s decrypted %d bytes\n", __func__, ret);
807-
dp = challenge + sizeof(struct ceph_x_encrypt_header);
820+
dp = challenge + __ceph_x_encrypt_offset(secret);
808821
dend = dp + ret;
809822

810823
ceph_decode_skip_8(&dp, dend, e_inval); /* struct_v */
@@ -851,7 +864,7 @@ static int decrypt_authorizer_reply(struct ceph_crypto_key *secret,
851864
u8 struct_v;
852865
int ret;
853866

854-
dp = *p + ceph_x_encrypt_offset();
867+
dp = *p + ceph_x_encrypt_offset(secret);
855868
ret = ceph_x_decrypt(secret, p, end);
856869
if (ret < 0)
857870
return ret;
@@ -974,7 +987,8 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg,
974987
__le32 front_crc;
975988
__le32 middle_crc;
976989
__le32 data_crc;
977-
} __packed *sigblock = enc_buf + ceph_x_encrypt_offset();
990+
} __packed *sigblock = enc_buf +
991+
ceph_x_encrypt_offset(&au->session_key);
978992

979993
sigblock->len = cpu_to_le32(4*sizeof(u32));
980994
sigblock->header_crc = msg->hdr.crc;

net/ceph/crypto.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,31 @@ int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt,
285285
}
286286
}
287287

288+
int ceph_crypt_data_offset(const struct ceph_crypto_key *key)
289+
{
290+
switch (key->type) {
291+
case CEPH_CRYPTO_NONE:
292+
case CEPH_CRYPTO_AES:
293+
return 0;
294+
default:
295+
BUG();
296+
}
297+
}
298+
299+
int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len)
300+
{
301+
switch (key->type) {
302+
case CEPH_CRYPTO_NONE:
303+
return data_len;
304+
case CEPH_CRYPTO_AES:
305+
/* PKCS#7 padding at the end */
306+
return data_len + AES_BLOCK_SIZE -
307+
(data_len & (AES_BLOCK_SIZE - 1));
308+
default:
309+
BUG();
310+
}
311+
}
312+
288313
static int ceph_key_preparse(struct key_preparsed_payload *prep)
289314
{
290315
struct ceph_crypto_key *ckey;

net/ceph/crypto.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key);
2828
/* crypto.c */
2929
int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt,
3030
void *buf, int buf_len, int in_len, int *pout_len);
31+
int ceph_crypt_data_offset(const struct ceph_crypto_key *key);
32+
int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len);
3133
int ceph_crypto_init(void);
3234
void ceph_crypto_shutdown(void);
3335

0 commit comments

Comments
 (0)