xref: /linux/drivers/nvme/common/tests/auth_kunit.c (revision 7fe6ac157b7e15c8976bd62ad7cb98e248884e83)
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