1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Unit tests for NVMe authentication functions 4 * 5 * Copyright 2026 Google LLC 6 */ 7 8 #include <crypto/sha2.h> 9 #include <kunit/test.h> 10 #include <linux/nvme.h> 11 #include <linux/nvme-auth.h> 12 #include <linux/slab.h> 13 14 struct nvme_auth_test_values { 15 u8 hmac_id; 16 size_t hash_len; 17 u8 expected_psk[NVME_AUTH_MAX_DIGEST_SIZE]; 18 char *expected_psk_digest; 19 u8 expected_tls_psk[NVME_AUTH_MAX_DIGEST_SIZE]; 20 }; 21 22 static void kfree_action(void *ptr) 23 { 24 kfree(ptr); 25 } 26 27 static void kunit_add_kfree_action(struct kunit *test, void *ptr) 28 { 29 KUNIT_ASSERT_EQ(test, 0, 30 kunit_add_action_or_reset(test, kfree_action, ptr)); 31 } 32 33 /* 34 * Test the derivation of a TLS PSK from the initial skey. The vals parameter 35 * gives the expected value of tls_psk as well as the intermediate values psk 36 * and psk_digest. The inputs are implicitly the fixed values set below. 37 */ 38 static void 39 test_nvme_auth_derive_tls_psk(struct kunit *test, 40 const struct nvme_auth_test_values *vals) 41 { 42 const u8 hmac_id = vals->hmac_id; 43 const size_t hash_len = vals->hash_len; 44 const size_t skey_len = hash_len; 45 u8 skey[NVME_AUTH_MAX_DIGEST_SIZE]; 46 u8 c1[NVME_AUTH_MAX_DIGEST_SIZE]; 47 u8 c2[NVME_AUTH_MAX_DIGEST_SIZE]; 48 const char *subsysnqn = "subsysnqn"; 49 const char *hostnqn = "hostnqn"; 50 u8 *psk = NULL, *tls_psk = NULL; 51 char *psk_digest = NULL; 52 size_t psk_len; 53 int ret; 54 55 for (int i = 0; i < NVME_AUTH_MAX_DIGEST_SIZE; i++) { 56 skey[i] = 'A' + i; 57 c1[i] = i; 58 c2[i] = 0xff - i; 59 } 60 61 ret = nvme_auth_generate_psk(hmac_id, skey, skey_len, c1, c2, hash_len, 62 &psk, &psk_len); 63 kunit_add_kfree_action(test, psk); 64 KUNIT_ASSERT_EQ(test, 0, ret); 65 KUNIT_ASSERT_EQ(test, hash_len, psk_len); 66 KUNIT_ASSERT_MEMEQ(test, vals->expected_psk, psk, psk_len); 67 68 ret = nvme_auth_generate_digest(hmac_id, psk, psk_len, subsysnqn, 69 hostnqn, &psk_digest); 70 kunit_add_kfree_action(test, psk_digest); 71 if (vals->expected_psk_digest == NULL) { 72 /* 73 * Algorithm has an ID assigned but is not supported by 74 * nvme_auth_generate_digest(). 75 */ 76 KUNIT_ASSERT_EQ(test, -EINVAL, ret); 77 return; 78 } 79 KUNIT_ASSERT_EQ(test, 0, ret); 80 KUNIT_ASSERT_STREQ(test, vals->expected_psk_digest, psk_digest); 81 82 ret = nvme_auth_derive_tls_psk(hmac_id, psk, psk_len, psk_digest, 83 &tls_psk); 84 kunit_add_kfree_action(test, tls_psk); 85 KUNIT_ASSERT_EQ(test, 0, ret); 86 KUNIT_ASSERT_MEMEQ(test, vals->expected_tls_psk, tls_psk, psk_len); 87 } 88 89 static void test_nvme_auth_derive_tls_psk_hmac_sha256(struct kunit *test) 90 { 91 static const struct nvme_auth_test_values vals = { 92 .hmac_id = NVME_AUTH_HASH_SHA256, 93 .hash_len = SHA256_DIGEST_SIZE, 94 .expected_psk = { 95 0x17, 0x33, 0xc5, 0x9f, 0xa7, 0xf4, 0x8f, 0xcf, 96 0x37, 0xf5, 0xf2, 0x6f, 0xc4, 0xff, 0x02, 0x68, 97 0xad, 0x4f, 0x78, 0xe0, 0x30, 0xf4, 0xf3, 0xb0, 98 0xbf, 0xd1, 0xd4, 0x7e, 0x7b, 0xb1, 0x44, 0x7a, 99 }, 100 .expected_psk_digest = "OldoKuTfKddMuyCznAZojkWD7P4D9/AtzDzLimtOxqI=", 101 .expected_tls_psk = { 102 0x3c, 0x17, 0xda, 0x62, 0x84, 0x74, 0xa0, 0x4d, 103 0x22, 0x47, 0xc4, 0xca, 0xb4, 0x79, 0x68, 0xc9, 104 0x15, 0x38, 0x81, 0x93, 0xf7, 0xc0, 0x71, 0xbd, 105 0x94, 0x89, 0xcc, 0x36, 0x66, 0xcd, 0x7c, 0xc8, 106 }, 107 }; 108 109 test_nvme_auth_derive_tls_psk(test, &vals); 110 } 111 112 static void test_nvme_auth_derive_tls_psk_hmac_sha384(struct kunit *test) 113 { 114 static const struct nvme_auth_test_values vals = { 115 .hmac_id = NVME_AUTH_HASH_SHA384, 116 .hash_len = SHA384_DIGEST_SIZE, 117 .expected_psk = { 118 0xf1, 0x4b, 0x2d, 0xd3, 0x23, 0x4c, 0x45, 0x96, 119 0x94, 0xd3, 0xbc, 0x63, 0xf8, 0x96, 0x8b, 0xd6, 120 0xb3, 0x7c, 0x2c, 0x6d, 0xe8, 0x49, 0xe2, 0x2e, 121 0x11, 0x87, 0x49, 0x00, 0x1c, 0xe4, 0xbb, 0xe8, 122 0x64, 0x0b, 0x9e, 0x3a, 0x74, 0x8c, 0xb1, 0x1c, 123 0xe4, 0xb1, 0xd7, 0x1d, 0x35, 0x9c, 0xce, 0x39, 124 }, 125 .expected_psk_digest = "cffMWk8TSS7HOQebjgYEIkrPrjWPV4JE5cdPB8WhEvY4JBW5YynKyv66XscN4A9n", 126 .expected_tls_psk = { 127 0x27, 0x74, 0x75, 0x32, 0x33, 0x53, 0x7b, 0x3f, 128 0xa5, 0x0e, 0xb7, 0xd1, 0x6a, 0x8e, 0x43, 0x45, 129 0x7d, 0x85, 0xf4, 0x90, 0x6c, 0x00, 0x5b, 0x22, 130 0x36, 0x61, 0x6c, 0x5d, 0x80, 0x93, 0x9d, 0x08, 131 0x98, 0xff, 0xf1, 0x5b, 0xb8, 0xb7, 0x71, 0x19, 132 0xd2, 0xbe, 0x0a, 0xac, 0x42, 0x3e, 0x75, 0x90, 133 }, 134 }; 135 136 test_nvme_auth_derive_tls_psk(test, &vals); 137 } 138 139 static void test_nvme_auth_derive_tls_psk_hmac_sha512(struct kunit *test) 140 { 141 static const struct nvme_auth_test_values vals = { 142 .hmac_id = NVME_AUTH_HASH_SHA512, 143 .hash_len = SHA512_DIGEST_SIZE, 144 .expected_psk = { 145 0x9c, 0x9f, 0x08, 0x9a, 0x61, 0x8b, 0x47, 0xd2, 146 0xd7, 0x5f, 0x4b, 0x6c, 0x28, 0x07, 0x04, 0x24, 147 0x48, 0x7b, 0x44, 0x5d, 0xd9, 0x6e, 0x70, 0xc4, 148 0xc0, 0x9b, 0x55, 0xe8, 0xb6, 0x00, 0x01, 0x52, 149 0xa3, 0x36, 0x3c, 0x34, 0x54, 0x04, 0x3f, 0x38, 150 0xf0, 0xb8, 0x50, 0x36, 0xde, 0xd4, 0x06, 0x55, 151 0x35, 0x0a, 0xa8, 0x7b, 0x8b, 0x6a, 0x28, 0x2b, 152 0x5c, 0x1a, 0xca, 0xe1, 0x62, 0x33, 0xdd, 0x5b, 153 }, 154 /* nvme_auth_generate_digest() doesn't support SHA-512 yet. */ 155 .expected_psk_digest = NULL, 156 }; 157 158 test_nvme_auth_derive_tls_psk(test, &vals); 159 } 160 161 static struct kunit_case nvme_auth_test_cases[] = { 162 KUNIT_CASE(test_nvme_auth_derive_tls_psk_hmac_sha256), 163 KUNIT_CASE(test_nvme_auth_derive_tls_psk_hmac_sha384), 164 KUNIT_CASE(test_nvme_auth_derive_tls_psk_hmac_sha512), 165 {}, 166 }; 167 168 static struct kunit_suite nvme_auth_test_suite = { 169 .name = "nvme-auth", 170 .test_cases = nvme_auth_test_cases, 171 }; 172 kunit_test_suite(nvme_auth_test_suite); 173 174 MODULE_DESCRIPTION("Unit tests for NVMe authentication functions"); 175 MODULE_LICENSE("GPL"); 176