1
0
Fork 0

Adding upstream version 1.11.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-16 10:51:02 +01:00
parent 42ce9d48e1
commit d21edaa886
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
946 changed files with 4896 additions and 1272 deletions

52
test/config/config-diff.sh Normal file → Executable file
View file

@ -1,24 +1,48 @@
#!/bin/bash -e
# SPDX-License-Identifier: LGPL-2.1-or-later
BUILD_DIR=$1
CONFIG_DUMP=$2
SYSDIR_INPUT=$3
CONFIG_JSON=$4
EXPECTED_OUTPUT=$5
positional_args=()
sysfs_tar=""
config_json=""
ACTUAL_OUTPUT="${BUILD_DIR}"/$(basename "${EXPECTED_OUTPUT}")
while [[ $# -gt 0 ]]; do
case $1 in
--sysfs-tar)
sysfs_tar=$2
shift 1
;;
--config-json)
config_json=$2
shift 1
;;
*)
positional_args+=("$1")
shift
;;
esac
done
TEST_NAME="$(basename -s .tar.xz $SYSDIR_INPUT)"
TEST_DIR="$BUILD_DIR/$TEST_NAME"
set -- "${positional_args[@]}"
rm -rf "${TEST_DIR}"
mkdir "${TEST_DIR}"
tar -x -f "${SYSDIR_INPUT}" -C "${TEST_DIR}"
test_binary="$1"
build_dir="$2"
expected_output="$3"
LIBNVME_SYSFS_PATH="$TEST_DIR" \
sysfs_path=""
if [[ -n "${sysfs_tar}" ]]; then
test_name="$(basename -s .tar.xz ${sysfs_tar})"
sysfs_path="${build_dir}/${test_name}"
rm -rf "${sysfs_path}"
mkdir "${sysfs_path}"
tar -x -f "${sysfs_tar}" -C "${sysfs_path}"
fi
output="${build_dir}"/$(basename "${expected_output}")
LIBNVME_SYSFS_PATH="${sysfs_path}" \
LIBNVME_HOSTNQN=nqn.2014-08.org.nvmexpress:uuid:ce4fee3e-c02c-11ee-8442-830d068a36c6 \
LIBNVME_HOSTID=ce4fee3e-c02c-11ee-8442-830d068a36c6 \
"${CONFIG_DUMP}" "${CONFIG_JSON}" > "${ACTUAL_OUTPUT}" || echo "test failed"
"${test_binary}" "${config_json}" > "${output}" || echo "test failed"
diff -u "${EXPECTED_OUTPUT}" "${ACTUAL_OUTPUT}"
diff -u "${expected_output}" "${output}"

View file

@ -0,0 +1,21 @@
[
{
"hostnqn":"nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36",
"hostid":"2cd2c43b-a90a-45c1-a8cd-86b33ab273b6",
"subsystems":[
{
"nqn":"nqn.io-1",
"ports":[
{
"transport":"tcp",
"traddr":"192.168.154.148",
"trsvcid":"4420",
"dhchap_key":"none",
"tls":true,
"tls_key":"NVMeTLSkey-1:01:Hhc5sFjwSZ6w5hPY19tqprajYtuYci3tN+Z2wGViDk3rpSR+:"
}
]
}
]
}
]

View file

@ -0,0 +1,21 @@
[
{
"hostnqn":"nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36",
"hostid":"2cd2c43b-a90a-45c1-a8cd-86b33ab273b6",
"subsystems":[
{
"nqn":"nqn.io-1",
"ports":[
{
"transport":"tcp",
"traddr":"192.168.154.148",
"trsvcid":"4420",
"dhchap_key":"none",
"tls":true,
"tls_key":"NVMeTLSkey-1:01:Hhc5sFjwSZ6w5hPY19tqprajYtuYci3tN+Z2wGViDk3rpSR+:"
}
]
}
]
}
]

View file

@ -0,0 +1,22 @@
[
{
"hostnqn":"nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36",
"hostid":"2cd2c43b-a90a-45c1-a8cd-86b33ab273b6",
"subsystems":[
{
"nqn":"nqn.io-1",
"ports":[
{
"transport":"tcp",
"traddr":"192.168.154.148",
"trsvcid":"4420",
"dhchap_key":"none",
"tls":true,
"tls_psk_identity":"NVMe1R01 nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 nqn.io-1 QMFIifx2SCVnlE2hc4MQb0r+2g56x3G7P6jJtDiYK+I=",
"tls_key":"NVMeTLSkey-1:01:Hhc5sFjwSZ6w5hPY19tqprajYtuYci3tN+Z2wGViDk3rpSR+:"
}
]
}
]
}
]

View file

@ -0,0 +1,21 @@
[
{
"hostnqn":"nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36",
"hostid":"2cd2c43b-a90a-45c1-a8cd-86b33ab273b6",
"subsystems":[
{
"nqn":"nqn.io-1",
"ports":[
{
"transport":"tcp",
"traddr":"192.168.154.148",
"trsvcid":"4420",
"dhchap_key":"none",
"tls":true,
"tls_key":"NVMeTLSkey-1:01:Hhc5sFjwSZ6w5hPY19tqprajYtuYci3tN+Z2wGViDk3rpSR+:"
}
]
}
]
}
]

View file

@ -7,6 +7,10 @@
diff = find_program('diff', required : false)
if diff.found()
srcdir = meson.current_source_dir()
builddir = meson.current_build_dir()
config_dump = executable(
'test-config-dump',
['config-dump.c'],
@ -26,11 +30,11 @@ if diff.found()
t_file,
config_diff,
args : [
meson.current_build_dir(),
config_dump.full_path(),
files('data'/t_file + '.tar.xz'),
files('data'/t_file + '.json'),
files('data'/t_file + '.out'),
builddir,
srcdir + '/data/' + t_file + '.out',
'--sysfs-tar', srcdir + '/data/' + t_file + '.tar.xz',
'--config-json', srcdir + '/data/' + t_file + '.json',
],
depends : config_dump,
)
@ -47,13 +51,38 @@ if diff.found()
'hostnqn-order',
config_diff,
args : [
meson.current_build_dir(),
test_hostnqn_order.full_path(),
files('data/hostnqn-order.tar.xz'),
files('data/hostnqn-order.json'),
files('data/hostnqn-order.out'),
builddir,
srcdir + '/data/hostnqn-order.out',
'--sysfs-tar', srcdir + '/data/hostnqn-order.tar.xz',
'--config-json', srcdir + '/data/hostnqn-order.json',
],
depends : test_hostnqn_order,
)
test_psk_json = executable(
'test-psk-json',
['psk-json.c'],
dependencies: libnvme_dep,
include_directories: [incdir],
)
config_data = [
'tls_key-1',
'tls_key-2',
]
foreach t_file : config_data
test(
'psk-json-' + t_file,
config_diff,
args : [
test_psk_json.full_path(),
builddir,
srcdir + '/data/' + t_file + '.out',
'--config-json', srcdir + '/data/' + t_file + '.json',
],
depends : test_psk_json,
)
endforeach
endif

89
test/config/psk-json.c Normal file
View file

@ -0,0 +1,89 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* This file is part of libnvme.
* Copyright (c) 2024 Daniel Wagner, SUSE LLC
*/
#include "nvme/linux.h"
#include "nvme/tree.h"
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <errno.h>
#include <libnvme.h>
static bool import_export_key(nvme_ctrl_t c)
{
unsigned char version, hmac, *key;
char *encoded_key;
size_t len;
key = nvme_import_tls_key_versioned(nvme_ctrl_get_tls_key(c),
&version, &hmac, &len);
if (!key) {
printf("ERROR: nvme_import_tls_key_versioned failed with %d\n",
errno);
return false;
}
encoded_key = nvme_export_tls_key_versioned(version, hmac, key, len);
free(key);
if (!encoded_key) {
printf("ERROR: nvme_export_tls_key_versioned failed with %d\n",
errno);
return false;
}
nvme_ctrl_set_tls_key(c, encoded_key);
free(encoded_key);
return true;
}
static bool psk_json_test(char *file)
{
bool pass = false;
nvme_root_t r;
nvme_host_t h;
nvme_subsystem_t s;
nvme_ctrl_t c;
int err;
r = nvme_create_root(stderr, LOG_ERR);
if (!r)
return false;
err = nvme_read_config(r, file);
if (err)
goto out;
nvme_for_each_host(r, h)
nvme_for_each_subsystem(h, s)
nvme_subsystem_for_each_ctrl(s, c)
if (!import_export_key(c))
goto out;
err = nvme_dump_config(r);
if (err)
goto out;
pass = true;
out:
nvme_free_tree(r);
return pass;
}
int main(int argc, char *argv[])
{
bool pass;
pass = psk_json_test(argv[1]);
fflush(stdout);
exit(pass ? EXIT_SUCCESS : EXIT_FAILURE);
}

View file

@ -104,6 +104,15 @@ if conf.get('HAVE_NETDB')
test('util', test_util)
endif
psk = executable(
'test-psk',
['psk.c'],
dependencies: libnvme_dep,
include_directories: [incdir, internal_incdir]
)
test('psk', psk)
subdir('ioctl')
subdir('nbft')

View file

@ -1908,6 +1908,103 @@ static void test_endpoint_quirk_probe(struct nvme_mi_ep *ep)
assert(rc == 0);
}
struct req_dlen_doff_data {
enum {
DATA_DIR_IN,
DATA_DIR_OUT,
} direction;
unsigned int req_len;
unsigned int resp_len;
unsigned int exp_doff;
};
static int test_admin_dlen_doff_cb(struct nvme_mi_ep *ep,
struct nvme_mi_req *req,
struct nvme_mi_resp *resp,
void *data)
{
struct req_dlen_doff_data *args = data;
__u8 *hdr = (__u8 *)req->hdr;
__u32 dlen, doff;
dlen = hdr[35] << 24 | hdr[34] << 16 | hdr[33] << 8 | hdr[32];
doff = hdr[39] << 24 | hdr[38] << 16 | hdr[37] << 8 | hdr[36];
if (args->direction == DATA_DIR_OUT) {
assert(dlen == args->req_len);
assert(dlen == req->data_len);
assert(doff == 0);
} else {
assert(dlen == args->resp_len);
assert(dlen == resp->data_len);
assert(doff == args->exp_doff);
}
/* minimal valid response */
hdr = (__u8 *)resp->hdr;
hdr[4] = 0x00; /* status: success */
test_transport_resp_calc_mic(resp);
return 0;
}
/* Check dlen value on admin_xfer requests that include data. */
static void test_admin_dlen_doff_req(struct nvme_mi_ep *ep)
{
struct {
struct nvme_mi_admin_req_hdr hdr;
unsigned char data[4096];
} admin_req = { 0 };
struct nvme_mi_admin_resp_hdr admin_resp = { 0 };
struct req_dlen_doff_data data = { 0 };
size_t resp_sz = 0;
nvme_mi_ctrl_t ctrl;
int rc;
data.direction = DATA_DIR_OUT;
data.req_len = sizeof(admin_req.data);
test_set_transport_callback(ep, test_admin_dlen_doff_cb, &data);
ctrl = nvme_mi_init_ctrl(ep, 0);
assert(ctrl);
rc = nvme_mi_admin_xfer(ctrl, &admin_req.hdr, sizeof(admin_req.data),
&admin_resp, 0, &resp_sz);
assert(!rc);
};
/* Check dlen value on admin_xfer requests that return data in their response.
*/
static void test_admin_dlen_doff_resp(struct nvme_mi_ep *ep)
{
struct {
struct nvme_mi_admin_resp_hdr hdr;
unsigned char data[4096];
} admin_resp = { 0 };
struct nvme_mi_admin_req_hdr admin_req = { 0 };
struct req_dlen_doff_data data = { 0 };
nvme_mi_ctrl_t ctrl;
size_t resp_sz;
int rc;
data.direction = DATA_DIR_IN;
data.resp_len = sizeof(admin_resp.data);
resp_sz = sizeof(admin_resp.data);
test_set_transport_callback(ep, test_admin_dlen_doff_cb, &data);
ctrl = nvme_mi_init_ctrl(ep, 0);
assert(ctrl);
rc = nvme_mi_admin_xfer(ctrl, &admin_req, 0, &admin_resp.hdr, 0,
&resp_sz);
assert(!rc);
};
#define DEFINE_TEST(name) { #name, test_ ## name }
struct test {
const char *name;
@ -1950,6 +2047,8 @@ struct test {
DEFINE_TEST(admin_sanitize_nvm),
DEFINE_TEST(admin_get_log_split),
DEFINE_TEST(endpoint_quirk_probe),
DEFINE_TEST(admin_dlen_doff_req),
DEFINE_TEST(admin_dlen_doff_resp),
};
static void run_test(struct test *test, FILE *logfd, nvme_mi_ep_t ep)

225
test/psk.c Normal file
View file

@ -0,0 +1,225 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* This file is part of libnvme.
* Copyright (c) 2024 Daniel Wagner, SUSE Software Solutions
*/
#include "nvme/linux.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ccan/array_size/array_size.h>
#include <libnvme.h>
static int test_rc;
struct test_data {
const unsigned char configured_psk[48];
size_t psk_length;
unsigned char version;
unsigned char hmac;
const char *exported_psk;
};
static struct test_data test_data[] = {
{ { 0x55, 0x12, 0xDB, 0xB6,
0x73, 0x7D, 0x01, 0x06,
0xF6, 0x59, 0x75, 0xB7,
0x73, 0xDF, 0xB0, 0x11,
0xFF, 0xC3, 0x44, 0xBC,
0xF4, 0x42, 0xE2, 0xDD,
0x6D, 0x8B, 0xC4, 0x87,
0x0B, 0x5D, 0x5B, 0x03},
32, 1, NVME_HMAC_ALG_NONE,
"NVMeTLSkey-1:00:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwNf9LrZ:" },
{ { 0x55, 0x12, 0xDB, 0xB6,
0x73, 0x7D, 0x01, 0x06,
0xF6, 0x59, 0x75, 0xB7,
0x73, 0xDF, 0xB0, 0x11,
0xFF, 0xC3, 0x44, 0xBC,
0xF4, 0x42, 0xE2, 0xDD,
0x6D, 0x8B, 0xC4, 0x87,
0x0B, 0x5D, 0x5B, 0x03},
32, 1, NVME_HMAC_ALG_SHA2_256,
"NVMeTLSkey-1:01:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwNf9LrZ:" },
{ { 0x55, 0x12, 0xDB, 0xB6,
0x73, 0x7D, 0x01, 0x06,
0xF6, 0x59, 0x75, 0xB7,
0x73, 0xDF, 0xB0, 0x11,
0xFF, 0xC3, 0x44, 0xBC,
0xF4, 0x42, 0xE2, 0xDD,
0x6D, 0x8B, 0xC4, 0x87,
0x0B, 0x5D, 0x5B, 0x03,
0xFF, 0xC3, 0x44, 0xBC,
0xF4, 0x42, 0xE2, 0xDD,
0x6D, 0x8B, 0xC4, 0x87,
0x0B, 0x5D, 0x5B, 0x03},
48, 1, NVME_HMAC_ALG_SHA2_384,
"NVMeTLSkey-1:02:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwP/w0S89ELi3W2LxIcLXVsDn8kXZQ==:" },
};
static void check_str(const char *exp, const char *res)
{
if (!strcmp(res, exp))
return;
printf("ERROR: got '%s', expected '%s'\n", res, exp);
test_rc = 1;
}
static void export_test(struct test_data *test)
{
char *psk;
if (test->version != 1 ||
!(test->hmac == NVME_HMAC_ALG_SHA2_256 ||
test->hmac == NVME_HMAC_ALG_SHA2_384))
return;
printf("test nvme_export_tls_key hmac %d %s\n",
test->hmac, test->exported_psk);
psk = nvme_export_tls_key(test->configured_psk, test->psk_length);
if (!psk) {
test_rc = 1;
printf("ERROR: nvme_export_tls_key() failed with %d\n", errno);
return;
}
check_str(test->exported_psk, psk);
free(psk);
}
static void import_test(struct test_data *test)
{
unsigned char *psk;
int psk_length;
unsigned int hmac;
if (test->version != 1 ||
!(test->hmac == NVME_HMAC_ALG_SHA2_256 ||
test->hmac == NVME_HMAC_ALG_SHA2_384))
return;
printf("test nvme_import_tls_key hmac %d %s\n",
test->hmac, test->exported_psk);
psk = nvme_import_tls_key(test->exported_psk, &psk_length, &hmac);
if (!psk) {
test_rc = 1;
printf("ERROR: nvme_import_tls_key() failed with %d\n", errno);
return;
}
if (test->hmac != hmac) {
test_rc = 1;
printf("ERROR: hmac parsing failed\n");
goto out;
}
if (test->psk_length != psk_length) {
test_rc = 1;
printf("ERROR: length parsing failed\n");
goto out;
}
if (memcmp(test->configured_psk, psk, psk_length)) {
test_rc = 1;
printf("ERROR: parsing psk failed\n");
}
out:
free(psk);
}
static void export_versioned_test(struct test_data *test)
{
char *psk;
if (test->version != 1)
return;
printf("test nvme_export_tls_key_versioned hmac %d %s\n",
test->hmac, test->exported_psk);
psk = nvme_export_tls_key_versioned(test->version, test->hmac,
test->configured_psk,
test->psk_length);
if (!psk) {
test_rc = 1;
printf("ERROR: nvme_export_tls_key_versioned() failed with %d\n",
errno);
return;
}
check_str(test->exported_psk, psk);
free(psk);
}
static void import_versioned_test(struct test_data *test)
{
unsigned char *psk;
unsigned char version;
unsigned char hmac;
size_t psk_length;
if (test->version != 1)
return;
printf("test nvme_import_tls_key_versioned hmac %d %s\n",
test->hmac, test->exported_psk);
psk = nvme_import_tls_key_versioned(test->exported_psk, &version,
&hmac, &psk_length);
if (!psk) {
test_rc = 1;
printf("ERROR: nvme_import_tls_key_versioned() failed with %d\n",
errno);
return;
}
if (test->version != version) {
test_rc = 1;
printf("ERROR: version parsing failed\n");
goto out;
}
if (test->hmac != hmac) {
test_rc = 1;
printf("ERROR: hmac parsing failed\n");
goto out;
}
if (test->psk_length != psk_length) {
test_rc = 1;
printf("ERROR: length parsing failed\n");
goto out;
}
if (memcmp(test->configured_psk, psk, psk_length)) {
test_rc = 1;
printf("ERROR: parsing psk failed\n");
}
out:
free(psk);
}
int main(void)
{
for (int i = 0; i < ARRAY_SIZE(test_data); i++)
export_test(&test_data[i]);
for (int i = 0; i < ARRAY_SIZE(test_data); i++)
import_test(&test_data[i]);
for (int i = 0; i < ARRAY_SIZE(test_data); i++)
export_versioned_test(&test_data[i]);
for (int i = 0; i < ARRAY_SIZE(test_data); i++)
import_versioned_test(&test_data[i]);
return test_rc ? EXIT_FAILURE : EXIT_SUCCESS;
}