From f070b78cd1359b811e994ed542d387a459d48055 Mon Sep 17 00:00:00 2001 From: paul luse Date: Fri, 31 Jan 2020 22:19:09 +0000 Subject: [PATCH] module/crypto: add RPC and plumbing to support QAT AES_XTS cipher Signed-off-by: paul luse Change-Id: Iadd03f8da305e97e3f1d57ef4aeaece400e8d959 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/441 Tested-by: SPDK CI Jenkins Reviewed-by: Shuhei Matsumoto Reviewed-by: Aleksey Marchuk --- module/bdev/crypto/vbdev_crypto.c | 20 ++++++++++--- module/bdev/crypto/vbdev_crypto.h | 9 +++++- module/bdev/crypto/vbdev_crypto_rpc.c | 42 ++++++++++++++++++++++++++- scripts/rpc.py | 6 +++- scripts/rpc/bdev.py | 7 +++-- 5 files changed, 75 insertions(+), 9 deletions(-) diff --git a/module/bdev/crypto/vbdev_crypto.c b/module/bdev/crypto/vbdev_crypto.c index 61efe4417..c43609bd3 100644 --- a/module/bdev/crypto/vbdev_crypto.c +++ b/module/bdev/crypto/vbdev_crypto.c @@ -1367,7 +1367,8 @@ crypto_bdev_ch_destroy_cb(void *io_device, void *ctx_buf) * on the global list. */ static int vbdev_crypto_insert_name(const char *bdev_name, const char *vbdev_name, - const char *crypto_pmd, const char *key) + const char *crypto_pmd, const char *key, + const char *cipher, const char *key2) { struct bdev_names *name; int rc, j; @@ -1452,14 +1453,15 @@ error_alloc_bname: /* RPC entry point for crypto creation. */ int create_crypto_disk(const char *bdev_name, const char *vbdev_name, - const char *crypto_pmd, const char *key) + const char *crypto_pmd, const char *key, + const char *cipher, const char *key2) { struct spdk_bdev *bdev = NULL; int rc = 0; bdev = spdk_bdev_get_by_name(bdev_name); - rc = vbdev_crypto_insert_name(bdev_name, vbdev_name, crypto_pmd, key); + rc = vbdev_crypto_insert_name(bdev_name, vbdev_name, crypto_pmd, key, cipher, key2); if (rc) { return rc; } @@ -1490,6 +1492,8 @@ vbdev_crypto_init(void) int i; int rc = 0; const char *key = NULL; + const char *cipher = NULL; + const char *key2 = NULL; /* Fully configure both SW and HW drivers. */ rc = vbdev_crypto_init_crypto_drivers(); @@ -1534,8 +1538,16 @@ vbdev_crypto_init(void) return -EINVAL; } + /* These are optional. */ + cipher = spdk_conf_section_get_nmval(sp, "CRY", i, 4); + if (cipher == NULL) { + cipher = AES_CBC; + } + key2 = spdk_conf_section_get_nmval(sp, "CRY", i, 5); + + /* Note: config file options do not support QAT AES_XTS, use RPC */ rc = vbdev_crypto_insert_name(conf_bdev_name, conf_vbdev_name, - crypto_pmd, key); + crypto_pmd, key, cipher, key2); if (rc != 0) { return rc; } diff --git a/module/bdev/crypto/vbdev_crypto.h b/module/bdev/crypto/vbdev_crypto.h index f3e70fd0b..458b29c6b 100644 --- a/module/bdev/crypto/vbdev_crypto.h +++ b/module/bdev/crypto/vbdev_crypto.h @@ -44,6 +44,10 @@ #define AESNI_MB "crypto_aesni_mb" #define QAT "crypto_qat" +/* Supported ciphers */ +#define AES_CBC "AES_CBC" /* QAT and AESNI_MB */ +#define AES_XTS "AES_XTS" /* QAT only */ + typedef void (*spdk_delete_crypto_complete)(void *cb_arg, int bdeverrno); /** @@ -53,10 +57,13 @@ typedef void (*spdk_delete_crypto_complete)(void *cb_arg, int bdeverrno); * \param vbdev_name Name of the new crypto vbdev. * \param crypto_pmd Name of the polled mode driver to use for this vbdev. * \param key The key to use for this vbdev. + * \param cipher The cipher to use for this vbdev. + * \param keys The 2nd key to use for AES_XTS cipher. * \return 0 on success, other on failure. */ int create_crypto_disk(const char *bdev_name, const char *vbdev_name, - const char *crypto_pmd, const char *key); + const char *crypto_pmd, const char *key, + const char *cipher, const char *key2); /** * Delete crypto bdev. diff --git a/module/bdev/crypto/vbdev_crypto_rpc.c b/module/bdev/crypto/vbdev_crypto_rpc.c index e0d428188..d730b0fc8 100644 --- a/module/bdev/crypto/vbdev_crypto_rpc.c +++ b/module/bdev/crypto/vbdev_crypto_rpc.c @@ -39,6 +39,8 @@ struct rpc_construct_crypto { char *name; char *crypto_pmd; char *key; + char *cipher; + char *key2; }; /* Free the allocated memory resource after the RPC handling. */ @@ -49,6 +51,8 @@ free_rpc_construct_crypto(struct rpc_construct_crypto *r) free(r->name); free(r->crypto_pmd); free(r->key); + free(r->cipher); + free(r->key2); } /* Structure to decode the input parameters for this RPC method. */ @@ -57,6 +61,8 @@ static const struct spdk_json_object_decoder rpc_construct_crypto_decoders[] = { {"name", offsetof(struct rpc_construct_crypto, name), spdk_json_decode_string}, {"crypto_pmd", offsetof(struct rpc_construct_crypto, crypto_pmd), spdk_json_decode_string}, {"key", offsetof(struct rpc_construct_crypto, key), spdk_json_decode_string}, + {"cipher", offsetof(struct rpc_construct_crypto, cipher), spdk_json_decode_string, true}, + {"key2", offsetof(struct rpc_construct_crypto, key2), spdk_json_decode_string, true}, }; /* Decode the parameters for this RPC method and properly construct the crypto @@ -78,8 +84,42 @@ spdk_rpc_bdev_crypto_create(struct spdk_jsonrpc_request *request, goto cleanup; } + if (req.cipher == NULL) { + req.cipher = strdup(AES_CBC); + if (req.cipher == NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, + "Unable to allocate memory for req.cipher"); + goto cleanup; + } + } + + if (strcmp(req.cipher, AES_XTS) != 0 && strcmp(req.cipher, AES_CBC) != 0) { + spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid cipher: %s", + req.cipher); + goto cleanup; + } + + if (strcmp(req.crypto_pmd, AESNI_MB) == 0 && strcmp(req.cipher, AES_XTS) == 0) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid cipher. AES_XTS is only available on QAT."); + goto cleanup; + } + + if (strcmp(req.cipher, AES_XTS) == 0 && req.key2 == NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid key. A 2nd key is needed for AES_XTS."); + goto cleanup; + } + + if (strcmp(req.cipher, AES_CBC) == 0 && req.key2 != NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid key. A 2nd key is needed only for AES_XTS."); + goto cleanup; + } + rc = create_crypto_disk(req.base_bdev_name, req.name, - req.crypto_pmd, req.key); + req.crypto_pmd, req.key, req.cipher, req.key2); if (rc) { spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); goto cleanup; diff --git a/scripts/rpc.py b/scripts/rpc.py index f412a4525..086d267e8 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -195,13 +195,17 @@ if __name__ == "__main__": base_bdev_name=args.base_bdev_name, name=args.name, crypto_pmd=args.crypto_pmd, - key=args.key)) + key=args.key, + cipher=args.cipher, + key2=args.key2)) p = subparsers.add_parser('bdev_crypto_create', aliases=['construct_crypto_bdev'], help='Add a crypto vbdev') p.add_argument('base_bdev_name', help="Name of the base bdev") p.add_argument('name', help="Name of the crypto vbdev") p.add_argument('crypto_pmd', help="Name of the crypto device driver") p.add_argument('key', help="Key") + p.add_argument('-c', '--cipher', help="cipher to use, AES_CBC or AES_XTS (QAT only)", default="AES_CBC") + p.add_argument('-k2', '--key2', help="2nd key for cipher AET_XTS", default=None) p.set_defaults(func=bdev_crypto_create) def bdev_crypto_delete(args): diff --git a/scripts/rpc/bdev.py b/scripts/rpc/bdev.py index 7e561e4c4..67acf538c 100644 --- a/scripts/rpc/bdev.py +++ b/scripts/rpc/bdev.py @@ -74,7 +74,7 @@ def bdev_compress_get_orphans(client, name=None): @deprecated_alias('construct_crypto_bdev') -def bdev_crypto_create(client, base_bdev_name, name, crypto_pmd, key): +def bdev_crypto_create(client, base_bdev_name, name, crypto_pmd, key, cipher=None, key2=None): """Construct a crypto virtual block device. Args: @@ -87,7 +87,10 @@ def bdev_crypto_create(client, base_bdev_name, name, crypto_pmd, key): Name of created virtual block device. """ params = {'base_bdev_name': base_bdev_name, 'name': name, 'crypto_pmd': crypto_pmd, 'key': key} - + if cipher: + params['cipher'] = cipher + if key2: + params['key2'] = key2 return client.call('bdev_crypto_create', params)