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

nvme/auth: calculate HMAC-CHAP response



This patch adds a function that calculates a response to the HMAC-CHAP
challenge (without the DH augmentation).

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


Community-CI: Mellanox Build Bot
Reviewed-by: default avatarJim Harris <jim.harris@samsung.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <ben@nvidia.com>
parent b85ffe60
Loading
Loading
Loading
Loading
+84 −6
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include "spdk/string.h"
#include "spdk/util.h"
#include "nvme_internal.h"
#include <openssl/evp.h>

#define NVME_AUTH_DATA_SIZE		4096
#define NVME_AUTH_CHAP_KEY_MAX_SIZE	256
@@ -20,9 +21,7 @@
	SPDK_ERRLOG("[%s:%s:%u] " fmt, (q)->ctrlr->trid.subnqn, (q)->ctrlr->opts.hostnqn, \
		    (q)->id, ## __VA_ARGS__)

const char *nvme_auth_get_digest_name(uint8_t id);

const char *
static const char *
nvme_auth_get_digest_name(uint8_t id)
{
	const char *names[] = {
@@ -116,9 +115,7 @@ nvme_auth_transform_key(struct spdk_key *key, int hash, const void *keyin, size_
	}
}

int nvme_auth_get_key(struct spdk_key *key, void *buf, size_t buflen);

int
static int
nvme_auth_get_key(struct spdk_key *key, void *buf, size_t buflen)
{
	char keystr[NVME_AUTH_CHAP_KEY_MAX_SIZE + 1] = {};
@@ -180,6 +177,87 @@ out:
	return rc;
}

int nvme_auth_calc_response(struct spdk_key *key, enum spdk_nvmf_dhchap_hash hash,
			    const char *type, uint32_t seq, uint16_t tid, uint8_t scc,
			    const char *nqn1, const char *nqn2, const void *dhkey, size_t dhlen,
			    const void *cval, void *rval);

int
nvme_auth_calc_response(struct spdk_key *key, enum spdk_nvmf_dhchap_hash hash,
			const char *type, uint32_t seq, uint16_t tid, uint8_t scc,
			const char *nqn1, const char *nqn2, const void *dhkey, size_t dhlen,
			const void *cval, void *rval)
{
	EVP_MAC *hmac;
	EVP_MAC_CTX *ctx;
	OSSL_PARAM params[2];
	uint8_t keybuf[NVME_AUTH_CHAP_KEY_MAX_SIZE], term = 0;
	size_t hlen;
	int rc, keylen;

	assert(dhkey == NULL && dhlen == 0);
	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;
	}

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

	hlen = nvme_auth_get_digest_len(hash);
	params[0] = OSSL_PARAM_construct_utf8_string("digest",
			(char *)nvme_auth_get_digest_name(hash), 0);
	params[1] = OSSL_PARAM_construct_end();

	rc = -EIO;
	if (EVP_MAC_init(ctx, keybuf, (size_t)keylen, params) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, cval, hlen) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)&seq, sizeof(seq)) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)&tid, sizeof(tid)) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)&scc, sizeof(scc)) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)type, strlen(type)) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)nqn1, strlen(nqn1)) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)&term, sizeof(term)) != 1) {
		goto out;
	}
	if (EVP_MAC_update(ctx, (void *)nqn2, strlen(nqn2)) != 1) {
		goto out;
	}
	if (EVP_MAC_final(ctx, rval, &hlen, hlen) != 1) {
		goto out;
	}
	rc = 0;
out:
	spdk_memset_s(keybuf, sizeof(keybuf), 0, sizeof(keybuf));
	EVP_MAC_CTX_free(ctx);
	EVP_MAC_free(hmac);

	return rc;
}

static int
nvme_auth_submit_request(struct spdk_nvme_qpair *qpair,
			 enum spdk_nvmf_fabric_cmd_types type, uint32_t len)