18db51b4eSKonrad Sztyber /* SPDX-License-Identifier: BSD-3-Clause 28db51b4eSKonrad Sztyber * Copyright (c) 2024 Intel Corporation. All rights reserved. 38db51b4eSKonrad Sztyber */ 48db51b4eSKonrad Sztyber 58db51b4eSKonrad Sztyber #include "spdk/keyring_module.h" 6*e93c9915SKonrad Sztyber #include "spdk/module/keyring/file.h" 78db51b4eSKonrad Sztyber #include "spdk/log.h" 88db51b4eSKonrad Sztyber #include "spdk/string.h" 98db51b4eSKonrad Sztyber #include "spdk/util.h" 108db51b4eSKonrad Sztyber 118db51b4eSKonrad Sztyber struct keyring_file_key { 128db51b4eSKonrad Sztyber char *path; 138db51b4eSKonrad Sztyber }; 148db51b4eSKonrad Sztyber 15*e93c9915SKonrad Sztyber static struct spdk_keyring_module g_keyring_file; 16*e93c9915SKonrad Sztyber 178db51b4eSKonrad Sztyber static int 188db51b4eSKonrad Sztyber keyring_file_check_path(const char *path, int *size) 198db51b4eSKonrad Sztyber { 208db51b4eSKonrad Sztyber struct stat st; 218db51b4eSKonrad Sztyber int rc, errsv; 228db51b4eSKonrad Sztyber 238db51b4eSKonrad Sztyber if (path[0] != '/') { 248db51b4eSKonrad Sztyber SPDK_ERRLOG("Non-absolute paths are not allowed: %s\n", path); 258db51b4eSKonrad Sztyber return -EPERM; 268db51b4eSKonrad Sztyber } 278db51b4eSKonrad Sztyber 288db51b4eSKonrad Sztyber rc = stat(path, &st); 298db51b4eSKonrad Sztyber if (rc != 0) { 308db51b4eSKonrad Sztyber errsv = errno; 318db51b4eSKonrad Sztyber SPDK_ERRLOG("Could not stat key file '%s': %s\n", path, spdk_strerror(errsv)); 328db51b4eSKonrad Sztyber return -errsv; 338db51b4eSKonrad Sztyber } 348db51b4eSKonrad Sztyber 358db51b4eSKonrad Sztyber if ((st.st_mode & 077) || st.st_uid != getuid()) { 368db51b4eSKonrad Sztyber SPDK_ERRLOG("Invalid permissions for key file '%s': 0%o\n", path, st.st_mode); 378db51b4eSKonrad Sztyber return -EPERM; 388db51b4eSKonrad Sztyber } 398db51b4eSKonrad Sztyber 408db51b4eSKonrad Sztyber if (size != NULL) { 418db51b4eSKonrad Sztyber *size = st.st_size; 428db51b4eSKonrad Sztyber } 438db51b4eSKonrad Sztyber 448db51b4eSKonrad Sztyber return 0; 458db51b4eSKonrad Sztyber } 468db51b4eSKonrad Sztyber 4705172c75SKonrad Sztyber static void 4805172c75SKonrad Sztyber keyring_file_write_key_config(void *ctx, struct spdk_key *key) 4905172c75SKonrad Sztyber { 5005172c75SKonrad Sztyber struct spdk_json_write_ctx *w = ctx; 5105172c75SKonrad Sztyber struct keyring_file_key *kkey; 5205172c75SKonrad Sztyber 5305172c75SKonrad Sztyber if (spdk_key_get_module(key) != &g_keyring_file) { 5405172c75SKonrad Sztyber return; 5505172c75SKonrad Sztyber } 5605172c75SKonrad Sztyber 5705172c75SKonrad Sztyber kkey = spdk_key_get_ctx(key); 5805172c75SKonrad Sztyber 5905172c75SKonrad Sztyber spdk_json_write_object_begin(w); 6005172c75SKonrad Sztyber spdk_json_write_named_string(w, "method", "keyring_file_add_key"); 6105172c75SKonrad Sztyber spdk_json_write_named_object_begin(w, "params"); 6205172c75SKonrad Sztyber spdk_json_write_named_string(w, "name", spdk_key_get_name(key)); 6305172c75SKonrad Sztyber spdk_json_write_named_string(w, "path", kkey->path); 6405172c75SKonrad Sztyber spdk_json_write_object_end(w); 6505172c75SKonrad Sztyber spdk_json_write_object_end(w); 6605172c75SKonrad Sztyber } 6705172c75SKonrad Sztyber 6805172c75SKonrad Sztyber static void 6905172c75SKonrad Sztyber keyring_file_write_config(struct spdk_json_write_ctx *w) 7005172c75SKonrad Sztyber { 7105172c75SKonrad Sztyber spdk_keyring_for_each_key(NULL, w, keyring_file_write_key_config, 0); 7205172c75SKonrad Sztyber } 7305172c75SKonrad Sztyber 7405172c75SKonrad Sztyber static void 7505172c75SKonrad Sztyber keyring_file_dump_info(struct spdk_key *key, struct spdk_json_write_ctx *w) 7605172c75SKonrad Sztyber { 7705172c75SKonrad Sztyber struct keyring_file_key *kkey = spdk_key_get_ctx(key); 7805172c75SKonrad Sztyber 7905172c75SKonrad Sztyber spdk_json_write_named_string(w, "path", kkey->path); 8005172c75SKonrad Sztyber } 8105172c75SKonrad Sztyber 828db51b4eSKonrad Sztyber static size_t 838db51b4eSKonrad Sztyber keyring_file_get_ctx_size(void) 848db51b4eSKonrad Sztyber { 858db51b4eSKonrad Sztyber return sizeof(struct keyring_file_key); 868db51b4eSKonrad Sztyber } 878db51b4eSKonrad Sztyber 888db51b4eSKonrad Sztyber static int 898db51b4eSKonrad Sztyber keyring_file_get_key(struct spdk_key *key, void *buf, int len) 908db51b4eSKonrad Sztyber { 918db51b4eSKonrad Sztyber struct keyring_file_key *kkey = spdk_key_get_ctx(key); 928db51b4eSKonrad Sztyber FILE *file; 938db51b4eSKonrad Sztyber int rc, errsv, size = 0; 948db51b4eSKonrad Sztyber 958db51b4eSKonrad Sztyber rc = keyring_file_check_path(kkey->path, &size); 968db51b4eSKonrad Sztyber if (rc != 0) { 978db51b4eSKonrad Sztyber return rc; 988db51b4eSKonrad Sztyber } 998db51b4eSKonrad Sztyber 1008db51b4eSKonrad Sztyber if (size > len) { 1018db51b4eSKonrad Sztyber SPDK_ERRLOG("Invalid key '%s' size: %d > %d\n", spdk_key_get_name(key), size, len); 1028db51b4eSKonrad Sztyber return -ENOBUFS; 1038db51b4eSKonrad Sztyber } 1048db51b4eSKonrad Sztyber 1058db51b4eSKonrad Sztyber file = fopen(kkey->path, "r"); 1068db51b4eSKonrad Sztyber if (!file) { 1078db51b4eSKonrad Sztyber errsv = errno; 1088db51b4eSKonrad Sztyber SPDK_ERRLOG("Could not open key '%s': %s\n", spdk_key_get_name(key), 1098db51b4eSKonrad Sztyber spdk_strerror(errsv)); 1108db51b4eSKonrad Sztyber return -errsv; 1118db51b4eSKonrad Sztyber } 1128db51b4eSKonrad Sztyber 1138db51b4eSKonrad Sztyber rc = (int)fread(buf, 1, size, file); 1148db51b4eSKonrad Sztyber if (rc != size) { 1158db51b4eSKonrad Sztyber SPDK_ERRLOG("Could not load key '%s'\n", spdk_key_get_name(key)); 1168db51b4eSKonrad Sztyber rc = -EIO; 1178db51b4eSKonrad Sztyber } 1188db51b4eSKonrad Sztyber 1198db51b4eSKonrad Sztyber fclose(file); 1208db51b4eSKonrad Sztyber 1218db51b4eSKonrad Sztyber return rc; 1228db51b4eSKonrad Sztyber } 1238db51b4eSKonrad Sztyber 1248db51b4eSKonrad Sztyber static void 1258db51b4eSKonrad Sztyber keyring_file_remove_key(struct spdk_key *key) 1268db51b4eSKonrad Sztyber { 1278db51b4eSKonrad Sztyber struct keyring_file_key *kkey = spdk_key_get_ctx(key); 1288db51b4eSKonrad Sztyber 1298db51b4eSKonrad Sztyber free(kkey->path); 1308db51b4eSKonrad Sztyber } 1318db51b4eSKonrad Sztyber 1328db51b4eSKonrad Sztyber static int 1338db51b4eSKonrad Sztyber keyring_file_add_key(struct spdk_key *key, void *ctx) 1348db51b4eSKonrad Sztyber { 1358db51b4eSKonrad Sztyber struct keyring_file_key *kkey = spdk_key_get_ctx(key); 136*e93c9915SKonrad Sztyber const char *path = ctx; 1378db51b4eSKonrad Sztyber int rc; 1388db51b4eSKonrad Sztyber 139*e93c9915SKonrad Sztyber rc = keyring_file_check_path(path, NULL); 1408db51b4eSKonrad Sztyber if (rc != 0) { 1418db51b4eSKonrad Sztyber return rc; 1428db51b4eSKonrad Sztyber } 1438db51b4eSKonrad Sztyber 144*e93c9915SKonrad Sztyber kkey->path = strdup(path); 1458db51b4eSKonrad Sztyber if (kkey->path == NULL) { 1468db51b4eSKonrad Sztyber return -ENOMEM; 1478db51b4eSKonrad Sztyber } 1488db51b4eSKonrad Sztyber 1498db51b4eSKonrad Sztyber return 0; 1508db51b4eSKonrad Sztyber } 1518db51b4eSKonrad Sztyber 152*e93c9915SKonrad Sztyber int 153*e93c9915SKonrad Sztyber spdk_keyring_file_add_key(const char *name, const char *path) 154*e93c9915SKonrad Sztyber { 155*e93c9915SKonrad Sztyber struct spdk_key_opts opts = {}; 156*e93c9915SKonrad Sztyber 157*e93c9915SKonrad Sztyber opts.size = SPDK_SIZEOF(&opts, ctx); 158*e93c9915SKonrad Sztyber opts.name = name; 159*e93c9915SKonrad Sztyber opts.module = &g_keyring_file; 160*e93c9915SKonrad Sztyber opts.ctx = (void *)path; 161*e93c9915SKonrad Sztyber 162*e93c9915SKonrad Sztyber return spdk_keyring_add_key(&opts); 163*e93c9915SKonrad Sztyber } 164*e93c9915SKonrad Sztyber 165*e93c9915SKonrad Sztyber int 166*e93c9915SKonrad Sztyber spdk_keyring_file_remove_key(const char *name) 167*e93c9915SKonrad Sztyber { 168*e93c9915SKonrad Sztyber return spdk_keyring_remove_key(name, &g_keyring_file); 169*e93c9915SKonrad Sztyber } 170*e93c9915SKonrad Sztyber 171*e93c9915SKonrad Sztyber static struct spdk_keyring_module g_keyring_file = { 1728db51b4eSKonrad Sztyber .name = "keyring_file", 1738db51b4eSKonrad Sztyber .add_key = keyring_file_add_key, 1748db51b4eSKonrad Sztyber .remove_key = keyring_file_remove_key, 1758db51b4eSKonrad Sztyber .get_key = keyring_file_get_key, 1768db51b4eSKonrad Sztyber .get_ctx_size = keyring_file_get_ctx_size, 17705172c75SKonrad Sztyber .dump_info = keyring_file_dump_info, 17805172c75SKonrad Sztyber .write_config = keyring_file_write_config, 1798db51b4eSKonrad Sztyber }; 1808db51b4eSKonrad Sztyber 1818db51b4eSKonrad Sztyber SPDK_KEYRING_REGISTER_MODULE(keyring_file, &g_keyring_file); 182