All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chaitanya Kulkarni <chaitanyak@nvidia.com>
To: Hannes Reinecke <hare@suse.de>, Sagi Grimberg <sagi@grimberg.me>
Cc: Christoph Hellwig <hch@lst.de>, Keith Busch <keith.busch@wdc.com>,
	"linux-nvme@lists.infradead.org" <linux-nvme@lists.infradead.org>
Subject: Re: [PATCH 06/11] nvme: Implement In-Band authentication
Date: Thu, 24 Mar 2022 16:53:35 +0000	[thread overview]
Message-ID: <fb9d1fb7-98e8-f592-8acc-997292097345@nvidia.com> (raw)
In-Reply-To: <20220323071303.14671-7-hare@suse.de>

On 3/23/22 00:12, Hannes Reinecke wrote:
> Implement NVMe-oF In-Band authentication according to NVMe TPAR 8006.
> This patch adds two new fabric options 'dhchap_secret' to specify the
> pre-shared key (in ASCII respresentation according to NVMe 2.0 section
> 8.13.5.8 'Secret representation') and 'dhchap_ctrl_secret' to specify
> the pre-shared controller key for bi-directional authentication of both
> the host and the controller.
> Re-authentication can be triggered by writing the PSK into the new
> controller sysfs attribute 'dhchap_secret' or 'dhchap_ctrl_secret'.
> 
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
>   drivers/nvme/host/Kconfig   |   11 +
>   drivers/nvme/host/Makefile  |    1 +
>   drivers/nvme/host/auth.c    | 1140 +++++++++++++++++++++++++++++++++++
>   drivers/nvme/host/auth.h    |   32 +
>   drivers/nvme/host/core.c    |  141 ++++-
>   drivers/nvme/host/fabrics.c |   79 ++-
>   drivers/nvme/host/fabrics.h |    7 +
>   drivers/nvme/host/nvme.h    |   31 +
>   drivers/nvme/host/rdma.c    |    1 +
>   drivers/nvme/host/tcp.c     |    1 +
>   drivers/nvme/host/trace.c   |   32 +
>   11 files changed, 1469 insertions(+), 7 deletions(-)
>   create mode 100644 drivers/nvme/host/auth.c
>   create mode 100644 drivers/nvme/host/auth.h
> 
> diff --git a/drivers/nvme/host/Kconfig b/drivers/nvme/host/Kconfig
> index d6d056963c06..dd0e91fb0615 100644
> --- a/drivers/nvme/host/Kconfig
> +++ b/drivers/nvme/host/Kconfig
> @@ -91,3 +91,14 @@ config NVME_TCP
>   	  from https://github.com/linux-nvme/nvme-cli.
>   
>   	  If unsure, say N.
> +
> +config NVME_AUTH
> +	bool "NVM Express over Fabrics In-Band Authentication"
> +	depends on NVME_CORE
> +	select CRYPTO_HMAC
> +	select CRYPTO_SHA256
> +	select CRYPTO_SHA512
> +	help
> +	  This provides support for NVMe over Fabrics In-Band Authentication.
> +
> +	  If unsure, say N.
> diff --git a/drivers/nvme/host/Makefile b/drivers/nvme/host/Makefile
> index 476c5c988496..7755f5e3b281 100644
> --- a/drivers/nvme/host/Makefile
> +++ b/drivers/nvme/host/Makefile
> @@ -15,6 +15,7 @@ nvme-core-$(CONFIG_NVME_MULTIPATH)	+= multipath.o
>   nvme-core-$(CONFIG_BLK_DEV_ZONED)	+= zns.o
>   nvme-core-$(CONFIG_FAULT_INJECTION_DEBUG_FS)	+= fault_inject.o
>   nvme-core-$(CONFIG_NVME_HWMON)		+= hwmon.o
> +nvme-core-$(CONFIG_NVME_AUTH)		+= auth.o
>   
>   nvme-y					+= pci.o
>   
> diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c
> new file mode 100644
> index 000000000000..4bca4ba1ccea
> --- /dev/null
> +++ b/drivers/nvme/host/auth.c
> @@ -0,0 +1,1140 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2020 Hannes Reinecke, SUSE Linux
> + */
> +
> +#include <linux/crc32.h>
> +#include <linux/base64.h>
> +#include <linux/prandom.h>
> +#include <asm/unaligned.h>
> +#include <crypto/hash.h>
> +#include <crypto/dh.h>
> +#include "nvme.h"
> +#include "fabrics.h"
> +#include "auth.h"
> +
> +static u32 nvme_dhchap_seqnum;
> +static DEFINE_MUTEX(nvme_dhchap_mutex);
> +
> +struct nvme_dhchap_queue_context {
> +	struct list_head entry;
> +	struct work_struct auth_work;
> +	struct nvme_ctrl *ctrl;
> +	struct crypto_shash *shash_tfm;
> +	void *buf;
> +	size_t buf_size;
> +	int qid;
> +	int error;
> +	u32 s1;
> +	u32 s2;
> +	u16 transaction;
> +	u8 status;
> +	u8 hash_id;
> +	size_t hash_len;
> +	u8 dhgroup_id;
> +	u8 c1[64];
> +	u8 c2[64];
> +	u8 response[64];
> +	u8 *host_response;
> +};
> +
> +u32 nvme_auth_get_seqnum(void)
> +{
> +	u32 seqnum;
> +
> +	mutex_lock(&nvme_dhchap_mutex);
> +	if (!nvme_dhchap_seqnum)
> +		nvme_dhchap_seqnum = prandom_u32();
> +	else {
> +		nvme_dhchap_seqnum++;
> +		if (!nvme_dhchap_seqnum)
> +			nvme_dhchap_seqnum++;
> +	}
> +	seqnum = nvme_dhchap_seqnum;
> +	mutex_unlock(&nvme_dhchap_mutex);
> +	return seqnum;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_get_seqnum);
> +
> +static struct nvme_auth_dhgroup_map {
> +	u8 id;
> +	const char name[16];
> +	const char kpp[16];
> +} dhgroup_map[] = {
> +	{ .id = NVME_AUTH_DHGROUP_NULL,
> +	  .name = "null", .kpp = "null" },
> +	{ .id = NVME_AUTH_DHGROUP_2048,
> +	  .name = "ffdhe2048", .kpp = "ffdhe2048(dh)" },
> +	{ .id = NVME_AUTH_DHGROUP_3072,
> +	  .name = "ffdhe3072", .kpp = "ffdhe3072(dh)" },
> +	{ .id = NVME_AUTH_DHGROUP_4096,
> +	  .name = "ffdhe4096", .kpp = "ffdhe4096(dh)" },
> +	{ .id = NVME_AUTH_DHGROUP_6144,
> +	  .name = "ffdhe6144", .kpp = "ffdhe6144(dh)" },
> +	{ .id = NVME_AUTH_DHGROUP_8192,
> +	  .name = "ffdhe8192", .kpp = "ffdhe8192(dh)" },
> +};
> +
> +const char *nvme_auth_dhgroup_name(u8 dhgroup_id)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
> +		if (dhgroup_map[i].id == dhgroup_id)
> +			return dhgroup_map[i].name;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_name);
> +
> +const char *nvme_auth_dhgroup_kpp(u8 dhgroup_id)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
> +		if (dhgroup_map[i].id == dhgroup_id)
> +			return dhgroup_map[i].kpp;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_kpp);
> +
> +u8 nvme_auth_dhgroup_id(const char *dhgroup_name)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
> +		if (!strncmp(dhgroup_map[i].name, dhgroup_name,
> +			     strlen(dhgroup_map[i].name)))
> +			return dhgroup_map[i].id;
> +	}
> +	return NVME_AUTH_DHGROUP_INVALID;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_id);
> +
> +static struct nvme_dhchap_hash_map {
> +	int id;
> +	int len;
> +	const char hmac[15];
> +	const char digest[15];
> +} hash_map[] = {
> +	{.id = NVME_AUTH_HASH_SHA256, .len = 32,
> +	 .hmac = "hmac(sha256)", .digest = "sha256" },
> +	{.id = NVME_AUTH_HASH_SHA384, .len = 48,
> +	 .hmac = "hmac(sha384)", .digest = "sha384" },
> +	{.id = NVME_AUTH_HASH_SHA512, .len = 64,
> +	 .hmac = "hmac(sha512)", .digest = "sha512" },
> +};
> +
> +const char *nvme_auth_hmac_name(u8 hmac_id)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(hash_map); i++) {
> +		if (hash_map[i].id == hmac_id)
> +			return hash_map[i].hmac;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_hmac_name);
> +
> +const char *nvme_auth_digest_name(u8 hmac_id)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(hash_map); i++) {
> +		if (hash_map[i].id == hmac_id)
> +			return hash_map[i].digest;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_digest_name);
> +
> +u8 nvme_auth_hmac_id(const char *hmac_name)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(hash_map); i++) {
> +		if (!strncmp(hash_map[i].hmac, hmac_name,
> +			     strlen(hash_map[i].hmac)))
> +			return hash_map[i].id;
> +	}
> +	return NVME_AUTH_HASH_INVALID;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_hmac_id);
> +
> +size_t nvme_auth_hmac_hash_len(u8 hmac_id)
> +{
> +	int i;
> +
> +	for (i = 0; i < ARRAY_SIZE(hash_map); i++) {
> +		if (hash_map[i].id == hmac_id)
> +			return hash_map[i].len;
> +	}
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_hmac_hash_len);

we can remove loops in the above helpers and the id member in
the struct with the help of the sparse array, why not :-

/* Defined hash functions for DH-HMAC-CHAP authentication */
enum { 

        NVME_AUTH_HASH_SHA256   = 0x01,
        NVME_AUTH_HASH_SHA384   = 0x02,
        NVME_AUTH_HASH_SHA512   = 0x03,
        NVME_AUTH_HASH_INVALID  = 0xff,
};

static struct nvme_dhchap_hash_map {
	int len;
	const char *hmac;
	const char *digest;
} hash_map[] = {
	[NVME_AUTH_HASH_SHA256] = {	.len = 32,
					.hmac = "hmac(sha256)",
					.digest = "sha256"
				},
	[NVME_AUTH_HASH_SHA384] = {	.len = 48,
					.hmac = "hmac(sha384)",
					.digest = "sha384"
				},
	[NVME_AUTH_HASH_SHA512] = {	.len = 64,
					.hmac = "hmac(sha512)",
					.digest = "sha512"
				},
};

const char *nvme_auth_hmac_name(unsigned int hmac_id)
{
	if ((hmac_id > ARRAY_SIZE(hash_map)) || !hash_map[hmac_id].hmac)
		return NULL;
	return hash_map[hmac_id].hmac;
}

const char *nvme_auth_digest_name(unsigned int hmac_id)
{
	if ((hmac_id > ARRAY_SIZE(hash_map)) || !hash_map[hmac_id].hmac)
		return NULL;
	return hash_map[hmac_id].digest;
}

size_t nvme_auth_hmac_hash_len(unsigned int hmac_id)
{
	if ((hmac_id > ARRAY_SIZE(hash_map)) || !hash_map[hmac_id].hmac)
		return 0;
	return hash_map[hmac_id].len;
}

unsigned int nvme_auth_hmac_id(const char *hmac_name)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(hash_map); i++) {
		if (!hash_map[i].hmac)
			continue;
		if (!strncmp(hash_map[i].hmac, hmac_name,
			     strlen(hash_map[i].hmac)))
			return i;
	}
	return NVME_AUTH_HASH_INVALID;
}

See [1] that has a test program execution, same can be applied to
nvme_dhchap_hash_map.

> +
> +struct nvme_dhchap_key *nvme_auth_extract_key(unsigned char *secret,
> +					      u8 key_hash)
> +{
> +	struct nvme_dhchap_key *key;
> +	unsigned char *p;
> +	u32 crc;
> +	int ret, key_len;
> +	size_t allocated_len = strlen(secret);
> +
> +	/* Secret might be affixed with a ':' */
> +	p = strrchr(secret, ':');
> +	if (p)
> +		allocated_len = p - secret;
> +	key = kzalloc(sizeof(*key), GFP_KERNEL);
> +	if (!key)
> +		return ERR_PTR(-ENOMEM);
> +	key->key = kzalloc(allocated_len, GFP_KERNEL);
> +	if (!key->key) {
> +		ret = -ENOMEM;
> +		goto out_free_key;
> +	}
> +
> +	key_len = base64_decode(secret, allocated_len, key->key);
> +	if (key_len < 0) {
> +		pr_debug("base64 key decoding error %d\n",
> +			 key_len);
> +		ret = key_len;
> +		goto out_free_secret;
> +	}
> +
> +	if (key_len != 36 && key_len != 52 &&
> +	    key_len != 68) {
> +		pr_err("Invalid DH-HMAC-CHAP key len %d\n",
> +		       key_len);
> +		ret = -EINVAL;
> +		goto out_free_secret;
> +	}
> +
> +	if (key_hash > 0 &&
> +	    (key_len - 4) != nvme_auth_hmac_hash_len(key_hash)) {
> +		pr_err("Invalid DH-HMAC-CHAP key len %d for %s\n", key_len,
> +		       nvme_auth_hmac_name(key_hash));
> +		ret = -EINVAL;
> +		goto out_free_secret;
> +	}
> +
> +	/* The last four bytes is the CRC in little-endian format */
> +	key_len -= 4;
> +	/*
> +	 * The linux implementation doesn't do pre- and post-increments,
> +	 * so we have to do it manually.
> +	 */
> +	crc = ~crc32(~0, key->key, key_len);
> +
> +	if (get_unaligned_le32(key->key + key_len) != crc) {
> +		pr_err("DH-HMAC-CHAP key crc mismatch (key %08x, crc %08x)\n",
> +		       get_unaligned_le32(key->key + key_len), crc);
> +		ret = -EKEYREJECTED;
> +		goto out_free_secret;
> +	}
> +	key->len = key_len;
> +	key->hash = key_hash;
> +	return key;
> +out_free_secret:
> +	kfree_sensitive(key->key);
> +out_free_key:
> +	kfree(key);
> +	return ERR_PTR(ret);
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_extract_key);
> +
> +void nvme_auth_free_key(struct nvme_dhchap_key *key)
> +{
> +	if (!key)
> +		return;
> +	kfree_sensitive(key->key);
> +	kfree(key);
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_free_key);
> +
> +u8 *nvme_auth_transform_key(struct nvme_dhchap_key *key, char *nqn)
> +{
> +	const char *hmac_name = nvme_auth_hmac_name(key->hash);
> +	struct crypto_shash *key_tfm;
> +	struct shash_desc *shash;
> +	u8 *transformed_key;
> +	int ret;
> +
> +	if (key->hash == 0) {
> +		transformed_key = kmemdup(key->key, key->len, GFP_KERNEL);
> +		return transformed_key ? transformed_key : ERR_PTR(-ENOMEM);
> +	}
> +
> +	if (!key || !key->key) {
> +		pr_warn("No key specified\n");
> +		return ERR_PTR(-ENOKEY);
> +	}
> +	if (!hmac_name) {
> +		pr_warn("Invalid key hash id %d\n", key->hash);
> +		return ERR_PTR(-EINVAL);
> +	}
> +
> +	key_tfm = crypto_alloc_shash(hmac_name, 0, 0);
> +	if (IS_ERR(key_tfm))
> +		return (u8 *)key_tfm;
> +
> +	shash = kmalloc(sizeof(struct shash_desc) +
> +			crypto_shash_descsize(key_tfm),
> +			GFP_KERNEL);
> +	if (!shash) {
> +		ret = -ENOMEM;
> +		goto out_free_key;
> +	}
> +
> +	transformed_key = kzalloc(crypto_shash_digestsize(key_tfm), GFP_KERNEL);
> +	if (!transformed_key) {
> +		ret = -ENOMEM;
> +		goto out_free_shash;
> +	}
> +
> +	shash->tfm = key_tfm;
> +	ret = crypto_shash_setkey(key_tfm, key->key, key->len);
> +	if (ret < 0)
> +		goto out_free_shash;
> +	ret = crypto_shash_init(shash);
> +	if (ret < 0)
> +		goto out_free_shash;
> +	ret = crypto_shash_update(shash, nqn, strlen(nqn));
> +	if (ret < 0)
> +		goto out_free_shash;
> +	ret = crypto_shash_update(shash, "NVMe-over-Fabrics", 17);
> +	if (ret < 0)
> +		goto out_free_shash;
> +	ret = crypto_shash_final(shash, transformed_key);
> +out_free_shash:
> +	kfree(shash);
> +out_free_key:
> +	crypto_free_shash(key_tfm);
> +	if (ret < 0) {
> +		kfree_sensitive(transformed_key);
> +		return ERR_PTR(ret);
> +	}
> +	return transformed_key;
> +}
> +EXPORT_SYMBOL_GPL(nvme_auth_transform_key);
> +
> +#define nvme_auth_flags_from_qid(qid) \
> +	(qid == 0) ? 0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED
> +#define nvme_auth_queue_from_qid(ctrl, qid) \
> +	(qid == 0) ? (ctrl)->fabrics_q : (ctrl)->connect_q
> +
> +static int nvme_auth_send(struct nvme_ctrl *ctrl, int qid,
> +		void *data, size_t tl)
> +{
> +	struct nvme_command cmd = {};
> +	blk_mq_req_flags_t flags = nvme_auth_flags_from_qid(qid);
> +	struct request_queue *q = nvme_auth_queue_from_qid(ctrl, qid);
> +	int ret;
> +
> +	cmd.auth_send.opcode = nvme_fabrics_command;
> +	cmd.auth_send.fctype = nvme_fabrics_type_auth_send;
> +	cmd.auth_send.secp = NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER;
> +	cmd.auth_send.spsp0 = 0x01;
> +	cmd.auth_send.spsp1 = 0x01;
> +	cmd.auth_send.tl = cpu_to_le32(tl);
> +
> +	ret = __nvme_submit_sync_cmd(q, &cmd, NULL, data, tl, 0,
> +				     qid == 0 ? NVME_QID_ANY : qid,
> +				     0, flags);
> +	if (ret > 0)
> +		dev_warn(ctrl->device,
> +			"qid %d auth_send failed with status %d\n", qid, ret);
> +	else if (ret < 0)
> +		dev_err(ctrl->device,
> +			"qid %d auth_send failed with error %d\n", qid, ret);
> +	return ret;
> +}
> +
> +static int nvme_auth_receive(struct nvme_ctrl *ctrl, int qid,
> +		void *buf, size_t al)
> +{
> +	struct nvme_command cmd = {};
> +	blk_mq_req_flags_t flags = nvme_auth_flags_from_qid(qid);
> +	struct request_queue *q = nvme_auth_queue_from_qid(ctrl, qid);
> +	int ret;
> +
> +	cmd.auth_receive.opcode = nvme_fabrics_command;
> +	cmd.auth_receive.fctype = nvme_fabrics_type_auth_receive;
> +	cmd.auth_receive.secp = NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER;
> +	cmd.auth_receive.spsp0 = 0x01;
> +	cmd.auth_receive.spsp1 = 0x01;
> +	cmd.auth_receive.al = cpu_to_le32(al);
> +
> +	ret = __nvme_submit_sync_cmd(q, &cmd, NULL, buf, al, 0,
> +				     qid == 0 ? NVME_QID_ANY : qid,
> +				     0, flags);
> +	if (ret > 0) {
> +		dev_warn(ctrl->device,
> +			 "qid %d auth_recv failed with status %x\n", qid, ret);
> +		ret = -EIO;
> +	} else if (ret < 0) {
> +		dev_err(ctrl->device,
> +			"qid %d auth_recv failed with error %d\n", qid, ret);
> +	}
> +
> +	return ret;
> +}
> +

Why not use something like this ? It reduces the duplicate code and
need for macros :-

static int nvme_auth_send_recv_common(bool send, struct nvme_ctrl *ctrl,
                                       int qid, void *buf, size_t buflen)

{
         strucy nvme_cmd cmd = { };
         blk_mq_req_flags_t flags;
         struct request_queue *q;
         int ret;

         flags = qid == 0 ? 0 : BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT;
         q = qid == 0 ? ctrl->fabrics_q : ctrl->connect_q;

         /* auth send/recv share common offset for the various fields in 
cmd */
         cmd.auth_send.opcode = nvme_fabrics_command;
         cmd.auth_send.secp = NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER;
         cmd.auth_send.spsp0 = 0x01;
         cmd.auth_send.spsp1 = 0x01;
         cmd.auth_send.al = cpu_to_le32(buflen);
         cmd.auth_receive.fctype = send ? nvme_fabrics_type_auth_send :
                                          nvme_fabrics_type_auth_receive;

         ret = nvme_submit_sync_cmd(q, &cmd, NULL, buf, buflen, 0,
                                    qid == 0 ? NVME_QID_ANY : qid,
                                    0, flags);
         if (ret > 0)
                 dev_warn(ctrl->device,
                         "qid %d fctype 0x%x failed with status %d\n", qid,
                         cmd.auth_send.fctype, ret);
         else if (ret < 0)
                 dev_err(ctrl->device,
                         "qid %d fctype 0x%x failed with error %d\n", qid,
                         cmd.auth_send.fctype, ret);
         return ret;
}


static int nvme_auth_send(struct nvme_ctrl *c, int qid, void *data, 
size_t tl)
{
         return nvme_auth_send_recv_common(true, c, qid, data, tl);
}

static int nvme_auth_receive(struct nvme_ctrl *ctrl, int qid,
                 void *buf, size_t al)
{
         return nvme_auth_send_recv_common(false, c, qid, data, tl);

}



> +static int nvme_auth_receive_validate(struct nvme_ctrl *ctrl, int qid,
> +		struct nvmf_auth_dhchap_failure_data *data,
> +		u16 transaction, u8 expected_msg)
> +{
> +	dev_dbg(ctrl->device, "%s: qid %d auth_type %d auth_id %x\n",
> +		__func__, qid, data->auth_type, data->auth_id);
> +
> +	if (data->auth_type == NVME_AUTH_COMMON_MESSAGES &&
> +	    data->auth_id == NVME_AUTH_DHCHAP_MESSAGE_FAILURE1) {
> +		return data->rescode_exp;
> +	}
> +	if (data->auth_type != NVME_AUTH_DHCHAP_MESSAGES ||
> +	    data->auth_id != expected_msg) {
> +		dev_warn(ctrl->device,
> +			 "qid %d invalid message %02x/%02x\n",
> +			 qid, data->auth_type, data->auth_id);
> +		return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
> +	}
> +	if (le16_to_cpu(data->t_id) != transaction) {
> +		dev_warn(ctrl->device,
> +			 "qid %d invalid transaction ID %d\n",
> +			 qid, le16_to_cpu(data->t_id));
> +		return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
> +	}
> +	return 0;
> +}
> +
[...]


[1] # cat  a.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/uio.h>
#include <stdlib.h>

#define COUNT (10)
#define LEN (1024)

#define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(arr[0])))

/* Defined hash functions for DH-HMAC-CHAP authentication */
enum { 

        NVME_AUTH_HASH_SHA256   = 0x01,
        NVME_AUTH_HASH_SHA384   = 0x02,
        NVME_AUTH_HASH_SHA512   = 0x03,
        NVME_AUTH_HASH_INVALID  = 0xff,
};

static struct nvme_dhchap_hash_map {
	int len;
	const char *hmac;
	const char *digest;
} hash_map[] = {
	[NVME_AUTH_HASH_SHA256] = {	.len = 32,
					.hmac = "hmac(sha256)",
					.digest = "sha256"
				},
	[NVME_AUTH_HASH_SHA384] = {	.len = 48,
					.hmac = "hmac(sha384)",
					.digest = "sha384"
				},
	[NVME_AUTH_HASH_SHA512] = {	.len = 64,
					.hmac = "hmac(sha512)",
					.digest = "sha512"
				},
};

const char *nvme_auth_hmac_name(unsigned int hmac_id)
{
	if ((hmac_id > ARRAY_SIZE(hash_map)) || !hash_map[hmac_id].hmac)
		return NULL;
	return hash_map[hmac_id].hmac;
}

const char *nvme_auth_digest_name(unsigned int hmac_id)
{
	if ((hmac_id > ARRAY_SIZE(hash_map)) || !hash_map[hmac_id].hmac)
		return NULL;
	return hash_map[hmac_id].digest;
}

size_t nvme_auth_hmac_hash_len(unsigned int hmac_id)
{
	if ((hmac_id > ARRAY_SIZE(hash_map)) || !hash_map[hmac_id].hmac)
		return 0;
	return hash_map[hmac_id].len;
}

unsigned int nvme_auth_hmac_id(const char *hmac_name)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(hash_map); i++) {
		if (!hash_map[i].hmac)
			continue;
		if (!strncmp(hash_map[i].hmac, hmac_name,
			     strlen(hash_map[i].hmac)))
			return i;
	}
	return NVME_AUTH_HASH_INVALID;
}

int main(void)
{
	printf("-------------------------------------------------------\n");
	printf("hmac_id = 0x%s name 0x%x\n", "hmac(sha256)",
			nvme_auth_hmac_id("hmac(sha256)"));
	printf("hmac_id = 0x%s name 0x%x\n", "hmac(sha384)",
			nvme_auth_hmac_id("hmac(sha384)"));
	printf("hmac_id = 0x%s name 0x%x\n", "hmac(sha512)",
			nvme_auth_hmac_id("hmac(sha512)"));
	printf("hmac_id = 0x%s name 0x%x\n", "",
			nvme_auth_hmac_id(""));
	printf("hmac_id = 0x%s name 0x%x\n", "asdfadsf",
			nvme_auth_hmac_id("asdfadsf"));

	printf("-------------------------------------------------------\n");
	printf("hmac_id = 0x%x name %s\n", NVME_AUTH_HASH_SHA256,
			nvme_auth_hmac_name(NVME_AUTH_HASH_SHA256));
	printf("hmac_id = 0x%x name %s\n", NVME_AUTH_HASH_SHA384,
			nvme_auth_hmac_name(NVME_AUTH_HASH_SHA384));
	printf("hmac_id = 0x%x name %s\n", NVME_AUTH_HASH_SHA512,
			nvme_auth_hmac_name(NVME_AUTH_HASH_SHA512));
	printf("hmac_id = 0x%x name %s\n", 0x05,
			nvme_auth_hmac_name(0x05));
	printf("hmac_id = 0x%x name %s\n", 0x0ff,
			nvme_auth_hmac_name(0xff));
	printf("hmac_id = 0x%x name %s\n", 0x0ff1,
			nvme_auth_hmac_name(0xff1));

	printf("-------------------------------------------------------\n");
	printf("hmac_id = 0x%x digest %s\n", NVME_AUTH_HASH_SHA256,
			nvme_auth_digest_name(NVME_AUTH_HASH_SHA256));
	printf("hmac_id = 0x%x digest %s\n", NVME_AUTH_HASH_SHA384,
			nvme_auth_digest_name(NVME_AUTH_HASH_SHA384));
	printf("hmac_id = 0x%x digest %s\n", NVME_AUTH_HASH_SHA512,
			nvme_auth_digest_name(NVME_AUTH_HASH_SHA512));
	printf("hmac_id = 0x%x digest %s\n", 0x05,
			nvme_auth_digest_name(0x05));
	printf("hmac_id = 0x%x digest %s\n", 0x0ff,
			nvme_auth_digest_name(0xff));
	printf("hmac_id = 0x%x digest %s\n", 0x0ff1,
			nvme_auth_digest_name(0xff1));

	printf("-------------------------------------------------------\n");
	printf("hmac_id = 0x%x len %d\n", NVME_AUTH_HASH_SHA256,
			nvme_auth_hmac_hash_len(NVME_AUTH_HASH_SHA256));
	printf("hmac_id = 0x%x len %d\n", NVME_AUTH_HASH_SHA384,
			nvme_auth_hmac_hash_len(NVME_AUTH_HASH_SHA384));
	printf("hmac_id = 0x%x len %d\n", NVME_AUTH_HASH_SHA512,
			nvme_auth_hmac_hash_len(NVME_AUTH_HASH_SHA512));
	printf("hmac_id = 0x%x len %d\n", 0x05,
			nvme_auth_hmac_hash_len(0x05));
	printf("hmac_id = 0x%x len %d\n", 0x0ff,
			nvme_auth_hmac_hash_len(0xff));
	printf("hmac_id = 0x%x len %d\n", 0x0ff1,
			nvme_auth_hmac_hash_len(0xff1));

         return 0;
}
nvme (nvme-5.18) # gcc a.c
nvme (nvme-5.18) # ./a.out
-------------------------------------------------------
hmac_id = 0xhmac(sha256) name 0x1
hmac_id = 0xhmac(sha384) name 0x2
hmac_id = 0xhmac(sha512) name 0x3
hmac_id = 0x name 0xff
hmac_id = 0xasdfadsf name 0xff
-------------------------------------------------------
hmac_id = 0x1 name hmac(sha256)
hmac_id = 0x2 name hmac(sha384)
hmac_id = 0x3 name hmac(sha512)
hmac_id = 0x5 name (null)
hmac_id = 0xff name (null)
hmac_id = 0xff1 name (null)
-------------------------------------------------------
hmac_id = 0x1 digest sha256
hmac_id = 0x2 digest sha384
hmac_id = 0x3 digest sha512
hmac_id = 0x5 digest (null)
hmac_id = 0xff digest (null)
hmac_id = 0xff1 digest (null)
-------------------------------------------------------
hmac_id = 0x1 len 32
hmac_id = 0x2 len 48
hmac_id = 0x3 len 64
hmac_id = 0x5 len 0
hmac_id = 0xff len 0
hmac_id = 0xff1 len 0



  reply	other threads:[~2022-03-24 16:53 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-23  7:12 [PATCHv9 00/11] nvme: In-band authentication support Hannes Reinecke
2022-03-23  7:12 ` [PATCH 01/11] crypto: add crypto_has_shash() Hannes Reinecke
2022-03-23  7:12 ` [PATCH 02/11] crypto: add crypto_has_kpp() Hannes Reinecke
2022-03-23  7:12 ` [PATCH 03/11] lib/base64: RFC4648-compliant base64 encoding Hannes Reinecke
2022-03-23  7:12 ` [PATCH 04/11] nvme: add definitions for NVMe In-Band authentication Hannes Reinecke
2022-03-23  7:12 ` [PATCH 05/11] nvme-fabrics: decode 'authentication required' connect error Hannes Reinecke
2022-03-23  7:12 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-03-24 16:53   ` Chaitanya Kulkarni [this message]
2022-03-25  7:57     ` Hannes Reinecke
2022-03-23  7:12 ` [PATCH 07/11] nvme-auth: Diffie-Hellman key exchange support Hannes Reinecke
2022-03-23  7:13 ` [PATCH 08/11] nvmet: parse fabrics commands on io queues Hannes Reinecke
2022-03-23  7:13 ` [PATCH 09/11] nvmet: Implement basic In-Band Authentication Hannes Reinecke
2022-03-23  7:13 ` [PATCH 10/11] nvmet-auth: Diffie-Hellman key exchange support Hannes Reinecke
2022-03-23  7:13 ` [PATCH 11/11] nvmet-auth: expire authentication sessions Hannes Reinecke
2022-03-24 17:06 ` [PATCHv9 00/11] nvme: In-band authentication support Sagi Grimberg
  -- strict thread matches above, loose matches on Subject: below --
2022-06-27  9:51 [PATCHv18 " Hannes Reinecke
2022-06-27  9:52 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-06-23  6:17 [PATCHv17 00/11] nvme: In-band authentication support Hannes Reinecke
2022-06-23  6:17 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-06-21 17:24 [PATCHv16 00/11] nvme: In-band authentication support Hannes Reinecke
2022-06-21 17:24 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-06-22 17:43   ` Sagi Grimberg
2022-06-21  9:02 [PATCHv15 00/11] nvme: In-band authentication support Hannes Reinecke
2022-06-21  9:02 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-06-21 14:24   ` Sagi Grimberg
2022-06-21 14:26     ` Hannes Reinecke
2022-06-21 14:50       ` Sagi Grimberg
2022-06-21 14:59         ` Sagi Grimberg
2022-06-22  6:01           ` Hannes Reinecke
2022-06-22  8:43             ` Sagi Grimberg
2022-06-22  9:06               ` Hannes Reinecke
2022-06-22  9:09                 ` Sagi Grimberg
2022-06-22  9:20                   ` Hannes Reinecke
2022-06-22  9:58                     ` Sagi Grimberg
2022-06-22 10:26                       ` Hannes Reinecke
2022-06-22 10:31                         ` Sagi Grimberg
2022-06-22  5:43         ` Hannes Reinecke
2022-06-08 14:45 [PATCHv14 00/11] nvme: In-band authentication support Hannes Reinecke
2022-06-08 14:45 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-06-13 18:12   ` Christoph Hellwig
2022-06-20  6:50     ` Hannes Reinecke
2022-05-18 11:22 [PATCHv12 00/11] nvme: In-band authentication support Hannes Reinecke
2022-05-18 11:22 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-03-28 13:39 [PATCHv11 00/11] nvme: In-band authentication support Hannes Reinecke
2022-03-28 13:39 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2022-04-27 17:59   ` Nayak, Prashanth
2022-04-28  6:05     ` Hannes Reinecke
2022-03-28  8:08 [PATCHv10 00/11] nvme: In-band authentication support Hannes Reinecke
2022-03-28  8:08 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2021-07-16 11:04 [RFC PATCH 00/11] nvme: In-band authentication support Hannes Reinecke
2021-07-16 11:04 ` [PATCH 06/11] nvme: Implement In-Band authentication Hannes Reinecke
2021-07-16 11:04   ` Hannes Reinecke
2021-07-17  7:22   ` Sagi Grimberg
2021-07-17  7:22     ` Sagi Grimberg
2021-07-18 12:21     ` Hannes Reinecke
2021-07-18 12:21       ` Hannes Reinecke
2021-07-19  8:47       ` Sagi Grimberg
2021-07-19  8:47         ` Sagi Grimberg
2021-07-20 20:28       ` Vladislav Bolkhovitin
2021-07-20 20:28         ` Vladislav Bolkhovitin
2021-07-21  6:12         ` Hannes Reinecke
2021-07-21  6:12           ` Hannes Reinecke
2021-07-17 16:49   ` Stephan Müller
2021-07-17 16:49     ` Stephan Müller
2021-07-18 12:43     ` Hannes Reinecke
2021-07-18 12:43       ` Hannes Reinecke
2021-07-18 12:47       ` Stephan Müller
2021-07-18 12:47         ` Stephan Müller
2021-07-20 20:27   ` Vladislav Bolkhovitin
2021-07-20 20:27     ` Vladislav Bolkhovitin
2021-07-21  6:08     ` Hannes Reinecke
2021-07-21  6:08       ` Hannes Reinecke
2021-07-21 12:10       ` Vladislav Bolkhovitin
2021-07-21 12:10         ` Vladislav Bolkhovitin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=fb9d1fb7-98e8-f592-8acc-997292097345@nvidia.com \
    --to=chaitanyak@nvidia.com \
    --cc=hare@suse.de \
    --cc=hch@lst.de \
    --cc=keith.busch@wdc.com \
    --cc=linux-nvme@lists.infradead.org \
    --cc=sagi@grimberg.me \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.