Commit 1cab50da authored by Chris Leech's avatar Chris Leech Committed by Keith Busch
Browse files

nvme-auth: add hkdf_expand_label()



Provide an implementation of RFC 8446 (TLS 1.3) HKDF-Expand-Label

Signed-off-by: default avatarChris Leech <cleech@redhat.com>
Signed-off-by: default avatarHannes Reinecke <hare@kernel.org>
Signed-off-by: default avatarKeith Busch <kbusch@kernel.org>
parent df4666a4
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -683,6 +683,59 @@ int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size_t psk_len,
}
EXPORT_SYMBOL_GPL(nvme_auth_generate_digest);

/**
 * hkdf_expand_label - HKDF-Expand-Label (RFC 8846 section 7.1)
 * @hmac_tfm: hash context keyed with pseudorandom key
 * @label: ASCII label without "tls13 " prefix
 * @labellen: length of @label
 * @context: context bytes
 * @contextlen: length of @context
 * @okm: output keying material
 * @okmlen: length of @okm
 *
 * Build the TLS 1.3 HkdfLabel structure and invoke hkdf_expand().
 *
 * Returns 0 on success with output keying material stored in @okm,
 * or a negative errno value otherwise.
 */
static int hkdf_expand_label(struct crypto_shash *hmac_tfm,
		const u8 *label, unsigned int labellen,
		const u8 *context, unsigned int contextlen,
		u8 *okm, unsigned int okmlen)
{
	int err;
	u8 *info;
	unsigned int infolen;
	const char *tls13_prefix = "tls13 ";
	unsigned int prefixlen = strlen(tls13_prefix);

	if (WARN_ON(labellen > (255 - prefixlen)))
		return -EINVAL;
	if (WARN_ON(contextlen > 255))
		return -EINVAL;

	infolen = 2 + (1 + prefixlen + labellen) + (1 + contextlen);
	info = kzalloc(infolen, GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	/* HkdfLabel.Length */
	put_unaligned_be16(okmlen, info);

	/* HkdfLabel.Label */
	info[2] = prefixlen + labellen;
	memcpy(info + 3, tls13_prefix, prefixlen);
	memcpy(info + 3 + prefixlen, label, labellen);

	/* HkdfLabel.Context */
	info[3 + prefixlen + labellen] = contextlen;
	memcpy(info + 4 + prefixlen + labellen, context, contextlen);

	err = hkdf_expand(hmac_tfm, info, infolen, okm, okmlen);
	kfree_sensitive(info);
	return err;
}

/**
 * nvme_auth_derive_tls_psk - Derive TLS PSK
 * @hmac_id: Hash function identifier