From: Ilya Dryomov Date: Mon, 22 Dec 2025 18:44:24 +0000 (+0100) Subject: libceph: introduce ceph_crypto_key_prepare() X-Git-Tag: ceph-for-7.0-rc1~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6cec0b61aacce4da5125b21c718189f0dc11eb51;p=ceph-client.git libceph: introduce ceph_crypto_key_prepare() In preparation for bringing in a new encryption scheme/key type, decouple decoding or cloning the key from allocating required crypto API objects and setting them up. The rationale is that a) in some cases a shallow clone is sufficient and b) ceph_crypto_key_prepare() may grow additional parameters that would be inconvenient to provide at the point the key is originally decoded. Signed-off-by: Ilya Dryomov --- diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 5d7245884f95..abdd35be263a 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c @@ -221,6 +221,10 @@ static int process_one_ticket(struct ceph_auth_client *ac, if (ret) goto out; + ret = ceph_crypto_key_prepare(&new_session_key); + if (ret) + goto out; + ceph_decode_need(&dp, dend, sizeof(struct ceph_timespec), bad); ceph_decode_timespec64(&validity, dp); dp += sizeof(struct ceph_timespec); @@ -380,6 +384,10 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac, if (ret) goto out_au; + ret = ceph_crypto_key_prepare(&au->session_key); + if (ret) + goto out_au; + maxlen = sizeof(*msg_a) + ticket_blob_len + ceph_x_encrypt_buflen(&au->session_key, sizeof(*msg_b)); dout(" need len %d\n", maxlen); @@ -1106,21 +1114,26 @@ int ceph_x_init(struct ceph_auth_client *ac) int ret; dout("ceph_x_init %p\n", ac); - ret = -ENOMEM; xi = kzalloc(sizeof(*xi), GFP_NOFS); if (!xi) - goto out; + return -ENOMEM; ret = -EINVAL; if (!ac->key) { pr_err("no secret set (for auth_x protocol)\n"); - goto out_nomem; + goto err_xi; } ret = ceph_crypto_key_clone(&xi->secret, ac->key); if (ret < 0) { pr_err("cannot clone key: %d\n", ret); - goto out_nomem; + goto err_xi; + } + + ret = ceph_crypto_key_prepare(&xi->secret); + if (ret) { + pr_err("cannot prepare key: %d\n", ret); + goto err_secret; } xi->starting = true; @@ -1131,8 +1144,9 @@ int ceph_x_init(struct ceph_auth_client *ac) ac->ops = &ceph_x_ops; return 0; -out_nomem: +err_secret: + ceph_crypto_key_destroy(&xi->secret); +err_xi: kfree(xi); -out: return ret; } diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 2b98daffe9af..3453dc303315 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -16,65 +16,61 @@ #include #include "crypto.h" -/* - * Set ->key and ->tfm. The rest of the key should be filled in before - * this function is called. - */ -static int set_secret(struct ceph_crypto_key *key, void *buf) +static int set_aes_tfm(struct ceph_crypto_key *key) { unsigned int noio_flag; int ret; - key->key = NULL; - key->tfm = NULL; - - switch (key->type) { - case CEPH_CRYPTO_NONE: - return 0; /* nothing to do */ - case CEPH_CRYPTO_AES: - break; - default: - return -ENOTSUPP; - } - - key->key = kmemdup(buf, key->len, GFP_NOIO); - if (!key->key) { - ret = -ENOMEM; - goto fail; - } - - /* crypto_alloc_sync_skcipher() allocates with GFP_KERNEL */ noio_flag = memalloc_noio_save(); key->tfm = crypto_alloc_sync_skcipher("cbc(aes)", 0, 0); memalloc_noio_restore(noio_flag); if (IS_ERR(key->tfm)) { ret = PTR_ERR(key->tfm); key->tfm = NULL; - goto fail; + return ret; } ret = crypto_sync_skcipher_setkey(key->tfm, key->key, key->len); if (ret) - goto fail; + return ret; return 0; +} -fail: - ceph_crypto_key_destroy(key); - return ret; +int ceph_crypto_key_prepare(struct ceph_crypto_key *key) +{ + switch (key->type) { + case CEPH_CRYPTO_NONE: + return 0; /* nothing to do */ + case CEPH_CRYPTO_AES: + return set_aes_tfm(key); + default: + return -ENOTSUPP; + } } +/* + * @dst should be zeroed before this function is called. + */ int ceph_crypto_key_clone(struct ceph_crypto_key *dst, const struct ceph_crypto_key *src) { - memcpy(dst, src, sizeof(struct ceph_crypto_key)); - return set_secret(dst, src->key); + dst->type = src->type; + dst->created = src->created; + dst->len = src->len; + + dst->key = kmemdup(src->key, src->len, GFP_NOIO); + if (!dst->key) + return -ENOMEM; + + return 0; } +/* + * @key should be zeroed before this function is called. + */ int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) { - int ret; - ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad); key->type = ceph_decode_16(p); ceph_decode_copy(p, &key->created, sizeof(key->created)); @@ -85,10 +81,13 @@ int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end) return -EINVAL; } - ret = set_secret(key, *p); + key->key = kmemdup(*p, key->len, GFP_NOIO); + if (!key->key) + return -ENOMEM; + memzero_explicit(*p, key->len); *p += key->len; - return ret; + return 0; bad: dout("failed to decode crypto key\n"); @@ -322,7 +321,7 @@ static int ceph_key_preparse(struct key_preparsed_payload *prep) goto err; ret = -ENOMEM; - ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); + ckey = kzalloc(sizeof(*ckey), GFP_KERNEL); if (!ckey) goto err; diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 736ec6d2fbcb..2b8f8f68ff7a 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -19,6 +19,7 @@ struct ceph_crypto_key { struct crypto_sync_skcipher *tfm; }; +int ceph_crypto_key_prepare(struct ceph_crypto_key *key); int ceph_crypto_key_clone(struct ceph_crypto_key *dst, const struct ceph_crypto_key *src); int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end);