diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-05 08:35:48 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-08-05 08:35:48 +0000 |
commit | fb4382cf6ceb11ce2c5781d14714e15e45022d03 (patch) | |
tree | 4d529e6152272fde35bc85955a300b4811f672ca /src/nvme/linux.c | |
parent | Releasing debian version 1.9-1. (diff) | |
download | libnvme-fb4382cf6ceb11ce2c5781d14714e15e45022d03.tar.xz libnvme-fb4382cf6ceb11ce2c5781d14714e15e45022d03.zip |
Merging upstream version 1.10.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/nvme/linux.c')
-rw-r--r-- | src/nvme/linux.c | 209 |
1 files changed, 134 insertions, 75 deletions
diff --git a/src/nvme/linux.c b/src/nvme/linux.c index 25196fd..aff0544 100644 --- a/src/nvme/linux.c +++ b/src/nvme/linux.c @@ -18,7 +18,6 @@ #include <unistd.h> #ifdef CONFIG_OPENSSL -#include <openssl/engine.h> #include <openssl/evp.h> #include <openssl/hmac.h> #include <openssl/kdf.h> @@ -166,7 +165,7 @@ int nvme_get_telemetry_log(int fd, bool create, bool ctrl, bool rae, size_t max_ struct nvme_telemetry_log *telem; enum nvme_cmd_get_log_lid lid; - _cleanup_free_ void *log; + _cleanup_free_ void *log = NULL; void *tmp; int err; size_t dalb; @@ -296,8 +295,8 @@ int nvme_get_new_host_telemetry(int fd, struct nvme_telemetry_log **log, int nvme_get_lba_status_log(int fd, bool rae, struct nvme_lba_status_log **log) { + _cleanup_free_ struct nvme_lba_status_log *buf = NULL; __u32 size; - _cleanup_free_ struct nvme_lba_status_log *buf; void *tmp; int err; struct nvme_get_log_args args = { @@ -386,6 +385,16 @@ int nvme_namespace_detach_ctrls(int fd, __u32 nsid, __u16 num_ctrls, NVME_DEFAULT_IOCTL_TIMEOUT); } +size_t nvme_get_ana_log_len_from_id_ctrl(const struct nvme_id_ctrl *id_ctrl, + bool rgo) +{ + __u32 nanagrpid = le32_to_cpu(id_ctrl->nanagrpid); + size_t size = sizeof(struct nvme_ana_log) + + nanagrpid * sizeof(struct nvme_ana_group_desc); + + return rgo ? size : size + le32_to_cpu(id_ctrl->mnan) * sizeof(__le32); +} + int nvme_get_ana_log_len(int fd, size_t *analen) { _cleanup_free_ struct nvme_id_ctrl *ctrl = NULL; @@ -400,9 +409,7 @@ int nvme_get_ana_log_len(int fd, size_t *analen) if (ret) return ret; - *analen = sizeof(struct nvme_ana_log) + - le32_to_cpu(ctrl->nanagrpid) * sizeof(struct nvme_ana_group_desc) + - le32_to_cpu(ctrl->mnan) * sizeof(__le32); + *analen = nvme_get_ana_log_len_from_id_ctrl(ctrl, false); return 0; } @@ -544,22 +551,18 @@ static int derive_retained_key(int hmac, const char *hostnqn, return -1; } -static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, char *identity, - unsigned char *retained, size_t key_len) +static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *retained, size_t key_len, + char *digest, size_t digest_len) { - if (version != 0) { - nvme_msg(NULL, LOG_ERR, "NVMe TLS 2.0 is not supported; " - "recompile with OpenSSL support.\n"); - errno = ENOTSUP; - return -1; - } - sprintf(identity, "NVMe0R%02d %s %s", - hmac, hostnqn, subsysnqn); - return strlen(identity); + nvme_msg(NULL, LOG_ERR, "NVMe TLS 2.0 is not supported; " + "recompile with OpenSSL support.\n"); + errno = ENOTSUP; + return -1; } -static int derive_tls_key(int hmac, const char *identity, +static int derive_tls_key(int version, int hmac, const char *context, unsigned char *retained, unsigned char *psk, size_t key_len) { @@ -655,7 +658,7 @@ static int derive_retained_key(int hmac, const char *hostnqn, return key_len; } -static int derive_tls_key(int hmac, const char *identity, +static int derive_tls_key(int version, int hmac, const char *context, unsigned char *retained, unsigned char *psk, size_t key_len) { @@ -703,9 +706,20 @@ static int derive_tls_key(int hmac, const char *identity, errno = ENOKEY; return -1; } + if (version == 1) { + char hash_str[4]; + + sprintf(hash_str, "%02d ", hmac); + if (EVP_PKEY_CTX_add1_hkdf_info(ctx, + (const unsigned char *)hash_str, + strlen(hash_str)) <= 0) { + errno = ENOKEY; + return -1; + } + } if (EVP_PKEY_CTX_add1_hkdf_info(ctx, - (const unsigned char *)identity, - strlen(identity)) <= 0) { + (const unsigned char *)context, + strlen(context)) <= 0) { errno = ENOKEY; return -1; } @@ -731,9 +745,6 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, _cleanup_hmac_ctx_ HMAC_CTX *hmac_ctx = NULL; const EVP_MD *md; - ENGINE_load_builtin_engines(); - ENGINE_register_all_complete(); - hmac_ctx = HMAC_CTX_new(); if (!hmac_ctx) { errno = ENOMEM; @@ -788,28 +799,18 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, return 0; } -static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, char *identity, - unsigned char *retained, size_t key_len) +static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *retained, size_t key_len, + char *digest, size_t digest_len) { static const char hmac_seed[] = "NVMe-over-Fabrics"; size_t hmac_len; const EVP_MD *md = select_hmac(hmac, &hmac_len); _cleanup_hmac_ctx_ HMAC_CTX *hmac_ctx = NULL; _cleanup_free_ unsigned char *psk_ctx = NULL; - _cleanup_free_ char *enc_ctx = NULL; size_t len; - if (version == 0) { - sprintf(identity, "NVMe%01dR%02d %s %s", - version, hmac, hostnqn, subsysnqn); - return strlen(identity); - } - if (version > 1) { - errno = EINVAL; - return -1; - } - hmac_ctx = HMAC_CTX_new(); if (!hmac_ctx) { errno = ENOMEM; @@ -856,17 +857,19 @@ static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, errno = ENOKEY; return -1; } - enc_ctx = malloc(key_len * 2); - memset(enc_ctx, 0, key_len * 2); - len = base64_encode(psk_ctx, key_len, enc_ctx); + if (key_len * 2 > digest_len) { + errno = EINVAL; + return -1; + } + memset(digest, 0, digest_len); + len = base64_encode(psk_ctx, key_len, digest); if (len < 0) { errno = ENOKEY; return len; } - sprintf(identity, "NVMe%01dR%02d %s %s %s", - version, hmac, hostnqn, subsysnqn, enc_ctx); - return strlen(identity); + return strlen(digest); } + #endif /* !CONFIG_OPENSSL_1 */ #ifdef CONFIG_OPENSSL_3 @@ -961,9 +964,10 @@ int nvme_gen_dhchap_key(char *hostnqn, enum nvme_hmac_alg hmac, return 0; } -static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, - int version, int hmac, char *identity, - unsigned char *retained, size_t key_len) +static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *retained, size_t key_len, + char *digest, size_t digest_len) { static const char hmac_seed[] = "NVMe-over-Fabrics"; size_t hmac_len; @@ -972,21 +976,10 @@ static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, _cleanup_evp_mac_ctx_ EVP_MAC_CTX *mac_ctx = NULL; _cleanup_evp_mac_ EVP_MAC *mac = NULL; char *progq = NULL; - char *digest = NULL; + char *dig = NULL; _cleanup_free_ unsigned char *psk_ctx = NULL; - _cleanup_free_ char *enc_ctx = NULL; size_t len; - if (version == 0) { - sprintf(identity, "NVMe%01dR%02d %s %s", - version, hmac, hostnqn, subsysnqn); - return strlen(identity); - } - if (version > 1) { - errno = EINVAL; - return -1; - } - lib_ctx = OSSL_LIB_CTX_new(); if (!lib_ctx) { errno = ENOMEM; @@ -1005,19 +998,19 @@ static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, } switch (hmac) { case NVME_HMAC_ALG_SHA2_256: - digest = OSSL_DIGEST_NAME_SHA2_256; + dig = OSSL_DIGEST_NAME_SHA2_256; break; case NVME_HMAC_ALG_SHA2_384: - digest = OSSL_DIGEST_NAME_SHA2_384; + dig = OSSL_DIGEST_NAME_SHA2_384; break; default: errno = EINVAL; break; } - if (!digest) + if (!dig) return -1; *p++ = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, - digest, 0); + dig, 0); *p = OSSL_PARAM_construct_end(); psk_ctx = malloc(key_len); @@ -1061,18 +1054,38 @@ static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, errno = EMSGSIZE; return -1; } - enc_ctx = malloc(hmac_len * 2); - memset(enc_ctx, 0, hmac_len * 2); - len = base64_encode(psk_ctx, hmac_len, enc_ctx); + if (hmac_len * 2 > digest_len) { + errno = EINVAL; + return -1; + } + memset(digest, 0, digest_len); + len = base64_encode(psk_ctx, hmac_len, digest); if (len < 0) { errno = ENOKEY; return len; } + return strlen(digest); +} +#endif /* !CONFIG_OPENSSL_3 */ + +static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, + int version, int hmac, char *digest, + char *identity) +{ + if (version == 0) { + sprintf(identity, "NVMe%01dR%02d %s %s", + version, hmac, hostnqn, subsysnqn); + return strlen(identity); + } + if (version > 1) { + errno = EINVAL; + return -1; + } + sprintf(identity, "NVMe%01dR%02d %s %s %s", - version, hmac, hostnqn, subsysnqn, enc_ctx); + version, hmac, hostnqn, subsysnqn, digest); return strlen(identity); } -#endif /* !CONFIG_OPENSSL_3 */ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, char *identity, int version, @@ -1080,6 +1093,8 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, unsigned char *psk, int key_len) { _cleanup_free_ unsigned char *retained = NULL; + _cleanup_free_ char *digest = NULL; + char *context = identity; int ret = -1; if (!hostnqn || !subsysnqn || !identity || !psk) { @@ -1095,11 +1110,28 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, ret = derive_retained_key(hmac, hostnqn, configured, retained, key_len); if (ret < 0) return ret; + + if (version == 1) { + size_t digest_len = 2 * key_len; + + digest = malloc(digest_len); + if (!digest) { + errno = ENOMEM; + return -1; + } + ret = derive_psk_digest(hostnqn, subsysnqn, version, hmac, + retained, key_len, + digest, digest_len); + if (ret) + return ret; + context = digest; + } ret = gen_tls_identity(hostnqn, subsysnqn, version, hmac, - identity, retained, key_len); + digest, identity); if (ret < 0) return ret; - return derive_tls_key(hmac, identity, retained, psk, key_len); + return derive_tls_key(version, hmac, context, retained, + psk, key_len); } static size_t nvme_identity_len(int hmac, int version, const char *hostnqn, @@ -1355,6 +1387,24 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, return key; } +long nvme_revoke_tls_key(const char *keyring, const char *key_type, + const char *identity) +{ + key_serial_t keyring_id; + long key; + + keyring_id = nvme_lookup_keyring(keyring); + if (keyring_id == 0) { + errno = ENOKEY; + return 0; + } + + key = keyctl_search(keyring_id, key_type, identity, 0); + if (key < 0) + return -1; + + return keyctl_revoke(key); +} #else long nvme_lookup_keyring(const char *keyring) { @@ -1419,6 +1469,15 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, errno = ENOTSUP; return -1; } + +long nvme_revoke_tls_key(const char *keyring, const char *key_type, + const char *identity) +{ + nvme_msg(NULL, LOG_ERR, "key operations not supported; " + "recompile with keyutils support.\n"); + errno = ENOTSUP; + return -1; +} #endif long nvme_insert_tls_key(const char *keyring, const char *key_type, @@ -1513,10 +1572,10 @@ unsigned char *nvme_import_tls_key(const char *encoded_key, int *key_len, return NULL; } crc = crc32(crc, decoded_key, decoded_len); - key_crc = ((u_int32_t)decoded_key[decoded_len]) | - ((u_int32_t)decoded_key[decoded_len + 1] << 8) | - ((u_int32_t)decoded_key[decoded_len + 2] << 16) | - ((u_int32_t)decoded_key[decoded_len + 3] << 24); + key_crc = ((uint32_t)decoded_key[decoded_len]) | + ((uint32_t)decoded_key[decoded_len + 1] << 8) | + ((uint32_t)decoded_key[decoded_len + 2] << 16) | + ((uint32_t)decoded_key[decoded_len + 3] << 24); if (key_crc != crc) { nvme_msg(NULL, LOG_ERR, "CRC mismatch (key %08x, crc %08x)", key_crc, crc); |