From 1dee7bc7f2085ae8090251fca1a16953b1842ff3 Mon Sep 17 00:00:00 2001 From: Pablo de Lara Date: Thu, 23 Feb 2017 15:21:32 +0000 Subject: [PATCH] crypto/openssl: support DES DOCSIS BPI 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 --- 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 +++ .../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 189b71bb86..aeb2a500b4 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 3a28c9d63b..e34191519a 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 fcc7faa06a..cd55780c38 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -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 --------------- diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c index 09173b2120..5046eac1d1 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_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; diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c index 131a37c9b6..25d1a4b0ce 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 65c5f9794b..4d820c51bb 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 493518d1e7..a7218f476c 100644 --- a/test/test/test_cryptodev.c +++ b/test/test/test_cryptodev.c @@ -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), diff --git a/test/test/test_cryptodev_blockcipher.c b/test/test/test_cryptodev_blockcipher.c index 9d39b7d761..9d6ebd61c6 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 6e3712114a..389558a925 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 388d87e182..b29a49ef5d 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.20.1