From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 6172237AC for ; Thu, 30 Mar 2017 19:27:44 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=intel; t=1490894864; x=1522430864; h=from:to:cc:subject:date:message-id:in-reply-to: references; bh=on8M6EM4psn/lVs0/W+oELT5rt3paHxlQ8pLbsbESSc=; b=AvGuJpqBaw08lG+xnGzB946ddpmIIlTnn9yUR5hcoVzEAu2G3yTseUIH tJTIztZOPy9GIVayO0gHm+Bg2TqnUg==; Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 30 Mar 2017 10:27:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,247,1486454400"; d="scan'208";a="82802423" Received: from silpixa00381631.ir.intel.com (HELO silpixa00381631.ger.corp.intel.com) ([10.237.222.122]) by fmsmga006.fm.intel.com with ESMTP; 30 Mar 2017 10:27:29 -0700 From: Pablo de Lara To: dev@dpdk.org Cc: Pablo de Lara Date: Thu, 30 Mar 2017 18:27:22 +0100 Message-Id: <1490894842-31011-1-git-send-email-pablo.de.lara.guarch@intel.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1490892823-29697-1-git-send-email-pablo.de.lara.guarch@intel.com> References: <1490892823-29697-1-git-send-email-pablo.de.lara.guarch@intel.com> Subject: [dpdk-dev] [PATCH v4] crypto/openssl: add DES DOCSIS BPI support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Mar 2017 17:27:45 -0000 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 Acked-by: Deepak Kumar Jain Tested-by: Yang Gang --- Changes in v4: - Updated release notes Changes in v3: - Rebased against dpdk-next-crypto latest code - Fixed commit message (missing PMD word) - Optimized code, using ECB XOR IV combination, instead of CFB, avoiding an extra crypto initialization Changes in v2: - Added patch dependency note - Fixed the commit message doc/guides/cryptodevs/features/openssl.ini | 18 +-- doc/guides/cryptodevs/openssl.rst | 1 + doc/guides/rel_notes/release_17_05.rst | 6 + drivers/crypto/openssl/rte_openssl_pmd.c | 137 +++++++++++++++++++++++ drivers/crypto/openssl/rte_openssl_pmd_ops.c | 20 ++++ drivers/crypto/openssl/rte_openssl_pmd_private.h | 2 + test/test/test_cryptodev.c | 18 +++ test/test/test_cryptodev_blockcipher.c | 5 + test/test/test_cryptodev_blockcipher.h | 3 +- test/test/test_cryptodev_des_test_vectors.h | 137 +++++++++++++++++++++++ 10 files changed, 337 insertions(+), 10 deletions(-) diff --git a/doc/guides/cryptodevs/features/openssl.ini b/doc/guides/cryptodevs/features/openssl.ini index 189b71b..aeb2a50 100644 --- a/doc/guides/cryptodevs/features/openssl.ini +++ b/doc/guides/cryptodevs/features/openssl.ini @@ -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. ; diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst index 3a28c9d..e341915 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 7623786..fc24931 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -74,6 +74,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 --------------- diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c index 09173b2..5046eac 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,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_openssl_cipher_encrypt(struct rte_mbuf *mbuf_src, uint8_t *dst, 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; diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c index 131a37c..25d1a4b 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..4d820c5 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, @@ -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 */ diff --git a/test/test/test_cryptodev.c b/test/test/test_cryptodev.c index 493518d..a7218f4 100644 --- a/test/test/test_cryptodev.c +++ b/test/test/test_cryptodev.c @@ -4349,6 +4349,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; @@ -7713,6 +7729,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/test/test/test_cryptodev_blockcipher.c b/test/test/test_cryptodev_blockcipher.c index 9d39b7d..9d6ebd6 100644 --- a/test/test/test_cryptodev_blockcipher.c +++ b/test/test/test_cryptodev_blockcipher.c @@ -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]); diff --git a/test/test/test_cryptodev_blockcipher.h b/test/test/test_cryptodev_blockcipher.h index 6e37121..389558a 100644 --- a/test/test/test_cryptodev_blockcipher.h +++ b/test/test/test_cryptodev_blockcipher.h @@ -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 { diff --git a/test/test/test_cryptodev_des_test_vectors.h b/test/test/test_cryptodev_des_test_vectors.h index 388d87e..b29a49e 100644 --- a/test/test/test_cryptodev_des_test_vectors.h +++ b/test/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", -- 2.7.4