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 0 : keyring_linux_get_opts(struct keyring_linux_opts *opts)
23 : {
24 0 : memcpy(opts, &g_opts, sizeof(*opts));
25 0 : }
26 :
27 : int
28 0 : keyring_linux_set_opts(struct keyring_linux_opts *opts)
29 : {
30 0 : g_opts.enable = opts->enable;
31 :
32 0 : return 0;
33 : }
34 :
35 : static int
36 0 : linux_find_key(const char *name, key_serial_t *outsn)
37 : {
38 0 : key_serial_t sn;
39 :
40 0 : sn = request_key("user", name, NULL, KEY_SPEC_SESSION_KEYRING);
41 0 : if (sn < 0) {
42 0 : return -errno;
43 : }
44 :
45 0 : if (outsn != NULL) {
46 0 : *outsn = sn;
47 0 : }
48 :
49 0 : return 0;
50 0 : }
51 :
52 : static int
53 0 : linux_probe_key(const char *name)
54 : {
55 0 : struct spdk_key_opts opts = {};
56 0 : int rc;
57 :
58 0 : rc = linux_find_key(name, NULL);
59 0 : if (rc != 0) {
60 0 : return rc;
61 : }
62 :
63 0 : opts.size = SPDK_SIZEOF(&opts, module);
64 0 : opts.name = name;
65 0 : opts.module = &g_keyring_linux;
66 :
67 0 : return spdk_keyring_add_key(&opts);
68 0 : }
69 :
70 : static int
71 0 : linux_add_key(struct spdk_key *key, void *ctx)
72 : {
73 0 : struct linux_key *lkey = spdk_key_get_ctx(key);
74 :
75 0 : return linux_find_key(spdk_key_get_name(key), &lkey->sn);
76 0 : }
77 :
78 : static void
79 0 : linux_remove_key(struct spdk_key *key)
80 : {
81 : /* no-op */
82 0 : }
83 :
84 : static int
85 0 : linux_get_key(struct spdk_key *key, void *buf, int len)
86 : {
87 0 : struct linux_key *lkey = spdk_key_get_ctx(key);
88 0 : int rc, errsv;
89 :
90 0 : rc = keyctl_read(lkey->sn, buf, len);
91 0 : 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 0 : 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 0 : return rc;
104 0 : }
105 :
106 : static size_t
107 0 : linux_get_ctx_size(void)
108 : {
109 0 : return sizeof(struct linux_key);
110 : }
111 :
112 : static void
113 0 : linux_dump_info(struct spdk_key *key, struct spdk_json_write_ctx *w)
114 : {
115 0 : struct linux_key *lkey = spdk_key_get_ctx(key);
116 :
117 0 : spdk_json_write_named_uint32(w, "sn", lkey->sn);
118 0 : }
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 0 : linux_init(void)
133 : {
134 0 : 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 0 : SPDK_KEYRING_REGISTER_MODULE(linux, &g_keyring_linux);
|