Message ID | 20210716110428.9727-12-hare@suse.de (mailing list archive) |
---|---|
State | Not Applicable |
Delegated to: | Herbert Xu |
Headers | show |
Series | nvme: In-band authentication support | expand |
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
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
> 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?
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
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 {
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(-)