Commit 979f5511 authored by Konrad Sztyber's avatar Konrad Sztyber Committed by Tomasz Zawadzki
Browse files

nvme/auth: support DH-HMAC-CHAP key transformation



It is now possible to use transformed key by running an HMAC over the
configured DH-HMAC-CHAP key and the NQN of the host.  As described in
the NVMe spec, this mode is automatically selected when the configured
key specifies non-zero hash function (i.e. DHHC-1:{01,02,03} selects
HMAC with sha256, sha384, and sha512 respectively).

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


Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: Mellanox Build Bot
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
parent 0da65a77
Loading
Loading
Loading
Loading
+47 −7
Original line number Diff line number Diff line
@@ -136,9 +136,14 @@ nvme_auth_print_cpl(struct spdk_nvme_qpair *qpair, const char *msg)
}

static int
nvme_auth_transform_key(struct spdk_key *key, int hash, const void *keyin, size_t keylen,
			void *out, size_t outlen)
nvme_auth_transform_key(struct spdk_key *key, int hash, const char *nqn,
			const void *keyin, size_t keylen, void *out, size_t outlen)
{
	EVP_MAC *hmac = NULL;
	EVP_MAC_CTX *ctx = NULL;
	OSSL_PARAM params[2];
	int rc;

	switch (hash) {
	case SPDK_NVMF_DHCHAP_HASH_NONE:
		if (keylen > outlen) {
@@ -151,16 +156,51 @@ nvme_auth_transform_key(struct spdk_key *key, int hash, const void *keyin, size_
	case SPDK_NVMF_DHCHAP_HASH_SHA256:
	case SPDK_NVMF_DHCHAP_HASH_SHA384:
	case SPDK_NVMF_DHCHAP_HASH_SHA512:
		SPDK_ERRLOG("Key transformation is not supported\n");
		return -EINVAL;
		break;
	default:
		SPDK_ERRLOG("Unsupported key hash: 0x%x (key=%s)\n", hash, spdk_key_get_name(key));
		return -EINVAL;
	}

	hmac = EVP_MAC_fetch(NULL, "hmac", NULL);
	if (hmac == NULL) {
		return -EIO;
	}
	ctx = EVP_MAC_CTX_new(hmac);
	if (ctx == NULL) {
		rc = -EIO;
		goto out;
	}
	params[0] = OSSL_PARAM_construct_utf8_string("digest",
			(char *)nvme_auth_get_digest_name(hash), 0);
	params[1] = OSSL_PARAM_construct_end();

	if (EVP_MAC_init(ctx, keyin, keylen, params) != 1) {
		rc = -EIO;
		goto out;
	}
	if (EVP_MAC_update(ctx, nqn, strlen(nqn)) != 1) {
		rc = -EIO;
		goto out;
	}
	if (EVP_MAC_update(ctx, "NVMe-over-Fabrics", strlen("NVMe-over-Fabrics")) != 1) {
		rc = -EIO;
		goto out;
	}
	if (EVP_MAC_final(ctx, out, &outlen, outlen) != 1) {
		rc = -EIO;
		goto out;
	}
	rc = (int)outlen;
out:
	EVP_MAC_CTX_free(ctx);
	EVP_MAC_free(hmac);

	return rc;
}

static int
nvme_auth_get_key(struct spdk_key *key, void *buf, size_t buflen)
nvme_auth_get_key(struct spdk_key *key, const char *nqn, void *buf, size_t buflen)
{
	char keystr[NVME_AUTH_CHAP_KEY_MAX_SIZE + 1] = {};
	char keyb64[NVME_AUTH_CHAP_KEY_MAX_SIZE] = {};
@@ -213,7 +253,7 @@ nvme_auth_get_key(struct spdk_key *key, void *buf, size_t buflen)
		goto out;
	}

	rc = nvme_auth_transform_key(key, hash, keyb64, keylen, buf, buflen);
	rc = nvme_auth_transform_key(key, hash, nqn, keyb64, keylen, buf, buflen);
out:
	spdk_memset_s(keystr, sizeof(keystr), 0, sizeof(keystr));
	spdk_memset_s(keyb64, sizeof(keyb64), 0, sizeof(keyb64));
@@ -316,7 +356,7 @@ nvme_auth_calc_response(struct spdk_key *key, enum spdk_nvmf_dhchap_hash hash,
		goto out;
	}

	keylen = nvme_auth_get_key(key, keybuf, sizeof(keybuf));
	keylen = nvme_auth_get_key(key, nqn1, keybuf, sizeof(keybuf));
	if (keylen < 0) {
		rc = keylen;
		goto out;