nvme-auth: use transformed key size to create resp
authorMark O'Donovan <shiftee@posteo.net>
Tue, 17 Oct 2023 17:09:18 +0000 (17:09 +0000)
committerKeith Busch <kbusch@kernel.org>
Tue, 17 Oct 2023 20:57:54 +0000 (13:57 -0700)
This does not change current behaviour as the driver currently
verifies that the secret size is the same size as the length of
the transformation hash.

Co-developed-by: Akash Appaiah <Akash.Appaiah@dell.com>
Signed-off-by: Akash Appaiah <Akash.Appaiah@dell.com>
Signed-off-by: Mark O'Donovan <shiftee@posteo.net>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Keith Busch <kbusch@kernel.org>
drivers/nvme/common/auth.c
drivers/nvme/host/auth.c
drivers/nvme/target/auth.c
include/linux/nvme-auth.h

index 16a071448d5401cbdf4efeb6c1b6f8b69ff579d2..f954aeb647a57efd17114f85856afdd91df8aa5c 100644 (file)
@@ -242,21 +242,25 @@ void nvme_auth_free_key(struct nvme_dhchap_key *key)
 }
 EXPORT_SYMBOL_GPL(nvme_auth_free_key);
 
-u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn)
+struct nvme_dhchap_key *nvme_auth_transform_key(
+               struct nvme_dhchap_key *key, char *nqn)
 {
        const char *hmac_name;
        struct crypto_shash *key_tfm;
        struct shash_desc *shash;
-       u8 *transformed_key;
-       int ret;
+       struct nvme_dhchap_key *transformed_key;
+       int ret, key_len;
 
        if (!key) {
                pr_warn("No key specified\n");
                return ERR_PTR(-ENOKEY);
        }
        if (key->hash == 0) {
-               transformed_key = kmemdup(key->key, key->len, GFP_KERNEL);
-               return transformed_key ? transformed_key : ERR_PTR(-ENOMEM);
+               key_len = nvme_auth_key_struct_size(key->len);
+               transformed_key = kmemdup(key, key_len, GFP_KERNEL);
+               if (!transformed_key)
+                       return ERR_PTR(-ENOMEM);
+               return transformed_key;
        }
        hmac_name = nvme_auth_hmac_name(key->hash);
        if (!hmac_name) {
@@ -266,7 +270,7 @@ u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn)
 
        key_tfm = crypto_alloc_shash(hmac_name, 0, 0);
        if (IS_ERR(key_tfm))
-               return (u8 *)key_tfm;
+               return ERR_CAST(key_tfm);
 
        shash = kmalloc(sizeof(struct shash_desc) +
                        crypto_shash_descsize(key_tfm),
@@ -276,7 +280,8 @@ u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn)
                goto out_free_key;
        }
 
-       transformed_key = kzalloc(crypto_shash_digestsize(key_tfm), GFP_KERNEL);
+       key_len = crypto_shash_digestsize(key_tfm);
+       transformed_key = nvme_auth_alloc_key(key_len, key->hash);
        if (!transformed_key) {
                ret = -ENOMEM;
                goto out_free_shash;
@@ -295,7 +300,7 @@ u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn)
        ret = crypto_shash_update(shash, "NVMe-over-Fabrics", 17);
        if (ret < 0)
                goto out_free_transformed_key;
-       ret = crypto_shash_final(shash, transformed_key);
+       ret = crypto_shash_final(shash, transformed_key->key);
        if (ret < 0)
                goto out_free_transformed_key;
 
@@ -305,7 +310,7 @@ u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn)
        return transformed_key;
 
 out_free_transformed_key:
-       kfree_sensitive(transformed_key);
+       nvme_auth_free_key(transformed_key);
 out_free_shash:
        kfree(shash);
 out_free_key:
index daf5d144a8eaf79f75feae225af1a57ea586ad81..de1390d705dc9dd20acb8586c19cc0d44109c324 100644 (file)
@@ -23,6 +23,7 @@ struct nvme_dhchap_queue_context {
        struct nvme_ctrl *ctrl;
        struct crypto_shash *shash_tfm;
        struct crypto_kpp *dh_tfm;
+       struct nvme_dhchap_key *transformed_key;
        void *buf;
        int qid;
        int error;
@@ -36,7 +37,6 @@ struct nvme_dhchap_queue_context {
        u8 c1[64];
        u8 c2[64];
        u8 response[64];
-       u8 *host_response;
        u8 *ctrl_key;
        u8 *host_key;
        u8 *sess_key;
@@ -428,12 +428,12 @@ static int nvme_auth_dhchap_setup_host_response(struct nvme_ctrl *ctrl,
        dev_dbg(ctrl->device, "%s: qid %d host response seq %u transaction %d\n",
                __func__, chap->qid, chap->s1, chap->transaction);
 
-       if (!chap->host_response) {
-               chap->host_response = nvme_auth_transform_key(ctrl->host_key,
+       if (!chap->transformed_key) {
+               chap->transformed_key = nvme_auth_transform_key(ctrl->host_key,
                                                ctrl->opts->host->nqn);
-               if (IS_ERR(chap->host_response)) {
-                       ret = PTR_ERR(chap->host_response);
-                       chap->host_response = NULL;
+               if (IS_ERR(chap->transformed_key)) {
+                       ret = PTR_ERR(chap->transformed_key);
+                       chap->transformed_key = NULL;
                        return ret;
                }
        } else {
@@ -442,7 +442,7 @@ static int nvme_auth_dhchap_setup_host_response(struct nvme_ctrl *ctrl,
        }
 
        ret = crypto_shash_setkey(chap->shash_tfm,
-                       chap->host_response, ctrl->host_key->len);
+                       chap->transformed_key->key, chap->transformed_key->len);
        if (ret) {
                dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
                         chap->qid, ret);
@@ -508,19 +508,19 @@ static int nvme_auth_dhchap_setup_ctrl_response(struct nvme_ctrl *ctrl,
                struct nvme_dhchap_queue_context *chap)
 {
        SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
-       u8 *ctrl_response;
+       struct nvme_dhchap_key *transformed_key;
        u8 buf[4], *challenge = chap->c2;
        int ret;
 
-       ctrl_response = nvme_auth_transform_key(ctrl->ctrl_key,
+       transformed_key = nvme_auth_transform_key(ctrl->ctrl_key,
                                ctrl->opts->subsysnqn);
-       if (IS_ERR(ctrl_response)) {
-               ret = PTR_ERR(ctrl_response);
+       if (IS_ERR(transformed_key)) {
+               ret = PTR_ERR(transformed_key);
                return ret;
        }
 
        ret = crypto_shash_setkey(chap->shash_tfm,
-                       ctrl_response, ctrl->ctrl_key->len);
+                       transformed_key->key, transformed_key->len);
        if (ret) {
                dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
                         chap->qid, ret);
@@ -586,7 +586,7 @@ static int nvme_auth_dhchap_setup_ctrl_response(struct nvme_ctrl *ctrl,
 out:
        if (challenge != chap->c2)
                kfree(challenge);
-       kfree(ctrl_response);
+       nvme_auth_free_key(transformed_key);
        return ret;
 }
 
@@ -648,8 +648,8 @@ gen_sesskey:
 
 static void nvme_auth_reset_dhchap(struct nvme_dhchap_queue_context *chap)
 {
-       kfree_sensitive(chap->host_response);
-       chap->host_response = NULL;
+       nvme_auth_free_key(chap->transformed_key);
+       chap->transformed_key = NULL;
        kfree_sensitive(chap->host_key);
        chap->host_key = NULL;
        chap->host_key_len = 0;
index 4dcddcf95279b3b56c7c04a542c29d0463287682..3ddbc3880cac8d327074fe8f923b9f257979c8bd 100644 (file)
@@ -267,7 +267,8 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
        struct shash_desc *shash;
        struct nvmet_ctrl *ctrl = req->sq->ctrl;
        const char *hash_name;
-       u8 *challenge = req->sq->dhchap_c1, *host_response;
+       u8 *challenge = req->sq->dhchap_c1;
+       struct nvme_dhchap_key *transformed_key;
        u8 buf[4];
        int ret;
 
@@ -291,14 +292,15 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
                goto out_free_tfm;
        }
 
-       host_response = nvme_auth_transform_key(ctrl->host_key, ctrl->hostnqn);
-       if (IS_ERR(host_response)) {
-               ret = PTR_ERR(host_response);
+       transformed_key = nvme_auth_transform_key(ctrl->host_key,
+                                                 ctrl->hostnqn);
+       if (IS_ERR(transformed_key)) {
+               ret = PTR_ERR(transformed_key);
                goto out_free_tfm;
        }
 
-       ret = crypto_shash_setkey(shash_tfm, host_response,
-                                 ctrl->host_key->len);
+       ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
+                                 transformed_key->len);
        if (ret)
                goto out_free_response;
 
@@ -365,7 +367,7 @@ out:
                kfree(challenge);
        kfree(shash);
 out_free_response:
-       kfree_sensitive(host_response);
+       nvme_auth_free_key(transformed_key);
 out_free_tfm:
        crypto_free_shash(shash_tfm);
        return 0;
@@ -378,7 +380,8 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
        struct shash_desc *shash;
        struct nvmet_ctrl *ctrl = req->sq->ctrl;
        const char *hash_name;
-       u8 *challenge = req->sq->dhchap_c2, *ctrl_response;
+       u8 *challenge = req->sq->dhchap_c2;
+       struct nvme_dhchap_key *transformed_key;
        u8 buf[4];
        int ret;
 
@@ -402,15 +405,15 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8 *response,
                goto out_free_tfm;
        }
 
-       ctrl_response = nvme_auth_transform_key(ctrl->ctrl_key,
+       transformed_key = nvme_auth_transform_key(ctrl->ctrl_key,
                                                ctrl->subsysnqn);
-       if (IS_ERR(ctrl_response)) {
-               ret = PTR_ERR(ctrl_response);
+       if (IS_ERR(transformed_key)) {
+               ret = PTR_ERR(transformed_key);
                goto out_free_tfm;
        }
 
-       ret = crypto_shash_setkey(shash_tfm, ctrl_response,
-                                 ctrl->ctrl_key->len);
+       ret = crypto_shash_setkey(shash_tfm, transformed_key->key,
+                                 transformed_key->len);
        if (ret)
                goto out_free_response;
 
@@ -474,7 +477,7 @@ out:
                kfree(challenge);
        kfree(shash);
 out_free_response:
-       kfree_sensitive(ctrl_response);
+       nvme_auth_free_key(transformed_key);
 out_free_tfm:
        crypto_free_shash(shash_tfm);
        return 0;
index a5ae9abe1ef6b5d6ad911ced3a8e96d07d9da542..c1d0bc5d9624461c5df4443d2e330d46377f4c2e 100644 (file)
@@ -29,7 +29,8 @@ struct nvme_dhchap_key *nvme_auth_extract_key(unsigned char *secret,
                                              u8 key_hash);
 void nvme_auth_free_key(struct nvme_dhchap_key *key);
 struct nvme_dhchap_key *nvme_auth_alloc_key(u32 len, u8 hash);
-u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn);
+struct nvme_dhchap_key *nvme_auth_transform_key(
+                               struct nvme_dhchap_key *key, char *nqn);
 int nvme_auth_generate_key(u8 *secret, struct nvme_dhchap_key **ret_key);
 int nvme_auth_augmented_challenge(u8 hmac_id, u8 *skey, size_t skey_len,
                                  u8 *challenge, u8 *aug, size_t hlen);