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
keyring_linux_get_opts(struct keyring_linux_opts * opts)22 keyring_linux_get_opts(struct keyring_linux_opts *opts)
23 {
24 memcpy(opts, &g_opts, sizeof(*opts));
25 }
26
27 int
keyring_linux_set_opts(struct keyring_linux_opts * opts)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
linux_find_key(const char * name,key_serial_t * outsn)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
linux_probe_key(const char * name)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
linux_add_key(struct spdk_key * key,void * ctx)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
linux_remove_key(struct spdk_key * key)79 linux_remove_key(struct spdk_key *key)
80 {
81 /* no-op */
82 }
83
84 static int
linux_get_key(struct spdk_key * key,void * buf,int len)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
linux_get_ctx_size(void)107 linux_get_ctx_size(void)
108 {
109 return sizeof(struct linux_key);
110 }
111
112 static void
linux_dump_info(struct spdk_key * key,struct spdk_json_write_ctx * w)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
linux_write_config(struct spdk_json_write_ctx * w)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
linux_init(void)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