diff --git a/include/spdk/accel.h b/include/spdk/accel.h index a8ee8af81..052e4afb1 100644 --- a/include/spdk/accel.h +++ b/include/spdk/accel.h @@ -381,6 +381,81 @@ int spdk_accel_append_decompress(struct spdk_accel_sequence **seq, struct spdk_i struct spdk_memory_domain *src_domain, void *src_domain_ctx, int flags, spdk_accel_step_cb cb_fn, void *cb_arg); +/** + * Append an encrypt operation to a sequence. + * + * `nbytes` must be multiple of `block_size`. `iv` is used to encrypt the first logical block of + * size `block_size`. If `src_iovs` describes more than one logical block then `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 seq Sequence object. If NULL, a new sequence object will be created. + * \param ch I/O channel. + * \param key Data Encryption Key identifier + * \param dst_iovs Destination I/O vector array. + * \param dst_iovcnt Size of the `dst_iovs` array. + * \param dst_domain Memory domain to which the destination buffers belong. + * \param dst_domain_ctx Destination buffer domain context. + * \param src_iovs Source I/O vector array. + * \param src_iovcnt Size of the `src_iovs` array. + * \param src_domain Memory domain to which the source buffers belong. + * \param src_domain_ctx Source buffer domain context. + * \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 `iv`. + * \param flags Accel operation flags. + * \param cb_fn Callback to be executed once this operation is completed. + * \param cb_arg Argument to be passed to `cb_fn`. + * + * \return 0 if operation was successfully added to the sequence, negative errno otherwise. + */ +int spdk_accel_append_encrypt(struct spdk_accel_sequence **seq, struct spdk_io_channel *ch, + struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct spdk_memory_domain *dst_domain, void *dst_domain_ctx, + struct iovec *src_iovs, uint32_t src_iovcnt, + struct spdk_memory_domain *src_domain, void *src_domain_ctx, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_step_cb cb_fn, void *cb_arg); + +/** + * Append a decrypt operation to a sequence. + * + * `nbytes` must be multiple of `block_size`. `iv` is used to decrypt the first logical block of + * size `block_size`. If `src_iovs` describes more than one logical block then `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 seq Sequence object. If NULL, a new sequence object will be created. + * \param ch I/O channel. + * \param key Data Encryption Key identifier + * \param dst_iovs Destination I/O vector array. + * \param dst_iovcnt Size of the `dst_iovs` array. + * \param dst_domain Memory domain to which the destination buffers belong. + * \param dst_domain_ctx Destination buffer domain context. + * \param src_iovs Source I/O vector array. + * \param src_iovcnt Size of the `src_iovs` array. + * \param src_domain Memory domain to which the source buffers belong. + * \param src_domain_ctx Source buffer domain context. + * \param iv Initialization vector (tweak) used for decryption. Should be the same as `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 `iv`. + * \param flags Accel operation flags. + * \param cb_fn Callback to be executed once this operation is completed. + * \param cb_arg Argument to be passed to `cb_fn`. + * + * \return 0 if operation was successfully added to the sequence, negative errno otherwise. + */ +int spdk_accel_append_decrypt(struct spdk_accel_sequence **seq, struct spdk_io_channel *ch, + struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct spdk_memory_domain *dst_domain, void *dst_domain_ctx, + struct iovec *src_iovs, uint32_t src_iovcnt, + struct spdk_memory_domain *src_domain, void *src_domain_ctx, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_step_cb cb_fn, void *cb_arg); + /** * Finish a sequence and execute all its operations. After the completion callback is executed, the * sequence object is automatically freed. diff --git a/lib/accel/accel.c b/lib/accel/accel.c index 9b5a18565..e458d1d5f 100644 --- a/lib/accel/accel.c +++ b/lib/accel/accel.c @@ -919,6 +919,118 @@ spdk_accel_append_decompress(struct spdk_accel_sequence **pseq, struct spdk_io_c return 0; } +int +spdk_accel_append_encrypt(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch, + struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct spdk_memory_domain *dst_domain, void *dst_domain_ctx, + struct iovec *src_iovs, uint32_t src_iovcnt, + struct spdk_memory_domain *src_domain, void *src_domain_ctx, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_step_cb cb_fn, void *cb_arg) +{ + struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); + struct spdk_accel_task *task; + struct spdk_accel_sequence *seq = *pseq; + + if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || + !block_size)) { + return -EINVAL; + } + + if (seq == NULL) { + seq = accel_sequence_get(accel_ch); + if (spdk_unlikely(seq == NULL)) { + return -ENOMEM; + } + } + + assert(seq->ch == accel_ch); + task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg); + if (spdk_unlikely(task == NULL)) { + if (*pseq == NULL) { + accel_sequence_put(seq); + } + + return -ENOMEM; + } + + task->crypto_key = key; + task->src_domain = src_domain; + task->src_domain_ctx = src_domain_ctx; + task->s.iovs = src_iovs; + task->s.iovcnt = src_iovcnt; + task->dst_domain = dst_domain; + task->dst_domain_ctx = dst_domain_ctx; + task->d.iovs = dst_iovs; + task->d.iovcnt = dst_iovcnt; + task->iv = iv; + task->block_size = block_size; + task->flags = flags; + task->op_code = ACCEL_OPC_ENCRYPT; + + TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link); + *pseq = seq; + + return 0; +} + +int +spdk_accel_append_decrypt(struct spdk_accel_sequence **pseq, struct spdk_io_channel *ch, + struct spdk_accel_crypto_key *key, + struct iovec *dst_iovs, uint32_t dst_iovcnt, + struct spdk_memory_domain *dst_domain, void *dst_domain_ctx, + struct iovec *src_iovs, uint32_t src_iovcnt, + struct spdk_memory_domain *src_domain, void *src_domain_ctx, + uint64_t iv, uint32_t block_size, int flags, + spdk_accel_step_cb cb_fn, void *cb_arg) +{ + struct accel_io_channel *accel_ch = spdk_io_channel_get_ctx(ch); + struct spdk_accel_task *task; + struct spdk_accel_sequence *seq = *pseq; + + if (spdk_unlikely(!dst_iovs || !dst_iovcnt || !src_iovs || !src_iovcnt || !key || + !block_size)) { + return -EINVAL; + } + + if (seq == NULL) { + seq = accel_sequence_get(accel_ch); + if (spdk_unlikely(seq == NULL)) { + return -ENOMEM; + } + } + + assert(seq->ch == accel_ch); + task = accel_sequence_get_task(accel_ch, seq, cb_fn, cb_arg); + if (spdk_unlikely(task == NULL)) { + if (*pseq == NULL) { + accel_sequence_put(seq); + } + + return -ENOMEM; + } + + task->crypto_key = key; + task->src_domain = src_domain; + task->src_domain_ctx = src_domain_ctx; + task->s.iovs = src_iovs; + task->s.iovcnt = src_iovcnt; + task->dst_domain = dst_domain; + task->dst_domain_ctx = dst_domain_ctx; + task->d.iovs = dst_iovs; + task->d.iovcnt = dst_iovcnt; + task->iv = iv; + task->block_size = block_size; + task->flags = flags; + task->op_code = ACCEL_OPC_DECRYPT; + + TAILQ_INSERT_TAIL(&seq->tasks, task, seq_link); + *pseq = seq; + + return 0; +} + int spdk_accel_get_buf(struct spdk_io_channel *ch, uint64_t len, void **buf, struct spdk_memory_domain **domain, void **domain_ctx) @@ -1461,7 +1573,9 @@ accel_sequence_merge_tasks(struct spdk_accel_sequence *seq, struct spdk_accel_ta * So, for the sake of simplicity, skip this type of operations for now. */ if (next->op_code != ACCEL_OPC_DECOMPRESS && - next->op_code != ACCEL_OPC_COPY) { + next->op_code != ACCEL_OPC_COPY && + next->op_code != ACCEL_OPC_ENCRYPT && + next->op_code != ACCEL_OPC_DECRYPT) { break; } if (task->dst_domain != next->src_domain) { @@ -1479,6 +1593,8 @@ accel_sequence_merge_tasks(struct spdk_accel_sequence *seq, struct spdk_accel_ta break; case ACCEL_OPC_DECOMPRESS: case ACCEL_OPC_FILL: + case ACCEL_OPC_ENCRYPT: + case ACCEL_OPC_DECRYPT: /* We can only merge tasks when one of them is a copy */ if (next->op_code != ACCEL_OPC_COPY) { break; diff --git a/lib/accel/spdk_accel.map b/lib/accel/spdk_accel.map index 2c964b4c6..0c053d3c2 100644 --- a/lib/accel/spdk_accel.map +++ b/lib/accel/spdk_accel.map @@ -23,6 +23,8 @@ spdk_accel_append_copy; spdk_accel_append_fill; spdk_accel_append_decompress; + spdk_accel_append_encrypt; + spdk_accel_append_decrypt; spdk_accel_sequence_finish; spdk_accel_sequence_abort; spdk_accel_sequence_reverse; diff --git a/test/unit/lib/accel/accel.c/accel_ut.c b/test/unit/lib/accel/accel.c/accel_ut.c index 4b550dc80..3bf0d3fff 100644 --- a/test/unit/lib/accel/accel.c/accel_ut.c +++ b/test/unit/lib/accel/accel.c/accel_ut.c @@ -1463,6 +1463,7 @@ test_sequence_copy_elision(void) struct iovec src_iovs[4], dst_iovs[4], exp_iovs[2]; char buf[4096], tmp[4][4096]; struct accel_module modules[ACCEL_OPC_LAST]; + struct spdk_accel_crypto_key key = {}; int i, rc, completed; ioch = spdk_accel_get_io_channel(); @@ -1750,6 +1751,112 @@ test_sequence_copy_elision(void) CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_FILL].count, 1); + /* Check copy + encrypt + copy */ + seq = NULL; + completed = 0; + g_seq_operations[ACCEL_OPC_COPY].count = 0; + g_seq_operations[ACCEL_OPC_ENCRYPT].count = 0; + g_seq_operations[ACCEL_OPC_ENCRYPT].dst_iovcnt = 1; + g_seq_operations[ACCEL_OPC_ENCRYPT].src_iovcnt = 1; + g_seq_operations[ACCEL_OPC_ENCRYPT].src_iovs = &exp_iovs[0]; + g_seq_operations[ACCEL_OPC_ENCRYPT].dst_iovs = &exp_iovs[1]; + exp_iovs[0].iov_base = tmp[0]; + exp_iovs[0].iov_len = sizeof(tmp[0]); + exp_iovs[1].iov_base = buf; + exp_iovs[1].iov_len = sizeof(buf); + + dst_iovs[0].iov_base = tmp[1]; + dst_iovs[0].iov_len = sizeof(tmp[1]); + src_iovs[0].iov_base = tmp[0]; + src_iovs[0].iov_len = sizeof(tmp[0]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, + &src_iovs[0], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[1].iov_base = tmp[2]; + dst_iovs[1].iov_len = sizeof(tmp[2]); + src_iovs[1].iov_base = tmp[1]; + src_iovs[1].iov_len = sizeof(tmp[1]); + rc = spdk_accel_append_encrypt(&seq, ioch, &key, &dst_iovs[1], 1, NULL, NULL, + &src_iovs[1], 1, NULL, NULL, 0, sizeof(tmp[2]), 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[2].iov_base = buf; + dst_iovs[2].iov_len = sizeof(buf); + src_iovs[2].iov_base = tmp[2]; + src_iovs[2].iov_len = sizeof(tmp[2]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[2], 1, NULL, NULL, + &src_iovs[2], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + ut_seq.complete = false; + rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); + CU_ASSERT_EQUAL(rc, 0); + + poll_threads(); + + CU_ASSERT_EQUAL(completed, 3); + CU_ASSERT(ut_seq.complete); + CU_ASSERT_EQUAL(ut_seq.status, 0); + CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); + CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_ENCRYPT].count, 1); + + /* Check copy + decrypt + copy */ + seq = NULL; + completed = 0; + g_seq_operations[ACCEL_OPC_COPY].count = 0; + g_seq_operations[ACCEL_OPC_DECRYPT].count = 0; + g_seq_operations[ACCEL_OPC_DECRYPT].dst_iovcnt = 1; + g_seq_operations[ACCEL_OPC_DECRYPT].src_iovcnt = 1; + g_seq_operations[ACCEL_OPC_DECRYPT].src_iovs = &exp_iovs[0]; + g_seq_operations[ACCEL_OPC_DECRYPT].dst_iovs = &exp_iovs[1]; + exp_iovs[0].iov_base = tmp[0]; + exp_iovs[0].iov_len = sizeof(tmp[0]); + exp_iovs[1].iov_base = buf; + exp_iovs[1].iov_len = sizeof(buf); + + dst_iovs[0].iov_base = tmp[1]; + dst_iovs[0].iov_len = sizeof(tmp[1]); + src_iovs[0].iov_base = tmp[0]; + src_iovs[0].iov_len = sizeof(tmp[0]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, + &src_iovs[0], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[1].iov_base = tmp[2]; + dst_iovs[1].iov_len = sizeof(tmp[2]); + src_iovs[1].iov_base = tmp[1]; + src_iovs[1].iov_len = sizeof(tmp[1]); + rc = spdk_accel_append_decrypt(&seq, ioch, &key, &dst_iovs[1], 1, NULL, NULL, + &src_iovs[1], 1, NULL, NULL, 0, sizeof(tmp[2]), 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[2].iov_base = buf; + dst_iovs[2].iov_len = sizeof(buf); + src_iovs[2].iov_base = tmp[2]; + src_iovs[2].iov_len = sizeof(tmp[2]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[2], 1, NULL, NULL, + &src_iovs[2], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + ut_seq.complete = false; + rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); + CU_ASSERT_EQUAL(rc, 0); + + poll_threads(); + + CU_ASSERT_EQUAL(completed, 3); + CU_ASSERT(ut_seq.complete); + CU_ASSERT_EQUAL(ut_seq.status, 0); + CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_COPY].count, 0); + CU_ASSERT_EQUAL(g_seq_operations[ACCEL_OPC_DECRYPT].count, 1); + /* Cleanup module pointers to make subsequent tests work correctly */ for (i = 0; i < ACCEL_OPC_LAST; ++i) { g_modules_opc[i] = modules[i]; @@ -1757,6 +1864,10 @@ test_sequence_copy_elision(void) g_seq_operations[ACCEL_OPC_DECOMPRESS].src_iovs = NULL; g_seq_operations[ACCEL_OPC_DECOMPRESS].dst_iovs = NULL; + g_seq_operations[ACCEL_OPC_ENCRYPT].src_iovs = NULL; + g_seq_operations[ACCEL_OPC_ENCRYPT].src_iovs = NULL; + g_seq_operations[ACCEL_OPC_DECRYPT].dst_iovs = NULL; + g_seq_operations[ACCEL_OPC_DECRYPT].dst_iovs = NULL; spdk_put_io_channel(ioch); poll_threads(); @@ -2784,6 +2895,204 @@ test_sequence_module_memory_domain(void) poll_threads(); } +#ifdef SPDK_CONFIG_ISAL_CRYPTO +static void +ut_encrypt_cb(void *cb_arg, int status) +{ + int *completed = cb_arg; + + CU_ASSERT_EQUAL(status, 0); + + *completed = 1; +} + +static void +test_sequence_crypto(void) +{ + struct spdk_accel_sequence *seq = NULL; + struct spdk_io_channel *ioch; + struct spdk_accel_crypto_key *key; + struct spdk_accel_crypto_key_create_param key_params = { + .cipher = "AES_XTS", + .hex_key = "00112233445566778899aabbccddeeff", + .hex_key2 = "ffeeddccbbaa99887766554433221100", + .key_name = "ut_key", + }; + struct ut_sequence ut_seq; + unsigned char buf[4096], encrypted[4096] = {}, data[4096], tmp[3][4096]; + struct iovec src_iovs[4], dst_iovs[4]; + int rc, completed = 0; + size_t i; + + ioch = spdk_accel_get_io_channel(); + SPDK_CU_ASSERT_FATAL(ioch != NULL); + + rc = spdk_accel_crypto_key_create(&key_params); + CU_ASSERT_EQUAL(rc, 0); + key = spdk_accel_crypto_key_get(key_params.key_name); + SPDK_CU_ASSERT_FATAL(key != NULL); + + for (i = 0; i < sizeof(data); ++i) { + data[i] = (uint8_t)i & 0xff; + } + + dst_iovs[0].iov_base = encrypted; + dst_iovs[0].iov_len = sizeof(encrypted); + src_iovs[0].iov_base = data; + src_iovs[0].iov_len = sizeof(data); + rc = spdk_accel_submit_encrypt(ioch, key, &dst_iovs[0], 1, &src_iovs[0], 1, 0, 4096, 0, + ut_encrypt_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + while (!completed) { + poll_threads(); + } + + /* Verify that encryption operation in a sequence produces the same result */ + seq = NULL; + completed = 0; + + dst_iovs[0].iov_base = tmp[0]; + dst_iovs[0].iov_len = sizeof(tmp[0]); + src_iovs[0].iov_base = data; + src_iovs[0].iov_len = sizeof(data); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, + &src_iovs[0], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[1].iov_base = tmp[1]; + dst_iovs[1].iov_len = sizeof(tmp[1]); + src_iovs[1].iov_base = tmp[0]; + src_iovs[1].iov_len = sizeof(tmp[0]); + rc = spdk_accel_append_encrypt(&seq, ioch, key, &dst_iovs[1], 1, NULL, NULL, + &src_iovs[1], 1, NULL, NULL, 0, 4096, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[2].iov_base = buf; + dst_iovs[2].iov_len = sizeof(buf); + src_iovs[2].iov_base = tmp[1]; + src_iovs[2].iov_len = sizeof(tmp[1]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[2], 1, NULL, NULL, + &src_iovs[2], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + ut_seq.complete = false; + rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); + CU_ASSERT_EQUAL(rc, 0); + + poll_threads(); + + CU_ASSERT_EQUAL(completed, 3); + CU_ASSERT(ut_seq.complete); + CU_ASSERT_EQUAL(ut_seq.status, 0); + CU_ASSERT_EQUAL(memcmp(buf, encrypted, sizeof(buf)), 0); + + /* Check that decryption produces the original buffer */ + seq = NULL; + completed = 0; + memset(buf, 0, sizeof(buf)); + + dst_iovs[0].iov_base = tmp[0]; + dst_iovs[0].iov_len = sizeof(tmp[0]); + src_iovs[0].iov_base = encrypted; + src_iovs[0].iov_len = sizeof(encrypted); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, + &src_iovs[0], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[1].iov_base = tmp[1]; + dst_iovs[1].iov_len = sizeof(tmp[1]); + src_iovs[1].iov_base = tmp[0]; + src_iovs[1].iov_len = sizeof(tmp[0]); + rc = spdk_accel_append_decrypt(&seq, ioch, key, &dst_iovs[1], 1, NULL, NULL, + &src_iovs[1], 1, NULL, NULL, 0, 4096, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[2].iov_base = buf; + dst_iovs[2].iov_len = sizeof(buf); + src_iovs[2].iov_base = tmp[1]; + src_iovs[2].iov_len = sizeof(tmp[1]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[2], 1, NULL, NULL, + &src_iovs[2], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + ut_seq.complete = false; + rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); + CU_ASSERT_EQUAL(rc, 0); + + poll_threads(); + + CU_ASSERT_EQUAL(completed, 3); + CU_ASSERT(ut_seq.complete); + CU_ASSERT_EQUAL(ut_seq.status, 0); + CU_ASSERT_EQUAL(memcmp(buf, data, sizeof(buf)), 0); + + /* Check encrypt + decrypt in a single sequence */ + seq = NULL; + completed = 0; + memset(buf, 0, sizeof(buf)); + + dst_iovs[0].iov_base = tmp[0]; + dst_iovs[0].iov_len = sizeof(tmp[0]); + src_iovs[0].iov_base = data; + src_iovs[0].iov_len = sizeof(data); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[0], 1, NULL, NULL, + &src_iovs[0], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[1].iov_base = tmp[1]; + dst_iovs[1].iov_len = sizeof(tmp[1]); + src_iovs[1].iov_base = tmp[0]; + src_iovs[1].iov_len = sizeof(tmp[0]); + rc = spdk_accel_append_encrypt(&seq, ioch, key, &dst_iovs[1], 1, NULL, NULL, + &src_iovs[1], 1, NULL, NULL, 0, 4096, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + + dst_iovs[2].iov_base = tmp[2]; + dst_iovs[2].iov_len = sizeof(tmp[2]); + src_iovs[2].iov_base = tmp[1]; + src_iovs[2].iov_len = sizeof(tmp[1]); + rc = spdk_accel_append_decrypt(&seq, ioch, key, &dst_iovs[2], 1, NULL, NULL, + &src_iovs[2], 1, NULL, NULL, 0, 4096, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + dst_iovs[3].iov_base = buf; + dst_iovs[3].iov_len = sizeof(buf); + src_iovs[3].iov_base = tmp[2]; + src_iovs[3].iov_len = sizeof(tmp[2]); + rc = spdk_accel_append_copy(&seq, ioch, &dst_iovs[3], 1, NULL, NULL, + &src_iovs[3], 1, NULL, NULL, 0, + ut_sequence_step_cb, &completed); + CU_ASSERT_EQUAL(rc, 0); + + ut_seq.complete = false; + rc = spdk_accel_sequence_finish(seq, ut_sequence_complete_cb, &ut_seq); + CU_ASSERT_EQUAL(rc, 0); + + poll_threads(); + + CU_ASSERT_EQUAL(completed, 4); + CU_ASSERT(ut_seq.complete); + CU_ASSERT_EQUAL(ut_seq.status, 0); + CU_ASSERT_EQUAL(memcmp(buf, data, sizeof(buf)), 0); + + rc = spdk_accel_crypto_key_destroy(key); + CU_ASSERT_EQUAL(rc, 0); + spdk_put_io_channel(ioch); + poll_threads(); +} +#endif /* SPDK_CONFIG_ISAL_CRYPTO */ + static int test_sequence_setup(void) { @@ -2865,7 +3174,9 @@ main(int argc, char **argv) CU_ADD_TEST(seq_suite, test_sequence_accel_buffers); CU_ADD_TEST(seq_suite, test_sequence_memory_domain); CU_ADD_TEST(seq_suite, test_sequence_module_memory_domain); - +#ifdef SPDK_CONFIG_ISAL_CRYPTO /* accel_sw requires isa-l-crypto for crypto operations */ + CU_ADD_TEST(seq_suite, test_sequence_crypto); +#endif suite = CU_add_suite("accel", test_setup, test_cleanup); CU_ADD_TEST(suite, test_spdk_accel_task_complete); CU_ADD_TEST(suite, test_get_task);