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