[PATCH v3] nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C

alistair23@gmail.com posted 1 patch 2 weeks, 5 days ago
drivers/nvme/host/auth.c | 26 ++++++++++++++------------
include/linux/nvme.h     |  2 ++
2 files changed, 16 insertions(+), 12 deletions(-)
[PATCH v3] nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C
Posted by alistair23@gmail.com 2 weeks, 5 days ago
From: Alistair Francis <alistair.francis@wdc.com>

Section 8.3.4.5.2 of the NVMe 2.1 base spec states that

"""
The 00h identifier shall not be proposed in an AUTH_Negotiate message
that requests secure channel concatenation (i.e., with the SC_C field
set to a non-zero value).
"""

We need to ensure that we don't set the NVME_AUTH_DHGROUP_NULL idlist if
SC_C is set.

Signed-off-by: Kamaljit Singh <kamaljit.singh@opensource.wdc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
---
v3:
 - Ensure chap->sc_c is set before the if statement
v2:
 - Use a macro for Diffie-Hellman Group Identifier List Offset
 - Use a pointer for data->auth_protocol[0].dhchap.idlist

 drivers/nvme/host/auth.c | 26 ++++++++++++++------------
 include/linux/nvme.h     |  2 ++
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c
index 405e7c03b1cf..f9efed08997c 100644
--- a/drivers/nvme/host/auth.c
+++ b/drivers/nvme/host/auth.c
@@ -125,6 +125,8 @@ static int nvme_auth_set_dhchap_negotiate_data(struct nvme_ctrl *ctrl,
 {
 	struct nvmf_auth_dhchap_negotiate_data *data = chap->buf;
 	size_t size = sizeof(*data) + sizeof(union nvmf_auth_protocol);
+	u8 dh_list_offset = DH_GID_LIST_OFFSET;
+	u8 *idlist = data->auth_protocol[0].dhchap.idlist;
 
 	if (size > CHAP_BUF_SIZE) {
 		chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
@@ -141,21 +143,21 @@ static int nvme_auth_set_dhchap_negotiate_data(struct nvme_ctrl *ctrl,
 			data->sc_c = NVME_AUTH_SECP_NEWTLSPSK;
 	} else
 		data->sc_c = NVME_AUTH_SECP_NOSC;
+	chap->sc_c = data->sc_c;
 	data->napd = 1;
 	data->auth_protocol[0].dhchap.authid = NVME_AUTH_DHCHAP_AUTH_ID;
 	data->auth_protocol[0].dhchap.halen = 3;
-	data->auth_protocol[0].dhchap.dhlen = 6;
-	data->auth_protocol[0].dhchap.idlist[0] = NVME_AUTH_HASH_SHA256;
-	data->auth_protocol[0].dhchap.idlist[1] = NVME_AUTH_HASH_SHA384;
-	data->auth_protocol[0].dhchap.idlist[2] = NVME_AUTH_HASH_SHA512;
-	data->auth_protocol[0].dhchap.idlist[30] = NVME_AUTH_DHGROUP_NULL;
-	data->auth_protocol[0].dhchap.idlist[31] = NVME_AUTH_DHGROUP_2048;
-	data->auth_protocol[0].dhchap.idlist[32] = NVME_AUTH_DHGROUP_3072;
-	data->auth_protocol[0].dhchap.idlist[33] = NVME_AUTH_DHGROUP_4096;
-	data->auth_protocol[0].dhchap.idlist[34] = NVME_AUTH_DHGROUP_6144;
-	data->auth_protocol[0].dhchap.idlist[35] = NVME_AUTH_DHGROUP_8192;
-
-	chap->sc_c = data->sc_c;
+	idlist[0] = NVME_AUTH_HASH_SHA256;
+	idlist[1] = NVME_AUTH_HASH_SHA384;
+	idlist[2] = NVME_AUTH_HASH_SHA512;
+	if (chap->sc_c == NVME_AUTH_SECP_NOSC)
+		idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_NULL;
+	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_2048;
+	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_3072;
+	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_4096;
+	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_6144;
+	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_8192;
+	data->auth_protocol[0].dhchap.dhlen = dh_list_offset - DH_GID_LIST_OFFSET;
 
 	return size;
 }
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 655d194f8e72..bd540ef33b63 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -2332,4 +2332,6 @@ enum nvme_pr_change_ptpl {
 
 #define NVME_PR_IGNORE_KEY (1 << 3)
 
+#define DH_GID_LIST_OFFSET 30
+
 #endif /* _LINUX_NVME_H */
-- 
2.53.0
Re: [PATCH v3] nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C
Posted by Christoph Hellwig 2 weeks, 5 days ago
On Wed, Mar 18, 2026 at 10:46:58AM +1000, alistair23@gmail.com wrote:
> +	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_6144;
> +	idlist[dh_list_offset++] = NVME_AUTH_DHGROUP_8192;
> +	data->auth_protocol[0].dhchap.dhlen = dh_list_offset - DH_GID_LIST_OFFSET;

Still an overly long line here.

>  
>  	return size;
>  }
> diff --git a/include/linux/nvme.h b/include/linux/nvme.h
> index 655d194f8e72..bd540ef33b63 100644
> --- a/include/linux/nvme.h
> +++ b/include/linux/nvme.h
> @@ -2332,4 +2332,6 @@ enum nvme_pr_change_ptpl {
>  
>  #define NVME_PR_IGNORE_KEY (1 << 3)
>  
> +#define DH_GID_LIST_OFFSET 30

Note that we have a target side patch ("nvmet: auth: validate dhchap id
list lengths") also adding defines related to this, but in a different
place and using different naming:


+#define NVME_AUTH_DHCHAP_MAX_HASH_IDS 30
+#define NVME_AUTH_DHCHAP_MAX_DH_IDS 30

Back in the day we usually did nvme.h patch separately to handle these
kinds of conflicts a little better.

YunJe/Alistair, maybe whoever resends next should split this out,
add all the required values and add a pointer to the spec?
Re: [PATCH v3] nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C
Posted by Chris Leech 2 weeks, 5 days ago
On Wed, Mar 18, 2026 at 08:56:55AM +0100, Christoph Hellwig wrote:
> On Wed, Mar 18, 2026 at 10:46:58AM +1000, alistair23@gmail.com wrote:
> >  
> > +#define DH_GID_LIST_OFFSET 30
> 
> Note that we have a target side patch ("nvmet: auth: validate dhchap id
> list lengths") also adding defines related to this, but in a different
> place and using different naming:
> 
> 
> +#define NVME_AUTH_DHCHAP_MAX_HASH_IDS 30
> +#define NVME_AUTH_DHCHAP_MAX_DH_IDS 30
> 
> Back in the day we usually did nvme.h patch separately to handle these
> kinds of conflicts a little better.
> 
> YunJe/Alistair, maybe whoever resends next should split this out,
> add all the required values and add a pointer to the spec?

Is there a good reason to keep a single idlist[60] in the struct
defintiion and need this offset at all? Or can we repalce it with
somthing like haidlist[30], dhidlist[30]?

NVMe base spec r2.3 section is 8.3.5.5.2, where these are seperate
fields named HashIDList and DHgIDList.

- Chris
Re: [PATCH v3] nvme-auth: Don't propose NVME_AUTH_DHGROUP_NULL with SC_C
Posted by Alistair Francis 2 weeks, 4 days ago
On Thu, Mar 19, 2026 at 2:25 AM Chris Leech <cleech@redhat.com> wrote:
>
> On Wed, Mar 18, 2026 at 08:56:55AM +0100, Christoph Hellwig wrote:
> > On Wed, Mar 18, 2026 at 10:46:58AM +1000, alistair23@gmail.com wrote:
> > >
> > > +#define DH_GID_LIST_OFFSET 30
> >
> > Note that we have a target side patch ("nvmet: auth: validate dhchap id
> > list lengths") also adding defines related to this, but in a different
> > place and using different naming:
> >
> >
> > +#define NVME_AUTH_DHCHAP_MAX_HASH_IDS 30
> > +#define NVME_AUTH_DHCHAP_MAX_DH_IDS 30
> >
> > Back in the day we usually did nvme.h patch separately to handle these
> > kinds of conflicts a little better.
> >
> > YunJe/Alistair, maybe whoever resends next should split this out,
> > add all the required values and add a pointer to the spec?
>
> Is there a good reason to keep a single idlist[60] in the struct
> defintiion and need this offset at all? Or can we repalce it with
> somthing like haidlist[30], dhidlist[30]?
>
> NVMe base spec r2.3 section is 8.3.5.5.2, where these are seperate
> fields named HashIDList and DHgIDList.

The 2.1 spec kind of implies a single array with an offset of 33 for
the DHgIDList, which I assume is why this was written the way it is.

I'm open to changing it if people free strongly though

Alistair

>
> - Chris
>