Commit 519ecd61 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Jim Harris
Browse files

nvme/auth: make DH functions public



We'll want to use these functions on the target side too.

This patch also introduces struct spdk_nvme_dhchap_dhkey, which is only
used to avoid exposing openssl's EVP_PKEY on the interface.  It'll also
make it possible to add extra context to a DH key, if we ever need it,
without having to modify the API.

Signed-off-by: default avatarKonrad Sztyber <konrad.sztyber@intel.com>
Change-Id: I67359b40c844fa1142ade5e35897ca46ace7cc61
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/22757


Reviewed-by: default avatarBen Walker <ben@nvidia.com>
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarSeung yeon Shin <syeon.shin@samsung.com>
parent 060e0334
Loading
Loading
Loading
Loading
+46 −0
Original line number Diff line number Diff line
@@ -37,4 +37,50 @@ int spdk_nvme_dhchap_calculate(struct spdk_key *key, enum spdk_nvmf_dhchap_hash
			       const char *nqn1, const char *nqn2, const void *dhkey, size_t dhlen,
			       const void *cval, void *rval);

/** DH-HMAC-CHAP Diffie-Hellman key */
struct spdk_nvme_dhchap_dhkey;

/**
 * Generate a Diffie-Hellman key.
 *
 * \param dhg Diffie-Hellman group.
 *
 * \return Diffie-Hellman key or NULL on failure.
 */
struct spdk_nvme_dhchap_dhkey *spdk_nvme_dhchap_generate_dhkey(enum spdk_nvmf_dhchap_dhgroup dhg);

/**
 * Free a DH key generated with `spdk_nvme_dhchap_generate_dhkey()`.
 *
 * \param key DH key.  If NULL, this function is a no-op.
 */
void spdk_nvme_dhchap_dhkey_free(struct spdk_nvme_dhchap_dhkey **key);

/**
 * Get the public part of a DH key.
 *
 * \param key DH key.
 * \param pub Buffer to hold the public key.
 * \param len Length of the `pub` buffer.  After a successful call to this function, this variable
 * will hold the length of the public key.
 *
 * \return 0 on success or negative errno on failure.
 */
int spdk_nvme_dhchap_dhkey_get_pubkey(struct spdk_nvme_dhchap_dhkey *key, void *pub, size_t *len);

/**
 * Derive a secret from a DH key and peer's public key.
 *
 * \param key DH key.
 * \param peer Peer's public key.
 * \param peerlen Length of the peer's public key.
 * \param secret Buffer to hold the secret value.
 * \param seclen Length of the `secret` buffer.  After a successful call to this function, this
 * variable will hold the length of the secret value.
 *
 * \return 0 on success or negative errno on failure.
 */
int spdk_nvme_dhchap_dhkey_derive_secret(struct spdk_nvme_dhchap_dhkey *key, const void *peer,
		size_t peerlen, void *secret, size_t *seclen);

#endif /* SPDK_INTERNAL_NVME_H */
+29 −15
Original line number Diff line number Diff line
@@ -480,8 +480,8 @@ out:
	return rc;
}

static EVP_PKEY *
nvme_auth_generate_dhkey(enum spdk_nvmf_dhchap_dhgroup dhgroup)
struct spdk_nvme_dhchap_dhkey *
spdk_nvme_dhchap_generate_dhkey(enum spdk_nvmf_dhchap_dhgroup dhgroup)
{
	EVP_PKEY_CTX *ctx = NULL;
	EVP_PKEY *key = NULL;
@@ -508,12 +508,24 @@ nvme_auth_generate_dhkey(enum spdk_nvmf_dhchap_dhgroup dhgroup)
	}
error:
	EVP_PKEY_CTX_free(ctx);
	return key;
	return (void *)key;
}

static int
nvme_auth_dhkey_get_pubkey(EVP_PKEY *key, void *pub, size_t *len)
void
spdk_nvme_dhchap_dhkey_free(struct spdk_nvme_dhchap_dhkey **key)
{
	if (key == NULL) {
		return;
	}

	EVP_PKEY_free(*(EVP_PKEY **)key);
	*key = NULL;
}

int
spdk_nvme_dhchap_dhkey_get_pubkey(struct spdk_nvme_dhchap_dhkey *dhkey, void *pub, size_t *len)
{
	EVP_PKEY *key = (EVP_PKEY *)dhkey;
	BIGNUM *bn = NULL;
	int rc;

@@ -593,10 +605,11 @@ error:
	return result;
}

static int
nvme_auth_derive_dhsecret(EVP_PKEY *key, const void *peer, size_t peerlen,
			  void *secret, size_t *seclen)
int
spdk_nvme_dhchap_dhkey_derive_secret(struct spdk_nvme_dhchap_dhkey *dhkey,
				     const void *peer, size_t peerlen, void *secret, size_t *seclen)
{
	EVP_PKEY *key = (EVP_PKEY *)dhkey;
	EVP_PKEY_CTX *ctx = NULL;
	EVP_PKEY *peerkey = NULL;
	char dhgroup[64] = {};
@@ -885,13 +898,13 @@ nvme_auth_send_reply(struct spdk_nvme_qpair *qpair)
	struct spdk_nvmf_dhchap_challenge *challenge = status->dma_data;
	struct spdk_nvmf_dhchap_reply *reply = status->dma_data;
	struct nvme_auth *auth = &qpair->auth;
	struct spdk_nvme_dhchap_dhkey *dhkey;
	uint8_t hl, response[NVME_AUTH_DATA_SIZE];
	uint8_t pubkey[NVME_AUTH_DH_KEY_MAX_SIZE];
	uint8_t dhsec[NVME_AUTH_DH_KEY_MAX_SIZE];
	uint8_t ctrlr_challenge[NVME_AUTH_DIGEST_MAX_SIZE] = {};
	size_t dhseclen = 0, publen = 0;
	uint32_t seqnum = 0;
	EVP_PKEY *dhkey;
	int rc;

	auth->hash = challenge->hash_id;
@@ -900,19 +913,20 @@ nvme_auth_send_reply(struct spdk_nvme_qpair *qpair)
		dhseclen = sizeof(dhsec);
		publen = sizeof(pubkey);
		AUTH_LOGDUMP("ctrlr pubkey:", &challenge->cval[hl], challenge->dhvlen);
		dhkey = nvme_auth_generate_dhkey((enum spdk_nvmf_dhchap_dhgroup)challenge->dhg_id);
		dhkey = spdk_nvme_dhchap_generate_dhkey(
				(enum spdk_nvmf_dhchap_dhgroup)challenge->dhg_id);
		if (dhkey == NULL) {
			return -EINVAL;
		}
		rc = nvme_auth_dhkey_get_pubkey(dhkey, pubkey, &publen);
		rc = spdk_nvme_dhchap_dhkey_get_pubkey(dhkey, pubkey, &publen);
		if (rc != 0) {
			EVP_PKEY_free(dhkey);
			spdk_nvme_dhchap_dhkey_free(&dhkey);
			return rc;
		}
		AUTH_LOGDUMP("host pubkey:", pubkey, publen);
		rc = nvme_auth_derive_dhsecret(dhkey, &challenge->cval[hl], challenge->dhvlen,
					       dhsec, &dhseclen);
		EVP_PKEY_free(dhkey);
		rc = spdk_nvme_dhchap_dhkey_derive_secret(dhkey,
				&challenge->cval[hl], challenge->dhvlen, dhsec, &dhseclen);
		spdk_nvme_dhchap_dhkey_free(&dhkey);
		if (rc != 0) {
			return rc;
		}
+4 −0
Original line number Diff line number Diff line
@@ -215,6 +215,10 @@

	# functions from spdk_internal/nvme.h
	spdk_nvme_dhchap_calculate;
	spdk_nvme_dhchap_generate_dhkey;
	spdk_nvme_dhchap_dhkey_free;
	spdk_nvme_dhchap_dhkey_get_pubkey;
	spdk_nvme_dhchap_dhkey_derive_secret;

	# public functions from nvme_zns.h
	spdk_nvme_zns_ns_get_data;