crypto/openssl: support DES DOCSIS BPI
authorPablo de Lara <pablo.de.lara.guarch@intel.com>
Thu, 23 Feb 2017 15:21:32 +0000 (15:21 +0000)
committerPablo de Lara <pablo.de.lara.guarch@intel.com>
Wed, 5 Apr 2017 22:17:44 +0000 (00:17 +0200)
Adds support in OpenSSL PMD 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@intel.com>
Acked-by: Deepak Kumar Jain <deepak.k.jain@intel.com>
Tested-by: Yang Gang <gangx.yang@intel.com>
doc/guides/cryptodevs/features/openssl.ini
doc/guides/cryptodevs/openssl.rst
doc/guides/rel_notes/release_17_05.rst
drivers/crypto/openssl/rte_openssl_pmd.c
drivers/crypto/openssl/rte_openssl_pmd_ops.c
drivers/crypto/openssl/rte_openssl_pmd_private.h
test/test/test_cryptodev.c
test/test/test_cryptodev_blockcipher.c
test/test/test_cryptodev_blockcipher.h
test/test/test_cryptodev_des_test_vectors.h

index 189b71b..aeb2a50 100644 (file)
@@ -11,15 +11,15 @@ Sym operation chaining = Y
 ; Supported crypto algorithms of the 'openssl' crypto driver.
 ;
 [Cipher]
-AES CBC (128) = Y
-AES CBC (192) = Y
-AES CBC (256) = Y
-AES CTR (128) = Y
-AES CTR (192) = Y
-AES CTR (256) = Y
-3DES CBC      = Y
-3DES CTR      = Y
-
+AES CBC (128)  = Y
+AES CBC (192)  = Y
+AES CBC (256)  = Y
+AES CTR (128)  = Y
+AES CTR (192)  = Y
+AES CTR (256)  = Y
+3DES CBC       = Y
+3DES CTR       = Y
+DES DOCSIS BPI = Y
 ;
 ; Supported authentication algorithms of the 'openssl' crypto driver.
 ;
index 3a28c9d..e341915 100644 (file)
@@ -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``
index fcc7faa..cd55780 100644 (file)
@@ -251,6 +251,12 @@ New Features
 
   * AES DOCSIS BPI algorithm.
 
+* **Updated the OpenSSL PMD.**
+
+  The OpenSSL PMD has been updated with additional support for:
+
+  * DES DOCSIS BPI algorithm.
+
 Resolved Issues
 ---------------
 
index 09173b2..5046eac 100644 (file)
@@ -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,21 @@ 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();
+               sess->cipher.evp_algo = EVP_des_cbc();
 
+               sess->cipher.bpi_ctx = EVP_CIPHER_CTX_new();
+               /* IV will be ECB encrypted whether direction is encrypt or decrypt */
+               if (EVP_EncryptInit_ex(sess->cipher.bpi_ctx, EVP_des_ecb(),
+                               NULL, xform->cipher.key.data, 0) != 1)
+                       return -EINVAL;
+
+               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;
@@ -407,6 +423,9 @@ openssl_reset_session(struct openssl_session *sess)
 {
        EVP_CIPHER_CTX_free(sess->cipher.ctx);
 
+       if (sess->chain_order == OPENSSL_CHAIN_CIPHER_BPI)
+               EVP_CIPHER_CTX_free(sess->cipher.bpi_ctx);
+
        switch (sess->auth.mode) {
        case OPENSSL_AUTH_AS_AUTH:
                EVP_MD_CTX_destroy(sess->auth.auth.ctx);
@@ -577,6 +596,29 @@ process_cipher_encrypt_err:
        return -EINVAL;
 }
 
+/** Process standard openssl cipher encryption */
+static int
+process_openssl_cipher_bpi_encrypt(uint8_t *src, uint8_t *dst,
+               uint8_t *iv, int srclen,
+               EVP_CIPHER_CTX *ctx)
+{
+       uint8_t i;
+       uint8_t encrypted_iv[DES_BLOCK_SIZE];
+       int encrypted_ivlen;
+
+       if (EVP_EncryptUpdate(ctx, encrypted_iv, &encrypted_ivlen,
+                       iv, DES_BLOCK_SIZE) <= 0)
+               goto process_cipher_encrypt_err;
+
+       for (i = 0; i < srclen; i++)
+               *(dst + i) = *(src + i) ^ (encrypted_iv[i]);
+
+       return 0;
+
+process_cipher_encrypt_err:
+       OPENSSL_LOG_ERR("Process openssl cipher bpi encrypt failed");
+       return -EINVAL;
+}
 /** Process standard openssl cipher decryption */
 static int
 process_openssl_cipher_decrypt(struct rte_mbuf *mbuf_src, uint8_t *dst,
@@ -969,6 +1011,98 @@ 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;
+       uint8_t block_size, last_block_len;
+       int srclen, status = 0;
+
+       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;
+
+       block_size = DES_BLOCK_SIZE;
+
+       last_block_len = srclen % block_size;
+       if (sess->cipher.direction == RTE_CRYPTO_CIPHER_OP_ENCRYPT) {
+               /* Encrypt only with ECB mode XOR IV */
+               if (srclen < block_size) {
+                       status = process_openssl_cipher_bpi_encrypt(src, dst,
+                                       iv, srclen,
+                                       sess->cipher.bpi_ctx);
+               } 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, sess->cipher.evp_algo);
+                       if (last_block_len) {
+                               /* Point at last block */
+                               dst += srclen;
+                               /*
+                                * IV is the last encrypted block from
+                                * the previous operation
+                                */
+                               iv = dst - block_size;
+                               src += srclen;
+                               srclen = last_block_len;
+                               /* Encrypt the last frame with ECB mode */
+                               status |= process_openssl_cipher_bpi_encrypt(src,
+                                               dst, iv,
+                                               srclen, sess->cipher.bpi_ctx);
+                       }
+               }
+       } else {
+               /* Decrypt only with ECB mode (encrypt, as it is same operation) */
+               if (srclen < block_size) {
+                       status = process_openssl_cipher_bpi_encrypt(src, dst,
+                                       iv,
+                                       srclen,
+                                       sess->cipher.bpi_ctx);
+               } else {
+                       if (last_block_len) {
+                               /* Point at last block */
+                               dst += srclen - last_block_len;
+                               src += srclen - last_block_len;
+                               /*
+                                * IV is the last full block
+                                */
+                               iv = src - block_size;
+                               /*
+                                * Decrypt the last frame with ECB mode
+                                * (encrypt, as it is the same operation)
+                                */
+                               status = process_openssl_cipher_bpi_encrypt(src,
+                                               dst, iv,
+                                               last_block_len, sess->cipher.bpi_ctx);
+                               /* 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,
+                                       sess->cipher.evp_algo);
+               }
+       }
+
+       if (status != 0)
+               op->status = RTE_CRYPTO_OP_STATUS_ERROR;
+}
+
 /** Process auth operation */
 static void
 process_openssl_auth_op
@@ -1052,6 +1186,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;
index 131a37c..25d1a4b 100644 (file)
@@ -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()
 };
index 65c5f97..4d820c5 100644 (file)
@@ -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,
@@ -127,6 +128,7 @@ struct openssl_session {
                /**< pointer to EVP algorithm function */
                EVP_CIPHER_CTX *ctx;
                /**< pointer to EVP context structure */
+               EVP_CIPHER_CTX *bpi_ctx;
        } cipher;
 
        /** Authentication Parameters */
index 493518d..a7218f4 100644 (file)
@@ -4348,6 +4348,22 @@ test_DES_cipheronly_qat_all(void)
        return TEST_SUCCESS;
 }
 
+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)
 {
@@ -7712,6 +7728,8 @@ static struct unit_test_suite cryptodev_openssl_testsuite  = {
                                test_3DES_chain_openssl_all),
                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),
 
index 9d39b7d..9d6ebd6 100644 (file)
@@ -633,6 +633,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]);
index 6e37121..389558a 100644 (file)
@@ -72,7 +72,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 {
index 388d87e..b29a49e 100644 (file)
@@ -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",