1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "vbdev_crypto.h" 35 36 /* Structure to hold the parameters for this RPC method. */ 37 struct rpc_construct_crypto { 38 char *base_bdev_name; 39 char *name; 40 char *crypto_pmd; 41 char *key; 42 char *cipher; 43 char *key2; 44 }; 45 46 /* Free the allocated memory resource after the RPC handling. */ 47 static void 48 free_rpc_construct_crypto(struct rpc_construct_crypto *r) 49 { 50 free(r->base_bdev_name); 51 free(r->name); 52 free(r->crypto_pmd); 53 free(r->key); 54 free(r->cipher); 55 free(r->key2); 56 } 57 58 /* Structure to decode the input parameters for this RPC method. */ 59 static const struct spdk_json_object_decoder rpc_construct_crypto_decoders[] = { 60 {"base_bdev_name", offsetof(struct rpc_construct_crypto, base_bdev_name), spdk_json_decode_string}, 61 {"name", offsetof(struct rpc_construct_crypto, name), spdk_json_decode_string}, 62 {"crypto_pmd", offsetof(struct rpc_construct_crypto, crypto_pmd), spdk_json_decode_string}, 63 {"key", offsetof(struct rpc_construct_crypto, key), spdk_json_decode_string}, 64 {"cipher", offsetof(struct rpc_construct_crypto, cipher), spdk_json_decode_string, true}, 65 {"key2", offsetof(struct rpc_construct_crypto, key2), spdk_json_decode_string, true}, 66 }; 67 68 /* Decode the parameters for this RPC method and properly construct the crypto 69 * device. Error status returned in the failed cases. 70 */ 71 static void 72 rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request, 73 const struct spdk_json_val *params) 74 { 75 struct rpc_construct_crypto req = {NULL}; 76 struct spdk_json_write_ctx *w; 77 int rc; 78 79 if (spdk_json_decode_object(params, rpc_construct_crypto_decoders, 80 SPDK_COUNTOF(rpc_construct_crypto_decoders), 81 &req)) { 82 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 83 "Invalid parameters"); 84 goto cleanup; 85 } 86 87 if (req.cipher == NULL) { 88 req.cipher = strdup(AES_CBC); 89 if (req.cipher == NULL) { 90 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 91 "Unable to allocate memory for req.cipher"); 92 goto cleanup; 93 } 94 } 95 96 if (strcmp(req.cipher, AES_XTS) != 0 && strcmp(req.cipher, AES_CBC) != 0) { 97 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 98 "Invalid cipher: %s", 99 req.cipher); 100 goto cleanup; 101 } 102 103 if (strcmp(req.crypto_pmd, AESNI_MB) == 0 && strcmp(req.cipher, AES_XTS) == 0) { 104 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 105 "Invalid cipher. AES_XTS is only available on QAT."); 106 goto cleanup; 107 } 108 109 if (strcmp(req.cipher, AES_XTS) == 0 && req.key2 == NULL) { 110 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 111 "Invalid key. A 2nd key is needed for AES_XTS."); 112 goto cleanup; 113 } 114 115 if (strcmp(req.cipher, AES_CBC) == 0 && req.key2 != NULL) { 116 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 117 "Invalid key. A 2nd key is needed only for AES_XTS."); 118 goto cleanup; 119 } 120 121 rc = create_crypto_disk(req.base_bdev_name, req.name, 122 req.crypto_pmd, req.key, req.cipher, req.key2); 123 if (rc) { 124 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 125 goto cleanup; 126 } 127 128 w = spdk_jsonrpc_begin_result(request); 129 spdk_json_write_string(w, req.name); 130 spdk_jsonrpc_end_result(request, w); 131 free_rpc_construct_crypto(&req); 132 return; 133 134 cleanup: 135 free_rpc_construct_crypto(&req); 136 } 137 SPDK_RPC_REGISTER("bdev_crypto_create", rpc_bdev_crypto_create, SPDK_RPC_RUNTIME) 138 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_crypto_create, construct_crypto_bdev) 139 140 struct rpc_delete_crypto { 141 char *name; 142 }; 143 144 static void 145 free_rpc_delete_crypto(struct rpc_delete_crypto *req) 146 { 147 free(req->name); 148 } 149 150 static const struct spdk_json_object_decoder rpc_delete_crypto_decoders[] = { 151 {"name", offsetof(struct rpc_delete_crypto, name), spdk_json_decode_string}, 152 }; 153 154 static void 155 rpc_bdev_crypto_delete_cb(void *cb_arg, int bdeverrno) 156 { 157 struct spdk_jsonrpc_request *request = cb_arg; 158 159 spdk_jsonrpc_send_bool_response(request, bdeverrno == 0); 160 } 161 162 static void 163 rpc_bdev_crypto_delete(struct spdk_jsonrpc_request *request, 164 const struct spdk_json_val *params) 165 { 166 struct rpc_delete_crypto req = {NULL}; 167 struct spdk_bdev *bdev; 168 169 if (spdk_json_decode_object(params, rpc_delete_crypto_decoders, 170 SPDK_COUNTOF(rpc_delete_crypto_decoders), 171 &req)) { 172 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 173 "Invalid parameters"); 174 goto cleanup; 175 } 176 177 bdev = spdk_bdev_get_by_name(req.name); 178 if (bdev == NULL) { 179 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 180 goto cleanup; 181 } 182 183 delete_crypto_disk(bdev, rpc_bdev_crypto_delete_cb, request); 184 185 free_rpc_delete_crypto(&req); 186 187 return; 188 189 cleanup: 190 free_rpc_delete_crypto(&req); 191 } 192 SPDK_RPC_REGISTER("bdev_crypto_delete", rpc_bdev_crypto_delete, SPDK_RPC_RUNTIME) 193 SPDK_RPC_REGISTER_ALIAS_DEPRECATED(bdev_crypto_delete, delete_crypto_bdev) 194