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