]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
introduce ceph_crypto_key_prepare()
authorIlya Dryomov <idryomov@gmail.com>
Mon, 22 Dec 2025 18:44:24 +0000 (19:44 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Tue, 6 Jan 2026 02:22:04 +0000 (03:22 +0100)
net/ceph/auth_x.c
net/ceph/crypto.c
net/ceph/crypto.h

index 5d7245884f9551febc086737e7782fb95a874399..abdd35be263a2d548e835061b189ee131eafac31 100644 (file)
@@ -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;
 }
index 2b98daffe9af738131cf116c9c41660bb470d2b2..3453dc3033156851fe134106c848f2c11d803e81 100644 (file)
 #include <linux/ceph/decode.h>
 #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;
 
index 736ec6d2fbcb206a7ab429631d8e1a680e92d990..2b8f8f68ff7a8c5461e6bd4b485fb7cd59e4a38f 100644 (file)
@@ -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);