mbox series

[RFC,00/11] nvme: In-band authentication support

Message ID 20210716110428.9727-1-hare@suse.de
Headers show
Series nvme: In-band authentication support | expand

Message

Hannes Reinecke July 16, 2021, 11:04 a.m. UTC
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.

Hannes Reinecke (11):
  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: Implement In-Band authentication
  nvme-auth: augmented challenge support
  nvmet: Parse fabrics commands on all queues
  nvmet: Implement basic In-Band Authentication
  nvmet-auth: implement support for augmented challenge
  nvme: add non-standard ECDH and curve25517 algorithms

 crypto/Kconfig                         |    8 +
 crypto/Makefile                        |    1 +
 crypto/ffdhe_helper.c                  |  877 +++++++++++++++++
 crypto/kpp.c                           |    6 +
 crypto/shash.c                         |    6 +
 drivers/nvme/host/Kconfig              |   11 +
 drivers/nvme/host/Makefile             |    1 +
 drivers/nvme/host/auth.c               | 1188 ++++++++++++++++++++++++
 drivers/nvme/host/auth.h               |   23 +
 drivers/nvme/host/core.c               |   77 +-
 drivers/nvme/host/fabrics.c            |   65 +-
 drivers/nvme/host/fabrics.h            |    8 +
 drivers/nvme/host/nvme.h               |   15 +
 drivers/nvme/host/trace.c              |   32 +
 drivers/nvme/target/Kconfig            |   10 +
 drivers/nvme/target/Makefile           |    1 +
 drivers/nvme/target/admin-cmd.c        |    4 +
 drivers/nvme/target/auth.c             |  608 ++++++++++++
 drivers/nvme/target/configfs.c         |  102 +-
 drivers/nvme/target/core.c             |   10 +
 drivers/nvme/target/fabrics-cmd-auth.c |  472 ++++++++++
 drivers/nvme/target/fabrics-cmd.c      |   30 +-
 drivers/nvme/target/nvmet.h            |   71 ++
 include/crypto/ffdhe.h                 |   24 +
 include/crypto/hash.h                  |    2 +
 include/crypto/kpp.h                   |    2 +
 include/linux/base64.h                 |   16 +
 include/linux/nvme.h                   |  187 +++-
 lib/Makefile                           |    2 +-
 lib/base64.c                           |  111 +++
 30 files changed, 3961 insertions(+), 9 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

Comments

Sagi Grimberg July 17, 2021, 6:06 a.m. UTC | #1
> Hi all,


Hey Hannes, nice progress. This is definitely
a step in the right direction.

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


Please call out the TP 8006 specifically so people can look
into 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.


Glad to see this turned out to be very simple!

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


TLS is an additional effort, as discussed, inband auth alone
has merits and we should not lock it down to NVMe/TCP-TLS.

> As usual, comments and reviews are welcome.


Having another look into this now...
Sagi Grimberg July 17, 2021, 6:08 a.m. UTC | #2
> Add helper function to determine if a given synchronous hash is supported.


Can you add more info in the change log? Who is the consumer
and why is this needed.
Sagi Grimberg July 17, 2021, 6:08 a.m. UTC | #3
> Add helper function to determine if a given key-agreement protocol primitive is supported.


Same comment.
Sagi Grimberg July 17, 2021, 6:14 a.m. UTC | #4
> Add helper functions to generaten Finite Field DH Ephemeral Parameters as

> specified in RFC 7919.

> 

> Signed-off-by: Hannes Reinecke <hare@suse.de>

> ---

>   crypto/Kconfig         |   8 +

>   crypto/Makefile        |   1 +

>   crypto/ffdhe_helper.c  | 877 +++++++++++++++++++++++++++++++++++++++++

>   include/crypto/ffdhe.h |  24 ++

>   4 files changed, 910 insertions(+)

>   create mode 100644 crypto/ffdhe_helper.c

>   create mode 100644 include/crypto/ffdhe.h

> 

> diff --git a/crypto/Kconfig b/crypto/Kconfig

> index ca3b02dcbbfa..1bea506ba56f 100644

> --- a/crypto/Kconfig

> +++ b/crypto/Kconfig

> @@ -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"


I'd stick with "Diffie-Hellman" in the tristate.

> +	select CRYPTO_DH

> +	select CRYPTO_KPP

> +	select CRYPTO_RNG_DEFAULT

> +	help

> +	  Generic implementation of the Finite Field DH algorithm


Diffie-Hellman algorithm
And not sure I'd call it algorithm implementation, but rather a
helper but maybe something like:
Finite Field Diffie-Hellman ephemeral parameters helper implementation

> +

>   config CRYPTO_ECC

>   	tristate

>   

> diff --git a/crypto/Makefile b/crypto/Makefile

> index 10526d4559b8..d3bc79fba23f 100644

> --- a/crypto/Makefile

> +++ b/crypto/Makefile

> @@ -177,6 +177,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

> diff --git a/crypto/ffdhe_helper.c b/crypto/ffdhe_helper.c

> new file mode 100644

> index 000000000000..dc023e30c4e5

> --- /dev/null

> +++ b/crypto/ffdhe_helper.c

> @@ -0,0 +1,877 @@

> +/* SPDX-License-Identifier: GPL-2.0-or-later */

> +/*

> + * Finite Field DH Ephemeral Parameters (RFC 7919)

> + *

> + * 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 <linux/mpi.h>

> +

> +/*

> + * ffdhe2048 generator (g), modulus (p) and group size (q)


Maybe worth to refer exactly the source of these parameters
in the comment body (rfc section/appendix).

> + */

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

> diff --git a/include/crypto/ffdhe.h b/include/crypto/ffdhe.h

> new file mode 100644

> index 000000000000..6cb9253ddb34

> --- /dev/null

> +++ b/include/crypto/ffdhe.h

> @@ -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 <hare@suse.de>

> + */

> +#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 */

>
Hannes Reinecke July 17, 2021, 1:57 p.m. UTC | #5
On 7/17/21 8:14 AM, Sagi Grimberg wrote:
>> Add helper functions to generaten Finite Field DH Ephemeral Parameters as

>> specified in RFC 7919.

>>

>> Signed-off-by: Hannes Reinecke <hare@suse.de>

>> ---

>>   crypto/Kconfig         |   8 +

>>   crypto/Makefile        |   1 +

>>   crypto/ffdhe_helper.c  | 877 +++++++++++++++++++++++++++++++++++++++++

>>   include/crypto/ffdhe.h |  24 ++

>>   4 files changed, 910 insertions(+)

>>   create mode 100644 crypto/ffdhe_helper.c

>>   create mode 100644 include/crypto/ffdhe.h

>>

>> diff --git a/crypto/Kconfig b/crypto/Kconfig

>> index ca3b02dcbbfa..1bea506ba56f 100644

>> --- a/crypto/Kconfig

>> +++ b/crypto/Kconfig

>> @@ -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"

> 

> I'd stick with "Diffie-Hellman" in the tristate.

> 


Ok.

>> +    select CRYPTO_DH

>> +    select CRYPTO_KPP

>> +    select CRYPTO_RNG_DEFAULT

>> +    help

>> +      Generic implementation of the Finite Field DH algorithm

> 

> Diffie-Hellman algorithm

> And not sure I'd call it algorithm implementation, but rather a

> helper but maybe something like:

> Finite Field Diffie-Hellman ephemeral parameters helper implementation

> 


Wasn't sure how to call it myself; as stated I'm not a security expert.

>> +

>>   config CRYPTO_ECC

>>       tristate

>> diff --git a/crypto/Makefile b/crypto/Makefile

>> index 10526d4559b8..d3bc79fba23f 100644

>> --- a/crypto/Makefile

>> +++ b/crypto/Makefile

>> @@ -177,6 +177,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

>> diff --git a/crypto/ffdhe_helper.c b/crypto/ffdhe_helper.c

>> new file mode 100644

>> index 000000000000..dc023e30c4e5

>> --- /dev/null

>> +++ b/crypto/ffdhe_helper.c

>> @@ -0,0 +1,877 @@

>> +/* SPDX-License-Identifier: GPL-2.0-or-later */

>> +/*

>> + * Finite Field DH Ephemeral Parameters (RFC 7919)

>> + *

>> + * 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 <linux/mpi.h>

>> +

>> +/*

>> + * ffdhe2048 generator (g), modulus (p) and group size (q)

> 

> Maybe worth to refer exactly the source of these parameters

> in the comment body (rfc section/appendix).

> 


Sure. These actually are copies from RFC 7919, so will be adding a 
reference to it.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare@suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
Stephan Mueller July 17, 2021, 3:03 p.m. UTC | #6
Am Freitag, 16. Juli 2021, 13:04:20 CEST schrieb Hannes Reinecke:

Hi Hannes,

> +#include <linux/module.h>

> +#include <crypto/internal/kpp.h>

> +#include <crypto/kpp.h>

> +#include <crypto/dh.h>

> +#include <linux/mpi.h>

> +

> +/*

> + * ffdhe2048 generator (g), modulus (p) and group size (q)

> + */

> +const u8 ffdhe2048_g[] = { 0x02 };


What about using static const here (and for all the following groups)?

Ciao
Stephan
Stephan Mueller July 17, 2021, 4:49 p.m. UTC | #7
Am Freitag, 16. Juli 2021, 13:04:27 CEST schrieb Hannes Reinecke:

Hi Hannes,

> Implement support for augmented challenge with FFDHE groups.

> This patch adds a new configfs attribute 'dhchap_dhgroup' to

> select the DH group to use.

> 

> Signed-off-by: Hannes Reinecke <hare@suse.de>

> ---

>  drivers/nvme/target/auth.c             | 241 ++++++++++++++++++++++++-

>  drivers/nvme/target/configfs.c         |  31 ++++

>  drivers/nvme/target/fabrics-cmd-auth.c |  14 +-

>  3 files changed, 281 insertions(+), 5 deletions(-)

> 

> diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c

> index 00c7d051dfb1..cc7f12a7c8bf 100644

> --- a/drivers/nvme/target/auth.c

> +++ b/drivers/nvme/target/auth.c

> @@ -58,11 +58,56 @@ int nvmet_auth_set_host_key(struct nvmet_host *host,

> const char *secret)

> 

>  int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, int dhgroup_id)

>  {

> +	struct nvmet_host_link *p;

> +	struct nvmet_host *host = NULL;

> +	const char *dhgroup_kpp;

>  	int ret = -ENOTSUPP;

> 

>  	if (dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_NULL)

>  		return 0;

> 

> +	down_read(&nvmet_config_sem);

> +	if (ctrl->subsys->type == NVME_NQN_DISC)

> +		goto out_unlock;

> +

> +	list_for_each_entry(p, &ctrl->subsys->hosts, entry) {

> +		if (strcmp(nvmet_host_name(p->host), ctrl->hostnqn))

> +			continue;

> +		host = p->host;

> +		break;

> +	}

> +	if (!host) {

> +		pr_debug("host %s not found\n", ctrl->hostnqn);

> +		ret = -ENXIO;

> +		goto out_unlock;

> +	}

> +

> +	if (host->dhchap_dhgroup_id != dhgroup_id) {

> +		ret = -EINVAL;

> +		goto out_unlock;

> +	}

> +	dhgroup_kpp = nvme_auth_dhgroup_kpp(dhgroup_id);

> +	if (!dhgroup_kpp) {

> +		ret = -EINVAL;

> +		goto out_unlock;

> +	}

> +	ctrl->dh_tfm = crypto_alloc_kpp(dhgroup_kpp, 0, 0);

> +	if (IS_ERR(ctrl->dh_tfm)) {

> +		pr_debug("failed to setup DH group %d, err %ld\n",

> +			 dhgroup_id, PTR_ERR(ctrl->dh_tfm));

> +		ret = PTR_ERR(ctrl->dh_tfm);

> +		ctrl->dh_tfm = NULL;

> +	} else {

> +		ctrl->dh_gid = dhgroup_id;

> +		ctrl->dh_keysize = nvme_auth_dhgroup_pubkey_size(dhgroup_id);

> +		pr_debug("select DH group %d keysize %d\n",

> +			 ctrl->dh_gid, ctrl->dh_keysize);

> +		ret = 0;

> +	}

> +

> +out_unlock:

> +	up_read(&nvmet_config_sem);

> +

>  	return ret;

>  }

> 

> @@ -192,6 +237,101 @@ bool nvmet_check_auth_status(struct nvmet_req *req)

>  	return true;

>  }

> 

> +static int nvmet_auth_hash_sesskey(struct nvmet_req *req, u8 *hashed_key)

> +{

> +	struct nvmet_ctrl *ctrl = req->sq->ctrl;

> +	const char *hmac_name, *digest_name;

> +	struct crypto_shash *tfm;

> +	int hmac_id, ret;

> +

> +	if (!ctrl->shash_tfm) {

> +		pr_debug("%s: hash alg not set\n", __func__);

> +		return -EINVAL;

> +	}

> +	hmac_name = crypto_shash_alg_name(ctrl->shash_tfm);

> +	hmac_id = nvme_auth_hmac_id(hmac_name);

> +	if (hmac_id < 0) {

> +		pr_debug("%s: unsupported hmac %s\n", __func__,

> +			 hmac_name);

> +		return -EINVAL;

> +	}

> +	digest_name = nvme_auth_digest_name(hmac_id);

> +	if (!digest_name) {

> +		pr_debug("%s: failed to get digest for %s\n", __func__,

> +			 hmac_name);

> +		return -EINVAL;

> +	}

> +	tfm = crypto_alloc_shash(digest_name, 0, 0);

> +	if (IS_ERR(tfm))

> +		return -ENOMEM;

> +

> +	ret = crypto_shash_tfm_digest(tfm, req->sq->dhchap_skey,

> +				      req->sq->dhchap_skey_len, hashed_key);

> +	if (ret < 0)

> +		pr_debug("%s: Failed to hash digest len %d\n", __func__,

> +			 req->sq->dhchap_skey_len);

> +

> +	crypto_free_shash(tfm);

> +	return ret;

> +}

> +

> +static int nvmet_auth_augmented_challenge(struct nvmet_req *req,

> +					  u8 *challenge, u8 *aug)

> +{

> +	struct nvmet_ctrl *ctrl = req->sq->ctrl;

> +	struct crypto_shash *tfm;

> +	struct shash_desc *desc;

> +	u8 *hashed_key;

> +	const char *hash_name;

> +	int hash_len = req->sq->dhchap_hash_len;

> +	int ret;

> +

> +	hashed_key = kmalloc(hash_len, GFP_KERNEL);

> +	if (!hashed_key)

> +		return -ENOMEM;

> +

> +	ret = nvmet_auth_hash_sesskey(req, hashed_key);

> +	if (ret < 0) {

> +		pr_debug("failed to hash session key, err %d\n", ret);

> +		kfree(hashed_key);

> +		return ret;

> +	}

> +	hash_name = crypto_shash_alg_name(ctrl->shash_tfm);

> +	if (!hash_name) {

> +		pr_debug("Invalid hash algoritm\n");

> +		return -EINVAL;

> +	}

> +	tfm = crypto_alloc_shash(hash_name, 0, 0);

> +	if (IS_ERR(tfm)) {

> +		ret = PTR_ERR(tfm);

> +		goto out_free_key;

> +	}

> +	desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),

> +		       GFP_KERNEL);

> +	if (!desc) {

> +		ret = -ENOMEM;

> +		goto out_free_hash;

> +	}

> +	desc->tfm = tfm;

> +

> +	ret = crypto_shash_setkey(tfm, hashed_key, hash_len);

> +	if (ret)

> +		goto out_free_desc;

> +	ret = crypto_shash_init(desc);

> +	if (ret)

> +		goto out_free_desc;

> +	crypto_shash_update(desc, challenge, hash_len);

> +	crypto_shash_final(desc, aug);

> +

> +out_free_desc:

> +	kfree_sensitive(desc);

> +out_free_hash:

> +	crypto_free_shash(tfm);

> +out_free_key:

> +	kfree(hashed_key);

> +	return ret;

> +}

> +

>  int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,

>  			 unsigned int shash_len)

>  {

> @@ -202,8 +342,15 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8

> *response, int ret;

> 

>  	if (ctrl->dh_gid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

> -		ret = -ENOTSUPP;

> -		goto out;

> +		challenge = kmalloc(shash_len, GFP_KERNEL);


Alignment?

> +		if (!challenge) {

> +			ret = -ENOMEM;

> +			goto out;

> +		}

> +		ret = nvmet_auth_augmented_challenge(req, req->sq->dhchap_c1,

> +						     challenge);

> +		if (ret)

> +			goto out;

>  	}

> 

>  	shash->tfm = ctrl->shash_tfm;

> @@ -264,8 +411,15 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8

> *response, ctrl->cntlid, ctrl->hostnqn);

> 

>  	if (ctrl->dh_gid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

> -		ret = -ENOTSUPP;

> -		goto out;

> +		challenge = kmalloc(shash_len, GFP_KERNEL);


dto.
> +		if (!challenge) {

> +			ret = -ENOMEM;

> +			goto out;

> +		}

> +		ret = nvmet_auth_augmented_challenge(req, req->sq->dhchap_c2,

> +						     challenge);

> +		if (ret)

> +			goto out;

>  	}

> 

>  	shash->tfm = ctrl->shash_tfm;

> @@ -307,6 +461,85 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8

> *response, return 0;

>  }

> 

> +int nvmet_auth_ctrl_exponential(struct nvmet_req *req,

> +				u8 *buf, int buf_size)

> +{

> +	struct nvmet_ctrl *ctrl = req->sq->ctrl;

> +	struct kpp_request *kpp_req;

> +	struct crypto_wait wait;

> +	char *pkey;

> +	struct scatterlist dst;

> +	int ret, pkey_len;

> +

> +	if (ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_2048 ||

> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_3072 ||

> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_4096 ||

> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_6144 ||

> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_8192) {

> +		struct dh p = {0};

> +		int bits = nvme_auth_dhgroup_pubkey_size(ctrl->dh_gid) << 3;

> +

> +		ret = crypto_ffdhe_params(&p, bits);

> +		if (ret)

> +			return ret;

> +

> +		p.key = ctrl->dhchap_key;

> +		p.key_size = ctrl->dhchap_key_len;

> +

> +		pkey_len = crypto_dh_key_len(&p);

> +		pkey = kmalloc(pkey_len, GFP_KERNEL);

> +		if (!pkey)

> +			return -ENOMEM;

> +

> +		get_random_bytes(pkey, pkey_len);

> +		ret = crypto_dh_encode_key(pkey, pkey_len, &p);

> +		if (ret) {

> +			pr_debug("failed to encode private key, error %d\n",

> +				 ret);

> +			goto out;

> +		}

> +	} else {

> +		pr_warn("invalid dh group %d\n", ctrl->dh_gid);

> +		return -EINVAL;

> +	}

> +	ret = crypto_kpp_set_secret(ctrl->dh_tfm, pkey, pkey_len);

> +	if (ret) {

> +		pr_debug("failed to set private key, error %d\n", ret);

> +		goto out;

> +	}

> +

> +	kpp_req = kpp_request_alloc(ctrl->dh_tfm, GFP_KERNEL);

> +	if (!kpp_req) {

> +		pr_debug("cannot allocate kpp request\n");

> +		ret = -ENOMEM;

> +		goto out;

> +	}

> +

> +	crypto_init_wait(&wait);

> +	kpp_request_set_input(kpp_req, NULL, 0);

> +	sg_init_one(&dst, buf, buf_size);

> +	kpp_request_set_output(kpp_req, &dst, buf_size);

> +	kpp_request_set_callback(kpp_req, CRYPTO_TFM_REQ_MAY_BACKLOG,

> +				 crypto_req_done, &wait);

> +

> +	ret = crypto_wait_req(crypto_kpp_generate_public_key(kpp_req), &wait);

> +	kpp_request_free(kpp_req);

> +	if (ret == -EOVERFLOW) {

> +		pr_debug("public key buffer too small, need %d is %d\n",

> +			 crypto_kpp_maxsize(ctrl->dh_tfm), buf_size);

> +		ret = -ENOKEY;

> +	} else if (ret) {

> +		pr_debug("failed to generate public key, err %d\n", ret);

> +		ret = -ENOKEY;

> +	} else

> +		pr_debug("%s: ctrl public key %*ph\n", __func__,

> +			 (int)buf_size, buf);

> +

> +out:

> +	kfree_sensitive(pkey);

> +	return ret;

> +}


In general: the target/host authentication code looks very similar. Is there 
no way to have a common code base?
> +

>  int nvmet_auth_ctrl_sesskey(struct nvmet_req *req,

>  			    u8 *pkey, int pkey_size)

>  {

> diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c

> index e0760911a761..e9b8884a83b0 100644

> --- a/drivers/nvme/target/configfs.c

> +++ b/drivers/nvme/target/configfs.c

> @@ -1712,9 +1712,40 @@ 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_hash,

> +	&nvmet_host_attr_dhchap_dhgroup,

>  	NULL,

>  };

>  #endif /* CONFIG_NVME_TARGET_AUTH */

> diff --git a/drivers/nvme/target/fabrics-cmd-auth.c

> b/drivers/nvme/target/fabrics-cmd-auth.c index 962f9f5e9d89..478ac351c645

> 100644

> --- a/drivers/nvme/target/fabrics-cmd-auth.c

> +++ b/drivers/nvme/target/fabrics-cmd-auth.c

> @@ -98,7 +98,11 @@ static u16 nvmet_auth_reply(struct nvmet_req *req, void

> *d) return NVME_AUTH_DHCHAP_FAILURE_INVALID_PAYLOAD;

> 

>  	if (data->dhvlen) {

> -		return NVME_AUTH_DHCHAP_FAILURE_INVALID_PAYLOAD;

> +		if (!ctrl->dh_tfm)

> +			return NVME_AUTH_DHCHAP_FAILURE_INVALID_PAYLOAD;

> +		if (nvmet_auth_ctrl_sesskey(req, data->rval + 2 * data->hl,

> +					    data->dhvlen) < 0)

> +			return NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

>  	}

> 

>  	response = kmalloc(data->hl, GFP_KERNEL);

> @@ -299,6 +303,8 @@ static int nvmet_auth_challenge(struct nvmet_req *req,

> void *d, int al) int ret = 0;

>  	int data_size = sizeof(*d) + req->sq->dhchap_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);

> @@ -317,6 +323,12 @@ 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 = ctrl->dh_keysize;

> +		ret = nvmet_auth_ctrl_exponential(req, data->cval + data->hl,

> +						  data->dhvlen);

> +	}

>  	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, data->dhvlen);



Ciao
Stephan
Stephan Mueller July 17, 2021, 4:49 p.m. UTC | #8
Am Freitag, 16. Juli 2021, 13:04:24 CEST schrieb Hannes Reinecke:

Hi Hannes,

> Implement support for augmented challenge using FFDHE groups.

> 

> Signed-off-by: Hannes Reinecke <hare@suse.de>

> ---

>  drivers/nvme/host/auth.c | 403 +++++++++++++++++++++++++++++++++++----

>  1 file changed, 371 insertions(+), 32 deletions(-)

> 

> diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c

> index 448a3adebea6..754343aced19 100644

> --- a/drivers/nvme/host/auth.c

> +++ b/drivers/nvme/host/auth.c

> @@ -8,6 +8,8 @@

>  #include <asm/unaligned.h>

>  #include <crypto/hash.h>

>  #include <crypto/kpp.h>

> +#include <crypto/dh.h>

> +#include <crypto/ffdhe.h>

>  #include "nvme.h"

>  #include "fabrics.h"

>  #include "auth.h"

> @@ -16,6 +18,8 @@ static u32 nvme_dhchap_seqnum;

> 

>  struct nvme_dhchap_context {

>  	struct crypto_shash *shash_tfm;

> +	struct crypto_shash *digest_tfm;

> +	struct crypto_kpp *dh_tfm;

>  	unsigned char *key;

>  	size_t key_len;

>  	int qid;

> @@ -25,6 +29,8 @@ struct nvme_dhchap_context {

>  	u8 status;

>  	u8 hash_id;

>  	u8 hash_len;

> +	u8 dhgroup_id;

> +	u16 dhgroup_size;

>  	u8 c1[64];

>  	u8 c2[64];

>  	u8 response[64];

> @@ -36,6 +42,94 @@ struct nvme_dhchap_context {

>  	int sess_key_len;

>  };

> 

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

> +

>  struct nvmet_dhchap_hash_map {

>  	int id;

>  	int hash_len;

> @@ -243,11 +337,16 @@ static int nvme_auth_dhchap_negotiate(struct nvme_ctrl

> *ctrl, 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 = 1;

> +	data->auth_protocol[0].dhchap.dhlen = 6;

>  	data->auth_protocol[0].dhchap.idlist[0] = NVME_AUTH_DHCHAP_HASH_SHA256;

>  	data->auth_protocol[0].dhchap.idlist[1] = NVME_AUTH_DHCHAP_HASH_SHA384;

>  	data->auth_protocol[0].dhchap.idlist[2] = NVME_AUTH_DHCHAP_HASH_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;

>  }

> @@ -274,14 +373,7 @@ static int nvme_auth_dhchap_challenge(struct nvme_ctrl

> *ctrl, chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;

>  		return -EPROTO;

>  	}

> -	switch (data->dhgid) {

> -	case NVME_AUTH_DHCHAP_DHGROUP_NULL:

> -		gid_name = "null";

> -		break;

> -	default:

> -		gid_name = NULL;

> -		break;

> -	}

> +	gid_name = nvme_auth_dhgroup_kpp(data->dhgid);

>  	if (!gid_name) {

>  		dev_warn(ctrl->device,

>  			 "qid %d: DH-HMAC-CHAP: invalid DH group id %d\n",

> @@ -290,10 +382,24 @@ static int nvme_auth_dhchap_challenge(struct nvme_ctrl

> *ctrl, return -EPROTO;

>  	}

>  	if (data->dhgid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

> -		chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

> -		return -EPROTO;

> -	}

> -	if (data->dhgid == NVME_AUTH_DHCHAP_DHGROUP_NULL && data->dhvlen != 0) {

> +		if (data->dhvlen == 0) {

> +			dev_warn(ctrl->device,

> +				 "qid %d: DH-HMAC-CHAP: empty DH value\n",

> +				 chap->qid);

> +			chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

> +			return -EPROTO;

> +		}

> +		chap->dh_tfm = crypto_alloc_kpp(gid_name, 0, 0);

> +		if (IS_ERR(chap->dh_tfm)) {

> +			dev_warn(ctrl->device,

> +				 "qid %d: DH-HMAC-CHAP: failed to initialize %s\n",

> +				 chap->qid, gid_name);

> +			chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

> +			chap->dh_tfm = NULL;

> +			return -EPROTO;

> +		}

> +		chap->dhgroup_id = data->dhgid;

> +	} else if (data->dhvlen != 0) {

>  		dev_warn(ctrl->device,

>  			 "qid %d: DH-HMAC-CHAP: invalid DH value for NULL DH\n",

>  			chap->qid);

> @@ -313,6 +419,16 @@ static int nvme_auth_dhchap_challenge(struct nvme_ctrl

> *ctrl, chap->hash_len = data->hl;

>  	chap->s1 = le32_to_cpu(data->seqnum);

>  	memcpy(chap->c1, data->cval, chap->hash_len);

> +	if (data->dhvlen) {

> +		chap->ctrl_key = kmalloc(data->dhvlen, GFP_KERNEL);

> +		if (!chap->ctrl_key)

> +			return -ENOMEM;

> +		chap->ctrl_key_len = data->dhvlen;

> +		memcpy(chap->ctrl_key, data->cval + chap->hash_len,

> +		       data->dhvlen);

> +		dev_dbg(ctrl->device, "ctrl public key %*ph\n",

> +			 (int)chap->ctrl_key_len, chap->ctrl_key);

> +	}

> 

>  	return 0;

>  }

> @@ -353,10 +469,13 @@ static int nvme_auth_dhchap_reply(struct nvme_ctrl

> *ctrl, memcpy(data->rval + chap->hash_len, chap->c2,

>  		       chap->hash_len);

>  	}

> -	if (chap->host_key_len)

> +	if (chap->host_key_len) {

> +		dev_dbg(ctrl->device, "%s: qid %d host public key %*ph\n",

> +			__func__, chap->qid,

> +			chap->host_key_len, chap->host_key);

>  		memcpy(data->rval + 2 * chap->hash_len, chap->host_key,

>  		       chap->host_key_len);

> -

> +	}

>  	return size;

>  }

> 

> @@ -440,23 +559,10 @@ static int nvme_auth_dhchap_failure2(struct nvme_ctrl

> *ctrl, int nvme_auth_select_hash(struct nvme_ctrl *ctrl,

>  			  struct nvme_dhchap_context *chap)

>  {

> -	char *hash_name;

> +	const char *hash_name, *digest_name;

>  	int ret;

> 

> -	switch (chap->hash_id) {

> -	case NVME_AUTH_DHCHAP_HASH_SHA256:

> -		hash_name = "hmac(sha256)";

> -		break;

> -	case NVME_AUTH_DHCHAP_HASH_SHA384:

> -		hash_name = "hmac(sha384)";

> -		break;

> -	case NVME_AUTH_DHCHAP_HASH_SHA512:

> -		hash_name = "hmac(sha512)";

> -		break;

> -	default:

> -		hash_name = NULL;

> -		break;

> -	}

> +	hash_name = nvme_auth_hmac_name(chap->hash_id);

>  	if (!hash_name) {

>  		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

>  		return -EPROTO;

> @@ -468,26 +574,100 @@ int nvme_auth_select_hash(struct nvme_ctrl *ctrl,

>  		chap->shash_tfm = NULL;

>  		return -EPROTO;

>  	}

> +	digest_name = nvme_auth_digest_name(chap->hash_id);

> +	if (!digest_name) {

> +		crypto_free_shash(chap->shash_tfm);

> +		chap->shash_tfm = NULL;

> +		return -EPROTO;

> +	}

> +	chap->digest_tfm = crypto_alloc_shash(digest_name, 0, 0);

> +	if (IS_ERR(chap->digest_tfm)) {

> +		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> +		crypto_free_shash(chap->shash_tfm);

> +		chap->shash_tfm = NULL;

> +		chap->digest_tfm = NULL;

> +		return -EPROTO;

> +	}

>  	if (!chap->key) {

>  		dev_warn(ctrl->device, "qid %d: cannot select hash, no key\n",

>  			 chap->qid);

>  		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> +		crypto_free_shash(chap->digest_tfm);

>  		crypto_free_shash(chap->shash_tfm);

>  		chap->shash_tfm = NULL;

> +		chap->digest_tfm = NULL;

>  		return -EINVAL;

>  	}

>  	ret = crypto_shash_setkey(chap->shash_tfm, chap->key, chap->key_len);

>  	if (ret) {

>  		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> +		crypto_free_shash(chap->digest_tfm);

>  		crypto_free_shash(chap->shash_tfm);

>  		chap->shash_tfm = NULL;

> +		chap->digest_tfm = NULL;

>  		return ret;

>  	}

> -	dev_info(ctrl->device, "qid %d: DH-HMAC_CHAP: selected hash %s\n",

> -		 chap->qid, hash_name);

> +	dev_dbg(ctrl->device, "qid %d: DH-HMAC_CHAP: selected hash %s\n",

> +		chap->qid, hash_name);

>  	return 0;

>  }

> 

> +static int nvme_auth_augmented_challenge(struct nvme_dhchap_context *chap,

> +					 u8 *challenge, u8 *aug)

> +{

> +	struct crypto_shash *tfm;

> +	struct shash_desc *desc;

> +	u8 *hashed_key;

> +	const char *hash_name;

> +	int ret;

> +

> +	hashed_key = kmalloc(chap->hash_len, GFP_KERNEL);

> +	if (!hashed_key)

> +		return -ENOMEM;

> +

> +	ret = crypto_shash_tfm_digest(chap->digest_tfm, chap->sess_key,

> +				      chap->sess_key_len, hashed_key);

> +	if (ret < 0) {

> +		pr_debug("failed to hash session key, err %d\n", ret);

> +		kfree(hashed_key);

> +		return ret;

> +	}

> +	hash_name = crypto_shash_alg_name(chap->shash_tfm);

> +	if (!hash_name) {

> +		pr_debug("Invalid hash algoritm\n");

> +		return -EINVAL;

> +	}

> +	tfm = crypto_alloc_shash(hash_name, 0, 0);

> +	if (IS_ERR(tfm)) {

> +		ret = PTR_ERR(tfm);

> +		goto out_free_key;

> +	}

> +	desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),

> +		       GFP_KERNEL);

> +	if (!desc) {

> +		ret = -ENOMEM;

> +		goto out_free_hash;

> +	}

> +	desc->tfm = tfm;

> +

> +	ret = crypto_shash_setkey(tfm, hashed_key, chap->hash_len);

> +	if (ret)

> +		goto out_free_desc;

> +	ret = crypto_shash_init(desc);

> +	if (ret)

> +		goto out_free_desc;

> +	crypto_shash_update(desc, challenge, chap->hash_len);

> +	crypto_shash_final(desc, aug);

> +

> +out_free_desc:

> +	kfree_sensitive(desc);

> +out_free_hash:

> +	crypto_free_shash(tfm);

> +out_free_key:

> +	kfree(hashed_key);

> +	return ret;

> +}

> +

>  static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl,

>  					  struct nvme_dhchap_context *chap)

>  {

> @@ -497,6 +677,16 @@ static int nvme_auth_dhchap_host_response(struct

> nvme_ctrl *ctrl,

> 

>  	dev_dbg(ctrl->device, "%s: qid %d host response seq %d transaction 

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

> +	if (chap->dh_tfm) {

> +		challenge = kmalloc(chap->hash_len, GFP_KERNEL);


Again, alignment?

> +		if (!challenge) {

> +			ret = -ENOMEM;

> +			goto out;

> +		}

> +		ret = nvme_auth_augmented_challenge(chap, chap->c1, challenge);

> +		if (ret)

> +			goto out;

> +	}

>  	shash->tfm = chap->shash_tfm;

>  	ret = crypto_shash_init(shash);

>  	if (ret)

> @@ -532,6 +722,8 @@ static int nvme_auth_dhchap_host_response(struct

> nvme_ctrl *ctrl, goto out;

>  	ret = crypto_shash_final(shash, chap->response);

>  out:

> +	if (challenge != chap->c1)

> +		kfree(challenge);

>  	return ret;

>  }

> 

> @@ -542,6 +734,17 @@ static int nvme_auth_dhchap_ctrl_response(struct

> nvme_ctrl *ctrl, u8 buf[4], *challenge = chap->c2;

>  	int ret;

> 

> +	if (chap->dh_tfm) {

> +		challenge = kmalloc(chap->hash_len, GFP_KERNEL);


dto.

> +		if (!challenge) {

> +			ret = -ENOMEM;

> +			goto out;

> +		}

> +		ret = nvme_auth_augmented_challenge(chap, chap->c2,

> +						    challenge);

> +		if (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",

> @@ -585,6 +788,8 @@ static int nvme_auth_dhchap_ctrl_response(struct

> nvme_ctrl *ctrl, goto out;

>  	ret = crypto_shash_final(shash, chap->response);

>  out:

> +	if (challenge != chap->c2)

> +		kfree(challenge);

>  	return ret;

>  }

> 

> @@ -644,10 +849,134 @@ int nvme_auth_generate_key(struct nvme_ctrl *ctrl,

>  	return 0;

>  }

> 

> +static int nvme_auth_dhchap_exponential(struct nvme_ctrl *ctrl,

> +					struct nvme_dhchap_context *chap)

> +{

> +	struct kpp_request *req;

> +	struct crypto_wait wait;

> +	struct scatterlist src, dst;

> +	u8 *pkey;

> +	int ret, pkey_len;

> +

> +	if (chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_2048 ||

> +	    chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_3072 ||

> +	    chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_4096 ||

> +	    chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_6144 ||

> +	    chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_8192) {

> +		struct dh p = {0};

> +		int pubkey_size = nvme_auth_dhgroup_pubkey_size(chap->dhgroup_id);

> +

> +		ret = crypto_ffdhe_params(&p, pubkey_size << 3);

> +		if (ret) {

> +			dev_dbg(ctrl->device,

> +				"failed to generate ffdhe params, error %d\n",

> +				ret);

> +			return ret;

> +		}

> +		p.key = chap->key;

> +		p.key_size = chap->key_len;

> +

> +		pkey_len = crypto_dh_key_len(&p);

> +		pkey = kzalloc(pkey_len, GFP_KERNEL);

> +

> +		get_random_bytes(pkey, pkey_len);

> +		ret = crypto_dh_encode_key(pkey, pkey_len, &p);

> +		if (ret) {

> +			dev_dbg(ctrl->device,

> +				"failed to encode pkey, error %d\n", ret);

> +			kfree(pkey);

> +			return ret;

> +		}

> +		chap->host_key_len = pubkey_size;

> +		chap->sess_key_len = pubkey_size;

> +	} else {

> +		dev_warn(ctrl->device, "Invalid DH group id %d\n",

> +			 chap->dhgroup_id);

> +		chap->status = NVME_AUTH_DHCHAP_FAILURE_INVALID_PAYLOAD;

> +		return -EINVAL;

> +	}

> +

> +	ret = crypto_kpp_set_secret(chap->dh_tfm, pkey, pkey_len);

> +	if (ret) {

> +		dev_dbg(ctrl->dev, "failed to set secret, error %d\n", ret);

> +		kfree(pkey);

> +		return ret;

> +	}

> +	req = kpp_request_alloc(chap->dh_tfm, GFP_KERNEL);

> +	if (!req) {

> +		ret = -ENOMEM;

> +		goto out_free_exp;

> +	}

> +

> +	chap->host_key = kzalloc(chap->host_key_len, GFP_KERNEL);

> +	if (!chap->host_key) {

> +		ret = -ENOMEM;

> +		goto out_free_req;

> +	}

> +	crypto_init_wait(&wait);

> +	kpp_request_set_input(req, NULL, 0);

> +	sg_init_one(&dst, chap->host_key, chap->host_key_len);

> +	kpp_request_set_output(req, &dst, chap->host_key_len);

> +	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,

> +				 crypto_req_done, &wait);

> +

> +	ret = crypto_wait_req(crypto_kpp_generate_public_key(req), &wait);

> +	if (ret == -EOVERFLOW) {

> +		dev_dbg(ctrl->dev,

> +			"public key buffer too small, wants %d is %d\n",

> +			crypto_kpp_maxsize(chap->dh_tfm), chap->host_key_len);

> +		goto out_free_host;

> +	} else if (ret) {

> +		dev_dbg(ctrl->dev,

> +			"failed to generate public key, error %d\n", ret);

> +		goto out_free_host;

> +	}

> +

> +	chap->sess_key = kmalloc(chap->sess_key_len, GFP_KERNEL);

> +	if (!chap->sess_key)

> +		goto out_free_host;

> +

> +	crypto_init_wait(&wait);

> +	sg_init_one(&src, chap->ctrl_key, chap->ctrl_key_len);

> +	kpp_request_set_input(req, &src, chap->ctrl_key_len);

> +	sg_init_one(&dst, chap->sess_key, chap->sess_key_len);

> +	kpp_request_set_output(req, &dst, chap->sess_key_len);

> +	kpp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,

> +				 crypto_req_done, &wait);

> +

> +	ret = crypto_wait_req(crypto_kpp_compute_shared_secret(req), &wait);

> +	if (ret) {

> +		dev_dbg(ctrl->dev,

> +			"failed to generate shared secret, error %d\n", ret);

> +		kfree_sensitive(chap->sess_key);

> +		chap->sess_key = NULL;

> +		chap->sess_key_len = 0;

> +	} else

> +		dev_dbg(ctrl->dev, "shared secret %*ph\n",

> +			 (int)chap->sess_key_len, chap->sess_key);

> +out_free_host:

> +	if (ret) {

> +		kfree(chap->host_key);

> +		chap->host_key = NULL;

> +		chap->host_key_len = 0;

> +	}

> +out_free_req:

> +	kpp_request_free(req);

> +out_free_exp:

> +	kfree_sensitive(pkey);

> +	if (ret)

> +		chap->status = NVME_AUTH_DHCHAP_FAILURE_INVALID_PAYLOAD;

> +	return ret;

> +}

> +

>  void nvme_auth_free(struct nvme_dhchap_context *chap)

>  {

>  	if (chap->shash_tfm)

>  		crypto_free_shash(chap->shash_tfm);

> +	if (chap->digest_tfm)

> +		crypto_free_shash(chap->digest_tfm);

> +	if (chap->dh_tfm)

> +		crypto_free_kpp(chap->dh_tfm);

>  	if (chap->key)

>  		kfree(chap->key);

>  	if (chap->ctrl_key)

> @@ -732,6 +1061,15 @@ int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int

> qid) if (ret)

>  		goto fail2;

> 

> +	if (chap->ctrl_key_len) {

> +		dev_dbg(ctrl->device,

> +			"%s: qid %d DH-HMAC-DHAP DH exponential\n",

> +			__func__, qid);

> +		ret = nvme_auth_dhchap_exponential(ctrl, chap);

> +		if (ret)

> +			goto fail2;

> +	}

> +

>  	dev_dbg(ctrl->device, "%s: qid %d DH-HMAC-CHAP host response\n",

>  		__func__, qid);

>  	ret = nvme_auth_dhchap_host_response(ctrl, chap);

> @@ -806,6 +1144,7 @@ int nvme_auth_negotiate(struct nvme_ctrl *ctrl, int

> qid) ret = -EPROTO;

>  	if (!ret) {

>  		ctrl->dhchap_hash = chap->hash_id;

> +		ctrl->dhchap_dhgroup = chap->dhgroup_id;

>  	}

>  	kfree(buf);

>  	nvme_auth_free(chap);



Ciao
Stephan
Hannes Reinecke July 18, 2021, 12:22 p.m. UTC | #9
On 7/17/21 5:03 PM, Stephan Müller wrote:
> Am Freitag, 16. Juli 2021, 13:04:20 CEST schrieb Hannes Reinecke:

> 

> Hi Hannes,

> 

>> +#include <linux/module.h>

>> +#include <crypto/internal/kpp.h>

>> +#include <crypto/kpp.h>

>> +#include <crypto/dh.h>

>> +#include <linux/mpi.h>

>> +

>> +/*

>> + * ffdhe2048 generator (g), modulus (p) and group size (q)

>> + */

>> +const u8 ffdhe2048_g[] = { 0x02 };

> 

> What about using static const here (and for all the following groups)?

> 

Yes, of course. Will be fixing it.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare@suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
Hannes Reinecke July 18, 2021, 12:25 p.m. UTC | #10
On 7/17/21 6:49 PM, Stephan Müller wrote:
> Am Freitag, 16. Juli 2021, 13:04:27 CEST schrieb Hannes Reinecke:

> 

> Hi Hannes,

> 

>> Implement support for augmented challenge with FFDHE groups.

>> This patch adds a new configfs attribute 'dhchap_dhgroup' to

>> select the DH group to use.

>>

>> Signed-off-by: Hannes Reinecke <hare@suse.de>

>> ---

>>   drivers/nvme/target/auth.c             | 241 ++++++++++++++++++++++++-

>>   drivers/nvme/target/configfs.c         |  31 ++++

>>   drivers/nvme/target/fabrics-cmd-auth.c |  14 +-

>>   3 files changed, 281 insertions(+), 5 deletions(-)

>>

>> diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c

>> index 00c7d051dfb1..cc7f12a7c8bf 100644

>> --- a/drivers/nvme/target/auth.c

>> +++ b/drivers/nvme/target/auth.c

>> @@ -58,11 +58,56 @@ int nvmet_auth_set_host_key(struct nvmet_host *host,

>> const char *secret)

>>

>>   int nvmet_setup_dhgroup(struct nvmet_ctrl *ctrl, int dhgroup_id)

>>   {

>> +	struct nvmet_host_link *p;

>> +	struct nvmet_host *host = NULL;

>> +	const char *dhgroup_kpp;

>>   	int ret = -ENOTSUPP;

>>

>>   	if (dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_NULL)

>>   		return 0;

>>

>> +	down_read(&nvmet_config_sem);

>> +	if (ctrl->subsys->type == NVME_NQN_DISC)

>> +		goto out_unlock;

>> +

>> +	list_for_each_entry(p, &ctrl->subsys->hosts, entry) {

>> +		if (strcmp(nvmet_host_name(p->host), ctrl->hostnqn))

>> +			continue;

>> +		host = p->host;

>> +		break;

>> +	}

>> +	if (!host) {

>> +		pr_debug("host %s not found\n", ctrl->hostnqn);

>> +		ret = -ENXIO;

>> +		goto out_unlock;

>> +	}

>> +

>> +	if (host->dhchap_dhgroup_id != dhgroup_id) {

>> +		ret = -EINVAL;

>> +		goto out_unlock;

>> +	}

>> +	dhgroup_kpp = nvme_auth_dhgroup_kpp(dhgroup_id);

>> +	if (!dhgroup_kpp) {

>> +		ret = -EINVAL;

>> +		goto out_unlock;

>> +	}

>> +	ctrl->dh_tfm = crypto_alloc_kpp(dhgroup_kpp, 0, 0);

>> +	if (IS_ERR(ctrl->dh_tfm)) {

>> +		pr_debug("failed to setup DH group %d, err %ld\n",

>> +			 dhgroup_id, PTR_ERR(ctrl->dh_tfm));

>> +		ret = PTR_ERR(ctrl->dh_tfm);

>> +		ctrl->dh_tfm = NULL;

>> +	} else {

>> +		ctrl->dh_gid = dhgroup_id;

>> +		ctrl->dh_keysize = nvme_auth_dhgroup_pubkey_size(dhgroup_id);

>> +		pr_debug("select DH group %d keysize %d\n",

>> +			 ctrl->dh_gid, ctrl->dh_keysize);

>> +		ret = 0;

>> +	}

>> +

>> +out_unlock:

>> +	up_read(&nvmet_config_sem);

>> +

>>   	return ret;

>>   }

>>

>> @@ -192,6 +237,101 @@ bool nvmet_check_auth_status(struct nvmet_req *req)

>>   	return true;

>>   }

>>

>> +static int nvmet_auth_hash_sesskey(struct nvmet_req *req, u8 *hashed_key)

>> +{

>> +	struct nvmet_ctrl *ctrl = req->sq->ctrl;

>> +	const char *hmac_name, *digest_name;

>> +	struct crypto_shash *tfm;

>> +	int hmac_id, ret;

>> +

>> +	if (!ctrl->shash_tfm) {

>> +		pr_debug("%s: hash alg not set\n", __func__);

>> +		return -EINVAL;

>> +	}

>> +	hmac_name = crypto_shash_alg_name(ctrl->shash_tfm);

>> +	hmac_id = nvme_auth_hmac_id(hmac_name);

>> +	if (hmac_id < 0) {

>> +		pr_debug("%s: unsupported hmac %s\n", __func__,

>> +			 hmac_name);

>> +		return -EINVAL;

>> +	}

>> +	digest_name = nvme_auth_digest_name(hmac_id);

>> +	if (!digest_name) {

>> +		pr_debug("%s: failed to get digest for %s\n", __func__,

>> +			 hmac_name);

>> +		return -EINVAL;

>> +	}

>> +	tfm = crypto_alloc_shash(digest_name, 0, 0);

>> +	if (IS_ERR(tfm))

>> +		return -ENOMEM;

>> +

>> +	ret = crypto_shash_tfm_digest(tfm, req->sq->dhchap_skey,

>> +				      req->sq->dhchap_skey_len, hashed_key);

>> +	if (ret < 0)

>> +		pr_debug("%s: Failed to hash digest len %d\n", __func__,

>> +			 req->sq->dhchap_skey_len);

>> +

>> +	crypto_free_shash(tfm);

>> +	return ret;

>> +}

>> +

>> +static int nvmet_auth_augmented_challenge(struct nvmet_req *req,

>> +					  u8 *challenge, u8 *aug)

>> +{

>> +	struct nvmet_ctrl *ctrl = req->sq->ctrl;

>> +	struct crypto_shash *tfm;

>> +	struct shash_desc *desc;

>> +	u8 *hashed_key;

>> +	const char *hash_name;

>> +	int hash_len = req->sq->dhchap_hash_len;

>> +	int ret;

>> +

>> +	hashed_key = kmalloc(hash_len, GFP_KERNEL);

>> +	if (!hashed_key)

>> +		return -ENOMEM;

>> +

>> +	ret = nvmet_auth_hash_sesskey(req, hashed_key);

>> +	if (ret < 0) {

>> +		pr_debug("failed to hash session key, err %d\n", ret);

>> +		kfree(hashed_key);

>> +		return ret;

>> +	}

>> +	hash_name = crypto_shash_alg_name(ctrl->shash_tfm);

>> +	if (!hash_name) {

>> +		pr_debug("Invalid hash algoritm\n");

>> +		return -EINVAL;

>> +	}

>> +	tfm = crypto_alloc_shash(hash_name, 0, 0);

>> +	if (IS_ERR(tfm)) {

>> +		ret = PTR_ERR(tfm);

>> +		goto out_free_key;

>> +	}

>> +	desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),

>> +		       GFP_KERNEL);

>> +	if (!desc) {

>> +		ret = -ENOMEM;

>> +		goto out_free_hash;

>> +	}

>> +	desc->tfm = tfm;

>> +

>> +	ret = crypto_shash_setkey(tfm, hashed_key, hash_len);

>> +	if (ret)

>> +		goto out_free_desc;

>> +	ret = crypto_shash_init(desc);

>> +	if (ret)

>> +		goto out_free_desc;

>> +	crypto_shash_update(desc, challenge, hash_len);

>> +	crypto_shash_final(desc, aug);

>> +

>> +out_free_desc:

>> +	kfree_sensitive(desc);

>> +out_free_hash:

>> +	crypto_free_shash(tfm);

>> +out_free_key:

>> +	kfree(hashed_key);

>> +	return ret;

>> +}

>> +

>>   int nvmet_auth_host_hash(struct nvmet_req *req, u8 *response,

>>   			 unsigned int shash_len)

>>   {

>> @@ -202,8 +342,15 @@ int nvmet_auth_host_hash(struct nvmet_req *req, u8

>> *response, int ret;

>>

>>   	if (ctrl->dh_gid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

>> -		ret = -ENOTSUPP;

>> -		goto out;

>> +		challenge = kmalloc(shash_len, GFP_KERNEL);

> 

> Alignment?

> 


With what?
And why?

>> +		if (!challenge) {

>> +			ret = -ENOMEM;

>> +			goto out;

>> +		}

>> +		ret = nvmet_auth_augmented_challenge(req, req->sq->dhchap_c1,

>> +						     challenge);

>> +		if (ret)

>> +			goto out;

>>   	}

>>

>>   	shash->tfm = ctrl->shash_tfm;

>> @@ -264,8 +411,15 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8

>> *response, ctrl->cntlid, ctrl->hostnqn);

>>

>>   	if (ctrl->dh_gid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

>> -		ret = -ENOTSUPP;

>> -		goto out;

>> +		challenge = kmalloc(shash_len, GFP_KERNEL);

> 

> dto.


dto.

>> +		if (!challenge) {

>> +			ret = -ENOMEM;

>> +			goto out;

>> +		}

>> +		ret = nvmet_auth_augmented_challenge(req, req->sq->dhchap_c2,

>> +						     challenge);

>> +		if (ret)

>> +			goto out;

>>   	}

>>

>>   	shash->tfm = ctrl->shash_tfm;

>> @@ -307,6 +461,85 @@ int nvmet_auth_ctrl_hash(struct nvmet_req *req, u8

>> *response, return 0;

>>   }

>>

>> +int nvmet_auth_ctrl_exponential(struct nvmet_req *req,

>> +				u8 *buf, int buf_size)

>> +{

>> +	struct nvmet_ctrl *ctrl = req->sq->ctrl;

>> +	struct kpp_request *kpp_req;

>> +	struct crypto_wait wait;

>> +	char *pkey;

>> +	struct scatterlist dst;

>> +	int ret, pkey_len;

>> +

>> +	if (ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_2048 ||

>> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_3072 ||

>> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_4096 ||

>> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_6144 ||

>> +	    ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_8192) {

>> +		struct dh p = {0};

>> +		int bits = nvme_auth_dhgroup_pubkey_size(ctrl->dh_gid) << 3;

>> +

>> +		ret = crypto_ffdhe_params(&p, bits);

>> +		if (ret)

>> +			return ret;

>> +

>> +		p.key = ctrl->dhchap_key;

>> +		p.key_size = ctrl->dhchap_key_len;

>> +

>> +		pkey_len = crypto_dh_key_len(&p);

>> +		pkey = kmalloc(pkey_len, GFP_KERNEL);

>> +		if (!pkey)

>> +			return -ENOMEM;

>> +

>> +		get_random_bytes(pkey, pkey_len);

>> +		ret = crypto_dh_encode_key(pkey, pkey_len, &p);

>> +		if (ret) {

>> +			pr_debug("failed to encode private key, error %d\n",

>> +				 ret);

>> +			goto out;

>> +		}

>> +	} else {

>> +		pr_warn("invalid dh group %d\n", ctrl->dh_gid);

>> +		return -EINVAL;

>> +	}

>> +	ret = crypto_kpp_set_secret(ctrl->dh_tfm, pkey, pkey_len);

>> +	if (ret) {

>> +		pr_debug("failed to set private key, error %d\n", ret);

>> +		goto out;

>> +	}

>> +

>> +	kpp_req = kpp_request_alloc(ctrl->dh_tfm, GFP_KERNEL);

>> +	if (!kpp_req) {

>> +		pr_debug("cannot allocate kpp request\n");

>> +		ret = -ENOMEM;

>> +		goto out;

>> +	}

>> +

>> +	crypto_init_wait(&wait);

>> +	kpp_request_set_input(kpp_req, NULL, 0);

>> +	sg_init_one(&dst, buf, buf_size);

>> +	kpp_request_set_output(kpp_req, &dst, buf_size);

>> +	kpp_request_set_callback(kpp_req, CRYPTO_TFM_REQ_MAY_BACKLOG,

>> +				 crypto_req_done, &wait);

>> +

>> +	ret = crypto_wait_req(crypto_kpp_generate_public_key(kpp_req), &wait);

>> +	kpp_request_free(kpp_req);

>> +	if (ret == -EOVERFLOW) {

>> +		pr_debug("public key buffer too small, need %d is %d\n",

>> +			 crypto_kpp_maxsize(ctrl->dh_tfm), buf_size);

>> +		ret = -ENOKEY;

>> +	} else if (ret) {

>> +		pr_debug("failed to generate public key, err %d\n", ret);

>> +		ret = -ENOKEY;

>> +	} else

>> +		pr_debug("%s: ctrl public key %*ph\n", __func__,

>> +			 (int)buf_size, buf);

>> +

>> +out:

>> +	kfree_sensitive(pkey);

>> +	return ret;

>> +}

> 

> In general: the target/host authentication code looks very similar. Is there

> no way to have a common code base?


That is the plan, but I would need to rework the parameter passing for 
the target code to also use a 'dhchap' authentication block like the 
host code does.
But Sagi is not entirely happy with it, so I'll rework the code once we 
have consensus there.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare@suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
Hannes Reinecke July 18, 2021, 12:27 p.m. UTC | #11
On 7/17/21 6:49 PM, Stephan Müller wrote:
> Am Freitag, 16. Juli 2021, 13:04:24 CEST schrieb Hannes Reinecke:

> 

> Hi Hannes,

> 

>> Implement support for augmented challenge using FFDHE groups.

>>

>> Signed-off-by: Hannes Reinecke <hare@suse.de>

>> ---

>>   drivers/nvme/host/auth.c | 403 +++++++++++++++++++++++++++++++++++----

>>   1 file changed, 371 insertions(+), 32 deletions(-)

>>

>> diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c

>> index 448a3adebea6..754343aced19 100644

>> --- a/drivers/nvme/host/auth.c

>> +++ b/drivers/nvme/host/auth.c

>> @@ -8,6 +8,8 @@

>>   #include <asm/unaligned.h>

>>   #include <crypto/hash.h>

>>   #include <crypto/kpp.h>

>> +#include <crypto/dh.h>

>> +#include <crypto/ffdhe.h>

>>   #include "nvme.h"

>>   #include "fabrics.h"

>>   #include "auth.h"

>> @@ -16,6 +18,8 @@ static u32 nvme_dhchap_seqnum;

>>

>>   struct nvme_dhchap_context {

>>   	struct crypto_shash *shash_tfm;

>> +	struct crypto_shash *digest_tfm;

>> +	struct crypto_kpp *dh_tfm;

>>   	unsigned char *key;

>>   	size_t key_len;

>>   	int qid;

>> @@ -25,6 +29,8 @@ struct nvme_dhchap_context {

>>   	u8 status;

>>   	u8 hash_id;

>>   	u8 hash_len;

>> +	u8 dhgroup_id;

>> +	u16 dhgroup_size;

>>   	u8 c1[64];

>>   	u8 c2[64];

>>   	u8 response[64];

>> @@ -36,6 +42,94 @@ struct nvme_dhchap_context {

>>   	int sess_key_len;

>>   };

>>

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

>> +

>>   struct nvmet_dhchap_hash_map {

>>   	int id;

>>   	int hash_len;

>> @@ -243,11 +337,16 @@ static int nvme_auth_dhchap_negotiate(struct nvme_ctrl

>> *ctrl, 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 = 1;

>> +	data->auth_protocol[0].dhchap.dhlen = 6;

>>   	data->auth_protocol[0].dhchap.idlist[0] = NVME_AUTH_DHCHAP_HASH_SHA256;

>>   	data->auth_protocol[0].dhchap.idlist[1] = NVME_AUTH_DHCHAP_HASH_SHA384;

>>   	data->auth_protocol[0].dhchap.idlist[2] = NVME_AUTH_DHCHAP_HASH_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;

>>   }

>> @@ -274,14 +373,7 @@ static int nvme_auth_dhchap_challenge(struct nvme_ctrl

>> *ctrl, chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;

>>   		return -EPROTO;

>>   	}

>> -	switch (data->dhgid) {

>> -	case NVME_AUTH_DHCHAP_DHGROUP_NULL:

>> -		gid_name = "null";

>> -		break;

>> -	default:

>> -		gid_name = NULL;

>> -		break;

>> -	}

>> +	gid_name = nvme_auth_dhgroup_kpp(data->dhgid);

>>   	if (!gid_name) {

>>   		dev_warn(ctrl->device,

>>   			 "qid %d: DH-HMAC-CHAP: invalid DH group id %d\n",

>> @@ -290,10 +382,24 @@ static int nvme_auth_dhchap_challenge(struct nvme_ctrl

>> *ctrl, return -EPROTO;

>>   	}

>>   	if (data->dhgid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

>> -		chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

>> -		return -EPROTO;

>> -	}

>> -	if (data->dhgid == NVME_AUTH_DHCHAP_DHGROUP_NULL && data->dhvlen != 0) {

>> +		if (data->dhvlen == 0) {

>> +			dev_warn(ctrl->device,

>> +				 "qid %d: DH-HMAC-CHAP: empty DH value\n",

>> +				 chap->qid);

>> +			chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

>> +			return -EPROTO;

>> +		}

>> +		chap->dh_tfm = crypto_alloc_kpp(gid_name, 0, 0);

>> +		if (IS_ERR(chap->dh_tfm)) {

>> +			dev_warn(ctrl->device,

>> +				 "qid %d: DH-HMAC-CHAP: failed to initialize %s\n",

>> +				 chap->qid, gid_name);

>> +			chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

>> +			chap->dh_tfm = NULL;

>> +			return -EPROTO;

>> +		}

>> +		chap->dhgroup_id = data->dhgid;

>> +	} else if (data->dhvlen != 0) {

>>   		dev_warn(ctrl->device,

>>   			 "qid %d: DH-HMAC-CHAP: invalid DH value for NULL DH\n",

>>   			chap->qid);

>> @@ -313,6 +419,16 @@ static int nvme_auth_dhchap_challenge(struct nvme_ctrl

>> *ctrl, chap->hash_len = data->hl;

>>   	chap->s1 = le32_to_cpu(data->seqnum);

>>   	memcpy(chap->c1, data->cval, chap->hash_len);

>> +	if (data->dhvlen) {

>> +		chap->ctrl_key = kmalloc(data->dhvlen, GFP_KERNEL);

>> +		if (!chap->ctrl_key)

>> +			return -ENOMEM;

>> +		chap->ctrl_key_len = data->dhvlen;

>> +		memcpy(chap->ctrl_key, data->cval + chap->hash_len,

>> +		       data->dhvlen);

>> +		dev_dbg(ctrl->device, "ctrl public key %*ph\n",

>> +			 (int)chap->ctrl_key_len, chap->ctrl_key);

>> +	}

>>

>>   	return 0;

>>   }

>> @@ -353,10 +469,13 @@ static int nvme_auth_dhchap_reply(struct nvme_ctrl

>> *ctrl, memcpy(data->rval + chap->hash_len, chap->c2,

>>   		       chap->hash_len);

>>   	}

>> -	if (chap->host_key_len)

>> +	if (chap->host_key_len) {

>> +		dev_dbg(ctrl->device, "%s: qid %d host public key %*ph\n",

>> +			__func__, chap->qid,

>> +			chap->host_key_len, chap->host_key);

>>   		memcpy(data->rval + 2 * chap->hash_len, chap->host_key,

>>   		       chap->host_key_len);

>> -

>> +	}

>>   	return size;

>>   }

>>

>> @@ -440,23 +559,10 @@ static int nvme_auth_dhchap_failure2(struct nvme_ctrl

>> *ctrl, int nvme_auth_select_hash(struct nvme_ctrl *ctrl,

>>   			  struct nvme_dhchap_context *chap)

>>   {

>> -	char *hash_name;

>> +	const char *hash_name, *digest_name;

>>   	int ret;

>>

>> -	switch (chap->hash_id) {

>> -	case NVME_AUTH_DHCHAP_HASH_SHA256:

>> -		hash_name = "hmac(sha256)";

>> -		break;

>> -	case NVME_AUTH_DHCHAP_HASH_SHA384:

>> -		hash_name = "hmac(sha384)";

>> -		break;

>> -	case NVME_AUTH_DHCHAP_HASH_SHA512:

>> -		hash_name = "hmac(sha512)";

>> -		break;

>> -	default:

>> -		hash_name = NULL;

>> -		break;

>> -	}

>> +	hash_name = nvme_auth_hmac_name(chap->hash_id);

>>   	if (!hash_name) {

>>   		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

>>   		return -EPROTO;

>> @@ -468,26 +574,100 @@ int nvme_auth_select_hash(struct nvme_ctrl *ctrl,

>>   		chap->shash_tfm = NULL;

>>   		return -EPROTO;

>>   	}

>> +	digest_name = nvme_auth_digest_name(chap->hash_id);

>> +	if (!digest_name) {

>> +		crypto_free_shash(chap->shash_tfm);

>> +		chap->shash_tfm = NULL;

>> +		return -EPROTO;

>> +	}

>> +	chap->digest_tfm = crypto_alloc_shash(digest_name, 0, 0);

>> +	if (IS_ERR(chap->digest_tfm)) {

>> +		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

>> +		crypto_free_shash(chap->shash_tfm);

>> +		chap->shash_tfm = NULL;

>> +		chap->digest_tfm = NULL;

>> +		return -EPROTO;

>> +	}

>>   	if (!chap->key) {

>>   		dev_warn(ctrl->device, "qid %d: cannot select hash, no key\n",

>>   			 chap->qid);

>>   		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

>> +		crypto_free_shash(chap->digest_tfm);

>>   		crypto_free_shash(chap->shash_tfm);

>>   		chap->shash_tfm = NULL;

>> +		chap->digest_tfm = NULL;

>>   		return -EINVAL;

>>   	}

>>   	ret = crypto_shash_setkey(chap->shash_tfm, chap->key, chap->key_len);

>>   	if (ret) {

>>   		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

>> +		crypto_free_shash(chap->digest_tfm);

>>   		crypto_free_shash(chap->shash_tfm);

>>   		chap->shash_tfm = NULL;

>> +		chap->digest_tfm = NULL;

>>   		return ret;

>>   	}

>> -	dev_info(ctrl->device, "qid %d: DH-HMAC_CHAP: selected hash %s\n",

>> -		 chap->qid, hash_name);

>> +	dev_dbg(ctrl->device, "qid %d: DH-HMAC_CHAP: selected hash %s\n",

>> +		chap->qid, hash_name);

>>   	return 0;

>>   }

>>

>> +static int nvme_auth_augmented_challenge(struct nvme_dhchap_context *chap,

>> +					 u8 *challenge, u8 *aug)

>> +{

>> +	struct crypto_shash *tfm;

>> +	struct shash_desc *desc;

>> +	u8 *hashed_key;

>> +	const char *hash_name;

>> +	int ret;

>> +

>> +	hashed_key = kmalloc(chap->hash_len, GFP_KERNEL);

>> +	if (!hashed_key)

>> +		return -ENOMEM;

>> +

>> +	ret = crypto_shash_tfm_digest(chap->digest_tfm, chap->sess_key,

>> +				      chap->sess_key_len, hashed_key);

>> +	if (ret < 0) {

>> +		pr_debug("failed to hash session key, err %d\n", ret);

>> +		kfree(hashed_key);

>> +		return ret;

>> +	}

>> +	hash_name = crypto_shash_alg_name(chap->shash_tfm);

>> +	if (!hash_name) {

>> +		pr_debug("Invalid hash algoritm\n");

>> +		return -EINVAL;

>> +	}

>> +	tfm = crypto_alloc_shash(hash_name, 0, 0);

>> +	if (IS_ERR(tfm)) {

>> +		ret = PTR_ERR(tfm);

>> +		goto out_free_key;

>> +	}

>> +	desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),

>> +		       GFP_KERNEL);

>> +	if (!desc) {

>> +		ret = -ENOMEM;

>> +		goto out_free_hash;

>> +	}

>> +	desc->tfm = tfm;

>> +

>> +	ret = crypto_shash_setkey(tfm, hashed_key, chap->hash_len);

>> +	if (ret)

>> +		goto out_free_desc;

>> +	ret = crypto_shash_init(desc);

>> +	if (ret)

>> +		goto out_free_desc;

>> +	crypto_shash_update(desc, challenge, chap->hash_len);

>> +	crypto_shash_final(desc, aug);

>> +

>> +out_free_desc:

>> +	kfree_sensitive(desc);

>> +out_free_hash:

>> +	crypto_free_shash(tfm);

>> +out_free_key:

>> +	kfree(hashed_key);

>> +	return ret;

>> +}

>> +

>>   static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl,

>>   					  struct nvme_dhchap_context *chap)

>>   {

>> @@ -497,6 +677,16 @@ static int nvme_auth_dhchap_host_response(struct

>> nvme_ctrl *ctrl,

>>

>>   	dev_dbg(ctrl->device, "%s: qid %d host response seq %d transaction

> %d\n",

>>   		__func__, chap->qid, chap->s1, chap->transaction);

>> +	if (chap->dh_tfm) {

>> +		challenge = kmalloc(chap->hash_len, GFP_KERNEL);

> 

> Again, alignment?

> 


Again, why?

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare@suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
Stephan Mueller July 18, 2021, 12:57 p.m. UTC | #12
Am Sonntag, 18. Juli 2021, 14:27:48 CEST schrieb Hannes Reinecke:

Hi Hannes,

> On 7/17/21 6:49 PM, Stephan Müller wrote:

> > Am Freitag, 16. Juli 2021, 13:04:24 CEST schrieb Hannes Reinecke:

> > 

> > Hi Hannes,

> > 

> >> Implement support for augmented challenge using FFDHE groups.

> >> 

> >> Signed-off-by: Hannes Reinecke <hare@suse.de>

> >> ---

> >> 

> >>   drivers/nvme/host/auth.c | 403 +++++++++++++++++++++++++++++++++++----

> >>   1 file changed, 371 insertions(+), 32 deletions(-)

> >> 

> >> diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c

> >> index 448a3adebea6..754343aced19 100644

> >> --- a/drivers/nvme/host/auth.c

> >> +++ b/drivers/nvme/host/auth.c

> >> @@ -8,6 +8,8 @@

> >> 

> >>   #include <asm/unaligned.h>

> >>   #include <crypto/hash.h>

> >>   #include <crypto/kpp.h>

> >> 

> >> +#include <crypto/dh.h>

> >> +#include <crypto/ffdhe.h>

> >> 

> >>   #include "nvme.h"

> >>   #include "fabrics.h"

> >>   #include "auth.h"

> >> 

> >> @@ -16,6 +18,8 @@ static u32 nvme_dhchap_seqnum;

> >> 

> >>   struct nvme_dhchap_context {

> >>   

> >>   	struct crypto_shash *shash_tfm;

> >> 

> >> +	struct crypto_shash *digest_tfm;

> >> +	struct crypto_kpp *dh_tfm;

> >> 

> >>   	unsigned char *key;

> >>   	size_t key_len;

> >>   	int qid;

> >> 

> >> @@ -25,6 +29,8 @@ struct nvme_dhchap_context {

> >> 

> >>   	u8 status;

> >>   	u8 hash_id;

> >>   	u8 hash_len;

> >> 

> >> +	u8 dhgroup_id;

> >> +	u16 dhgroup_size;

> >> 

> >>   	u8 c1[64];

> >>   	u8 c2[64];

> >>   	u8 response[64];

> >> 

> >> @@ -36,6 +42,94 @@ struct nvme_dhchap_context {

> >> 

> >>   	int sess_key_len;

> >>   

> >>   };

> >> 

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

> >> +

> >> 

> >>   struct nvmet_dhchap_hash_map {

> >>   

> >>   	int id;

> >>   	int hash_len;

> >> 

> >> @@ -243,11 +337,16 @@ static int nvme_auth_dhchap_negotiate(struct

> >> nvme_ctrl *ctrl, 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 = 1;

> >> +	data->auth_protocol[0].dhchap.dhlen = 6;

> >> 

> >>   	data->auth_protocol[0].dhchap.idlist[0] =

> >>   	NVME_AUTH_DHCHAP_HASH_SHA256;

> >>   	data->auth_protocol[0].dhchap.idlist[1] =

> >>   	NVME_AUTH_DHCHAP_HASH_SHA384;

> >>   	data->auth_protocol[0].dhchap.idlist[2] =

> >>   	NVME_AUTH_DHCHAP_HASH_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;

> >>   

> >>   }

> >> 

> >> @@ -274,14 +373,7 @@ static int nvme_auth_dhchap_challenge(struct

> >> nvme_ctrl

> >> *ctrl, chap->status = NVME_AUTH_DHCHAP_FAILURE_HASH_UNUSABLE;

> >> 

> >>   		return -EPROTO;

> >>   	

> >>   	}

> >> 

> >> -	switch (data->dhgid) {

> >> -	case NVME_AUTH_DHCHAP_DHGROUP_NULL:

> >> -		gid_name = "null";

> >> -		break;

> >> -	default:

> >> -		gid_name = NULL;

> >> -		break;

> >> -	}

> >> +	gid_name = nvme_auth_dhgroup_kpp(data->dhgid);

> >> 

> >>   	if (!gid_name) {

> >>   	

> >>   		dev_warn(ctrl->device,

> >>   		

> >>   			 "qid %d: DH-HMAC-CHAP: invalid DH group id %d\n",

> >> 

> >> @@ -290,10 +382,24 @@ static int nvme_auth_dhchap_challenge(struct

> >> nvme_ctrl *ctrl, return -EPROTO;

> >> 

> >>   	}

> >>   	if (data->dhgid != NVME_AUTH_DHCHAP_DHGROUP_NULL) {

> >> 

> >> -		chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

> >> -		return -EPROTO;

> >> -	}

> >> -	if (data->dhgid == NVME_AUTH_DHCHAP_DHGROUP_NULL && data->dhvlen != 0)

> >> {

> >> +		if (data->dhvlen == 0) {

> >> +			dev_warn(ctrl->device,

> >> +				 "qid %d: DH-HMAC-CHAP: empty DH value\n",

> >> +				 chap->qid);

> >> +			chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

> >> +			return -EPROTO;

> >> +		}

> >> +		chap->dh_tfm = crypto_alloc_kpp(gid_name, 0, 0);

> >> +		if (IS_ERR(chap->dh_tfm)) {

> >> +			dev_warn(ctrl->device,

> >> +				 "qid %d: DH-HMAC-CHAP: failed to initialize %s\n",

> >> +				 chap->qid, gid_name);

> >> +			chap->status = NVME_AUTH_DHCHAP_FAILURE_DHGROUP_UNUSABLE;

> >> +			chap->dh_tfm = NULL;

> >> +			return -EPROTO;

> >> +		}

> >> +		chap->dhgroup_id = data->dhgid;

> >> +	} else if (data->dhvlen != 0) {

> >> 

> >>   		dev_warn(ctrl->device,

> >>   		

> >>   			 "qid %d: DH-HMAC-CHAP: invalid DH value for NULL 

DH\n",
> >>   			

> >>   			chap->qid);

> >> 

> >> @@ -313,6 +419,16 @@ static int nvme_auth_dhchap_challenge(struct

> >> nvme_ctrl

> >> *ctrl, chap->hash_len = data->hl;

> >> 

> >>   	chap->s1 = le32_to_cpu(data->seqnum);

> >>   	memcpy(chap->c1, data->cval, chap->hash_len);

> >> 

> >> +	if (data->dhvlen) {

> >> +		chap->ctrl_key = kmalloc(data->dhvlen, GFP_KERNEL);

> >> +		if (!chap->ctrl_key)

> >> +			return -ENOMEM;

> >> +		chap->ctrl_key_len = data->dhvlen;

> >> +		memcpy(chap->ctrl_key, data->cval + chap->hash_len,

> >> +		       data->dhvlen);

> >> +		dev_dbg(ctrl->device, "ctrl public key %*ph\n",

> >> +			 (int)chap->ctrl_key_len, chap->ctrl_key);

> >> +	}

> >> 

> >>   	return 0;

> >>   

> >>   }

> >> 

> >> @@ -353,10 +469,13 @@ static int nvme_auth_dhchap_reply(struct nvme_ctrl

> >> *ctrl, memcpy(data->rval + chap->hash_len, chap->c2,

> >> 

> >>   		       chap->hash_len);

> >>   	

> >>   	}

> >> 

> >> -	if (chap->host_key_len)

> >> +	if (chap->host_key_len) {

> >> +		dev_dbg(ctrl->device, "%s: qid %d host public key %*ph\n",

> >> +			__func__, chap->qid,

> >> +			chap->host_key_len, chap->host_key);

> >> 

> >>   		memcpy(data->rval + 2 * chap->hash_len, chap->host_key,

> >>   		

> >>   		       chap->host_key_len);

> >> 

> >> -

> >> +	}

> >> 

> >>   	return size;

> >>   

> >>   }

> >> 

> >> @@ -440,23 +559,10 @@ static int nvme_auth_dhchap_failure2(struct

> >> nvme_ctrl

> >> *ctrl, int nvme_auth_select_hash(struct nvme_ctrl *ctrl,

> >> 

> >>   			  struct nvme_dhchap_context *chap)

> >>   

> >>   {

> >> 

> >> -	char *hash_name;

> >> +	const char *hash_name, *digest_name;

> >> 

> >>   	int ret;

> >> 

> >> -	switch (chap->hash_id) {

> >> -	case NVME_AUTH_DHCHAP_HASH_SHA256:

> >> -		hash_name = "hmac(sha256)";

> >> -		break;

> >> -	case NVME_AUTH_DHCHAP_HASH_SHA384:

> >> -		hash_name = "hmac(sha384)";

> >> -		break;

> >> -	case NVME_AUTH_DHCHAP_HASH_SHA512:

> >> -		hash_name = "hmac(sha512)";

> >> -		break;

> >> -	default:

> >> -		hash_name = NULL;

> >> -		break;

> >> -	}

> >> +	hash_name = nvme_auth_hmac_name(chap->hash_id);

> >> 

> >>   	if (!hash_name) {

> >>   	

> >>   		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> >>   		return -EPROTO;

> >> 

> >> @@ -468,26 +574,100 @@ int nvme_auth_select_hash(struct nvme_ctrl *ctrl,

> >> 

> >>   		chap->shash_tfm = NULL;

> >>   		return -EPROTO;

> >>   	

> >>   	}

> >> 

> >> +	digest_name = nvme_auth_digest_name(chap->hash_id);

> >> +	if (!digest_name) {

> >> +		crypto_free_shash(chap->shash_tfm);

> >> +		chap->shash_tfm = NULL;

> >> +		return -EPROTO;

> >> +	}

> >> +	chap->digest_tfm = crypto_alloc_shash(digest_name, 0, 0);

> >> +	if (IS_ERR(chap->digest_tfm)) {

> >> +		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> >> +		crypto_free_shash(chap->shash_tfm);

> >> +		chap->shash_tfm = NULL;

> >> +		chap->digest_tfm = NULL;

> >> +		return -EPROTO;

> >> +	}

> >> 

> >>   	if (!chap->key) {

> >>   	

> >>   		dev_warn(ctrl->device, "qid %d: cannot select hash, no 

key\n",
> >>   		

> >>   			 chap->qid);

> >>   		

> >>   		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> >> 

> >> +		crypto_free_shash(chap->digest_tfm);

> >> 

> >>   		crypto_free_shash(chap->shash_tfm);

> >>   		chap->shash_tfm = NULL;

> >> 

> >> +		chap->digest_tfm = NULL;

> >> 

> >>   		return -EINVAL;

> >>   	

> >>   	}

> >>   	ret = crypto_shash_setkey(chap->shash_tfm, chap->key, chap-

>key_len);

> >>   	if (ret) {

> >>   	

> >>   		chap->status = NVME_AUTH_DHCHAP_FAILURE_NOT_USABLE;

> >> 

> >> +		crypto_free_shash(chap->digest_tfm);

> >> 

> >>   		crypto_free_shash(chap->shash_tfm);

> >>   		chap->shash_tfm = NULL;

> >> 

> >> +		chap->digest_tfm = NULL;

> >> 

> >>   		return ret;

> >>   	

> >>   	}

> >> 

> >> -	dev_info(ctrl->device, "qid %d: DH-HMAC_CHAP: selected hash %s\n",

> >> -		 chap->qid, hash_name);

> >> +	dev_dbg(ctrl->device, "qid %d: DH-HMAC_CHAP: selected hash %s\n",

> >> +		chap->qid, hash_name);

> >> 

> >>   	return 0;

> >>   

> >>   }

> >> 

> >> +static int nvme_auth_augmented_challenge(struct nvme_dhchap_context

> >> *chap,

> >> +					 u8 *challenge, u8 *aug)

> >> +{

> >> +	struct crypto_shash *tfm;

> >> +	struct shash_desc *desc;

> >> +	u8 *hashed_key;

> >> +	const char *hash_name;

> >> +	int ret;

> >> +

> >> +	hashed_key = kmalloc(chap->hash_len, GFP_KERNEL);

> >> +	if (!hashed_key)

> >> +		return -ENOMEM;

> >> +

> >> +	ret = crypto_shash_tfm_digest(chap->digest_tfm, chap->sess_key,

> >> +				      chap->sess_key_len, hashed_key);

> >> +	if (ret < 0) {

> >> +		pr_debug("failed to hash session key, err %d\n", ret);

> >> +		kfree(hashed_key);

> >> +		return ret;

> >> +	}

> >> +	hash_name = crypto_shash_alg_name(chap->shash_tfm);

> >> +	if (!hash_name) {

> >> +		pr_debug("Invalid hash algoritm\n");

> >> +		return -EINVAL;

> >> +	}

> >> +	tfm = crypto_alloc_shash(hash_name, 0, 0);

> >> +	if (IS_ERR(tfm)) {

> >> +		ret = PTR_ERR(tfm);

> >> +		goto out_free_key;

> >> +	}

> >> +	desc = kmalloc(sizeof(struct shash_desc) + crypto_shash_descsize(tfm),

> >> +		       GFP_KERNEL);

> >> +	if (!desc) {

> >> +		ret = -ENOMEM;

> >> +		goto out_free_hash;

> >> +	}

> >> +	desc->tfm = tfm;

> >> +

> >> +	ret = crypto_shash_setkey(tfm, hashed_key, chap->hash_len);

> >> +	if (ret)

> >> +		goto out_free_desc;

> >> +	ret = crypto_shash_init(desc);

> >> +	if (ret)

> >> +		goto out_free_desc;

> >> +	crypto_shash_update(desc, challenge, chap->hash_len);

> >> +	crypto_shash_final(desc, aug);

> >> +

> >> +out_free_desc:

> >> +	kfree_sensitive(desc);

> >> +out_free_hash:

> >> +	crypto_free_shash(tfm);

> >> +out_free_key:

> >> +	kfree(hashed_key);

> >> +	return ret;

> >> +}

> >> +

> >> 

> >>   static int nvme_auth_dhchap_host_response(struct nvme_ctrl *ctrl,

> >>   

> >>   					  struct nvme_dhchap_context *chap)

> >>   

> >>   {

> >> 

> >> @@ -497,6 +677,16 @@ static int nvme_auth_dhchap_host_response(struct

> >> nvme_ctrl *ctrl,

> >> 

> >>   	dev_dbg(ctrl->device, "%s: qid %d host response seq %d 

transaction
> > 

> > %d\n",

> > 

> >>   		__func__, chap->qid, chap->s1, chap->transaction);

> >> 

> >> +	if (chap->dh_tfm) {

> >> +		challenge = kmalloc(chap->hash_len, GFP_KERNEL);

> > 

> > Again, alignment?

> 

> Again, why?


This buffer is the digest buffer of a shash_final, no? check 
crypto_shash_final and see that you could spare yourself some extra work if 
aligned.


Ciao
Stephan
Simo Sorce July 19, 2021, 10:02 a.m. UTC | #13
On Fri, 2021-07-16 at 13:04 +0200, Hannes Reinecke wrote:
> 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.


Hi Hannes,
could you please reference the specific standards that describe the
NVMe authentication protocols?

Thanks,
Simo.

-- 
Simo Sorce
RHEL Crypto Team
Red Hat, Inc
Hannes Reinecke July 19, 2021, 11:11 a.m. UTC | #14
On 7/19/21 12:02 PM, Simo Sorce wrote:
> On Fri, 2021-07-16 at 13:04 +0200, Hannes Reinecke wrote:

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

> 

> Hi Hannes,

> could you please reference the specific standards that describe the

> NVMe authentication protocols?

> 


https://nvmexpress.org/wp-content/uploads/NVM-Express-Base-Specification-2_0-2021.06.02-Ratified-5.pdf

Section '8.13 NVMe-over-Fabrics In-band authentication'

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		           Kernel Storage Architect
hare@suse.de			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
Vladislav Bolkhovitin July 20, 2021, 8:26 p.m. UTC | #15
Hi,

Great to see those patches coming! After some review, they look to be
very well done. Some comments/suggestions below.

1. I strongly recommend to implement DH exponentials reuse (g x mod p /
g y mod p as well as g xy mod p) as specified in section 8.13.5.7
"DH-HMAC-CHAP Security Requirements". When I was working on TP 8006 I
had a prototype that demonstrated that DH math has quite significant
latency, something like (as far as I remember) 30ms for 4K group and few
hundreds of ms for 8K group. For single connection it is not a big deal,
but imagine AMD EPYC with 128 cores. Since all connections are created
sequentially, even with 30 ms per connection time to complete full
remote device connection would become 128*30 => almost 4 seconds. With
8K group it might be more than 10 seconds. Users are unlikely going to
be happy with this, especially in cases, when connecting multiple of
NVMe-oF devices is a part of a server or VM boot sequence.

If DH exponential reuse implemented, for all subsequent connections the
DH math is excluded, so authentication overhead becomes pretty much
negligible.

In my prototype I implemented DH exponential reuse as a simple
per-host/target cache that keeps DH exponentials (including g xy mod p)
for up to 10 seconds. Simple and sufficient.

Another, might be ever more significant reason why DH exponential reuse
is important is that without it x (or y on the host side) must always be
randomly generated each time a new connection is established. Which
means, for instance, for 8K groups for each connection 1KB of random
bytes must be taken from the random pool. With 128 connections it is now
128KB. Quite a big pressure on the random pool that DH exponential reuse
mostly avoids.

Those are the 2 reasons why we added this DH exponential reuse sentence
in the spec. In the original TP 8006 there was a small informative piece
explaining reasonings behind that, but for some reasons it was removed
from the final version.

2. What is the status of this code from perspective of stability in face
of malicious host behavior? Seems implementation is carefully done, but,
for instance, at the first look I was not able to find a code to clean
up if host in not acting for too long in the middle of exchange. Other
observation is that in nvmet_execute_auth_send()
nvmet_check_transfer_len() does not check if tl size is reasonable,
i.e., for instance, not 1GB.

For sure, we don't want to allow remote hosts to hang or crash target.
For instance, because of OOM conditions that happened, because malicious
host asked target to allocate too much memory or open to many being
authenticated connections in which the host is not going to reply in the
middle of exchange.

Asking, because don't want to go in my review too far ahead from the
author ;)

In this regard, it would be great if you add in your test application
ability to perform authentication with random parameters and randomly
stop responding. Overnight running of such test would give us good
degree of confidence that it will always work as expected.

Vlad

On 7/16/21 2:04 PM, Hannes Reinecke wrote:
> 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.

> 

> Hannes Reinecke (11):

>   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: Implement In-Band authentication

>   nvme-auth: augmented challenge support

>   nvmet: Parse fabrics commands on all queues

>   nvmet: Implement basic In-Band Authentication

>   nvmet-auth: implement support for augmented challenge

>   nvme: add non-standard ECDH and curve25517 algorithms

> 

>  crypto/Kconfig                         |    8 +

>  crypto/Makefile                        |    1 +

>  crypto/ffdhe_helper.c                  |  877 +++++++++++++++++

>  crypto/kpp.c                           |    6 +

>  crypto/shash.c                         |    6 +

>  drivers/nvme/host/Kconfig              |   11 +

>  drivers/nvme/host/Makefile             |    1 +

>  drivers/nvme/host/auth.c               | 1188 ++++++++++++++++++++++++

>  drivers/nvme/host/auth.h               |   23 +

>  drivers/nvme/host/core.c               |   77 +-

>  drivers/nvme/host/fabrics.c            |   65 +-

>  drivers/nvme/host/fabrics.h            |    8 +

>  drivers/nvme/host/nvme.h               |   15 +

>  drivers/nvme/host/trace.c              |   32 +

>  drivers/nvme/target/Kconfig            |   10 +

>  drivers/nvme/target/Makefile           |    1 +

>  drivers/nvme/target/admin-cmd.c        |    4 +

>  drivers/nvme/target/auth.c             |  608 ++++++++++++

>  drivers/nvme/target/configfs.c         |  102 +-

>  drivers/nvme/target/core.c             |   10 +

>  drivers/nvme/target/fabrics-cmd-auth.c |  472 ++++++++++

>  drivers/nvme/target/fabrics-cmd.c      |   30 +-

>  drivers/nvme/target/nvmet.h            |   71 ++

>  include/crypto/ffdhe.h                 |   24 +

>  include/crypto/hash.h                  |    2 +

>  include/crypto/kpp.h                   |    2 +

>  include/linux/base64.h                 |   16 +

>  include/linux/nvme.h                   |  187 +++-

>  lib/Makefile                           |    2 +-

>  lib/base64.c                           |  111 +++

>  30 files changed, 3961 insertions(+), 9 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

>
Hannes Reinecke July 21, 2021, 6:06 a.m. UTC | #16
On 7/20/21 10:26 PM, Vladislav Bolkhovitin wrote:
> Hi,

> 

> Great to see those patches coming! After some review, they look to be

> very well done. Some comments/suggestions below.

> 

> 1. I strongly recommend to implement DH exponentials reuse (g x mod p /

> g y mod p as well as g xy mod p) as specified in section 8.13.5.7

> "DH-HMAC-CHAP Security Requirements". When I was working on TP 8006 I

> had a prototype that demonstrated that DH math has quite significant

> latency, something like (as far as I remember) 30ms for 4K group and few

> hundreds of ms for 8K group. For single connection it is not a big deal,

> but imagine AMD EPYC with 128 cores. Since all connections are created

> sequentially, even with 30 ms per connection time to complete full

> remote device connection would become 128*30 => almost 4 seconds. With

> 8K group it might be more than 10 seconds. Users are unlikely going to

> be happy with this, especially in cases, when connecting multiple of

> NVMe-oF devices is a part of a server or VM boot sequence.

> 

Oh, indeed, I can confirm that. FFDHE calculations are quite time-consuming.
But incidentally, ECDH and curve25519 are reasonably fast, so maybe
there _is_ a value in having a TPAR asking for them to be specified, too ...

> If DH exponential reuse implemented, for all subsequent connections the

> DH math is excluded, so authentication overhead becomes pretty much

> negligible.

> 

> In my prototype I implemented DH exponential reuse as a simple

> per-host/target cache that keeps DH exponentials (including g xy mod p)

> for up to 10 seconds. Simple and sufficient.

> 


Frankly, I hadn't looked at exponential reuse; this implementation
really is just a first step to get feedback from people if this is a
direction they want to go.

> Another, might be ever more significant reason why DH exponential reuse

> is important is that without it x (or y on the host side) must always be

> randomly generated each time a new connection is established. Which

> means, for instance, for 8K groups for each connection 1KB of random

> bytes must be taken from the random pool. With 128 connections it is now

> 128KB. Quite a big pressure on the random pool that DH exponential reuse

> mostly avoids.

> 

> Those are the 2 reasons why we added this DH exponential reuse sentence

> in the spec. In the original TP 8006 there was a small informative piece

> explaining reasonings behind that, but for some reasons it was removed

> from the final version.

> 


Thanks for the hint. I'll be adding exponential reuse to the code.

> 2. What is the status of this code from perspective of stability in face

> of malicious host behavior? Seems implementation is carefully done, but,

> for instance, at the first look I was not able to find a code to clean

> up if host in not acting for too long in the middle of exchange. Other

> observation is that in nvmet_execute_auth_send()

> nvmet_check_transfer_len() does not check if tl size is reasonable,

> i.e., for instance, not 1GB.

> 


That is true; exchange timeouts are missing. Will be adding them, of
course. And haven't thought of checking for tl size overflows; will be
adding them, too.

> For sure, we don't want to allow remote hosts to hang or crash target.

> For instance, because of OOM conditions that happened, because malicious

> host asked target to allocate too much memory or open to many being

> authenticated connections in which the host is not going to reply in the

> middle of exchange.

> 

This is something I'll need to look at, anyway. What we do not want is a
userspace application chipping in and send a 'negotiate' command without
any subsequent steps, thereby invalidating the existing authentication.

> Asking, because don't want to go in my review too far ahead from the

> author ;)

> 

> In this regard, it would be great if you add in your test application

> ability to perform authentication with random parameters and randomly

> stop responding. Overnight running of such test would give us good

> degree of confidence that it will always work as expected.

> 


That indeed would be good; let me think on how something like that can
be implemented.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke		           Kernel Storage Architect
hare@suse.de			                  +49 911 74053 688
SUSE Software Solutions Germany GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), GF: Felix Imendörffer
Vladislav Bolkhovitin July 21, 2021, 12:10 p.m. UTC | #17
On 7/21/21 9:06 AM, Hannes Reinecke wrote:
> On 7/20/21 10:26 PM, Vladislav Bolkhovitin wrote:

>> Hi,

>>

>> Great to see those patches coming! After some review, they look to be

>> very well done. Some comments/suggestions below.

>>

>> 1. I strongly recommend to implement DH exponentials reuse (g x mod p /

>> g y mod p as well as g xy mod p) as specified in section 8.13.5.7

>> "DH-HMAC-CHAP Security Requirements". When I was working on TP 8006 I

>> had a prototype that demonstrated that DH math has quite significant

>> latency, something like (as far as I remember) 30ms for 4K group and few

>> hundreds of ms for 8K group. For single connection it is not a big deal,

>> but imagine AMD EPYC with 128 cores. Since all connections are created

>> sequentially, even with 30 ms per connection time to complete full

>> remote device connection would become 128*30 => almost 4 seconds. With

>> 8K group it might be more than 10 seconds. Users are unlikely going to

>> be happy with this, especially in cases, when connecting multiple of

>> NVMe-oF devices is a part of a server or VM boot sequence.

>>

> Oh, indeed, I can confirm that. FFDHE calculations are quite time-consuming.

> But incidentally, ECDH and curve25519 are reasonably fast,


Yes, EC calculations are very fast, this is why EC cryptography is
gaining more and more popularity.

> so maybe

> there _is_ a value in having a TPAR asking for them to be specified, too ...


There's too much politics and procedures involved here. Even in the
current scope it took more, than 2 years to get the spec officially done
(I started proposing it early 2018). Maybe, in future, if someone comes
in the the committee with the corresponding proposal and value
justification.

Although, frankly speaking, with DH exponentials reuse I personally
don't see much value in ECDH in this application. Maybe, only for very
small embedded devices with really limited computational capabilities.

>> If DH exponential reuse implemented, for all subsequent connections the

>> DH math is excluded, so authentication overhead becomes pretty much

>> negligible.

>>

>> In my prototype I implemented DH exponential reuse as a simple

>> per-host/target cache that keeps DH exponentials (including g xy mod p)

>> for up to 10 seconds. Simple and sufficient.

>>

> 

> Frankly, I hadn't looked at exponential reuse; this implementation

> really is just a first step to get feedback from people if this is a

> direction they want to go.


Sure, I understand.

>> Another, might be ever more significant reason why DH exponential reuse

>> is important is that without it x (or y on the host side) must always be

>> randomly generated each time a new connection is established. Which

>> means, for instance, for 8K groups for each connection 1KB of random

>> bytes must be taken from the random pool. With 128 connections it is now

>> 128KB. Quite a big pressure on the random pool that DH exponential reuse

>> mostly avoids.

>>

>> Those are the 2 reasons why we added this DH exponential reuse sentence

>> in the spec. In the original TP 8006 there was a small informative piece

>> explaining reasonings behind that, but for some reasons it was removed

>> from the final version.

>>

> 

> Thanks for the hint. I'll be adding exponential reuse to the code.


Yes, please. Otherwise, people might start talking that Linux NVMe-oF
authentication is too bad and slow.

Vlad
Vladislav Bolkhovitin July 23, 2021, 8:02 p.m. UTC | #18
Another comment is that better to perform CRC check of dhchap_secret and
generation of dhchap_key right where the secret was specified (e.g.,
nvmet_auth_set_host_key() on the target side).

No need to do it every time for every connection and by that increase
authentication latency. As I wrote in the other comment, it might be 128
or more connections established during connecting to a single NVMe-oF
device.

Vlad
Hannes Reinecke July 24, 2021, 11:17 a.m. UTC | #19
On 7/23/21 10:02 PM, Vladislav Bolkhovitin wrote:
> Another comment is that better to perform CRC check of dhchap_secret and

> generation of dhchap_key right where the secret was specified (e.g.,

> nvmet_auth_set_host_key() on the target side).

> 

> No need to do it every time for every connection and by that increase

> authentication latency. As I wrote in the other comment, it might be 128

> or more connections established during connecting to a single NVMe-oF

> device.

> 

And this is something I did deliberately.
The primary issue here is that the user might want/need to change the 
PSK for re-authentication. But for that he might need to check what the 
original/current PSK is, so I think we need to keep the original PSK as 
passed in from the user.
And I found it a waste of space to store the decoded secret in addition 
to the original one, seeing that it can be derived from the original one.
But your argument about the many connections required for a single NVMe 
association is certainly true, to it would make sense to keep the decode 
one around, too, just to speed up computation.
Will be updating the patchset.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare@suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer