1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2024 Intel Corporation. All rights reserved. 3 */ 4 5 #include <keyutils.h> 6 #include "keyring_linux.h" 7 #include "spdk/keyring.h" 8 #include "spdk/keyring_module.h" 9 #include "spdk/log.h" 10 #include "spdk/string.h" 11 #include "spdk/util.h" 12 13 static struct keyring_linux_opts g_opts; 14 15 struct linux_key { 16 key_serial_t sn; 17 }; 18 19 static struct spdk_keyring_module g_keyring_linux; 20 21 void 22 keyring_linux_get_opts(struct keyring_linux_opts *opts) 23 { 24 memcpy(opts, &g_opts, sizeof(*opts)); 25 } 26 27 int 28 keyring_linux_set_opts(struct keyring_linux_opts *opts) 29 { 30 g_opts.enable = opts->enable; 31 32 return 0; 33 } 34 35 static int 36 linux_find_key(const char *name, key_serial_t *outsn) 37 { 38 key_serial_t sn; 39 40 sn = request_key("user", name, NULL, KEY_SPEC_SESSION_KEYRING); 41 if (sn < 0) { 42 return -errno; 43 } 44 45 if (outsn != NULL) { 46 *outsn = sn; 47 } 48 49 return 0; 50 } 51 52 static int 53 linux_probe_key(const char *name) 54 { 55 struct spdk_key_opts opts = {}; 56 int rc; 57 58 rc = linux_find_key(name, NULL); 59 if (rc != 0) { 60 return rc; 61 } 62 63 opts.size = SPDK_SIZEOF(&opts, module); 64 opts.name = name; 65 opts.module = &g_keyring_linux; 66 67 return spdk_keyring_add_key(&opts); 68 } 69 70 static int 71 linux_add_key(struct spdk_key *key, void *ctx) 72 { 73 struct linux_key *lkey = spdk_key_get_ctx(key); 74 75 return linux_find_key(spdk_key_get_name(key), &lkey->sn); 76 } 77 78 static void 79 linux_remove_key(struct spdk_key *key) 80 { 81 /* no-op */ 82 } 83 84 static int 85 linux_get_key(struct spdk_key *key, void *buf, int len) 86 { 87 struct linux_key *lkey = spdk_key_get_ctx(key); 88 int rc, errsv; 89 90 rc = keyctl_read(lkey->sn, buf, len); 91 if (rc < 0) { 92 errsv = errno; 93 SPDK_ERRLOG("Failed to read key '%s': %s\n", spdk_key_get_name(key), 94 spdk_strerror(errsv)); 95 return -errsv; 96 } 97 98 if (rc > len) { 99 SPDK_ERRLOG("Failed to read key '%s': buffer to small\n", spdk_key_get_name(key)); 100 return -ENOBUFS; 101 } 102 103 return rc; 104 } 105 106 static size_t 107 linux_get_ctx_size(void) 108 { 109 return sizeof(struct linux_key); 110 } 111 112 static void 113 linux_dump_info(struct spdk_key *key, struct spdk_json_write_ctx *w) 114 { 115 struct linux_key *lkey = spdk_key_get_ctx(key); 116 117 spdk_json_write_named_uint32(w, "sn", lkey->sn); 118 } 119 120 static void 121 linux_write_config(struct spdk_json_write_ctx *w) 122 { 123 spdk_json_write_object_begin(w); 124 spdk_json_write_named_string(w, "method", "keyring_linux_set_options"); 125 spdk_json_write_named_object_begin(w, "params"); 126 spdk_json_write_named_bool(w, "enable", g_opts.enable); 127 spdk_json_write_object_end(w); 128 spdk_json_write_object_end(w); 129 } 130 131 static int 132 linux_init(void) 133 { 134 return g_opts.enable ? 0 : -ENODEV; 135 } 136 137 static struct spdk_keyring_module g_keyring_linux = { 138 .name = "linux", 139 .init = linux_init, 140 .probe_key = linux_probe_key, 141 .add_key = linux_add_key, 142 .remove_key = linux_remove_key, 143 .get_key = linux_get_key, 144 .get_ctx_size = linux_get_ctx_size, 145 .dump_info = linux_dump_info, 146 .write_config = linux_write_config, 147 }; 148 SPDK_KEYRING_REGISTER_MODULE(linux, &g_keyring_linux); 149