diff --git a/src/libnvme.map b/src/libnvme.map index bf2d5a378..af722218a 100644 --- a/src/libnvme.map +++ b/src/libnvme.map @@ -3,6 +3,8 @@ LIBNVME_UNRELEASED { global: nvme_set_etdas; nvme_clear_etdas; + nvme_insert_tls_key_compat; + nvme_generate_tls_key_identity_compat; }; LIBNVME_1_14 { diff --git a/src/nvme/linux.c b/src/nvme/linux.c index cdbb91254..7d06858a1 100644 --- a/src/nvme/linux.c +++ b/src/nvme/linux.c @@ -600,6 +600,17 @@ static int derive_retained_key(int hmac, const char *hostnqn, return -1; } +static int derive_retained_key_compat(int hmac, const char *hostnqn, + unsigned char *generated, + unsigned char *retained, + size_t key_len) +{ + nvme_msg(NULL, LOG_ERR, "NVMe TLS is not supported; " + "recompile with OpenSSL support.\n"); + errno = ENOTSUP; + return -1; +} + static int derive_psk_digest(const char *hostnqn, const char *subsysnqn, int version, int cipher, unsigned char *retained, size_t key_len, @@ -620,6 +631,16 @@ static int derive_tls_key(int version, int cipher, const char *context, errno = ENOTSUP; return -1; } + +static int derive_tls_key_compat(int version, int cipher, const char *context, + unsigned char *retained, + unsigned char *psk, size_t key_len) +{ + nvme_msg(NULL, LOG_ERR, "NVMe TLS is not supported; " + "recompile with OpenSSL support.\n"); + errno = ENOTSUP; + return -1; +} #else /* CONFIG_OPENSSL */ static unsigned char default_hmac(size_t key_len) { @@ -665,6 +686,46 @@ static DEFINE_CLEANUP_FUNC( cleanup_evp_pkey_ctx, EVP_PKEY_CTX *, EVP_PKEY_CTX_free) #define _cleanup_evp_pkey_ctx_ __cleanup__(cleanup_evp_pkey_ctx) +/* + * hkdf_info_printf() + * + * Helper function to append variable length label and context to an HkdfLabel + * + * RFC 8446 (TLS 1.3) Section 7.1 defines the HKDF-Expand-Label function as a + * specialization of the HKDF-Expand function (RFC 5869), where the info + * parameter is structured as an HkdfLabel. + * + * An HkdfLabel structure includes two variable length vectors (label and + * context) which must be preceded by their content length as per RFC 8446 + * Section 3.4 (and not NUL terminated as per Section 7.1). Additionally, + * HkdfLabel.label must begin with "tls13 " + * + * Returns the number of bytes appended to the HKDF info buffer, or -1 on an + * error. + */ +__attribute__((format(printf, 2, 3))) +static int hkdf_info_printf(EVP_PKEY_CTX *ctx, char *fmt, ...) +{ + _cleanup_free_ char *str; + uint8_t len; + int ret; + va_list myargs; + + va_start(myargs, fmt); + ret = vasprintf(&str, fmt, myargs); + va_end(myargs); + if (ret < 0) + return ret; + if (ret > 255) + return -1; + len = ret; + if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)&len, 1) <= 0) + return -1; + if (EVP_PKEY_CTX_add1_hkdf_info(ctx, (unsigned char *)str, len) <= 0) + return -1; + return (ret + 1); +} + /* * derive_retained_key() * @@ -697,6 +758,67 @@ static int derive_retained_key(int hmac, const char *hostnqn, unsigned char *configured, unsigned char *retained, size_t key_len) +{ + _cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL; + uint16_t length = htons(key_len & 0xFFFF); + const EVP_MD *md; + size_t hmac_len; + + if (hmac == NVME_HMAC_ALG_NONE) { + memcpy(retained, configured, key_len); + return key_len; + } + + md = select_hmac(hmac, &hmac_len); + if (!md || !hmac_len) { + errno = EINVAL; + return -1; + } + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + if (!ctx) { + errno = ENOMEM; + return -1; + } + + if (EVP_PKEY_derive_init(ctx) <= 0) { + errno = ENOMEM; + return -1; + } + if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) { + errno = ENOKEY; + return -1; + } + if (EVP_PKEY_CTX_set1_hkdf_key(ctx, configured, key_len) <= 0) { + errno = ENOKEY; + return -1; + } + if (EVP_PKEY_CTX_add1_hkdf_info(ctx, + (const unsigned char *)&length, 2) <= 0) { + errno = ENOKEY; + return -1; + } + if (hkdf_info_printf(ctx, "tls13 HostNQN") <= 0) { + errno = ENOKEY; + return -1; + } + if (hkdf_info_printf(ctx, "%s", hostnqn) <= 0) { + errno = ENOKEY; + return -1; + } + + if (EVP_PKEY_derive(ctx, retained, &key_len) <= 0) { + errno = ENOKEY; + return -1; + } + + return key_len; +} + +static int derive_retained_key_compat(int hmac, const char *hostnqn, + unsigned char *configured, + unsigned char *retained, + size_t key_len) { _cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL; uint16_t length = key_len & 0xFFFF; @@ -783,9 +905,78 @@ static int derive_retained_key(int hmac, const char *hostnqn, * * and the value '0' is invalid here. */ + static int derive_tls_key(int version, unsigned char cipher, const char *context, unsigned char *retained, unsigned char *psk, size_t key_len) +{ + _cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL; + uint16_t length = htons(key_len & 0xFFFF); + const EVP_MD *md; + size_t hmac_len; + + md = select_hmac(cipher, &hmac_len); + if (!md || !hmac_len) { + errno = EINVAL; + return -1; + } + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); + if (!ctx) { + errno = ENOMEM; + return -1; + } + + if (EVP_PKEY_derive_init(ctx) <= 0) { + errno = ENOMEM; + return -1; + } + if (EVP_PKEY_CTX_set_hkdf_md(ctx, md) <= 0) { + errno = ENOKEY; + return -1; + } + if (EVP_PKEY_CTX_set1_hkdf_key(ctx, retained, key_len) <= 0) { + errno = ENOKEY; + return -1; + } + if (EVP_PKEY_CTX_add1_hkdf_info(ctx, + (const unsigned char *)&length, 2) <= 0) { + errno = ENOKEY; + return -1; + } + if (hkdf_info_printf(ctx, "tls13 nvme-tls-psk") <= 0) { + errno = ENOKEY; + return -1; + } + switch (version) { + case 0: + if (hkdf_info_printf(ctx, "%s", context) <= 0) { + errno = ENOKEY; + return -1; + } + break; + case 1: + if (hkdf_info_printf(ctx, "%02d %s", cipher, context) <= 0) { + errno = ENOKEY; + return -1; + } + break; + default: + errno = ENOKEY; + return -1; + } + + if (EVP_PKEY_derive(ctx, psk, &key_len) <= 0) { + errno = ENOKEY; + return -1; + } + + return key_len; +} + +static int derive_tls_key_compat(int version, unsigned char cipher, + const char *context, unsigned char *retained, + unsigned char *psk, size_t key_len) { _cleanup_evp_pkey_ctx_ EVP_PKEY_CTX *ctx = NULL; uint16_t length = key_len & 0xFFFF; @@ -1074,7 +1265,7 @@ static int gen_tls_identity(const char *hostnqn, const char *subsysnqn, static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, char *identity, int version, int hmac, unsigned char *configured, - unsigned char *psk, int key_len) + unsigned char *psk, int key_len, bool compat) { _cleanup_free_ unsigned char *retained = NULL; _cleanup_free_ char *digest = NULL; @@ -1092,7 +1283,12 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, errno = ENOMEM; return -1; } - ret = derive_retained_key(hmac, hostnqn, configured, retained, key_len); + if (compat) + ret = derive_retained_key_compat(hmac, hostnqn, configured, + retained, key_len); + else + ret = derive_retained_key(hmac, hostnqn, configured, + retained, key_len); if (ret < 0) return ret; @@ -1120,6 +1316,9 @@ static int derive_nvme_keys(const char *hostnqn, const char *subsysnqn, digest, identity); if (ret < 0) return ret; + if (compat) + return derive_tls_key_compat(version, cipher, context, retained, + psk, key_len); return derive_tls_key(version, cipher, context, retained, psk, key_len); } @@ -1156,20 +1355,64 @@ char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, int ret = -1; identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn); - if (identity_len < 0) + if (identity_len < 0) { + errno = EINVAL; return NULL; + } identity = malloc(identity_len); - if (!identity) + if (!identity) { + errno = ENOMEM; return NULL; + } psk = malloc(key_len); - if (!psk) + if (!psk) { + errno = ENOMEM; + goto out_free_identity; + } + + memset(psk, 0, key_len); + ret = derive_nvme_keys(hostnqn, subsysnqn, identity, version, hmac, + configured_key, psk, key_len, false); +out_free_identity: + if (ret < 0) { + free(identity); + identity = NULL; + } + return identity; +} + +char *nvme_generate_tls_key_identity_compat(const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len) +{ + _cleanup_free_ unsigned char *psk = NULL; + char *identity; + ssize_t identity_len; + int ret = -1; + + identity_len = nvme_identity_len(hmac, version, hostnqn, subsysnqn); + if (identity_len < 0) { + errno = EINVAL; + return NULL; + } + + identity = malloc(identity_len); + if (!identity) { + errno = ENOMEM; + return NULL; + } + + psk = malloc(key_len); + if (!psk) { + errno = ENOMEM; goto out_free_identity; + } memset(psk, 0, key_len); ret = derive_nvme_keys(hostnqn, subsysnqn, identity, version, hmac, - configured_key, psk, key_len); + configured_key, psk, key_len, true); out_free_identity: if (ret < 0) { free(identity); @@ -1337,10 +1580,11 @@ int nvme_scan_tls_keys(const char *keyring, nvme_scan_tls_keys_cb_t cb, return ret; } -static long __nvme_insert_tls_key_versioned(key_serial_t keyring_id, const char *key_type, - const char *hostnqn, const char *subsysnqn, - int version, int hmac, - unsigned char *configured_key, int key_len) +static long __nvme_insert_tls_key(key_serial_t keyring_id, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len, + bool compat) { _cleanup_free_ unsigned char *psk = NULL; _cleanup_free_ char *identity = NULL; @@ -1366,7 +1610,7 @@ static long __nvme_insert_tls_key_versioned(key_serial_t keyring_id, const char } memset(psk, 0, key_len); ret = derive_nvme_keys(hostnqn, subsysnqn, identity, version, hmac, - configured_key, psk, key_len); + configured_key, psk, key_len, compat); if (ret != key_len) { errno = ENOKEY; return 0; @@ -1394,10 +1638,33 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, ret = nvme_set_keyring(keyring_id); if (ret < 0) return 0; - return __nvme_insert_tls_key_versioned(keyring_id, key_type, - hostnqn, subsysnqn, - version, hmac, - configured_key, key_len); + return __nvme_insert_tls_key(keyring_id, key_type, + hostnqn, subsysnqn, + version, hmac, + configured_key, key_len, false); +} + +long nvme_insert_tls_key_compat(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len) +{ + key_serial_t keyring_id; + int ret; + + keyring_id = nvme_lookup_keyring(keyring); + if (keyring_id == 0) { + errno = ENOKEY; + return 0; + } + + ret = nvme_set_keyring(keyring_id); + if (ret < 0) + return 0; + return __nvme_insert_tls_key(keyring_id, key_type, + hostnqn, subsysnqn, + version, hmac, + configured_key, key_len, true); } long nvme_revoke_tls_key(const char *keyring, const char *key_type, @@ -1419,7 +1686,7 @@ long nvme_revoke_tls_key(const char *keyring, const char *key_type, return keyctl_revoke(key); } -static long __nvme_insert_tls_key(long keyring_id, +static long __nvme_import_tls_key(long keyring_id, const char *hostnqn, const char *subsysnqn, const char *identity, const char *key) { @@ -1440,10 +1707,10 @@ static long __nvme_insert_tls_key(long keyring_id, * configured key. Derive a new key and load the newly * created key into the keystore. */ - return __nvme_insert_tls_key_versioned(keyring_id, "psk", - hostnqn, subsysnqn, - version, hmac, - key_data, key_len); + return __nvme_insert_tls_key(keyring_id, "psk", + hostnqn, subsysnqn, + version, hmac, + key_data, key_len, false); } return nvme_update_key(keyring_id, "psk", identity, @@ -1498,7 +1765,7 @@ int __nvme_import_keys_from_config(nvme_host_t h, nvme_ctrl_t c, id = nvme_lookup_key("psk", identity); if (!id) - id = __nvme_insert_tls_key(kr_id, hostnqn, + id = __nvme_import_tls_key(kr_id, hostnqn, subsysnqn, identity, key); if (id <= 0) { diff --git a/src/nvme/linux.h b/src/nvme/linux.h index 330fa9fd3..3b438720d 100644 --- a/src/nvme/linux.h +++ b/src/nvme/linux.h @@ -400,6 +400,32 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, int version, int hmac, unsigned char *configured_key, int key_len); +/** + * nvme_insert_tls_key_compat() - Derive and insert TLS key + * @keyring: Keyring to use + * @key_type: Type of the resulting key + * @hostnqn: Host NVMe Qualified Name + * @subsysnqn: Subsystem NVMe Qualified Name + * @version: Key version to use + * @hmac: HMAC algorithm + * @configured_key: Configured key data to derive the key from + * @key_len: Length of @configured_key + * + * Derives a 'retained' TLS key as specified in NVMe TCP 1.0a (if + * @version s set to '0') or NVMe TP8028 (if @version is set to '1) and + * stores it as type @key_type in the keyring specified by @keyring. + * This version differs from @nvme_insert_tls_key_versioned() in that it + * uses the original implementation for HKDF Expand-Label which does not + * prefix the 'info' and 'label' strings with the length. + * + * Return: The key serial number if the key could be inserted into + * the keyring or 0 with errno otherwise. + */ +long nvme_insert_tls_key_compat(const char *keyring, const char *key_type, + const char *hostnqn, const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, int key_len); + /** * nvme_generate_tls_key_identity() - Generate the TLS key identity * @hostnqn: Host NVMe Qualified Name @@ -413,12 +439,37 @@ long nvme_insert_tls_key_versioned(const char *keyring, const char *key_type, * generate the corresponding TLs identity. * * Return: The string containing the TLS identity. It is the responsibility - * of the caller to free the returned string. + * of the caller to free the returned string. On error NULL is returned with + * errno set. */ char *nvme_generate_tls_key_identity(const char *hostnqn, const char *subsysnqn, int version, int hmac, unsigned char *configured_key, int key_len); +/** + * nvme_generate_tls_key_identity_compat() - Generate the TLS key identity + * @hostnqn: Host NVMe Qualified Name + * @subsysnqn: Subsystem NVMe Qualified Name + * @version: Key version to use + * @hmac: HMAC algorithm + * @configured_key: Configured key data to derive the key from + * @key_len: Length of @configured_key + * + * Derives a 'retained' TLS key as specified in NVMe TCP and + * generate the corresponding TLs identity. This version differs + * from @nvme_generate_tls_key_identity() in that it uses the original + * implementation for HKDF-Expand-Label which does not prefix the 'info' + * and 'label' string with the length. + * + * Return: The string containing the TLS identity. It is the responsibility + * of the caller to free the returned string. + */ +char *nvme_generate_tls_key_identity_compat(const char *hostnqn, + const char *subsysnqn, + int version, int hmac, + unsigned char *configured_key, + int key_len); + /** * nvme_revoke_tls_key() - Revoke TLS key from keyring * @keyring: Keyring to use diff --git a/test/psk.c b/test/psk.c index 02cb6d813..c9112e9ee 100644 --- a/test/psk.c +++ b/test/psk.c @@ -15,7 +15,7 @@ static int test_rc; -struct test_data { +struct test_data_psk { const unsigned char configured_psk[48]; size_t psk_length; unsigned char version; @@ -23,7 +23,7 @@ struct test_data { const char *exported_psk; }; -static struct test_data test_data[] = { +static struct test_data_psk test_data_psk[] = { { { 0x55, 0x12, 0xDB, 0xB6, 0x73, 0x7D, 0x01, 0x06, 0xF6, 0x59, 0x75, 0xB7, @@ -60,6 +60,74 @@ static struct test_data test_data[] = { "NVMeTLSkey-1:02:VRLbtnN9AQb2WXW3c9+wEf/DRLz0QuLdbYvEhwtdWwP/w0S89ELi3W2LxIcLXVsDn8kXZQ==:" }, }; +struct test_data_identity { + const unsigned char configured_psk[48]; + size_t psk_length; + unsigned char version; + unsigned char hmac; + const char *hostnqn; + const char *subsysnqn; + const char *identity; +}; + +static struct test_data_identity test_data_identity[] = { + { { 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, + "nqn.psk-test-host", "nqn.psk-test-subsys", + "NVMe1R01 nqn.psk-test-host nqn.psk-test-subsys iSbjiStwJ/1TrTvDlt2fjFmzvsytOJelidNnA+X5lEU=" }, + { { 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, + "nqn.psk-test-host", "nqn.psk-test-subsys", + "NVMe1R02 nqn.psk-test-host nqn.psk-test-subsys QhW2+Rp6RzHlNtCslyRxMnwJ11tKKhz8JCAQpQ+XUD8f9td1VeH5h53yz2wKJG1a" }, +}; + +static struct test_data_identity test_data_identity_compat[] = { + { { 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, + "nqn.psk-test-host", "nqn.psk-test-subsys", + "NVMe1R01 nqn.psk-test-host nqn.psk-test-subsys 66GuqV08TsAGII39teWUfwQwizjv06Jy8jOcX3NAAzM=" }, + { { 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, + "nqn.psk-test-host", "nqn.psk-test-subsys", + "NVMe1R02 nqn.psk-test-host nqn.psk-test-subsys RsKmYJ3nAn1ApjjMloJFbAkLPivONDAX/xW327YBUsn2eGShXSjCZvBaOxscLqmz" }, +}; + static void check_str(const char *exp, const char *res) { if (!strcmp(res, exp)) @@ -70,7 +138,7 @@ static void check_str(const char *exp, const char *res) test_rc = 1; } -static void export_test(struct test_data *test) +static void export_test(struct test_data_psk *test) { char *psk; @@ -92,7 +160,7 @@ static void export_test(struct test_data *test) free(psk); } -static void import_test(struct test_data *test) +static void import_test(struct test_data_psk *test) { unsigned char *psk; int psk_length; @@ -133,7 +201,7 @@ static void import_test(struct test_data *test) free(psk); } -static void export_versioned_test(struct test_data *test) +static void export_versioned_test(struct test_data_psk *test) { char *psk; @@ -158,7 +226,7 @@ static void export_versioned_test(struct test_data *test) free(psk); } -static void import_versioned_test(struct test_data *test) +static void import_versioned_test(struct test_data_psk *test) { unsigned char *psk; unsigned char version; @@ -207,19 +275,80 @@ static void import_versioned_test(struct test_data *test) free(psk); } +static void identity_test(struct test_data_identity *test) +{ + char *id; + + if (test->version != 1 || + !(test->hmac == NVME_HMAC_ALG_SHA2_256 || + test->hmac == NVME_HMAC_ALG_SHA2_384)) + return; + + printf("test nvme_generate_tls_key_identity host %s subsys %s hmac %d %s\n", + test->hostnqn, test->subsysnqn, test->hmac, test->identity); + + id = nvme_generate_tls_key_identity(test->hostnqn, test->subsysnqn, + test->version, test->hmac, + (unsigned char *)test->configured_psk, + test->psk_length); + if (!id) { + if (errno == ENOTSUP) + return; + test_rc = 1; + printf("ERROR: nvme_generate_tls_key_identity() failed with %d\n", errno); + return; + } + check_str(test->identity, id); + free(id); +} + +static void identity_test_compat(struct test_data_identity *test) +{ + char *id; + + if (test->version != 1 || + !(test->hmac == NVME_HMAC_ALG_SHA2_256 || + test->hmac == NVME_HMAC_ALG_SHA2_384)) + return; + + printf("test nvme_generate_tls_key_identity_compat host %s subsys %s hmac %d %s\n", + test->hostnqn, test->subsysnqn, test->hmac, test->identity); + + id = nvme_generate_tls_key_identity_compat(test->hostnqn, + test->subsysnqn, + test->version, test->hmac, + (unsigned char *)test->configured_psk, + test->psk_length); + if (!id) { + if (errno == ENOTSUP) + return; + test_rc = 1; + printf("ERROR: nvme_generate_tls_key_identity_compat() failed with %d\n", errno); + return; + } + check_str(test->identity, id); + free(id); +} + 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_psk); i++) + export_test(&test_data_psk[i]); + + for (int i = 0; i < ARRAY_SIZE(test_data_psk); i++) + import_test(&test_data_psk[i]); + + for (int i = 0; i < ARRAY_SIZE(test_data_psk); i++) + export_versioned_test(&test_data_psk[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_psk); i++) + import_versioned_test(&test_data_psk[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_identity); i++) + identity_test(&test_data_identity[i]); - for (int i = 0; i < ARRAY_SIZE(test_data); i++) - import_versioned_test(&test_data[i]); + for (int i = 0; i < ARRAY_SIZE(test_data_identity_compat); i++) + identity_test_compat(&test_data_identity_compat[i]); return test_rc ? EXIT_FAILURE : EXIT_SUCCESS; }