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
kfree_action(void * ptr)22 static void kfree_action(void *ptr)
23 {
24 kfree(ptr);
25 }
26
kunit_add_kfree_action(struct kunit * test,void * ptr)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
test_nvme_auth_derive_tls_psk(struct kunit * test,const struct nvme_auth_test_values * vals)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
test_nvme_auth_derive_tls_psk_hmac_sha256(struct kunit * test)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
test_nvme_auth_derive_tls_psk_hmac_sha384(struct kunit * test)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
test_nvme_auth_derive_tls_psk_hmac_sha512(struct kunit * test)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