Branch data Line data Source code
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 : 3 : keyring_linux_get_opts(struct keyring_linux_opts *opts)
23 : : {
24 : 3 : memcpy(opts, &g_opts, sizeof(*opts));
25 : 3 : }
26 : :
27 : : int
28 : 3 : keyring_linux_set_opts(struct keyring_linux_opts *opts)
29 : : {
30 [ - + ]: 3 : g_opts.enable = opts->enable;
31 : :
32 : 3 : return 0;
33 : : }
34 : :
35 : : static int
36 : 12 : linux_find_key(const char *name, key_serial_t *outsn)
37 : : {
38 : : key_serial_t sn;
39 : :
40 : 12 : sn = request_key("user", name, NULL, KEY_SPEC_SESSION_KEYRING);
41 [ - + ]: 12 : if (sn < 0) {
42 : 0 : return -errno;
43 : : }
44 : :
45 [ + + ]: 12 : if (outsn != NULL) {
46 : 6 : *outsn = sn;
47 : : }
48 : :
49 : 12 : return 0;
50 : : }
51 : :
52 : : static int
53 : 6 : linux_probe_key(const char *name)
54 : : {
55 : 6 : struct spdk_key_opts opts = {};
56 : : int rc;
57 : :
58 : 6 : rc = linux_find_key(name, NULL);
59 [ - + ]: 6 : if (rc != 0) {
60 : 0 : return rc;
61 : : }
62 : :
63 : 6 : opts.size = SPDK_SIZEOF(&opts, module);
64 : 6 : opts.name = name;
65 : 6 : opts.module = &g_keyring_linux;
66 : :
67 : 6 : return spdk_keyring_add_key(&opts);
68 : : }
69 : :
70 : : static int
71 : 6 : linux_add_key(struct spdk_key *key, void *ctx)
72 : : {
73 : 6 : struct linux_key *lkey = spdk_key_get_ctx(key);
74 : :
75 : 6 : return linux_find_key(spdk_key_get_name(key), &lkey->sn);
76 : : }
77 : :
78 : : static void
79 : 6 : linux_remove_key(struct spdk_key *key)
80 : : {
81 : : /* no-op */
82 : 6 : }
83 : :
84 : : static int
85 : 6 : linux_get_key(struct spdk_key *key, void *buf, int len)
86 : : {
87 : 6 : struct linux_key *lkey = spdk_key_get_ctx(key);
88 : : int rc, errsv;
89 : :
90 : 6 : rc = keyctl_read(lkey->sn, buf, len);
91 [ - + ]: 6 : if (rc < 0) {
92 : 0 : errsv = errno;
93 : 0 : SPDK_ERRLOG("Failed to read key '%s': %s\n", spdk_key_get_name(key),
94 : : spdk_strerror(errsv));
95 : 0 : return -errsv;
96 : : }
97 : :
98 [ - + ]: 6 : if (rc > len) {
99 : 0 : SPDK_ERRLOG("Failed to read key '%s': buffer to small\n", spdk_key_get_name(key));
100 : 0 : return -ENOBUFS;
101 : : }
102 : :
103 : 6 : return rc;
104 : : }
105 : :
106 : : static size_t
107 : 6 : linux_get_ctx_size(void)
108 : : {
109 : 6 : return sizeof(struct linux_key);
110 : : }
111 : :
112 : : static void
113 : 6 : linux_dump_info(struct spdk_key *key, struct spdk_json_write_ctx *w)
114 : : {
115 : 6 : struct linux_key *lkey = spdk_key_get_ctx(key);
116 : :
117 : 6 : spdk_json_write_named_uint32(w, "sn", lkey->sn);
118 : 6 : }
119 : :
120 : : static void
121 : 0 : linux_write_config(struct spdk_json_write_ctx *w)
122 : : {
123 : 0 : spdk_json_write_object_begin(w);
124 : 0 : spdk_json_write_named_string(w, "method", "keyring_linux_set_options");
125 : 0 : spdk_json_write_named_object_begin(w, "params");
126 [ # # ]: 0 : spdk_json_write_named_bool(w, "enable", g_opts.enable);
127 : 0 : spdk_json_write_object_end(w);
128 : 0 : spdk_json_write_object_end(w);
129 : 0 : }
130 : :
131 : : static int
132 : 1778 : linux_init(void)
133 : : {
134 [ - + + + ]: 1778 : 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 : 1930 : SPDK_KEYRING_REGISTER_MODULE(linux, &g_keyring_linux);
|