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 : 26816 : 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 [ - + # # ]: 26816 : keyname = strstr(name, ":");
41 [ + + ]: 26816 : if (keyname == NULL) {
42 : 26782 : return name;
43 : : }
44 : :
45 [ # # ]: 34 : return keyname + 1;
46 : 40 : }
47 : :
48 : : static struct spdk_key *
49 : 3458 : keyring_find_key(const char *name)
50 : : {
51 : : struct spdk_key *key;
52 : :
53 [ + + # # : 13706 : TAILQ_FOREACH(key, &g_keyring.keys, tailq) {
# # # # #
# # # ]
54 [ + + + + : 13448 : if (strcmp(keyring_get_key_name(key->name),
+ + # # #
# # # ]
55 : 40 : keyring_get_key_name(name)) == 0) {
56 : 3160 : return key;
57 : : }
58 : 0 : }
59 : :
60 : 298 : return NULL;
61 : 33 : }
62 : :
63 : : static void
64 : 247 : keyring_free_key(struct spdk_key *key)
65 : : {
66 [ + + # # : 247 : assert(key->refcnt == 0);
# # # # ]
67 : :
68 [ # # # # ]: 247 : free(key->name);
69 : 247 : free(key);
70 : 247 : }
71 : :
72 : : static int
73 : 7484 : keyring_put_key(struct spdk_key *key)
74 : : {
75 [ + + # # : 7484 : assert(key->refcnt > 0);
# # # # ]
76 [ # # # # ]: 7484 : key->refcnt--;
77 : :
78 [ + + # # : 7484 : if (key->refcnt == 0) {
# # ]
79 [ - + - + : 231 : assert(key->removed);
# # # # #
# ]
80 [ - + # # : 231 : TAILQ_REMOVE(&g_keyring.removed_keys, key, tailq);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
81 : 231 : keyring_free_key(key);
82 : :
83 : 231 : return 0;
84 : : }
85 : :
86 [ # # # # ]: 7253 : return key->refcnt;
87 : 15 : }
88 : :
89 : : int
90 : 259 : spdk_keyring_add_key(const struct spdk_key_opts *opts)
91 : : {
92 : 259 : struct spdk_key *key = NULL;
93 [ # # # # ]: 259 : struct spdk_keyring_module *module = opts->module;
94 : : const char *keyname;
95 : 259 : int rc = 0;
96 : :
97 : : /* For now, only global keyring is supported */
98 [ - + # # : 259 : keyname = strstr(opts->name, ":");
# # # # ]
99 [ + + + + : 259 : 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 [ # # ]: 259 : pthread_mutex_lock(&g_keyring.mutex);
106 [ + + # # : 259 : 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 [ # # # # : 251 : key = calloc(1, sizeof(*key) + module->get_ctx_size());
# # # # ]
113 [ + + ]: 251 : if (key == NULL) {
114 : 0 : rc = -ENOMEM;
115 : 0 : goto out;
116 : : }
117 : :
118 [ - + # # : 251 : key->name = strdup(opts->name);
# # # # #
# ]
119 [ + + # # : 251 : if (key->name == NULL) {
# # ]
120 : 0 : rc = -ENOMEM;
121 : 0 : goto out;
122 : : }
123 : :
124 [ # # # # : 251 : rc = module->add_key(key, opts->ctx);
# # # # #
# # # ]
125 [ + + ]: 251 : if (rc != 0) {
126 [ # # # # ]: 16 : SPDK_ERRLOG("Failed to add key '%s' to the keyring\n", opts->name);
127 : 16 : goto out;
128 : : }
129 : :
130 [ # # # # ]: 235 : key->module = module;
131 [ # # # # ]: 235 : key->refcnt = 1;
132 [ # # # # : 235 : TAILQ_INSERT_TAIL(&g_keyring.keys, key, tailq);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
133 : 252 : out:
134 [ # # ]: 259 : pthread_mutex_unlock(&g_keyring.mutex);
135 [ + + + + ]: 259 : if (rc != 0 && key != NULL) {
136 : 16 : keyring_free_key(key);
137 : 1 : }
138 : :
139 : 259 : return rc;
140 : 7 : }
141 : :
142 : : static void
143 : 235 : keyring_remove_key(struct spdk_key *key)
144 : : {
145 [ - + - + : 235 : assert(!key->removed);
# # # # #
# ]
146 [ # # # # ]: 235 : key->removed = true;
147 [ # # # # : 235 : key->module->remove_key(key);
# # # # #
# # # ]
148 [ + + # # : 235 : TAILQ_REMOVE(&g_keyring.keys, key, tailq);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
149 [ # # # # : 235 : TAILQ_INSERT_TAIL(&g_keyring.removed_keys, key, tailq);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
150 : 235 : keyring_put_key(key);
151 : 235 : }
152 : :
153 : : int
154 : 43 : spdk_keyring_remove_key(const char *name, struct spdk_keyring_module *module)
155 : : {
156 : : struct spdk_key *key;
157 : 43 : int rc = 0;
158 : :
159 [ - + ]: 43 : pthread_mutex_lock(&g_keyring.mutex);
160 : 43 : key = keyring_find_key(name);
161 [ + + ]: 43 : if (key == NULL) {
162 : 8 : SPDK_ERRLOG("Key '%s' does not exist\n", name);
163 : 8 : rc = -ENOKEY;
164 : 8 : goto out;
165 : : }
166 : :
167 [ + + # # : 35 : if (key->module != module) {
# # ]
168 [ # # # # ]: 4 : SPDK_ERRLOG("Key '%s' is not owned by module '%s'\n", name, module->name);
169 : 4 : rc = -EINVAL;
170 : 4 : goto out;
171 : : }
172 : :
173 : 31 : keyring_remove_key(key);
174 : 36 : out:
175 [ - + ]: 43 : pthread_mutex_unlock(&g_keyring.mutex);
176 : 43 : return rc;
177 : : }
178 : :
179 : : static struct spdk_key *
180 : 39 : keyring_probe_key(const char *name)
181 : : {
182 : : struct spdk_keyring_module *module;
183 : 39 : struct spdk_key *key = NULL;
184 : : int rc;
185 : :
186 [ + + # # : 72 : TAILQ_FOREACH(module, &g_keyring.modules, tailq) {
# # # # #
# # # ]
187 [ + + # # : 39 : if (module->probe_key == NULL) {
# # ]
188 : 33 : continue;
189 : : }
190 : :
191 [ # # # # : 6 : rc = module->probe_key(name);
# # # # ]
192 [ + - ]: 6 : if (rc == 0) {
193 : 6 : key = keyring_find_key(name);
194 [ - + ]: 6 : if (key == NULL) {
195 [ # # # # ]: 0 : SPDK_ERRLOG("Successfully probed key '%s' using module '%s', but "
196 : : "the key is unavailable\n", name, module->name);
197 : 0 : return NULL;
198 : : }
199 : :
200 [ # # # # ]: 6 : key->probed = true;
201 : 6 : break;
202 [ # # ]: 0 : } else if (rc != -ENOKEY) {
203 : : /* The module is aware of the key but couldn't instantiate it */
204 [ # # # # ]: 0 : assert(keyring_find_key(name) == NULL);
205 [ # # # # : 0 : SPDK_ERRLOG("Failed to probe key '%s' using module '%s': %s\n",
# # ]
206 : : name, module->name, spdk_strerror(-rc));
207 : 0 : break;
208 : : }
209 : 0 : }
210 : :
211 : 39 : return key;
212 : 6 : }
213 : :
214 : : struct spdk_key *
215 : 3150 : spdk_keyring_get_key(const char *name)
216 : : {
217 : : struct spdk_key *key;
218 : :
219 [ - + ]: 3150 : pthread_mutex_lock(&g_keyring.mutex);
220 : 3150 : key = keyring_find_key(name);
221 [ + + ]: 3150 : if (key == NULL) {
222 : 39 : key = keyring_probe_key(name);
223 [ + + ]: 39 : if (key == NULL) {
224 : 33 : goto out;
225 : : }
226 : 0 : }
227 : :
228 [ # # # # ]: 3117 : key->refcnt++;
229 : 3131 : out:
230 [ - + ]: 3150 : pthread_mutex_unlock(&g_keyring.mutex);
231 : :
232 : 3150 : return key;
233 : : }
234 : :
235 : : void
236 : 15467 : spdk_keyring_put_key(struct spdk_key *key)
237 : : {
238 : : int refcnt;
239 : :
240 [ + + ]: 15467 : if (key == NULL) {
241 : 8218 : return;
242 : : }
243 : :
244 [ - + ]: 7249 : pthread_mutex_lock(&g_keyring.mutex);
245 : 7249 : refcnt = keyring_put_key(key);
246 [ + + - + : 7249 : if (refcnt == 1 && key->probed && !key->removed) {
+ + - + +
- # # # #
# # # # ]
247 : 6 : keyring_remove_key(key);
248 : 0 : }
249 [ - + ]: 7249 : pthread_mutex_unlock(&g_keyring.mutex);
250 : 77 : }
251 : :
252 : : struct spdk_key *
253 : 4140 : spdk_key_dup(struct spdk_key *key)
254 : : {
255 [ - + ]: 4140 : pthread_mutex_lock(&g_keyring.mutex);
256 [ # # # # ]: 4140 : key->refcnt++;
257 [ - + ]: 4140 : pthread_mutex_unlock(&g_keyring.mutex);
258 : :
259 : 4140 : return key;
260 : : }
261 : :
262 : : const char *
263 : 2259 : spdk_key_get_name(struct spdk_key *key)
264 : : {
265 [ # # # # ]: 2259 : return key->name;
266 : : }
267 : :
268 : : int
269 : 3642 : spdk_key_get_key(struct spdk_key *key, void *buf, int len)
270 : : {
271 [ # # # # ]: 3642 : struct spdk_keyring_module *module = key->module;
272 : :
273 [ + + + + : 3642 : if (key->removed) {
# # # # ]
274 : 4 : return -ENOKEY;
275 : : }
276 : :
277 [ # # # # : 3638 : return module->get_key(key, buf, len);
# # # # ]
278 : 3 : }
279 : :
280 : : void *
281 : 4226 : spdk_key_get_ctx(struct spdk_key *key)
282 : : {
283 [ # # ]: 4226 : return key + 1;
284 : : }
285 : :
286 : :
287 : : struct spdk_keyring_module *
288 : 18 : spdk_key_get_module(struct spdk_key *key)
289 : : {
290 [ # # # # ]: 18 : return key->module;
291 : : }
292 : :
293 : : void
294 : 128 : spdk_keyring_write_config(struct spdk_json_write_ctx *w)
295 : : {
296 : : struct spdk_keyring_module *module;
297 : :
298 [ + + + - : 256 : TAILQ_FOREACH(module, &g_keyring.modules, tailq) {
+ + + - +
- + - ]
299 [ + + + - : 128 : if (module->write_config != NULL) {
- + ]
300 [ + - + - : 128 : module->write_config(w);
- + + - ]
301 : 9 : }
302 : 9 : }
303 : 128 : }
304 : :
305 : : void
306 : 194 : spdk_keyring_for_each_key(struct spdk_keyring *keyring,
307 : : void *ctx, void (*fn)(void *ctx, struct spdk_key *key), uint32_t flags)
308 : : {
309 : : struct spdk_key *key, *tmp;
310 : :
311 [ + + # # ]: 194 : assert(keyring == NULL);
312 [ + + ]: 194 : pthread_mutex_lock(&g_keyring.mutex);
313 [ + + + - : 302 : TAILQ_FOREACH_SAFE(key, &g_keyring.keys, tailq, tmp) {
+ - # # #
# # # -
+ ]
314 [ # # # # ]: 108 : fn(ctx, key);
315 : 0 : }
316 : :
317 [ + + ]: 194 : if (flags & SPDK_KEYRING_FOR_EACH_ALL) {
318 [ + + # # : 72 : TAILQ_FOREACH_SAFE(key, &g_keyring.removed_keys, tailq, tmp) {
# # # # #
# # # #
# ]
319 [ # # # # ]: 6 : fn(ctx, key);
320 : 0 : }
321 : 0 : }
322 [ + + ]: 194 : pthread_mutex_unlock(&g_keyring.mutex);
323 : 194 : }
324 : :
325 : : void
326 : 4304 : spdk_keyring_register_module(struct spdk_keyring_module *module)
327 : : {
328 [ + - + - : 4304 : TAILQ_INSERT_TAIL(&g_keyring.modules, module, tailq);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
329 : 4304 : }
330 : :
331 : : void
332 : 96 : keyring_dump_key_info(struct spdk_key *key, struct spdk_json_write_ctx *w)
333 : : {
334 [ # # # # ]: 96 : struct spdk_keyring_module *module = key->module;
335 : :
336 [ # # # # ]: 96 : spdk_json_write_named_string(w, "name", key->name);
337 [ # # # # ]: 96 : spdk_json_write_named_string(w, "module", module->name);
338 [ - + # # : 96 : spdk_json_write_named_bool(w, "removed", key->removed);
# # ]
339 [ - + # # : 96 : spdk_json_write_named_bool(w, "probed", key->probed);
# # ]
340 [ # # # # ]: 96 : spdk_json_write_named_int32(w, "refcnt", key->refcnt);
341 : :
342 [ - + + + : 96 : if (!key->removed && module->dump_info != NULL) {
+ - # # #
# # # #
# ]
343 [ # # # # : 90 : module->dump_info(key, w);
# # # # ]
344 : 0 : }
345 : 96 : }
346 : :
347 : : int
348 : 2144 : spdk_keyring_init(void)
349 : : {
350 : : struct spdk_keyring_module *module, *tmp;
351 : 803 : pthread_mutexattr_t attr;
352 : : int rc;
353 : :
354 [ + + ]: 2144 : rc = pthread_mutexattr_init(&attr);
355 [ - + ]: 2144 : if (rc != 0) {
356 : 0 : SPDK_ERRLOG("Failed to initialize mutex attr\n");
357 [ # # ]: 0 : return -rc;
358 : : }
359 : :
360 [ + + ]: 2144 : rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
361 [ - + ]: 2144 : if (rc != 0) {
362 : 0 : SPDK_ERRLOG("Failed to set mutex attr\n");
363 [ # # ]: 0 : pthread_mutexattr_destroy(&attr);
364 [ # # ]: 0 : return -rc;
365 : : }
366 : :
367 [ + + ]: 2144 : rc = pthread_mutex_init(&g_keyring.mutex, &attr);
368 [ + + ]: 2144 : if (rc != 0) {
369 : 0 : SPDK_ERRLOG("Failed to initialize mutex\n");
370 [ # # ]: 0 : pthread_mutexattr_destroy(&attr);
371 [ # # ]: 0 : return -rc;
372 : : }
373 : :
374 [ + + ]: 2144 : pthread_mutexattr_destroy(&attr);
375 [ + + + + : 6079 : TAILQ_FOREACH_SAFE(module, &g_keyring.modules, tailq, tmp) {
+ + + - +
- + - +
+ ]
376 [ + + + - : 3935 : if (module->init != NULL) {
+ + ]
377 [ + - + - : 1887 : rc = module->init();
- + + - ]
378 [ + + ]: 1887 : if (rc != 0) {
379 [ + + ]: 1884 : if (rc == -ENODEV) {
380 [ + + + + : 1884 : SPDK_INFOLOG(keyring, "Skipping module %s\n", module->name);
+ - # # #
# ]
381 [ + + + - : 1884 : TAILQ_REMOVE(&g_keyring.modules, module, tailq);
+ - - + #
# # # # #
# # # # #
# # # # #
# # + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ]
382 : 1884 : rc = 0;
383 : 1884 : continue;
384 : : }
385 : :
386 [ # # # # : 0 : SPDK_ERRLOG("Failed to initialize module %s: %s\n",
# # ]
387 : : module->name, spdk_strerror(-rc));
388 : 0 : break;
389 : : }
390 : 0 : }
391 : :
392 [ + + + + : 2051 : SPDK_INFOLOG(keyring, "Initialized module %s\n", module->name);
+ - # # #
# ]
393 : 93 : }
394 : :
395 [ + + ]: 2144 : if (rc != 0) {
396 [ # # # # : 0 : TAILQ_FOREACH(tmp, &g_keyring.modules, tailq) {
# # # # #
# # # ]
397 [ # # ]: 0 : if (tmp == module) {
398 : 0 : break;
399 : : }
400 [ # # # # : 0 : if (tmp->cleanup != NULL) {
# # ]
401 [ # # # # : 0 : tmp->cleanup();
# # # # ]
402 : 0 : }
403 : 0 : }
404 : 0 : }
405 : :
406 : 2144 : return rc;
407 : 97 : }
408 : :
409 : : void
410 : 2144 : spdk_keyring_cleanup(void)
411 : : {
412 : : struct spdk_keyring_module *module;
413 : : struct spdk_key *key;
414 : :
415 [ + + + - : 2342 : while (!TAILQ_EMPTY(&g_keyring.keys)) {
- + ]
416 [ # # # # ]: 198 : key = TAILQ_FIRST(&g_keyring.keys);
417 : 198 : keyring_remove_key(key);
418 : : }
419 : :
420 [ + + + - : 2144 : while (!TAILQ_EMPTY(&g_keyring.removed_keys)) {
- + ]
421 [ # # # # ]: 0 : key = TAILQ_FIRST(&g_keyring.removed_keys);
422 [ # # # # : 0 : SPDK_WARNLOG("Key '%s' still has %d references\n", key->name, key->refcnt);
# # # # ]
423 [ # # # # ]: 0 : key->refcnt = 0;
424 [ # # # # : 0 : TAILQ_REMOVE(&g_keyring.removed_keys, key, tailq);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
425 : 0 : keyring_free_key(key);
426 : : }
427 : :
428 [ + + + - : 4195 : TAILQ_FOREACH(module, &g_keyring.modules, tailq) {
+ + + - +
- + - ]
429 [ + + + - : 2051 : if (module->cleanup != NULL) {
+ - ]
430 [ # # # # : 0 : module->cleanup();
# # # # ]
431 : 0 : }
432 : 93 : }
433 : 2144 : }
434 : :
435 : 2583 : SPDK_LOG_REGISTER_COMPONENT(keyring)
|