diff --git a/CHANGELOG.md b/CHANGELOG.md index bdd31913d..85882b25e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ New library isa-l-crypto has been added, it is used by accel library in crypto operations. +New functions `spdk_accel_submit_encrypt` and `spdk_accel_submit_decrypt` were added. + ### bdev Both of interleaved and separated metadata are now supported by the malloc bdev module. diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index 48f348018..a52d08acd 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -442,6 +442,8 @@ Example response: "framework_monitor_context_switch", "spdk_kill_instance", "accel_get_opc_assignments", + "accel_crypto_key_create", + "accel_crypto_keys_get", "ioat_scan_accel_module", "dsa_scan_accel_module", "bdev_virtio_attach_controller", @@ -1776,6 +1778,92 @@ Example response: } ~~~ +### accel_crypto_key_create {#rpc_accel_crypto_key_create} + +Create a crypt key which will be used in accel framework + +#### Parameters + +Name | Optional | Type | Description +-----------|----------| ----------- | ----------------- +cipher | Required | string | crypto cipher to use +key | Required | string | Key in **hex** form +key2 | Optional | string | Optional 2nd part of the key or a tweak in **hex** form +name | Required | string | The key name + +#### Example + +Example request: + +~~~json +{ + "jsonrpc": "2.0", + "method": "accel_crypto_key_create", + "id": 1, + "params": { + "cipher": "AES_XTS", + "key": "00112233445566778899001122334455", + "key2": "00112233445566778899001122334455", + "name": "super_key" + } +} +~~~ + +Example response: + +~~~json +{ + "jsonrpc": "2.0", + "id": 1, + "result": true +} +~~~ + +### accel_crypto_keys_get {#rpc_accel_crypto_keys_get} + +Get information about existing crypto keys + +#### Parameters + +Name | Optional | Type | Description +----------------------- |----------| ----------- | ----------------- +key_name | Optional | string | If specified, return info about a specific key + +#### Example + +Example request: + +~~~json +{ + "jsonrpc": "2.0", + "method": "accel_crypto_keys_get", + "id": 1 +} +~~~ + +Example response: + +~~~json +{ + "jsonrpc": "2.0", + "id": 1, + "result": [ + { + "name": "test_dek", + "cipher": "AES_XTS", + "key": "00112233445566778899001122334455", + "key2": "11223344556677889900112233445500" + }, + { + "name": "test_dek2", + "cipher": "AES_XTS", + "key": "11223344556677889900112233445500", + "key2": "22334455667788990011223344550011" + } + ] +} +~~~ + ### dsa_scan_accel_module {#rpc_dsa_scan_accel_module} Set config and enable dsa accel module offload. diff --git a/include/spdk/accel.h b/include/spdk/accel.h index 25bb8cc9d..a8ee8af81 100644 --- a/include/spdk/accel.h +++ b/include/spdk/accel.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (C) 2020 Intel Corporation. + * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES * All rights reserved. */ @@ -17,9 +18,19 @@ extern "C" { #endif +/** Data Encryption Key identifier */ +struct spdk_accel_crypto_key; + /* Flags for accel operations */ #define ACCEL_FLAG_PERSISTENT (1 << 0) +struct spdk_accel_crypto_key_create_param { + char *cipher; /**< Cipher to be used for crypto operations */ + char *hex_key; /**< Hexlified key */ + char *hex_key2; /**< Hexlified key2 */ + char *key_name; /**< Key name */ +}; + enum accel_opcode { ACCEL_OPC_COPY = 0, ACCEL_OPC_FILL = 1, @@ -29,7 +40,9 @@ enum accel_opcode { ACCEL_OPC_COPY_CRC32C = 5, ACCEL_OPC_COMPRESS = 6, ACCEL_OPC_DECOMPRESS = 7, - ACCEL_OPC_LAST = 8, + ACCEL_OPC_ENCRYPT = 8, + ACCEL_OPC_DECRYPT = 9, + ACCEL_OPC_LAST = 10, }; /** @@ -71,6 +84,29 @@ void spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg); */ struct spdk_io_channel *spdk_accel_get_io_channel(void); +/** + * Create a crypto key with given parameters. Accel module copies content of \b param structure + * + * \param param Key parameters + * \return 0 on success, negated errno on error + */ +int spdk_accel_crypto_key_create(const struct spdk_accel_crypto_key_create_param *param); + +/** + * Destroy a crypto key + * + * \param key Key to destroy + * \return 0 on success, negated errno on error + */ +int spdk_accel_crypto_key_destroy(struct spdk_accel_crypto_key *key); + +/** + * Find a crypto key structure by name + * \param name Key name + * \return Crypto key structure or NULL + */ +struct spdk_accel_crypto_key *spdk_accel_crypto_key_get(const char *name); + /** * Submit a copy request. * @@ -404,6 +440,67 @@ int spdk_accel_get_buf(struct spdk_io_channel *ch, uint64_t len, void **buf, void spdk_accel_put_buf(struct spdk_io_channel *ch, void *buf, struct spdk_memory_domain *domain, void *domain_ctx); +/** + * Build and submit a data encryption request. + * + * This function will build the encryption request and submit it. \b nbytes must be multiple of \b block_size. + * \b iv is used to encrypt the first logical block of size \b block_size. If \b src_iovs describes more than + * one logical block then \b iv will be incremented for each next logical block. + * Data Encryption Key identifier should be created before calling this function using methods specific to the accel + * module being used. + * + * \param ch I/O channel associated with this call + * \param key Data Encryption Key identifier + * \param dst_iovs The io vector array which stores the dst data and len. + * \param dst_iovcnt The size of the destination io vectors. + * \param src_iovs The io vector array which stores the src data and len. + * \param src_iovcnt The size of the source io vectors. + * \param iv Initialization vector (tweak) used for encryption + * \param block_size Logical block size, if src contains more than 1 logical block, subsequent logical blocks will be + * encrypted with incremented \b iv + * \param flags Accel framework flags for operations. + * \param cb_fn Callback function which will be called when the request is complete. + * \param cb_arg Opaque value which will be passed back as the arg parameter in the completion callback. + * + * \return 0 on success, negative errno on failure. + */ +int spdk_accel_submit_encrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct iovec *src_iovs, uint32_t src_iovcnt, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_completion_cb cb_fn, void *cb_arg); + +/** + * Build and submit a data decryption request. + * + * This function will build the decryption request and submit it. \b nbytes must be multiple of \b block_size. + * \b iv is used to decrypt the first logical block of size \b block_size. If \b src_iovs describes more than + * one logical block then \b iv will be incremented for each next logical block. + * Data Encryption Key identifier should be created before calling this function using methods specific to the accel + * module being used. + * + * \param ch I/O channel associated with this call + * \param key Data Encryption Key identifier + * \param dst_iovs The io vector array which stores the dst data and len. + * \param dst_iovcnt The size of the destination io vectors. + * \param src_iovs The io vector array which stores the src data and len. + * \param src_iovcnt The size of the source io vectors. + * \param iv Initialization vector (tweak) used for decryption. Should be the same as \b iv used for encryption of a + * data block + * \param block_size Logical block size, if src contains more than 1 logical block, subsequent logical blocks will be + * decrypted with incremented \b iv + * \param flags Accel framework flags for operations. + * \param cb_fn Callback function which will be called when the request is complete. + * \param cb_arg Opaque value which will be passed back as the arg parameter in the completion callback. + * + * \return 0 on success, negative errno on failure. + */ +int spdk_accel_submit_decrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct iovec *src_iovs, uint32_t src_iovcnt, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_completion_cb cb_fn, void *cb_arg); + /** * Return the name of the module assigned to a specific opcode. * diff --git a/include/spdk_internal/accel_module.h b/include/spdk_internal/accel_module.h index 2bf6188b6..0a77963d0 100644 --- a/include/spdk_internal/accel_module.h +++ b/include/spdk_internal/accel_module.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (C) 2020 Intel Corporation. + * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES * All rights reserved. */ @@ -12,10 +13,25 @@ #include "spdk/queue.h" #include "spdk/config.h" +struct spdk_accel_module_if; struct spdk_accel_task; void spdk_accel_task_complete(struct spdk_accel_task *task, int status); +/** Some reasonable key length used with strnlen() */ +#define SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH (256 + 1) + +struct spdk_accel_crypto_key { + void *priv; /**< Module private data */ + char *key; /**< Key in binary form */ + size_t key_size; /**< Key size in bytes */ + char *key2; /**< Key2 in binary form */ + size_t key2_size; /**< Key2 size in bytes */ + struct spdk_accel_module_if *module_if; /**< Accel module the key belongs to */ + struct spdk_accel_crypto_key_create_param param; /**< User input parameters */ + TAILQ_ENTRY(spdk_accel_crypto_key) link; +}; + struct spdk_accel_task { struct accel_io_channel *accel_ch; spdk_accel_completion_cb cb_fn; @@ -45,14 +61,19 @@ struct spdk_accel_task { void *dst2; uint32_t seed; uint64_t fill_pattern; + struct spdk_accel_crypto_key *crypto_key; }; union { uint32_t *crc_dst; uint32_t *output_size; + uint32_t block_size; /* for crypto op */ }; enum accel_opcode op_code; uint64_t nbytes; - uint64_t nbytes_dst; + union { + uint64_t nbytes_dst; /* for compress op */ + uint64_t iv; /* Initialization vector (tweak) for crypto op */ + }; int flags; int status; TAILQ_ENTRY(spdk_accel_task) link; @@ -89,6 +110,13 @@ struct spdk_accel_module_if { struct spdk_io_channel *(*get_io_channel)(void); int (*submit_tasks)(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task); + /** + * Create crypto key function. Module is responsible to fill all necessary parameters in + * \b spdk_accel_crypto_key structure + */ + int (*crypto_key_init)(struct spdk_accel_crypto_key *key); + void (*crypto_key_deinit)(struct spdk_accel_crypto_key *key); + TAILQ_ENTRY(spdk_accel_module_if) tailq; }; diff --git a/lib/accel/Makefile b/lib/accel/Makefile index 6265b24f8..cfc92ec06 100644 --- a/lib/accel/Makefile +++ b/lib/accel/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (C) 2015 Intel Corporation. +# Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES # All rights reserved. # @@ -17,6 +18,10 @@ ifeq ($(CONFIG_ISAL), y) LOCAL_SYS_LIBS = -L$(ISAL_DIR)/.libs -lisal endif +ifeq ($(CONFIG_ISAL_CRYPTO), y) +LOCAL_SYS_LIBS = -L$(ISAL_CRYPTO_DIR)/.libs -lisal_crypto +endif + SPDK_MAP_FILE = $(abspath $(CURDIR)/spdk_accel.map) include $(SPDK_ROOT_DIR)/mk/spdk.lib.mk diff --git a/lib/accel/accel.c b/lib/accel/accel.c index b7f7d7fca..7e70f89a7 100644 --- a/lib/accel/accel.c +++ b/lib/accel/accel.c @@ -18,6 +18,7 @@ #include "spdk/json.h" #include "spdk/crc32.h" #include "spdk/util.h" +#include "spdk/hexlify.h" /* Accelerator Framework: The following provides a top level * generic API for the accelerator functions defined here. Modules, @@ -46,13 +47,17 @@ static struct spdk_memory_domain *g_accel_domain; static TAILQ_HEAD(, spdk_accel_module_if) spdk_accel_module_list = TAILQ_HEAD_INITIALIZER(spdk_accel_module_list); +/* Crypto keyring */ +static TAILQ_HEAD(, spdk_accel_crypto_key) g_keyring = TAILQ_HEAD_INITIALIZER(g_keyring); +static struct spdk_spinlock g_keyring_spin; + /* Global array mapping capabilities to modules */ static struct spdk_accel_module_if *g_modules_opc[ACCEL_OPC_LAST] = {}; static char *g_modules_opc_override[ACCEL_OPC_LAST] = {}; static const char *g_opcode_strings[ACCEL_OPC_LAST] = { "copy", "fill", "dualcast", "compare", "crc32c", "copy_crc32c", - "compress", "decompress" + "compress", "decompress", "encrypt", "decrypt" }; struct accel_buffer { @@ -191,8 +196,6 @@ _get_task(struct accel_io_channel *accel_ch, spdk_accel_completion_cb cb_fn, voi return accel_task; } - - /* Accel framework public API for copy function */ int spdk_accel_submit_copy(struct spdk_io_channel *ch, void *dst, void *src, @@ -526,6 +529,106 @@ spdk_accel_submit_decompress(struct spdk_io_channel *ch, struct iovec *dst_iovs, return 0; } +int +spdk_accel_submit_encrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct iovec *src_iovs, uint32_t src_iovcnt, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_completion_cb cb_fn, void *cb_arg) +{ + struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); + struct spdk_accel_task *accel_task; + struct spdk_accel_module_if *module = g_modules_opc[ACCEL_OPC_ENCRYPT]; + struct spdk_io_channel *module_ch = accel_ch->module_ch[ACCEL_OPC_ENCRYPT]; + size_t src_nbytes = 0, dst_nbytes = 0; + uint32_t i; + + if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || !block_size)) { + return -EINVAL; + } + + for (i = 0; i < src_iovcnt; i++) { + src_nbytes += src_iovs[i].iov_len; + } + for (i = 0; i < dst_iovcnt; i++) { + dst_nbytes += dst_iovs[i].iov_len; + } + if (spdk_unlikely(src_nbytes != dst_nbytes || !src_nbytes)) { + return -ERANGE; + } + if (spdk_unlikely(src_nbytes % block_size != 0)) { + return -EINVAL; + } + + accel_task = _get_task(accel_ch, cb_fn, cb_arg); + if (accel_task == NULL) { + return -ENOMEM; + } + + accel_task->crypto_key = key; + accel_task->s.iovs = src_iovs; + accel_task->s.iovcnt = src_iovcnt; + accel_task->d.iovs = dst_iovs; + accel_task->d.iovcnt = dst_iovcnt; + accel_task->nbytes = src_nbytes; + accel_task->iv = iv; + accel_task->block_size = block_size; + accel_task->flags = flags; + accel_task->op_code = ACCEL_OPC_ENCRYPT; + + return module->submit_tasks(module_ch, accel_task); +} + +int +spdk_accel_submit_decrypt(struct spdk_io_channel *ch, struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct iovec *src_iovs, uint32_t src_iovcnt, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_completion_cb cb_fn, void *cb_arg) +{ + struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); + struct spdk_accel_task *accel_task; + struct spdk_accel_module_if *module = g_modules_opc[ACCEL_OPC_DECRYPT]; + struct spdk_io_channel *module_ch = accel_ch->module_ch[ACCEL_OPC_DECRYPT]; + size_t src_nbytes = 0, dst_nbytes = 0; + uint32_t i; + + if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || !block_size)) { + return -EINVAL; + } + + for (i = 0; i < src_iovcnt; i++) { + src_nbytes += src_iovs[i].iov_len; + } + for (i = 0; i < dst_iovcnt; i++) { + dst_nbytes += dst_iovs[i].iov_len; + } + if (spdk_unlikely(src_nbytes != dst_nbytes || !src_nbytes)) { + return -ERANGE; + } + if (spdk_unlikely(src_nbytes % block_size != 0)) { + return -EINVAL; + } + + accel_task = _get_task(accel_ch, cb_fn, cb_arg); + if (accel_task == NULL) { + return -ENOMEM; + } + + accel_task->crypto_key = key; + accel_task->s.iovs = src_iovs; + accel_task->s.iovcnt = src_iovcnt; + accel_task->d.iovs = dst_iovs; + accel_task->d.iovcnt = dst_iovcnt; + accel_task->nbytes = src_nbytes; + accel_task->iv = iv; + accel_task->block_size = block_size; + accel_task->flags = flags; + accel_task->op_code = ACCEL_OPC_DECRYPT; + + return module->submit_tasks(module_ch, accel_task); +} + static inline struct accel_buffer * accel_get_buf(struct accel_io_channel *ch, uint64_t len) { @@ -1036,7 +1139,224 @@ _module_find_by_name(const char *name) return accel_module; } -/* Helper function when when accel modules register with the framework. */ +static inline struct spdk_accel_crypto_key * +_accel_crypto_key_get(const char *name) +{ + struct spdk_accel_crypto_key *key; + + assert(spdk_spin_held(&g_keyring_spin)); + + TAILQ_FOREACH(key, &g_keyring, link) { + if (strcmp(name, key->param.key_name) == 0) { + return key; + } + } + + return NULL; +} + +static void +accel_crypto_key_free_mem(struct spdk_accel_crypto_key *key) +{ + if (key->param.hex_key) { + spdk_memset_s(key->param.hex_key, key->key_size * 2, 0, key->key_size * 2); + free(key->param.hex_key); + } + if (key->param.hex_key2) { + spdk_memset_s(key->param.hex_key2, key->key2_size * 2, 0, key->key2_size * 2); + free(key->param.hex_key2); + } + free(key->param.key_name); + free(key->param.cipher); + if (key->key) { + spdk_memset_s(key->key, key->key_size, 0, key->key_size); + free(key->key); + } + if (key->key2) { + spdk_memset_s(key->key2, key->key2_size, 0, key->key2_size); + free(key->key2); + } + free(key); +} + +static void +accel_crypto_key_destroy_unsafe(struct spdk_accel_crypto_key *key) +{ + assert(key->module_if); + assert(key->module_if->crypto_key_deinit); + + key->module_if->crypto_key_deinit(key); + accel_crypto_key_free_mem(key); +} + +/* + * This function mitigates a timing side channel which could be caused by using strcmp() + * Please refer to chapter "Mitigating Information Leakage Based on Variable Timing" in + * the article [1] for more details + * [1] https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/secure-coding/mitigate-timing-side-channel-crypto-implementation.html + */ +static bool +accel_aes_xts_keys_equal(const char *k1, size_t k1_len, const char *k2, size_t k2_len) +{ + size_t i; + volatile size_t x = k1_len ^ k2_len; + + for (i = 0; ((i < k1_len) & (i < k2_len)); i++) { + x |= k1[i] ^ k2[i]; + } + + return x == 0; +} + +int +spdk_accel_crypto_key_create(const struct spdk_accel_crypto_key_create_param *param) +{ + struct spdk_accel_module_if *module; + struct spdk_accel_crypto_key *key; + size_t hex_key_size, hex_key2_size; + int rc; + + if (!param || !param->hex_key || !param->cipher || !param->key_name) { + return -EINVAL; + } + + if (g_modules_opc[ACCEL_OPC_ENCRYPT] != g_modules_opc[ACCEL_OPC_DECRYPT]) { + /* hardly ever possible, but let's check and warn the user */ + SPDK_ERRLOG("Different accel modules are used for encryption and decryption\n"); + } + module = g_modules_opc[ACCEL_OPC_ENCRYPT]; + + if (!module) { + SPDK_ERRLOG("No accel module found assigned for crypto operation\n"); + return -ENOENT; + } + if (!module->crypto_key_init) { + SPDK_ERRLOG("Accel module \"%s\" doesn't support crypto operations\n", module->name); + return -ENOTSUP; + } + + key = calloc(1, sizeof(*key)); + if (!key) { + return -ENOMEM; + } + + key->param.key_name = strdup(param->key_name); + if (!key->param.key_name) { + rc = -ENOMEM; + goto error; + } + + key->param.cipher = strdup(param->cipher); + if (!key->param.cipher) { + rc = -ENOMEM; + goto error; + } + + hex_key_size = strnlen(param->hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH); + if (hex_key_size == SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH) { + SPDK_ERRLOG("key1 size exceeds max %d\n", SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH); + rc = -EINVAL; + goto error; + } + key->param.hex_key = strdup(param->hex_key); + if (!key->param.hex_key) { + rc = -ENOMEM; + goto error; + } + + key->key_size = hex_key_size / 2; + key->key = spdk_unhexlify(key->param.hex_key); + if (!key->key) { + SPDK_ERRLOG("Failed to unhexlify key1\n"); + rc = -EINVAL; + goto error; + } + + if (param->hex_key2) { + hex_key2_size = strnlen(param->hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH); + if (hex_key2_size == SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH) { + SPDK_ERRLOG("key2 size exceeds max %d\n", SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH); + rc = -EINVAL; + goto error; + } + key->param.hex_key2 = strdup(param->hex_key2); + if (!key->param.hex_key2) { + rc = -ENOMEM; + goto error; + } + + key->key2_size = hex_key2_size / 2; + key->key2 = spdk_unhexlify(key->param.hex_key2); + if (!key->key2) { + SPDK_ERRLOG("Failed to unhexlify key2\n"); + rc = -EINVAL; + goto error; + } + + if (accel_aes_xts_keys_equal(key->key, key->key_size, key->key2, key->key2_size)) { + SPDK_ERRLOG("Identical keys are not secure\n"); + rc = -EINVAL; + goto error; + } + } + + key->module_if = module; + + spdk_spin_lock(&g_keyring_spin); + if (_accel_crypto_key_get(param->key_name)) { + rc = -EEXIST; + } else { + rc = module->crypto_key_init(key); + if (!rc) { + TAILQ_INSERT_TAIL(&g_keyring, key, link); + } + } + spdk_spin_unlock(&g_keyring_spin); + + if (rc) { + goto error; + } + + return 0; + +error: + accel_crypto_key_free_mem(key); + return rc; +} + +int +spdk_accel_crypto_key_destroy(struct spdk_accel_crypto_key *key) +{ + if (!key || !key->module_if) { + return -EINVAL; + } + + spdk_spin_lock(&g_keyring_spin); + if (!_accel_crypto_key_get(key->param.key_name)) { + spdk_spin_unlock(&g_keyring_spin); + return -ENOENT; + } + TAILQ_REMOVE(&g_keyring, key, link); + spdk_spin_unlock(&g_keyring_spin); + + accel_crypto_key_destroy_unsafe(key); + + return 0; +} + +struct spdk_accel_crypto_key * +spdk_accel_crypto_key_get(const char *name) +{ + struct spdk_accel_crypto_key *key; + + spdk_spin_lock(&g_keyring_spin); + key = _accel_crypto_key_get(name); + spdk_spin_unlock(&g_keyring_spin); + + return key; +} + +/* Helper function when accel modules register with the framework. */ void spdk_accel_module_list_add(struct spdk_accel_module_if *accel_module) { @@ -1048,7 +1368,7 @@ spdk_accel_module_list_add(struct spdk_accel_module_if *accel_module) /* Make sure that the software module is at the head of the list, this * will assure that all opcodes are later assigned to software first and - * then udpated to HW modules as they are registered. + * then updated to HW modules as they are registered. */ if (strcmp(accel_module->name, "software") == 0) { TAILQ_INSERT_HEAD(&spdk_accel_module_list, accel_module, tailq); @@ -1178,14 +1498,16 @@ spdk_accel_initialize(void) return rc; } + spdk_spin_init(&g_keyring_spin); + g_modules_started = true; accel_module_initialize(); /* Create our priority global map of opcodes to modules, we populate starting * with the software module (guaranteed to be first on the list) and then - * updating opcodes with HW modules that have been initilaized. + * updating opcodes with HW modules that have been initialized. * NOTE: all opcodes must be supported by software in the event that no HW - * modules are initilaized to support the operation. + * modules are initialized to support the operation. */ TAILQ_FOREACH(accel_module, &spdk_accel_module_list, tailq) { for (op = 0; op < ACCEL_OPC_LAST; op++) { @@ -1214,6 +1536,11 @@ spdk_accel_initialize(void) } } + if (g_modules_opc[ACCEL_OPC_ENCRYPT] != g_modules_opc[ACCEL_OPC_DECRYPT]) { + SPDK_ERRLOG("Different accel modules are assigned to encrypt and decrypt operations"); + return -EINVAL; + } + #ifdef DEBUG for (op = 0; op < ACCEL_OPC_LAST; op++) { assert(g_modules_opc[op] != NULL); @@ -1264,6 +1591,59 @@ accel_write_overridden_opc(struct spdk_json_write_ctx *w, const char *opc_str, spdk_json_write_object_end(w); } +static void +__accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key) +{ + spdk_json_write_named_string(w, "name", key->param.key_name); + spdk_json_write_named_string(w, "cipher", key->param.cipher); + spdk_json_write_named_string(w, "key", key->param.hex_key); + if (key->param.hex_key2) { + spdk_json_write_named_string(w, "key2", key->param.hex_key2); + } +} + +void +_accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key) +{ + spdk_json_write_object_begin(w); + __accel_crypto_key_dump_param(w, key); + spdk_json_write_object_end(w); +} + +static void +_accel_crypto_key_write_config_json(struct spdk_json_write_ctx *w, + struct spdk_accel_crypto_key *key) +{ + spdk_json_write_object_begin(w); + spdk_json_write_named_string(w, "method", "accel_crypto_key_create"); + spdk_json_write_named_object_begin(w, "params"); + __accel_crypto_key_dump_param(w, key); + spdk_json_write_object_end(w); + spdk_json_write_object_end(w); +} + +static void +_accel_crypto_keys_write_config_json(struct spdk_json_write_ctx *w, bool full_dump) +{ + struct spdk_accel_crypto_key *key; + + spdk_spin_lock(&g_keyring_spin); + TAILQ_FOREACH(key, &g_keyring, link) { + if (full_dump) { + _accel_crypto_key_write_config_json(w, key); + } else { + _accel_crypto_key_dump_param(w, key); + } + } + spdk_spin_unlock(&g_keyring_spin); +} + +void +_accel_crypto_keys_dump_param(struct spdk_json_write_ctx *w) +{ + _accel_crypto_keys_write_config_json(w, false); +} + void spdk_accel_write_config_json(struct spdk_json_write_ctx *w) { @@ -1285,6 +1665,9 @@ spdk_accel_write_config_json(struct spdk_json_write_ctx *w) accel_write_overridden_opc(w, g_opcode_strings[i], g_modules_opc_override[i]); } } + + _accel_crypto_keys_write_config_json(w, true); + spdk_json_write_array_end(w); } @@ -1298,6 +1681,7 @@ spdk_accel_module_finish(void) } if (!g_accel_module) { + spdk_spin_destroy(&g_keyring_spin); accel_module_finish_cb(); return; } @@ -1312,6 +1696,7 @@ spdk_accel_module_finish(void) void spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg) { + struct spdk_accel_crypto_key *key, *key_tmp; enum accel_opcode op; assert(cb_fn != NULL); @@ -1319,6 +1704,12 @@ spdk_accel_finish(spdk_accel_fini_cb cb_fn, void *cb_arg) g_fini_cb_fn = cb_fn; g_fini_cb_arg = cb_arg; + spdk_spin_lock(&g_keyring_spin); + TAILQ_FOREACH_SAFE(key, &g_keyring, link, key_tmp) { + accel_crypto_key_destroy_unsafe(key); + } + spdk_spin_unlock(&g_keyring_spin); + for (op = 0; op < ACCEL_OPC_LAST; op++) { if (g_modules_opc_override[op] != NULL) { free(g_modules_opc_override[op]); diff --git a/lib/accel/accel_internal.h b/lib/accel/accel_internal.h index 4af0d4d49..2cb1cca91 100644 --- a/lib/accel/accel_internal.h +++ b/lib/accel/accel_internal.h @@ -23,5 +23,8 @@ struct module_info { typedef void (*_accel_for_each_module_fn)(struct module_info *info); void _accel_for_each_module(struct module_info *info, _accel_for_each_module_fn fn); int _accel_get_opc_name(enum accel_opcode opcode, const char **opcode_name); +void _accel_crypto_key_dump_param(struct spdk_json_write_ctx *w, struct spdk_accel_crypto_key *key); +void _accel_crypto_keys_dump_param(struct spdk_json_write_ctx *w); + #endif diff --git a/lib/accel/accel_rpc.c b/lib/accel/accel_rpc.c index baa467700..8c2f56d2d 100644 --- a/lib/accel/accel_rpc.c +++ b/lib/accel/accel_rpc.c @@ -5,12 +5,14 @@ */ #include "accel_internal.h" +#include "spdk_internal/accel_module.h" #include "spdk/rpc.h" #include "spdk/util.h" #include "spdk/event.h" #include "spdk/stdinc.h" #include "spdk/env.h" +#include "spdk/util.h" static void rpc_accel_get_opc_assignments(struct spdk_jsonrpc_request *request, @@ -171,3 +173,102 @@ cleanup: } SPDK_RPC_REGISTER("accel_assign_opc", rpc_accel_assign_opc, SPDK_RPC_STARTUP) + +struct rpc_accel_crypto_key_create { + struct spdk_accel_crypto_key_create_param param; +}; + +static const struct spdk_json_object_decoder rpc_accel_dek_create_decoders[] = { + {"cipher", offsetof(struct rpc_accel_crypto_key_create, param.cipher), spdk_json_decode_string}, + {"key", offsetof(struct rpc_accel_crypto_key_create, param.hex_key), spdk_json_decode_string}, + {"key2", offsetof(struct rpc_accel_crypto_key_create, param.hex_key2), spdk_json_decode_string, true}, + {"name", offsetof(struct rpc_accel_crypto_key_create, param.key_name), spdk_json_decode_string}, +}; + +static void +rpc_accel_crypto_key_create(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_accel_crypto_key_create req = {}; + size_t key_size; + int rc; + + if (spdk_json_decode_object(params, rpc_accel_dek_create_decoders, + SPDK_COUNTOF(rpc_accel_dek_create_decoders), + &req)) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, + "spdk_json_decode_object failed"); + goto cleanup; + } + + rc = spdk_accel_crypto_key_create(&req.param); + if (rc) { + spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "failed to create DEK, rc %d", rc); + } else { + spdk_jsonrpc_send_bool_response(request, true); + } + +cleanup: + free(req.param.cipher); + if (req.param.hex_key) { + key_size = strnlen(req.param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH); + spdk_memset_s(req.param.hex_key, key_size, 0, key_size); + free(req.param.hex_key); + } + if (req.param.hex_key2) { + key_size = strnlen(req.param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH); + spdk_memset_s(req.param.hex_key2, key_size, 0, key_size); + free(req.param.hex_key2); + } + free(req.param.key_name); +} +SPDK_RPC_REGISTER("accel_crypto_key_create", rpc_accel_crypto_key_create, SPDK_RPC_RUNTIME) + +struct rpc_accel_crypto_keys_get_ctx { + char *key_name; +}; + +static const struct spdk_json_object_decoder rpc_accel_crypto_keys_get_decoders[] = { + {"key_name", offsetof(struct rpc_accel_crypto_keys_get_ctx, key_name), spdk_json_decode_string, true}, +}; + +static void +rpc_accel_crypto_keys_get(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_accel_crypto_keys_get_ctx req = {}; + struct spdk_accel_crypto_key *key = NULL; + struct spdk_json_write_ctx *w; + + if (params && spdk_json_decode_object(params, rpc_accel_crypto_keys_get_decoders, + SPDK_COUNTOF(rpc_accel_crypto_keys_get_decoders), + &req)) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, + "spdk_json_decode_object failed"); + free(req.key_name); + return; + } + + if (req.key_name) { + key = spdk_accel_crypto_key_get(req.key_name); + free(req.key_name); + if (!key) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "key was not found\n"); + return; + } + } + + w = spdk_jsonrpc_begin_result(request); + spdk_json_write_array_begin(w); + + if (key) { + _accel_crypto_key_dump_param(w, key); + } else { + _accel_crypto_keys_dump_param(w); + } + + spdk_json_write_array_end(w); + spdk_jsonrpc_end_result(request, w); +} +SPDK_RPC_REGISTER("accel_crypto_keys_get", rpc_accel_crypto_keys_get, SPDK_RPC_RUNTIME) diff --git a/lib/accel/accel_sw.c b/lib/accel/accel_sw.c index ee65949ba..4b8853fb8 100644 --- a/lib/accel/accel_sw.c +++ b/lib/accel/accel_sw.c @@ -1,11 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright (C) 2022 Intel Corporation. + * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES * All rights reserved. */ #include "spdk/stdinc.h" #include "spdk_internal/accel_module.h" +#include "accel_internal.h" #include "spdk/env.h" #include "spdk/likely.h" @@ -21,7 +23,16 @@ #ifdef SPDK_CONFIG_ISAL #include "../isa-l/include/igzip_lib.h" +#ifdef SPDK_CONFIG_ISAL_CRYPTO +#include "../isa-l-crypto/include/aes_xts.h" #endif +#endif + +#define ACCEL_AES_XTS_128_KEY_SIZE 16 +#define ACCEL_AES_XTS_256_KEY_SIZE 32 +#define ACCEL_AES_XTS "AES_XTS" +/* Per the AES-XTS spec, the size of data unit cannot be bigger than 2^20 blocks, 128b each block */ +#define ACCEL_AES_XTS_MAX_BLOCK_SIZE (1 << 24) struct sw_accel_io_channel { /* for ISAL */ @@ -33,6 +44,19 @@ struct sw_accel_io_channel { TAILQ_HEAD(, spdk_accel_task) tasks_to_complete; }; +typedef void (*sw_accel_crypto_op)(uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, + const uint8_t *src, uint8_t *dst); + +struct sw_accel_crypto_key_data { + sw_accel_crypto_op encrypt; + sw_accel_crypto_op decrypt; +}; + +static struct spdk_accel_module_if g_sw_module; + +static void sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *_key); +static int sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key); + /* Post SW completions to a list and complete in a poller as we don't want to * complete them on the caller's stack as they'll likely submit another. */ inline static void @@ -68,6 +92,8 @@ sw_accel_supports_opcode(enum accel_opcode opc) case ACCEL_OPC_COPY_CRC32C: case ACCEL_OPC_COMPRESS: case ACCEL_OPC_DECOMPRESS: + case ACCEL_OPC_ENCRYPT: + case ACCEL_OPC_DECRYPT: return true; default: return false; @@ -230,7 +256,7 @@ _sw_accel_compress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *ac rc = isal_deflate(&sw_ch->stream); if (rc) { - SPDK_ERRLOG("isal_deflate retunred error %d.\n", rc); + SPDK_ERRLOG("isal_deflate returned error %d.\n", rc); } if (remaining > 0) { @@ -290,7 +316,7 @@ _sw_accel_decompress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task * rc = isal_inflate(&sw_ch->state); if (rc) { - SPDK_ERRLOG("isal_inflate retunred error %d.\n", rc); + SPDK_ERRLOG("isal_inflate returned error %d.\n", rc); } } while (sw_ch->state.block_state < ISAL_BLOCK_FINISH); @@ -303,6 +329,127 @@ _sw_accel_decompress(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task * #endif } +static int +_sw_accel_crypto_operation(struct spdk_accel_task *accel_task, struct spdk_accel_crypto_key *key, + sw_accel_crypto_op op) +{ +#ifdef SPDK_CONFIG_ISAL_CRYPTO + uint64_t iv[2]; + size_t remaining_len; + uint64_t src_offset = 0, dst_offset = 0; + uint32_t src_iovpos = 0, dst_iovpos = 0, src_iovcnt, dst_iovcnt; + uint32_t block_size, crypto_len, crypto_accum_len = 0; + struct iovec *src_iov, *dst_iov; + uint8_t *src, *dst; + + /* iv is 128 bits, since we are using logical block address (64 bits) as iv, fill first 8 bytes with zeroes */ + iv[0] = 0; + iv[1] = accel_task->iv; + src_iov = accel_task->s.iovs; + src_iovcnt = accel_task->s.iovcnt; + if (accel_task->d.iovcnt) { + dst_iov = accel_task->d.iovs; + dst_iovcnt = accel_task->d.iovcnt; + } else { + /* inplace operation */ + dst_iov = accel_task->s.iovs; + dst_iovcnt = accel_task->s.iovcnt; + } + block_size = accel_task->block_size; + + if (!src_iovcnt || !dst_iovcnt || !block_size || !op) { + SPDK_ERRLOG("src_iovcnt %d, dst_iovcnt %d, block_size %d, op %p\n", src_iovcnt, dst_iovcnt, + block_size, op); + return -EINVAL; + } + + remaining_len = accel_task->nbytes; + + while (remaining_len) { + crypto_len = spdk_min(block_size - crypto_accum_len, src_iov->iov_len - src_offset); + crypto_len = spdk_min(crypto_len, dst_iov->iov_len - dst_offset); + src = (uint8_t *)src_iov->iov_base + src_offset; + dst = (uint8_t *)dst_iov->iov_base + dst_offset; + + op((uint8_t *)key->key2, (uint8_t *)key->key, (uint8_t *)iv, crypto_len, src, dst); + + src_offset += crypto_len; + dst_offset += crypto_len; + crypto_accum_len += crypto_len; + remaining_len -= crypto_len; + + if (crypto_accum_len == block_size) { + /* we can process part of logical block. Once the whole block is processed, increment iv */ + crypto_accum_len = 0; + iv[1]++; + } + if (src_offset == src_iov->iov_len) { + src_iov++; + src_iovpos++; + src_offset = 0; + } + if (src_iovpos == src_iovcnt) { + break; + } + if (dst_offset == dst_iov->iov_len) { + dst_iov++; + dst_iovpos++; + dst_offset = 0; + } + if (dst_iovpos == dst_iovcnt) { + break; + } + } + + if (remaining_len) { + SPDK_ERRLOG("remaining len %zu\n", remaining_len); + return -EINVAL; + } + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int +_sw_accel_encrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task) +{ + struct spdk_accel_crypto_key *key; + struct sw_accel_crypto_key_data *key_data; + + key = accel_task->crypto_key; + if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) { + return -EINVAL; + } + if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) { + SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n", + ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size); + return -ERANGE; + } + key_data = key->priv; + return _sw_accel_crypto_operation(accel_task, key, key_data->encrypt); +} + +static int +_sw_accel_decrypt(struct sw_accel_io_channel *sw_ch, struct spdk_accel_task *accel_task) +{ + struct spdk_accel_crypto_key *key; + struct sw_accel_crypto_key_data *key_data; + + key = accel_task->crypto_key; + if (spdk_unlikely(key->module_if != &g_sw_module || !key->priv)) { + return -EINVAL; + } + if (spdk_unlikely(accel_task->block_size > ACCEL_AES_XTS_MAX_BLOCK_SIZE)) { + SPDK_WARNLOG("Max block size for AES_XTS is limited to %u, current size %u\n", + ACCEL_AES_XTS_MAX_BLOCK_SIZE, accel_task->block_size); + return -ERANGE; + } + key_data = key->priv; + return _sw_accel_crypto_operation(accel_task, key, key_data->decrypt); +} + static int sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_task) { @@ -359,6 +506,12 @@ sw_accel_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *accel_ case ACCEL_OPC_DECOMPRESS: rc = _sw_accel_decompress(sw_ch, accel_task); break; + case ACCEL_OPC_ENCRYPT: + rc = _sw_accel_encrypt(sw_ch, accel_task); + break; + case ACCEL_OPC_DECRYPT: + rc = _sw_accel_decrypt(sw_ch, accel_task); + break; default: assert(false); break; @@ -380,14 +533,16 @@ static void sw_accel_module_fini(void *ctxt); static size_t sw_accel_module_get_ctx_size(void); static struct spdk_accel_module_if g_sw_module = { - .module_init = sw_accel_module_init, - .module_fini = sw_accel_module_fini, - .write_config_json = NULL, - .get_ctx_size = sw_accel_module_get_ctx_size, + .module_init = sw_accel_module_init, + .module_fini = sw_accel_module_fini, + .write_config_json = NULL, + .get_ctx_size = sw_accel_module_get_ctx_size, .name = "software", .supports_opcode = sw_accel_supports_opcode, .get_io_channel = sw_accel_get_io_channel, - .submit_tasks = sw_accel_submit_tasks + .submit_tasks = sw_accel_submit_tasks, + .crypto_key_init = sw_accel_crypto_key_init, + .crypto_key_deinit = sw_accel_crypto_key_deinit, }; static int @@ -477,4 +632,74 @@ sw_accel_module_fini(void *ctxt) spdk_accel_module_finish(); } +static int +sw_accel_create_aes_xts(struct spdk_accel_crypto_key *key) +{ +#ifdef SPDK_CONFIG_ISAL_CRYPTO + struct sw_accel_crypto_key_data *key_data; + + if (!key->key || !key->key2) { + SPDK_ERRLOG("key or key2 are missing\n"); + return -EINVAL; + } + + if (!key->key_size || key->key_size != key->key2_size) { + SPDK_ERRLOG("key size %zu is not equal to key2 size %zu or is 0\n", key->key_size, + key->key2_size); + return -EINVAL; + } + + key_data = calloc(1, sizeof(*key_data)); + if (!key_data) { + return -ENOMEM; + } + + switch (key->key_size) { + case ACCEL_AES_XTS_128_KEY_SIZE: + key_data->encrypt = XTS_AES_128_enc; + key_data->decrypt = XTS_AES_128_dec; + break; + case ACCEL_AES_XTS_256_KEY_SIZE: + key_data->encrypt = XTS_AES_256_enc; + key_data->decrypt = XTS_AES_256_dec; + break; + default: + SPDK_ERRLOG("Incorrect key size %zu, should be %d for AEX_XTS_128 or %d for AES_XTS_256\n", + key->key_size, ACCEL_AES_XTS_128_KEY_SIZE, ACCEL_AES_XTS_256_KEY_SIZE); + free(key_data); + return -EINVAL; + } + + key->priv = key_data; + + return 0; +#else + return -ENOTSUP; +#endif +} + +static int +sw_accel_crypto_key_init(struct spdk_accel_crypto_key *key) +{ + if (!key || !key->param.cipher) { + return -EINVAL; + } + if (strcmp(key->param.cipher, ACCEL_AES_XTS) == 0) { + return sw_accel_create_aes_xts(key); + } else { + SPDK_ERRLOG("Only %s cipher is supported\n", ACCEL_AES_XTS); + return -EINVAL; + } +} + +static void +sw_accel_crypto_key_deinit(struct spdk_accel_crypto_key *key) +{ + if (!key || key->module_if != &g_sw_module || !key->priv) { + return; + } + + free(key->priv); +} + SPDK_ACCEL_MODULE_REGISTER(sw, &g_sw_module) diff --git a/lib/accel/spdk_accel.map b/lib/accel/spdk_accel.map index 5262e9a46..2c964b4c6 100644 --- a/lib/accel/spdk_accel.map +++ b/lib/accel/spdk_accel.map @@ -15,6 +15,8 @@ spdk_accel_submit_copy_crc32cv; spdk_accel_submit_compress; spdk_accel_submit_decompress; + spdk_accel_submit_encrypt; + spdk_accel_submit_decrypt; spdk_accel_get_opc_module_name; spdk_accel_assign_opc; spdk_accel_write_config_json; @@ -26,6 +28,9 @@ spdk_accel_sequence_reverse; spdk_accel_get_buf; spdk_accel_put_buf; + spdk_accel_crypto_key_create; + spdk_accel_crypto_key_destroy; + spdk_accel_crypto_key_get; # functions needed by modules spdk_accel_module_list_add; diff --git a/python/spdk/rpc/accel.py b/python/spdk/rpc/accel.py index ad527b859..3d320f296 100644 --- a/python/spdk/rpc/accel.py +++ b/python/spdk/rpc/accel.py @@ -31,3 +31,37 @@ def accel_assign_opc(client, opname, module): } return client.call('accel_assign_opc', params) + + +def accel_crypto_key_create(client, cipher, key, key2, name): + """Create Data Encryption Key Identifier. + + Args: + cipher: cipher + key: key + key2: key2 + name: key name + """ + params = { + 'cipher': cipher, + 'key': key, + 'name': name, + } + if key2 is not None: + params['key2'] = key2 + + return client.call('accel_crypto_key_create', params) + + +def accel_crypto_keys_get(client, key_name): + """Get a list of the crypto keys. + + Args: + key_name: Get information about a specific key + """ + params = {} + + if key_name is not None: + params['key_name'] = key_name + + return client.call('accel_crypto_keys_get', params) diff --git a/scripts/rpc.py b/scripts/rpc.py index 16e92049c..8ee6fd116 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2792,6 +2792,28 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p.add_argument('-m', '--module', help='name of module') p.set_defaults(func=accel_assign_opc) + def accel_crypto_key_create(args): + print_dict(rpc.accel.accel_crypto_key_create(args.client, + cipher=args.cipher, + key=args.key, + key2=args.key2, + name=args.name)) + + p = subparsers.add_parser('accel_crypto_key_create', help='Create encryption key') + p.add_argument('-c', '--cipher', help='cipher', required=True, type=str) + p.add_argument('-k', '--key', help='key', required=True, type=str) + p.add_argument('-e', '--key2', help='key2', required=False, type=str) + p.add_argument('-n', '--name', help='key name', required=True, type=str) + p.set_defaults(func=accel_crypto_key_create) + + def accel_crypto_keys_get(args): + print_dict(rpc.accel.accel_crypto_keys_get(args.client, + key_name=args.key_name)) + + p = subparsers.add_parser('accel_crypto_keys_get', help='Get a list of the crypto keys') + p.add_argument('-k', '--key-name', help='Get information about a specific key', type=str) + p.set_defaults(func=accel_crypto_keys_get) + # ioat def ioat_scan_accel_module(args): rpc.ioat.ioat_scan_accel_module(args.client) diff --git a/test/external_code/hello_world/Makefile b/test/external_code/hello_world/Makefile index ba4be9e1c..ec1a21043 100644 --- a/test/external_code/hello_world/Makefile +++ b/test/external_code/hello_world/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (C) 2020 Intel Corporation. +# Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES # All rights reserved. # @@ -13,22 +14,22 @@ SYS_LIB := $(shell PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)" pkg-config --libs --stat # Shows how to compile both an external bdev and an external application against the SPDK combined shared object and dpdk shared objects. bdev_shared_combo: $(CC) $(COMMON_CFLAGS) -L../passthru -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lpassthru_external \ - -lspdk $(DPDK_LIB) -Wl,--no-whole-archive + -lspdk $(DPDK_LIB) -Wl,--no-whole-archive $(SYS_LIB) # Shows how to compile both an external bdev and an external application against the SPDK individual shared objects and dpdk shared objects. bdev_shared_iso: $(CC) $(COMMON_CFLAGS) -L../passthru -Wl,--no-as-needed -o hello_bdev ./hello_bdev.c \ -lpassthru_external $(SPDK_EVENT_LIB) \ - $(DPDK_LIB) + $(DPDK_LIB) $(SYS_LIB) # Shows how to compile an external application against the SPDK combined shared object and dpdk shared objects. alone_shared_combo: - $(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lspdk $(DPDK_LIB) + $(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c -lspdk $(DPDK_LIB) $(SYS_LIB) # Shows how to compile an external application against the SPDK individual shared objects and dpdk shared objects. alone_shared_iso: $(CC) $(COMMON_CFLAGS) -Wl,-rpath=$(SPDK_LIB_DIR),--no-as-needed -o hello_bdev ./hello_bdev.c \ - $(SPDK_EVENT_LIB) $(DPDK_LIB) + $(SPDK_EVENT_LIB) $(DPDK_LIB) $(SYS_LIB) # Shows how to compile an external application against the SPDK archives. alone_static: diff --git a/test/unit/lib/accel/accel.c/accel_ut.c b/test/unit/lib/accel/accel.c/accel_ut.c index 9fc539431..667356cfa 100644 --- a/test/unit/lib/accel/accel.c/accel_ut.c +++ b/test/unit/lib/accel/accel.c/accel_ut.c @@ -24,6 +24,17 @@ DEFINE_STUB(spdk_memory_domain_create, int, struct spdk_memory_domain_ctx *ctx, const char *id), 0); DEFINE_STUB_V(spdk_memory_domain_destroy, (struct spdk_memory_domain *domain)); +#ifdef SPDK_CONFIG_ISAL +DEFINE_STUB_V(XTS_AES_128_enc, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, + const uint8_t *src, uint8_t *dst)); +DEFINE_STUB_V(XTS_AES_128_dec, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, + const uint8_t *src, uint8_t *dst)); +DEFINE_STUB_V(XTS_AES_256_enc, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, + const uint8_t *src, uint8_t *dst)); +DEFINE_STUB_V(XTS_AES_256_dec, (uint8_t *k2, uint8_t *k1, uint8_t *tweak, uint64_t lba_size, + const uint8_t *src, uint8_t *dst)); +#endif + /* global vars and setup/cleanup functions used for all test functions */ struct spdk_accel_module_if g_module = {}; struct spdk_io_channel *g_ch = NULL;