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 int 154 spdk_keyring_remove_key(const char *name, struct spdk_keyring_module *module) 155 { 156 struct spdk_key *key; 157 int rc = 0; 158 159 pthread_mutex_lock(&g_keyring.mutex); 160 key = keyring_find_key(name); 161 if (key == NULL) { 162 SPDK_ERRLOG("Key '%s' does not exist\n", name); 163 rc = -ENOKEY; 164 goto out; 165 } 166 167 if (key->module != module) { 168 SPDK_ERRLOG("Key '%s' is not owned by module '%s'\n", name, module->name); 169 rc = -EINVAL; 170 goto out; 171 } 172 173 keyring_remove_key(key); 174 out: 175 pthread_mutex_unlock(&g_keyring.mutex); 176 return rc; 177 } 178 179 static struct spdk_key * 180 keyring_probe_key(const char *name) 181 { 182 struct spdk_keyring_module *module; 183 struct spdk_key *key = NULL; 184 int rc; 185 186 TAILQ_FOREACH(module, &g_keyring.modules, tailq) { 187 if (module->probe_key == NULL) { 188 continue; 189 } 190 191 rc = module->probe_key(name); 192 if (rc == 0) { 193 key = keyring_find_key(name); 194 if (key == NULL) { 195 SPDK_ERRLOG("Successfully probed key '%s' using module '%s', but " 196 "the key is unavailable\n", name, module->name); 197 return NULL; 198 } 199 200 key->probed = true; 201 break; 202 } else if (rc != -ENOKEY) { 203 /* The module is aware of the key but couldn't instantiate it */ 204 assert(keyring_find_key(name) == NULL); 205 SPDK_ERRLOG("Failed to probe key '%s' using module '%s': %s\n", 206 name, module->name, spdk_strerror(-rc)); 207 break; 208 } 209 } 210 211 return key; 212 } 213 214 struct spdk_key * 215 spdk_keyring_get_key(const char *name) 216 { 217 struct spdk_key *key; 218 219 pthread_mutex_lock(&g_keyring.mutex); 220 key = keyring_find_key(name); 221 if (key == NULL) { 222 key = keyring_probe_key(name); 223 if (key == NULL) { 224 goto out; 225 } 226 } 227 228 key->refcnt++; 229 out: 230 pthread_mutex_unlock(&g_keyring.mutex); 231 232 return key; 233 } 234 235 void 236 spdk_keyring_put_key(struct spdk_key *key) 237 { 238 int refcnt; 239 240 if (key == NULL) { 241 return; 242 } 243 244 pthread_mutex_lock(&g_keyring.mutex); 245 refcnt = keyring_put_key(key); 246 if (refcnt == 1 && key->probed && !key->removed) { 247 keyring_remove_key(key); 248 } 249 pthread_mutex_unlock(&g_keyring.mutex); 250 } 251 252 struct spdk_key * 253 spdk_key_dup(struct spdk_key *key) 254 { 255 pthread_mutex_lock(&g_keyring.mutex); 256 key->refcnt++; 257 pthread_mutex_unlock(&g_keyring.mutex); 258 259 return key; 260 } 261 262 const char * 263 spdk_key_get_name(struct spdk_key *key) 264 { 265 return key->name; 266 } 267 268 int 269 spdk_key_get_key(struct spdk_key *key, void *buf, int len) 270 { 271 struct spdk_keyring_module *module = key->module; 272 273 if (key->removed) { 274 return -ENOKEY; 275 } 276 277 return module->get_key(key, buf, len); 278 } 279 280 void * 281 spdk_key_get_ctx(struct spdk_key *key) 282 { 283 return key + 1; 284 } 285 286 287 struct spdk_keyring_module * 288 spdk_key_get_module(struct spdk_key *key) 289 { 290 return key->module; 291 } 292 293 void 294 spdk_keyring_write_config(struct spdk_json_write_ctx *w) 295 { 296 struct spdk_keyring_module *module; 297 298 TAILQ_FOREACH(module, &g_keyring.modules, tailq) { 299 if (module->write_config != NULL) { 300 module->write_config(w); 301 } 302 } 303 } 304 305 void 306 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 assert(keyring == NULL); 312 pthread_mutex_lock(&g_keyring.mutex); 313 TAILQ_FOREACH_SAFE(key, &g_keyring.keys, tailq, tmp) { 314 fn(ctx, key); 315 } 316 317 if (flags & SPDK_KEYRING_FOR_EACH_ALL) { 318 TAILQ_FOREACH_SAFE(key, &g_keyring.removed_keys, tailq, tmp) { 319 fn(ctx, key); 320 } 321 } 322 pthread_mutex_unlock(&g_keyring.mutex); 323 } 324 325 void 326 spdk_keyring_register_module(struct spdk_keyring_module *module) 327 { 328 TAILQ_INSERT_TAIL(&g_keyring.modules, module, tailq); 329 } 330 331 void 332 keyring_dump_key_info(struct spdk_key *key, struct spdk_json_write_ctx *w) 333 { 334 struct spdk_keyring_module *module = key->module; 335 336 spdk_json_write_named_string(w, "name", key->name); 337 spdk_json_write_named_string(w, "module", module->name); 338 spdk_json_write_named_bool(w, "removed", key->removed); 339 spdk_json_write_named_bool(w, "probed", key->probed); 340 spdk_json_write_named_int32(w, "refcnt", key->refcnt); 341 342 if (!key->removed && module->dump_info != NULL) { 343 module->dump_info(key, w); 344 } 345 } 346 347 int 348 spdk_keyring_init(void) 349 { 350 struct spdk_keyring_module *module, *tmp; 351 pthread_mutexattr_t attr; 352 int rc; 353 354 rc = pthread_mutexattr_init(&attr); 355 if (rc != 0) { 356 SPDK_ERRLOG("Failed to initialize mutex attr\n"); 357 return -rc; 358 } 359 360 rc = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 361 if (rc != 0) { 362 SPDK_ERRLOG("Failed to set mutex attr\n"); 363 pthread_mutexattr_destroy(&attr); 364 return -rc; 365 } 366 367 rc = pthread_mutex_init(&g_keyring.mutex, &attr); 368 if (rc != 0) { 369 SPDK_ERRLOG("Failed to initialize mutex\n"); 370 pthread_mutexattr_destroy(&attr); 371 return -rc; 372 } 373 374 pthread_mutexattr_destroy(&attr); 375 TAILQ_FOREACH_SAFE(module, &g_keyring.modules, tailq, tmp) { 376 if (module->init != NULL) { 377 rc = module->init(); 378 if (rc != 0) { 379 if (rc == -ENODEV) { 380 SPDK_INFOLOG(keyring, "Skipping module %s\n", module->name); 381 TAILQ_REMOVE(&g_keyring.modules, module, tailq); 382 rc = 0; 383 continue; 384 } 385 386 SPDK_ERRLOG("Failed to initialize module %s: %s\n", 387 module->name, spdk_strerror(-rc)); 388 break; 389 } 390 } 391 392 SPDK_INFOLOG(keyring, "Initialized module %s\n", module->name); 393 } 394 395 if (rc != 0) { 396 TAILQ_FOREACH(tmp, &g_keyring.modules, tailq) { 397 if (tmp == module) { 398 break; 399 } 400 if (tmp->cleanup != NULL) { 401 tmp->cleanup(); 402 } 403 } 404 } 405 406 return rc; 407 } 408 409 void 410 spdk_keyring_cleanup(void) 411 { 412 struct spdk_keyring_module *module; 413 struct spdk_key *key; 414 415 while (!TAILQ_EMPTY(&g_keyring.keys)) { 416 key = TAILQ_FIRST(&g_keyring.keys); 417 keyring_remove_key(key); 418 } 419 420 while (!TAILQ_EMPTY(&g_keyring.removed_keys)) { 421 key = TAILQ_FIRST(&g_keyring.removed_keys); 422 SPDK_WARNLOG("Key '%s' still has %d references\n", key->name, key->refcnt); 423 key->refcnt = 0; 424 TAILQ_REMOVE(&g_keyring.removed_keys, key, tailq); 425 keyring_free_key(key); 426 } 427 428 TAILQ_FOREACH(module, &g_keyring.modules, tailq) { 429 if (module->cleanup != NULL) { 430 module->cleanup(); 431 } 432 } 433 } 434 435 SPDK_LOG_REGISTER_COMPONENT(keyring) 436