[dpdk-dev] [PATCH] cryptodev: changes to crypto operation APIs to support non prescriptive chaining of crypto transforms in a crypto operation. app/test: updates to cryptodev unit tests to support new xform chaining APIs. aesni_mb_pmd: updates to device to support API changes

Declan Doherty declan.doherty at intel.com
Tue Sep 15 18:36:13 CEST 2015


Proposed changes to cryptodev API for comment based on Neil's comments
on the initial RFC. I have included the updates to the cryptodev unit test
suite and the AESNI multi buffer PMD for illustrative purposes, I will include the
changes for the QAT in a V1 patchset if the proposes changes to the API are
acceptable.

Signed-off-by: Declan Doherty <declan.doherty at intel.com>
---
 app/test/test_cryptodev.c                          | 276 +++++++++++++++------
 drivers/crypto/aesni_mb/aesni_mb_ops.h             |   2 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c         | 188 +++++++++-----
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c     |  10 +-
 drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h |  28 ++-
 lib/librte_cryptodev/rte_crypto.h                  | 141 ++++++++---
 lib/librte_cryptodev/rte_cryptodev.c               |  54 ++--
 lib/librte_cryptodev/rte_cryptodev.h               |  26 +-
 lib/librte_cryptodev/rte_cryptodev_pmd.h           |  10 +-
 9 files changed, 506 insertions(+), 229 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 68cc0bf..93b7e0a 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -62,6 +62,8 @@
 #define DIGEST_BYTE_LENGTH_SHA1		(BYTE_LENGTH(160))
 #define DIGEST_BYTE_LENGTH_SHA256	(BYTE_LENGTH(256))
 #define DIGEST_BYTE_LENGTH_SHA512	(BYTE_LENGTH(512))
+#define DIGEST_BYTE_LENGTH_AES_XCBC     (BYTE_LENGTH(96))
+#define AES_XCBC_MAC_KEY_SZ             (16)
 
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA1		(12)
 #define TRUNCATED_DIGEST_BYTE_LENGTH_SHA256		(16)
@@ -75,13 +77,13 @@ struct crypto_testsuite_params {
 	struct rte_cryptodev_config conf;
 	struct rte_cryptodev_qp_conf qp_conf;
 
-	uint8_t valid_devs[RTE_MAX_CRYPTODEVS];
+	uint8_t valid_devs[RTE_CRYPTO_MAX_DEVS];
 	uint8_t valid_dev_count;
 };
 
 struct crypto_unittest_params {
-	struct rte_crypto_cipher_params cipher_params;
-	struct rte_crypto_hash_params hash_params;
+	struct rte_crypto_xform cipher_xform;
+	struct rte_crypto_xform auth_xform;
 
 	struct rte_cryptodev_session *sess;
 
@@ -92,6 +94,17 @@ struct crypto_unittest_params {
 	uint8_t *digest;
 };
 
+/*
+ * Forward declarations.
+ */
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(struct crypto_unittest_params *ut_params);
+
+static int
+test_AES_CBC_HMAC_SHA512_decrypt_perform(struct rte_cryptodev_session *sess,
+		struct crypto_unittest_params *ut_params,
+		struct crypto_testsuite_params *ts_param);
+
 static struct rte_mbuf *
 setup_test_string(struct rte_mempool *mpool,
 		const char *string, size_t len, uint8_t blocksize)
@@ -184,7 +197,7 @@ testsuite_setup(void)
 	}
 
 	ts_params->crypto_op_pool = rte_crypto_op_pool_create("CRYPTO_OP_POOL",
-			NUM_MBUFS, MBUF_CACHE_SIZE, rte_socket_id());
+			NUM_MBUFS, MBUF_CACHE_SIZE, 2, rte_socket_id());
 	if (ts_params->crypto_op_pool == NULL) {
 		RTE_LOG(ERR, USER1, "Can't create CRYPTO_OP_POOL\n");
 		return TEST_FAILED;
@@ -436,6 +449,11 @@ static const uint8_t catch_22_quote_2_512_bytes_AES_CBC_ciphertext[] = {
 	0X95, 0XBB, 0X26, 0X74, 0X69, 0X12, 0X7F, 0XF1, 0XBB, 0XFF, 0XAE, 0XB5, 0X99, 0X6E, 0XCB, 0X0C
 };
 
+static const uint8_t catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA1_digest[] = {
+	0x9a, 0X4f, 0X88, 0X1b, 0Xb6, 0X8f, 0Xd8, 0X60,
+	0X42, 0X1a, 0X7d, 0X3d, 0Xf5, 0X82, 0X80, 0Xf1,
+	0X18, 0X8c, 0X1d, 0X32 };
+
 
 static int
 test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
@@ -452,22 +470,28 @@ test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
 	TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
 
 	/* Setup Cipher Parameters */
-	ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-	ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
-	ut_params->cipher_params.key.data = aes_cbc_key;
-	ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+	ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+	ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+	ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+	ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
 
 	/* Setup HMAC Parameters */
-	ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
-	ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
-	ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA1;
-	ut_params->hash_params.auth_key.data = hmac_sha1_key;
-	ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA1;
+
+	ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+	ut_params->auth_xform.next = NULL;
+
+	ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+	ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
+	ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA1;
+	ut_params->auth_xform.auth.key.data = hmac_sha1_key;
+	ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA1;
 
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-			&ut_params->cipher_params, &ut_params->hash_params,
-			RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH);
+			&ut_params->cipher_xform);
 	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	/* Generate Crypto op data structure */
@@ -522,6 +546,88 @@ test_AES_CBC_HMAC_SHA1_encrypt_digest(void)
 	return TEST_SUCCESS;
 }
 
+
+static int
+test_AES_CBC_HMAC_SHA1_encrypt_digest_sessionless(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	struct crypto_unittest_params *ut_params = &unittest_params;
+
+	/* Generate test mbuf data and space for digest */
+	ut_params->ibuf = setup_test_string(ts_params->mbuf_pool, catch_22_quote,
+			QUOTE_512_BYTES, 0);
+
+	ut_params->digest = (uint8_t *)rte_pktmbuf_append(ut_params->ibuf,
+			DIGEST_BYTE_LENGTH_SHA1);
+	TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
+
+	/* Generate Crypto op data structure */
+	ut_params->op = rte_crypto_op_alloc_sessionless(ts_params->crypto_op_pool, 2);
+	TEST_ASSERT_NOT_NULL(ut_params->op, "Failed to allocate crypto_op");
+
+	/* Set crypto operation data parameters */
+	ut_params->op->xform->type = RTE_CRYPTO_XFORM_CIPHER;
+
+	/* cipher parameters */
+	ut_params->op->xform->cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+	ut_params->op->xform->cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->op->xform->cipher.key.data = aes_cbc_key;
+	ut_params->op->xform->cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+
+	/* hash parameters */
+	ut_params->op->xform->next->type = RTE_CRYPTO_XFORM_AUTH;
+
+	ut_params->op->xform->next->auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+	ut_params->op->xform->next->auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
+	ut_params->op->xform->next->auth.key.length = HMAC_KEY_LENGTH_SHA1;
+	ut_params->op->xform->next->auth.key.data = hmac_sha1_key;
+	ut_params->op->xform->next->auth.digest_length = DIGEST_BYTE_LENGTH_SHA1;
+
+	ut_params->op->digest.data = ut_params->digest;
+	ut_params->op->digest.phys_addr = rte_pktmbuf_mtophys_offset(ut_params->ibuf,
+			QUOTE_512_BYTES);
+	ut_params->op->digest.length = DIGEST_BYTE_LENGTH_SHA1;
+
+	ut_params->op->iv.data = (uint8_t *)rte_pktmbuf_prepend(ut_params->ibuf,
+			CIPHER_IV_LENGTH_AES_CBC);
+	ut_params->op->iv.phys_addr = rte_pktmbuf_mtophys(ut_params->ibuf);
+	ut_params->op->iv.length = CIPHER_IV_LENGTH_AES_CBC;
+
+	rte_memcpy(ut_params->op->iv.data, aes_cbc_iv, CIPHER_IV_LENGTH_AES_CBC);
+
+	ut_params->op->data.to_cipher.offset = CIPHER_IV_LENGTH_AES_CBC;
+	ut_params->op->data.to_cipher.length = QUOTE_512_BYTES;
+	ut_params->op->data.to_hash.offset = CIPHER_IV_LENGTH_AES_CBC;
+	ut_params->op->data.to_hash.length = QUOTE_512_BYTES;
+
+	rte_pktmbuf_attach_crypto_op(ut_params->ibuf, ut_params->op);
+
+	/* Process crypto operation */
+	ut_params->obuf = process_crypto_request(ts_params->valid_devs[0],
+			ut_params->ibuf);
+	TEST_ASSERT_NOT_NULL(ut_params->obuf, "failed to retrieve obuf");
+
+	/* Validate obuf */
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			rte_pktmbuf_mtod(ut_params->obuf, uint8_t *) +
+			CIPHER_IV_LENGTH_AES_CBC,
+			catch_22_quote_2_512_bytes_AES_CBC_ciphertext,
+			QUOTE_512_BYTES,
+			"Ciphertext data not as expected");
+
+	TEST_ASSERT_BUFFERS_ARE_EQUAL(
+			rte_pktmbuf_mtod(ut_params->obuf, uint8_t *) +
+			CIPHER_IV_LENGTH_AES_CBC + QUOTE_512_BYTES,
+			catch_22_quote_2_512_bytes_AES_CBC_HMAC_SHA1_digest,
+			gbl_cryptodev_type == RTE_CRYPTODEV_AESNI_MB_PMD ?
+					TRUNCATED_DIGEST_BYTE_LENGTH_SHA1 :
+					DIGEST_BYTE_LENGTH_SHA1,
+			"Generated digest data not as expected");
+
+	free_testsuite_mbufs();
+	return TEST_SUCCESS;
+}
+
 static int
 test_AES_CBC_HMAC_SHA1_decrypt_digest_verify(void)
 {
@@ -542,22 +648,27 @@ test_AES_CBC_HMAC_SHA1_decrypt_digest_verify(void)
 			DIGEST_BYTE_LENGTH_SHA1);
 
 	/* Setup Cipher Parameters */
-	ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-	ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
-	ut_params->cipher_params.key.data = aes_cbc_key;
-	ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+	ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+	ut_params->cipher_xform.next = NULL;
+
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
+	ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+	ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
 
 	/* Setup HMAC Parameters */
-	ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
-	ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
-	ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA1;
-	ut_params->hash_params.auth_key.data = hmac_sha1_key;
-	ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA1;
+	ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+	ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+	ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
+	ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA1_HMAC;
+	ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA1;
+	ut_params->auth_xform.auth.key.data = hmac_sha1_key;
+	ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA1;
 
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-			&ut_params->cipher_params, &ut_params->hash_params,
-			RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER);
+			&ut_params->auth_xform);
 	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	/* Generate Crypto op data structure */
@@ -641,22 +752,27 @@ test_AES_CBC_HMAC_SHA256_encrypt_digest(void)
 	TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
 
 	/* Setup Cipher Parameters */
-	ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-	ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
-	ut_params->cipher_params.key.data = aes_cbc_key;
-	ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+	ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+	ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+	ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+	ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
 
 	/* Setup HMAC Parameters */
-	ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
-	ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
-	ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA256;
-	ut_params->hash_params.auth_key.data = hmac_sha256_key;
-	ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA256;
+	ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+	ut_params->auth_xform.next = NULL;
+
+	ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+	ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
+	ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA256;
+	ut_params->auth_xform.auth.key.data = hmac_sha256_key;
+	ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA256;
 
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-			&ut_params->cipher_params, &ut_params->hash_params,
-			RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH);
+			&ut_params->cipher_xform);
 	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	/* Generate Crypto op data structure */
@@ -731,22 +847,27 @@ test_AES_CBC_HMAC_SHA256_decrypt_digest_verify(void)
 			DIGEST_BYTE_LENGTH_SHA256);
 
 	/* Setup Cipher Parameters */
-	ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-	ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
-	ut_params->cipher_params.key.data = aes_cbc_key;
-	ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+	ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+	ut_params->cipher_xform.next = NULL;
+
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
+	ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+	ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
 
 	/* Setup HMAC Parameters */
-	ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
-	ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
-	ut_params->hash_params.auth_key.data = hmac_sha256_key;
-	ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA256;
-	ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA256;
+	ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+	ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+	ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
+	ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA256_HMAC;
+	ut_params->auth_xform.auth.key.data = hmac_sha256_key;
+	ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA256;
+	ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA256;
 
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-			&ut_params->cipher_params, &ut_params->hash_params,
-			RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER);
+			&ut_params->auth_xform);
 	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	/* Generate Crypto op data structure */
@@ -837,22 +958,27 @@ test_AES_CBC_HMAC_SHA512_encrypt_digest(void)
 	TEST_ASSERT_NOT_NULL(ut_params->digest, "no room to append digest");
 
 	/* Setup Cipher Parameters */
-	ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-	ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
-	ut_params->cipher_params.key.data = aes_cbc_key;
-	ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+	ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+	ut_params->cipher_xform.next = &ut_params->auth_xform;
+
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT;
+	ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+	ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
 
 	/* Setup HMAC Parameters */
-	ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
-	ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
-	ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA512;
-	ut_params->hash_params.auth_key.data = hmac_sha512_key;
-	ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA512;
+	ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+	ut_params->auth_xform.next = NULL;
+
+	ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE;
+	ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
+	ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA512;
+	ut_params->auth_xform.auth.key.data = hmac_sha512_key;
+	ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA512;
 
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-			&ut_params->cipher_params, &ut_params->hash_params,
-			RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH);
+			&ut_params->cipher_xform);
 
 	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
@@ -931,8 +1057,7 @@ test_AES_CBC_HMAC_SHA512_decrypt_digest_verify(void)
 
 	/* Create Crypto session*/
 	ut_params->sess = rte_cryptodev_session_create(ts_params->valid_devs[0],
-			&ut_params->cipher_params, &ut_params->hash_params,
-			RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER);
+			&ut_params->auth_xform);
 	TEST_ASSERT_NOT_NULL(ut_params->sess, "Session creation failed");
 
 	return test_AES_CBC_HMAC_SHA512_decrypt_perform(ut_params->sess,
@@ -944,17 +1069,23 @@ test_AES_CBC_HMAC_SHA512_decrypt_create_session_params(struct crypto_unittest_pa
 {
 
 	/* Setup Cipher Parameters */
-	ut_params->cipher_params.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
-	ut_params->cipher_params.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
-	ut_params->cipher_params.key.data = aes_cbc_key;
-	ut_params->cipher_params.key.length = CIPHER_KEY_LENGTH_AES_CBC;
+	ut_params->cipher_xform.type = RTE_CRYPTO_XFORM_CIPHER;
+	ut_params->cipher_xform.next = NULL;
+
+	ut_params->cipher_xform.cipher.algo = RTE_CRYPTO_SYM_CIPHER_AES_CBC;
+	ut_params->cipher_xform.cipher.op = RTE_CRYPTO_SYM_CIPHER_OP_DECRYPT;
+	ut_params->cipher_xform.cipher.key.data = aes_cbc_key;
+	ut_params->cipher_xform.cipher.key.length = CIPHER_KEY_LENGTH_AES_CBC;
 
 	/* Setup HMAC Parameters */
-	ut_params->hash_params.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
-	ut_params->hash_params.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
-	ut_params->hash_params.auth_key.data = hmac_sha512_key;
-	ut_params->hash_params.auth_key.length = HMAC_KEY_LENGTH_SHA512;
-	ut_params->hash_params.digest_length = DIGEST_BYTE_LENGTH_SHA512;
+	ut_params->auth_xform.type = RTE_CRYPTO_XFORM_AUTH;
+	ut_params->auth_xform.next = &ut_params->cipher_xform;
+
+	ut_params->auth_xform.auth.op = RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY;
+	ut_params->auth_xform.auth.algo = RTE_CRYPTO_SYM_HASH_SHA512_HMAC;
+	ut_params->auth_xform.auth.key.data = hmac_sha512_key;
+	ut_params->auth_xform.auth.key.length = HMAC_KEY_LENGTH_SHA512;
+	ut_params->auth_xform.auth.digest_length = DIGEST_BYTE_LENGTH_SHA512;
 	return TEST_SUCCESS;
 }
 
@@ -1047,6 +1178,11 @@ static struct unit_test_suite cryptodev_testsuite  = {
 		TEST_CASE_ST(ut_setup, ut_teardown, test_AES_CBC_HMAC_SHA512_encrypt_digest),
 		TEST_CASE_ST(ut_setup, ut_teardown, test_AES_CBC_HMAC_SHA512_decrypt_digest_verify),
 
+		TEST_CASE_ST(ut_setup, ut_teardown, test_AES_CBC_HMAC_AES_XCBC_encrypt_digest),
+		TEST_CASE_ST(ut_setup, ut_teardown, test_AES_CBC_HMAC_AES_XCBC_decrypt_digest_verify),
+
+		TEST_CASE_ST(ut_setup, ut_teardown, test_AES_CBC_HMAC_SHA1_encrypt_digest_sessionless),
+
 		TEST_CASES_END() /**< NULL terminate unit test array */
 	}
 };
diff --git a/drivers/crypto/aesni_mb/aesni_mb_ops.h b/drivers/crypto/aesni_mb/aesni_mb_ops.h
index ab96990..1188278 100644
--- a/drivers/crypto/aesni_mb/aesni_mb_ops.h
+++ b/drivers/crypto/aesni_mb/aesni_mb_ops.h
@@ -59,7 +59,7 @@ typedef void (*aes_keyexp_128_t)(void *key, void *enc_exp_keys, void *dec_exp_ke
 typedef void (*aes_keyexp_192_t)(void *key, void *enc_exp_keys, void *dec_exp_keys);
 typedef void (*aes_keyexp_256_t)(void *key, void *enc_exp_keys, void *dec_exp_keys);
 
-typedef void (*aes_xcbc_expand_key_t)(void *key, void *k1_exp, void *k2, void *k3);
+typedef void (*aes_xcbc_expand_key_t)(void *key, void *exp_k1, void *k2, void *k3);
 
 typedef void (*aesni_gcm_t)(gcm_data *my_ctx_data, u8 *out, const u8 *in,
 		u64 plaintext_len, u8 *iv, const u8 *aad, u64 aad_len,
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
index 65a3731..506754e 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c
@@ -104,31 +104,101 @@ calculate_auth_precomputes(hash_one_block_t one_block_hash,
 	memset(opad_buf, 0, blocksize);
 }
 
-int
-aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
+static int
+aesni_mb_get_chain_order(const struct rte_crypto_xform *xform)
+{
+	/* multi-buffer only supports HASH_CIPHER or CIPHER_HASH chained
+	 * operations, all other options are invalid, so we must have exactly
+	 * 2 xform structs chained together */
+	if (xform->next == NULL || xform->next->next != NULL)
+		return -1;
+
+	if (xform->type == RTE_CRYPTO_XFORM_AUTH &&
+			xform->next->type == RTE_CRYPTO_XFORM_CIPHER)
+		return HASH_CIPHER;
+
+	if (xform->type == RTE_CRYPTO_XFORM_CIPHER &&
+				xform->next->type == RTE_CRYPTO_XFORM_AUTH)
+		return CIPHER_HASH;
+
+	return -1;
+}
+
+static int
+aesni_mb_set_session_auth_parameters(const struct aesni_mb_ops *mb_ops,
 		struct aesni_mb_session *sess,
-		struct rte_crypto_cipher_params *cipher_params,
-		struct rte_crypto_hash_params *auth_params,
-		enum rte_crypto_operation_chain op_chain)
+		const struct rte_crypto_xform *xform)
 {
-	aes_keyexp_t aes_keyexp_fn;
 	hash_one_block_t hash_oneblock_fn;
 
-	/* Select Crypto operation - hash then cipher / cipher then hash */
-	switch (op_chain) {
-	case RTE_CRYPTO_SYM_OPCHAIN_HASH_CIPHER:
-		sess->chain_order = HASH_CIPHER;
+	if (xform->type != RTE_CRYPTO_XFORM_AUTH) {
+		MB_LOG_ERR("Crypto xform struct not of type auth");
+		return -1;
+	}
+
+	/* Set Authentication Parameters */
+	if (xform->auth.algo == RTE_CRYPTO_SYM_HASH_AES_XCBC_MAC) {
+		sess->auth.algo = AES_XCBC;
+		(*mb_ops->aux.keyexp.aes_xcbc)(xform->auth.key.data,
+				sess->auth.xcbc.k1_expanded,
+				sess->auth.xcbc.k2, sess->auth.xcbc.k3);
+		return 0;
+	}
+
+	switch (xform->auth.algo) {
+	case RTE_CRYPTO_SYM_HASH_MD5_HMAC:
+		sess->auth.algo = MD5;
+		hash_oneblock_fn = mb_ops->aux.one_block.md5;
 		break;
-	case RTE_CRYPTO_SYM_OPCHAIN_CIPHER_HASH:
-		sess->chain_order = CIPHER_HASH;
+	case RTE_CRYPTO_SYM_HASH_SHA1_HMAC:
+		sess->auth.algo = SHA1;
+		hash_oneblock_fn = mb_ops->aux.one_block.sha1;
+		break;
+	case RTE_CRYPTO_SYM_HASH_SHA224_HMAC:
+		sess->auth.algo = SHA_224;
+		hash_oneblock_fn = mb_ops->aux.one_block.sha224;
+		break;
+	case RTE_CRYPTO_SYM_HASH_SHA256_HMAC:
+		sess->auth.algo = SHA_256;
+		hash_oneblock_fn = mb_ops->aux.one_block.sha256;
+		break;
+	case RTE_CRYPTO_SYM_HASH_SHA384_HMAC:
+		sess->auth.algo = SHA_384;
+		hash_oneblock_fn = mb_ops->aux.one_block.sha384;
+		break;
+	case RTE_CRYPTO_SYM_HASH_SHA512_HMAC:
+		sess->auth.algo = SHA_512;
+		hash_oneblock_fn = mb_ops->aux.one_block.sha512;
 		break;
 	default:
-		printf("unsupported operation chain order parameter");
+		MB_LOG_ERR("Unsupported authentication algorithm selection");
+		return -1;
+	}
+
+	/* Calculate Authentication precomputes */
+	calculate_auth_precomputes(hash_oneblock_fn,
+			sess->auth.pads.inner, sess->auth.pads.outer,
+			xform->auth.key.data,
+			xform->auth.key.length,
+			get_auth_algo_blocksize(sess->auth.algo));
+
+	return 0;
+}
+
+static int
+aesni_mb_set_session_cipher_parameters(const struct aesni_mb_ops *mb_ops,
+		struct aesni_mb_session *sess,
+		const struct rte_crypto_xform *xform)
+{
+	aes_keyexp_t aes_keyexp_fn;
+
+	if (xform->type != RTE_CRYPTO_XFORM_CIPHER) {
+		MB_LOG_ERR("Crypto xform struct not of type cipher");
 		return -1;
 	}
 
 	/* Select cipher direction */
-	switch (cipher_params->op) {
+	switch (xform->cipher.op) {
 	case RTE_CRYPTO_SYM_CIPHER_OP_ENCRYPT:
 		sess->cipher.direction = ENCRYPT;
 		break;
@@ -136,22 +206,22 @@ aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
 		sess->cipher.direction = DECRYPT;
 		break;
 	default:
-		printf("unsupported cipher operation parameter");
+		MB_LOG_ERR("Unsupported cipher operation parameter");
 		return -1;
 	}
 
 	/* Select cipher mode */
-	switch (cipher_params->algo) {
+	switch (xform->cipher.algo) {
 	case RTE_CRYPTO_SYM_CIPHER_AES_CBC:
 		sess->cipher.mode = CBC;
 		break;
 	default:
-		printf("unsupported cipher mode parameter");
+		MB_LOG_ERR("Unsupported cipher mode parameter");
 		return -1;
 	}
 
 	/* Check key length and choose key expansion function */
-	switch (cipher_params->key.length) {
+	switch (xform->cipher.key.length) {
 	case AES_128_BYTES:
 		sess->cipher.key_length_in_bytes = AES_128_BYTES;
 		aes_keyexp_fn = mb_ops->aux.keyexp.aes128;
@@ -165,53 +235,53 @@ aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
 		aes_keyexp_fn = mb_ops->aux.keyexp.aes256;
 		break;
 	default:
-		printf("unsupported cipher key length");
+		MB_LOG_ERR("Unsupported cipher key length");
 		return -1;
 	}
 
 	/* Expanded cipher keys */
-	(*aes_keyexp_fn)(cipher_params->key.data,
+	(*aes_keyexp_fn)(xform->cipher.key.data,
 			sess->cipher.expanded_aes_keys.encode,
 			sess->cipher.expanded_aes_keys.decode);
 
-	/* Set Authentication Parameters */
-	switch (auth_params->algo) {
-	case RTE_CRYPTO_SYM_HASH_MD5_HMAC:
-		sess->auth.algo = MD5;
-		hash_oneblock_fn = mb_ops->aux.one_block.md5;
-		break;
-	case RTE_CRYPTO_SYM_HASH_SHA1_HMAC:
-		sess->auth.algo = SHA1;
-		hash_oneblock_fn = mb_ops->aux.one_block.sha1;
-		break;
-	case RTE_CRYPTO_SYM_HASH_SHA224_HMAC:
-		sess->auth.algo = SHA_224;
-		hash_oneblock_fn = mb_ops->aux.one_block.sha224;
-		break;
-	case RTE_CRYPTO_SYM_HASH_SHA256_HMAC:
-		sess->auth.algo = SHA_256;
-		hash_oneblock_fn = mb_ops->aux.one_block.sha256;
-		break;
-	case RTE_CRYPTO_SYM_HASH_SHA384_HMAC:
-		sess->auth.algo = SHA_384;
-		hash_oneblock_fn = mb_ops->aux.one_block.sha384;
+	return 0;
+}
+
+
+int
+aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
+		struct aesni_mb_session *sess,
+		const struct rte_crypto_xform *xform)
+{
+	const struct rte_crypto_xform *auth_xform = NULL;
+	const struct rte_crypto_xform *cipher_xform = NULL;
+
+	/* Select Crypto operation - hash then cipher / cipher then hash */
+	switch (aesni_mb_get_chain_order(xform)) {
+	case HASH_CIPHER:
+		sess->chain_order = HASH_CIPHER;
+		auth_xform = xform;
+		cipher_xform = xform->next;
 		break;
-	case RTE_CRYPTO_SYM_HASH_SHA512_HMAC:
-		sess->auth.algo = SHA_512;
-		hash_oneblock_fn = mb_ops->aux.one_block.sha512;
+	case CIPHER_HASH:
+		sess->chain_order = CIPHER_HASH;
+		auth_xform = xform->next;
+		cipher_xform = xform;
 		break;
 	default:
-		printf("unsupported authentication algorithm selection");
+		MB_LOG_ERR("Unsupported operation chain order parameter");
 		return -1;
 	}
 
-	/* Calculate Authentication precomputes */
-	calculate_auth_precomputes(hash_oneblock_fn,
-			sess->auth.pads.inner, sess->auth.pads.outer,
-			auth_params->auth_key.data,
-			auth_params->auth_key.length,
-			get_auth_algo_blocksize(sess->auth.algo));
+	if (aesni_mb_set_session_auth_parameters(mb_ops, sess, auth_xform)) {
+		MB_LOG_ERR("Invalid/unsupported authentication parameters");
+		return -1;
+	}
 
+	if (aesni_mb_set_session_cipher_parameters(mb_ops, sess, cipher_xform)) {
+		MB_LOG_ERR("Invalid/unsupported cipher parameters");
+		return -1;
+	}
 	return 0;
 }
 
@@ -239,9 +309,7 @@ process_crypto_op(struct aesni_mb_qp *qp, JOB_AES_HMAC *job, struct rte_mbuf *m)
 			return NULL;
 
 		if (unlikely(aesni_mb_set_session_parameters(qp->mb_ops,
-				sess, &c_op->op_params.cipher,
-				&c_op->op_params.hash,
-				c_op->op_params.opchain) != 0))
+				sess, c_op->xform) != 0))
 			return NULL;
 	} else {
 		sess = (struct aesni_mb_session *)c_op->session;
@@ -250,7 +318,6 @@ process_crypto_op(struct aesni_mb_qp *qp, JOB_AES_HMAC *job, struct rte_mbuf *m)
 	/* Set crypto operation */
 	job->chain_order = sess->chain_order;
 
-
 	/* Set cipher parameters */
 	job->cipher_direction = sess->cipher.direction;
 	job->cipher_mode = sess->cipher.mode;
@@ -262,9 +329,14 @@ process_crypto_op(struct aesni_mb_qp *qp, JOB_AES_HMAC *job, struct rte_mbuf *m)
 
 	/* Set authentication parameters */
 	job->hash_alg = sess->auth.algo;
-	job->hashed_auth_key_xor_ipad = sess->auth.pads.inner;
-	job->hashed_auth_key_xor_opad = sess->auth.pads.outer;
-
+	if (job->hash_alg == AES_XCBC) {
+		job->_k1_expanded = sess->auth.xcbc.k1_expanded;
+		job->_k2 = sess->auth.xcbc.k2;
+		job->_k3 = sess->auth.xcbc.k3;
+	} else {
+		job->hashed_auth_key_xor_ipad = sess->auth.pads.inner;
+		job->hashed_auth_key_xor_opad = sess->auth.pads.outer;
+	}
 
 	/* Mutable crypto operation parameters */
 
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
index fb57e7b..d9cdd5b 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c
@@ -286,9 +286,7 @@ aesni_mb_pmd_session_mempool_create(struct rte_cryptodev *dev,
 
 static struct rte_cryptodev_session *
 aesni_mb_pmd_create_session(struct rte_cryptodev *dev,
-		struct rte_crypto_cipher_params *cipher_setup_data,
-		struct rte_crypto_hash_params *hash_setup_data,
-		enum rte_crypto_operation_chain op_chain)
+		struct rte_crypto_xform *xform)
 {
 	struct aesni_mb_private *internals = dev->data->dev_private;
 	struct aesni_mb_session *sess  =
@@ -299,9 +297,9 @@ aesni_mb_pmd_create_session(struct rte_cryptodev *dev,
 		return NULL;
 	}
 
-	if (aesni_mb_set_session_parameters(
-			&job_ops[internals->vector_mode], sess,
-			cipher_setup_data, hash_setup_data, op_chain) != 0) {
+	if (aesni_mb_set_session_parameters(&job_ops[internals->vector_mode],
+			sess, xform) != 0) {
+		MB_LOG_ERR("failed configure session parameters");
 		aesni_mb_free_session(internals->sess_mp, sess);
 	}
 
diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
index c5c4a86..abfec16 100644
--- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
+++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h
@@ -178,13 +178,21 @@ struct aesni_mb_session {
 
 	struct {
 		JOB_HASH_ALG algo;	/** Authentication Algorithm */
-
-		struct {
-			uint8_t inner[128] __rte_align(16);	/**< inner pad */
-			uint8_t outer[128] __rte_align(16);	/**< outer pad */
-		} pads;
-		/** HMAC Authentication pads - allocating space for the maximum
-		 * pad size supported which is 128 bytes for SHA512 */
+		union {
+			struct {
+				uint8_t inner[128] __rte_align(16);	/**< inner pad */
+				uint8_t outer[128] __rte_align(16);	/**< outer pad */
+			} pads;
+			/** HMAC Authentication pads - allocating space for the maximum
+			 * pad size supported which is 128 bytes for SHA512 */
+
+			struct {
+			    uint32_t k1_expanded[44] __rte_align(16);	/* k1 (expanded key). */
+			    uint8_t k2[16] __rte_align(16);		/* k2. */
+			    uint8_t k3[16] __rte_align(16);		/* k3. */
+			} xcbc;
+			/** Expanded XCBC authentication keys */
+		};
 
 		uint8_t digest[64] __rte_align(16);
 	} auth;	/**< Authentication Parameters */
@@ -212,10 +220,10 @@ aesni_mb_free_session(struct rte_mempool *mempool,
 extern int
 aesni_mb_set_session_parameters(const struct aesni_mb_ops *mb_ops,
 		struct aesni_mb_session *sess,
-		struct rte_crypto_cipher_params *cparams,
-		struct rte_crypto_hash_params *aparams,
-		enum rte_crypto_operation_chain op_chain);
+		const struct rte_crypto_xform *xform);
+
 
+/** device specific operations function pointer structure */
 extern struct rte_cryptodev_ops *rte_aesni_mb_pmd_ops;
 
 
diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h
index b776609..2160003 100644
--- a/lib/librte_cryptodev/rte_crypto.h
+++ b/lib/librte_cryptodev/rte_crypto.h
@@ -121,8 +121,8 @@ enum rte_crypto_cipher_algorithm {
 	RTE_CRYPTO_SYM_CIPHER_AES_F8,
 	/**< AES algorithm in F8 mode */
 	RTE_CRYPTO_SYM_CIPHER_AES_GCM,
-	/**< AES algorithm in CGM mode. When this cipher algorithm is used the
-	 * *RTE_CRYPTO_SYM_CIPHER_AES_GCM* element of the
+	/**< AES algorithm in GCM mode. When this cipher algorithm is used the
+	 * *RTE_CRYPTO_SYM_HASH_AES_GCM* element of the
 	 * *rte_crypto_hash_algorithm* enum MUST be used to set up the related
 	 * *rte_crypto_hash_setup_data* structure in the session context or in
 	 * the op_params of the crypto operation structure in the case of a
@@ -164,7 +164,7 @@ struct rte_crypto_key {
  * This structure contains data relating to Cipher (Encryption and Decryption)
  *  use to create a session.
  */
-struct rte_crypto_cipher_params {
+struct rte_crypto_cipher_xform {
 	enum rte_crypto_cipher_operation op;
 	/**< This parameter determines if the cipher operation is an encrypt or
 	 * a decrypt operation. For the RC4 algorithm and the F8/CTR modes,
@@ -203,8 +203,8 @@ struct rte_crypto_cipher_params {
 	 **/
 };
 
-/** Symmetric Hash / Authentication Algorithms */
-enum rte_crypto_hash_algorithm {
+/** Symmetric Authentication / Hash Algorithms */
+enum rte_crypto_auth_algorithm {
 	RTE_CRYPTO_SYM_HASH_NONE = 0,
 	/**< No hash algorithm. */
 
@@ -276,27 +276,24 @@ enum rte_crypto_hash_algorithm {
 	/**< ZUC algorithm in EIA3 mode */
 };
 
-/** Symmetric Hash Operations */
-enum rte_crypto_hash_operation {
+/** Symmetric Authentication / Hash Operations */
+enum rte_crypto_auth_operation {
 	RTE_CRYPTO_SYM_HASH_OP_DIGEST_VERIFY,	/**< Verify digest */
 	RTE_CRYPTO_SYM_HASH_OP_DIGEST_GENERATE	/**< Generate digest */
 };
 
 /**
- * Hash Setup Data.
+ * Authentication / Hash transform data.
  *
- * This structure contains data relating to a hash session. The fields hash_algorithm, hash_mode and digest_result_len are common to all
- *      three hash modes and MUST be set for each mode.
- *
- *****************************************************************************/
-struct rte_crypto_hash_params {
-	enum rte_crypto_hash_operation op;
-	/* hash operation type */
-	enum rte_crypto_hash_algorithm algo;
-	/* hashing algorithm selection */
-
-	struct rte_crypto_key auth_key;
-	/**< Authentication key data.
+ * This structure contains data relating to an authentication/hash crypto
+ * transforms. The fields op, algo and digest_length are common to all
+ * authentication transforms and MUST be set.
+ */
+struct rte_crypto_auth_xform {
+	enum rte_crypto_auth_operation op;	/**< Authentication operation type */
+	enum rte_crypto_auth_algorithm algo;	/**< Authentication algorithm selection */
+
+	struct rte_crypto_key key;		/**< Authentication key data.
 	 * The authentication key length MUST be less than or equal to the
 	 * block size of the algorithm. It is the callers responsibility to
 	 * ensure that the key length is compliant with the standard being used
@@ -346,9 +343,36 @@ struct rte_crypto_hash_params {
 };
 
 /**
+ * Defines the crypto transforms available
+ */
+enum rte_crypto_xform_type {
+	RTE_CRYPTO_XFORM_NOT_SPECIFIED = 0,
+	RTE_CRYPTO_XFORM_AUTH,
+	RTE_CRYPTO_XFORM_CIPHER
+};
+
+/**
+ * Crypto transform structure.
+ *
+ * This is used to specify the crypto transforms required, multiple transforms
+ * can be chained together to specify a chain transforms such as authentication
+ * then cipher, or cipher then authentication. Each transform structure can
+ * hold a single transform, the type field is used to specify which transform
+ * is contained within the union */
+struct rte_crypto_xform {
+	struct rte_crypto_xform *next; /**< next xform in chain */
+
+	enum rte_crypto_xform_type type; /**< xform type */
+	union {
+		struct rte_crypto_auth_xform auth;	/**< Authentication / hash xform */
+		struct rte_crypto_cipher_xform cipher;	/**< Cipher xform */
+	};
+};
+
+/**
  * Crypto operation session type. This is used to specify whether a crypto
  * operation has session structure attached for immutable parameters or if all
- * operation information is include in the operation data structure op_params.
+ * operation information is included in the operation data structure.
  */
 enum rte_crypto_op_sess_type {
 	RTE_CRYPTO_OP_WITH_SESSION,	/**< Session based crypto operation */
@@ -370,11 +394,7 @@ struct rte_crypto_op_data {
 	union {
 		struct rte_cryptodev_session *session;
 		/**< Handle for the initialised session context */
-		struct {
-			struct rte_crypto_cipher_params cipher;
-			struct rte_crypto_hash_params hash;
-			enum rte_crypto_operation_chain opchain;
-		} op_params;
+		struct rte_crypto_xform *xform;
 		/**< Session-less API crypto operation parameters */
 	};
 
@@ -570,6 +590,20 @@ struct rte_crypto_op_data {
 	struct rte_mempool *pool;	/**< mempool used to allocate crypto op */
 };
 
+
+/**
+ * Crypto Operation Pool Private Data Structure
+ */
+struct crypto_op_pool_private {
+	unsigned max_nb_xforms;
+};
+
+
+extern struct rte_mempool *
+rte_crypto_op_pool_create(const char *name, unsigned nb_ops,
+		unsigned cache_size, unsigned nb_xforms, int socket_id);
+
+
 /**
  * Reset the fields of a packet mbuf to their default values.
  *
@@ -579,9 +613,8 @@ struct rte_crypto_op_data {
  *   The packet mbuf to be resetted.
  */
 static inline void
-rte_crypto_op_reset(struct rte_crypto_op_data *op)
+__rte_crypto_op_reset(struct rte_crypto_op_data *op)
 {
-
 	op->type = RTE_CRYPTO_OP_SESSIONLESS;
 }
 
@@ -597,13 +630,10 @@ __rte_crypto_op_raw_alloc(struct rte_mempool *mp)
 }
 
 /**
- * Create an crypto operation structure which is used to define the crypto
- * operation processing which is to be done on a packet.
+ * Allocate a crypto operation structure from an crypto pool which is used 
+ * to define the crypto operation processing which is to be done on a packet.
  *
- * @param	dev_id		Device identifier
- * @param	m_src		Source mbuf of data for processing.
- * @param	m_dst		Destination mbuf for processed data. Can be NULL
- *				if crypto operation is done in place.
+ * @param	mp		crypto operation pool
  */
 static inline struct rte_crypto_op_data *
 rte_crypto_op_alloc(struct rte_mempool *mp)
@@ -611,7 +641,41 @@ rte_crypto_op_alloc(struct rte_mempool *mp)
 	struct rte_crypto_op_data *op;
 
 	if ((op = __rte_crypto_op_raw_alloc(mp)) != NULL)
-		rte_crypto_op_reset(op);
+		__rte_crypto_op_reset(op);
+	return op;
+}
+
+/**
+ * Allocate a sessionless crypto operation structure from an crypto pool which is used 
+ * to define the crypto operation processing which is to be done on a packet. The number of
+ * xforms supported is calculated from the mempools private data is used to check whether
+ * enough extra data has been allocated for each xform requested after the operation structure
+ *
+ * @param	mp			crypto operation pool
+ * @param	nb_xforms	number of crypto transforms to be used in operation
+ */
+static inline struct rte_crypto_op_data *
+rte_crypto_op_alloc_sessionless(struct rte_mempool *mp, unsigned nb_xforms)
+{
+	struct rte_crypto_op_data *op = NULL;
+	struct rte_crypto_xform *xform = NULL;
+	struct crypto_op_pool_private *priv_data =
+					(struct crypto_op_pool_private *)
+					rte_mempool_get_priv(mp);
+
+	if (nb_xforms > priv_data->max_nb_xforms && nb_xforms > 0)
+		return op;
+
+	if ((op = __rte_crypto_op_raw_alloc(mp)) != NULL) {
+		__rte_crypto_op_reset(op);
+
+		xform = op->xform = (struct rte_crypto_xform *)(op + 1);
+
+		do {
+			xform->type = RTE_CRYPTO_XFORM_NOT_SPECIFIED;
+			xform = xform->next = --nb_xforms > 0 ? xform + 1 : NULL;
+		} while (xform);
+	}
 	return op;
 }
 
@@ -629,10 +693,9 @@ rte_crypto_op_free(struct rte_crypto_op_data *op)
 	}
 }
 
-extern struct rte_mempool *
-rte_crypto_op_pool_create(const char *name, unsigned n, unsigned cache_size,
-		int socket_id);
-
+/**
+ * Attach a session to a crypto operation
+ */
 static inline void
 rte_crypto_op_attach_session(struct rte_crypto_op_data *op,
 		struct rte_cryptodev_session *sess)
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index a1797ce..7f2e5d1 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -101,13 +101,13 @@
 	} \
 } while (0)
 
-struct rte_cryptodev rte_crypto_devices[RTE_MAX_CRYPTODEVS];
+struct rte_cryptodev rte_crypto_devices[RTE_CRYPTO_MAX_DEVS];
 
 static struct rte_cryptodev_global cryptodev_globals = {
 		.devs			= &rte_crypto_devices[0],
 		.data			= NULL,
 		.nb_devs		= 0,
-		.max_devs		= RTE_MAX_CRYPTODEVS
+		.max_devs		= RTE_CRYPTO_MAX_DEVS
 };
 
 struct rte_cryptodev_global *rte_cryptodev_globals = &cryptodev_globals;
@@ -164,11 +164,11 @@ rte_cryptodev_find_free_device_index(void)
 {
 	uint8_t dev_id;
 
-	for (dev_id = 0; dev_id < RTE_MAX_CRYPTODEVS; dev_id++) {
+	for (dev_id = 0; dev_id < RTE_CRYPTO_MAX_DEVS; dev_id++) {
 		if (rte_crypto_devices[dev_id].attached == RTE_CRYPTODEV_DETACHED)
 			return dev_id;
 	}
-	return RTE_MAX_CRYPTODEVS;
+	return RTE_CRYPTO_MAX_DEVS;
 }
 
 struct rte_cryptodev *
@@ -178,7 +178,7 @@ rte_cryptodev_pmd_allocate(const char *name, enum pmd_type type, int socket_id)
 	struct rte_cryptodev *cryptodev;
 
 	dev_id = rte_cryptodev_find_free_device_index();
-	if (dev_id == RTE_MAX_CRYPTODEVS) {
+	if (dev_id == RTE_CRYPTO_MAX_DEVS) {
 		CDEV_LOG_ERR("Reached maximum number of crypto devices");
 		return NULL;
 	}
@@ -868,9 +868,7 @@ rte_cryptodev_pmd_callback_process(struct rte_cryptodev *dev,
 
 struct rte_cryptodev_session *
 rte_cryptodev_session_create(uint8_t dev_id,
-		struct rte_crypto_cipher_params *cipher_setup_data,
-		struct rte_crypto_hash_params *hash_setup_data,
-		enum rte_crypto_operation_chain op_chain)
+		struct rte_crypto_xform *xform)
 {
 	struct rte_cryptodev *dev;
 
@@ -879,10 +877,10 @@ rte_cryptodev_session_create(uint8_t dev_id,
 		return NULL;
 	}
 
-	 dev = &rte_crypto_devices[dev_id];
+	dev = &rte_crypto_devices[dev_id];
 
-	 return dev->dev_ops->session_create(dev, cipher_setup_data,
-			 hash_setup_data, op_chain);
+	FUNC_PTR_OR_ERR_RET(*dev->dev_ops->session_create, NULL);
+	return dev->dev_ops->session_create(dev, xform);
 }
 
 void
@@ -896,9 +894,10 @@ rte_cryptodev_session_free(uint8_t dev_id,
 		return;
 	}
 
-	 dev = &rte_crypto_devices[dev_id];
+	dev = &rte_crypto_devices[dev_id];
 
-	 dev->dev_ops->session_destroy(dev, session);
+	FUNC_PTR_OR_RET(*dev->dev_ops->session_destroy);
+	dev->dev_ops->session_destroy(dev, session);
 }
 
 
@@ -922,15 +921,24 @@ rte_crypto_op_pool_init(__rte_unused struct rte_mempool *mp,
 }
 
 struct rte_mempool *
-rte_crypto_op_pool_create(const char *name, unsigned n, unsigned cache_size,
-		int socket_id)
+rte_crypto_op_pool_create(const char *name, unsigned size,
+		unsigned cache_size, unsigned nb_xforms, int socket_id)
 {
+	struct crypto_op_pool_private *priv_data = NULL;
+
+	unsigned elt_size = sizeof(struct rte_crypto_op_data) +
+			(sizeof(struct rte_crypto_xform) * nb_xforms);
+
 	/* lookup mempool in case already allocated */
 	struct rte_mempool *mp = rte_mempool_lookup(name);
 	if (mp != NULL) {
-		if (mp->elt_size != sizeof(struct rte_crypto_op_data) ||
+		priv_data = (struct crypto_op_pool_private *)
+				rte_mempool_get_priv(mp);
+
+		if (priv_data->max_nb_xforms <  nb_xforms ||
+				mp->elt_size != elt_size ||
 				mp->cache_size < cache_size ||
-				mp->size < n) {
+				mp->size < size) {
 			mp = NULL;
 			CDEV_LOG_ERR("%s mempool already exists with "
 					"incompatible initialisation parameters",
@@ -941,11 +949,12 @@ rte_crypto_op_pool_create(const char *name, unsigned n, unsigned cache_size,
 		return mp;
 	}
 
-	mp = rte_mempool_create(name,	/* mempool name */
-			n,			/* number of elements*/
-			sizeof(struct rte_crypto_op_data),/* element size*/
+	mp = rte_mempool_create(
+			name,				/* mempool name */
+			size,				/* number of elements*/
+			elt_size,			/* element size*/
 			cache_size,			/* Cache size*/
-			0,				/* private data size */
+			sizeof(struct crypto_op_pool_private),	/* private data size */
 			rte_crypto_op_pool_init,	/* pool initialisation constructor */
 			NULL,				/* pool initialisation constructor argument */
 			rte_crypto_op_init,		/* obj constructor */
@@ -958,6 +967,9 @@ rte_crypto_op_pool_create(const char *name, unsigned n, unsigned cache_size,
 		return NULL;
 	}
 
+	priv_data = (struct crypto_op_pool_private *)rte_mempool_get_priv(mp);
+
+	priv_data->max_nb_xforms = nb_xforms;
 
 	CDEV_LOG_DEBUG("%s mempool created!", name);
 	return mp;
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index d7694ad..d2d34f2 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -501,31 +501,23 @@ rte_cryptodev_enqueue_burst(uint8_t dev_id, uint16_t qp_id,
  * parameters of symmetric cryptographic operation.
  * To perform the operation the rte_cryptodev_enqueue_burst function is
  * used.  Each mbuf should contain a reference to the session
- * pointer returned from this function.
- * Memory to contain the session information is allocated by the
- * implementation.
- * An upper limit on the number of session that many be created is
- * defined by a build configuration constant.
+ * pointer returned from this function contained within it's crypto_op if a
+ * session-based operation is being provisioned. Memory to contain the session
+ * information is allocated from within mempool managed by the cryptodev.
+ *
  * The rte_cryptodev_session_free must be called to free allocated
- * memory when the session information is no longer needed.
+ * memory when the session is no longer required.
  *
- * @param	dev_id			The device identifier.
- * @param	cipher_setup_data	The parameters associated with the
- *					cipher operation. This may be NULL.
- * @param	hash_setup_data		The parameters associated with the hash
- *					operation. This may be NULL.
- * @param	op_chain		Specifies the crypto operation chaining,
- *					cipher and/or hash and the order in
- *					which they are performed.
+ * @param	dev_id		The device identifier.
+ * @param	xform		Crypto transform chain.
+
  *
  * @return
  *  Pointer to the created session or NULL
  */
 extern struct rte_cryptodev_session *
 rte_cryptodev_session_create(uint8_t dev_id,
-		struct rte_crypto_cipher_params *cipher_setup_data,
-		struct rte_crypto_hash_params *hash_setup_data,
-		enum rte_crypto_operation_chain op_chain);
+		struct rte_crypto_xform *xform);
 
 
 /**
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index e6fdd1c..aa2f6c4 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -453,10 +453,8 @@ typedef int (*cryptodev_create_session_pool_t)(
 /**
  * Create a Crypto session on a device.
  *
- * @param	dev			Crypto device pointer
- * @param	cipher_setup_data	Cipher operation parameters
- * @param	hash_setup_data		Hash operation parameters
- * @param	op_chain		Operation chaining
+ * @param	dev		Crypto device pointer
+ * @param	xform		Single or chain of crypto xforms
  *
  * @return
  *  - Returns cryptodev session structure on success.
@@ -464,9 +462,7 @@ typedef int (*cryptodev_create_session_pool_t)(
  * */
 typedef struct rte_cryptodev_session * (*cryptodev_create_session_t)(
 		struct rte_cryptodev *dev,
-		struct rte_crypto_cipher_params *cipher_setup_data,
-		struct rte_crypto_hash_params *hash_setup_data,
-		enum rte_crypto_operation_chain op_chain);
+		struct rte_crypto_xform *xform);
 
 /**
  * Free Crypto session.
-- 
2.4.3



More information about the dev mailing list