Branch data 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 : 114 : free_rpc_construct_crypto(struct rpc_construct_crypto *r)
26 : : {
27 : 114 : free(r->base_bdev_name);
28 : 114 : free(r->name);
29 : 114 : free(r->crypto_pmd);
30 : 114 : free(r->param.cipher);
31 [ + + ]: 114 : if (r->param.hex_key) {
32 [ - + - + ]: 5 : memset(r->param.hex_key, 0, strnlen(r->param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH));
33 : 5 : free(r->param.hex_key);
34 : : }
35 [ - + ]: 114 : 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 : : }
39 : 114 : free(r->param.key_name);
40 : 114 : }
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 : 114 : create_crypto_opts(struct rpc_construct_crypto *rpc, struct spdk_accel_crypto_key *key,
55 : : bool key_owner)
56 : : {
57 : 114 : struct vbdev_crypto_opts *opts = calloc(1, sizeof(*opts));
58 : :
59 [ - + ]: 114 : if (!opts) {
60 : 0 : return NULL;
61 : : }
62 : :
63 [ - + ]: 114 : opts->bdev_name = strdup(rpc->base_bdev_name);
64 [ - + ]: 114 : if (!opts->bdev_name) {
65 : 0 : free_crypto_opts(opts);
66 : 0 : return NULL;
67 : : }
68 [ - + ]: 114 : opts->vbdev_name = strdup(rpc->name);
69 [ - + ]: 114 : if (!opts->vbdev_name) {
70 : 0 : free_crypto_opts(opts);
71 : 0 : return NULL;
72 : : }
73 : :
74 : 114 : opts->key = key;
75 : 114 : opts->key_owner = key_owner;
76 : :
77 : 114 : 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
84 : 114 : rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request,
85 : : const struct spdk_json_val *params)
86 : : {
87 : 114 : struct rpc_construct_crypto req = {};
88 : 114 : struct vbdev_crypto_opts *crypto_opts = NULL;
89 : : struct spdk_json_write_ctx *w;
90 : 114 : struct spdk_accel_crypto_key *key = NULL;
91 : 114 : struct spdk_accel_crypto_key *created_key = NULL;
92 : 114 : int rc = 0;
93 : :
94 [ - + ]: 114 : 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 [ - + ]: 114 : 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 [ + + ]: 114 : if (req.param.key_name) {
109 : : /* New config version */
110 : 109 : key = spdk_accel_crypto_key_get(req.param.key_name);
111 [ + - ]: 109 : if (key) {
112 [ + - + - : 109 : if (req.param.hex_key || req.param.cipher || req.crypto_pmd) {
- + ]
113 : 0 : SPDK_NOTICELOG("Key name specified, other parameters are ignored\n");
114 : : }
115 : 109 : SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
116 : : }
117 : : }
118 : :
119 : : /* No key_name. Support legacy configuration */
120 [ + + ]: 114 : if (!key) {
121 [ - + ]: 5 : 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 [ + + ]: 5 : if (req.param.cipher == NULL) {
128 [ - + ]: 1 : req.param.cipher = strdup(BDEV_CRYPTO_DEFAULT_CIPHER);
129 [ - + ]: 1 : 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 : : }
135 [ + + ]: 5 : if (req.crypto_pmd) {
136 : 1 : SPDK_WARNLOG("\"crypto_pmd\" parameters is obsolete and ignored\n");
137 : : }
138 : :
139 : 5 : req.param.key_name = calloc(1, MAX_KEY_NAME_LEN);
140 [ - + ]: 5 : 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 [ - + ]: 5 : 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 : 5 : key = spdk_accel_crypto_key_get(req.param.key_name);
150 [ - + ]: 5 : if (key) {
151 : 0 : SPDK_NOTICELOG("Found key \"%s\"\n", req.param.key_name);
152 : : } else {
153 : 5 : rc = spdk_accel_crypto_key_create(&req.param);
154 [ + - ]: 5 : if (!rc) {
155 : 5 : key = spdk_accel_crypto_key_get(req.param.key_name);
156 : 5 : created_key = key;
157 : : }
158 : : }
159 : : }
160 : :
161 [ - + ]: 114 : 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 : 114 : crypto_opts = create_crypto_opts(&req, key, created_key != NULL);
170 [ - + ]: 114 : 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 : 114 : rc = create_crypto_disk(crypto_opts);
177 [ - + ]: 114 : 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 : 114 : w = spdk_jsonrpc_begin_result(request);
184 : 114 : spdk_json_write_string(w, req.name);
185 : 114 : spdk_jsonrpc_end_result(request, w);
186 : :
187 : 114 : cleanup:
188 [ - + - - ]: 114 : if (rc && created_key) {
189 : 0 : spdk_accel_crypto_key_destroy(created_key);
190 : : }
191 : 114 : free_rpc_construct_crypto(&req);
192 : 114 : }
193 : 206 : 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 : 6 : free_rpc_delete_crypto(struct rpc_delete_crypto *req)
201 : : {
202 : 6 : free(req->name);
203 : 6 : }
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 : 6 : rpc_bdev_crypto_delete_cb(void *cb_arg, int bdeverrno)
211 : : {
212 : 6 : struct spdk_jsonrpc_request *request = cb_arg;
213 : :
214 [ + - ]: 6 : if (bdeverrno == 0) {
215 : 6 : spdk_jsonrpc_send_bool_response(request, true);
216 : : } else {
217 : 0 : spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno));
218 : : }
219 : 6 : }
220 : :
221 : : static void
222 : 6 : rpc_bdev_crypto_delete(struct spdk_jsonrpc_request *request,
223 : : const struct spdk_json_val *params)
224 : : {
225 : 6 : struct rpc_delete_crypto req = {NULL};
226 : :
227 [ - + ]: 6 : 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 : 6 : delete_crypto_disk(req.name, rpc_bdev_crypto_delete_cb, request);
236 : :
237 : 6 : free_rpc_delete_crypto(&req);
238 : :
239 : 6 : return;
240 : :
241 : 0 : cleanup:
242 : 0 : free_rpc_delete_crypto(&req);
243 : : }
244 : 206 : SPDK_RPC_REGISTER("bdev_crypto_delete", rpc_bdev_crypto_delete, SPDK_RPC_RUNTIME)
|