diff mbox series

[11/11] nvme: add non-standard ECDH and curve25517 algorithms

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

Commit Message

Hannes Reinecke July 16, 2021, 11:04 a.m. UTC
TLS 1.3 specifies ECDH and curve25517 in addition to the FFDHE
groups, and these are already implemented in the kernel.
So add support for these non-standard groups for NVMe in-band
authentication to validate the augmented challenge implementation.

Signed-off-by: Hannes Reinecke <hare@suse.de>
---
 drivers/nvme/host/auth.c   | 38 +++++++++++++++++++++++++++++++++++++-
 drivers/nvme/target/auth.c | 23 +++++++++++++++++++++++
 include/linux/nvme.h       |  2 ++
 3 files changed, 62 insertions(+), 1 deletion(-)

Comments

Stephan Mueller July 17, 2021, 4:50 p.m. UTC | #1
Am Freitag, 16. Juli 2021, 13:04:28 CEST schrieb Hannes Reinecke:

Hi Hannes,

> TLS 1.3 specifies ECDH and curve25517 in addition to the FFDHE


curve25519?

> groups, and these are already implemented in the kernel.

> So add support for these non-standard groups for NVMe in-band

> authentication to validate the augmented challenge implementation.

> 

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

> ---

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

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

>  include/linux/nvme.h       |  2 ++

>  3 files changed, 62 insertions(+), 1 deletion(-)

> 

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

> index 754343aced19..d0dd63b455ef 100644

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

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

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

>  #include <crypto/kpp.h>

>  #include <crypto/dh.h>

>  #include <crypto/ffdhe.h>

> +#include <crypto/ecdh.h>

> +#include <crypto/curve25519.h>

>  #include "nvme.h"

>  #include "fabrics.h"

>  #include "auth.h"

> @@ -67,6 +69,13 @@ struct nvme_auth_dhgroup_map {

>  	{ .id = NVME_AUTH_DHCHAP_DHGROUP_8192,

>  	  .name = "ffdhe8192", .kpp = "dh",

>  	  .privkey_size = 1024, .pubkey_size = 1024 },

> +	{ .id = NVME_AUTH_DHCHAP_DHGROUP_ECDH,

> +	  .name = "ecdh", .kpp = "ecdh-nist-p256",

> +	  .privkey_size = 32, .pubkey_size = 64 },

> +	{ .id = NVME_AUTH_DHCHAP_DHGROUP_25519,

> +	  .name = "curve25519", .kpp = "curve25519",

> +	  .privkey_size = CURVE25519_KEY_SIZE,

> +	  .pubkey_size = CURVE25519_KEY_SIZE },

>  };

> 

>  const char *nvme_auth_dhgroup_name(int dhgroup_id)

> @@ -337,7 +346,7 @@ 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 = 6;

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

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

> @@ -347,6 +356,8 @@ static int nvme_auth_dhchap_negotiate(struct nvme_ctrl

> *ctrl, 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; +	data->auth_protocol[0].dhchap.idlist[9] 

=
> NVME_AUTH_DHCHAP_DHGROUP_ECDH; +	data->auth_protocol[0].dhchap.idlist[10] 

=
> NVME_AUTH_DHCHAP_DHGROUP_25519;

> 

>  	return size;

>  }

> @@ -889,6 +900,31 @@ static int nvme_auth_dhchap_exponential(struct

> nvme_ctrl *ctrl, }

>  		chap->host_key_len = pubkey_size;

>  		chap->sess_key_len = pubkey_size;

> +	} else if (chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_ECDH) {

> +		struct ecdh p = {0};

> +

> +		pkey_len = crypto_ecdh_key_len(&p);

> +		pkey = kzalloc(pkey_len, GFP_KERNEL);

> +		if (!pkey)

> +			return -ENOMEM;

> +

> +		get_random_bytes(pkey, pkey_len);

> +		ret = crypto_ecdh_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 = 64;

> +		chap->sess_key_len = 32;

> +	} else if (chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_25519) {

> +		pkey_len = CURVE25519_KEY_SIZE;

> +		pkey = kzalloc(pkey_len, GFP_KERNEL);

> +		if (!pkey)

> +			return -ENOMEM;

> +		get_random_bytes(pkey, pkey_len);

> +		chap->host_key_len = chap->sess_key_len = CURVE25519_KEY_SIZE;

>  	} else {

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

>  			 chap->dhgroup_id);

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

> index cc7f12a7c8bf..7e3b613cb08b 100644

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

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

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

>  #include <crypto/kpp.h>

>  #include <crypto/dh.h>

>  #include <crypto/ffdhe.h>

> +#include <crypto/ecdh.h>

> +#include <crypto/curve25519.h>

>  #include <linux/crc32.h>

>  #include <linux/base64.h>

>  #include <linux/ctype.h>

> @@ -498,6 +500,27 @@ int nvmet_auth_ctrl_exponential(struct nvmet_req *req,

>  				 ret);

>  			goto out;

>  		}

> +	} else if (ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_ECDH) {

> +		struct ecdh p = {0};

> +

> +		pkey_len = crypto_ecdh_key_len(&p);

> +		pkey = kmalloc(pkey_len, GFP_KERNEL);

> +		if (!pkey)

> +			return -ENOMEM;

> +

> +		get_random_bytes(pkey, pkey_len);

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

> +		if (ret) {

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

> +				 ret);

> +			goto out;

> +		}

> +	} else if (ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_25519) {

> +		pkey_len = CURVE25519_KEY_SIZE;

> +		pkey = kmalloc(pkey_len, GFP_KERNEL);

> +		if (!pkey)

> +			return -ENOMEM;

> +		get_random_bytes(pkey, pkey_len);

>  	} else {

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

>  		return -EINVAL;

> diff --git a/include/linux/nvme.h b/include/linux/nvme.h

> index 7b94abacfd08..75b638adbca1 100644

> --- a/include/linux/nvme.h

> +++ b/include/linux/nvme.h

> @@ -1476,6 +1476,8 @@ enum {

>  	NVME_AUTH_DHCHAP_DHGROUP_4096	= 0x03,

>  	NVME_AUTH_DHCHAP_DHGROUP_6144	= 0x04,

>  	NVME_AUTH_DHCHAP_DHGROUP_8192	= 0x05,

> +	NVME_AUTH_DHCHAP_DHGROUP_ECDH   = 0x0e,

> +	NVME_AUTH_DHCHAP_DHGROUP_25519  = 0x0f,

>  };

> 

>  union nvmf_auth_protocol {



Ciao
Stephan
Hannes Reinecke July 18, 2021, 12:44 p.m. UTC | #2
On 7/17/21 6:50 PM, Stephan Müller wrote:
> Am Freitag, 16. Juli 2021, 13:04:28 CEST schrieb Hannes Reinecke:

> 

> Hi Hannes,

> 

>> TLS 1.3 specifies ECDH and curve25517 in addition to the FFDHE

> 

> curve25519?

> 


Of course.

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
Sagi Grimberg July 19, 2021, 9:23 a.m. UTC | #3
> TLS 1.3 specifies ECDH and curve25517 in addition to the FFDHE

> groups, and these are already implemented in the kernel.


So?

> So add support for these non-standard groups for NVMe in-band

> authentication to validate the augmented challenge implementation.


Why? why should users come to expect controllers to support it?
Hannes Reinecke July 19, 2021, 9:56 a.m. UTC | #4
On 7/19/21 11:23 AM, Sagi Grimberg wrote:
> 

>> TLS 1.3 specifies ECDH and curve25517 in addition to the FFDHE

>> groups, and these are already implemented in the kernel.

> 

> So?

> 

>> So add support for these non-standard groups for NVMe in-band

>> authentication to validate the augmented challenge implementation.

> 

> Why? why should users come to expect controllers to support it?


Having ECDH and curve25517 algorithms (which are known-good
implementations) allows one to validate the ffdhe implementation, ie to
ensure that the remainder of the protocol works as designed, even if the
ffdhe implementation might not.
And one could argue that TLS1.3 specifies all of these algorithms, so
NVMe with it's explicit reference to TLS should do so, too.

But I don't insist on it; it's just nice for debugging, that's all.

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
diff mbox series

Patch

diff --git a/drivers/nvme/host/auth.c b/drivers/nvme/host/auth.c
index 754343aced19..d0dd63b455ef 100644
--- a/drivers/nvme/host/auth.c
+++ b/drivers/nvme/host/auth.c
@@ -10,6 +10,8 @@ 
 #include <crypto/kpp.h>
 #include <crypto/dh.h>
 #include <crypto/ffdhe.h>
+#include <crypto/ecdh.h>
+#include <crypto/curve25519.h>
 #include "nvme.h"
 #include "fabrics.h"
 #include "auth.h"
@@ -67,6 +69,13 @@  struct nvme_auth_dhgroup_map {
 	{ .id = NVME_AUTH_DHCHAP_DHGROUP_8192,
 	  .name = "ffdhe8192", .kpp = "dh",
 	  .privkey_size = 1024, .pubkey_size = 1024 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_ECDH,
+	  .name = "ecdh", .kpp = "ecdh-nist-p256",
+	  .privkey_size = 32, .pubkey_size = 64 },
+	{ .id = NVME_AUTH_DHCHAP_DHGROUP_25519,
+	  .name = "curve25519", .kpp = "curve25519",
+	  .privkey_size = CURVE25519_KEY_SIZE,
+	  .pubkey_size = CURVE25519_KEY_SIZE },
 };
 
 const char *nvme_auth_dhgroup_name(int dhgroup_id)
@@ -337,7 +346,7 @@  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 = 6;
+	data->auth_protocol[0].dhchap.dhlen = 8;
 	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;
@@ -347,6 +356,8 @@  static int nvme_auth_dhchap_negotiate(struct nvme_ctrl *ctrl,
 	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;
+	data->auth_protocol[0].dhchap.idlist[9] = NVME_AUTH_DHCHAP_DHGROUP_ECDH;
+	data->auth_protocol[0].dhchap.idlist[10] = NVME_AUTH_DHCHAP_DHGROUP_25519;
 
 	return size;
 }
@@ -889,6 +900,31 @@  static int nvme_auth_dhchap_exponential(struct nvme_ctrl *ctrl,
 		}
 		chap->host_key_len = pubkey_size;
 		chap->sess_key_len = pubkey_size;
+	} else if (chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_ECDH) {
+		struct ecdh p = {0};
+
+		pkey_len = crypto_ecdh_key_len(&p);
+		pkey = kzalloc(pkey_len, GFP_KERNEL);
+		if (!pkey)
+			return -ENOMEM;
+
+		get_random_bytes(pkey, pkey_len);
+		ret = crypto_ecdh_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 = 64;
+		chap->sess_key_len = 32;
+	} else if (chap->dhgroup_id == NVME_AUTH_DHCHAP_DHGROUP_25519) {
+		pkey_len = CURVE25519_KEY_SIZE;
+		pkey = kzalloc(pkey_len, GFP_KERNEL);
+		if (!pkey)
+			return -ENOMEM;
+		get_random_bytes(pkey, pkey_len);
+		chap->host_key_len = chap->sess_key_len = CURVE25519_KEY_SIZE;
 	} else {
 		dev_warn(ctrl->device, "Invalid DH group id %d\n",
 			 chap->dhgroup_id);
diff --git a/drivers/nvme/target/auth.c b/drivers/nvme/target/auth.c
index cc7f12a7c8bf..7e3b613cb08b 100644
--- a/drivers/nvme/target/auth.c
+++ b/drivers/nvme/target/auth.c
@@ -13,6 +13,8 @@ 
 #include <crypto/kpp.h>
 #include <crypto/dh.h>
 #include <crypto/ffdhe.h>
+#include <crypto/ecdh.h>
+#include <crypto/curve25519.h>
 #include <linux/crc32.h>
 #include <linux/base64.h>
 #include <linux/ctype.h>
@@ -498,6 +500,27 @@  int nvmet_auth_ctrl_exponential(struct nvmet_req *req,
 				 ret);
 			goto out;
 		}
+	} else if (ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_ECDH) {
+		struct ecdh p = {0};
+
+		pkey_len = crypto_ecdh_key_len(&p);
+		pkey = kmalloc(pkey_len, GFP_KERNEL);
+		if (!pkey)
+			return -ENOMEM;
+
+		get_random_bytes(pkey, pkey_len);
+		ret = crypto_ecdh_encode_key(pkey, pkey_len, &p);
+		if (ret) {
+			pr_debug("failed to encode private key, error %d\n",
+				 ret);
+			goto out;
+		}
+	} else if (ctrl->dh_gid == NVME_AUTH_DHCHAP_DHGROUP_25519) {
+		pkey_len = CURVE25519_KEY_SIZE;
+		pkey = kmalloc(pkey_len, GFP_KERNEL);
+		if (!pkey)
+			return -ENOMEM;
+		get_random_bytes(pkey, pkey_len);
 	} else {
 		pr_warn("invalid dh group %d\n", ctrl->dh_gid);
 		return -EINVAL;
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 7b94abacfd08..75b638adbca1 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -1476,6 +1476,8 @@  enum {
 	NVME_AUTH_DHCHAP_DHGROUP_4096	= 0x03,
 	NVME_AUTH_DHCHAP_DHGROUP_6144	= 0x04,
 	NVME_AUTH_DHCHAP_DHGROUP_8192	= 0x05,
+	NVME_AUTH_DHCHAP_DHGROUP_ECDH   = 0x0e,
+	NVME_AUTH_DHCHAP_DHGROUP_25519  = 0x0f,
 };
 
 union nvmf_auth_protocol {