Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2024 Intel Corporation. All rights reserved.
3 : : */
4 : : #include "spdk_internal/cunit.h"
5 : : #include "spdk_internal/mock.h"
6 : : #include "spdk/util.h"
7 : :
8 : : #include "keyring/keyring.c"
9 : :
10 : : #include "unit/lib/json_mock.c"
11 : :
12 : : struct ut_key {
13 : : #define UT_KEY_SIZE 64
14 : : char buf[UT_KEY_SIZE];
15 : : int len;
16 : : };
17 : :
18 : : struct ut_key_opts {
19 : : char *buf;
20 : : int len;
21 : : };
22 : :
23 : : static int g_add_status;
24 : :
25 : : static int
26 : 5 : ut_keyring_add_key(struct spdk_key *key, void *ctx)
27 : : {
28 : 5 : struct ut_key_opts *opts = ctx;
29 : 5 : struct ut_key *utkey = spdk_key_get_ctx(key);
30 : :
31 [ + + ]: 5 : if (g_add_status) {
32 : 1 : return g_add_status;
33 : : }
34 : :
35 [ + - ]: 4 : SPDK_CU_ASSERT_FATAL(opts != NULL);
36 : :
37 : : /* Use spdk_json_val's start/len to pass a buffer with the key */
38 : 4 : memcpy(utkey->buf, opts->buf, opts->len);
39 : 4 : utkey->len = opts->len;
40 : :
41 : 4 : return 0;
42 : 5 : }
43 : :
44 : : static bool g_remove_called;
45 : :
46 : : static void
47 : 4 : ut_keyring_remove_key(struct spdk_key *key)
48 : : {
49 : 4 : struct ut_key *utkey = spdk_key_get_ctx(key);
50 : :
51 : 4 : memset(utkey->buf, 0, utkey->len);
52 : 4 : g_remove_called = true;
53 : 4 : }
54 : :
55 : : static int
56 : 2 : ut_keyring_get_key(struct spdk_key *key, void *buf, int len)
57 : : {
58 : 2 : struct ut_key *utkey = spdk_key_get_ctx(key);
59 : :
60 : 2 : memcpy(buf, utkey->buf, utkey->len);
61 : :
62 : 2 : return utkey->len;
63 : : }
64 : :
65 : : static size_t
66 : 5 : ut_keyring_get_ctx_size(void)
67 : : {
68 : 5 : return sizeof(struct ut_key);
69 : : }
70 : :
71 : : static struct spdk_keyring_module g_module = {
72 : : .name = "ut",
73 : : .add_key = ut_keyring_add_key,
74 : : .remove_key = ut_keyring_remove_key,
75 : : .get_key = ut_keyring_get_key,
76 : : .get_ctx_size = ut_keyring_get_ctx_size,
77 : : };
78 : :
79 : 1 : SPDK_KEYRING_REGISTER_MODULE(ut, &g_module);
80 : :
81 : : static void
82 : 1 : test_keyring_add_remove(void)
83 : : {
84 : 1 : struct spdk_key_opts opts = {};
85 : : struct spdk_key *key;
86 : 1 : char keybuf[UT_KEY_SIZE] = {}, rcvbuf[UT_KEY_SIZE] = {};
87 : 1 : struct ut_key_opts uopts = { .buf = keybuf, .len = UT_KEY_SIZE };
88 : 1 : struct spdk_keyring_module module2 = { .name = "ut2" };
89 : : int rc;
90 : :
91 : : /* Add a key */
92 : 1 : memset(keybuf, 0xa5, UT_KEY_SIZE);
93 : 1 : opts.size = SPDK_SIZEOF(&opts, ctx);
94 : 1 : opts.name = "key0";
95 : 1 : opts.module = &g_module;
96 : 1 : opts.ctx = &uopts;
97 : 1 : rc = spdk_keyring_add_key(&opts);
98 : 1 : CU_ASSERT_EQUAL(rc, 0);
99 : :
100 : : /* Get a reference to that key */
101 : 1 : key = spdk_keyring_get_key("key0");
102 : 1 : CU_ASSERT_PTR_NOT_NULL(key);
103 : :
104 : : /* Get its keying material */
105 : 1 : rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE);
106 : 1 : CU_ASSERT_EQUAL(rc, UT_KEY_SIZE)
107 : 1 : CU_ASSERT_EQUAL(memcmp(rcvbuf, keybuf, UT_KEY_SIZE), 0);
108 : :
109 : : /* Remove it and try to get another reference */
110 : 1 : spdk_keyring_remove_key("key0", &g_module);
111 : 1 : CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0"));
112 : :
113 : : /* Now that the key has been remove spdk_key_get_key() should result in an -ENOKEY error */
114 : 1 : rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE);
115 : 1 : CU_ASSERT_EQUAL(rc, -ENOKEY);
116 : :
117 : : /* Finally, release the reference */
118 : 1 : spdk_keyring_put_key(key);
119 : :
120 : : /* Explicitly specify global keyring */
121 : 1 : rc = spdk_keyring_add_key(&opts);
122 : 1 : CU_ASSERT_EQUAL(rc, 0);
123 : 1 : key = spdk_keyring_get_key(":key0");
124 : 1 : CU_ASSERT_PTR_NOT_NULL(key);
125 : :
126 : 1 : memset(rcvbuf, 0, UT_KEY_SIZE);
127 : 1 : rc = spdk_key_get_key(key, rcvbuf, UT_KEY_SIZE);
128 : 1 : CU_ASSERT_EQUAL(rc, UT_KEY_SIZE)
129 : 1 : CU_ASSERT_EQUAL(memcmp(rcvbuf, keybuf, UT_KEY_SIZE), 0);
130 : :
131 : 1 : spdk_keyring_put_key(key);
132 : :
133 : : /* Remove the key without explicitly specifying global keyring */
134 : 1 : spdk_keyring_remove_key("key0", &g_module);
135 : 1 : CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0"));
136 : 1 : CU_ASSERT_PTR_NULL(spdk_keyring_get_key(":key0"));
137 : :
138 : : /* Try to create a key with the same name twice */
139 : 1 : opts.size = SPDK_SIZEOF(&opts, ctx);
140 : 1 : opts.name = "key0";
141 : 1 : opts.module = &g_module;
142 : 1 : opts.ctx = &uopts;
143 : 1 : rc = spdk_keyring_add_key(&opts);
144 : 1 : CU_ASSERT_EQUAL(rc, 0);
145 : 1 : rc = spdk_keyring_add_key(&opts);
146 : 1 : CU_ASSERT_EQUAL(rc, -EEXIST);
147 : :
148 : : /* Explicitly specify global keyring */
149 : 1 : opts.name = ":key0";
150 : 1 : rc = spdk_keyring_add_key(&opts);
151 : 1 : CU_ASSERT_EQUAL(rc, -EEXIST);
152 : :
153 : : /* Try to remove a key owned by a different module */
154 : 1 : spdk_keyring_remove_key("key0", &module2);
155 : 1 : CU_ASSERT_PTR_NOT_NULL(spdk_keyring_get_key("key0"));
156 : 1 : CU_ASSERT_PTR_NOT_NULL(spdk_keyring_get_key(":key0"));
157 : :
158 : 1 : spdk_keyring_remove_key(":key0", &g_module);
159 : 1 : CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0"));
160 : 1 : CU_ASSERT_PTR_NULL(spdk_keyring_get_key(":key0"));
161 : 1 : CU_ASSERT(g_remove_called);
162 : 1 : g_remove_called = false;
163 : :
164 : : /* Remove an already removed key */
165 : 1 : spdk_keyring_remove_key("key0", &g_module);
166 : 1 : spdk_keyring_remove_key(":key0", &g_module);
167 : 1 : CU_ASSERT(!g_remove_called);
168 : :
169 : : /* Check that an error from module's add_key() results in failure */
170 : 1 : g_add_status = -EIO;
171 : 1 : opts.size = SPDK_SIZEOF(&opts, ctx);
172 : 1 : opts.name = "key0";
173 : 1 : opts.module = &g_module;
174 : 1 : opts.ctx = &uopts;
175 : 1 : rc = spdk_keyring_add_key(&opts);
176 : 1 : CU_ASSERT_EQUAL(rc, -EIO);
177 : 1 : CU_ASSERT_PTR_NULL(spdk_keyring_get_key("key0"));
178 : 1 : g_add_status = 0;
179 : 1 : }
180 : :
181 : : static void
182 : 1 : test_keyring_get_put(void)
183 : : {
184 : 1 : struct spdk_key_opts opts = {};
185 : : struct spdk_key *key, *tmp;
186 : 1 : char keybuf[UT_KEY_SIZE] = {};
187 : 1 : struct ut_key_opts uopts = { .buf = keybuf, .len = UT_KEY_SIZE };
188 : : int rc, i;
189 : :
190 : 1 : opts.size = SPDK_SIZEOF(&opts, ctx);
191 : 1 : opts.name = "key0";
192 : 1 : opts.module = &g_module;
193 : 1 : opts.ctx = &uopts;
194 : 1 : rc = spdk_keyring_add_key(&opts);
195 : 1 : CU_ASSERT_EQUAL(rc, 0);
196 : :
197 : : /* Get multiple references to the same key */
198 : 1 : key = spdk_keyring_get_key("key0");
199 : 1 : CU_ASSERT_PTR_NOT_NULL(key);
200 : : #define UT_KEY_REFS 8
201 [ + + ]: 9 : for (i = 0; i < UT_KEY_REFS; ++i) {
202 : 8 : tmp = spdk_keyring_get_key("key0");
203 : 8 : CU_ASSERT_PTR_EQUAL(key, tmp);
204 : 8 : }
205 : :
206 : : /* Remove the key and verify (relying on the address sanitizer to catch any use-after-free
207 : : * errors) that the reference is still valid
208 : : */
209 : 1 : spdk_keyring_remove_key("key0", &g_module);
210 : 1 : CU_ASSERT_EQUAL(strcmp(spdk_key_get_name(key), "key0"), 0);
211 : :
212 : : /* Release all but one reference and verify that it's still valid (again, relying on the
213 : : * address sanitizer)
214 : : */
215 [ + + ]: 9 : for (i = 0; i < UT_KEY_REFS; ++i) {
216 : 8 : spdk_keyring_put_key(key);
217 : 8 : CU_ASSERT_EQUAL(strcmp(spdk_key_get_name(key), "key0"), 0);
218 : 8 : }
219 : :
220 : : /* Release the last reference - this should also free the key */
221 : 1 : spdk_keyring_put_key(key);
222 : 1 : }
223 : :
224 : : int
225 : 1 : main(int argc, char **argv)
226 : : {
227 : : CU_pSuite suite;
228 : : unsigned int num_failures;
229 : :
230 : 1 : CU_initialize_registry();
231 : :
232 : 1 : suite = CU_add_suite("keyring", NULL, NULL);
233 : 1 : CU_ADD_TEST(suite, test_keyring_add_remove);
234 : 1 : CU_ADD_TEST(suite, test_keyring_get_put);
235 : :
236 : 1 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
237 : 1 : CU_cleanup_registry();
238 : :
239 : 1 : return num_failures;
240 : : }
|