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