u8 nvme_auth_dhgroup_id(constchar *dhgroup_name)
{ int i;
if (!dhgroup_name || !strlen(dhgroup_name)) return NVME_AUTH_DHGROUP_INVALID; for (i = 0; i < ARRAY_SIZE(dhgroup_map); i++) { if (!strlen(dhgroup_map[i].name)) continue; if (!strncmp(dhgroup_map[i].name, dhgroup_name,
strlen(dhgroup_map[i].name))) return i;
} return NVME_AUTH_DHGROUP_INVALID;
}
EXPORT_SYMBOL_GPL(nvme_auth_dhgroup_id);
u8 nvme_auth_hmac_id(constchar *hmac_name)
{ int i;
if (!hmac_name || !strlen(hmac_name)) return NVME_AUTH_HASH_INVALID;
for (i = 0; i < ARRAY_SIZE(hash_map); i++) { if (!strlen(hash_map[i].hmac)) continue; if (!strncmp(hash_map[i].hmac, hmac_name,
strlen(hash_map[i].hmac))) return i;
} return NVME_AUTH_HASH_INVALID;
}
EXPORT_SYMBOL_GPL(nvme_auth_hmac_id);
/* Secret might be affixed with a ':' */
p = strrchr(secret, ':'); if (p)
allocated_len = p - secret;
key = nvme_auth_alloc_key(allocated_len, 0); if (!key) return ERR_PTR(-ENOMEM);
if (key_len != 36 && key_len != 52 &&
key_len != 68) {
pr_err("Invalid key len %d\n", key_len);
ret = -EINVAL; goto out_free_secret;
}
/* The last four bytes is the CRC in little-endian format */
key_len -= 4; /* * The linux implementation doesn't do pre- and post-increments, * so we have to do it manually.
*/
crc = ~crc32(~0, key->key, key_len);
if (sscanf(secret, "DHHC-1:%hhd:%*s:", &key_hash) != 1) return -EINVAL;
/* Pass in the secret without the 'DHHC-1:XX:' prefix */
key = nvme_auth_extract_key(secret + 10, key_hash); if (IS_ERR(key)) {
*ret_key = NULL; return PTR_ERR(key);
}
/** * nvme_auth_generate_psk - Generate a PSK for TLS * @hmac_id: Hash function identifier * @skey: Session key * @skey_len: Length of @skey * @c1: Value of challenge C1 * @c2: Value of challenge C2 * @hash_len: Hash length of the hash algorithm * @ret_psk: Pointer to the resulting generated PSK * @ret_len: length of @ret_psk * * Generate a PSK for TLS as specified in NVMe base specification, section * 8.13.5.9: Generated PSK for TLS * * The generated PSK for TLS shall be computed applying the HMAC function * using the hash function H( ) selected by the HashID parameter in the * DH-HMAC-CHAP_Challenge message with the session key KS as key to the * concatenation of the two challenges C1 and C2 (i.e., generated * PSK = HMAC(KS, C1 || C2)). * * Returns 0 on success with a valid generated PSK pointer in @ret_psk and * the length of @ret_psk in @ret_len, or a negative error number otherwise.
*/ int nvme_auth_generate_psk(u8 hmac_id, u8 *skey, size_t skey_len,
u8 *c1, u8 *c2, size_t hash_len, u8 **ret_psk, size_t *ret_len)
{ struct crypto_shash *tfm;
SHASH_DESC_ON_STACK(shash, tfm);
u8 *psk; constchar *hmac_name; int ret, psk_len;
/** * nvme_auth_generate_digest - Generate TLS PSK digest * @hmac_id: Hash function identifier * @psk: Generated input PSK * @psk_len: Length of @psk * @subsysnqn: NQN of the subsystem * @hostnqn: NQN of the host * @ret_digest: Pointer to the returned digest * * Generate a TLS PSK digest as specified in TP8018 Section 3.6.1.3: * TLS PSK and PSK identity Derivation * * The PSK digest shall be computed by encoding in Base64 (refer to RFC * 4648) the result of the application of the HMAC function using the hash * function specified in item 4 above (ie the hash function of the cipher * suite associated with the PSK identity) with the PSK as HMAC key to the * concatenation of: * - the NQN of the host (i.e., NQNh) not including the null terminator; * - a space character; * - the NQN of the NVM subsystem (i.e., NQNc) not including the null * terminator; * - a space character; and * - the seventeen ASCII characters "NVMe-over-Fabrics" * (i.e., <PSK digest> = Base64(HMAC(PSK, NQNh || " " || NQNc || " " || * "NVMe-over-Fabrics"))). * The length of the PSK digest depends on the hash function used to compute * it as follows: * - If the SHA-256 hash function is used, the resulting PSK digest is 44 * characters long; or * - If the SHA-384 hash function is used, the resulting PSK digest is 64 * characters long. * * Returns 0 on success with a valid digest pointer in @ret_digest, or a * negative error number on failure.
*/ int nvme_auth_generate_digest(u8 hmac_id, u8 *psk, size_t psk_len, char *subsysnqn, char *hostnqn, u8 **ret_digest)
{ struct crypto_shash *tfm;
SHASH_DESC_ON_STACK(shash, tfm);
u8 *digest, *enc; constchar *hmac_name;
size_t digest_len, hmac_len; int ret;
if (WARN_ON(!subsysnqn || !hostnqn)) return -EINVAL;
/** * nvme_auth_derive_tls_psk - Derive TLS PSK * @hmac_id: Hash function identifier * @psk: generated input PSK * @psk_len: size of @psk * @psk_digest: TLS PSK digest * @ret_psk: Pointer to the resulting TLS PSK * * Derive a TLS PSK as specified in TP8018 Section 3.6.1.3: * TLS PSK and PSK identity Derivation * * The TLS PSK shall be derived as follows from an input PSK * (i.e., either a retained PSK or a generated PSK) and a PSK * identity using the HKDF-Extract and HKDF-Expand-Label operations * (refer to RFC 5869 and RFC 8446) where the hash function is the * one specified by the hash specifier of the PSK identity: * 1. PRK = HKDF-Extract(0, Input PSK); and * 2. TLS PSK = HKDF-Expand-Label(PRK, "nvme-tls-psk", PskIdentityContext, L), * where PskIdentityContext is the hash identifier indicated in * the PSK identity concatenated to a space character and to the * Base64 PSK digest (i.e., "<hash> <PSK digest>") and L is the * output size in bytes of the hash function (i.e., 32 for SHA-256 * and 48 for SHA-384). * * Returns 0 on success with a valid psk pointer in @ret_psk or a negative * error number otherwise.
*/ int nvme_auth_derive_tls_psk(int hmac_id, u8 *psk, size_t psk_len,
u8 *psk_digest, u8 **ret_psk)
{ struct crypto_shash *hmac_tfm; constchar *hmac_name; constchar *psk_prefix = "tls13 nvme-tls-psk"; staticconstchar default_salt[HKDF_MAX_HASHLEN];
size_t info_len, prk_len; char *info; unsignedchar *prk, *tls_key; int ret;
hmac_tfm = crypto_alloc_shash(hmac_name, 0, 0); if (IS_ERR(hmac_tfm)) return PTR_ERR(hmac_tfm);
prk_len = crypto_shash_digestsize(hmac_tfm);
prk = kzalloc(prk_len, GFP_KERNEL); if (!prk) {
ret = -ENOMEM; goto out_free_shash;
}
if (WARN_ON(prk_len > HKDF_MAX_HASHLEN)) {
ret = -EINVAL; goto out_free_prk;
}
ret = hkdf_extract(hmac_tfm, psk, psk_len,
default_salt, prk_len, prk); if (ret) goto out_free_prk;
ret = crypto_shash_setkey(hmac_tfm, prk, prk_len); if (ret) goto out_free_prk;
/* * 2 additional bytes for the length field from HDKF-Expand-Label, * 2 additional bytes for the HMAC ID, and one byte for the space * separator.
*/
info_len = strlen(psk_digest) + strlen(psk_prefix) + 5;
info = kzalloc(info_len + 1, GFP_KERNEL); if (!info) {
ret = -ENOMEM; goto out_free_prk;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.