Skip to contentSkip to conversation

nvme: In-band authentication support

PATCH Superseded Hannes Reinecke 4 participants 37 messages Nov 12, 2021 – Nov 19, 2021

Subsystems (5)

v5 of 18 Superseded Latest is v18 →

lore
Share & tools
lore

Hannes Reinecke

author maintainer
#0 lore raw

v5 cover nvme: In-band authentication support

Hi all,

recent updates to the NVMe spec have added definitions for in-band authentication, and seeing that it provides some real benefit especially for NVMe-TCP here's an attempt to implement it.

Tricky bit here is that the specification orients itself on TLS 1.3, but supports only the FFDHE groups. Which of course the kernel doesn't support. I've been able to come up with a patch for this, but as this is my first attempt to fix anything in the crypto area I would invite people more familiar with these matters to have a look.

Also note that this is just for in-band authentication. Secure concatenation (ie starting TLS with the negotiated parameters) is not implemented; one would need to update the kernel TLS implementation for this, which at this time is beyond scope.

As usual, comments and reviews are welcome.

Changes to v4:
- Validate against blktest suite
- Fixup base64 decoding
- Transform secret with correct hmac algorithm

Changes to v3:
- Renamed parameter to 'dhchap_ctrl_key'
- Fixed bi-directional authentication
- Included reviews from Sagi
- Fixed base64 algorithm for transport encoding

Changes to v2:
- Dropped non-standard algorithms
- Reworked base64 based on fs/crypto/fname.c
- Fixup crash with no keys

Changes to the original submission:
- Included reviews from Vladislav
- Included reviews from Sagi
- Implemented re-authentication support
- Fixed up key handling

Hannes Reinecke (12):
crypto: add crypto_has_shash()
crypto: add crypto_has_kpp()
crypto/ffdhe: Finite Field DH Ephemeral Parameters lib/base64: RFC4648-compliant base64 encoding
nvme: add definitions for NVMe In-Band authentication
nvme-fabrics: decode 'authentication required' connect error
nvme: Implement In-Band authentication
nvme-auth: Diffie-Hellman key exchange support
nvmet: Parse fabrics commands on all queues
nvmet: Implement basic In-Band Authentication
nvmet-auth: Diffie-Hellman key exchange support
nvmet-auth: expire authentication sessions

 crypto/Kconfig                         |    8 +
 crypto/Makefile                        |    1 +
 crypto/ffdhe_helper.c                  |  880 +++++++++++++
 crypto/kpp.c                           |    6 +
 crypto/shash.c                         |    6 +
 drivers/nvme/host/Kconfig              |   12 +
 drivers/nvme/host/Makefile             |    1 +
 drivers/nvme/host/auth.c               | 1564 ++++++++++++++++++++++++
 drivers/nvme/host/auth.h               |   34 +
 drivers/nvme/host/core.c               |  133 +-
 drivers/nvme/host/fabrics.c            |   83 +-
 drivers/nvme/host/fabrics.h            |    7 +
 drivers/nvme/host/nvme.h               |   36 +
 drivers/nvme/host/tcp.c                |    1 +
 drivers/nvme/host/trace.c              |   32 +
 drivers/nvme/target/Kconfig            |   12 +
 drivers/nvme/target/Makefile           |    1 +
 drivers/nvme/target/admin-cmd.c        |    4 +
 drivers/nvme/target/auth.c             |  544 +++++++++
 drivers/nvme/target/configfs.c         |  138 ++-
 drivers/nvme/target/core.c             |   10 +
 drivers/nvme/target/fabrics-cmd-auth.c |  513 ++++++++
 drivers/nvme/target/fabrics-cmd.c      |   30 +-
 drivers/nvme/target/nvmet.h            |   77 ++
 include/crypto/ffdhe.h                 |   24 +
 include/crypto/hash.h                  |    2 +
 include/crypto/kpp.h                   |    2 +
 include/linux/base64.h                 |   16 +
 include/linux/nvme.h                   |  186 ++-
 lib/Makefile                           |    2 +-
 lib/base64.c                           |  103 ++
 31 files changed, 4456 insertions(+), 12 deletions(-)
 create mode 100644 crypto/ffdhe_helper.c
 create mode 100644 drivers/nvme/host/auth.c
 create mode 100644 drivers/nvme/host/auth.h
 create mode 100644 drivers/nvme/target/auth.c
 create mode 100644 drivers/nvme/target/fabrics-cmd-auth.c
 create mode 100644 include/crypto/ffdhe.h
 create mode 100644 include/linux/base64.h
 create mode 100644 lib/base64.c
Signature · 1 line
2.29.2
author maintainer
#1 lore raw

PATCH v5 1/12 crypto: add crypto_has_shash()

Add helper function to determine if a given synchronous hash is supported.

---
 crypto/shash.c        | 6 ++++++
 include/crypto/hash.h | 2 ++
 2 files changed, 8 insertions(+)
crypto/shash.c +6 -0
index 0a0a50cb694f..4c88e63b3350 100644
@@ -521,6 +521,12 @@ struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_shash);
 
+int crypto_has_shash(const char *alg_name, u32 type, u32 mask)
+{
+	return crypto_type_has_alg(alg_name, &crypto_shash_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_has_shash);
+
 static int shash_prepare_alg(struct shash_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
include/crypto/hash.h +2 -0
index f140e4643949..f5841992dc9b 100644
@@ -718,6 +718,8 @@ static inline void ahash_request_set_crypt(struct ahash_request *req,
 struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
 					u32 mask);
 
+int crypto_has_shash(const char *alg_name, u32 type, u32 mask);
+
 static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)
 {
 	return &tfm->base;
Signature · 1 line
2.29.2
Reviewed-by on v5 1/12
#2 lore raw

Re: [PATCH 01/12] crypto: add crypto_has_shash()

Quoted 33 lines · Hannes Reinecke

Add helper function to determine if a given synchronous hash is supported.

---
  crypto/shash.c        | 6 ++++++
  include/crypto/hash.h | 2 ++
  2 files changed, 8 insertions(+)
crypto/shash.c +6 -0
index 0a0a50cb694f..4c88e63b3350 100644
@@ -521,6 +521,12 @@ struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
  }
  EXPORT_SYMBOL_GPL(crypto_alloc_shash);
 
+int crypto_has_shash(const char *alg_name, u32 type, u32 mask)
+{
+	return crypto_type_has_alg(alg_name, &crypto_shash_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_has_shash);
+
  static int shash_prepare_alg(struct shash_alg *alg)
  {
  	struct crypto_alg *base = &alg->base;
include/crypto/hash.h +0 -0
index f140e4643949..f5841992dc9b 100644

include/crypto/hash.h static inline void ahash_request_set_crypt(struct ahash_request *req, · line 725

Quoted 8 lines
include/crypto/hash.h +2 -0
@@ -718,6 +718,8 @@ static inline void ahash_request_set_crypt(struct ahash_request *req,
  struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
  					u32 mask);
 
+int crypto_has_shash(const char *alg_name, u32 type, u32 mask);
+
  static inline struct crypto_tfm *crypto_shash_tfm(struct crypto_shash *tfm)
  {
  	return &tfm->base;
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
author maintainer
#3 lore raw

PATCH v5 2/12 crypto: add crypto_has_kpp()

In reply to Hannes Reinecke

Add helper function to determine if a given key-agreement protocol primitive is supported.

---
 crypto/kpp.c         | 6 ++++++
 include/crypto/kpp.h | 2 ++
 2 files changed, 8 insertions(+)
crypto/kpp.c +6 -0
index 313b2c699963..416e8a1a03ee 100644
@@ -87,6 +87,12 @@ struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask)
 }
 EXPORT_SYMBOL_GPL(crypto_alloc_kpp);
 
+int crypto_has_kpp(const char *alg_name, u32 type, u32 mask)
+{
+	return crypto_type_has_alg(alg_name, &crypto_kpp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_has_kpp);
+
 static void kpp_prepare_alg(struct kpp_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
include/crypto/kpp.h +2 -0
index cccceadc164b..24d01e9877c1 100644
@@ -104,6 +104,8 @@ struct kpp_alg {
  */
 struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask);
 
+int crypto_has_kpp(const char *alg_name, u32 type, u32 mask);
+
 static inline struct crypto_tfm *crypto_kpp_tfm(struct crypto_kpp *tfm)
 {
 	return &tfm->base;
Signature · 1 line
2.29.2
Reviewed-by on v5 2/12
#4 lore raw

Re: [PATCH 02/12] crypto: add crypto_has_kpp()

Quoted 34 lines · Hannes Reinecke

Add helper function to determine if a given key-agreement protocol primitive is supported.

---
  crypto/kpp.c         | 6 ++++++
  include/crypto/kpp.h | 2 ++
  2 files changed, 8 insertions(+)
crypto/kpp.c +6 -0
index 313b2c699963..416e8a1a03ee 100644
@@ -87,6 +87,12 @@ struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask)
  }
  EXPORT_SYMBOL_GPL(crypto_alloc_kpp);
 
+int crypto_has_kpp(const char *alg_name, u32 type, u32 mask)
+{
+	return crypto_type_has_alg(alg_name, &crypto_kpp_type, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_has_kpp);
+
  static void kpp_prepare_alg(struct kpp_alg *alg)
  {
  	struct crypto_alg *base = &alg->base;
include/crypto/kpp.h +0 -0
index cccceadc164b..24d01e9877c1 100644

include/crypto/kpp.h struct kpp_alg { · line 111

Quoted 8 lines
include/crypto/kpp.h +2 -0
@@ -104,6 +104,8 @@ struct kpp_alg {
   */
  struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask);
 
+int crypto_has_kpp(const char *alg_name, u32 type, u32 mask);
+
  static inline struct crypto_tfm *crypto_kpp_tfm(struct crypto_kpp *tfm)
  {
  	return &tfm->base;
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
author maintainer
#5 lore raw

PATCH v5 3/12 crypto/ffdhe: Finite Field DH Ephemeral Parameters

In reply to Hannes Reinecke

Add helper functions to generaten Finite Field DH Ephemeral Parameters as specified in RFC 7919.

---
 crypto/Kconfig         |   8 +
 crypto/Makefile        |   1 +
 crypto/ffdhe_helper.c  | 880 +++++++++++++++++++++++++++++++++++++++++
 include/crypto/ffdhe.h |  24 ++
 4 files changed, 913 insertions(+)
 create mode 100644 crypto/ffdhe_helper.c
 create mode 100644 include/crypto/ffdhe.h
crypto/Kconfig +8 -0
index 285f82647d2b..0181d2a2982c 100644
@@ -231,6 +231,14 @@ config CRYPTO_DH
 	help
 	  Generic implementation of the Diffie-Hellman algorithm.
 
+config CRYPTO_FFDHE
+	tristate "Finite Field DH (RFC 7919) ephemeral parameters"
+	select CRYPTO_DH
+	select CRYPTO_KPP
+	select CRYPTO_RNG_DEFAULT
+	help
+	  Generic implementation of the Finite Field DH algorithm
+
 config CRYPTO_ECC
 	tristate
 	select CRYPTO_RNG_DEFAULT
crypto/Makefile +1 -0
index 429c4d57458c..2c4049ec12fc 100644
@@ -178,6 +178,7 @@ obj-$(CONFIG_CRYPTO_OFB) += ofb.o
 obj-$(CONFIG_CRYPTO_ECC) += ecc.o
 obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o
 obj-$(CONFIG_CRYPTO_CURVE25519) += curve25519-generic.o
+obj-$(CONFIG_CRYPTO_FFDHE) += ffdhe_helper.o
 
 ecdh_generic-y += ecdh.o
 ecdh_generic-y += ecdh_helper.o
crypto/ffdhe_helper.c new file +880 -0

880 lines not on this page · raw message

include/crypto/ffdhe.h new file +24 -0
new file mode 100644
index 000000000000..6cb9253ddb34
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Finite-Field Diffie-Hellman definition according to RFC 7919
+ *
+ * Copyright (c) 2021, SUSE Software Products
+ * Authors: Hannes Reinecke <[email protected]>
+ */
+#ifndef _CRYPTO_FFDHE_
+#define _CRYPTO_FFDHE_
+
+/**
+ * crypto_ffdhe_params() - Generate FFDHE params
+ * @params: DH params
+ * @bits: Bitsize of the FFDHE parameters
+ *
+ * This functions sets the FFDHE parameter for @bits in @params.
+ * Valid bit sizes are 2048, 3072, 4096, 6144, or 8194.
+ *
+ * Returns: 0 on success, errno on failure.
+ */
+
+int crypto_ffdhe_params(struct dh *p, int bits);
+
+#endif /* _CRYPTO_FFDHE_H */
Signature · 1 line
2.29.2
Reviewed-by on v5 3/12
#7 lore raw

Re: [PATCH 03/12] crypto/ffdhe: Finite Field DH Ephemeral Parameters

In reply to Hannes Reinecke
Quoted 951 lines · Hannes Reinecke

Add helper functions to generaten Finite Field DH Ephemeral Parameters as specified in RFC 7919.

---
  crypto/Kconfig         |   8 +
  crypto/Makefile        |   1 +
  crypto/ffdhe_helper.c  | 880 +++++++++++++++++++++++++++++++++++++++++
  include/crypto/ffdhe.h |  24 ++
  4 files changed, 913 insertions(+)

create mode 100644 crypto/ffdhe_helper.c
create mode 100644 include/crypto/ffdhe.h

crypto/Kconfig +8 -0
index 285f82647d2b..0181d2a2982c 100644
@@ -231,6 +231,14 @@ config CRYPTO_DH
  	help
  	  Generic implementation of the Diffie-Hellman algorithm.
 
+config CRYPTO_FFDHE
+	tristate "Finite Field DH (RFC 7919) ephemeral parameters"
+	select CRYPTO_DH
+	select CRYPTO_KPP
+	select CRYPTO_RNG_DEFAULT
+	help
+	  Generic implementation of the Finite Field DH algorithm
+
  config CRYPTO_ECC
  	tristate
  	select CRYPTO_RNG_DEFAULT
crypto/Makefile +1 -0
index 429c4d57458c..2c4049ec12fc 100644
@@ -178,6 +178,7 @@ obj-$(CONFIG_CRYPTO_OFB) += ofb.o
  obj-$(CONFIG_CRYPTO_ECC) += ecc.o
  obj-$(CONFIG_CRYPTO_ESSIV) += essiv.o
  obj-$(CONFIG_CRYPTO_CURVE25519) += curve25519-generic.o
+obj-$(CONFIG_CRYPTO_FFDHE) += ffdhe_helper.o
 
  ecdh_generic-y += ecdh.o
  ecdh_generic-y += ecdh_helper.o
crypto/ffdhe_helper.c new file +880 -0
new file mode 100644
index 000000000000..d7018bc3a8ec
@@ -0,0 +1,880 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Finite Field DH Ephemeral Parameters
+ * Values are taken from RFC 7919 Appendix A
+ *
+ * Copyright (c) 2021, Hannes Reinecke, SUSE Software Products
+ */
+
+#include <linux/module.h>
+#include <crypto/internal/kpp.h>
+#include <crypto/kpp.h>
+#include <crypto/dh.h>
+#include <crypto/ffdhe.h>
+#include <linux/mpi.h>
+/*
+ * ffdhe2048 generator (g), modulus (p) and group size (q)
+ */
+const u8 ffdhe2048_g[] = { 0x02 };
+
+const u8 ffdhe2048_p[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
+	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
+	0xd8,0xb9,0xc5,0x83,0xce,0x2d,0x36,0x95,
+	0xa9,0xe1,0x36,0x41,0x14,0x64,0x33,0xfb,
+	0xcc,0x93,0x9d,0xce,0x24,0x9b,0x3e,0xf9,
+	0x7d,0x2f,0xe3,0x63,0x63,0x0c,0x75,0xd8,
+	0xf6,0x81,0xb2,0x02,0xae,0xc4,0x61,0x7a,
+	0xd3,0xdf,0x1e,0xd5,0xd5,0xfd,0x65,0x61,
+	0x24,0x33,0xf5,0x1f,0x5f,0x06,0x6e,0xd0,
+	0x85,0x63,0x65,0x55,0x3d,0xed,0x1a,0xf3,
+	0xb5,0x57,0x13,0x5e,0x7f,0x57,0xc9,0x35,
+	0x98,0x4f,0x0c,0x70,0xe0,0xe6,0x8b,0x77,
+	0xe2,0xa6,0x89,0xda,0xf3,0xef,0xe8,0x72,
+	0x1d,0xf1,0x58,0xa1,0x36,0xad,0xe7,0x35,
+	0x30,0xac,0xca,0x4f,0x48,0x3a,0x79,0x7a,
+	0xbc,0x0a,0xb1,0x82,0xb3,0x24,0xfb,0x61,
+	0xd1,0x08,0xa9,0x4b,0xb2,0xc8,0xe3,0xfb,
+	0xb9,0x6a,0xda,0xb7,0x60,0xd7,0xf4,0x68,
+	0x1d,0x4f,0x42,0xa3,0xde,0x39,0x4d,0xf4,
+	0xae,0x56,0xed,0xe7,0x63,0x72,0xbb,0x19,
+	0x0b,0x07,0xa7,0xc8,0xee,0x0a,0x6d,0x70,
+	0x9e,0x02,0xfc,0xe1,0xcd,0xf7,0xe2,0xec,
+	0xc0,0x34,0x04,0xcd,0x28,0x34,0x2f,0x61,
+	0x91,0x72,0xfe,0x9c,0xe9,0x85,0x83,0xff,
+	0x8e,0x4f,0x12,0x32,0xee,0xf2,0x81,0x83,
+	0xc3,0xfe,0x3b,0x1b,0x4c,0x6f,0xad,0x73,
+	0x3b,0xb5,0xfc,0xbc,0x2e,0xc2,0x20,0x05,
+	0xc5,0x8e,0xf1,0x83,0x7d,0x16,0x83,0xb2,
+	0xc6,0xf3,0x4a,0x26,0xc1,0xb2,0xef,0xfa,
+	0x88,0x6b,0x42,0x38,0x61,0x28,0x5c,0x97,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const u8 ffdhe2048_q[] = {
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
+	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
+	0xec,0x5c,0xe2,0xc1,0xe7,0x16,0x9b,0x4a,
+	0xd4,0xf0,0x9b,0x20,0x8a,0x32,0x19,0xfd,
+	0xe6,0x49,0xce,0xe7,0x12,0x4d,0x9f,0x7c,
+	0xbe,0x97,0xf1,0xb1,0xb1,0x86,0x3a,0xec,
+	0x7b,0x40,0xd9,0x01,0x57,0x62,0x30,0xbd,
+	0x69,0xef,0x8f,0x6a,0xea,0xfe,0xb2,0xb0,
+	0x92,0x19,0xfa,0x8f,0xaf,0x83,0x37,0x68,
+	0x42,0xb1,0xb2,0xaa,0x9e,0xf6,0x8d,0x79,
+	0xda,0xab,0x89,0xaf,0x3f,0xab,0xe4,0x9a,
+	0xcc,0x27,0x86,0x38,0x70,0x73,0x45,0xbb,
+	0xf1,0x53,0x44,0xed,0x79,0xf7,0xf4,0x39,
+	0x0e,0xf8,0xac,0x50,0x9b,0x56,0xf3,0x9a,
+	0x98,0x56,0x65,0x27,0xa4,0x1d,0x3c,0xbd,
+	0x5e,0x05,0x58,0xc1,0x59,0x92,0x7d,0xb0,
+	0xe8,0x84,0x54,0xa5,0xd9,0x64,0x71,0xfd,
+	0xdc,0xb5,0x6d,0x5b,0xb0,0x6b,0xfa,0x34,
+	0x0e,0xa7,0xa1,0x51,0xef,0x1c,0xa6,0xfa,
+	0x57,0x2b,0x76,0xf3,0xb1,0xb9,0x5d,0x8c,
+	0x85,0x83,0xd3,0xe4,0x77,0x05,0x36,0xb8,
+	0x4f,0x01,0x7e,0x70,0xe6,0xfb,0xf1,0x76,
+	0x60,0x1a,0x02,0x66,0x94,0x1a,0x17,0xb0,
+	0xc8,0xb9,0x7f,0x4e,0x74,0xc2,0xc1,0xff,
+	0xc7,0x27,0x89,0x19,0x77,0x79,0x40,0xc1,
+	0xe1,0xff,0x1d,0x8d,0xa6,0x37,0xd6,0xb9,
+	0x9d,0xda,0xfe,0x5e,0x17,0x61,0x10,0x02,
+	0xe2,0xc7,0x78,0xc1,0xbe,0x8b,0x41,0xd9,
+	0x63,0x79,0xa5,0x13,0x60,0xd9,0x77,0xfd,
+	0x44,0x35,0xa1,0x1c,0x30,0x94,0x2e,0x4b,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+/*
+ * ffdhe3072 generator (g), modulus (p) and group size (q)
+ */
+
+const u8 ffdhe3072_g[] = { 0x02 };
+
+const u8 ffdhe3072_p[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
+	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
+	0xd8,0xb9,0xc5,0x83,0xce,0x2d,0x36,0x95,
+	0xa9,0xe1,0x36,0x41,0x14,0x64,0x33,0xfb,
+	0xcc,0x93,0x9d,0xce,0x24,0x9b,0x3e,0xf9,
+	0x7d,0x2f,0xe3,0x63,0x63,0x0c,0x75,0xd8,
+	0xf6,0x81,0xb2,0x02,0xae,0xc4,0x61,0x7a,
+	0xd3,0xdf,0x1e,0xd5,0xd5,0xfd,0x65,0x61,
+	0x24,0x33,0xf5,0x1f,0x5f,0x06,0x6e,0xd0,
+	0x85,0x63,0x65,0x55,0x3d,0xed,0x1a,0xf3,
+	0xb5,0x57,0x13,0x5e,0x7f,0x57,0xc9,0x35,
+	0x98,0x4f,0x0c,0x70,0xe0,0xe6,0x8b,0x77,
+	0xe2,0xa6,0x89,0xda,0xf3,0xef,0xe8,0x72,
+	0x1d,0xf1,0x58,0xa1,0x36,0xad,0xe7,0x35,
+	0x30,0xac,0xca,0x4f,0x48,0x3a,0x79,0x7a,
+	0xbc,0x0a,0xb1,0x82,0xb3,0x24,0xfb,0x61,
+	0xd1,0x08,0xa9,0x4b,0xb2,0xc8,0xe3,0xfb,
+	0xb9,0x6a,0xda,0xb7,0x60,0xd7,0xf4,0x68,
+	0x1d,0x4f,0x42,0xa3,0xde,0x39,0x4d,0xf4,
+	0xae,0x56,0xed,0xe7,0x63,0x72,0xbb,0x19,
+	0x0b,0x07,0xa7,0xc8,0xee,0x0a,0x6d,0x70,
+	0x9e,0x02,0xfc,0xe1,0xcd,0xf7,0xe2,0xec,
+	0xc0,0x34,0x04,0xcd,0x28,0x34,0x2f,0x61,
+	0x91,0x72,0xfe,0x9c,0xe9,0x85,0x83,0xff,
+	0x8e,0x4f,0x12,0x32,0xee,0xf2,0x81,0x83,
+	0xc3,0xfe,0x3b,0x1b,0x4c,0x6f,0xad,0x73,
+	0x3b,0xb5,0xfc,0xbc,0x2e,0xc2,0x20,0x05,
+	0xc5,0x8e,0xf1,0x83,0x7d,0x16,0x83,0xb2,
+	0xc6,0xf3,0x4a,0x26,0xc1,0xb2,0xef,0xfa,
+	0x88,0x6b,0x42,0x38,0x61,0x1f,0xcf,0xdc,
+	0xde,0x35,0x5b,0x3b,0x65,0x19,0x03,0x5b,
+	0xbc,0x34,0xf4,0xde,0xf9,0x9c,0x02,0x38,
+	0x61,0xb4,0x6f,0xc9,0xd6,0xe6,0xc9,0x07,
+	0x7a,0xd9,0x1d,0x26,0x91,0xf7,0xf7,0xee,
+	0x59,0x8c,0xb0,0xfa,0xc1,0x86,0xd9,0x1c,
+	0xae,0xfe,0x13,0x09,0x85,0x13,0x92,0x70,
+	0xb4,0x13,0x0c,0x93,0xbc,0x43,0x79,0x44,
+	0xf4,0xfd,0x44,0x52,0xe2,0xd7,0x4d,0xd3,
+	0x64,0xf2,0xe2,0x1e,0x71,0xf5,0x4b,0xff,
+	0x5c,0xae,0x82,0xab,0x9c,0x9d,0xf6,0x9e,
+	0xe8,0x6d,0x2b,0xc5,0x22,0x36,0x3a,0x0d,
+	0xab,0xc5,0x21,0x97,0x9b,0x0d,0xea,0xda,
+	0x1d,0xbf,0x9a,0x42,0xd5,0xc4,0x48,0x4e,
+	0x0a,0xbc,0xd0,0x6b,0xfa,0x53,0xdd,0xef,
+	0x3c,0x1b,0x20,0xee,0x3f,0xd5,0x9d,0x7c,
+	0x25,0xe4,0x1d,0x2b,0x66,0xc6,0x2e,0x37,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const u8 ffdhe3072_q[] = {
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
+	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
+	0xec,0x5c,0xe2,0xc1,0xe7,0x16,0x9b,0x4a,
+	0xd4,0xf0,0x9b,0x20,0x8a,0x32,0x19,0xfd,
+	0xe6,0x49,0xce,0xe7,0x12,0x4d,0x9f,0x7c,
+	0xbe,0x97,0xf1,0xb1,0xb1,0x86,0x3a,0xec,
+	0x7b,0x40,0xd9,0x01,0x57,0x62,0x30,0xbd,
+	0x69,0xef,0x8f,0x6a,0xea,0xfe,0xb2,0xb0,
+	0x92,0x19,0xfa,0x8f,0xaf,0x83,0x37,0x68,
+	0x42,0xb1,0xb2,0xaa,0x9e,0xf6,0x8d,0x79,
+	0xda,0xab,0x89,0xaf,0x3f,0xab,0xe4,0x9a,
+	0xcc,0x27,0x86,0x38,0x70,0x73,0x45,0xbb,
+	0xf1,0x53,0x44,0xed,0x79,0xf7,0xf4,0x39,
+	0x0e,0xf8,0xac,0x50,0x9b,0x56,0xf3,0x9a,
+	0x98,0x56,0x65,0x27,0xa4,0x1d,0x3c,0xbd,
+	0x5e,0x05,0x58,0xc1,0x59,0x92,0x7d,0xb0,
+	0xe8,0x84,0x54,0xa5,0xd9,0x64,0x71,0xfd,
+	0xdc,0xb5,0x6d,0x5b,0xb0,0x6b,0xfa,0x34,
+	0x0e,0xa7,0xa1,0x51,0xef,0x1c,0xa6,0xfa,
+	0x57,0x2b,0x76,0xf3,0xb1,0xb9,0x5d,0x8c,
+	0x85,0x83,0xd3,0xe4,0x77,0x05,0x36,0xb8,
+	0x4f,0x01,0x7e,0x70,0xe6,0xfb,0xf1,0x76,
+	0x60,0x1a,0x02,0x66,0x94,0x1a,0x17,0xb0,
+	0xc8,0xb9,0x7f,0x4e,0x74,0xc2,0xc1,0xff,
+	0xc7,0x27,0x89,0x19,0x77,0x79,0x40,0xc1,
+	0xe1,0xff,0x1d,0x8d,0xa6,0x37,0xd6,0xb9,
+	0x9d,0xda,0xfe,0x5e,0x17,0x61,0x10,0x02,
+	0xe2,0xc7,0x78,0xc1,0xbe,0x8b,0x41,0xd9,
+	0x63,0x79,0xa5,0x13,0x60,0xd9,0x77,0xfd,
+	0x44,0x35,0xa1,0x1c,0x30,0x8f,0xe7,0xee,
+	0x6f,0x1a,0xad,0x9d,0xb2,0x8c,0x81,0xad,
+	0xde,0x1a,0x7a,0x6f,0x7c,0xce,0x01,0x1c,
+	0x30,0xda,0x37,0xe4,0xeb,0x73,0x64,0x83,
+	0xbd,0x6c,0x8e,0x93,0x48,0xfb,0xfb,0xf7,
+	0x2c,0xc6,0x58,0x7d,0x60,0xc3,0x6c,0x8e,
+	0x57,0x7f,0x09,0x84,0xc2,0x89,0xc9,0x38,
+	0x5a,0x09,0x86,0x49,0xde,0x21,0xbc,0xa2,
+	0x7a,0x7e,0xa2,0x29,0x71,0x6b,0xa6,0xe9,
+	0xb2,0x79,0x71,0x0f,0x38,0xfa,0xa5,0xff,
+	0xae,0x57,0x41,0x55,0xce,0x4e,0xfb,0x4f,
+	0x74,0x36,0x95,0xe2,0x91,0x1b,0x1d,0x06,
+	0xd5,0xe2,0x90,0xcb,0xcd,0x86,0xf5,0x6d,
+	0x0e,0xdf,0xcd,0x21,0x6a,0xe2,0x24,0x27,
+	0x05,0x5e,0x68,0x35,0xfd,0x29,0xee,0xf7,
+	0x9e,0x0d,0x90,0x77,0x1f,0xea,0xce,0xbe,
+	0x12,0xf2,0x0e,0x95,0xb3,0x63,0x17,0x1b,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+/*
+ * ffdhe4096 generator (g), modulus (p) and group size (q)
+ */
+
+const u8 ffdhe4096_g[] = { 0x02 };
+
+const u8 ffdhe4096_p[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
+	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
+	0xd8,0xb9,0xc5,0x83,0xce,0x2d,0x36,0x95,
+	0xa9,0xe1,0x36,0x41,0x14,0x64,0x33,0xfb,
+	0xcc,0x93,0x9d,0xce,0x24,0x9b,0x3e,0xf9,
+	0x7d,0x2f,0xe3,0x63,0x63,0x0c,0x75,0xd8,
+	0xf6,0x81,0xb2,0x02,0xae,0xc4,0x61,0x7a,
+	0xd3,0xdf,0x1e,0xd5,0xd5,0xfd,0x65,0x61,
+	0x24,0x33,0xf5,0x1f,0x5f,0x06,0x6e,0xd0,
+	0x85,0x63,0x65,0x55,0x3d,0xed,0x1a,0xf3,
+	0xb5,0x57,0x13,0x5e,0x7f,0x57,0xc9,0x35,
+	0x98,0x4f,0x0c,0x70,0xe0,0xe6,0x8b,0x77,
+	0xe2,0xa6,0x89,0xda,0xf3,0xef,0xe8,0x72,
+	0x1d,0xf1,0x58,0xa1,0x36,0xad,0xe7,0x35,
+	0x30,0xac,0xca,0x4f,0x48,0x3a,0x79,0x7a,
+	0xbc,0x0a,0xb1,0x82,0xb3,0x24,0xfb,0x61,
+	0xd1,0x08,0xa9,0x4b,0xb2,0xc8,0xe3,0xfb,
+	0xb9,0x6a,0xda,0xb7,0x60,0xd7,0xf4,0x68,
+	0x1d,0x4f,0x42,0xa3,0xde,0x39,0x4d,0xf4,
+	0xae,0x56,0xed,0xe7,0x63,0x72,0xbb,0x19,
+	0x0b,0x07,0xa7,0xc8,0xee,0x0a,0x6d,0x70,
+	0x9e,0x02,0xfc,0xe1,0xcd,0xf7,0xe2,0xec,
+	0xc0,0x34,0x04,0xcd,0x28,0x34,0x2f,0x61,
+	0x91,0x72,0xfe,0x9c,0xe9,0x85,0x83,0xff,
+	0x8e,0x4f,0x12,0x32,0xee,0xf2,0x81,0x83,
+	0xc3,0xfe,0x3b,0x1b,0x4c,0x6f,0xad,0x73,
+	0x3b,0xb5,0xfc,0xbc,0x2e,0xc2,0x20,0x05,
+	0xc5,0x8e,0xf1,0x83,0x7d,0x16,0x83,0xb2,
+	0xc6,0xf3,0x4a,0x26,0xc1,0xb2,0xef,0xfa,
+	0x88,0x6b,0x42,0x38,0x61,0x1f,0xcf,0xdc,
+	0xde,0x35,0x5b,0x3b,0x65,0x19,0x03,0x5b,
+	0xbc,0x34,0xf4,0xde,0xf9,0x9c,0x02,0x38,
+	0x61,0xb4,0x6f,0xc9,0xd6,0xe6,0xc9,0x07,
+	0x7a,0xd9,0x1d,0x26,0x91,0xf7,0xf7,0xee,
+	0x59,0x8c,0xb0,0xfa,0xc1,0x86,0xd9,0x1c,
+	0xae,0xfe,0x13,0x09,0x85,0x13,0x92,0x70,
+	0xb4,0x13,0x0c,0x93,0xbc,0x43,0x79,0x44,
+	0xf4,0xfd,0x44,0x52,0xe2,0xd7,0x4d,0xd3,
+	0x64,0xf2,0xe2,0x1e,0x71,0xf5,0x4b,0xff,
+	0x5c,0xae,0x82,0xab,0x9c,0x9d,0xf6,0x9e,
+	0xe8,0x6d,0x2b,0xc5,0x22,0x36,0x3a,0x0d,
+	0xab,0xc5,0x21,0x97,0x9b,0x0d,0xea,0xda,
+	0x1d,0xbf,0x9a,0x42,0xd5,0xc4,0x48,0x4e,
+	0x0a,0xbc,0xd0,0x6b,0xfa,0x53,0xdd,0xef,
+	0x3c,0x1b,0x20,0xee,0x3f,0xd5,0x9d,0x7c,
+	0x25,0xe4,0x1d,0x2b,0x66,0x9e,0x1e,0xf1,
+	0x6e,0x6f,0x52,0xc3,0x16,0x4d,0xf4,0xfb,
+	0x79,0x30,0xe9,0xe4,0xe5,0x88,0x57,0xb6,
+	0xac,0x7d,0x5f,0x42,0xd6,0x9f,0x6d,0x18,
+	0x77,0x63,0xcf,0x1d,0x55,0x03,0x40,0x04,
+	0x87,0xf5,0x5b,0xa5,0x7e,0x31,0xcc,0x7a,
+	0x71,0x35,0xc8,0x86,0xef,0xb4,0x31,0x8a,
+	0xed,0x6a,0x1e,0x01,0x2d,0x9e,0x68,0x32,
+	0xa9,0x07,0x60,0x0a,0x91,0x81,0x30,0xc4,
+	0x6d,0xc7,0x78,0xf9,0x71,0xad,0x00,0x38,
+	0x09,0x29,0x99,0xa3,0x33,0xcb,0x8b,0x7a,
+	0x1a,0x1d,0xb9,0x3d,0x71,0x40,0x00,0x3c,
+	0x2a,0x4e,0xce,0xa9,0xf9,0x8d,0x0a,0xcc,
+	0x0a,0x82,0x91,0xcd,0xce,0xc9,0x7d,0xcf,
+	0x8e,0xc9,0xb5,0x5a,0x7f,0x88,0xa4,0x6b,
+	0x4d,0xb5,0xa8,0x51,0xf4,0x41,0x82,0xe1,
+	0xc6,0x8a,0x00,0x7e,0x5e,0x65,0x5f,0x6a,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const u8 ffdhe4096_q[] = {
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
+	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
+	0xec,0x5c,0xe2,0xc1,0xe7,0x16,0x9b,0x4a,
+	0xd4,0xf0,0x9b,0x20,0x8a,0x32,0x19,0xfd,
+	0xe6,0x49,0xce,0xe7,0x12,0x4d,0x9f,0x7c,
+	0xbe,0x97,0xf1,0xb1,0xb1,0x86,0x3a,0xec,
+	0x7b,0x40,0xd9,0x01,0x57,0x62,0x30,0xbd,
+	0x69,0xef,0x8f,0x6a,0xea,0xfe,0xb2,0xb0,
+	0x92,0x19,0xfa,0x8f,0xaf,0x83,0x37,0x68,
+	0x42,0xb1,0xb2,0xaa,0x9e,0xf6,0x8d,0x79,
+	0xda,0xab,0x89,0xaf,0x3f,0xab,0xe4,0x9a,
+	0xcc,0x27,0x86,0x38,0x70,0x73,0x45,0xbb,
+	0xf1,0x53,0x44,0xed,0x79,0xf7,0xf4,0x39,
+	0x0e,0xf8,0xac,0x50,0x9b,0x56,0xf3,0x9a,
+	0x98,0x56,0x65,0x27,0xa4,0x1d,0x3c,0xbd,
+	0x5e,0x05,0x58,0xc1,0x59,0x92,0x7d,0xb0,
+	0xe8,0x84,0x54,0xa5,0xd9,0x64,0x71,0xfd,
+	0xdc,0xb5,0x6d,0x5b,0xb0,0x6b,0xfa,0x34,
+	0x0e,0xa7,0xa1,0x51,0xef,0x1c,0xa6,0xfa,
+	0x57,0x2b,0x76,0xf3,0xb1,0xb9,0x5d,0x8c,
+	0x85,0x83,0xd3,0xe4,0x77,0x05,0x36,0xb8,
+	0x4f,0x01,0x7e,0x70,0xe6,0xfb,0xf1,0x76,
+	0x60,0x1a,0x02,0x66,0x94,0x1a,0x17,0xb0,
+	0xc8,0xb9,0x7f,0x4e,0x74,0xc2,0xc1,0xff,
+	0xc7,0x27,0x89,0x19,0x77,0x79,0x40,0xc1,
+	0xe1,0xff,0x1d,0x8d,0xa6,0x37,0xd6,0xb9,
+	0x9d,0xda,0xfe,0x5e,0x17,0x61,0x10,0x02,
+	0xe2,0xc7,0x78,0xc1,0xbe,0x8b,0x41,0xd9,
+	0x63,0x79,0xa5,0x13,0x60,0xd9,0x77,0xfd,
+	0x44,0x35,0xa1,0x1c,0x30,0x8f,0xe7,0xee,
+	0x6f,0x1a,0xad,0x9d,0xb2,0x8c,0x81,0xad,
+	0xde,0x1a,0x7a,0x6f,0x7c,0xce,0x01,0x1c,
+	0x30,0xda,0x37,0xe4,0xeb,0x73,0x64,0x83,
+	0xbd,0x6c,0x8e,0x93,0x48,0xfb,0xfb,0xf7,
+	0x2c,0xc6,0x58,0x7d,0x60,0xc3,0x6c,0x8e,
+	0x57,0x7f,0x09,0x84,0xc2,0x89,0xc9,0x38,
+	0x5a,0x09,0x86,0x49,0xde,0x21,0xbc,0xa2,
+	0x7a,0x7e,0xa2,0x29,0x71,0x6b,0xa6,0xe9,
+	0xb2,0x79,0x71,0x0f,0x38,0xfa,0xa5,0xff,
+	0xae,0x57,0x41,0x55,0xce,0x4e,0xfb,0x4f,
+	0x74,0x36,0x95,0xe2,0x91,0x1b,0x1d,0x06,
+	0xd5,0xe2,0x90,0xcb,0xcd,0x86,0xf5,0x6d,
+	0x0e,0xdf,0xcd,0x21,0x6a,0xe2,0x24,0x27,
+	0x05,0x5e,0x68,0x35,0xfd,0x29,0xee,0xf7,
+	0x9e,0x0d,0x90,0x77,0x1f,0xea,0xce,0xbe,
+	0x12,0xf2,0x0e,0x95,0xb3,0x4f,0x0f,0x78,
+	0xb7,0x37,0xa9,0x61,0x8b,0x26,0xfa,0x7d,
+	0xbc,0x98,0x74,0xf2,0x72,0xc4,0x2b,0xdb,
+	0x56,0x3e,0xaf,0xa1,0x6b,0x4f,0xb6,0x8c,
+	0x3b,0xb1,0xe7,0x8e,0xaa,0x81,0xa0,0x02,
+	0x43,0xfa,0xad,0xd2,0xbf,0x18,0xe6,0x3d,
+	0x38,0x9a,0xe4,0x43,0x77,0xda,0x18,0xc5,
+	0x76,0xb5,0x0f,0x00,0x96,0xcf,0x34,0x19,
+	0x54,0x83,0xb0,0x05,0x48,0xc0,0x98,0x62,
+	0x36,0xe3,0xbc,0x7c,0xb8,0xd6,0x80,0x1c,
+	0x04,0x94,0xcc,0xd1,0x99,0xe5,0xc5,0xbd,
+	0x0d,0x0e,0xdc,0x9e,0xb8,0xa0,0x00,0x1e,
+	0x15,0x27,0x67,0x54,0xfc,0xc6,0x85,0x66,
+	0x05,0x41,0x48,0xe6,0xe7,0x64,0xbe,0xe7,
+	0xc7,0x64,0xda,0xad,0x3f,0xc4,0x52,0x35,
+	0xa6,0xda,0xd4,0x28,0xfa,0x20,0xc1,0x70,
+	0xe3,0x45,0x00,0x3f,0x2f,0x32,0xaf,0xb5,
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+/*
+ * ffdhe6144 generator (g), modulus (p) and group size (q)
+ */
+
+const u8 ffdhe6144_g[] = { 0x02 };
+
+const u8 ffdhe6144_p[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
+	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
+	0xd8,0xb9,0xc5,0x83,0xce,0x2d,0x36,0x95,
+	0xa9,0xe1,0x36,0x41,0x14,0x64,0x33,0xfb,
+	0xcc,0x93,0x9d,0xce,0x24,0x9b,0x3e,0xf9,
+	0x7d,0x2f,0xe3,0x63,0x63,0x0c,0x75,0xd8,
+	0xf6,0x81,0xb2,0x02,0xae,0xc4,0x61,0x7a,
+	0xd3,0xdf,0x1e,0xd5,0xd5,0xfd,0x65,0x61,
+	0x24,0x33,0xf5,0x1f,0x5f,0x06,0x6e,0xd0,
+	0x85,0x63,0x65,0x55,0x3d,0xed,0x1a,0xf3,
+	0xb5,0x57,0x13,0x5e,0x7f,0x57,0xc9,0x35,
+	0x98,0x4f,0x0c,0x70,0xe0,0xe6,0x8b,0x77,
+	0xe2,0xa6,0x89,0xda,0xf3,0xef,0xe8,0x72,
+	0x1d,0xf1,0x58,0xa1,0x36,0xad,0xe7,0x35,
+	0x30,0xac,0xca,0x4f,0x48,0x3a,0x79,0x7a,
+	0xbc,0x0a,0xb1,0x82,0xb3,0x24,0xfb,0x61,
+	0xd1,0x08,0xa9,0x4b,0xb2,0xc8,0xe3,0xfb,
+	0xb9,0x6a,0xda,0xb7,0x60,0xd7,0xf4,0x68,
+	0x1d,0x4f,0x42,0xa3,0xde,0x39,0x4d,0xf4,
+	0xae,0x56,0xed,0xe7,0x63,0x72,0xbb,0x19,
+	0x0b,0x07,0xa7,0xc8,0xee,0x0a,0x6d,0x70,
+	0x9e,0x02,0xfc,0xe1,0xcd,0xf7,0xe2,0xec,
+	0xc0,0x34,0x04,0xcd,0x28,0x34,0x2f,0x61,
+	0x91,0x72,0xfe,0x9c,0xe9,0x85,0x83,0xff,
+	0x8e,0x4f,0x12,0x32,0xee,0xf2,0x81,0x83,
+	0xc3,0xfe,0x3b,0x1b,0x4c,0x6f,0xad,0x73,
+	0x3b,0xb5,0xfc,0xbc,0x2e,0xc2,0x20,0x05,
+	0xc5,0x8e,0xf1,0x83,0x7d,0x16,0x83,0xb2,
+	0xc6,0xf3,0x4a,0x26,0xc1,0xb2,0xef,0xfa,
+	0x88,0x6b,0x42,0x38,0x61,0x1f,0xcf,0xdc,
+	0xde,0x35,0x5b,0x3b,0x65,0x19,0x03,0x5b,
+	0xbc,0x34,0xf4,0xde,0xf9,0x9c,0x02,0x38,
+	0x61,0xb4,0x6f,0xc9,0xd6,0xe6,0xc9,0x07,
+	0x7a,0xd9,0x1d,0x26,0x91,0xf7,0xf7,0xee,
+	0x59,0x8c,0xb0,0xfa,0xc1,0x86,0xd9,0x1c,
+	0xae,0xfe,0x13,0x09,0x85,0x13,0x92,0x70,
+	0xb4,0x13,0x0c,0x93,0xbc,0x43,0x79,0x44,
+	0xf4,0xfd,0x44,0x52,0xe2,0xd7,0x4d,0xd3,
+	0x64,0xf2,0xe2,0x1e,0x71,0xf5,0x4b,0xff,
+	0x5c,0xae,0x82,0xab,0x9c,0x9d,0xf6,0x9e,
+	0xe8,0x6d,0x2b,0xc5,0x22,0x36,0x3a,0x0d,
+	0xab,0xc5,0x21,0x97,0x9b,0x0d,0xea,0xda,
+	0x1d,0xbf,0x9a,0x42,0xd5,0xc4,0x48,0x4e,
+	0x0a,0xbc,0xd0,0x6b,0xfa,0x53,0xdd,0xef,
+	0x3c,0x1b,0x20,0xee,0x3f,0xd5,0x9d,0x7c,
+	0x25,0xe4,0x1d,0x2b,0x66,0x9e,0x1e,0xf1,
+	0x6e,0x6f,0x52,0xc3,0x16,0x4d,0xf4,0xfb,
+	0x79,0x30,0xe9,0xe4,0xe5,0x88,0x57,0xb6,
+	0xac,0x7d,0x5f,0x42,0xd6,0x9f,0x6d,0x18,
+	0x77,0x63,0xcf,0x1d,0x55,0x03,0x40,0x04,
+	0x87,0xf5,0x5b,0xa5,0x7e,0x31,0xcc,0x7a,
+	0x71,0x35,0xc8,0x86,0xef,0xb4,0x31,0x8a,
+	0xed,0x6a,0x1e,0x01,0x2d,0x9e,0x68,0x32,
+	0xa9,0x07,0x60,0x0a,0x91,0x81,0x30,0xc4,
+	0x6d,0xc7,0x78,0xf9,0x71,0xad,0x00,0x38,
+	0x09,0x29,0x99,0xa3,0x33,0xcb,0x8b,0x7a,
+	0x1a,0x1d,0xb9,0x3d,0x71,0x40,0x00,0x3c,
+	0x2a,0x4e,0xce,0xa9,0xf9,0x8d,0x0a,0xcc,
+	0x0a,0x82,0x91,0xcd,0xce,0xc9,0x7d,0xcf,
+	0x8e,0xc9,0xb5,0x5a,0x7f,0x88,0xa4,0x6b,
+	0x4d,0xb5,0xa8,0x51,0xf4,0x41,0x82,0xe1,
+	0xc6,0x8a,0x00,0x7e,0x5e,0x0d,0xd9,0x02,
+	0x0b,0xfd,0x64,0xb6,0x45,0x03,0x6c,0x7a,
+	0x4e,0x67,0x7d,0x2c,0x38,0x53,0x2a,0x3a,
+	0x23,0xba,0x44,0x42,0xca,0xf5,0x3e,0xa6,
+	0x3b,0xb4,0x54,0x32,0x9b,0x76,0x24,0xc8,
+	0x91,0x7b,0xdd,0x64,0xb1,0xc0,0xfd,0x4c,
+	0xb3,0x8e,0x8c,0x33,0x4c,0x70,0x1c,0x3a,
+	0xcd,0xad,0x06,0x57,0xfc,0xcf,0xec,0x71,
+	0x9b,0x1f,0x5c,0x3e,0x4e,0x46,0x04,0x1f,
+	0x38,0x81,0x47,0xfb,0x4c,0xfd,0xb4,0x77,
+	0xa5,0x24,0x71,0xf7,0xa9,0xa9,0x69,0x10,
+	0xb8,0x55,0x32,0x2e,0xdb,0x63,0x40,0xd8,
+	0xa0,0x0e,0xf0,0x92,0x35,0x05,0x11,0xe3,
+	0x0a,0xbe,0xc1,0xff,0xf9,0xe3,0xa2,0x6e,
+	0x7f,0xb2,0x9f,0x8c,0x18,0x30,0x23,0xc3,
+	0x58,0x7e,0x38,0xda,0x00,0x77,0xd9,0xb4,
+	0x76,0x3e,0x4e,0x4b,0x94,0xb2,0xbb,0xc1,
+	0x94,0xc6,0x65,0x1e,0x77,0xca,0xf9,0x92,
+	0xee,0xaa,0xc0,0x23,0x2a,0x28,0x1b,0xf6,
+	0xb3,0xa7,0x39,0xc1,0x22,0x61,0x16,0x82,
+	0x0a,0xe8,0xdb,0x58,0x47,0xa6,0x7c,0xbe,
+	0xf9,0xc9,0x09,0x1b,0x46,0x2d,0x53,0x8c,
+	0xd7,0x2b,0x03,0x74,0x6a,0xe7,0x7f,0x5e,
+	0x62,0x29,0x2c,0x31,0x15,0x62,0xa8,0x46,
+	0x50,0x5d,0xc8,0x2d,0xb8,0x54,0x33,0x8a,
+	0xe4,0x9f,0x52,0x35,0xc9,0x5b,0x91,0x17,
+	0x8c,0xcf,0x2d,0xd5,0xca,0xce,0xf4,0x03,
+	0xec,0x9d,0x18,0x10,0xc6,0x27,0x2b,0x04,
+	0x5b,0x3b,0x71,0xf9,0xdc,0x6b,0x80,0xd6,
+	0x3f,0xdd,0x4a,0x8e,0x9a,0xdb,0x1e,0x69,
+	0x62,0xa6,0x95,0x26,0xd4,0x31,0x61,0xc1,
+	0xa4,0x1d,0x57,0x0d,0x79,0x38,0xda,0xd4,
+	0xa4,0x0e,0x32,0x9c,0xd0,0xe4,0x0e,0x65,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const u8 ffdhe6144_q[] = {
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
+	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
+	0xec,0x5c,0xe2,0xc1,0xe7,0x16,0x9b,0x4a,
+	0xd4,0xf0,0x9b,0x20,0x8a,0x32,0x19,0xfd,
+	0xe6,0x49,0xce,0xe7,0x12,0x4d,0x9f,0x7c,
+	0xbe,0x97,0xf1,0xb1,0xb1,0x86,0x3a,0xec,
+	0x7b,0x40,0xd9,0x01,0x57,0x62,0x30,0xbd,
+	0x69,0xef,0x8f,0x6a,0xea,0xfe,0xb2,0xb0,
+	0x92,0x19,0xfa,0x8f,0xaf,0x83,0x37,0x68,
+	0x42,0xb1,0xb2,0xaa,0x9e,0xf6,0x8d,0x79,
+	0xda,0xab,0x89,0xaf,0x3f,0xab,0xe4,0x9a,
+	0xcc,0x27,0x86,0x38,0x70,0x73,0x45,0xbb,
+	0xf1,0x53,0x44,0xed,0x79,0xf7,0xf4,0x39,
+	0x0e,0xf8,0xac,0x50,0x9b,0x56,0xf3,0x9a,
+	0x98,0x56,0x65,0x27,0xa4,0x1d,0x3c,0xbd,
+	0x5e,0x05,0x58,0xc1,0x59,0x92,0x7d,0xb0,
+	0xe8,0x84,0x54,0xa5,0xd9,0x64,0x71,0xfd,
+	0xdc,0xb5,0x6d,0x5b,0xb0,0x6b,0xfa,0x34,
+	0x0e,0xa7,0xa1,0x51,0xef,0x1c,0xa6,0xfa,
+	0x57,0x2b,0x76,0xf3,0xb1,0xb9,0x5d,0x8c,
+	0x85,0x83,0xd3,0xe4,0x77,0x05,0x36,0xb8,
+	0x4f,0x01,0x7e,0x70,0xe6,0xfb,0xf1,0x76,
+	0x60,0x1a,0x02,0x66,0x94,0x1a,0x17,0xb0,
+	0xc8,0xb9,0x7f,0x4e,0x74,0xc2,0xc1,0xff,
+	0xc7,0x27,0x89,0x19,0x77,0x79,0x40,0xc1,
+	0xe1,0xff,0x1d,0x8d,0xa6,0x37,0xd6,0xb9,
+	0x9d,0xda,0xfe,0x5e,0x17,0x61,0x10,0x02,
+	0xe2,0xc7,0x78,0xc1,0xbe,0x8b,0x41,0xd9,
+	0x63,0x79,0xa5,0x13,0x60,0xd9,0x77,0xfd,
+	0x44,0x35,0xa1,0x1c,0x30,0x8f,0xe7,0xee,
+	0x6f,0x1a,0xad,0x9d,0xb2,0x8c,0x81,0xad,
+	0xde,0x1a,0x7a,0x6f,0x7c,0xce,0x01,0x1c,
+	0x30,0xda,0x37,0xe4,0xeb,0x73,0x64,0x83,
+	0xbd,0x6c,0x8e,0x93,0x48,0xfb,0xfb,0xf7,
+	0x2c,0xc6,0x58,0x7d,0x60,0xc3,0x6c,0x8e,
+	0x57,0x7f,0x09,0x84,0xc2,0x89,0xc9,0x38,
+	0x5a,0x09,0x86,0x49,0xde,0x21,0xbc,0xa2,
+	0x7a,0x7e,0xa2,0x29,0x71,0x6b,0xa6,0xe9,
+	0xb2,0x79,0x71,0x0f,0x38,0xfa,0xa5,0xff,
+	0xae,0x57,0x41,0x55,0xce,0x4e,0xfb,0x4f,
+	0x74,0x36,0x95,0xe2,0x91,0x1b,0x1d,0x06,
+	0xd5,0xe2,0x90,0xcb,0xcd,0x86,0xf5,0x6d,
+	0x0e,0xdf,0xcd,0x21,0x6a,0xe2,0x24,0x27,
+	0x05,0x5e,0x68,0x35,0xfd,0x29,0xee,0xf7,
+	0x9e,0x0d,0x90,0x77,0x1f,0xea,0xce,0xbe,
+	0x12,0xf2,0x0e,0x95,0xb3,0x4f,0x0f,0x78,
+	0xb7,0x37,0xa9,0x61,0x8b,0x26,0xfa,0x7d,
+	0xbc,0x98,0x74,0xf2,0x72,0xc4,0x2b,0xdb,
+	0x56,0x3e,0xaf,0xa1,0x6b,0x4f,0xb6,0x8c,
+	0x3b,0xb1,0xe7,0x8e,0xaa,0x81,0xa0,0x02,
+	0x43,0xfa,0xad,0xd2,0xbf,0x18,0xe6,0x3d,
+	0x38,0x9a,0xe4,0x43,0x77,0xda,0x18,0xc5,
+	0x76,0xb5,0x0f,0x00,0x96,0xcf,0x34,0x19,
+	0x54,0x83,0xb0,0x05,0x48,0xc0,0x98,0x62,
+	0x36,0xe3,0xbc,0x7c,0xb8,0xd6,0x80,0x1c,
+	0x04,0x94,0xcc,0xd1,0x99,0xe5,0xc5,0xbd,
+	0x0d,0x0e,0xdc,0x9e,0xb8,0xa0,0x00,0x1e,
+	0x15,0x27,0x67,0x54,0xfc,0xc6,0x85,0x66,
+	0x05,0x41,0x48,0xe6,0xe7,0x64,0xbe,0xe7,
+	0xc7,0x64,0xda,0xad,0x3f,0xc4,0x52,0x35,
+	0xa6,0xda,0xd4,0x28,0xfa,0x20,0xc1,0x70,
+	0xe3,0x45,0x00,0x3f,0x2f,0x06,0xec,0x81,
+	0x05,0xfe,0xb2,0x5b,0x22,0x81,0xb6,0x3d,
+	0x27,0x33,0xbe,0x96,0x1c,0x29,0x95,0x1d,
+	0x11,0xdd,0x22,0x21,0x65,0x7a,0x9f,0x53,
+	0x1d,0xda,0x2a,0x19,0x4d,0xbb,0x12,0x64,
+	0x48,0xbd,0xee,0xb2,0x58,0xe0,0x7e,0xa6,
+	0x59,0xc7,0x46,0x19,0xa6,0x38,0x0e,0x1d,
+	0x66,0xd6,0x83,0x2b,0xfe,0x67,0xf6,0x38,
+	0xcd,0x8f,0xae,0x1f,0x27,0x23,0x02,0x0f,
+	0x9c,0x40,0xa3,0xfd,0xa6,0x7e,0xda,0x3b,
+	0xd2,0x92,0x38,0xfb,0xd4,0xd4,0xb4,0x88,
+	0x5c,0x2a,0x99,0x17,0x6d,0xb1,0xa0,0x6c,
+	0x50,0x07,0x78,0x49,0x1a,0x82,0x88,0xf1,
+	0x85,0x5f,0x60,0xff,0xfc,0xf1,0xd1,0x37,
+	0x3f,0xd9,0x4f,0xc6,0x0c,0x18,0x11,0xe1,
+	0xac,0x3f,0x1c,0x6d,0x00,0x3b,0xec,0xda,
+	0x3b,0x1f,0x27,0x25,0xca,0x59,0x5d,0xe0,
+	0xca,0x63,0x32,0x8f,0x3b,0xe5,0x7c,0xc9,
+	0x77,0x55,0x60,0x11,0x95,0x14,0x0d,0xfb,
+	0x59,0xd3,0x9c,0xe0,0x91,0x30,0x8b,0x41,
+	0x05,0x74,0x6d,0xac,0x23,0xd3,0x3e,0x5f,
+	0x7c,0xe4,0x84,0x8d,0xa3,0x16,0xa9,0xc6,
+	0x6b,0x95,0x81,0xba,0x35,0x73,0xbf,0xaf,
+	0x31,0x14,0x96,0x18,0x8a,0xb1,0x54,0x23,
+	0x28,0x2e,0xe4,0x16,0xdc,0x2a,0x19,0xc5,
+	0x72,0x4f,0xa9,0x1a,0xe4,0xad,0xc8,0x8b,
+	0xc6,0x67,0x96,0xea,0xe5,0x67,0x7a,0x01,
+	0xf6,0x4e,0x8c,0x08,0x63,0x13,0x95,0x82,
+	0x2d,0x9d,0xb8,0xfc,0xee,0x35,0xc0,0x6b,
+	0x1f,0xee,0xa5,0x47,0x4d,0x6d,0x8f,0x34,
+	0xb1,0x53,0x4a,0x93,0x6a,0x18,0xb0,0xe0,
+	0xd2,0x0e,0xab,0x86,0xbc,0x9c,0x6d,0x6a,
+	0x52,0x07,0x19,0x4e,0x68,0x72,0x07,0x32,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+/*
+ * ffdhe8192 generator (g), modulus (p) and group size (q)
+ */
+
+const u8 ffdhe8192_g[] = { 0x02 };
+
+const u8 ffdhe8192_p[] = {
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
+	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
+	0xd8,0xb9,0xc5,0x83,0xce,0x2d,0x36,0x95,
+	0xa9,0xe1,0x36,0x41,0x14,0x64,0x33,0xfb,
+	0xcc,0x93,0x9d,0xce,0x24,0x9b,0x3e,0xf9,
+	0x7d,0x2f,0xe3,0x63,0x63,0x0c,0x75,0xd8,
+	0xf6,0x81,0xb2,0x02,0xae,0xc4,0x61,0x7a,
+	0xd3,0xdf,0x1e,0xd5,0xd5,0xfd,0x65,0x61,
+	0x24,0x33,0xf5,0x1f,0x5f,0x06,0x6e,0xd0,
+	0x85,0x63,0x65,0x55,0x3d,0xed,0x1a,0xf3,
+	0xb5,0x57,0x13,0x5e,0x7f,0x57,0xc9,0x35,
+	0x98,0x4f,0x0c,0x70,0xe0,0xe6,0x8b,0x77,
+	0xe2,0xa6,0x89,0xda,0xf3,0xef,0xe8,0x72,
+	0x1d,0xf1,0x58,0xa1,0x36,0xad,0xe7,0x35,
+	0x30,0xac,0xca,0x4f,0x48,0x3a,0x79,0x7a,
+	0xbc,0x0a,0xb1,0x82,0xb3,0x24,0xfb,0x61,
+	0xd1,0x08,0xa9,0x4b,0xb2,0xc8,0xe3,0xfb,
+	0xb9,0x6a,0xda,0xb7,0x60,0xd7,0xf4,0x68,
+	0x1d,0x4f,0x42,0xa3,0xde,0x39,0x4d,0xf4,
+	0xae,0x56,0xed,0xe7,0x63,0x72,0xbb,0x19,
+	0x0b,0x07,0xa7,0xc8,0xee,0x0a,0x6d,0x70,
+	0x9e,0x02,0xfc,0xe1,0xcd,0xf7,0xe2,0xec,
+	0xc0,0x34,0x04,0xcd,0x28,0x34,0x2f,0x61,
+	0x91,0x72,0xfe,0x9c,0xe9,0x85,0x83,0xff,
+	0x8e,0x4f,0x12,0x32,0xee,0xf2,0x81,0x83,
+	0xc3,0xfe,0x3b,0x1b,0x4c,0x6f,0xad,0x73,
+	0x3b,0xb5,0xfc,0xbc,0x2e,0xc2,0x20,0x05,
+	0xc5,0x8e,0xf1,0x83,0x7d,0x16,0x83,0xb2,
+	0xc6,0xf3,0x4a,0x26,0xc1,0xb2,0xef,0xfa,
+	0x88,0x6b,0x42,0x38,0x61,0x1f,0xcf,0xdc,
+	0xde,0x35,0x5b,0x3b,0x65,0x19,0x03,0x5b,
+	0xbc,0x34,0xf4,0xde,0xf9,0x9c,0x02,0x38,
+	0x61,0xb4,0x6f,0xc9,0xd6,0xe6,0xc9,0x07,
+	0x7a,0xd9,0x1d,0x26,0x91,0xf7,0xf7,0xee,
+	0x59,0x8c,0xb0,0xfa,0xc1,0x86,0xd9,0x1c,
+	0xae,0xfe,0x13,0x09,0x85,0x13,0x92,0x70,
+	0xb4,0x13,0x0c,0x93,0xbc,0x43,0x79,0x44,
+	0xf4,0xfd,0x44,0x52,0xe2,0xd7,0x4d,0xd3,
+	0x64,0xf2,0xe2,0x1e,0x71,0xf5,0x4b,0xff,
+	0x5c,0xae,0x82,0xab,0x9c,0x9d,0xf6,0x9e,
+	0xe8,0x6d,0x2b,0xc5,0x22,0x36,0x3a,0x0d,
+	0xab,0xc5,0x21,0x97,0x9b,0x0d,0xea,0xda,
+	0x1d,0xbf,0x9a,0x42,0xd5,0xc4,0x48,0x4e,
+	0x0a,0xbc,0xd0,0x6b,0xfa,0x53,0xdd,0xef,
+	0x3c,0x1b,0x20,0xee,0x3f,0xd5,0x9d,0x7c,
+	0x25,0xe4,0x1d,0x2b,0x66,0x9e,0x1e,0xf1,
+	0x6e,0x6f,0x52,0xc3,0x16,0x4d,0xf4,0xfb,
+	0x79,0x30,0xe9,0xe4,0xe5,0x88,0x57,0xb6,
+	0xac,0x7d,0x5f,0x42,0xd6,0x9f,0x6d,0x18,
+	0x77,0x63,0xcf,0x1d,0x55,0x03,0x40,0x04,
+	0x87,0xf5,0x5b,0xa5,0x7e,0x31,0xcc,0x7a,
+	0x71,0x35,0xc8,0x86,0xef,0xb4,0x31,0x8a,
+	0xed,0x6a,0x1e,0x01,0x2d,0x9e,0x68,0x32,
+	0xa9,0x07,0x60,0x0a,0x91,0x81,0x30,0xc4,
+	0x6d,0xc7,0x78,0xf9,0x71,0xad,0x00,0x38,
+	0x09,0x29,0x99,0xa3,0x33,0xcb,0x8b,0x7a,
+	0x1a,0x1d,0xb9,0x3d,0x71,0x40,0x00,0x3c,
+	0x2a,0x4e,0xce,0xa9,0xf9,0x8d,0x0a,0xcc,
+	0x0a,0x82,0x91,0xcd,0xce,0xc9,0x7d,0xcf,
+	0x8e,0xc9,0xb5,0x5a,0x7f,0x88,0xa4,0x6b,
+	0x4d,0xb5,0xa8,0x51,0xf4,0x41,0x82,0xe1,
+	0xc6,0x8a,0x00,0x7e,0x5e,0x0d,0xd9,0x02,
+	0x0b,0xfd,0x64,0xb6,0x45,0x03,0x6c,0x7a,
+	0x4e,0x67,0x7d,0x2c,0x38,0x53,0x2a,0x3a,
+	0x23,0xba,0x44,0x42,0xca,0xf5,0x3e,0xa6,
+	0x3b,0xb4,0x54,0x32,0x9b,0x76,0x24,0xc8,
+	0x91,0x7b,0xdd,0x64,0xb1,0xc0,0xfd,0x4c,
+	0xb3,0x8e,0x8c,0x33,0x4c,0x70,0x1c,0x3a,
+	0xcd,0xad,0x06,0x57,0xfc,0xcf,0xec,0x71,
+	0x9b,0x1f,0x5c,0x3e,0x4e,0x46,0x04,0x1f,
+	0x38,0x81,0x47,0xfb,0x4c,0xfd,0xb4,0x77,
+	0xa5,0x24,0x71,0xf7,0xa9,0xa9,0x69,0x10,
+	0xb8,0x55,0x32,0x2e,0xdb,0x63,0x40,0xd8,
+	0xa0,0x0e,0xf0,0x92,0x35,0x05,0x11,0xe3,
+	0x0a,0xbe,0xc1,0xff,0xf9,0xe3,0xa2,0x6e,
+	0x7f,0xb2,0x9f,0x8c,0x18,0x30,0x23,0xc3,
+	0x58,0x7e,0x38,0xda,0x00,0x77,0xd9,0xb4,
+	0x76,0x3e,0x4e,0x4b,0x94,0xb2,0xbb,0xc1,
+	0x94,0xc6,0x65,0x1e,0x77,0xca,0xf9,0x92,
+	0xee,0xaa,0xc0,0x23,0x2a,0x28,0x1b,0xf6,
+	0xb3,0xa7,0x39,0xc1,0x22,0x61,0x16,0x82,
+	0x0a,0xe8,0xdb,0x58,0x47,0xa6,0x7c,0xbe,
+	0xf9,0xc9,0x09,0x1b,0x46,0x2d,0x53,0x8c,
+	0xd7,0x2b,0x03,0x74,0x6a,0xe7,0x7f,0x5e,
+	0x62,0x29,0x2c,0x31,0x15,0x62,0xa8,0x46,
+	0x50,0x5d,0xc8,0x2d,0xb8,0x54,0x33,0x8a,
+	0xe4,0x9f,0x52,0x35,0xc9,0x5b,0x91,0x17,
+	0x8c,0xcf,0x2d,0xd5,0xca,0xce,0xf4,0x03,
+	0xec,0x9d,0x18,0x10,0xc6,0x27,0x2b,0x04,
+	0x5b,0x3b,0x71,0xf9,0xdc,0x6b,0x80,0xd6,
+	0x3f,0xdd,0x4a,0x8e,0x9a,0xdb,0x1e,0x69,
+	0x62,0xa6,0x95,0x26,0xd4,0x31,0x61,0xc1,
+	0xa4,0x1d,0x57,0x0d,0x79,0x38,0xda,0xd4,
+	0xa4,0x0e,0x32,0x9c,0xcf,0xf4,0x6a,0xaa,
+	0x36,0xad,0x00,0x4c,0xf6,0x00,0xc8,0x38,
+	0x1e,0x42,0x5a,0x31,0xd9,0x51,0xae,0x64,
+	0xfd,0xb2,0x3f,0xce,0xc9,0x50,0x9d,0x43,
+	0x68,0x7f,0xeb,0x69,0xed,0xd1,0xcc,0x5e,
+	0x0b,0x8c,0xc3,0xbd,0xf6,0x4b,0x10,0xef,
+	0x86,0xb6,0x31,0x42,0xa3,0xab,0x88,0x29,
+	0x55,0x5b,0x2f,0x74,0x7c,0x93,0x26,0x65,
+	0xcb,0x2c,0x0f,0x1c,0xc0,0x1b,0xd7,0x02,
+	0x29,0x38,0x88,0x39,0xd2,0xaf,0x05,0xe4,
+	0x54,0x50,0x4a,0xc7,0x8b,0x75,0x82,0x82,
+	0x28,0x46,0xc0,0xba,0x35,0xc3,0x5f,0x5c,
+	0x59,0x16,0x0c,0xc0,0x46,0xfd,0x82,0x51,
+	0x54,0x1f,0xc6,0x8c,0x9c,0x86,0xb0,0x22,
+	0xbb,0x70,0x99,0x87,0x6a,0x46,0x0e,0x74,
+	0x51,0xa8,0xa9,0x31,0x09,0x70,0x3f,0xee,
+	0x1c,0x21,0x7e,0x6c,0x38,0x26,0xe5,0x2c,
+	0x51,0xaa,0x69,0x1e,0x0e,0x42,0x3c,0xfc,
+	0x99,0xe9,0xe3,0x16,0x50,0xc1,0x21,0x7b,
+	0x62,0x48,0x16,0xcd,0xad,0x9a,0x95,0xf9,
+	0xd5,0xb8,0x01,0x94,0x88,0xd9,0xc0,0xa0,
+	0xa1,0xfe,0x30,0x75,0xa5,0x77,0xe2,0x31,
+	0x83,0xf8,0x1d,0x4a,0x3f,0x2f,0xa4,0x57,
+	0x1e,0xfc,0x8c,0xe0,0xba,0x8a,0x4f,0xe8,
+	0xb6,0x85,0x5d,0xfe,0x72,0xb0,0xa6,0x6e,
+	0xde,0xd2,0xfb,0xab,0xfb,0xe5,0x8a,0x30,
+	0xfa,0xfa,0xbe,0x1c,0x5d,0x71,0xa8,0x7e,
+	0x2f,0x74,0x1e,0xf8,0xc1,0xfe,0x86,0xfe,
+	0xa6,0xbb,0xfd,0xe5,0x30,0x67,0x7f,0x0d,
+	0x97,0xd1,0x1d,0x49,0xf7,0xa8,0x44,0x3d,
+	0x08,0x22,0xe5,0x06,0xa9,0xf4,0x61,0x4e,
+	0x01,0x1e,0x2a,0x94,0x83,0x8f,0xf8,0x8c,
+	0xd6,0x8c,0x8b,0xb7,0xc5,0xc6,0x42,0x4c,
+	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+const u8 ffdhe8192_q[] = {
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
+	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
+	0xec,0x5c,0xe2,0xc1,0xe7,0x16,0x9b,0x4a,
+	0xd4,0xf0,0x9b,0x20,0x8a,0x32,0x19,0xfd,
+	0xe6,0x49,0xce,0xe7,0x12,0x4d,0x9f,0x7c,
+	0xbe,0x97,0xf1,0xb1,0xb1,0x86,0x3a,0xec,
+	0x7b,0x40,0xd9,0x01,0x57,0x62,0x30,0xbd,
+	0x69,0xef,0x8f,0x6a,0xea,0xfe,0xb2,0xb0,
+	0x92,0x19,0xfa,0x8f,0xaf,0x83,0x37,0x68,
+	0x42,0xb1,0xb2,0xaa,0x9e,0xf6,0x8d,0x79,
+	0xda,0xab,0x89,0xaf,0x3f,0xab,0xe4,0x9a,
+	0xcc,0x27,0x86,0x38,0x70,0x73,0x45,0xbb,
+	0xf1,0x53,0x44,0xed,0x79,0xf7,0xf4,0x39,
+	0x0e,0xf8,0xac,0x50,0x9b,0x56,0xf3,0x9a,
+	0x98,0x56,0x65,0x27,0xa4,0x1d,0x3c,0xbd,
+	0x5e,0x05,0x58,0xc1,0x59,0x92,0x7d,0xb0,
+	0xe8,0x84,0x54,0xa5,0xd9,0x64,0x71,0xfd,
+	0xdc,0xb5,0x6d,0x5b,0xb0,0x6b,0xfa,0x34,
+	0x0e,0xa7,0xa1,0x51,0xef,0x1c,0xa6,0xfa,
+	0x57,0x2b,0x76,0xf3,0xb1,0xb9,0x5d,0x8c,
+	0x85,0x83,0xd3,0xe4,0x77,0x05,0x36,0xb8,
+	0x4f,0x01,0x7e,0x70,0xe6,0xfb,0xf1,0x76,
+	0x60,0x1a,0x02,0x66,0x94,0x1a,0x17,0xb0,
+	0xc8,0xb9,0x7f,0x4e,0x74,0xc2,0xc1,0xff,
+	0xc7,0x27,0x89,0x19,0x77,0x79,0x40,0xc1,
+	0xe1,0xff,0x1d,0x8d,0xa6,0x37,0xd6,0xb9,
+	0x9d,0xda,0xfe,0x5e,0x17,0x61,0x10,0x02,
+	0xe2,0xc7,0x78,0xc1,0xbe,0x8b,0x41,0xd9,
+	0x63,0x79,0xa5,0x13,0x60,0xd9,0x77,0xfd,
+	0x44,0x35,0xa1,0x1c,0x30,0x8f,0xe7,0xee,
+	0x6f,0x1a,0xad,0x9d,0xb2,0x8c,0x81,0xad,
+	0xde,0x1a,0x7a,0x6f,0x7c,0xce,0x01,0x1c,
+	0x30,0xda,0x37,0xe4,0xeb,0x73,0x64,0x83,
+	0xbd,0x6c,0x8e,0x93,0x48,0xfb,0xfb,0xf7,
+	0x2c,0xc6,0x58,0x7d,0x60,0xc3,0x6c,0x8e,
+	0x57,0x7f,0x09,0x84,0xc2,0x89,0xc9,0x38,
+	0x5a,0x09,0x86,0x49,0xde,0x21,0xbc,0xa2,
+	0x7a,0x7e,0xa2,0x29,0x71,0x6b,0xa6,0xe9,
+	0xb2,0x79,0x71,0x0f,0x38,0xfa,0xa5,0xff,
+	0xae,0x57,0x41,0x55,0xce,0x4e,0xfb,0x4f,
+	0x74,0x36,0x95,0xe2,0x91,0x1b,0x1d,0x06,
+	0xd5,0xe2,0x90,0xcb,0xcd,0x86,0xf5,0x6d,
+	0x0e,0xdf,0xcd,0x21,0x6a,0xe2,0x24,0x27,
+	0x05,0x5e,0x68,0x35,0xfd,0x29,0xee,0xf7,
+	0x9e,0x0d,0x90,0x77,0x1f,0xea,0xce,0xbe,
+	0x12,0xf2,0x0e,0x95,0xb3,0x4f,0x0f,0x78,
+	0xb7,0x37,0xa9,0x61,0x8b,0x26,0xfa,0x7d,
+	0xbc,0x98,0x74,0xf2,0x72,0xc4,0x2b,0xdb,
+	0x56,0x3e,0xaf,0xa1,0x6b,0x4f,0xb6,0x8c,
+	0x3b,0xb1,0xe7,0x8e,0xaa,0x81,0xa0,0x02,
+	0x43,0xfa,0xad,0xd2,0xbf,0x18,0xe6,0x3d,
+	0x38,0x9a,0xe4,0x43,0x77,0xda,0x18,0xc5,
+	0x76,0xb5,0x0f,0x00,0x96,0xcf,0x34,0x19,
+	0x54,0x83,0xb0,0x05,0x48,0xc0,0x98,0x62,
+	0x36,0xe3,0xbc,0x7c,0xb8,0xd6,0x80,0x1c,
+	0x04,0x94,0xcc,0xd1,0x99,0xe5,0xc5,0xbd,
+	0x0d,0x0e,0xdc,0x9e,0xb8,0xa0,0x00,0x1e,
+	0x15,0x27,0x67,0x54,0xfc,0xc6,0x85,0x66,
+	0x05,0x41,0x48,0xe6,0xe7,0x64,0xbe,0xe7,
+	0xc7,0x64,0xda,0xad,0x3f,0xc4,0x52,0x35,
+	0xa6,0xda,0xd4,0x28,0xfa,0x20,0xc1,0x70,
+	0xe3,0x45,0x00,0x3f,0x2f,0x06,0xec,0x81,
+	0x05,0xfe,0xb2,0x5b,0x22,0x81,0xb6,0x3d,
+	0x27,0x33,0xbe,0x96,0x1c,0x29,0x95,0x1d,
+	0x11,0xdd,0x22,0x21,0x65,0x7a,0x9f,0x53,
+	0x1d,0xda,0x2a,0x19,0x4d,0xbb,0x12,0x64,
+	0x48,0xbd,0xee,0xb2,0x58,0xe0,0x7e,0xa6,
+	0x59,0xc7,0x46,0x19,0xa6,0x38,0x0e,0x1d,
+	0x66,0xd6,0x83,0x2b,0xfe,0x67,0xf6,0x38,
+	0xcd,0x8f,0xae,0x1f,0x27,0x23,0x02,0x0f,
+	0x9c,0x40,0xa3,0xfd,0xa6,0x7e,0xda,0x3b,
+	0xd2,0x92,0x38,0xfb,0xd4,0xd4,0xb4,0x88,
+	0x5c,0x2a,0x99,0x17,0x6d,0xb1,0xa0,0x6c,
+	0x50,0x07,0x78,0x49,0x1a,0x82,0x88,0xf1,
+	0x85,0x5f,0x60,0xff,0xfc,0xf1,0xd1,0x37,
+	0x3f,0xd9,0x4f,0xc6,0x0c,0x18,0x11,0xe1,
+	0xac,0x3f,0x1c,0x6d,0x00,0x3b,0xec,0xda,
+	0x3b,0x1f,0x27,0x25,0xca,0x59,0x5d,0xe0,
+	0xca,0x63,0x32,0x8f,0x3b,0xe5,0x7c,0xc9,
+	0x77,0x55,0x60,0x11,0x95,0x14,0x0d,0xfb,
+	0x59,0xd3,0x9c,0xe0,0x91,0x30,0x8b,0x41,
+	0x05,0x74,0x6d,0xac,0x23,0xd3,0x3e,0x5f,
+	0x7c,0xe4,0x84,0x8d,0xa3,0x16,0xa9,0xc6,
+	0x6b,0x95,0x81,0xba,0x35,0x73,0xbf,0xaf,
+	0x31,0x14,0x96,0x18,0x8a,0xb1,0x54,0x23,
+	0x28,0x2e,0xe4,0x16,0xdc,0x2a,0x19,0xc5,
+	0x72,0x4f,0xa9,0x1a,0xe4,0xad,0xc8,0x8b,
+	0xc6,0x67,0x96,0xea,0xe5,0x67,0x7a,0x01,
+	0xf6,0x4e,0x8c,0x08,0x63,0x13,0x95,0x82,
+	0x2d,0x9d,0xb8,0xfc,0xee,0x35,0xc0,0x6b,
+	0x1f,0xee,0xa5,0x47,0x4d,0x6d,0x8f,0x34,
+	0xb1,0x53,0x4a,0x93,0x6a,0x18,0xb0,0xe0,
+	0xd2,0x0e,0xab,0x86,0xbc,0x9c,0x6d,0x6a,
+	0x52,0x07,0x19,0x4e,0x67,0xfa,0x35,0x55,
+	0x1b,0x56,0x80,0x26,0x7b,0x00,0x64,0x1c,
+	0x0f,0x21,0x2d,0x18,0xec,0xa8,0xd7,0x32,
+	0x7e,0xd9,0x1f,0xe7,0x64,0xa8,0x4e,0xa1,
+	0xb4,0x3f,0xf5,0xb4,0xf6,0xe8,0xe6,0x2f,
+	0x05,0xc6,0x61,0xde,0xfb,0x25,0x88,0x77,
+	0xc3,0x5b,0x18,0xa1,0x51,0xd5,0xc4,0x14,
+	0xaa,0xad,0x97,0xba,0x3e,0x49,0x93,0x32,
+	0xe5,0x96,0x07,0x8e,0x60,0x0d,0xeb,0x81,
+	0x14,0x9c,0x44,0x1c,0xe9,0x57,0x82,0xf2,
+	0x2a,0x28,0x25,0x63,0xc5,0xba,0xc1,0x41,
+	0x14,0x23,0x60,0x5d,0x1a,0xe1,0xaf,0xae,
+	0x2c,0x8b,0x06,0x60,0x23,0x7e,0xc1,0x28,
+	0xaa,0x0f,0xe3,0x46,0x4e,0x43,0x58,0x11,
+	0x5d,0xb8,0x4c,0xc3,0xb5,0x23,0x07,0x3a,
+	0x28,0xd4,0x54,0x98,0x84,0xb8,0x1f,0xf7,
+	0x0e,0x10,0xbf,0x36,0x1c,0x13,0x72,0x96,
+	0x28,0xd5,0x34,0x8f,0x07,0x21,0x1e,0x7e,
+	0x4c,0xf4,0xf1,0x8b,0x28,0x60,0x90,0xbd,
+	0xb1,0x24,0x0b,0x66,0xd6,0xcd,0x4a,0xfc,
+	0xea,0xdc,0x00,0xca,0x44,0x6c,0xe0,0x50,
+	0x50,0xff,0x18,0x3a,0xd2,0xbb,0xf1,0x18,
+	0xc1,0xfc,0x0e,0xa5,0x1f,0x97,0xd2,0x2b,
+	0x8f,0x7e,0x46,0x70,0x5d,0x45,0x27,0xf4,
+	0x5b,0x42,0xae,0xff,0x39,0x58,0x53,0x37,
+	0x6f,0x69,0x7d,0xd5,0xfd,0xf2,0xc5,0x18,
+	0x7d,0x7d,0x5f,0x0e,0x2e,0xb8,0xd4,0x3f,
+	0x17,0xba,0x0f,0x7c,0x60,0xff,0x43,0x7f,
+	0x53,0x5d,0xfe,0xf2,0x98,0x33,0xbf,0x86,
+	0xcb,0xe8,0x8e,0xa4,0xfb,0xd4,0x22,0x1e,
+	0x84,0x11,0x72,0x83,0x54,0xfa,0x30,0xa7,
+	0x00,0x8f,0x15,0x4a,0x41,0xc7,0xfc,0x46,
+	0x6b,0x46,0x45,0xdb,0xe2,0xe3,0x21,0x26,
+	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+};
+
+struct ffdhe_group {
+	int bits;
+	int minsize;
+	const u8 *p;
+	const u8 *q;
+	const u8 *g;
+} ffdhe_group_map[] = {
+	{
+		.bits = 2048,
+		.minsize = 225,
+		.p = ffdhe2048_p,
+		.q = ffdhe2048_q,
+		.g = ffdhe2048_g,
+	},
+	{
+		.bits = 3072,
+		.minsize = 275,
+		.p = ffdhe3072_p,
+		.q = ffdhe3072_q,
+		.g = ffdhe3072_g,
+	},
+	{
+		.bits = 4096,
+		.minsize = 325,
+		.p = ffdhe4096_p,
+		.q = ffdhe4096_q,
+		.g = ffdhe4096_g,
+	},
+	{
+		.bits = 6144,
+		.minsize = 375,
+		.p = ffdhe6144_p,
+		.q = ffdhe6144_q,
+		.g = ffdhe6144_g,
+	},
+	{
+		.bits = 8192,
+		.minsize = 400,
+		.p = ffdhe8192_p,
+		.q = ffdhe8192_q,
+		.g = ffdhe8192_g,
+	},
+};
+
+int crypto_ffdhe_params(struct dh *p, int bits)
+{
+	struct ffdhe_group *grp = NULL;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ffdhe_group_map); i++) {
+		if (ffdhe_group_map[i].bits == bits) {
+			grp = &ffdhe_group_map[i];
+			break;
+		}
+	}
+	if (!grp || !p)
+		return -EINVAL;
+
+	p->p_size = grp->bits / 8;
+	p->p = (u8 *)grp->p;
+	p->g_size = 1;
+	p->g = (u8 *)grp->g;
+	p->q_size = grp->bits / 8;
+	p->q = (u8 *)grp->q;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(crypto_ffdhe_params);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FFDHE ephemeral parameters");
include/crypto/ffdhe.h new file +14 -0
new file mode 100644
index 000000000000..6cb9253ddb34
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Finite-Field Diffie-Hellman definition according to RFC 7919
+ *
+ * Copyright (c) 2021, SUSE Software Products
+ * Authors: Hannes Reinecke <[email protected]>
+ */
+#ifndef _CRYPTO_FFDHE_
+#define _CRYPTO_FFDHE_
+
+/**
+ * crypto_ffdhe_params() - Generate FFDHE params
+ * @params: DH params
+ * @bits: Bitsize of the FFDHE parameters

include/crypto/ffdhe.h line 24

Quoted 10 lines
include/crypto/ffdhe.h new file +10 -0
+ *
+ * This functions sets the FFDHE parameter for @bits in @params.
+ * Valid bit sizes are 2048, 3072, 4096, 6144, or 8194.
+ *
+ * Returns: 0 on success, errno on failure.
+ */
+
+int crypto_ffdhe_params(struct dh *p, int bits);
+
+#endif /* _CRYPTO_FFDHE_H */
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
#8 lore raw

Re: [PATCH 03/12] crypto/ffdhe: Finite Field DH Ephemeral Parameters

In reply to Hannes Reinecke
I love your patch! Perhaps something to improve:

Hi Hannes,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.16-rc1 next-20211117]
[cannot apply to herbert-cryptodev-2.6/master herbert-crypto-2.6/master linux-nvme/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Hannes-Reinecke/nvme-In-band-authentication-support/20211112-210112
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5833291ab6de9c3e2374336b51c814e515e8f3a5
config: x86_64-randconfig-s031-20211115 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.4-dirty
        # https://github.com/0day-ci/linux/commit/1eadaf1bdef889b9d1c0b9bb2609cd11599c76bc
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Hannes-Reinecke/nvme-In-band-authentication-support/20211112-210112
        git checkout 1eadaf1bdef889b9d1c0b9bb2609cd11599c76bc
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=x86_64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate

sparse warnings: (new ones prefixed by >>)

>> crypto/ffdhe_helper.c:18:10: sparse: sparse: symbol 'ffdhe2048_g' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:20:10: sparse: sparse: symbol 'ffdhe2048_p' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:55:10: sparse: sparse: symbol 'ffdhe2048_q' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:94:10: sparse: sparse: symbol 'ffdhe3072_g' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:96:10: sparse: sparse: symbol 'ffdhe3072_p' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:147:10: sparse: sparse: symbol 'ffdhe3072_q' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:202:10: sparse: sparse: symbol 'ffdhe4096_g' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:204:10: sparse: sparse: symbol 'ffdhe4096_p' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:271:10: sparse: sparse: symbol 'ffdhe4096_q' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:342:10: sparse: sparse: symbol 'ffdhe6144_g' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:344:10: sparse: sparse: symbol 'ffdhe6144_p' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:443:10: sparse: sparse: symbol 'ffdhe6144_q' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:546:10: sparse: sparse: symbol 'ffdhe8192_g' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:548:10: sparse: sparse: symbol 'ffdhe8192_p' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:679:10: sparse: sparse: symbol 'ffdhe8192_q' was not declared. Should it be static?
>> crypto/ffdhe_helper.c:816:3: sparse: sparse: symbol 'ffdhe_group_map' was not declared. Should it be static?

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

#9 lore raw

[RFC PATCH] crypto/ffdhe: ffdhe2048_g[] can be static

In reply to Hannes Reinecke
crypto/ffdhe_helper.c:18:10: warning: symbol 'ffdhe2048_g' was not declared. Should it be static? crypto/ffdhe_helper.c:20:10: warning: symbol 'ffdhe2048_p' was not declared. Should it be static?…

crypto/ffdhe_helper.c:18:10: warning: symbol 'ffdhe2048_g' was not declared. Should it be static? crypto/ffdhe_helper.c:20:10: warning: symbol 'ffdhe2048_p' was not declared. Should it be static? crypto/ffdhe_helper.c:55:10: warning: symbol 'ffdhe2048_q' was not declared. Should it be static? crypto/ffdhe_helper.c:94:10: warning: symbol 'ffdhe3072_g' was not declared. Should it be static? crypto/ffdhe_helper.c:96:10: warning: symbol 'ffdhe3072_p' was not declared. Should it be static? crypto/ffdhe_helper.c:147:10: warning: symbol 'ffdhe3072_q' was not declared. Should it be static? crypto/ffdhe_helper.c:202:10: warning: symbol 'ffdhe4096_g' was not declared. Should it be static? crypto/ffdhe_helper.c:204:10: warning: symbol 'ffdhe4096_p' was not declared. Should it be static? crypto/ffdhe_helper.c:271:10: warning: symbol 'ffdhe4096_q' was not declared. Should it be static? crypto/ffdhe_helper.c:342:10: warning: symbol 'ffdhe6144_g' was not declared. Should it be static? crypto/ffdhe_helper.c:344:10: warning: symbol 'ffdhe6144_p' was not declared. Should it be static? crypto/ffdhe_helper.c:443:10: warning: symbol 'ffdhe6144_q' was not declared. Should it be static? crypto/ffdhe_helper.c:546:10: warning: symbol 'ffdhe8192_g' was not declared. Should it be static? crypto/ffdhe_helper.c:548:10: warning: symbol 'ffdhe8192_p' was not declared. Should it be static? crypto/ffdhe_helper.c:679:10: warning: symbol 'ffdhe8192_q' was not declared. Should it be static?

---
 ffdhe_helper.c |   30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)
crypto/ffdhe_helper.c +15 -15
index d7018bc3a8ec5..5d8da12912523 100644
@@ -15,9 +15,9 @@
 /*
  * ffdhe2048 generator (g), modulus (p) and group size (q)
  */
-const u8 ffdhe2048_g[] = { 0x02 };
+static const u8 ffdhe2048_g[] = { 0x02 };
 
-const u8 ffdhe2048_p[] = {
+static const u8 ffdhe2048_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
 	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
@@ -52,7 +52,7 @@ const u8 ffdhe2048_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 };
 
-const u8 ffdhe2048_q[] = {
+static const u8 ffdhe2048_q[] = {
 	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
 	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
@@ -91,9 +91,9 @@ const u8 ffdhe2048_q[] = {
  * ffdhe3072 generator (g), modulus (p) and group size (q)
  */
 
-const u8 ffdhe3072_g[] = { 0x02 };
+static const u8 ffdhe3072_g[] = { 0x02 };
 
-const u8 ffdhe3072_p[] = {
+static const u8 ffdhe3072_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
 	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
@@ -144,7 +144,7 @@ const u8 ffdhe3072_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 };
 
-const u8 ffdhe3072_q[] = {
+static const u8 ffdhe3072_q[] = {
 	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
 	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
@@ -199,9 +199,9 @@ const u8 ffdhe3072_q[] = {
  * ffdhe4096 generator (g), modulus (p) and group size (q)
  */
 
-const u8 ffdhe4096_g[] = { 0x02 };
+static const u8 ffdhe4096_g[] = { 0x02 };
 
-const u8 ffdhe4096_p[] = {
+static const u8 ffdhe4096_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
 	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
@@ -268,7 +268,7 @@ const u8 ffdhe4096_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 };
 
-const u8 ffdhe4096_q[] = {
+static const u8 ffdhe4096_q[] = {
 	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
 	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
@@ -339,9 +339,9 @@ const u8 ffdhe4096_q[] = {
  * ffdhe6144 generator (g), modulus (p) and group size (q)
  */
 
-const u8 ffdhe6144_g[] = { 0x02 };
+static const u8 ffdhe6144_g[] = { 0x02 };
 
-const u8 ffdhe6144_p[] = {
+static const u8 ffdhe6144_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
 	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
@@ -440,7 +440,7 @@ const u8 ffdhe6144_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 };
 
-const u8 ffdhe6144_q[] = {
+static const u8 ffdhe6144_q[] = {
 	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
 	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
@@ -543,9 +543,9 @@ const u8 ffdhe6144_q[] = {
  * ffdhe8192 generator (g), modulus (p) and group size (q)
  */
 
-const u8 ffdhe8192_g[] = { 0x02 };
+static const u8 ffdhe8192_g[] = { 0x02 };
 
-const u8 ffdhe8192_p[] = {
+static const u8 ffdhe8192_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xad,0xf8,0x54,0x58,0xa2,0xbb,0x4a,0x9a,
 	0xaf,0xdc,0x56,0x20,0x27,0x3d,0x3c,0xf1,
@@ -676,7 +676,7 @@ const u8 ffdhe8192_p[] = {
 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 };
 
-const u8 ffdhe8192_q[] = {
+static const u8 ffdhe8192_q[] = {
 	0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 	0xd6,0xfc,0x2a,0x2c,0x51,0x5d,0xa5,0x4d,
 	0x57,0xee,0x2b,0x10,0x13,0x9e,0x9e,0x78,
author maintainer
#10 lore raw

PATCH v5 4/12 lib/base64: RFC4648-compliant base64 encoding

In reply to Hannes Reinecke

Add RFC4648-compliant base64 encoding and decoding routines, based on the base64url encoding in fs/crypto/fname.c.

---
 include/linux/base64.h |  16 +++++++
 lib/Makefile           |   2 +-
 lib/base64.c           | 103 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 include/linux/base64.h
 create mode 100644 lib/base64.c
include/linux/base64.h new file +16 -0
new file mode 100644
index 000000000000..660d4cb1ef31
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * base64 encoding, lifted from fs/crypto/fname.c.
+ */
+
+#ifndef _LINUX_BASE64_H
+#define _LINUX_BASE64_H
+
+#include <linux/types.h>
+
+#define BASE64_CHARS(nbytes)   DIV_ROUND_UP((nbytes) * 4, 3)
+
+int base64_encode(const u8 *src, int len, char *dst);
+int base64_decode(const char *src, int len, u8 *dst);
+
+#endif /* _LINUX_BASE64_H */
lib/Makefile +1 -1
index 364c23f15578..ddc5cb4c6eb8 100644
@@ -46,7 +46,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
 	 bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
 	 list_sort.o uuid.o iov_iter.o clz_ctz.o \
 	 bsearch.o find_bit.o llist.o memweight.o kfifo.o \
-	 percpu-refcount.o rhashtable.o \
+	 percpu-refcount.o rhashtable.o base64.o \
 	 once.o refcount.o usercopy.o errseq.o bucket_locks.o \
 	 generic-radix-tree.o
 obj-$(CONFIG_STRING_SELFTEST) += test_string.o
lib/base64.c new file +103 -0

103 lines not on this page · raw message

Signature · 1 line
2.29.2
Reviewed-by on v5 4/12
#11 lore raw

Re: [PATCH 04/12] lib/base64: RFC4648-compliant base64 encoding

Quoted 147 lines · Hannes Reinecke

Add RFC4648-compliant base64 encoding and decoding routines, based on the base64url encoding in fs/crypto/fname.c.

---
  include/linux/base64.h |  16 +++++++
  lib/Makefile           |   2 +-
  lib/base64.c           | 103 +++++++++++++++++++++++++++++++++++++++++
  3 files changed, 120 insertions(+), 1 deletion(-)

create mode 100644 include/linux/base64.h
create mode 100644 lib/base64.c

include/linux/base64.h new file +16 -0
new file mode 100644
index 000000000000..660d4cb1ef31
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * base64 encoding, lifted from fs/crypto/fname.c.
+ */
+
+#ifndef _LINUX_BASE64_H
+#define _LINUX_BASE64_H
+
+#include <linux/types.h>
+
+#define BASE64_CHARS(nbytes)   DIV_ROUND_UP((nbytes) * 4, 3)
+
+int base64_encode(const u8 *src, int len, char *dst);
+int base64_decode(const char *src, int len, u8 *dst);
+
+#endif /* _LINUX_BASE64_H */
lib/Makefile +1 -1
index 364c23f15578..ddc5cb4c6eb8 100644
@@ -46,7 +46,7 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \
  	 bust_spinlocks.o kasprintf.o bitmap.o scatterlist.o \
  	 list_sort.o uuid.o iov_iter.o clz_ctz.o \
  	 bsearch.o find_bit.o llist.o memweight.o kfifo.o \
-	 percpu-refcount.o rhashtable.o \
+	 percpu-refcount.o rhashtable.o base64.o \
  	 once.o refcount.o usercopy.o errseq.o bucket_locks.o \
  	 generic-radix-tree.o
  obj-$(CONFIG_STRING_SELFTEST) += test_string.o
lib/base64.c new file +93 -0
new file mode 100644
index 000000000000..60d46157da85
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * base64.c - RFC4648-compliant base64 encoding
+ *
+ * Copyright (c) 2020 Hannes Reinecke, SUSE
+ *
+ * Based on the base64url routines from fs/crypto/fname.c
+ * (which are using the URL-safe base64 encoding),
+ * modified to use the standard coding table from RFC4648 section 4.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/export.h>
+#include <linux/string.h>
+#include <linux/base64.h>
+
+static const char base64_table[65] =
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/**
+ * base64_encode() - base64-encode some binary data
+ * @src: the binary data to encode
+ * @srclen: the length of @src in bytes
+ * @dst: (output) the base64-encoded string.  Not NUL-terminated.
+ *
+ * Encodes data using base64 encoding, i.e. the "Base 64 Encoding" specified
+ * by RFC 4648, including the  '='-padding.
+ *
+ * Return: the length of the resulting base64url-encoded string in bytes.
+ */
+int base64_encode(const u8 *src, int srclen, char *dst)
+{
+	u32 ac = 0;
+	int bits = 0;
+	int i;
+	char *cp = dst;
+
+	for (i = 0; i < srclen; i++) {
+		ac = (ac << 8) | src[i];
+		bits += 8;
+		do {
+			bits -= 6;
+			*cp++ = base64_table[(ac >> bits) & 0x3f];
+		} while (bits >= 6);
+	}
+	if (bits) {
+		*cp++ = base64_table[(ac << (6 - bits)) & 0x3f];
+		bits -= 6;
+	}
+	while (bits < 0) {
+		*cp++ = '=';
+		bits += 2;
+	}
+	return cp - dst;
+}
+EXPORT_SYMBOL_GPL(base64_encode);
+
+/**
+ * base64_decode() - base64-decode a string
+ * @src: the string to decode.  Doesn't need to be NUL-terminated.
+ * @srclen: the length of @src in bytes
+ * @dst: (output) the decoded binary data
+ *
+ * Decodes a string using base64url encoding, i.e. the "Base 64 Encoding"
+ * specified by RFC 4648, including the  '='-padding.
+ *
+ * This implementation hasn't been optimized for performance.
+ *
+ * Return: the length of the resulting decoded binary data in bytes,
+ *	   or -1 if the string isn't a valid base64 string.
+ */
+int base64_decode(const char *src, int srclen, u8 *dst)
+{
+	u32 ac = 0;
+	int bits = 0;
+	int i;
+	u8 *bp = dst;
+
+	for (i = 0; i < srclen; i++) {
+		const char *p = strchr(base64_table, src[i]);
+
+		if (src[i] == '=') {
+			ac = (ac << 6);
+			bits += 6;
+			if (bits >= 8)
+				bits -= 8;
+			continue;
+		}
+		if (p == NULL || src[i] == 0)
+			return -1;
+		ac = (ac << 6) | (p - base64_table);
+		bits += 6;

lib/base64.c line 103

Quoted 10 lines
lib/base64.c new file +10 -0
+		if (bits >= 8) {
+			bits -= 8;
+			*bp++ = (u8)(ac >> bits);
+		}
+	}
+	if (ac & ((1 << bits) - 1))
+		return -1;
+	return bp - dst;
+}
+EXPORT_SYMBOL_GPL(base64_decode);
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
author maintainer
#12 lore raw

PATCH v5 5/12 nvme: add definitions for NVMe In-Band authentication

In reply to Hannes Reinecke

Add new definitions for NVMe In-band authentication as defined in the NVMe Base Specification v2.0.

---
 include/linux/nvme.h | 186 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 185 insertions(+), 1 deletion(-)
include/linux/nvme.h +185 -1
index 855dd9b3e84b..3e3858d3976f 100644
@@ -19,6 +19,7 @@
 #define NVMF_TRSVCID_SIZE	32
 #define NVMF_TRADDR_SIZE	256
 #define NVMF_TSAS_SIZE		256
+#define NVMF_AUTH_HASH_LEN	64
 
 #define NVME_DISC_SUBSYS_NAME	"nqn.2014-08.org.nvmexpress.discovery"
 
@@ -1278,6 +1279,8 @@ enum nvmf_capsule_command {
 	nvme_fabrics_type_property_set	= 0x00,
 	nvme_fabrics_type_connect	= 0x01,
 	nvme_fabrics_type_property_get	= 0x04,
+	nvme_fabrics_type_auth_send	= 0x05,
+	nvme_fabrics_type_auth_receive	= 0x06,
 };
 
 #define nvme_fabrics_type_name(type)   { type, #type }
@@ -1285,7 +1288,9 @@ enum nvmf_capsule_command {
 	__print_symbolic(type,						\
 		nvme_fabrics_type_name(nvme_fabrics_type_property_set),	\
 		nvme_fabrics_type_name(nvme_fabrics_type_connect),	\
-		nvme_fabrics_type_name(nvme_fabrics_type_property_get))
+		nvme_fabrics_type_name(nvme_fabrics_type_property_get), \
+		nvme_fabrics_type_name(nvme_fabrics_type_auth_send),	\
+		nvme_fabrics_type_name(nvme_fabrics_type_auth_receive))
 
 /*
  * If not fabrics command, fctype will be ignored.
@@ -1415,6 +1420,183 @@ struct nvmf_property_get_command {
 	__u8		resv4[16];
 };
 
+struct nvmf_auth_send_command {
+	__u8		opcode;
+	__u8		resv1;
+	__u16		command_id;
+	__u8		fctype;
+	__u8		resv2[19];
+	union nvme_data_ptr dptr;
+	__u8		resv3;
+	__u8		spsp0;
+	__u8		spsp1;
+	__u8		secp;
+	__le32		tl;
+	__u8		resv4[16];
+};
+
+struct nvmf_auth_receive_command {
+	__u8		opcode;
+	__u8		resv1;
+	__u16		command_id;
+	__u8		fctype;
+	__u8		resv2[19];
+	union nvme_data_ptr dptr;
+	__u8		resv3;
+	__u8		spsp0;
+	__u8		spsp1;
+	__u8		secp;
+	__le32		al;
+	__u8		resv4[16];
+};
+
+/* Value for secp */
+enum {
+	NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER	= 0xe9,
+};
+
+/* Defined value for auth_type */
+enum {
+	NVME_AUTH_COMMON_MESSAGES	= 0x00,
+	NVME_AUTH_DHCHAP_MESSAGES	= 0x01,
+};
+
+/* Defined messages for auth_id */
+enum {
+	NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE	= 0x00,
+	NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE	= 0x01,
+	NVME_AUTH_DHCHAP_MESSAGE_REPLY		= 0x02,
+	NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1	= 0x03,
+	NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2	= 0x04,
+	NVME_AUTH_DHCHAP_MESSAGE_FAILURE2	= 0xf0,
+	NVME_AUTH_DHCHAP_MESSAGE_FAILURE1	= 0xf1,
+};
+
+struct nvmf_auth_dhchap_protocol_descriptor {
+	__u8		authid;
+	__u8		rsvd;
+	__u8		halen;
+	__u8		dhlen;
+	__u8		idlist[60];
+};
+
+enum {
+	NVME_AUTH_DHCHAP_AUTH_ID	= 0x01,
+};
+
+/* Defined hash functions for DH-HMAC-CHAP authentication */
+enum {
+	NVME_AUTH_DHCHAP_SHA256	= 0x01,
+	NVME_AUTH_DHCHAP_SHA384	= 0x02,
+	NVME_AUTH_DHCHAP_SHA512	= 0x03,
+};
+
+/* Defined Diffie-Hellman group identifiers for DH-HMAC-CHAP authentication */
+enum {
+	NVME_AUTH_DHCHAP_DHGROUP_NULL	= 0x00,
+	NVME_AUTH_DHCHAP_DHGROUP_2048	= 0x01,
+	NVME_AUTH_DHCHAP_DHGROUP_3072	= 0x02,
+	NVME_AUTH_DHCHAP_DHGROUP_4096	= 0x03,
+	NVME_AUTH_DHCHAP_DHGROUP_6144	= 0x04,
+	NVME_AUTH_DHCHAP_DHGROUP_8192	= 0x05,
+};
+
+union nvmf_auth_protocol {
+	struct nvmf_auth_dhchap_protocol_descriptor dhchap;
+};
+
+struct nvmf_auth_dhchap_negotiate_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd;
+	__le16		t_id;
+	__u8		sc_c;
+	__u8		napd;
+	union nvmf_auth_protocol auth_protocol[];
+};
+
+struct nvmf_auth_dhchap_challenge_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__u16		rsvd1;
+	__le16		t_id;
+	__u8		hl;
+	__u8		rsvd2;
+	__u8		hashid;
+	__u8		dhgid;
+	__le16		dhvlen;
+	__le32		seqnum;
+	/* 'hl' bytes of challenge value */
+	__u8		cval[];
+	/* followed by 'dhvlen' bytes of DH value */
+};
+
+struct nvmf_auth_dhchap_reply_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		hl;
+	__u8		rsvd2;
+	__u8		cvalid;
+	__u8		rsvd3;
+	__le16		dhvlen;
+	__le32		seqnum;
+	/* 'hl' bytes of response data */
+	__u8		rval[];
+	/* followed by 'hl' bytes of Challenge value */
+	/* followed by 'dhvlen' bytes of DH value */
+};
+
+enum {
+	NVME_AUTH_DHCHAP_RESPONSE_VALID	= (1 << 0),
+};
+
+struct nvmf_auth_dhchap_success1_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		hl;
+	__u8		rsvd2;
+	__u8		rvalid;
+	__u8		rsvd3[7];
+	/* 'hl' bytes of response value if 'rvalid' is set */
+	__u8		rval[];
+};
+
+struct nvmf_auth_dhchap_success2_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		rsvd2[10];
+};
+
+struct nvmf_auth_dhchap_failure_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		rescode;
+	__u8		rescode_exp;
+};
+
+enum {
+	NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED	= 0x01,
+};
+
+enum {
+	NVME_AUTH_DHCHAP_FAILURE_FAILED			= 0x01,
+	NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE		= 0x02,
+	NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH	= 0x03,
+	NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE		= 0x04,
+	NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE	= 0x05,
+	NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD	= 0x06,
+	NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE	= 0x07,
+};
+
+
 struct nvme_dbbuf {
 	__u8			opcode;
 	__u8			flags;
@@ -1458,6 +1640,8 @@ struct nvme_command {
 		struct nvmf_connect_command connect;
 		struct nvmf_property_set_command prop_set;
 		struct nvmf_property_get_command prop_get;
+		struct nvmf_auth_send_command auth_send;
+		struct nvmf_auth_receive_command auth_receive;
 		struct nvme_dbbuf dbbuf;
 		struct nvme_directive_cmd directive;
 	};
Signature · 1 line
2.29.2
Reviewed-by on v5 5/12
#13 lore raw

Re: [PATCH 05/12] nvme: add definitions for NVMe In-Band authentication

Quoted 227 lines · Hannes Reinecke

Add new definitions for NVMe In-band authentication as defined in the NVMe Base Specification v2.0.

---
  include/linux/nvme.h | 186 ++++++++++++++++++++++++++++++++++++++++++-
  1 file changed, 185 insertions(+), 1 deletion(-)
include/linux/nvme.h +183 -1
index 855dd9b3e84b..3e3858d3976f 100644
@@ -19,6 +19,7 @@
  #define NVMF_TRSVCID_SIZE	32
  #define NVMF_TRADDR_SIZE	256
  #define NVMF_TSAS_SIZE		256
+#define NVMF_AUTH_HASH_LEN	64
 
  #define NVME_DISC_SUBSYS_NAME	"nqn.2014-08.org.nvmexpress.discovery"
 
@@ -1278,6 +1279,8 @@ enum nvmf_capsule_command {
  	nvme_fabrics_type_property_set	= 0x00,
  	nvme_fabrics_type_connect	= 0x01,
  	nvme_fabrics_type_property_get	= 0x04,
+	nvme_fabrics_type_auth_send	= 0x05,
+	nvme_fabrics_type_auth_receive	= 0x06,
  };
 
  #define nvme_fabrics_type_name(type)   { type, #type }
@@ -1285,7 +1288,9 @@ enum nvmf_capsule_command {
  	__print_symbolic(type,						\
  		nvme_fabrics_type_name(nvme_fabrics_type_property_set),	\
  		nvme_fabrics_type_name(nvme_fabrics_type_connect),	\
-		nvme_fabrics_type_name(nvme_fabrics_type_property_get))
+		nvme_fabrics_type_name(nvme_fabrics_type_property_get), \
+		nvme_fabrics_type_name(nvme_fabrics_type_auth_send),	\
+		nvme_fabrics_type_name(nvme_fabrics_type_auth_receive))
 
  /*
   * If not fabrics command, fctype will be ignored.
@@ -1415,6 +1420,183 @@ struct nvmf_property_get_command {
  	__u8		resv4[16];
  };
 
+struct nvmf_auth_send_command {
+	__u8		opcode;
+	__u8		resv1;
+	__u16		command_id;
+	__u8		fctype;
+	__u8		resv2[19];
+	union nvme_data_ptr dptr;
+	__u8		resv3;
+	__u8		spsp0;
+	__u8		spsp1;
+	__u8		secp;
+	__le32		tl;
+	__u8		resv4[16];
+};
+
+struct nvmf_auth_receive_command {
+	__u8		opcode;
+	__u8		resv1;
+	__u16		command_id;
+	__u8		fctype;
+	__u8		resv2[19];
+	union nvme_data_ptr dptr;
+	__u8		resv3;
+	__u8		spsp0;
+	__u8		spsp1;
+	__u8		secp;
+	__le32		al;
+	__u8		resv4[16];
+};
+
+/* Value for secp */
+enum {
+	NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER	= 0xe9,
+};
+
+/* Defined value for auth_type */
+enum {
+	NVME_AUTH_COMMON_MESSAGES	= 0x00,
+	NVME_AUTH_DHCHAP_MESSAGES	= 0x01,
+};
+
+/* Defined messages for auth_id */
+enum {
+	NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE	= 0x00,
+	NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE	= 0x01,
+	NVME_AUTH_DHCHAP_MESSAGE_REPLY		= 0x02,
+	NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1	= 0x03,
+	NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2	= 0x04,
+	NVME_AUTH_DHCHAP_MESSAGE_FAILURE2	= 0xf0,
+	NVME_AUTH_DHCHAP_MESSAGE_FAILURE1	= 0xf1,
+};
+
+struct nvmf_auth_dhchap_protocol_descriptor {
+	__u8		authid;
+	__u8		rsvd;
+	__u8		halen;
+	__u8		dhlen;
+	__u8		idlist[60];
+};
+
+enum {
+	NVME_AUTH_DHCHAP_AUTH_ID	= 0x01,
+};
+
+/* Defined hash functions for DH-HMAC-CHAP authentication */
+enum {
+	NVME_AUTH_DHCHAP_SHA256	= 0x01,
+	NVME_AUTH_DHCHAP_SHA384	= 0x02,
+	NVME_AUTH_DHCHAP_SHA512	= 0x03,
+};
+
+/* Defined Diffie-Hellman group identifiers for DH-HMAC-CHAP authentication */
+enum {
+	NVME_AUTH_DHCHAP_DHGROUP_NULL	= 0x00,
+	NVME_AUTH_DHCHAP_DHGROUP_2048	= 0x01,
+	NVME_AUTH_DHCHAP_DHGROUP_3072	= 0x02,
+	NVME_AUTH_DHCHAP_DHGROUP_4096	= 0x03,
+	NVME_AUTH_DHCHAP_DHGROUP_6144	= 0x04,
+	NVME_AUTH_DHCHAP_DHGROUP_8192	= 0x05,
+};
+
+union nvmf_auth_protocol {
+	struct nvmf_auth_dhchap_protocol_descriptor dhchap;
+};
+
+struct nvmf_auth_dhchap_negotiate_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd;
+	__le16		t_id;
+	__u8		sc_c;
+	__u8		napd;
+	union nvmf_auth_protocol auth_protocol[];
+};
+
+struct nvmf_auth_dhchap_challenge_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__u16		rsvd1;
+	__le16		t_id;
+	__u8		hl;
+	__u8		rsvd2;
+	__u8		hashid;
+	__u8		dhgid;
+	__le16		dhvlen;
+	__le32		seqnum;
+	/* 'hl' bytes of challenge value */
+	__u8		cval[];
+	/* followed by 'dhvlen' bytes of DH value */
+};
+
+struct nvmf_auth_dhchap_reply_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		hl;
+	__u8		rsvd2;
+	__u8		cvalid;
+	__u8		rsvd3;
+	__le16		dhvlen;
+	__le32		seqnum;
+	/* 'hl' bytes of response data */
+	__u8		rval[];
+	/* followed by 'hl' bytes of Challenge value */
+	/* followed by 'dhvlen' bytes of DH value */
+};
+
+enum {
+	NVME_AUTH_DHCHAP_RESPONSE_VALID	= (1 << 0),
+};
+
+struct nvmf_auth_dhchap_success1_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		hl;
+	__u8		rsvd2;
+	__u8		rvalid;
+	__u8		rsvd3[7];
+	/* 'hl' bytes of response value if 'rvalid' is set */
+	__u8		rval[];
+};
+
+struct nvmf_auth_dhchap_success2_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		rsvd2[10];
+};
+
+struct nvmf_auth_dhchap_failure_data {
+	__u8		auth_type;
+	__u8		auth_id;
+	__le16		rsvd1;
+	__le16		t_id;
+	__u8		rescode;
+	__u8		rescode_exp;
+};
+
+enum {
+	NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED	= 0x01,
+};
+
+enum {
+	NVME_AUTH_DHCHAP_FAILURE_FAILED			= 0x01,
+	NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE		= 0x02,
+	NVME_AUTH_DHCHAP_FAILURE_CONCAT_MISMATCH	= 0x03,
+	NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE		= 0x04,
+	NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE	= 0x05,
+	NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD	= 0x06,
+	NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE	= 0x07,
+};
+
+
  struct nvme_dbbuf {
  	__u8			opcode;
  	__u8			flags;

include/linux/nvme.h struct nvme_command { · line 1647

Quoted 8 lines
include/linux/nvme.h +2 -0
@@ -1458,6 +1640,8 @@ struct nvme_command {
  		struct nvmf_connect_command connect;
  		struct nvmf_property_set_command prop_set;
  		struct nvmf_property_get_command prop_get;
+		struct nvmf_auth_send_command auth_send;
+		struct nvmf_auth_receive_command auth_receive;
  		struct nvme_dbbuf dbbuf;
  		struct nvme_directive_cmd directive;
  	};
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
author maintainer
#14 lore raw

PATCH v5 6/12 nvme-fabrics: decode 'authentication required' connect error

In reply to Hannes Reinecke

The 'connect' command might fail with NVME_SC_AUTH_REQUIRED, so we should be decoding this error, too.

---
 drivers/nvme/host/fabrics.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/nvme/host/fabrics.c +4 -0
index c5a2b71c5268..a1343a0790f6 100644
@@ -332,6 +332,10 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
 		dev_err(ctrl->device,
 			"Connect command failed: host path error\n");
 		break;
+	case NVME_SC_AUTH_REQUIRED:
+		dev_err(ctrl->device,
+			"Connect command failed: authentication required\n");
+		break;
 	default:
 		dev_err(ctrl->device,
 			"Connect command failed, error wo/DNR bit: %d\n",
Signature · 1 line
2.29.2
Reviewed-by on v5 6/12
#15 lore raw

Re: [PATCH 06/12] nvme-fabrics: decode 'authentication required' connect error

Quoted 16 lines · Hannes Reinecke

The 'connect' command might fail with NVME_SC_AUTH_REQUIRED, so we should be decoding this error, too.

---
  drivers/nvme/host/fabrics.c | 4 ++++
  1 file changed, 4 insertions(+)
drivers/nvme/host/fabrics.c +0 -0
index c5a2b71c5268..a1343a0790f6 100644

drivers/nvme/host/fabrics.c static void nvmf_log_connect_error(struct nvme_ctrl *ctrl, · line 341

Quoted 10 lines
drivers/nvme/host/fabrics.c +4 -0
@@ -332,6 +332,10 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
  		dev_err(ctrl->device,
  			"Connect command failed: host path error\n");
  		break;
+	case NVME_SC_AUTH_REQUIRED:
+		dev_err(ctrl->device,
+			"Connect command failed: authentication required\n");
+		break;
  	default:
  		dev_err(ctrl->device,
  			"Connect command failed, error wo/DNR bit: %d\n",
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
author maintainer
#16 lore raw

PATCH v5 7/12 nvme: Implement In-Band authentication

In reply to Hannes Reinecke

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'.

---
 drivers/nvme/host/Kconfig   |   11 +
 drivers/nvme/host/Makefile  |    1 +
 drivers/nvme/host/auth.c    | 1164 +++++++++++++++++++++++++++++++++++
 drivers/nvme/host/auth.h    |   25 +
 drivers/nvme/host/core.c    |  133 +++-
 drivers/nvme/host/fabrics.c |   79 ++-
 drivers/nvme/host/fabrics.h |    7 +
 drivers/nvme/host/nvme.h    |   36 ++
 drivers/nvme/host/tcp.c     |    1 +
 drivers/nvme/host/trace.c   |   32 +
 10 files changed, 1482 insertions(+), 7 deletions(-)
 create mode 100644 drivers/nvme/host/auth.c
 create mode 100644 drivers/nvme/host/auth.h
drivers/nvme/host/Kconfig +11 -0
index dc0450ca23a3..49269c581ec4 100644
@@ -83,3 +83,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.
drivers/nvme/host/Makefile +1 -0
index dfaacd472e5d..4bae2a4a8d8c 100644
@@ -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
 
drivers/nvme/host/auth.c new file +1164 -0

1,164 lines not on this page · raw message

drivers/nvme/host/auth.h new file +25 -0
new file mode 100644
index 000000000000..216957848398
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Hannes Reinecke, SUSE Software Solutions
+ */
+
+#ifndef _NVME_AUTH_H
+#define _NVME_AUTH_H
+
+#include <crypto/kpp.h>
+
+const char *nvme_auth_dhgroup_name(int dhgroup_id);
+int nvme_auth_dhgroup_pubkey_size(int dhgroup_id);
+int nvme_auth_dhgroup_privkey_size(int dhgroup_id);
+const char *nvme_auth_dhgroup_kpp(int dhgroup_id);
+int nvme_auth_dhgroup_id(const char *dhgroup_name);
+
+const char *nvme_auth_hmac_name(int hmac_id);
+const char *nvme_auth_digest_name(int hmac_id);
+int nvme_auth_hmac_id(const char *hmac_name);
+
+unsigned char *nvme_auth_extract_secret(unsigned char *secret,
+					u8 key_hash, size_t *key_len);
+u8 *nvme_auth_transform_key(u8 *key, size_t key_len, u8 key_hash, char *nqn);
+
+#endif /* _NVME_AUTH_H */
drivers/nvme/host/core.c +129 -4

215 lines not on this page · raw message

drivers/nvme/host/fabrics.c +76 -3

134 lines not on this page · raw message

drivers/nvme/host/fabrics.h +7 -0
index c3203ff1c654..c2a03d99ac26 100644
@@ -68,6 +68,8 @@ enum {
 	NVMF_OPT_FAIL_FAST_TMO	= 1 << 20,
 	NVMF_OPT_HOST_IFACE	= 1 << 21,
 	NVMF_OPT_DISCOVERY	= 1 << 22,
+	NVMF_OPT_DHCHAP_SECRET	= 1 << 23,
+	NVMF_OPT_DHCHAP_CTRL_SECRET = 1 << 24,
 };
 
 /**
@@ -97,6 +99,9 @@ enum {
  * @max_reconnects: maximum number of allowed reconnect attempts before removing
  *              the controller, (-1) means reconnect forever, zero means remove
  *              immediately;
+ * @dhchap_secret: DH-HMAC-CHAP secret
+ * @dhchap_ctrl_secret: DH-HMAC-CHAP controller secret for bi-directional
+ *              authentication
  * @disable_sqflow: disable controller sq flow control
  * @hdr_digest: generate/verify header digest (TCP)
  * @data_digest: generate/verify data digest (TCP)
@@ -121,6 +126,8 @@ struct nvmf_ctrl_options {
 	unsigned int		kato;
 	struct nvmf_host	*host;
 	int			max_reconnects;
+	char			*dhchap_secret;
+	char			*dhchap_ctrl_secret;
 	bool			disable_sqflow;
 	bool			hdr_digest;
 	bool			data_digest;
drivers/nvme/host/nvme.h +36 -0
index b334af8aa264..4d3e33cc6e27 100644
@@ -324,6 +324,19 @@ struct nvme_ctrl {
 	struct work_struct ana_work;
 #endif
 
+#ifdef CONFIG_NVME_AUTH
+	struct work_struct dhchap_auth_work;
+	struct list_head dhchap_auth_list;
+	struct mutex dhchap_auth_mutex;
+	unsigned char *dhchap_key;
+	unsigned char *dhchap_ctrl_key;
+	size_t dhchap_key_len;
+	size_t dhchap_ctrl_key_len;
+	u8 dhchap_key_hash;
+	u8 dhchap_ctrl_key_hash;
+	u16 transaction;
+#endif
+
 	/* Power saving configuration */
 	u64 ps_max_latency_us;
 	bool apst_enabled;
@@ -910,6 +923,29 @@ static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
 	return ctrl->sgls & ((1 << 0) | (1 << 1));
 }
 
+#ifdef CONFIG_NVME_AUTH
+void nvme_auth_init_ctrl(struct nvme_ctrl *ctrl);
+void nvme_auth_stop(struct nvme_ctrl *ctrl);
+int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid);
+int nvme_auth_wait(struct nvme_ctrl *ctrl, int qid);
+void nvme_auth_reset(struct nvme_ctrl *ctrl);
+void nvme_auth_free(struct nvme_ctrl *ctrl);
+int nvme_auth_generate_key(struct nvme_ctrl *ctrl);
+int nvme_auth_generate_ctrl_key(struct nvme_ctrl *ctrl);
+#else
+static inline void nvme_auth_init_ctrl(struct nvme_ctrl *ctrl) {};
+static inline void nvme_auth_stop(struct nvme_ctrl *ctrl) {};
+static inline int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int qid)
+{
+	return -EPROTONOSUPPORT;
+}
+static inline int nvme_auth_wait(struct nvme_ctrl *ctrl, int qid)
+{
+	return NVME_SC_AUTH_REQUIRED;
+}
+static inline void nvme_auth_free(struct nvme_ctrl *ctrl) {};
+#endif
+
 u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
 			 u8 opcode);
 int nvme_execute_passthru_rq(struct request *rq);
drivers/nvme/host/tcp.c +1 -0
index 33bc83d8d992..bd8c724b3d13 100644
@@ -2096,6 +2096,7 @@ static void nvme_tcp_error_recovery_work(struct work_struct *work)
 				struct nvme_tcp_ctrl, err_work);
 	struct nvme_ctrl *ctrl = &tcp_ctrl->ctrl;
 
+	nvme_auth_stop(ctrl);
 	nvme_stop_keep_alive(ctrl);
 	nvme_tcp_teardown_io_queues(ctrl, false);
 	/* unquiesce to fail fast pending requests */
drivers/nvme/host/trace.c +32 -0
index 2a89c5aa0790..1c36fcedea20 100644
@@ -287,6 +287,34 @@ static const char *nvme_trace_fabrics_property_get(struct trace_seq *p, u8 *spc)
 	return ret;
 }
 
+static const char *nvme_trace_fabrics_auth_send(struct trace_seq *p, u8 *spc)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+	u8 spsp0 = spc[1];
+	u8 spsp1 = spc[2];
+	u8 secp = spc[3];
+	u32 tl = get_unaligned_le32(spc + 4);
+
+	trace_seq_printf(p, "spsp0=%02x, spsp1=%02x, secp=%02x, tl=%u",
+			 spsp0, spsp1, secp, tl);
+	trace_seq_putc(p, 0);
+	return ret;
+}
+
+static const char *nvme_trace_fabrics_auth_receive(struct trace_seq *p, u8 *spc)
+{
+	const char *ret = trace_seq_buffer_ptr(p);
+	u8 spsp0 = spc[1];
+	u8 spsp1 = spc[2];
+	u8 secp = spc[3];
+	u32 al = get_unaligned_le32(spc + 4);
+
+	trace_seq_printf(p, "spsp0=%02x, spsp1=%02x, secp=%02x, al=%u",
+			 spsp0, spsp1, secp, al);
+	trace_seq_putc(p, 0);
+	return ret;
+}
+
 static const char *nvme_trace_fabrics_common(struct trace_seq *p, u8 *spc)
 {
 	const char *ret = trace_seq_buffer_ptr(p);
@@ -306,6 +334,10 @@ const char *nvme_trace_parse_fabrics_cmd(struct trace_seq *p,
 		return nvme_trace_fabrics_connect(p, spc);
 	case nvme_fabrics_type_property_get:
 		return nvme_trace_fabrics_property_get(p, spc);
+	case nvme_fabrics_type_auth_send:
+		return nvme_trace_fabrics_auth_send(p, spc);
+	case nvme_fabrics_type_auth_receive:
+		return nvme_trace_fabrics_auth_receive(p, spc);
 	default:
 		return nvme_trace_fabrics_common(p, spc);
 	}
Signature · 1 line
2.29.2
maintainer
#17 lore raw

Re: [PATCH 07/12] nvme: Implement In-Band authentication

Quoted 268 lines · Hannes Reinecke

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'.

---
  drivers/nvme/host/Kconfig   |   11 +
  drivers/nvme/host/Makefile  |    1 +
  drivers/nvme/host/auth.c    | 1164 +++++++++++++++++++++++++++++++++++
  drivers/nvme/host/auth.h    |   25 +
  drivers/nvme/host/core.c    |  133 +++-
  drivers/nvme/host/fabrics.c |   79 ++-
  drivers/nvme/host/fabrics.h |    7 +
  drivers/nvme/host/nvme.h    |   36 ++
  drivers/nvme/host/tcp.c     |    1 +
  drivers/nvme/host/trace.c   |   32 +
  10 files changed, 1482 insertions(+), 7 deletions(-)

create mode 100644 drivers/nvme/host/auth.c
create mode 100644 drivers/nvme/host/auth.h

drivers/nvme/host/Kconfig +11 -0
index dc0450ca23a3..49269c581ec4 100644
@@ -83,3 +83,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.
drivers/nvme/host/Makefile +1 -0
index dfaacd472e5d..4bae2a4a8d8c 100644
@@ -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
 
drivers/nvme/host/auth.c new file +206 -0
new file mode 100644
index 000000000000..6ab95a178213
@@ -0,0 +1,1164 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Hannes Reinecke, SUSE Linux
+ */
+
+#include <linux/crc32.h>
+#include <linux/base64.h>
+#include <asm/unaligned.h>
+#include <crypto/hash.h>
+#include <crypto/dh.h>
+#include <crypto/ffdhe.h>
+#include "nvme.h"
+#include "fabrics.h"
+#include "auth.h"
+
+static atomic_t nvme_dhchap_seqnum = ATOMIC_INIT(0);
+
+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;
+	u8 hash_len;
+	u8 dhgroup_id;
+	u8 c1[64];
+	u8 c2[64];
+	u8 response[64];
+	u8 *host_response;
+};
+
+static struct nvme_auth_dhgroup_map {
+	int id;
+	const char name[16];
+	const char kpp[16];
+	int privkey_size;
+	int pubkey_size;
+} dhgroup_map[] = {
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_NULL,
+	  .name = "null", .kpp = "null",
+	  .privkey_size = 0, .pubkey_size = 0 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_2048,
+	  .name = "ffdhe2048", .kpp = "dh",
+	  .privkey_size = 256, .pubkey_size = 256 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_3072,
+	  .name = "ffdhe3072", .kpp = "dh",
+	  .privkey_size = 384, .pubkey_size = 384 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_4096,
+	  .name = "ffdhe4096", .kpp = "dh",
+	  .privkey_size = 512, .pubkey_size = 512 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_6144,
+	  .name = "ffdhe6144", .kpp = "dh",
+	  .privkey_size = 768, .pubkey_size = 768 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_8192,
+	  .name = "ffdhe8192", .kpp = "dh",
+	  .privkey_size = 1024, .pubkey_size = 1024 },
+};
+
+const char *nvme_auth_dhgroup_name(int 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);
+
+int nvme_auth_dhgroup_pubkey_size(int dhgroup_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
+		if (dhgroup_map[i].id == dhgroup_id)
+			return dhgroup_map[i].pubkey_size;
+	}
+	return -1;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_pubkey_size);
+
+int nvme_auth_dhgroup_privkey_size(int dhgroup_id)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
+		if (dhgroup_map[i].id == dhgroup_id)
+			return dhgroup_map[i].privkey_size;
+	}
+	return -1;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_privkey_size);
+
+const char *nvme_auth_dhgroup_kpp(int 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);
+
+int 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 -1;
+}
+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_DHCHAP_SHA256, .len = 32,
+	 .hmac = "hmac(sha256)", .digest = "sha256" },
+	{.id = NVME_AUTH_DHCHAP_SHA384, .len = 48,
+	 .hmac = "hmac(sha384)", .digest = "sha384" },
+	{.id = NVME_AUTH_DHCHAP_SHA512, .len = 64,
+	 .hmac = "hmac(sha512)", .digest = "sha512" },
+};
+
+const char *nvme_auth_hmac_name(int 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(int 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);
+
+int 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 -1;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_hmac_id);
+
+int nvme_auth_hmac_hash_len(int 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);
+
+unsigned char *nvme_auth_extract_secret(unsigned char *secret, u8 key_hash,
+					size_t *out_len)
+{
+	unsigned char *key, *p;
+	u32 crc;
+	int 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(allocated_len, GFP_KERNEL);
+	if (!key)
+		return ERR_PTR(-ENOMEM);
+

drivers/nvme/host/auth.c line 216

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	key_len = base64_decode(secret, allocated_len, key);
+	if (key_len < 0) {
+		pr_debug("base64 key decoding error %d\n",
+			 key_len);
+		return ERR_PTR(key_len);
+	}
+	if (key_len != 36 && key_len != 52 &&
+	    key_len != 68) {
+		pr_debug("Invalid key len %d\n",
+			 key_len);

pr_err?

drivers/nvme/host/auth.c line 223

Quoted 7 lines
drivers/nvme/host/auth.c new file +7 -0
+		kfree_sensitive(key);
+		return ERR_PTR(-EINVAL);
+	}
+	if (key_hash > 0 &&
+	    (key_len - 4) != nvme_auth_hmac_hash_len(key_hash)) {
+		pr_debug("Invalid key len %d for %s\n", key_len,
+			 nvme_auth_hmac_name(key_hash));

pr_err?

Quoted 5 lines
drivers/nvme/host/auth.c new file +5 -0
+		kfree_sensitive(key);
+		return ERR_PTR(-EINVAL);
+	}
+
+	/* The last four bytes is the CRC in little-endian format */

drivers/nvme/host/auth.c line 238

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	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_len);
+
+	if (get_unaligned_le32(key + key_len) != crc) {
+		pr_debug("DH-HMAC-CHAP key crc mismatch (key %08x, crc %08x)\n",
+		       get_unaligned_le32(key + key_len), crc);

pr_err?

Quoted 13 lines
drivers/nvme/host/auth.c new file +13 -0
+		kfree_sensitive(key);
+		return ERR_PTR(-EKEYREJECTED);
+	}
+	*out_len = key_len;
+	return key;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_extract_secret);
+
+u8 *nvme_auth_transform_key(u8 *key, size_t key_len, u8 key_hash, char *nqn)
+{
+	const char *hmac_name = nvme_auth_hmac_name(key_hash);
+	struct crypto_shash *key_tfm;
+	struct shash_desc *shash;

drivers/nvme/host/auth.c line 261

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	u8 *transformed_key;
+	int ret;
+
+	if (key_hash == 0) {
+		transformed_key = kmemdup(key, key_len, GFP_KERNEL);
+		return transformed_key ? transformed_key : ERR_PTR(-ENOMEM);
+	}
+
+	if (!key || !key_len) {
+		pr_warn("No key specified\n");

pr_err?

drivers/nvme/host/auth.c line 265

Quoted 4 lines
drivers/nvme/host/auth.c new file +4 -0
+		return ERR_PTR(-ENOKEY);
+	}
+	if (!hmac_name) {
+		pr_warn("Invalid key hash id %d\n", key_hash);

pr_err?

Quoted 59 lines
drivers/nvme/host/auth.c new file +59 -0
+		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_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);
+
+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 = qid == NVME_QID_ANY ?
+		0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED;
+	struct request_queue *q = qid == NVME_QID_ANY ?
+		ctrl->fabrics_q : ctrl->connect_q;
+	int ret;
+
+	cmd.auth_send.opcode = nvme_fabrics_command;
+	cmd.auth_send.fctype = nvme_fabrics_type_auth_send;

drivers/nvme/host/auth.c line 334

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	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, flags);
+	if (ret > 0)
+		dev_dbg(ctrl->device,
+			"%s: qid %d nvme status %d\n", __func__, qid, ret);

dev_err? Also can we phrase "failed auth_send" instead of the __func__?

drivers/nvme/host/auth.c line 337

Quoted 3 lines
drivers/nvme/host/auth.c new file +3 -0
+	else if (ret < 0)
+		dev_dbg(ctrl->device,
+			"%s: qid %d error %d\n", __func__, qid, ret);

dev_err?

Quoted 15 lines
drivers/nvme/host/auth.c new file +15 -0
+	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 = qid == NVME_QID_ANY ?
+		0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED;
+	struct request_queue *q = qid == NVME_QID_ANY ?
+		ctrl->fabrics_q : ctrl->connect_q;
+	int ret;
+
+	cmd.auth_receive.opcode = nvme_fabrics_command;
+	cmd.auth_receive.fctype = nvme_fabrics_type_auth_receive;

drivers/nvme/host/auth.c line 362

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	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, flags);
+	if (ret > 0) {
+		dev_dbg(ctrl->device, "%s: qid %d nvme status %x\n",
+			__func__, qid, ret);

dev_err? "failed auth_recv" instead of the __func__

drivers/nvme/host/auth.c line 367

Quoted 5 lines
drivers/nvme/host/auth.c new file +5 -0
+		ret = -EIO;
+	}
+	if (ret < 0) {
+		dev_dbg(ctrl->device, "%s: qid %d error %d\n",
+			__func__, qid, ret);

dev_err

Quoted 18 lines
drivers/nvme/host/auth.c new file +18 -0
+		return ret;
+	}
+
+	return 0;
+}
+
+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 ||

drivers/nvme/host/auth.c line 395

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	    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));

why not dev_err?

Quoted 448 lines
drivers/nvme/host/auth.c new file +448 -0
+		return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE;
+	}
+	return 0;
+}
+
+static int nvme_auth_set_dhchap_negotiate_data(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	struct nvmf_auth_dhchap_negotiate_data *data = chap->buf;
+	size_t size = sizeof(*data) + sizeof(union nvmf_auth_protocol);
+
+	if (chap->buf_size < size) {
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		return -EINVAL;
+	}
+	memset((u8 *)chap->buf, 0, size);
+	data->auth_type = NVME_AUTH_COMMON_MESSAGES;
+	data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
+	data->t_id = cpu_to_le16(chap->transaction);
+	data->sc_c = 0; /* No secure channel concatenation */
+	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_DHCHAP_SHA256;
+	data->auth_protocol[0].dhchap.idlist[1] = NVME_AUTH_DHCHAP_SHA384;
+	data->auth_protocol[0].dhchap.idlist[2] = NVME_AUTH_DHCHAP_SHA512;
+	data->auth_protocol[0].dhchap.idlist[3] = NVME_AUTH_DHCHAP_DHGROUP_NULL;
+	data->auth_protocol[0].dhchap.idlist[4] = NVME_AUTH_DHCHAP_DHGROUP_2048;
+	data->auth_protocol[0].dhchap.idlist[5] = NVME_AUTH_DHCHAP_DHGROUP_3072;
+	data->auth_protocol[0].dhchap.idlist[6] = NVME_AUTH_DHCHAP_DHGROUP_4096;
+	data->auth_protocol[0].dhchap.idlist[7] = NVME_AUTH_DHCHAP_DHGROUP_6144;
+	data->auth_protocol[0].dhchap.idlist[8] = NVME_AUTH_DHCHAP_DHGROUP_8192;
+
+	return size;
+}
+
+static int nvme_auth_process_dhchap_challenge(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	struct nvmf_auth_dhchap_challenge_data *data = chap->buf;
+	u16 dhvlen = le16_to_cpu(data->dhvlen);
+	size_t size = sizeof(*data) + data->hl + dhvlen;
+	const char *hmac_name, *kpp_name;
+
+	if (chap->buf_size < size) {
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		return NVME_SC_INVALID_FIELD;
+	}
+
+	hmac_name = nvme_auth_hmac_name(data->hashid);
+	if (!hmac_name) {
+		dev_warn(ctrl->device,
+			 "qid %d: invalid HASH ID %d\n",
+			 chap->qid, data->hashid);
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
+		return NVME_SC_INVALID_FIELD;
+	}
+
+	if (chap->hash_id == data->hashid && chap->shash_tfm &&
+	    !strcmp(crypto_shash_alg_name(chap->shash_tfm), hmac_name) &&
+	    crypto_shash_digestsize(chap->shash_tfm) == data->hl) {
+		dev_dbg(ctrl->device,
+			"qid %d: reuse existing hash %s\n",
+			chap->qid, hmac_name);
+		goto select_kpp;
+	}
+
+	/* Reset if hash cannot be reused */
+	if (chap->shash_tfm) {
+		crypto_free_shash(chap->shash_tfm);
+		chap->hash_id = 0;
+		chap->hash_len = 0;
+	}
+	chap->shash_tfm = crypto_alloc_shash(hmac_name, 0,
+					     CRYPTO_ALG_ALLOCATES_MEMORY);
+	if (IS_ERR(chap->shash_tfm)) {
+		dev_warn(ctrl->device,
+			 "qid %d: failed to allocate hash %s, error %ld\n",
+			 chap->qid, hmac_name, PTR_ERR(chap->shash_tfm));
+		chap->shash_tfm = NULL;
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
+		return NVME_SC_AUTH_REQUIRED;
+	}
+
+	if (crypto_shash_digestsize(chap->shash_tfm) != data->hl) {
+		dev_warn(ctrl->device,
+			 "qid %d: invalid hash length %d\n",
+			 chap->qid, data->hl);
+		crypto_free_shash(chap->shash_tfm);
+		chap->shash_tfm = NULL;
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
+		return NVME_SC_AUTH_REQUIRED;
+	}
+
+	/* Reset host response if the hash had been changed */
+	if (chap->hash_id != data->hashid) {
+		kfree(chap->host_response);
+		chap->host_response = NULL;
+	}
+
+	chap->hash_id = data->hashid;
+	chap->hash_len = data->hl;
+	dev_dbg(ctrl->device, "qid %d: selected hash %s\n",
+		chap->qid, hmac_name);
+
+select_kpp:
+	kpp_name = nvme_auth_dhgroup_kpp(data->dhgid);
+	if (!kpp_name) {
+		dev_warn(ctrl->device,
+			 "qid %d: invalid DH group id %d\n",
+			 chap->qid, data->dhgid);
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
+		return NVME_SC_AUTH_REQUIRED;
+	}
+
+	if (data->dhgid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {
+		dev_warn(ctrl->device,
+			 "qid %d: unsupported DH group %s\n",
+			 chap->qid, kpp_name);
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
+		return NVME_SC_AUTH_REQUIRED;
+	} else if (dhvlen != 0) {
+		dev_warn(ctrl->device,
+			 "qid %d: invalid DH value for NULL DH\n",
+			 chap->qid);
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		return NVME_SC_INVALID_FIELD;
+	}
+	chap->dhgroup_id = data->dhgid;
+
+	chap->s1 = le32_to_cpu(data->seqnum);
+	memcpy(chap->c1, data->cval, chap->hash_len);
+
+	return 0;
+}
+
+static int nvme_auth_set_dhchap_reply_data(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	struct nvmf_auth_dhchap_reply_data *data = chap->buf;
+	size_t size = sizeof(*data);
+
+	size += 2 * chap->hash_len;
+
+	if (chap->buf_size < size) {
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		return -EINVAL;
+	}
+
+	memset(chap->buf, 0, size);
+	data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
+	data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
+	data->t_id = cpu_to_le16(chap->transaction);
+	data->hl = chap->hash_len;
+	data->dhvlen = 0;
+	memcpy(data->rval, chap->response, chap->hash_len);
+	if (ctrl->opts->dhchap_ctrl_secret) {
+		get_random_bytes(chap->c2, chap->hash_len);
+		data->cvalid = 1;
+		chap->s2 = atomic_inc_return(&nvme_dhchap_seqnum);
+		memcpy(data->rval + chap->hash_len, chap->c2,
+		       chap->hash_len);
+		dev_dbg(ctrl->device, "%s: qid %d ctrl challenge %*ph\n",
+			__func__, chap->qid,
+			chap->hash_len, chap->c2);
+	} else {
+		memset(chap->c2, 0, chap->hash_len);
+		chap->s2 = 0;
+	}
+	data->seqnum = cpu_to_le32(chap->s2);
+	return size;
+}
+
+static int nvme_auth_process_dhchap_success1(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	struct nvmf_auth_dhchap_success1_data *data = chap->buf;
+	size_t size = sizeof(*data);
+
+	if (ctrl->opts->dhchap_ctrl_secret)
+		size += chap->hash_len;
+
+	if (chap->buf_size < size) {
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		return NVME_SC_INVALID_FIELD;
+	}
+
+	if (data->hl != chap->hash_len) {
+		dev_warn(ctrl->device,
+			 "qid %d: invalid hash length %d\n",
+			 chap->qid, data->hl);
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
+		return NVME_SC_INVALID_FIELD;
+	}
+
+	/* Just print out information for the admin queue */
+	if (chap->qid == -1)
+		dev_info(ctrl->device,
+			 "qid 0: authenticated with hash %s dhgroup %s\n",
+			 nvme_auth_hmac_name(chap->hash_id),
+			 nvme_auth_dhgroup_name(chap->dhgroup_id));
+
+	if (!data->rvalid)
+		return 0;
+
+	/* Validate controller response */
+	if (memcmp(chap->response, data->rval, data->hl)) {
+		dev_dbg(ctrl->device, "%s: qid %d ctrl response %*ph\n",
+			__func__, chap->qid, chap->hash_len, data->rval);
+		dev_dbg(ctrl->device, "%s: qid %d host response %*ph\n",
+			__func__, chap->qid, chap->hash_len, chap->response);
+		dev_warn(ctrl->device,
+			 "qid %d: controller authentication failed\n",
+			 chap->qid);
+		chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
+		return NVME_SC_AUTH_REQUIRED;
+	}
+
+	/* Just print out information for the admin queue */
+	if (chap->qid == -1)
+		dev_info(ctrl->device,
+			 "qid 0: controller authenticated\n");
+	return 0;
+}
+
+static int nvme_auth_set_dhchap_success2_data(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	struct nvmf_auth_dhchap_success2_data *data = chap->buf;
+	size_t size = sizeof(*data);
+
+	memset(chap->buf, 0, size);
+	data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
+	data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2;
+	data->t_id = cpu_to_le16(chap->transaction);
+
+	return size;
+}
+
+static int nvme_auth_set_dhchap_failure2_data(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	struct nvmf_auth_dhchap_failure_data *data = chap->buf;
+	size_t size = sizeof(*data);
+
+	memset(chap->buf, 0, size);
+	data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
+	data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
+	data->t_id = cpu_to_le16(chap->transaction);
+	data->rescode = NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED;
+	data->rescode_exp = chap->status;
+
+	return size;
+}
+
+static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
+	u8 buf[4], *challenge = chap->c1;
+	int ret;
+
+	dev_dbg(ctrl->device, "%s: qid %d host response seq %d transaction %d\n",
+		__func__, chap->qid, chap->s1, chap->transaction);
+
+	if (!chap->host_response) {
+		chap->host_response = nvme_auth_transform_key(ctrl->dhchap_key,
+					ctrl->dhchap_key_len,
+					ctrl->dhchap_key_hash,
+					ctrl->opts->host->nqn);
+		if (IS_ERR(chap->host_response)) {
+			ret = PTR_ERR(chap->host_response);
+			chap->host_response = NULL;
+			return ret;
+		}
+	} else {
+		dev_dbg(ctrl->device, "%s: qid %d re-using host response\n",
+			__func__, chap->qid);
+	}
+
+	ret = crypto_shash_setkey(chap->shash_tfm,
+			chap->host_response, ctrl->dhchap_key_len);
+	if (ret) {
+		dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
+			 chap->qid, ret);
+		goto out;
+	}
+
+	shash->tfm = chap->shash_tfm;
+	ret = crypto_shash_init(shash);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, challenge, chap->hash_len);
+	if (ret)
+		goto out;
+	put_unaligned_le32(chap->s1, buf);
+	ret = crypto_shash_update(shash, buf, 4);
+	if (ret)
+		goto out;
+	put_unaligned_le16(chap->transaction, buf);
+	ret = crypto_shash_update(shash, buf, 2);
+	if (ret)
+		goto out;
+	memset(buf, 0, sizeof(buf));
+	ret = crypto_shash_update(shash, buf, 1);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, "HostHost", 8);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, ctrl->opts->host->nqn,
+				  strlen(ctrl->opts->host->nqn));
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, buf, 1);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, ctrl->opts->subsysnqn,
+			    strlen(ctrl->opts->subsysnqn));
+	if (ret)
+		goto out;
+	ret = crypto_shash_final(shash, chap->response);
+out:
+	if (challenge != chap->c1)
+		kfree(challenge);
+	return ret;
+}
+
+static int nvme_auth_dhchap_ctrl_response(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)
+{
+	SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
+	u8 *ctrl_response;
+	u8 buf[4], *challenge = chap->c2;
+	int ret;
+
+	ctrl_response = nvme_auth_transform_key(ctrl->dhchap_ctrl_key,
+				ctrl->dhchap_ctrl_key_len,
+				ctrl->dhchap_ctrl_key_hash,
+				ctrl->opts->subsysnqn);
+	if (IS_ERR(ctrl_response)) {
+		ret = PTR_ERR(ctrl_response);
+		return ret;
+	}
+	ret = crypto_shash_setkey(chap->shash_tfm,
+			ctrl_response, ctrl->dhchap_ctrl_key_len);
+	if (ret) {
+		dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
+			 chap->qid, ret);
+		goto out;
+	}
+
+	dev_dbg(ctrl->device, "%s: qid %d host response seq %d transaction %d\n",
+		__func__, chap->qid, chap->s2, chap->transaction);
+	dev_dbg(ctrl->device, "%s: qid %d challenge %*ph\n",
+		__func__, chap->qid, chap->hash_len, challenge);
+	dev_dbg(ctrl->device, "%s: qid %d subsysnqn %s\n",
+		__func__, chap->qid, ctrl->opts->subsysnqn);
+	dev_dbg(ctrl->device, "%s: qid %d hostnqn %s\n",
+		__func__, chap->qid, ctrl->opts->host->nqn);
+	shash->tfm = chap->shash_tfm;
+	ret = crypto_shash_init(shash);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, challenge, chap->hash_len);
+	if (ret)
+		goto out;
+	put_unaligned_le32(chap->s2, buf);
+	ret = crypto_shash_update(shash, buf, 4);
+	if (ret)
+		goto out;
+	put_unaligned_le16(chap->transaction, buf);
+	ret = crypto_shash_update(shash, buf, 2);
+	if (ret)
+		goto out;
+	memset(buf, 0, 4);
+	ret = crypto_shash_update(shash, buf, 1);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, "Controller", 10);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, ctrl->opts->subsysnqn,
+				  strlen(ctrl->opts->subsysnqn));
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, buf, 1);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, ctrl->opts->host->nqn,
+				  strlen(ctrl->opts->host->nqn));
+	if (ret)
+		goto out;
+	ret = crypto_shash_final(shash, chap->response);
+out:
+	if (challenge != chap->c2)
+		kfree(challenge);
+	return ret;
+}
+
+int nvme_auth_generate_key(struct nvme_ctrl *ctrl)
+{
+	u8 *secret = ctrl->opts->dhchap_secret;
+	u8 *key;
+	size_t key_len;
+	u8 key_hash;
+
+	if (!secret)
+		return 0;
+
+	if (sscanf(secret, "DHHC-1:%hhd:%*s:", &key_hash) != 1)
+		return -EINVAL;
+
+	/* Pass in the secret without the 'DHHC-1:XX:' prefix */
+	key = nvme_auth_extract_secret(secret + 10, key_hash,
+				       &key_len);
+	if (IS_ERR(key)) {
+		dev_dbg(ctrl->device, "failed to extract key, error %ld\n",
+			PTR_ERR(key));
+		return PTR_ERR(key);
+	}
+
+	ctrl->dhchap_key = key;
+	key = NULL;
+	ctrl->dhchap_key_len = key_len;
+	ctrl->dhchap_key_hash = key_hash;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_generate_key);
+
+int nvme_auth_generate_ctrl_key(struct nvme_ctrl *ctrl)
+{
+	u8 *secret = ctrl->opts->dhchap_ctrl_secret;
+	u8 *key;
+	size_t key_len;
+	u8 key_hash;
+
+	if (!secret)
+		return 0;
+
+	if (sscanf(secret, "DHHC-1:%hhd:%*s:", &key_hash) != 1)
+		return -EINVAL;
+
+	/* Pass in the secret without the 'DHHC-1:XX:' prefix */
+	key = nvme_auth_extract_secret(secret + 10, key_hash,
+				       &key_len);

drivers/nvme/host/auth.c line 853

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+	if (IS_ERR(key))
+		return PTR_ERR(key);
+
+	ctrl->dhchap_ctrl_key = key;
+	key = NULL;
+	ctrl->dhchap_ctrl_key_len = key_len;
+	ctrl->dhchap_ctrl_key_hash = key_hash;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_generate_ctrl_key);

This and the other look identical just operate on
a different key, perhaps merge them into one?

Overall this looks sane to me.
Just nitpicking on the logging to use err when you hit a errors.

author maintainer
#18 lore raw

Re: [PATCH 07/12] nvme: Implement In-Band authentication

Quoted 274 lines · Sagi Grimberg
Quoted 271 lines · Hannes Reinecke

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'.

---
  drivers/nvme/host/Kconfig   |   11 +
  drivers/nvme/host/Makefile  |    1 +

  drivers/nvme/host/auth.c    | 1164 +++++++++++++++++++++++++++++++++++
  drivers/nvme/host/auth.h    |   25 +
  drivers/nvme/host/core.c    |  133 +++-

  drivers/nvme/host/fabrics.c |   79 ++-
  drivers/nvme/host/fabrics.h |    7 +
  drivers/nvme/host/nvme.h    |   36 ++
  drivers/nvme/host/tcp.c     |    1 +
  drivers/nvme/host/trace.c   |   32 +

  10 files changed, 1482 insertions(+), 7 deletions(-)

  create mode 100644 drivers/nvme/host/auth.c
  create mode 100644 drivers/nvme/host/auth.h

drivers/nvme/host/Kconfig +0 -0
index dc0450ca23a3..49269c581ec4 100644
@@ -83,3 +83,14 @@ config NVME_TCP

        from https://github.com/linux-nvme/nvme-cli.
          If unsure, say N.

drivers/nvme/host/Kconfig +9 -0
+
+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.

drivers/nvme/host/Kconfig +2 -0
+
+      If unsure, say N.
drivers/nvme/host/Makefile +0 -0
index dfaacd472e5d..4bae2a4a8d8c 100644
@@ -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..6ab95a178213

drivers/nvme/host/auth.c new file +191 -0
@@ -0,0 +1,1164 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2020 Hannes Reinecke, SUSE Linux
+ */
+
+#include <linux/crc32.h>
+#include <linux/base64.h>
+#include <asm/unaligned.h>
+#include <crypto/hash.h>
+#include <crypto/dh.h>
+#include <crypto/ffdhe.h>
+#include "nvme.h"
+#include "fabrics.h"
+#include "auth.h"
+
+static atomic_t nvme_dhchap_seqnum = ATOMIC_INIT(0);
+
+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;
+    u8 hash_len;
+    u8 dhgroup_id;
+    u8 c1[64];
+    u8 c2[64];
+    u8 response[64];
+    u8 *host_response;
+};
+
+static struct nvme_auth_dhgroup_map {
+    int id;
+    const char name[16];
+    const char kpp[16];
+    int privkey_size;
+    int pubkey_size;
+} dhgroup_map[] = {
+    { .id = NVME_AUTH_DHCHAP_DHGROUP_NULL,
+      .name = "null", .kpp = "null",
+      .privkey_size = 0, .pubkey_size = 0 },
+    { .id = NVME_AUTH_DHCHAP_DHGROUP_2048,
+      .name = "ffdhe2048", .kpp = "dh",
+      .privkey_size = 256, .pubkey_size = 256 },
+    { .id = NVME_AUTH_DHCHAP_DHGROUP_3072,
+      .name = "ffdhe3072", .kpp = "dh",
+      .privkey_size = 384, .pubkey_size = 384 },
+    { .id = NVME_AUTH_DHCHAP_DHGROUP_4096,
+      .name = "ffdhe4096", .kpp = "dh",
+      .privkey_size = 512, .pubkey_size = 512 },
+    { .id = NVME_AUTH_DHCHAP_DHGROUP_6144,
+      .name = "ffdhe6144", .kpp = "dh",
+      .privkey_size = 768, .pubkey_size = 768 },
+    { .id = NVME_AUTH_DHCHAP_DHGROUP_8192,
+      .name = "ffdhe8192", .kpp = "dh",
+      .privkey_size = 1024, .pubkey_size = 1024 },
+};
+
+const char *nvme_auth_dhgroup_name(int 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);
+
+int nvme_auth_dhgroup_pubkey_size(int dhgroup_id)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
+        if (dhgroup_map[i].id == dhgroup_id)
+            return dhgroup_map[i].pubkey_size;
+    }
+    return -1;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_pubkey_size);
+
+int nvme_auth_dhgroup_privkey_size(int dhgroup_id)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) {
+        if (dhgroup_map[i].id == dhgroup_id)
+            return dhgroup_map[i].privkey_size;
+    }
+    return -1;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_privkey_size);
+
+const char *nvme_auth_dhgroup_kpp(int 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);
+
+int 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 -1;
+}
+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_DHCHAP_SHA256, .len = 32,
+     .hmac = "hmac(sha256)", .digest = "sha256" },
+    {.id = NVME_AUTH_DHCHAP_SHA384, .len = 48,
+     .hmac = "hmac(sha384)", .digest = "sha384" },
+    {.id = NVME_AUTH_DHCHAP_SHA512, .len = 64,
+     .hmac = "hmac(sha512)", .digest = "sha512" },
+};
+
+const char *nvme_auth_hmac_name(int 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(int 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);
+
+int 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 -1;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_hmac_id);
+
+int nvme_auth_hmac_hash_len(int 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);
+
+unsigned char *nvme_auth_extract_secret(unsigned char *secret, u8

key_hash,
+                    size_t *out_len)

drivers/nvme/host/auth.c new file +18 -0
+{
+    unsigned char *key, *p;
+    u32 crc;
+    int 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(allocated_len, GFP_KERNEL);
+    if (!key)
+        return ERR_PTR(-ENOMEM);
+
+    key_len = base64_decode(secret, allocated_len, key);
+    if (key_len < 0) {
+        pr_debug("base64 key decoding error %d\n",
+             key_len);
Quoted 9 lines
Quoted 6 lines

+        return ERR_PTR(key_len);
+    }
+    if (key_len != 36 && key_len != 52 &&
+        key_len != 68) {
+        pr_debug("Invalid key len %d\n",
+             key_len);

pr_err?

Yeah; I've been running with debug enabled, so I would've seen it anyway.

Quoted 10 lines
Quoted 7 lines

+        kfree_sensitive(key);
+        return ERR_PTR(-EINVAL);
+    }
+    if (key_hash > 0 &&
+        (key_len - 4) != nvme_auth_hmac_hash_len(key_hash)) { +        pr_debug("Invalid key len %d for %s\n", key_len, +             nvme_auth_hmac_name(key_hash));

pr_err?

Same; will be fixing it.

Quoted 116 lines
Quoted 5 lines

+        kfree_sensitive(key);
+        return ERR_PTR(-EINVAL);
+    }

drivers/nvme/host/auth.c new file +2 -0
+
+    /* The last four bytes is the CRC in little-endian format */

drivers/nvme/host/auth.c line 238

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+    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_len);
+
+    if (get_unaligned_le32(key + key_len) != crc) {
+        pr_debug("DH-HMAC-CHAP key crc mismatch (key %08x, crc %08x)\n",
+               get_unaligned_le32(key + key_len), crc);

pr_err?

Quoted 14 lines

+        kfree_sensitive(key);
+        return ERR_PTR(-EKEYREJECTED);
+    }
+    *out_len = key_len;
+    return key;

drivers/nvme/host/auth.c new file +4 -0
+}
+EXPORT_SYMBOL_GPL(nvme_auth_extract_secret);
+
+u8 *nvme_auth_transform_key(u8 *key, size_t key_len, u8 key_hash,

char *nqn)

drivers/nvme/host/auth.c new file +4 -0
+{
+    const char *hmac_name = nvme_auth_hmac_name(key_hash);
+    struct crypto_shash *key_tfm;
+    struct shash_desc *shash;

drivers/nvme/host/auth.c line 261

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+    u8 *transformed_key;
+    int ret;
+
+    if (key_hash == 0) {
+        transformed_key = kmemdup(key, key_len, GFP_KERNEL);
+        return transformed_key ? transformed_key : ERR_PTR(-ENOMEM);
+    }
+
+    if (!key || !key_len) {
+        pr_warn("No key specified\n");

pr_err?

Quoted 4 lines

+        return ERR_PTR(-ENOKEY);
+    }
+    if (!hmac_name) {
+        pr_warn("Invalid key hash id %d\n", key_hash);

pr_err?

Quoted 64 lines

+        return ERR_PTR(-EINVAL);
+    }

drivers/nvme/host/auth.c new file +14 -0
+
+    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;
+    }

drivers/nvme/host/auth.c new file +43 -0
+
+    shash->tfm = key_tfm;
+    ret = crypto_shash_setkey(key_tfm, 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);
+
+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 = qid == NVME_QID_ANY ?
+        0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED;
+    struct request_queue *q = qid == NVME_QID_ANY ?
+        ctrl->fabrics_q : ctrl->connect_q;
+    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);
Quoted 9 lines
Quoted 6 lines

+
+    ret = __nvme_submit_sync_cmd(q, &cmd, NULL, data, tl, 0, qid, +                     0, flags);
+    if (ret > 0)
+        dev_dbg(ctrl->device,
+            "%s: qid %d nvme status %d\n", __func__, qid, ret);

dev_err? Also can we phrase "failed auth_send" instead of the __func__?

Yeah; the logging messages are inconsistent as it is. I've tried to stick the __func__ argument to any debug messages, and some human readable string for 'normal' errors.
Possibly not that consistent, though.

Quoted 64 lines
Quoted 3 lines

+    else if (ret < 0)
+        dev_dbg(ctrl->device,
+            "%s: qid %d error %d\n", __func__, qid, ret);

dev_err?

Quoted 15 lines

+    return ret;

drivers/nvme/host/auth.c new file +14 -0
+}
+
+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 = qid == NVME_QID_ANY ?
+        0 : BLK_MQ_REQ_NOWAIT | BLK_MQ_REQ_RESERVED;
+    struct request_queue *q = qid == NVME_QID_ANY ?
+        ctrl->fabrics_q : ctrl->connect_q;
+    int ret;
+
+    cmd.auth_receive.opcode = nvme_fabrics_command;
+    cmd.auth_receive.fctype = nvme_fabrics_type_auth_receive;

drivers/nvme/host/auth.c line 362

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+    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, flags);
+    if (ret > 0) {
+        dev_dbg(ctrl->device, "%s: qid %d nvme status %x\n",
+            __func__, qid, ret);

dev_err? "failed auth_recv" instead of the __func__

Quoted 5 lines

+        ret = -EIO;
+    }
+    if (ret < 0) {
+        dev_dbg(ctrl->device, "%s: qid %d error %d\n", +            __func__, qid, ret);

dev_err

Quoted 22 lines

+        return ret;
+    }

drivers/nvme/host/auth.c new file +20 -0
+
+    return 0;
+}
+
+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);
Quoted 9 lines
Quoted 6 lines

+        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));

why not dev_err?

Because it's a protocol error, and we can invoke the protocol error handling here.
Any dev_err() messages are inhibiting us to run the protocol at all. Or, at least, that's how I tried to handle things.

Quoted 461 lines
Quoted 461 lines

+        return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_MESSAGE; +    }
+    return 0;

drivers/nvme/host/auth.c new file +25 -0
+}
+
+static int nvme_auth_set_dhchap_negotiate_data(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    struct nvmf_auth_dhchap_negotiate_data *data = chap->buf;
+    size_t size = sizeof(*data) + sizeof(union nvmf_auth_protocol);
+
+    if (chap->buf_size < size) {
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+        return -EINVAL;
+    }
+    memset((u8 *)chap->buf, 0, size);
+    data->auth_type = NVME_AUTH_COMMON_MESSAGES;
+    data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
+    data->t_id = cpu_to_le16(chap->transaction);
+    data->sc_c = 0; /* No secure channel concatenation */
+    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_DHCHAP_SHA256;
+    data->auth_protocol[0].dhchap.idlist[1] = NVME_AUTH_DHCHAP_SHA384;
+    data->auth_protocol[0].dhchap.idlist[2] = NVME_AUTH_DHCHAP_SHA512;
+    data->auth_protocol[0].dhchap.idlist[3] =

NVME_AUTH_DHCHAP_DHGROUP_NULL;
+    data->auth_protocol[0].dhchap.idlist[4] =
NVME_AUTH_DHCHAP_DHGROUP_2048;
+    data->auth_protocol[0].dhchap.idlist[5] =
NVME_AUTH_DHCHAP_DHGROUP_3072;
+    data->auth_protocol[0].dhchap.idlist[6] =
NVME_AUTH_DHCHAP_DHGROUP_4096;
+    data->auth_protocol[0].dhchap.idlist[7] =
NVME_AUTH_DHCHAP_DHGROUP_6144;
+    data->auth_protocol[0].dhchap.idlist[8] =
NVME_AUTH_DHCHAP_DHGROUP_8192;

drivers/nvme/host/auth.c new file +231 -0
+
+    return size;
+}
+
+static int nvme_auth_process_dhchap_challenge(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    struct nvmf_auth_dhchap_challenge_data *data = chap->buf;
+    u16 dhvlen = le16_to_cpu(data->dhvlen);
+    size_t size = sizeof(*data) + data->hl + dhvlen;
+    const char *hmac_name, *kpp_name;
+
+    if (chap->buf_size < size) {
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+        return NVME_SC_INVALID_FIELD;
+    }
+
+    hmac_name = nvme_auth_hmac_name(data->hashid);
+    if (!hmac_name) {
+        dev_warn(ctrl->device,
+             "qid %d: invalid HASH ID %d\n",
+             chap->qid, data->hashid);
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
+        return NVME_SC_INVALID_FIELD;
+    }
+
+    if (chap->hash_id == data->hashid && chap->shash_tfm &&
+        !strcmp(crypto_shash_alg_name(chap->shash_tfm), hmac_name) &&
+        crypto_shash_digestsize(chap->shash_tfm) == data->hl) {
+        dev_dbg(ctrl->device,
+            "qid %d: reuse existing hash %s\n",
+            chap->qid, hmac_name);
+        goto select_kpp;
+    }
+
+    /* Reset if hash cannot be reused */
+    if (chap->shash_tfm) {
+        crypto_free_shash(chap->shash_tfm);
+        chap->hash_id = 0;
+        chap->hash_len = 0;
+    }
+    chap->shash_tfm = crypto_alloc_shash(hmac_name, 0,
+                         CRYPTO_ALG_ALLOCATES_MEMORY);
+    if (IS_ERR(chap->shash_tfm)) {
+        dev_warn(ctrl->device,
+             "qid %d: failed to allocate hash %s, error %ld\n",
+             chap->qid, hmac_name, PTR_ERR(chap->shash_tfm));
+        chap->shash_tfm = NULL;
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
+        return NVME_SC_AUTH_REQUIRED;
+    }
+
+    if (crypto_shash_digestsize(chap->shash_tfm) != data->hl) {
+        dev_warn(ctrl->device,
+             "qid %d: invalid hash length %d\n",
+             chap->qid, data->hl);
+        crypto_free_shash(chap->shash_tfm);
+        chap->shash_tfm = NULL;
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
+        return NVME_SC_AUTH_REQUIRED;
+    }
+
+    /* Reset host response if the hash had been changed */
+    if (chap->hash_id != data->hashid) {
+        kfree(chap->host_response);
+        chap->host_response = NULL;
+    }
+
+    chap->hash_id = data->hashid;
+    chap->hash_len = data->hl;
+    dev_dbg(ctrl->device, "qid %d: selected hash %s\n",
+        chap->qid, hmac_name);
+
+select_kpp:
+    kpp_name = nvme_auth_dhgroup_kpp(data->dhgid);
+    if (!kpp_name) {
+        dev_warn(ctrl->device,
+             "qid %d: invalid DH group id %d\n",
+             chap->qid, data->dhgid);
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
+        return NVME_SC_AUTH_REQUIRED;
+    }
+
+    if (data->dhgid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {
+        dev_warn(ctrl->device,
+             "qid %d: unsupported DH group %s\n",
+             chap->qid, kpp_name);
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
+        return NVME_SC_AUTH_REQUIRED;
+    } else if (dhvlen != 0) {
+        dev_warn(ctrl->device,
+             "qid %d: invalid DH value for NULL DH\n",
+             chap->qid);
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+        return NVME_SC_INVALID_FIELD;
+    }
+    chap->dhgroup_id = data->dhgid;
+
+    chap->s1 = le32_to_cpu(data->seqnum);
+    memcpy(chap->c1, data->cval, chap->hash_len);
+
+    return 0;
+}
+
+static int nvme_auth_set_dhchap_reply_data(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    struct nvmf_auth_dhchap_reply_data *data = chap->buf;
+    size_t size = sizeof(*data);
+
+    size += 2 * chap->hash_len;
+
+    if (chap->buf_size < size) {
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+        return -EINVAL;
+    }
+
+    memset(chap->buf, 0, size);
+    data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
+    data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_REPLY;
+    data->t_id = cpu_to_le16(chap->transaction);
+    data->hl = chap->hash_len;
+    data->dhvlen = 0;
+    memcpy(data->rval, chap->response, chap->hash_len);
+    if (ctrl->opts->dhchap_ctrl_secret) {
+        get_random_bytes(chap->c2, chap->hash_len);
+        data->cvalid = 1;
+        chap->s2 = atomic_inc_return(&nvme_dhchap_seqnum);
+        memcpy(data->rval + chap->hash_len, chap->c2,
+               chap->hash_len);
+        dev_dbg(ctrl->device, "%s: qid %d ctrl challenge %*ph\n",
+            __func__, chap->qid,
+            chap->hash_len, chap->c2);
+    } else {
+        memset(chap->c2, 0, chap->hash_len);
+        chap->s2 = 0;
+    }
+    data->seqnum = cpu_to_le32(chap->s2);
+    return size;
+}
+
+static int nvme_auth_process_dhchap_success1(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    struct nvmf_auth_dhchap_success1_data *data = chap->buf;
+    size_t size = sizeof(*data);
+
+    if (ctrl->opts->dhchap_ctrl_secret)
+        size += chap->hash_len;
+
+    if (chap->buf_size < size) {
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+        return NVME_SC_INVALID_FIELD;
+    }
+
+    if (data->hl != chap->hash_len) {
+        dev_warn(ctrl->device,
+             "qid %d: invalid hash length %d\n",
+             chap->qid, data->hl);
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;
+        return NVME_SC_INVALID_FIELD;
+    }
+
+    /* Just print out information for the admin queue */
+    if (chap->qid == -1)
+        dev_info(ctrl->device,
+             "qid 0: authenticated with hash %s dhgroup %s\n",
+             nvme_auth_hmac_name(chap->hash_id),
+             nvme_auth_dhgroup_name(chap->dhgroup_id));
+
+    if (!data->rvalid)
+        return 0;
+
+    /* Validate controller response */
+    if (memcmp(chap->response, data->rval, data->hl)) {
+        dev_dbg(ctrl->device, "%s: qid %d ctrl response %*ph\n",
+            __func__, chap->qid, chap->hash_len, data->rval);
+        dev_dbg(ctrl->device, "%s: qid %d host response %*ph\n",
+            __func__, chap->qid, chap->hash_len, chap->response);
+        dev_warn(ctrl->device,
+             "qid %d: controller authentication failed\n",
+             chap->qid);
+        chap->status = NVME_AUTH_DHCHAP_FAILURE_FAILED;
+        return NVME_SC_AUTH_REQUIRED;
+    }
+
+    /* Just print out information for the admin queue */
+    if (chap->qid == -1)
+        dev_info(ctrl->device,
+             "qid 0: controller authenticated\n");
+    return 0;
+}
+
+static int nvme_auth_set_dhchap_success2_data(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    struct nvmf_auth_dhchap_success2_data *data = chap->buf;
+    size_t size = sizeof(*data);
+
+    memset(chap->buf, 0, size);
+    data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
+    data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2;
+    data->t_id = cpu_to_le16(chap->transaction);
+
+    return size;
+}
+
+static int nvme_auth_set_dhchap_failure2_data(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    struct nvmf_auth_dhchap_failure_data *data = chap->buf;
+    size_t size = sizeof(*data);
+
+    memset(chap->buf, 0, size);
+    data->auth_type = NVME_AUTH_DHCHAP_MESSAGES;
+    data->auth_id = NVME_AUTH_DHCHAP_MESSAGE_FAILURE2;
+    data->t_id = cpu_to_le16(chap->transaction);
+    data->rescode = NVME_AUTH_DHCHAP_FAILURE_REASON_FAILED;
+    data->rescode_exp = chap->status;
+
+    return size;
+}
+
+static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
+    u8 buf[4], *challenge = chap->c1;
+    int ret;
+
+    dev_dbg(ctrl->device, "%s: qid %d host response seq %d

transaction %d\n",
+        __func__, chap->qid, chap->s1, chap->transaction);

drivers/nvme/host/auth.c new file +89 -0
+
+    if (!chap->host_response) {
+        chap->host_response = nvme_auth_transform_key(ctrl->dhchap_key,
+                    ctrl->dhchap_key_len,
+                    ctrl->dhchap_key_hash,
+                    ctrl->opts->host->nqn);
+        if (IS_ERR(chap->host_response)) {
+            ret = PTR_ERR(chap->host_response);
+            chap->host_response = NULL;
+            return ret;
+        }
+    } else {
+        dev_dbg(ctrl->device, "%s: qid %d re-using host response\n",
+            __func__, chap->qid);
+    }
+
+    ret = crypto_shash_setkey(chap->shash_tfm,
+            chap->host_response, ctrl->dhchap_key_len);
+    if (ret) {
+        dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
+             chap->qid, ret);
+        goto out;
+    }
+
+    shash->tfm = chap->shash_tfm;
+    ret = crypto_shash_init(shash);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, challenge, chap->hash_len);
+    if (ret)
+        goto out;
+    put_unaligned_le32(chap->s1, buf);
+    ret = crypto_shash_update(shash, buf, 4);
+    if (ret)
+        goto out;
+    put_unaligned_le16(chap->transaction, buf);
+    ret = crypto_shash_update(shash, buf, 2);
+    if (ret)
+        goto out;
+    memset(buf, 0, sizeof(buf));
+    ret = crypto_shash_update(shash, buf, 1);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, "HostHost", 8);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, ctrl->opts->host->nqn,
+                  strlen(ctrl->opts->host->nqn));
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, buf, 1);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, ctrl->opts->subsysnqn,
+                strlen(ctrl->opts->subsysnqn));
+    if (ret)
+        goto out;
+    ret = crypto_shash_final(shash, chap->response);
+out:
+    if (challenge != chap->c1)
+        kfree(challenge);
+    return ret;
+}
+
+static int nvme_auth_dhchap_ctrl_response(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)
+{
+    SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
+    u8 *ctrl_response;
+    u8 buf[4], *challenge = chap->c2;
+    int ret;
+
+    ctrl_response = nvme_auth_transform_key(ctrl->dhchap_ctrl_key,
+                ctrl->dhchap_ctrl_key_len,
+                ctrl->dhchap_ctrl_key_hash,
+                ctrl->opts->subsysnqn);
+    if (IS_ERR(ctrl_response)) {
+        ret = PTR_ERR(ctrl_response);
+        return ret;
+    }
+    ret = crypto_shash_setkey(chap->shash_tfm,
+            ctrl_response, ctrl->dhchap_ctrl_key_len);
+    if (ret) {
+        dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
+             chap->qid, ret);
+        goto out;
+    }
+
+    dev_dbg(ctrl->device, "%s: qid %d host response seq %d

transaction %d\n",
+        __func__, chap->qid, chap->s2, chap->transaction); +    dev_dbg(ctrl->device, "%s: qid %d challenge %*ph\n", +        __func__, chap->qid, chap->hash_len, challenge); +    dev_dbg(ctrl->device, "%s: qid %d subsysnqn %s\n", +        __func__, chap->qid, ctrl->opts->subsysnqn);
+    dev_dbg(ctrl->device, "%s: qid %d hostnqn %s\n",
+        __func__, chap->qid, ctrl->opts->host->nqn);
+    shash->tfm = chap->shash_tfm;
+    ret = crypto_shash_init(shash);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, challenge, chap->hash_len); +    if (ret)
+        goto out;
+    put_unaligned_le32(chap->s2, buf);
+    ret = crypto_shash_update(shash, buf, 4);
+    if (ret)
+        goto out;
+    put_unaligned_le16(chap->transaction, buf);
+    ret = crypto_shash_update(shash, buf, 2);
+    if (ret)
+        goto out;
+    memset(buf, 0, 4);
+    ret = crypto_shash_update(shash, buf, 1);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, "Controller", 10); +    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, ctrl->opts->subsysnqn, +                  strlen(ctrl->opts->subsysnqn));
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, buf, 1);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, ctrl->opts->host->nqn, +                  strlen(ctrl->opts->host->nqn));
+    if (ret)
+        goto out;
+    ret = crypto_shash_final(shash, chap->response);

drivers/nvme/host/auth.c new file +58 -0
+out:
+    if (challenge != chap->c2)
+        kfree(challenge);
+    return ret;
+}
+
+int nvme_auth_generate_key(struct nvme_ctrl *ctrl)
+{
+    u8 *secret = ctrl->opts->dhchap_secret;
+    u8 *key;
+    size_t key_len;
+    u8 key_hash;
+
+    if (!secret)
+        return 0;
+
+    if (sscanf(secret, "DHHC-1:%hhd:%*s:", &key_hash) != 1)
+        return -EINVAL;
+
+    /* Pass in the secret without the 'DHHC-1:XX:' prefix */
+    key = nvme_auth_extract_secret(secret + 10, key_hash,
+                       &key_len);
+    if (IS_ERR(key)) {
+        dev_dbg(ctrl->device, "failed to extract key, error %ld\n",
+            PTR_ERR(key));
+        return PTR_ERR(key);
+    }
+
+    ctrl->dhchap_key = key;
+    key = NULL;
+    ctrl->dhchap_key_len = key_len;
+    ctrl->dhchap_key_hash = key_hash;
+
+    return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_auth_generate_key);
+
+int nvme_auth_generate_ctrl_key(struct nvme_ctrl *ctrl)
+{
+    u8 *secret = ctrl->opts->dhchap_ctrl_secret;
+    u8 *key;
+    size_t key_len;
+    u8 key_hash;
+
+    if (!secret)
+        return 0;
+
+    if (sscanf(secret, "DHHC-1:%hhd:%*s:", &key_hash) != 1)
+        return -EINVAL;
+
+    /* Pass in the secret without the 'DHHC-1:XX:' prefix */
+    key = nvme_auth_extract_secret(secret + 10, key_hash,
+                       &key_len);
+    if (IS_ERR(key))
+        return PTR_ERR(key);
+
+    ctrl->dhchap_ctrl_key = key;
+    key = NULL;
Quoted 9 lines

drivers/nvme/host/auth.c line 853

Quoted 5 lines

+    ctrl->dhchap_ctrl_key_len = key_len;
+    ctrl->dhchap_ctrl_key_hash = key_hash;
+    return 0;

drivers/nvme/host/auth.c new file +2 -0
+}
+EXPORT_SYMBOL_GPL(nvme_auth_generate_ctrl_key);

This and the other look identical just operate on
a different key, perhaps merge them into one?

Yeah; was too lazy here.
I could easily add a flag to differentiate between host and controller key.

Quoted 3 lines

Overall this looks sane to me.
Just nitpicking on the logging to use err when you hit a errors.

Will be fixing stuff up and send out a new version.

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke		           Kernel Storage Architect
[email protected]			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
maintainer
#19 lore raw

Re: [PATCH 07/12] nvme: Implement In-Band authentication

In reply to Hannes Reinecke

drivers/nvme/host/auth.c line 653

Quoted 3 lines
drivers/nvme/host/auth.c new file +2 -0
+static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)

Maybe better to call it nvme_auth_dhchap_setup_host_response()?

Quoted 63 lines
drivers/nvme/host/auth.c new file +63 -0
+{
+	SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
+	u8 buf[4], *challenge = chap->c1;
+	int ret;
+
+	dev_dbg(ctrl->device, "%s: qid %d host response seq %d transaction %d\n",
+		__func__, chap->qid, chap->s1, chap->transaction);
+
+	if (!chap->host_response) {
+		chap->host_response = nvme_auth_transform_key(ctrl->dhchap_key,
+					ctrl->dhchap_key_len,
+					ctrl->dhchap_key_hash,
+					ctrl->opts->host->nqn);
+		if (IS_ERR(chap->host_response)) {
+			ret = PTR_ERR(chap->host_response);
+			chap->host_response = NULL;
+			return ret;
+		}
+	} else {
+		dev_dbg(ctrl->device, "%s: qid %d re-using host response\n",
+			__func__, chap->qid);
+	}
+
+	ret = crypto_shash_setkey(chap->shash_tfm,
+			chap->host_response, ctrl->dhchap_key_len);
+	if (ret) {
+		dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
+			 chap->qid, ret);
+		goto out;
+	}
+
+	shash->tfm = chap->shash_tfm;
+	ret = crypto_shash_init(shash);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, challenge, chap->hash_len);
+	if (ret)
+		goto out;
+	put_unaligned_le32(chap->s1, buf);
+	ret = crypto_shash_update(shash, buf, 4);
+	if (ret)
+		goto out;
+	put_unaligned_le16(chap->transaction, buf);
+	ret = crypto_shash_update(shash, buf, 2);
+	if (ret)
+		goto out;
+	memset(buf, 0, sizeof(buf));
+	ret = crypto_shash_update(shash, buf, 1);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, "HostHost", 8);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, ctrl->opts->host->nqn,
+				  strlen(ctrl->opts->host->nqn));
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, buf, 1);
+	if (ret)
+		goto out;
+	ret = crypto_shash_update(shash, ctrl->opts->subsysnqn,
+			    strlen(ctrl->opts->subsysnqn));
+	if (ret)

drivers/nvme/host/auth.c line 726

Quoted 10 lines
drivers/nvme/host/auth.c new file +10 -0
+		goto out;
+	ret = crypto_shash_final(shash, chap->response);
+out:
+	if (challenge != chap->c1)
+		kfree(challenge);
+	return ret;
+}
+
+static int nvme_auth_dhchap_ctrl_response(struct nvme_ctrl *ctrl,
+		struct nvme_dhchap_queue_context *chap)

Maybe better to call it nvme_auth_dhchap_validate_ctrl_response()?

author maintainer
#20 lore raw

Re: [PATCH 07/12] nvme: Implement In-Band authentication

Quoted 6 lines · Sagi Grimberg
Quoted 3 lines

+static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl, +        struct nvme_dhchap_queue_context *chap)

Maybe better to call it nvme_auth_dhchap_setup_host_response()?

Ok.

Quoted 68 lines
Quoted 68 lines
drivers/nvme/host/auth.c new file +6 -0
+{
+    SHASH_DESC_ON_STACK(shash, chap->shash_tfm);
+    u8 buf[4], *challenge = chap->c1;
+    int ret;
+
+    dev_dbg(ctrl->device, "%s: qid %d host response seq %d

transaction %d\n",
+        __func__, chap->qid, chap->s1, chap->transaction);

drivers/nvme/host/auth.c new file +60 -0
+
+    if (!chap->host_response) {
+        chap->host_response = nvme_auth_transform_key(ctrl->dhchap_key,
+                    ctrl->dhchap_key_len,
+                    ctrl->dhchap_key_hash,
+                    ctrl->opts->host->nqn);
+        if (IS_ERR(chap->host_response)) {
+            ret = PTR_ERR(chap->host_response);
+            chap->host_response = NULL;
+            return ret;
+        }
+    } else {
+        dev_dbg(ctrl->device, "%s: qid %d re-using host response\n",
+            __func__, chap->qid);
+    }
+
+    ret = crypto_shash_setkey(chap->shash_tfm,
+            chap->host_response, ctrl->dhchap_key_len);
+    if (ret) {
+        dev_warn(ctrl->device, "qid %d: failed to set key, error %d\n",
+             chap->qid, ret);
+        goto out;
+    }
+
+    shash->tfm = chap->shash_tfm;
+    ret = crypto_shash_init(shash);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, challenge, chap->hash_len);
+    if (ret)
+        goto out;
+    put_unaligned_le32(chap->s1, buf);
+    ret = crypto_shash_update(shash, buf, 4);
+    if (ret)
+        goto out;
+    put_unaligned_le16(chap->transaction, buf);
+    ret = crypto_shash_update(shash, buf, 2);
+    if (ret)
+        goto out;
+    memset(buf, 0, sizeof(buf));
+    ret = crypto_shash_update(shash, buf, 1);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, "HostHost", 8);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, ctrl->opts->host->nqn,
+                  strlen(ctrl->opts->host->nqn));
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, buf, 1);
+    if (ret)
+        goto out;
+    ret = crypto_shash_update(shash, ctrl->opts->subsysnqn,
+                strlen(ctrl->opts->subsysnqn));
+    if (ret)
+        goto out;
+    ret = crypto_shash_final(shash, chap->response);
+out:
+    if (challenge != chap->c1)
Quoted 8 lines

drivers/nvme/host/auth.c line 726

Quoted 6 lines

+        kfree(challenge);
+    return ret;

drivers/nvme/host/auth.c new file +4 -0
+}
+
+static int nvme_auth_dhchap_ctrl_response(struct nvme_ctrl *ctrl,
+        struct nvme_dhchap_queue_context *chap)

Maybe better to call it nvme_auth_dhchap_validate_ctrl_response()?

Will be doing so for the next round.

Thanks for the review.

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke		           Kernel Storage Architect
[email protected]			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
author maintainer
#21 lore raw

PATCH v5 8/12 nvme-auth: Diffie-Hellman key exchange support

In reply to Hannes Reinecke

Implement Diffie-Hellman key exchange using FFDHE groups for NVMe In-Band Authentication.

---
 drivers/nvme/host/Kconfig |   1 +
 drivers/nvme/host/auth.c  | 412 +++++++++++++++++++++++++++++++++++++-
 drivers/nvme/host/auth.h  |   8 +
 3 files changed, 415 insertions(+), 6 deletions(-)
drivers/nvme/host/Kconfig +1 -0
index 49269c581ec4..0fab5684feca 100644
@@ -90,6 +90,7 @@ config NVME_AUTH
 	select CRYPTO_HMAC
 	select CRYPTO_SHA256
 	select CRYPTO_SHA512
+	select CRYPTO_FFDHE
 	help
 	  This provides support for NVMe over Fabrics In-Band Authentication.
 
drivers/nvme/host/auth.c +406 -6

504 lines not on this page · raw message

drivers/nvme/host/auth.h +8 -0
index 216957848398..b45bf565720a 100644
@@ -21,5 +21,13 @@ int nvme_auth_hmac_id(const char *hmac_name);
 unsigned char *nvme_auth_extract_secret(unsigned char *secret,
 					u8 key_hash, size_t *key_len);
 u8 *nvme_auth_transform_key(u8 *key, size_t key_len, u8 key_hash, char *nqn);
+int nvme_auth_augmented_challenge(u8 hmac_id, u8 *skey, size_t skey_len,
+				  u8 *challenge, u8 *aug, size_t hlen);
+int nvme_auth_gen_privkey(struct crypto_kpp *dh_tfm, int dh_gid);
+int nvme_auth_gen_pubkey(struct crypto_kpp *dh_tfm,
+			 u8 *host_key, size_t host_key_len);
+int nvme_auth_gen_shared_secret(struct crypto_kpp *dh_tfm,
+				u8 *ctrl_key, size_t ctrl_key_len,
+				u8 *sess_key, size_t sess_key_len);
 
 #endif /* _NVME_AUTH_H */
Signature · 1 line
2.29.2
author maintainer
#22 lore raw

PATCH v5 9/12 nvmet: Parse fabrics commands on all queues

In reply to Hannes Reinecke

Fabrics commands might be sent to all queues, not just the admin one.

---
 drivers/nvme/target/core.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/nvme/target/core.c +2 -0
index 5119c687de68..a3abbf50f7e0 100644
@@ -943,6 +943,8 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
 	if (unlikely(!req->sq->ctrl))
 		/* will return an error for any non-connect command: */
 		status = nvmet_parse_connect_cmd(req);
+	else if (nvme_is_fabrics(req->cmd))
+		status = nvmet_parse_fabrics_cmd(req);
 	else if (likely(req->sq->qid != 0))
 		status = nvmet_parse_io_cmd(req);
 	else
Signature · 1 line
2.29.2
Reviewed-by on v5 9/12
#23 lore raw

Re: [PATCH 09/12] nvmet: Parse fabrics commands on all queues

Quoted 14 lines · Hannes Reinecke

Fabrics commands might be sent to all queues, not just the admin one.

---
  drivers/nvme/target/core.c | 2 ++
  1 file changed, 2 insertions(+)
drivers/nvme/target/core.c +0 -0
index 5119c687de68..a3abbf50f7e0 100644

drivers/nvme/target/core.c bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq, · line 950

Quoted 8 lines
drivers/nvme/target/core.c +2 -0
@@ -943,6 +943,8 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
  	if (unlikely(!req->sq->ctrl))
  		/* will return an error for any non-connect command: */
  		status = nvmet_parse_connect_cmd(req);
+	else if (nvme_is_fabrics(req->cmd))
+		status = nvmet_parse_fabrics_cmd(req);
  	else if (likely(req->sq->qid != 0))
  		status = nvmet_parse_io_cmd(req);
  	else
Signature · 1 line
Himanshu Madhani                                Oracle Linux Engineering
author maintainer
#24 lore raw

PATCH v5 10/12 nvmet: Implement basic In-Band Authentication

In reply to Hannes Reinecke

Implement NVMe-oF In-Band authentication according to NVMe TPAR 8006. This patch adds three additional configfs entries 'dhchap_key', 'dhchap_ctrl_key', and 'dhchap_hash' to the 'host' configfs directory. The 'dhchap_key' and 'dhchap_ctrl_key' entries need to be in the ASCII format as specified in NVMe Base Specification v2.0 section 8.13.5.8 'Secret representation'.
'dhchap_hash' defaults to 'hmac(sha256)', and can be written to to switch to a different HMAC algorithm.

---
 drivers/nvme/host/auth.h               |   1 +
 drivers/nvme/target/Kconfig            |  11 +
 drivers/nvme/target/Makefile           |   1 +
 drivers/nvme/target/admin-cmd.c        |   4 +
 drivers/nvme/target/auth.c             | 399 ++++++++++++++++++++
 drivers/nvme/target/configfs.c         | 107 +++++-
 drivers/nvme/target/core.c             |   8 +
 drivers/nvme/target/fabrics-cmd-auth.c | 484 +++++++++++++++++++++++++
 drivers/nvme/target/fabrics-cmd.c      |  30 +-
 drivers/nvme/target/nvmet.h            |  68 ++++
 10 files changed, 1110 insertions(+), 3 deletions(-)
 create mode 100644 drivers/nvme/target/auth.c
 create mode 100644 drivers/nvme/target/fabrics-cmd-auth.c
drivers/nvme/host/auth.h +1 -0
index b45bf565720a..1b12fb740565 100644
@@ -16,6 +16,7 @@ int nvme_auth_dhgroup_id(const char *dhgroup_name);
 
 const char *nvme_auth_hmac_name(int hmac_id);
 const char *nvme_auth_digest_name(int hmac_id);
+int nvme_auth_hmac_hash_len(int hmac_id);
 int nvme_auth_hmac_id(const char *hmac_name);
 
 unsigned char *nvme_auth_extract_secret(unsigned char *secret,
drivers/nvme/target/Kconfig +11 -0
index 973561c93888..70f3c385fc9f 100644
@@ -83,3 +83,14 @@ config NVME_TARGET_TCP
 	  devices over TCP.
 
 	  If unsure, say N.
+
+config NVME_TARGET_AUTH
+	bool "NVMe over Fabrics In-band Authentication support"
+	depends on NVME_TARGET
+	select CRYPTO_HMAC
+	select CRYPTO_SHA256
+	select CRYPTO_SHA512
+	help
+	  This enables support for NVMe over Fabrics In-band Authentication
+
+	  If unsure, say N.
drivers/nvme/target/Makefile +1 -0
index 9837e580fa7e..c66820102493 100644
@@ -13,6 +13,7 @@ nvmet-y		+= core.o configfs.o admin-cmd.o fabrics-cmd.o \
 			discovery.o io-cmd-file.o io-cmd-bdev.o
 nvmet-$(CONFIG_NVME_TARGET_PASSTHRU)	+= passthru.o
 nvmet-$(CONFIG_BLK_DEV_ZONED)		+= zns.o
+nvmet-$(CONFIG_NVME_TARGET_AUTH)	+= fabrics-cmd-auth.o auth.o
 nvme-loop-y	+= loop.o
 nvmet-rdma-y	+= rdma.o
 nvmet-fc-y	+= fc.o
drivers/nvme/target/admin-cmd.c +4 -0
index 6fb24746de06..b7f1e06b3fbc 100644
@@ -1014,6 +1014,10 @@ u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
 
 	if (nvme_is_fabrics(cmd))
 		return nvmet_parse_fabrics_cmd(req);
+
+	if (unlikely(!nvmet_check_auth_status(req)))
+		return NVME_SC_AUTH_REQUIRED | NVME_SC_DNR;
+
 	if (nvmet_is_disc_subsys(nvmet_req_subsys(req)))
 		return nvmet_parse_discovery_cmd(req);
 
drivers/nvme/target/auth.c new file +399 -0

399 lines not on this page · raw message

drivers/nvme/target/configfs.c +106 -1

136 lines not on this page · raw message

drivers/nvme/target/core.c +8 -0
index a3abbf50f7e0..175dfb98bf38 100644
@@ -793,6 +793,7 @@ void nvmet_sq_destroy(struct nvmet_sq *sq)
 	wait_for_completion(&sq->confirm_done);
 	wait_for_completion(&sq->free_done);
 	percpu_ref_exit(&sq->ref);
+	nvmet_auth_sq_free(sq);
 
 	if (ctrl) {
 		/*
@@ -1271,6 +1272,11 @@ u16 nvmet_check_ctrl_status(struct nvmet_req *req)
 		       req->cmd->common.opcode, req->sq->qid);
 		return NVME_SC_CMD_SEQ_ERROR | NVME_SC_DNR;
 	}
+
+	if (unlikely(!nvmet_check_auth_status(req))) {
+		pr_warn("qid %d not authenticated\n", req->sq->qid);
+		return NVME_SC_AUTH_REQUIRED | NVME_SC_DNR;
+	}
 	return 0;
 }
 
@@ -1461,6 +1467,8 @@ static void nvmet_ctrl_free(struct kref *ref)
 	flush_work(&ctrl->async_event_work);
 	cancel_work_sync(&ctrl->fatal_err_work);
 
+	nvmet_destroy_auth(ctrl);
+
 	ida_simple_remove(&cntlid_ida, ctrl->cntlid);
 
 	nvmet_async_events_free(ctrl);
drivers/nvme/target/fabrics-cmd-auth.c new file +484 -0

484 lines not on this page · raw message

drivers/nvme/target/fabrics-cmd.c +28 -2
index 70fb587e9413..641b4e2cd8c8 100644
@@ -93,6 +93,14 @@ u16 nvmet_parse_fabrics_cmd(struct nvmet_req *req)
 	case nvme_fabrics_type_property_get:
 		req->execute = nvmet_execute_prop_get;
 		break;
+#ifdef CONFIG_NVME_TARGET_AUTH
+	case nvme_fabrics_type_auth_send:
+		req->execute = nvmet_execute_auth_send;
+		break;
+	case nvme_fabrics_type_auth_receive:
+		req->execute = nvmet_execute_auth_receive;
+		break;
+#endif
 	default:
 		pr_debug("received unknown capsule type 0x%x\n",
 			cmd->fabrics.fctype);
@@ -173,6 +181,7 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
 	struct nvmf_connect_data *d;
 	struct nvmet_ctrl *ctrl = NULL;
 	u16 status = 0;
+	int ret;
 
 	if (!nvmet_check_transfer_len(req, sizeof(struct nvmf_connect_data)))
 		return;
@@ -215,18 +224,32 @@ static void nvmet_execute_admin_connect(struct nvmet_req *req)
 
 	uuid_copy(&ctrl->hostid, &d->hostid);
 
+	ret = nvmet_setup_auth(ctrl);
+	if (ret < 0) {
+		pr_err("Failed to setup authentication, error %d\n", ret);
+		nvmet_ctrl_put(ctrl);
+		if (ret == -EPERM)
+			status = (NVME_SC_CONNECT_INVALID_HOST | NVME_SC_DNR);
+		else
+			status = NVME_SC_INTERNAL;
+		goto out;
+	}
+
 	status = nvmet_install_queue(ctrl, req);
 	if (status) {
 		nvmet_ctrl_put(ctrl);
 		goto out;
 	}
 
-	pr_info("creating %s controller %d for subsystem %s for NQN %s%s.\n",
+	pr_info("creating %s controller %d for subsystem %s for NQN %s%s%s.\n",
 		nvmet_is_disc_subsys(ctrl->subsys) ? "discovery" : "nvm",
 		ctrl->cntlid, ctrl->subsys->subsysnqn, ctrl->hostnqn,
-		ctrl->pi_support ? " T10-PI is enabled" : "");
+		ctrl->pi_support ? " T10-PI is enabled" : "",
+		nvmet_has_auth(ctrl) ? " with DH-HMAC-CHAP" : "");
 	req->cqe->result.u16 = cpu_to_le16(ctrl->cntlid);
 
+	if (nvmet_has_auth(ctrl))
+		nvmet_init_auth(ctrl, req);
 out:
 	kfree(d);
 complete:
@@ -286,6 +309,9 @@ static void nvmet_execute_io_connect(struct nvmet_req *req)
 	req->cqe->result.u16 = cpu_to_le16(ctrl->cntlid);
 
 	pr_debug("adding queue %d to ctrl %d.\n", qid, ctrl->cntlid);
+	req->cqe->result.u16 = cpu_to_le16(ctrl->cntlid);
+	if (nvmet_has_auth(ctrl))
+		nvmet_init_auth(ctrl, req);
 
 out:
 	kfree(d);
drivers/nvme/target/nvmet.h +68 -0

90 lines not on this page · raw message

Signature · 1 line
2.29.2
#25 lore raw

Re: [PATCH 10/12] nvmet: Implement basic In-Band Authentication

I love your patch! Yet something to improve:

Hi Hannes,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.16-rc1 next-20211118]
[cannot apply to herbert-cryptodev-2.6/master herbert-crypto-2.6/master linux-nvme/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Hannes-Reinecke/nvme-In-band-authentication-support/20211112-210112
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5833291ab6de9c3e2374336b51c814e515e8f3a5
config: arm64-buildonly-randconfig-r006-20211119 (attached as .config)
compiler: aarch64-linux-gcc (GCC) 11.2.0

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/e5bfdfa04f93ef1857a48ce68e035aab7fe8b066
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Hannes-Reinecke/nvme-In-band-authentication-support/20211112-210112 git checkout e5bfdfa04f93ef1857a48ce68e035aab7fe8b066
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

>> aarch64-linux-ld: Unexpected GOT/PLT entries detected!
>> aarch64-linux-ld: Unexpected run-time procedure linkages detected!
   aarch64-linux-ld: drivers/nvme/target/configfs.o: in function `nvmet_host_dhchap_hash_store':
>> configfs.c:(.text+0x24): undefined reference to `nvme_auth_hmac_id'
>> aarch64-linux-ld: configfs.c:(.text+0x44): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/configfs.o: in function `nvmet_host_dhchap_hash_show':
>> configfs.c:(.text+0xcc): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/fabrics-cmd-auth.o: in function `nvmet_auth_negotiate':
>> fabrics-cmd-auth.c:(.text+0x340): undefined reference to `nvme_auth_dhgroup_name'
   aarch64-linux-ld: drivers/nvme/target/fabrics-cmd-auth.o: in function `nvmet_auth_challenge':
>> fabrics-cmd-auth.c:(.text+0x76c): undefined reference to `nvme_auth_hmac_hash_len'
   aarch64-linux-ld: drivers/nvme/target/fabrics-cmd-auth.o: in function `nvmet_execute_auth_receive':
   fabrics-cmd-auth.c:(.text+0x1300): undefined reference to `nvme_auth_hmac_hash_len'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_set_host_key':
>> auth.c:(.text+0x9c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_set_ctrl_key':
   auth.c:(.text+0x1dc): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_setup_auth':
   auth.c:(.text+0x494): undefined reference to `nvme_auth_hmac_name'
>> aarch64-linux-ld: auth.c:(.text+0x4ec): undefined reference to `nvme_auth_extract_secret'
>> aarch64-linux-ld: auth.c:(.text+0x598): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: auth.c:(.text+0x614): undefined reference to `nvme_auth_extract_secret'
   aarch64-linux-ld: auth.c:(.text+0x6ac): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_host_hash':
   auth.c:(.text+0x88c): undefined reference to `nvme_auth_hmac_name'
>> aarch64-linux-ld: auth.c:(.text+0x984): undefined reference to `nvme_auth_transform_key'

aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_ctrl_hash':
auth.c:(.text+0xcec): undefined reference to `nvme_auth_hmac_name'
aarch64-linux-ld: auth.c:(.text+0xde4): undefined reference to `nvme_auth_transform_key'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

author maintainer
#26 lore raw

PATCH v5 11/12 nvmet-auth: Diffie-Hellman key exchange support

In reply to Hannes Reinecke

Implement Diffie-Hellman key exchange using FFDHE groups for NVMe In-Band Authentication.
This patch adds a new host configfs attribute 'dhchap_dhgroup' to select the FFDHE group to use.

---
 drivers/nvme/target/Kconfig            |   1 +
 drivers/nvme/target/auth.c             | 152 ++++++++++++++++++++++++-
 drivers/nvme/target/configfs.c         |  31 +++++
 drivers/nvme/target/fabrics-cmd-auth.c |  19 +++-
 drivers/nvme/target/nvmet.h            |   8 ++
 5 files changed, 203 insertions(+), 8 deletions(-)
drivers/nvme/target/Kconfig +1 -0
index 70f3c385fc9f..2e41d70fd881 100644
@@ -90,6 +90,7 @@ config NVME_TARGET_AUTH
 	select CRYPTO_HMAC
 	select CRYPTO_SHA256
 	select CRYPTO_SHA512
+	select CRYPTO_FFDHE
 	help
 	  This enables support for NVMe over Fabrics In-band Authentication
 
drivers/nvme/target/auth.c +148 -4

185 lines not on this page · raw message

drivers/nvme/target/configfs.c +31 -0
index 38bafbc69714..1e272d0760ce 100644
@@ -1784,10 +1784,41 @@ static ssize_t nvmet_host_dhchap_hash_store(struct config_item *item,
 
 CONFIGFS_ATTR(nvmet_host_, dhchap_hash);
 
+static ssize_t nvmet_host_dhchap_dhgroup_show(struct config_item *item,
+		char *page)
+{
+	struct nvmet_host *host = to_host(item);
+	const char *dhgroup = nvme_auth_dhgroup_name(host->dhchap_dhgroup_id);
+
+	return sprintf(page, "%s\n", dhgroup ? dhgroup : "none");
+}
+
+static ssize_t nvmet_host_dhchap_dhgroup_store(struct config_item *item,
+		const char *page, size_t count)
+{
+	struct nvmet_host *host = to_host(item);
+	int dhgroup_id;
+
+	dhgroup_id = nvme_auth_dhgroup_id(page);
+	if (dhgroup_id < 0)
+		return -EINVAL;
+	if (dhgroup_id != NVME_AUTH_DHCHAP_DHGROUP_NULL) {
+		const char *kpp = nvme_auth_dhgroup_kpp(dhgroup_id);
+
+		if (!crypto_has_kpp(kpp, 0, 0))
+			return -EINVAL;
+	}
+	host->dhchap_dhgroup_id = dhgroup_id;
+	return count;
+}
+
+CONFIGFS_ATTR(nvmet_host_, dhchap_dhgroup);
+
 static struct configfs_attribute *nvmet_host_attrs[] = {
 	&nvmet_host_attr_dhchap_key,
 	&nvmet_host_attr_dhchap_ctrl_key,
 	&nvmet_host_attr_dhchap_hash,
+	&nvmet_host_attr_dhchap_dhgroup,
 	NULL,
 };
 #endif /* CONFIG_NVME_TARGET_AUTH */
drivers/nvme/target/fabrics-cmd-auth.c +15 -4
index b5f46cdb97fe..51955fbc6c55 100644
@@ -61,7 +61,7 @@ static u16 nvmet_auth_negotiate(struct nvmet_req *req, void *d)
 		     data->auth_protocol[0].dhchap.dhlen; i++) {
 		int tmp_dhgid = data->auth_protocol[0].dhchap.idlist[i];
 
-		if (tmp_dhgid == NVME_AUTH_DHCHAP_DHGROUP_NULL) {
+		if (tmp_dhgid != ctrl->dh_gid) {
 			dhgid = tmp_dhgid;
 			break;
 		}
@@ -71,7 +71,6 @@ static u16 nvmet_auth_negotiate(struct nvmet_req *req, void *d)
 			 __func__, ctrl->cntlid, req->sq->qid);
 		return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
 	}
-	ctrl->dh_gid = dhgid;
 	pr_debug("%s: ctrl %d qid %d: selected DH group %s (%d)\n",
 		 __func__, ctrl->cntlid, req->sq->qid,
 		 nvme_auth_dhgroup_name(ctrl->dh_gid), ctrl->dh_gid);
@@ -90,7 +89,11 @@ static u16 nvmet_auth_reply(struct nvmet_req *req, void *d)
 		 data->hl, data->cvalid, dhvlen);
 
 	if (dhvlen) {
-		return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		if (!ctrl->dh_tfm)
+			return NVME_AUTH_DHCHAP_FAILURE_INCORRECT_PAYLOAD;
+		if (nvmet_auth_ctrl_sesskey(req, data->rval + 2 * data->hl,
+					    dhvlen) < 0)
+			return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;
 	}
 
 	response = kmalloc(data->hl, GFP_KERNEL);
@@ -318,6 +321,8 @@ static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
 	int hash_len = nvme_auth_hmac_hash_len(ctrl->shash_id);
 	int data_size = sizeof(*d) + hash_len;
 
+	if (ctrl->dh_tfm)
+		data_size += ctrl->dh_keysize;
 	if (al < data_size) {
 		pr_debug("%s: buffer too small (al %d need %d)\n", __func__,
 			 al, data_size);
@@ -336,9 +341,15 @@ static int nvmet_auth_challenge(struct nvmet_req *req, void *d, int al)
 		return -ENOMEM;
 	get_random_bytes(req->sq->dhchap_c1, data->hl);
 	memcpy(data->cval, req->sq->dhchap_c1, data->hl);
+	if (ctrl->dh_tfm) {
+		data->dhgid = ctrl->dh_gid;
+		data->dhvlen = cpu_to_le32(ctrl->dh_keysize);
+		ret = nvmet_auth_ctrl_exponential(req, data->cval + data->hl,
+						  ctrl->dh_keysize);
+	}
 	pr_debug("%s: ctrl %d qid %d seq %d transaction %d hl %d dhvlen %d\n",
 		 __func__, ctrl->cntlid, req->sq->qid, req->sq->dhchap_s1,
-		 req->sq->dhchap_tid, data->hl, 0);
+		 req->sq->dhchap_tid, data->hl, ctrl->dh_keysize);
 	return ret;
 }
 
drivers/nvme/target/nvmet.h +8 -0
index ef1e7f7649c7..e2864310a048 100644
@@ -230,7 +230,10 @@ struct nvmet_ctrl {
 	size_t			dhchap_ctrl_key_len;
 	u8			dhchap_ctrl_key_hash;
 	u8			shash_id;
+	struct crypto_kpp	*dh_tfm;
 	u32			dh_gid;
+	u8			*dh_key;
+	u32			dh_keysize;
 #endif
 };
 
@@ -705,6 +708,7 @@ int nvmet_setup_auth(struct nvmet_ctrl *ctrl);
 void nvmet_init_auth(struct nvmet_ctrl *ctrl, struct nvmet_req *req);
 void nvmet_destroy_auth(struct nvmet_ctrl *ctrl);
 void nvmet_auth_sq_free(struct nvmet_sq *sq);
+int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, int dhgroup_id);
 bool nvmet_check_auth_status(struct nvmet_req *req);
 int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,
 			 unsigned int hash_len);
@@ -714,6 +718,10 @@ static inline bool nvmet_has_auth(struct nvmet_ctrl *ctrl)
 {
 	return ctrl->dhchap_key != NULL;
 }
+int nvmet_auth_ctrl_exponential(struct nvmet_req *req,
+				u8 *buf, int buf_size);
+int nvmet_auth_ctrl_sesskey(struct nvmet_req *req,
+			    u8 *buf, int buf_size);
 #else
 static inline int nvmet_setup_auth(struct nvmet_ctrl *ctrl)
 {
Signature · 1 line
2.29.2
#27 lore raw

Re: [PATCH 11/12] nvmet-auth: Diffie-Hellman key exchange support

I love your patch! Yet something to improve:

Hi Hannes,

I love your patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.16-rc1 next-20211118]
[cannot apply to herbert-cryptodev-2.6/master herbert-crypto-2.6/master linux-nvme/for-next] [If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Hannes-Reinecke/nvme-In-band-authentication-support/20211112-210112
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 5833291ab6de9c3e2374336b51c814e515e8f3a5
config: arm64-buildonly-randconfig-r006-20211119 (attached as .config)
compiler: aarch64-linux-gcc (GCC) 11.2.0

reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# https://github.com/0day-ci/linux/commit/745a999743a81a5cc9e23b5d558ab6d2976561c8
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Hannes-Reinecke/nvme-In-band-authentication-support/20211112-210112 git checkout 745a999743a81a5cc9e23b5d558ab6d2976561c8
# save the attached .config to linux build tree
mkdir build_dir
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arm64 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate

All errors (new ones prefixed by >>):

aarch64-linux-ld: Unexpected GOT/PLT entries detected!
aarch64-linux-ld: Unexpected run-time procedure linkages detected!
aarch64-linux-ld: drivers/nvme/target/configfs.o: in function `nvmet_host_dhchap_dhgroup_store':

>> configfs.c:(.text+0x24): undefined reference to `nvme_auth_dhgroup_id'
>> aarch64-linux-ld: configfs.c:(.text+0x6c): undefined reference to `nvme_auth_dhgroup_kpp'
   aarch64-linux-ld: drivers/nvme/target/configfs.o: in function `nvmet_host_dhchap_dhgroup_show':
>> configfs.c:(.text+0xdc): undefined reference to `nvme_auth_dhgroup_name'
   aarch64-linux-ld: drivers/nvme/target/configfs.o: in function `nvmet_host_dhchap_hash_show':
   configfs.c:(.text+0x94c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/configfs.o: in function `nvmet_host_dhchap_hash_store':
   configfs.c:(.text+0x9c4): undefined reference to `nvme_auth_hmac_id'
   aarch64-linux-ld: configfs.c:(.text+0x9e4): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/fabrics-cmd-auth.o: in function `nvmet_auth_negotiate':
   fabrics-cmd-auth.c:(.text+0x340): undefined reference to `nvme_auth_dhgroup_name'
   aarch64-linux-ld: drivers/nvme/target/fabrics-cmd-auth.o: in function `nvmet_auth_challenge':
   fabrics-cmd-auth.c:(.text+0x790): undefined reference to `nvme_auth_hmac_hash_len'
   aarch64-linux-ld: drivers/nvme/target/fabrics-cmd-auth.o: in function `nvmet_execute_auth_receive':
   fabrics-cmd-auth.c:(.text+0x1380): undefined reference to `nvme_auth_hmac_hash_len'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_set_host_key':
   auth.c:(.text+0x9c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_set_ctrl_key':
   auth.c:(.text+0x1dc): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_setup_dhgroup':
>> auth.c:(.text+0x37c): undefined reference to `nvme_auth_dhgroup_kpp'
>> aarch64-linux-ld: auth.c:(.text+0x460): undefined reference to `nvme_auth_dhgroup_pubkey_size'
>> aarch64-linux-ld: auth.c:(.text+0x4ac): undefined reference to `nvme_auth_gen_privkey'
>> aarch64-linux-ld: auth.c:(.text+0x530): undefined reference to `nvme_auth_gen_pubkey'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_setup_auth':
   auth.c:(.text+0x81c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: auth.c:(.text+0x874): undefined reference to `nvme_auth_extract_secret'
   aarch64-linux-ld: auth.c:(.text+0x920): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: auth.c:(.text+0x9a4): undefined reference to `nvme_auth_extract_secret'
   aarch64-linux-ld: auth.c:(.text+0xa3c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_host_hash':
   auth.c:(.text+0xc5c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: auth.c:(.text+0xd54): undefined reference to `nvme_auth_transform_key'
>> aarch64-linux-ld: auth.c:(.text+0xdf8): undefined reference to `nvme_auth_augmented_challenge'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_ctrl_hash':
   auth.c:(.text+0x111c): undefined reference to `nvme_auth_hmac_name'
   aarch64-linux-ld: auth.c:(.text+0x1214): undefined reference to `nvme_auth_transform_key'
   aarch64-linux-ld: auth.c:(.text+0x12b8): undefined reference to `nvme_auth_augmented_challenge'
   aarch64-linux-ld: drivers/nvme/target/auth.o: in function `nvmet_auth_ctrl_sesskey':
>> auth.c:(.text+0x16e4): undefined reference to `nvme_auth_dhgroup_privkey_size'
>> aarch64-linux-ld: auth.c:(.text+0x1724): undefined reference to `nvme_auth_gen_shared_secret'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

author maintainer
#28 lore raw

PATCH v5 12/12 nvmet-auth: expire authentication sessions

In reply to Hannes Reinecke

Each authentication step is required to be completed within the KATO interval (or two minutes if not set). So add a workqueue function to reset the transaction ID and the expected next protocol step; this will automatically the next authentication command referring to the terminated authentication.

---
 drivers/nvme/target/auth.c             |  1 +
 drivers/nvme/target/fabrics-cmd-auth.c | 20 +++++++++++++++++++-
 drivers/nvme/target/nvmet.h            |  1 +
 3 files changed, 21 insertions(+), 1 deletion(-)
drivers/nvme/target/auth.c +1 -0
index 7486077ca33e..58f11ccaecee 100644
@@ -237,6 +237,7 @@ int nvmet_setup_auth(struct nvmet_ctrl *ctrl)
 
 void nvmet_auth_sq_free(struct nvmet_sq *sq)
 {
+	cancel_delayed_work(&sq->auth_expired_work);
 	kfree(sq->dhchap_c1);
 	sq->dhchap_c1 = NULL;
 	kfree(sq->dhchap_c2);
drivers/nvme/target/fabrics-cmd-auth.c +19 -1
index 51955fbc6c55..2beaacedf2b6 100644
@@ -12,9 +12,22 @@
 #include "nvmet.h"
 #include "../host/auth.h"
 
+static void nvmet_auth_expired_work(struct work_struct *work)
+{
+	struct nvmet_sq *sq = container_of(to_delayed_work(work),
+			struct nvmet_sq, auth_expired_work);
+
+	pr_debug("%s: ctrl %d qid %d transaction %u expired, resetting\n",
+		 __func__, sq->ctrl->cntlid, sq->qid, sq->dhchap_tid);
+	sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
+	sq->dhchap_tid = -1;
+}
+
 void nvmet_init_auth(struct nvmet_ctrl *ctrl, struct nvmet_req *req)
 {
 	/* Initialize in-band authentication */
+	INIT_DELAYED_WORK(&req->sq->auth_expired_work,
+			  nvmet_auth_expired_work);
 	req->sq->authenticated = false;
 	req->sq->dhchap_step = NVME_AUTH_DHCHAP_MESSAGE_NEGOTIATE;
 	req->cqe->result.u32 |= 0x2 << 16;
@@ -305,8 +318,13 @@ void nvmet_execute_auth_send(struct nvmet_req *req)
 	req->cqe->result.u64 = 0;
 	nvmet_req_complete(req, status);
 	if (req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_SUCCESS2 &&
-	    req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
+	    req->sq->dhchap_step != NVME_AUTH_DHCHAP_MESSAGE_FAILURE2) {
+		unsigned long auth_expire_secs = ctrl->kato ? ctrl->kato : 120;
+
+		mod_delayed_work(system_wq, &req->sq->auth_expired_work,
+				 auth_expire_secs * HZ);
 		return;
+	}
 	/* Final states, clear up variables */
 	nvmet_auth_sq_free(req->sq);
 	if (req->sq->dhchap_step == NVME_AUTH_DHCHAP_MESSAGE_FAILURE2)
drivers/nvme/target/nvmet.h +1 -0
index e2864310a048..e13dad05f387 100644
@@ -109,6 +109,7 @@ struct nvmet_sq {
 	u32			sqhd;
 	bool			sqhd_disabled;
 #ifdef CONFIG_NVME_TARGET_AUTH
+	struct delayed_work	auth_expired_work;
 	bool			authenticated;
 	u16			dhchap_tid;
 	u16			dhchap_status;
Signature · 1 line
2.29.2
maintainer
#29 lore raw
In reply to Hannes Reinecke
Quoted 17 lines · Hannes Reinecke

Hi all,

recent updates to the NVMe spec have added definitions for in-band authentication, and seeing that it provides some real benefit especially for NVMe-TCP here's an attempt to implement it.

Tricky bit here is that the specification orients itself on TLS 1.3, but supports only the FFDHE groups. Which of course the kernel doesn't support. I've been able to come up with a patch for this, but as this is my first attempt to fix anything in the crypto area I would invite people more familiar with these matters to have a look.

Also note that this is just for in-band authentication. Secure concatenation (ie starting TLS with the negotiated parameters) is not implemented; one would need to update the kernel TLS implementation for this, which at this time is beyond scope.

Quoted 4 lines

As usual, comments and reviews are welcome.

Changes to v4:
- Validate against blktest suite

Nice! thanks hannes, this is going to be very useful moving forward.

Quoted 1 line

- Fixup base64 decoding

What was fixed up there?

Quoted 1 line

- Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps point me to the exact patch that fixes this?

author maintainer
#30 lore raw
Quoted 20 lines · Sagi Grimberg
Quoted 17 lines · Hannes Reinecke

Hi all,

recent updates to the NVMe spec have added definitions for in-band authentication, and seeing that it provides some real benefit especially for NVMe-TCP here's an attempt to implement it.

Tricky bit here is that the specification orients itself on TLS 1.3, but supports only the FFDHE groups. Which of course the kernel doesn't support. I've been able to come up with a patch for this, but as this is my first attempt to fix anything in the crypto area I would invite people more familiar with these matters to have a look.

Also note that this is just for in-band authentication. Secure concatenation (ie starting TLS with the negotiated parameters) is not implemented; one would need to update the kernel TLS implementation for this, which at this time is beyond scope.

Quoted 8 lines
Quoted 4 lines

As usual, comments and reviews are welcome.

Changes to v4:
- Validate against blktest suite

Nice! thanks hannes, this is going to be very useful moving forward.

Oh, definitely. The number of issue these tests found...

Quoted 4 lines
Quoted 1 line

- Fixup base64 decoding

What was fixed up there?

The padding character '=' wasn't handled correctly on decoding (the character itself was skipped, by the 'bits' value wasn't increased, leading to a spurious error in decoding an any key longer than 32 bit not being accepted.

Quoted 4 lines
Quoted 1 line

- Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps point me to the exact patch that fixes this?

Well, no, not really; the patch itself got squashed in the main patches.
But problem here was that the key transformation from section 8.13.5.7 had been using the hash algorithm from the initial challenge, not the one specified in the key itself. This lead to decoding errors when using a key with a different length than the hash algorithm.

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke                Kernel Storage Architect
[email protected]                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
maintainer
#31 lore raw
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines

Changes to v4:
- Validate against blktest suite

Nice! thanks hannes, this is going to be very useful moving forward.

Oh, definitely. The number of issue these tests found...

Great, good that this was useful for you.

Quoted 5 lines
Quoted 4 lines
Quoted 1 line

- Fixup base64 decoding

What was fixed up there?

The padding character '=' wasn't handled correctly on decoding (the character itself was skipped, by the 'bits' value wasn't increased, leading to a spurious error in decoding an any key longer than 32 bit not being accepted.

I see.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

- Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps point me to the exact patch that fixes this?

Well, no, not really; the patch itself got squashed in the main patches.
But problem here was that the key transformation from section 8.13.5.7 had been using the hash algorithm from the initial challenge, not the one specified in the key itself. This lead to decoding errors when using a key with a different length than the hash algorithm.

That is exactly what I reported, changing the key length leads to authentication errors.

author maintainer
#32 lore raw
Quoted 34 lines · Sagi Grimberg
Quoted 8 lines
Quoted 7 lines
Quoted 3 lines

Changes to v4:
- Validate against blktest suite

Nice! thanks hannes, this is going to be very useful moving forward.

Oh, definitely. The number of issue these tests found...

Great, good that this was useful for you.

Quoted 8 lines
Quoted 4 lines
Quoted 1 line

- Fixup base64 decoding

What was fixed up there?

The padding character '=' wasn't handled correctly on decoding (the character itself was skipped, by the 'bits' value wasn't increased, leading to a spurious error in decoding an any key longer than 32 bit not being accepted.

I see.

Quoted 11 lines
Quoted 4 lines
Quoted 1 line

- Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps point me to the exact patch that fixes this?

Well, no, not really; the patch itself got squashed in the main patches. But problem here was that the key transformation from section 8.13.5.7 had been using the hash algorithm from the initial challenge, not the one specified in the key itself.
This lead to decoding errors when using a key with a different length than the hash algorithm.

Quoted 2 lines

That is exactly what I reported, changing the key length leads to authentication errors.

Right-o. So it should be sorted then.

BTW, I've created a pull request for nvme-cli
(https://github.com/linux-nvme/nvme-cli/pull/1237)
to add a new command-line option 'dump-config'; can you check if that's what you had in mind or whether it needs to be improved further?

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke		           Kernel Storage Architect
[email protected]			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
maintainer
#33 lore raw
Quoted 5 lines

BTW, I've created a pull request for nvme-cli
(https://github.com/linux-nvme/nvme-cli/pull/1237)
to add a new command-line option 'dump-config'; can you check if that's what you had in mind or whether it needs to be improved further?

The dump is nice, thanks. I gave a couple of comments on the PR. I do suspect that people will want to populate this file outside of dump-config, hence we need a markdown documentation for it or in this case a json schema...

maintainer
#34 lore raw
In reply to Hannes Reinecke
Quoted 13 lines
Quoted 13 lines
Quoted 12 lines
Quoted 5 lines
Quoted 2 lines

- Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps point me to the exact patch that fixes this?

Well, no, not really; the patch itself got squashed in the main patches. But problem here was that the key transformation from section 8.13.5.7 had been using the hash algorithm from the initial challenge, not the one specified in the key itself.
This lead to decoding errors when using a key with a different length than the hash algorithm.

Quoted 4 lines
Quoted 2 lines

That is exactly what I reported, changing the key length leads to authentication errors.

Right-o. So it should be sorted then.

Hannes, was the issue on the host side or the controller side?

I'm a little lost into what was the actual fix...

author maintainer
#35 lore raw
Quoted 14 lines · Sagi Grimberg
Quoted 14 lines
Quoted 14 lines
Quoted 13 lines
Quoted 5 lines
Quoted 2 lines

- Transform secret with correct hmac algorithm

Is that what I reported last time? Can you perhaps point me to the exact patch that fixes this?

Well, no, not really; the patch itself got squashed in the main patches.
But problem here was that the key transformation from section 8.13.5.7 had been using the hash algorithm from the initial challenge, not the one specified in the key itself.
This lead to decoding errors when using a key with a different length than the hash algorithm.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

That is exactly what I reported, changing the key length leads to authentication errors.

Right-o. So it should be sorted then.

Hannes, was the issue on the host side or the controller side?

The issue was actually on the host side.

Quoted 1 line

I'm a little lost into what was the actual fix...

The basic fix was this:

@@ -927,13 +944,17 @@ static int nvme_auth_dhchap_host_response(struct nvme_ctrl
*ctrl,

        if (!chap->host_response) {
                chap->host_response =
nvme_auth_transform_key(ctrl->dhchap_key,
-                                       ctrl->dhchap_key_len, chap->hash_id,
+                                       ctrl->dhchap_key_len,
+                                       ctrl->dhchap_key_hash,
                                        ctrl->opts->host->nqn);
                if (IS_ERR(chap->host_response)) {
                        ret = PTR_ERR(chap->host_response);
                        chap->host_response = NULL;
                        return ret;
                }

(minus the linebreaks, of course).
'chap->hash_id' is the hash selected by the initial negotiation, which is wrong as we should have used the hash function selected by the key itself.

Cheers,

Hannes

Signature · 4 lines
Dr. Hannes Reinecke		           Kernel Storage Architect
[email protected]			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
maintainer
#36 lore raw
Quoted 27 lines
Quoted 3 lines

Hannes, was the issue on the host side or the controller side?

The issue was actually on the host side.

Quoted 1 line

I'm a little lost into what was the actual fix...

The basic fix was this:

(quoted diff) +0 -0
@@ -927,13 +944,17 @@ static int nvme_auth_dhchap_host_response(struct

nvme_ctrl
*ctrl,

         if (!chap->host_response) {
                 chap->host_response =

nvme_auth_transform_key(ctrl->dhchap_key,

(quoted diff) +2 -1
-                                       ctrl->dhchap_key_len, chap->hash_id,
+                                       ctrl->dhchap_key_len,
+                                       ctrl->dhchap_key_hash,
                                         ctrl->opts->host->nqn);
                 if (IS_ERR(chap->host_response)) {
                         ret = PTR_ERR(chap->host_response);
                         chap->host_response = NULL;
                         return ret;
                 }
Quoted 4 lines

(minus the linebreaks, of course).
'chap->hash_id' is the hash selected by the initial negotiation, which is wrong as we should have used the hash function selected by the key itself.

Makes sense. thanks.