1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2018 Intel Corporation.
3 * All rights reserved.
4 * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
5 * All rights reserved.
6 */
7
8 #include "vbdev_crypto.h"
9
10 #include "spdk/hexlify.h"
11
12 /* Reasonable bdev name length + cipher's name len */
13 #define MAX_KEY_NAME_LEN 128
14
15 /* Structure to hold the parameters for this RPC method. */
16 struct rpc_construct_crypto {
17 char *base_bdev_name;
18 char *name;
19 char *crypto_pmd;
20 struct spdk_accel_crypto_key_create_param param;
21 };
22
23 /* Free the allocated memory resource after the RPC handling. */
24 static void
free_rpc_construct_crypto(struct rpc_construct_crypto * r)25 free_rpc_construct_crypto(struct rpc_construct_crypto *r)
26 {
27 free(r->base_bdev_name);
28 free(r->name);
29 free(r->crypto_pmd);
30 free(r->param.cipher);
31 if (r->param.hex_key) {
32 memset(r->param.hex_key, 0, strnlen(r->param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
33 free(r->param.hex_key);
34 }
35 if (r->param.hex_key2) {
36 memset(r->param.hex_key2, 0, strnlen(r->param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
37 free(r->param.hex_key2);
38 }
39 free(r->param.key_name);
40 }
41
42 /* Structure to decode the input parameters for this RPC method. */
43 static const struct spdk_json_object_decoder rpc_construct_crypto_decoders[] = {
44 {"base_bdev_name", offsetof(struct rpc_construct_crypto, base_bdev_name), spdk_json_decode_string},
45 {"name", offsetof(struct rpc_construct_crypto, name), spdk_json_decode_string},
46 {"crypto_pmd", offsetof(struct rpc_construct_crypto, crypto_pmd), spdk_json_decode_string, true},
47 {"key", offsetof(struct rpc_construct_crypto, param.hex_key), spdk_json_decode_string, true},
48 {"cipher", offsetof(struct rpc_construct_crypto, param.cipher), spdk_json_decode_string, true},
49 {"key2", offsetof(struct rpc_construct_crypto, param.hex_key2), spdk_json_decode_string, true},
50 {"key_name", offsetof(struct rpc_construct_crypto, param.key_name), spdk_json_decode_string, true},
51 };
52
53 static struct vbdev_crypto_opts *
create_crypto_opts(struct rpc_construct_crypto * rpc,struct spdk_accel_crypto_key * key,bool key_owner)54 create_crypto_opts(struct rpc_construct_crypto *rpc, struct spdk_accel_crypto_key *key,
55 bool key_owner)
56 {
57 struct vbdev_crypto_opts *opts = calloc(1, sizeof(*opts));
58
59 if (!opts) {
60 return NULL;
61 }
62
63 opts->bdev_name = strdup(rpc->base_bdev_name);
64 if (!opts->bdev_name) {
65 free_crypto_opts(opts);
66 return NULL;
67 }
68 opts->vbdev_name = strdup(rpc->name);
69 if (!opts->vbdev_name) {
70 free_crypto_opts(opts);
71 return NULL;
72 }
73
74 opts->key = key;
75 opts->key_owner = key_owner;
76
77 return opts;
78 }
79
80 /* Decode the parameters for this RPC method and properly construct the crypto
81 * device. Error status returned in the failed cases.
82 */
83 static void
rpc_bdev_crypto_create(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)84 rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request,
85 const struct spdk_json_val *params)
86 {
87 struct rpc_construct_crypto req = {};
88 struct vbdev_crypto_opts *crypto_opts = NULL;
89 struct spdk_json_write_ctx *w;
90 struct spdk_accel_crypto_key *key = NULL;
91 struct spdk_accel_crypto_key *created_key = NULL;
92 int rc = 0;
93
94 if (spdk_json_decode_object(params, rpc_construct_crypto_decoders,
95 SPDK_COUNTOF(rpc_construct_crypto_decoders),
96 &req)) {
97 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
98 "Failed to decode crypto disk create parameters.");
99 goto cleanup;
100 }
101
102 if (!req.name) {
103 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
104 "crypto_bdev name is missing");
105 goto cleanup;
106 }
107
108 if (req.param.key_name) {
109 /* New config version */
110 key = spdk_accel_crypto_key_get(req.param.key_name);
111 if (key) {
112 if (req.param.hex_key || req.param.cipher || req.crypto_pmd) {
113 SPDK_NOTICELOG("Key name specified, other parameters are ignored\n");
114 }
115 SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
116 }
117 }
118
119 /* No key_name. Support legacy configuration */
120 if (!key) {
121 if (req.param.key_name) {
122 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
123 "Key was not found");
124 goto cleanup;
125 }
126
127 if (req.param.cipher == NULL) {
128 req.param.cipher = strdup(BDEV_CRYPTO_DEFAULT_CIPHER);
129 if (req.param.cipher == NULL) {
130 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
131 "Unable to allocate memory for req.cipher");
132 goto cleanup;
133 }
134 }
135 if (req.crypto_pmd) {
136 SPDK_WARNLOG("\"crypto_pmd\" parameters is obsolete and ignored\n");
137 }
138
139 req.param.key_name = calloc(1, MAX_KEY_NAME_LEN);
140 if (!req.param.key_name) {
141 /* The new API requires key name. Create it as pmd_name + cipher */
142 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
143 "Unable to allocate memory for key_name");
144 goto cleanup;
145 }
146 snprintf(req.param.key_name, MAX_KEY_NAME_LEN, "%s_%s", req.name, req.param.cipher);
147
148 /* Try to find a key with generated name, we may be loading from a json config where crypto_bdev had no key_name parameter */
149 key = spdk_accel_crypto_key_get(req.param.key_name);
150 if (key) {
151 SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
152 } else {
153 rc = spdk_accel_crypto_key_create(&req.param);
154 if (!rc) {
155 key = spdk_accel_crypto_key_get(req.param.key_name);
156 created_key = key;
157 }
158 }
159 }
160
161 if (!key) {
162 /* We haven't found an existing key or were not able to create a new one */
163 SPDK_ERRLOG("No key was found\n");
164 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
165 "No key was found");
166 goto cleanup;
167 }
168
169 crypto_opts = create_crypto_opts(&req, key, created_key != NULL);
170 if (!crypto_opts) {
171 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
172 "Memory allocation failed");
173 goto cleanup;
174 }
175
176 rc = create_crypto_disk(crypto_opts);
177 if (rc) {
178 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
179 free_crypto_opts(crypto_opts);
180 goto cleanup;
181 }
182
183 w = spdk_jsonrpc_begin_result(request);
184 spdk_json_write_string(w, req.name);
185 spdk_jsonrpc_end_result(request, w);
186
187 cleanup:
188 if (rc && created_key) {
189 spdk_accel_crypto_key_destroy(created_key);
190 }
191 free_rpc_construct_crypto(&req);
192 }
193 SPDK_RPC_REGISTER("bdev_crypto_create", rpc_bdev_crypto_create, SPDK_RPC_RUNTIME)
194
195 struct rpc_delete_crypto {
196 char *name;
197 };
198
199 static void
free_rpc_delete_crypto(struct rpc_delete_crypto * req)200 free_rpc_delete_crypto(struct rpc_delete_crypto *req)
201 {
202 free(req->name);
203 }
204
205 static const struct spdk_json_object_decoder rpc_delete_crypto_decoders[] = {
206 {"name", offsetof(struct rpc_delete_crypto, name), spdk_json_decode_string},
207 };
208
209 static void
rpc_bdev_crypto_delete_cb(void * cb_arg,int bdeverrno)210 rpc_bdev_crypto_delete_cb(void *cb_arg, int bdeverrno)
211 {
212 struct spdk_jsonrpc_request *request = cb_arg;
213
214 if (bdeverrno == 0) {
215 spdk_jsonrpc_send_bool_response(request, true);
216 } else {
217 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
218 }
219 }
220
221 static void
rpc_bdev_crypto_delete(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)222 rpc_bdev_crypto_delete(struct spdk_jsonrpc_request *request,
223 const struct spdk_json_val *params)
224 {
225 struct rpc_delete_crypto req = {NULL};
226
227 if (spdk_json_decode_object(params, rpc_delete_crypto_decoders,
228 SPDK_COUNTOF(rpc_delete_crypto_decoders),
229 &req)) {
230 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
231 "Invalid parameters");
232 goto cleanup;
233 }
234
235 delete_crypto_disk(req.name, rpc_bdev_crypto_delete_cb, request);
236
237 free_rpc_delete_crypto(&req);
238
239 return;
240
241 cleanup:
242 free_rpc_delete_crypto(&req);
243 }
244 SPDK_RPC_REGISTER("bdev_crypto_delete", rpc_bdev_crypto_delete, SPDK_RPC_RUNTIME)
245