Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2024 Intel Corporation. All rights reserved.
3 : : */
4 : :
5 : : #include "keyring_internal.h"
6 : : #include "spdk/keyring.h"
7 : : #include "spdk/keyring_module.h"
8 : : #include "spdk/log.h"
9 : : #include "spdk/queue.h"
10 : : #include "spdk/string.h"
11 : :
12 : : struct spdk_key {
13 : : char *name;
14 : : int refcnt;
15 : : bool removed;
16 : : bool probed;
17 : : struct spdk_keyring_module *module;
18 : : TAILQ_ENTRY(spdk_key) tailq;
19 : : };
20 : :
21 : : struct spdk_keyring {
22 : : pthread_mutex_t mutex;
23 : : TAILQ_HEAD(, spdk_keyring_module) modules;
24 : : TAILQ_HEAD(, spdk_key) keys;
25 : : TAILQ_HEAD(, spdk_key) removed_keys;
26 : : };
27 : :
28 : : static struct spdk_keyring g_keyring = {
29 : : .keys = TAILQ_HEAD_INITIALIZER(g_keyring.keys),
30 : : .removed_keys = TAILQ_HEAD_INITIALIZER(g_keyring.removed_keys),
31 : : .modules = TAILQ_HEAD_INITIALIZER(g_keyring.modules),
32 : : };
33 : :
34 : : static const char *
35 : 24692 : keyring_get_key_name(const char *name)
36 : : {
37 : : const char *keyname;
38 : :
39 : : /* Both "key0" and ":key0" refer to "key0" in the global keyring */
40 [ - + ]: 24692 : keyname = strstr(name, ":");
41 [ + + ]: 24692 : if (keyname == NULL) {
42 : 24662 : return name;
43 : : }
44 : :
45 : 30 : return keyname + 1;
46 : : }
47 : :
48 : : static struct spdk_key *
49 : 3127 : keyring_find_key(const char *name)
50 : : {
51 : : struct spdk_key *key;
52 : :
53 [ + + ]: 12607 : TAILQ_FOREACH(key, &g_keyring.keys, tailq) {
54 [ + + - + : 12346 : if (strcmp(keyring_get_key_name(key->name),
+ + ]
55 : : keyring_get_key_name(name)) == 0) {
56 : 2866 : return key;
57 : : }
58 : : }
59 : :
60 : 261 : return NULL;
61 : : }
62 : :
63 : : static void
64 : 167 : keyring_free_key(struct spdk_key *key)
65 : : {
66 [ - + ]: 167 : assert(key->refcnt == 0);
67 : :
68 : 167 : free(key->name);
69 : 167 : free(key);
70 : 167 : }
71 : :
72 : : static int
73 : 5090 : keyring_put_key(struct spdk_key *key)
74 : : {
75 [ - + ]: 5090 : assert(key->refcnt > 0);
76 : 5090 : key->refcnt--;
77 : :
78 [ + + ]: 5090 : if (key->refcnt == 0) {
79 [ - + - + ]: 160 : assert(key->removed);
80 [ - + ]: 160 : TAILQ_REMOVE(&g_keyring.removed_keys, key, tailq);
81 : 160 : keyring_free_key(key);
82 : :
83 : 160 : return 0;
84 : : }
85 : :
86 : 4930 : return key->refcnt;
87 : : }
88 : :
89 : : int
90 : 175 : spdk_keyring_add_key(const struct spdk_key_opts *opts)
91 : : {
92 : 175 : struct spdk_key *key = NULL;
93 : 175 : struct spdk_keyring_module *module = opts->module;
94 : : const char *keyname;
95 : 175 : int rc = 0;
96 : :
97 : : /* For now, only global keyring is supported */
98 [ - + ]: 175 : keyname = strstr(opts->name, ":");
99 [ + + - + ]: 175 : if (keyname != NULL && keyname != opts->name) {
100 : 0 : SPDK_ERRLOG("Couldn't add key '%s' to the keyring: keyring doesn't exist\n",
101 : : opts->name);
102 : 0 : return -EINVAL;
103 : : }
104 : :
105 : 175 : pthread_mutex_lock(&g_keyring.mutex);
106 [ + + ]: 175 : if (keyring_find_key(opts->name) != NULL) {
107 : 8 : SPDK_ERRLOG("Key '%s' already exists\n", opts->name);
108 : 8 : rc = -EEXIST;
109 : 8 : goto out;
110 : : }
111 : :
112 : 167 : key = calloc(1, sizeof(*key) + module->get_ctx_size());
113 [ - + ]: 167 : if (key == NULL) {
114 : 0 : rc = -ENOMEM;
115 : 0 : goto out;
116 : : }
117 : :
118 [ - + ]: 167 : key->name = strdup(opts->name);
119 [ - + ]: 167 : if (key->name == NULL) {
120 : 0 : rc = -ENOMEM;
121 : 0 : goto out;
122 : : }
123 : :
124 : 167 : rc = module->add_key(key, opts->ctx);
125 [ + + ]: 167 : if (rc != 0) {
126 : 7 : SPDK_ERRLOG("Failed to add key '%s' to the keyring\n", opts->name);
127 : 7 : goto out;
128 : : }
129 : :
130 : 160 : key->module = module;
131 : 160 : key->refcnt = 1;
132 : 160 : TAILQ_INSERT_TAIL(&g_keyring.keys, key, tailq);
133 : 175 : out:
134 : 175 : pthread_mutex_unlock(&g_keyring.mutex);
135 [ + + + + ]: 175 : if (rc != 0 && key != NULL) {
136 : 7 : keyring_free_key(key);
137 : : }
138 : :
139 : 175 : return rc;
140 : : }
141 : :
142 : : static void
143 : 160 : keyring_remove_key(struct spdk_key *key)
144 : : {
145 [ - + - + ]: 160 : assert(!key->removed);
146 : 160 : key->removed = true;
147 : 160 : key->module->remove_key(key);
148 [ + + ]: 160 : TAILQ_REMOVE(&g_keyring.keys, key, tailq);
149 : 160 : TAILQ_INSERT_TAIL(&g_keyring.removed_keys, key, tailq);
150 : 160 : keyring_put_key(key);
151 : 160 : }
152 : :
153 : : void
154 : 36 : spdk_keyring_remove_key(const char *name)
155 : : {
156 : : struct spdk_key *key;
157 : :
158 [ - + ]: 36 : pthread_mutex_lock(&g_keyring.mutex);
159 : 36 : key = keyring_find_key(name);
160 [ + + ]: 36 : if (key == NULL) {
161 : 8 : SPDK_WARNLOG("Key '%s' does not exist\n", name);
162 : 8 : goto out;
163 : : }
164 : :
165 : 28 : keyring_remove_key(key);
166 : 36 : out:
167 [ - + ]: 36 : pthread_mutex_unlock(&g_keyring.mutex);
168 : 36 : }
169 : :
170 : : static struct spdk_key *
171 : 86 : keyring_probe_key(const char *name)
172 : : {
173 : : struct spdk_keyring_module *module;
174 : 86 : struct spdk_key *key = NULL;
175 : : int rc;
176 : :
177 [ + + ]: 166 : TAILQ_FOREACH(module, &g_keyring.modules, tailq) {
178 [ + + ]: 86 : if (module->probe_key == NULL) {
179 : 80 : continue;
180 : : }
181 : :
182 : 6 : rc = module->probe_key(name);
183 [ + - ]: 6 : if (rc == 0) {
184 : 6 : key = keyring_find_key(name);
185 [ - + ]: 6 : if (key == NULL) {
186 : 0 : SPDK_ERRLOG("Successfully probed key '%s' using module '%s', but "
187 : : "the key is unavailable\n", name, module->name);
188 : 0 : return NULL;
189 : : }
190 : :
191 : 6 : key->probed = true;
192 : 6 : break;
193 [ # # ]: 0 : } else if (rc != -ENOKEY) {
194 : : /* The module is aware of the key but couldn't instantiate it */
195 [ # # ]: 0 : assert(keyring_find_key(name) == NULL);
196 : 0 : SPDK_ERRLOG("Failed to probe key '%s' using module '%s': %s\n",
197 : : name, module->name, spdk_strerror(-rc));
198 : 0 : break;
199 : : }
200 : : }
201 : :
202 : 86 : return key;
203 : : }
204 : :
205 : : struct spdk_key *
206 : 2910 : spdk_keyring_get_key(const char *name)
207 : : {
208 : : struct spdk_key *key;
209 : :
210 [ - + ]: 2910 : pthread_mutex_lock(&g_keyring.mutex);
211 : 2910 : key = keyring_find_key(name);
212 [ + + ]: 2910 : if (key == NULL) {
213 : 86 : key = keyring_probe_key(name);
214 [ + + ]: 86 : if (key == NULL) {
215 : 80 : goto out;
216 : : }
217 : : }
218 : :
219 : 2830 : key->refcnt++;
220 : 2910 : out:
221 [ - + ]: 2910 : pthread_mutex_unlock(&g_keyring.mutex);
222 : :
223 : 2910 : return key;
224 : : }
225 : :
226 : : void
227 : 12215 : spdk_keyring_put_key(struct spdk_key *key)
228 : : {
229 : : int refcnt;
230 : :
231 [ + + ]: 12215 : if (key == NULL) {
232 : 7285 : return;
233 : : }
234 : :
235 [ - + ]: 4930 : pthread_mutex_lock(&g_keyring.mutex);
236 : 4930 : refcnt = keyring_put_key(key);
237 [ + + - + : 4930 : if (refcnt == 1 && key->probed && !key->removed) {
+ + - + +
- ]
238 : 6 : keyring_remove_key(key);
239 : : }
240 [ - + ]: 4930 : pthread_mutex_unlock(&g_keyring.mutex);
241 : : }
242 : :
243 : : struct spdk_key *
244 : 2100 : spdk_key_dup(struct spdk_key *key)
245 : : {
246 [ - + ]: 2100 : pthread_mutex_lock(&g_keyring.mutex);
247 : 2100 : key->refcnt++;
248 [ - + ]: 2100 : pthread_mutex_unlock(&g_keyring.mutex);
249 : :
250 : 2100 : return key;
251 : : }
252 : :
253 : : const char *
254 : 2082 : spdk_key_get_name(struct spdk_key *key)
255 : : {
256 : 2082 : return key->name;
257 : : }
258 : :
259 : : int
260 : 3262 : spdk_key_get_key(struct spdk_key *key, void *buf, int len)
261 : : {
262 : 3262 : struct spdk_keyring_module *module = key->module;
263 : :
264 [ + + + + ]: 3262 : if (key->removed) {
265 : 4 : return -ENOKEY;
266 : : }
267 : :
268 : 3258 : return module->get_key(key, buf, len);
269 : : }
270 : :
271 : : void *
272 : 3681 : spdk_key_get_ctx(struct spdk_key *key)
273 : : {
274 : 3681 : return key + 1;
275 : : }
276 : :
277 : :
278 : : struct spdk_keyring_module *
279 : 12 : spdk_key_get_module(struct spdk_key *key)
280 : : {
281 : 12 : return key->module;
282 : : }
283 : :
284 : : void
285 : 124 : spdk_keyring_write_config(struct spdk_json_write_ctx *w)
286 : : {
287 : : struct spdk_keyring_module *module;
288 : :
289 [ + + ]: 248 : TAILQ_FOREACH(module, &g_keyring.modules, tailq) {
290 [ + - ]: 124 : if (module->write_config != NULL) {
291 : 124 : module->write_config(w);
292 : : }
293 : : }
294 : 124 : }
295 : :
296 : : void
297 : 190 : spdk_keyring_for_each_key(struct spdk_keyring *keyring,
298 : : void *ctx, void (*fn)(void *ctx, struct spdk_key *key), uint32_t flags)
299 : : {
300 : : struct spdk_key *key, *tmp;
301 : :
302 [ - + ]: 190 : assert(keyring == NULL);
303 [ - + ]: 190 : pthread_mutex_lock(&g_keyring.mutex);
304 [ + + ]: 292 : TAILQ_FOREACH_SAFE(key, &g_keyring.keys, tailq, tmp) {
305 : 102 : fn(ctx, key);
306 : : }
307 : :
308 [ + + ]: 190 : if (flags & SPDK_KEYRING_FOR_EACH_ALL) {
309 [ + + ]: 72 : TAILQ_FOREACH_SAFE(key, &g_keyring.removed_keys, tailq, tmp) {
310 : 6 : fn(ctx, key);
311 : : }
312 : : }
313 [ - + ]: 190 : pthread_mutex_unlock(&g_keyring.mutex);
314 : 190 : }
315 : :
316 : : void
317 : 4454 : spdk_keyring_register_module(struct spdk_keyring_module *module)
318 : : {
319 : 4454 : TAILQ_INSERT_TAIL(&g_keyring.modules, module, tailq);
320 : 4454 : }
321 : :
322 : : void
323 : 96 : keyring_dump_key_info(struct spdk_key *key, struct spdk_json_write_ctx *w)
324 : : {
325 : 96 : struct spdk_keyring_module *module = key->module;
326 : :
327 : 96 : spdk_json_write_named_string(w, "name", key->name);
328 : 96 : spdk_json_write_named_string(w, "module", module->name);
329 [ - + ]: 96 : spdk_json_write_named_bool(w, "removed", key->removed);
330 [ - + ]: 96 : spdk_json_write_named_bool(w, "probed", key->probed);
331 : 96 : spdk_json_write_named_int32(w, "refcnt", key->refcnt);
332 : :
333 [ - + + + : 96 : if (!key->removed && module->dump_info != NULL) {
+ - ]
334 : 90 : module->dump_info(key, w);
335 : : }
336 : 96 : }
337 : :
338 : : int
339 : 2217 : spdk_keyring_init(void)
340 : : {
341 : : struct spdk_keyring_module *module, *tmp;
342 : 1073 : pthread_mutexattr_t attr;
343 : : int rc;
344 : :
345 [ - + ]: 2217 : rc = pthread_mutexattr_init(&attr);
346 [ - + ]: 2217 : if (rc != 0) {
347 : 0 : SPDK_ERRLOG("Failed to initialize mutex attr\n");
348 : 0 : return -rc;
349 : : }
350 : :
351 [ - + ]: 2217 : rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
352 [ - + ]: 2217 : if (rc != 0) {
353 : 0 : SPDK_ERRLOG("Failed to set mutex attr\n");
354 [ # # ]: 0 : pthread_mutexattr_destroy(&attr);
355 : 0 : return -rc;
356 : : }
357 : :
358 [ - + ]: 2217 : rc = pthread_mutex_init(&g_keyring.mutex, &attr);
359 [ - + ]: 2217 : if (rc != 0) {
360 : 0 : SPDK_ERRLOG("Failed to initialize mutex\n");
361 [ # # ]: 0 : pthread_mutexattr_destroy(&attr);
362 : 0 : return -rc;
363 : : }
364 : :
365 [ - + ]: 2217 : pthread_mutexattr_destroy(&attr);
366 [ + + ]: 6303 : TAILQ_FOREACH_SAFE(module, &g_keyring.modules, tailq, tmp) {
367 [ + + ]: 4086 : if (module->init != NULL) {
368 : 1960 : rc = module->init();
369 [ + + ]: 1960 : if (rc != 0) {
370 [ + - ]: 1957 : if (rc == -ENODEV) {
371 [ - + - + ]: 1957 : SPDK_INFOLOG(keyring, "Skipping module %s\n", module->name);
372 [ + + ]: 1957 : TAILQ_REMOVE(&g_keyring.modules, module, tailq);
373 : 1957 : rc = 0;
374 : 1957 : continue;
375 : : }
376 : :
377 : 0 : SPDK_ERRLOG("Failed to initialize module %s: %s\n",
378 : : module->name, spdk_strerror(-rc));
379 : 0 : break;
380 : : }
381 : : }
382 : :
383 [ - + - + ]: 2129 : SPDK_INFOLOG(keyring, "Initialized module %s\n", module->name);
384 : : }
385 : :
386 [ - + ]: 2217 : if (rc != 0) {
387 [ # # ]: 0 : TAILQ_FOREACH(tmp, &g_keyring.modules, tailq) {
388 [ # # ]: 0 : if (tmp == module) {
389 : 0 : break;
390 : : }
391 [ # # ]: 0 : if (tmp->cleanup != NULL) {
392 : 0 : tmp->cleanup();
393 : : }
394 : : }
395 : : }
396 : :
397 : 2217 : return rc;
398 : : }
399 : :
400 : : void
401 : 2217 : spdk_keyring_cleanup(void)
402 : : {
403 : : struct spdk_keyring_module *module;
404 : : struct spdk_key *key;
405 : :
406 [ + + ]: 2343 : while (!TAILQ_EMPTY(&g_keyring.keys)) {
407 : 126 : key = TAILQ_FIRST(&g_keyring.keys);
408 : 126 : keyring_remove_key(key);
409 : : }
410 : :
411 [ - + ]: 2217 : while (!TAILQ_EMPTY(&g_keyring.removed_keys)) {
412 : 0 : key = TAILQ_FIRST(&g_keyring.removed_keys);
413 : 0 : SPDK_WARNLOG("Key '%s' still has %d references\n", key->name, key->refcnt);
414 : 0 : key->refcnt = 0;
415 [ # # ]: 0 : TAILQ_REMOVE(&g_keyring.removed_keys, key, tailq);
416 : 0 : keyring_free_key(key);
417 : : }
418 : :
419 [ + + ]: 4346 : TAILQ_FOREACH(module, &g_keyring.modules, tailq) {
420 [ - + ]: 2129 : if (module->cleanup != NULL) {
421 : 0 : module->cleanup();
422 : : }
423 : : }
424 : 2217 : }
425 : :
426 : 2730 : SPDK_LOG_REGISTER_COMPONENT(keyring)
|