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