Line data Source code
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
25 0 : free_rpc_construct_crypto(struct rpc_construct_crypto *r)
26 : {
27 0 : free(r->base_bdev_name);
28 0 : free(r->name);
29 0 : free(r->crypto_pmd);
30 0 : free(r->param.cipher);
31 0 : if (r->param.hex_key) {
32 0 : memset(r->param.hex_key, 0, strnlen(r->param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
33 0 : free(r->param.hex_key);
34 0 : }
35 0 : if (r->param.hex_key2) {
36 0 : memset(r->param.hex_key2, 0, strnlen(r->param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
37 0 : free(r->param.hex_key2);
38 0 : }
39 0 : free(r->param.key_name);
40 0 : }
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 *
54 0 : create_crypto_opts(struct rpc_construct_crypto *rpc, struct spdk_accel_crypto_key *key,
55 : bool key_owner)
56 : {
57 0 : struct vbdev_crypto_opts *opts = calloc(1, sizeof(*opts));
58 :
59 0 : if (!opts) {
60 0 : return NULL;
61 : }
62 :
63 0 : opts->bdev_name = strdup(rpc->base_bdev_name);
64 0 : if (!opts->bdev_name) {
65 0 : free_crypto_opts(opts);
66 0 : return NULL;
67 : }
68 0 : opts->vbdev_name = strdup(rpc->name);
69 0 : if (!opts->vbdev_name) {
70 0 : free_crypto_opts(opts);
71 0 : return NULL;
72 : }
73 :
74 0 : opts->key = key;
75 0 : opts->key_owner = key_owner;
76 :
77 0 : return opts;
78 0 : }
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
84 0 : rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request,
85 : const struct spdk_json_val *params)
86 : {
87 0 : struct rpc_construct_crypto req = {};
88 0 : struct vbdev_crypto_opts *crypto_opts = NULL;
89 0 : struct spdk_json_write_ctx *w;
90 0 : struct spdk_accel_crypto_key *key = NULL;
91 0 : struct spdk_accel_crypto_key *created_key = NULL;
92 0 : int rc = 0;
93 :
94 0 : if (spdk_json_decode_object(params, rpc_construct_crypto_decoders,
95 : SPDK_COUNTOF(rpc_construct_crypto_decoders),
96 : &req)) {
97 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
98 : "Failed to decode crypto disk create parameters.");
99 0 : goto cleanup;
100 : }
101 :
102 0 : if (!req.name) {
103 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
104 : "crypto_bdev name is missing");
105 0 : goto cleanup;
106 : }
107 :
108 0 : if (req.param.key_name) {
109 : /* New config version */
110 0 : key = spdk_accel_crypto_key_get(req.param.key_name);
111 0 : if (key) {
112 0 : if (req.param.hex_key || req.param.cipher || req.crypto_pmd) {
113 0 : SPDK_NOTICELOG("Key name specified, other parameters are ignored\n");
114 0 : }
115 0 : SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
116 0 : }
117 0 : }
118 :
119 : /* No key_name. Support legacy configuration */
120 0 : if (!key) {
121 0 : if (req.param.key_name) {
122 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
123 : "Key was not found");
124 0 : goto cleanup;
125 : }
126 :
127 0 : if (req.param.cipher == NULL) {
128 0 : req.param.cipher = strdup(BDEV_CRYPTO_DEFAULT_CIPHER);
129 0 : if (req.param.cipher == NULL) {
130 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
131 : "Unable to allocate memory for req.cipher");
132 0 : goto cleanup;
133 : }
134 0 : }
135 0 : if (req.crypto_pmd) {
136 0 : SPDK_WARNLOG("\"crypto_pmd\" parameters is obsolete and ignored\n");
137 0 : }
138 :
139 0 : req.param.key_name = calloc(1, MAX_KEY_NAME_LEN);
140 0 : if (!req.param.key_name) {
141 : /* The new API requires key name. Create it as pmd_name + cipher */
142 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
143 : "Unable to allocate memory for key_name");
144 0 : goto cleanup;
145 : }
146 0 : 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 0 : key = spdk_accel_crypto_key_get(req.param.key_name);
150 0 : if (key) {
151 0 : SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
152 0 : } else {
153 0 : rc = spdk_accel_crypto_key_create(&req.param);
154 0 : if (!rc) {
155 0 : key = spdk_accel_crypto_key_get(req.param.key_name);
156 0 : created_key = key;
157 0 : }
158 : }
159 0 : }
160 :
161 0 : if (!key) {
162 : /* We haven't found an existing key or were not able to create a new one */
163 0 : SPDK_ERRLOG("No key was found\n");
164 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
165 : "No key was found");
166 0 : goto cleanup;
167 : }
168 :
169 0 : crypto_opts = create_crypto_opts(&req, key, created_key != NULL);
170 0 : if (!crypto_opts) {
171 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
172 : "Memory allocation failed");
173 0 : goto cleanup;
174 : }
175 :
176 0 : rc = create_crypto_disk(crypto_opts);
177 0 : if (rc) {
178 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
179 0 : free_crypto_opts(crypto_opts);
180 0 : goto cleanup;
181 : }
182 :
183 0 : w = spdk_jsonrpc_begin_result(request);
184 0 : spdk_json_write_string(w, req.name);
185 0 : spdk_jsonrpc_end_result(request, w);
186 :
187 : cleanup:
188 0 : if (rc && created_key) {
189 0 : spdk_accel_crypto_key_destroy(created_key);
190 0 : }
191 0 : free_rpc_construct_crypto(&req);
192 0 : }
193 0 : 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
200 0 : free_rpc_delete_crypto(struct rpc_delete_crypto *req)
201 : {
202 0 : free(req->name);
203 0 : }
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
210 0 : rpc_bdev_crypto_delete_cb(void *cb_arg, int bdeverrno)
211 : {
212 0 : struct spdk_jsonrpc_request *request = cb_arg;
213 :
214 0 : if (bdeverrno == 0) {
215 0 : spdk_jsonrpc_send_bool_response(request, true);
216 0 : } else {
217 0 : spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
218 : }
219 0 : }
220 :
221 : static void
222 0 : rpc_bdev_crypto_delete(struct spdk_jsonrpc_request *request,
223 : const struct spdk_json_val *params)
224 : {
225 0 : struct rpc_delete_crypto req = {NULL};
226 :
227 0 : if (spdk_json_decode_object(params, rpc_delete_crypto_decoders,
228 : SPDK_COUNTOF(rpc_delete_crypto_decoders),
229 : &req)) {
230 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
231 : "Invalid parameters");
232 0 : goto cleanup;
233 : }
234 :
235 0 : delete_crypto_disk(req.name, rpc_bdev_crypto_delete_cb, request);
236 :
237 0 : free_rpc_delete_crypto(&req);
238 :
239 0 : return;
240 :
241 : cleanup:
242 0 : free_rpc_delete_crypto(&req);
243 0 : }
244 0 : SPDK_RPC_REGISTER("bdev_crypto_delete", rpc_bdev_crypto_delete, SPDK_RPC_RUNTIME)
|