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.gua...@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

Reply via email to