xref: /spdk/module/bdev/crypto/vbdev_crypto_rpc.c (revision 12fbe739a31b09aff0d05f354d4f3bbef99afc55)
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 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 *
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
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
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
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
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