From: Ilya Dryomov Date: Sat, 5 Jul 2025 09:28:21 +0000 (+0200) Subject: libceph: generalize ceph_x_encrypt_offset() and ceph_x_encrypt_buflen() X-Git-Tag: ceph-for-7.0-rc1~9 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0ee8bccf7396d50726c9c8dd3135fb64a9fe8426;p=ceph-client.git 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 --- diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index a21c157daf7d..5d7245884f95 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c @@ -44,23 +44,35 @@ static int ceph_x_should_authenticate(struct ceph_auth_client *ac) return !!need; } -static int ceph_x_encrypt_offset(void) +static int __ceph_x_encrypt_offset(const struct ceph_crypto_key *key) { - return sizeof(u32) + sizeof(struct ceph_x_encrypt_header); + return ceph_crypt_data_offset(key) + + sizeof(struct ceph_x_encrypt_header); } -static int ceph_x_encrypt_buflen(int ilen) +static int ceph_x_encrypt_offset(const struct ceph_crypto_key *key) { - return ceph_x_encrypt_offset() + ilen + 16; + return sizeof(u32) + __ceph_x_encrypt_offset(key); +} + +/* + * AES: ciphertext_len | hdr | data... | padding + */ +static int ceph_x_encrypt_buflen(const struct ceph_crypto_key *key, + int data_len) +{ + int encrypt_len = sizeof(struct ceph_x_encrypt_header) + data_len; + return sizeof(u32) + ceph_crypt_buflen(key, encrypt_len); } static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf, int buf_len, int plaintext_len) { - struct ceph_x_encrypt_header *hdr = buf + sizeof(u32); + struct ceph_x_encrypt_header *hdr; int ciphertext_len; int ret; + hdr = buf + sizeof(u32) + ceph_crypt_data_offset(secret); hdr->struct_v = 1; hdr->magic = cpu_to_le64(CEPHX_ENC_MAGIC); @@ -77,7 +89,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, void *buf, static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p, int ciphertext_len) { - struct ceph_x_encrypt_header *hdr = p; + struct ceph_x_encrypt_header *hdr; int plaintext_len; int ret; @@ -86,6 +98,7 @@ static int __ceph_x_decrypt(struct ceph_crypto_key *secret, void *p, if (ret) return ret; + hdr = p + ceph_crypt_data_offset(secret); if (le64_to_cpu(hdr->magic) != CEPHX_ENC_MAGIC) { pr_err("%s bad magic\n", __func__); return -EINVAL; @@ -193,7 +206,7 @@ static int process_one_ticket(struct ceph_auth_client *ac, } /* blob for me */ - dp = *p + ceph_x_encrypt_offset(); + dp = *p + ceph_x_encrypt_offset(secret); ret = ceph_x_decrypt(secret, p, end); if (ret < 0) goto out; @@ -220,7 +233,7 @@ static int process_one_ticket(struct ceph_auth_client *ac, ceph_decode_8_safe(p, end, is_enc, bad); if (is_enc) { /* encrypted */ - tp = *p + ceph_x_encrypt_offset(); + tp = *p + ceph_x_encrypt_offset(&th->session_key); ret = ceph_x_decrypt(&th->session_key, p, end); if (ret < 0) goto out; @@ -312,7 +325,7 @@ static int encrypt_authorizer(struct ceph_x_authorizer *au, p = (void *)(msg_a + 1) + le32_to_cpu(msg_a->ticket_blob.blob_len); end = au->buf->vec.iov_base + au->buf->vec.iov_len; - msg_b = p + ceph_x_encrypt_offset(); + msg_b = p + ceph_x_encrypt_offset(&au->session_key); msg_b->struct_v = 2; msg_b->nonce = cpu_to_le64(au->nonce); if (server_challenge) { @@ -368,7 +381,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac, goto out_au; maxlen = sizeof(*msg_a) + ticket_blob_len + - ceph_x_encrypt_buflen(sizeof(*msg_b)); + ceph_x_encrypt_buflen(&au->session_key, sizeof(*msg_b)); dout(" need len %d\n", maxlen); if (au->buf && au->buf->alloc_len < maxlen) { ceph_buffer_put(au->buf); @@ -507,7 +520,7 @@ static int ceph_x_build_request(struct ceph_auth_client *ac, struct ceph_x_authenticate *auth = (void *)(head + 1); void *enc_buf = xi->auth_authorizer.enc_buf; struct ceph_x_challenge_blob *blob = enc_buf + - ceph_x_encrypt_offset(); + ceph_x_encrypt_offset(&xi->secret); u64 *u; p = auth + 1; @@ -634,7 +647,7 @@ static int handle_auth_session_key(struct ceph_auth_client *ac, u64 global_id, ceph_decode_need(p, end, len, e_inval); dout("%s connection secret blob len %d\n", __func__, len); if (len > 0) { - dp = *p + ceph_x_encrypt_offset(); + dp = *p + ceph_x_encrypt_offset(&th->session_key); ret = ceph_x_decrypt(&th->session_key, p, *p + len); if (ret < 0) return ret; @@ -804,7 +817,7 @@ static int decrypt_authorizer_challenge(struct ceph_crypto_key *secret, return ret; dout("%s decrypted %d bytes\n", __func__, ret); - dp = challenge + sizeof(struct ceph_x_encrypt_header); + dp = challenge + __ceph_x_encrypt_offset(secret); dend = dp + ret; ceph_decode_skip_8(&dp, dend, e_inval); /* struct_v */ @@ -851,7 +864,7 @@ static int decrypt_authorizer_reply(struct ceph_crypto_key *secret, u8 struct_v; int ret; - dp = *p + ceph_x_encrypt_offset(); + dp = *p + ceph_x_encrypt_offset(secret); ret = ceph_x_decrypt(secret, p, end); if (ret < 0) return ret; @@ -974,7 +987,8 @@ static int calc_signature(struct ceph_x_authorizer *au, struct ceph_msg *msg, __le32 front_crc; __le32 middle_crc; __le32 data_crc; - } __packed *sigblock = enc_buf + ceph_x_encrypt_offset(); + } __packed *sigblock = enc_buf + + ceph_x_encrypt_offset(&au->session_key); sigblock->len = cpu_to_le32(4*sizeof(u32)); sigblock->header_crc = msg->hdr.crc; diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 5601732cf4fa..2b98daffe9af 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -285,6 +285,31 @@ int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt, } } +int ceph_crypt_data_offset(const struct ceph_crypto_key *key) +{ + switch (key->type) { + case CEPH_CRYPTO_NONE: + case CEPH_CRYPTO_AES: + return 0; + default: + BUG(); + } +} + +int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len) +{ + switch (key->type) { + case CEPH_CRYPTO_NONE: + return data_len; + case CEPH_CRYPTO_AES: + /* PKCS#7 padding at the end */ + return data_len + AES_BLOCK_SIZE - + (data_len & (AES_BLOCK_SIZE - 1)); + default: + BUG(); + } +} + static int ceph_key_preparse(struct key_preparsed_payload *prep) { struct ceph_crypto_key *ckey; diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index a20bad6d1e96..736ec6d2fbcb 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -28,6 +28,8 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key); /* crypto.c */ int ceph_crypt(const struct ceph_crypto_key *key, bool encrypt, void *buf, int buf_len, int in_len, int *pout_len); +int ceph_crypt_data_offset(const struct ceph_crypto_key *key); +int ceph_crypt_buflen(const struct ceph_crypto_key *key, int data_len); int ceph_crypto_init(void); void ceph_crypto_shutdown(void);