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