[dpdk-dev] [PATCH v2] crypto/openssl: add DES DOCSIS BPI support

Pablo de Lara pablo.de.lara.guarch at intel.com
Thu Feb 23 16:21:32 CET 2017


Adds support in OpenSSL for algorithm following the DOCSIS
specification, which combines DES-CBC for full DES blocks (8 bytes)
and DES-CFB for last runt block (less than 8 bytes).

Signed-off-by: Pablo de Lara <pablo.de.lara.guarch at intel.com>
---
This patch depends on patch http://dpdk.org/dev/patchwork/patch/20691/.

Changes in v2: 
- Added patch dependency note
- Fixed the commit message

 app/test/test_cryptodev.c                        |  18 +++
 app/test/test_cryptodev_blockcipher.c            |   5 +
 app/test/test_cryptodev_blockcipher.h            |   3 +-
 app/test/test_cryptodev_des_test_vectors.h       | 137 +++++++++++++++++++++++
 doc/guides/cryptodevs/openssl.rst                |   1 +
 doc/guides/rel_notes/release_17_05.rst           |   6 +
 drivers/crypto/openssl/rte_openssl_pmd.c         | 114 ++++++++++++++++++-
 drivers/crypto/openssl/rte_openssl_pmd_ops.c     |  20 ++++
 drivers/crypto/openssl/rte_openssl_pmd_private.h |   1 +
 9 files changed, 303 insertions(+), 2 deletions(-)

diff --git a/app/test/test_cryptodev.c b/app/test/test_cryptodev.c
index 357a92e..f49ae6a 100644
--- a/app/test/test_cryptodev.c
+++ b/app/test/test_cryptodev.c
@@ -4333,6 +4333,22 @@ test_DES_cipheronly_qat_all(void)
 }
 
 static int
+test_DES_docsis_openssl_all(void)
+{
+	struct crypto_testsuite_params *ts_params = &testsuite_params;
+	int status;
+
+	status = test_blockcipher_all_tests(ts_params->mbuf_pool,
+		ts_params->op_mpool, ts_params->valid_devs[0],
+		RTE_CRYPTODEV_OPENSSL_PMD,
+		BLKCIPHER_DES_DOCSIS_TYPE);
+
+	TEST_ASSERT_EQUAL(status, 0, "Test failed");
+
+	return TEST_SUCCESS;
+}
+
+static int
 test_3DES_cipheronly_qat_all(void)
 {
 	struct crypto_testsuite_params *ts_params = &testsuite_params;
@@ -7718,6 +7734,8 @@ static struct unit_test_suite cryptodev_openssl_testsuite  = {
 		TEST_CASE_ST(ut_setup, ut_teardown,
 				test_3DES_cipheronly_openssl_all),
 		TEST_CASE_ST(ut_setup, ut_teardown,
+				test_DES_docsis_openssl_all),
+		TEST_CASE_ST(ut_setup, ut_teardown,
 				test_authonly_openssl_all),
 
 		/** AES GCM Authenticated Encryption */
diff --git a/app/test/test_cryptodev_blockcipher.c b/app/test/test_cryptodev_blockcipher.c
index da87368..1394035 100644
--- a/app/test/test_cryptodev_blockcipher.c
+++ b/app/test/test_cryptodev_blockcipher.c
@@ -628,6 +628,11 @@ test_blockcipher_all_tests(struct rte_mempool *mbuf_pool,
 		sizeof(des_cipheronly_test_cases[0]);
 		tcs = des_cipheronly_test_cases;
 		break;
+	case BLKCIPHER_DES_DOCSIS_TYPE:
+		n_test_cases = sizeof(des_docsis_test_cases) /
+		sizeof(des_docsis_test_cases[0]);
+		tcs = des_docsis_test_cases;
+		break;
 	case BLKCIPHER_AUTHONLY_TYPE:
 		n_test_cases = sizeof(hash_test_cases) /
 		sizeof(hash_test_cases[0]);
diff --git a/app/test/test_cryptodev_blockcipher.h b/app/test/test_cryptodev_blockcipher.h
index 053aaa1..cccf05d 100644
--- a/app/test/test_cryptodev_blockcipher.h
+++ b/app/test/test_cryptodev_blockcipher.h
@@ -71,7 +71,8 @@ enum blockcipher_test_type {
 	BLKCIPHER_3DES_CHAIN_TYPE,	/* use triple_des_chain_test_cases[] */
 	BLKCIPHER_3DES_CIPHERONLY_TYPE,	/* triple_des_cipheronly_test_cases[] */
 	BLKCIPHER_AUTHONLY_TYPE,	/* use hash_test_cases[] */
-	BLKCIPHER_DES_CIPHERONLY_TYPE	/* use des_cipheronly_test_cases[] */
+	BLKCIPHER_DES_CIPHERONLY_TYPE,	/* use des_cipheronly_test_cases[] */
+	BLKCIPHER_DES_DOCSIS_TYPE	/* use des_docsis_test_cases[] */
 };
 
 struct blockcipher_test_case {
diff --git a/app/test/test_cryptodev_des_test_vectors.h b/app/test/test_cryptodev_des_test_vectors.h
index 388d87e..b29a49e 100644
--- a/app/test/test_cryptodev_des_test_vectors.h
+++ b/app/test/test_cryptodev_des_test_vectors.h
@@ -862,6 +862,143 @@ static const struct blockcipher_test_case des_cipheronly_test_cases[] = {
 
 };
 
+/* DES-DOCSIS-BPI test vectors */
+
+static const uint8_t plaintext_des_docsis_bpi_cfb[] = {
+	0x00, 0x01, 0x02, 0x88, 0xEE, 0x59, 0x7E
+};
+
+static const uint8_t ciphertext_des_docsis_bpi_cfb[] = {
+	0x17, 0x86, 0xA8, 0x03, 0xA0, 0x85, 0x75
+};
+
+static const uint8_t plaintext_des_docsis_bpi_cbc_cfb[] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x91,
+	0xD2, 0xD1, 0x9F
+};
+
+static const uint8_t ciphertext_des_docsis_bpi_cbc_cfb[] = {
+	0x0D, 0xDA, 0x5A, 0xCB, 0xD0, 0x5E, 0x55, 0x67,
+	0x51, 0x47, 0x46, 0x86, 0x8A, 0x71, 0xE5, 0x77,
+	0xEF, 0xAC, 0x88
+};
+
+/* Multiple of DES block size */
+static const struct blockcipher_test_data des_test_data_1 = {
+	.crypto_algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+	.cipher_key = {
+		.data = {
+			0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2
+		},
+		.len = 8
+	},
+	.iv = {
+		.data = {
+			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
+		},
+		.len = 8
+	},
+	.plaintext = {
+		.data = plaintext_des,
+		.len = 512
+	},
+	.ciphertext = {
+		.data = ciphertext512_des,
+		.len = 512
+	},
+};
+
+/* Less than DES block size */
+static const struct blockcipher_test_data des_test_data_2 = {
+	.crypto_algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+	.cipher_key = {
+		.data = {
+
+			0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+		},
+		.len = 8
+	},
+	.iv = {
+		.data = {
+			0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+		},
+		.len = 8
+	},
+	.plaintext = {
+		.data = plaintext_des_docsis_bpi_cfb,
+		.len = 7
+	},
+	.ciphertext = {
+		.data = ciphertext_des_docsis_bpi_cfb,
+		.len = 7
+	}
+};
+
+/* Not multiple of DES block size */
+static const struct blockcipher_test_data des_test_data_3 = {
+	.crypto_algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+	.cipher_key = {
+		.data = {
+			0xE6, 0x60, 0x0F, 0xD8, 0x85, 0x2E, 0xF5, 0xAB
+		},
+		.len = 8
+	},
+	.iv = {
+		.data = {
+			0x81, 0x0E, 0x52, 0x8E, 0x1C, 0x5F, 0xDA, 0x1A
+		},
+		.len = 8
+	},
+	.plaintext = {
+		.data = plaintext_des_docsis_bpi_cbc_cfb,
+		.len = 19
+	},
+	.ciphertext = {
+		.data = ciphertext_des_docsis_bpi_cbc_cfb,
+		.len = 19
+	}
+};
+static const struct blockcipher_test_case des_docsis_test_cases[] = {
+	{
+		.test_descr = "DES-DOCSIS-BPI Full Block Encryption",
+		.test_data = &des_test_data_1,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "DES-DOCSIS-BPI Runt Block Encryption",
+		.test_data = &des_test_data_2,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "DES-DOCSIS-BPI Uneven Encryption",
+		.test_data = &des_test_data_3,
+		.op_mask = BLOCKCIPHER_TEST_OP_ENCRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "DES-DOCSIS-BPI Full Block Decryption",
+		.test_data = &des_test_data_1,
+		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "DES-DOCSIS-BPI Runt Block Decryption",
+		.test_data = &des_test_data_2,
+		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	},
+	{
+		.test_descr = "DES-DOCSIS-BPI Uneven Decryption",
+		.test_data = &des_test_data_3,
+		.op_mask = BLOCKCIPHER_TEST_OP_DECRYPT,
+		.pmd_mask = BLOCKCIPHER_TEST_TARGET_PMD_OPENSSL
+	}
+
+};
+
 static const struct blockcipher_test_case triple_des_chain_test_cases[] = {
 	{
 		.test_descr = "3DES-128-CBC HMAC-SHA1 Encryption Digest",
diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst
index f6ed6ea..8a1cbbe 100644
--- a/doc/guides/cryptodevs/openssl.rst
+++ b/doc/guides/cryptodevs/openssl.rst
@@ -49,6 +49,7 @@ Supported cipher algorithms:
 * ``RTE_CRYPTO_CIPHER_AES_CTR``
 * ``RTE_CRYPTO_CIPHER_3DES_CTR``
 * ``RTE_CRYPTO_CIPHER_AES_GCM``
+* ``RTE_CRYPTO_CIPHER_DES_DOCSISBPI``
 
 Supported authentication algorithms:
 * ``RTE_CRYPTO_AUTH_AES_GMAC``
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index e25ea9f..7921594 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -41,6 +41,12 @@ New Features
      Also, make sure to start the actual text at the margin.
      =========================================================
 
+* **Updated the OpenSSL PMD.**
+
+  The OpenSSL PMD has been updated with additional support for:
+
+  * DES DOCSIS BPI algorithm.
+
 
 Resolved Issues
 ---------------
diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c
index e74c5cf..ff3682d 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -42,6 +42,8 @@
 
 #include "rte_openssl_pmd_private.h"
 
+#define DES_BLOCK_SIZE 8
+
 static int cryptodev_openssl_remove(const char *name);
 
 /*----------------------------------------------------------------------------*/
@@ -289,7 +291,13 @@ openssl_set_session_cipher_parameters(struct openssl_session *sess,
 				sess->cipher.key.data) != 0)
 			return -EINVAL;
 		break;
-
+	case RTE_CRYPTO_CIPHER_DES_DOCSISBPI:
+		sess->cipher.algo = xform->cipher.algo;
+		sess->chain_order = OPENSSL_CHAIN_CIPHER_BPI;
+		sess->cipher.ctx = EVP_CIPHER_CTX_new();
+		get_cipher_key(xform->cipher.key.data, sess->cipher.key.length,
+			sess->cipher.key.data);
+		break;
 	default:
 		sess->cipher.algo = RTE_CRYPTO_CIPHER_NULL;
 		return -EINVAL;
@@ -969,6 +977,107 @@ process_openssl_cipher_op
 		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
 }
 
+/** Process cipher operation */
+static void
+process_openssl_docsis_bpi_op(struct rte_crypto_op *op,
+		struct openssl_session *sess, struct rte_mbuf *mbuf_src,
+		struct rte_mbuf *mbuf_dst)
+{
+	uint8_t *src, *dst, *iv;
+	const EVP_CIPHER *full_block_algo, *runt_frame_algo;
+	uint8_t block_size, last_block_len;
+	int srclen, status = 0;
+	int offset;
+
+	srclen = op->sym->cipher.data.length;
+	src = rte_pktmbuf_mtod_offset(mbuf_src, uint8_t *,
+			op->sym->cipher.data.offset);
+	dst = rte_pktmbuf_mtod_offset(mbuf_dst, uint8_t *,
+			op->sym->cipher.data.offset);
+
+	iv = op->sym->cipher.iv.data;
+
+	full_block_algo = EVP_des_cbc();
+	runt_frame_algo = EVP_des_cfb();
+	block_size = DES_BLOCK_SIZE;
+
+	last_block_len = srclen % block_size;
+	if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT) {
+		/* Encrypt only with CFB mode */
+		if (srclen < block_size) {
+			status = process_openssl_cipher_encrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
+					sess->cipher.key.data, srclen,
+					sess->cipher.ctx, runt_frame_algo);
+		} else {
+			srclen -= last_block_len;
+			/* Encrypt with the block aligned stream with CBC mode */
+			status = process_openssl_cipher_encrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
+					sess->cipher.key.data, srclen,
+					sess->cipher.ctx, full_block_algo);
+			if (last_block_len) {
+				/* Point at last block */
+				offset = op->sym->cipher.data.offset + srclen;
+				dst += srclen;
+				/*
+				 * IV is the last encrypted block from
+				 * the previous operation
+				 */
+				iv = dst - block_size;
+				srclen = last_block_len;
+				/* Encrypt the last frame with CFB mode */
+				status |= process_openssl_cipher_encrypt(mbuf_src,
+						dst, offset, iv,
+						sess->cipher.key.data,
+						srclen, sess->cipher.ctx,
+						runt_frame_algo);
+			}
+		}
+	} else {
+		/* Decrypt only with CFB mode */
+		if (srclen < block_size) {
+			status = process_openssl_cipher_decrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
+					sess->cipher.key.data, srclen,
+					sess->cipher.ctx,
+					runt_frame_algo);
+		} else {
+			if (last_block_len) {
+				/* Point at last block */
+				offset = op->sym->cipher.data.offset + srclen
+					- last_block_len;
+				dst += srclen - last_block_len;
+				/*
+				 * IV is the last encrypted block from
+				 * the previous operation
+				 */
+				iv = src + srclen - last_block_len - block_size;
+				/* Decrypt the last frame with CFB mode */
+				status = process_openssl_cipher_decrypt(mbuf_src,
+						dst, offset,
+						iv, sess->cipher.key.data,
+						last_block_len, sess->cipher.ctx,
+						runt_frame_algo);
+				/* Prepare parameters for CBC mode op */
+				iv = op->sym->cipher.iv.data;
+				dst += last_block_len - srclen;
+				srclen -= last_block_len;
+			}
+
+			/* Decrypt with CBC mode */
+			status |= process_openssl_cipher_decrypt(mbuf_src, dst,
+					op->sym->cipher.data.offset, iv,
+					sess->cipher.key.data, srclen,
+					sess->cipher.ctx,
+					full_block_algo);
+		}
+	}
+
+	if (status != 0)
+		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+}
+
 /** Process auth operation */
 static void
 process_openssl_auth_op
@@ -1052,6 +1161,9 @@ process_op(const struct openssl_qp *qp, struct rte_crypto_op *op,
 	case OPENSSL_CHAIN_COMBINED:
 		process_openssl_combined_op(op, sess, msrc, mdst);
 		break;
+	case OPENSSL_CHAIN_CIPHER_BPI:
+		process_openssl_docsis_bpi_op(op, sess, msrc, mdst);
+		break;
 	default:
 		op->status = RTE_CRYPTO_OP_STATUS_ERROR;
 		break;
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
index 875550c..39ff3e0 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -442,6 +442,26 @@ static const struct rte_cryptodev_capabilities openssl_pmd_capabilities[] = {
 			}, }
 		}, }
 	},
+	{	/* DES DOCSIS BPI */
+		.op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+		{.sym = {
+			.xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+			{.cipher = {
+				.algo = RTE_CRYPTO_CIPHER_DES_DOCSISBPI,
+				.block_size = 8,
+				.key_size = {
+					.min = 8,
+					.max = 8,
+					.increment = 0
+				},
+				.iv_size = {
+					.min = 8,
+					.max = 8,
+					.increment = 0
+				}
+			}, }
+		}, }
+	},
 
 	RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
 };
diff --git a/drivers/crypto/openssl/rte_openssl_pmd_private.h b/drivers/crypto/openssl/rte_openssl_pmd_private.h
index 65c5f97..8b3f335 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_private.h
+++ b/drivers/crypto/openssl/rte_openssl_pmd_private.h
@@ -62,6 +62,7 @@
 enum openssl_chain_order {
 	OPENSSL_CHAIN_ONLY_CIPHER,
 	OPENSSL_CHAIN_ONLY_AUTH,
+	OPENSSL_CHAIN_CIPHER_BPI,
 	OPENSSL_CHAIN_CIPHER_AUTH,
 	OPENSSL_CHAIN_AUTH_CIPHER,
 	OPENSSL_CHAIN_COMBINED,
-- 
2.7.4



More information about the dev mailing list