From patchwork Wed Nov 29 17:12:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Fan Zhang X-Patchwork-Id: 31756 X-Patchwork-Delegate: pablo.de.lara.guarch@intel.com Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id C257A3195; Wed, 29 Nov 2017 18:13:44 +0100 (CET) Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by dpdk.org (Postfix) with ESMTP id 7EAC42C54 for ; Wed, 29 Nov 2017 18:13:42 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 29 Nov 2017 09:13:40 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.45,338,1508828400"; d="scan'208";a="13408073" Received: from silpixa00398673.ir.intel.com (HELO silpixa00398673.ger.corp.intel.com) ([10.237.223.54]) by orsmga002.jf.intel.com with ESMTP; 29 Nov 2017 09:13:39 -0800 From: Fan Zhang To: dev@dpdk.org Cc: roy.fan.zhang@intel.com, pablo.de.lara.guarch@intel.com Date: Wed, 29 Nov 2017 17:12:05 +0000 Message-Id: <20171129171205.56765-1-roy.fan.zhang@intel.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20171128141116.51668-1-roy.fan.zhang@intel.com> References: <20171128141116.51668-1-roy.fan.zhang@intel.com> Subject: [dpdk-dev] [PATCH v2] crypto/aesni_mb: add AES-CCM 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add support to AES-CCM, for 128, 192 and 256-bit keys. Signed-off-by: Fan Zhang --- v2: * Fixed a few bugs doc/guides/cryptodevs/aesni_mb.rst | 4 + doc/guides/cryptodevs/features/aesni_mb.ini | 3 + doc/guides/rel_notes/release_18_02.rst | 5 + drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c | 143 +++++++++++++++++++-- drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c | 31 ++++- drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h | 9 ++ test/test/test_cryptodev.c | 4 + 7 files changed, 187 insertions(+), 12 deletions(-) diff --git a/doc/guides/cryptodevs/aesni_mb.rst b/doc/guides/cryptodevs/aesni_mb.rst index 79e722c..081fdff 100644 --- a/doc/guides/cryptodevs/aesni_mb.rst +++ b/doc/guides/cryptodevs/aesni_mb.rst @@ -65,6 +65,10 @@ Hash algorithms: * RTE_CRYPTO_HASH_SHA512_HMAC * RTE_CRYPTO_HASH_AES_XCBC_HMAC +AEAD algorithms: + +* RTE_CRYPTO_AEAD_AES_CCM + Limitations ----------- diff --git a/doc/guides/cryptodevs/features/aesni_mb.ini b/doc/guides/cryptodevs/features/aesni_mb.ini index fab07cb..d1f268d 100644 --- a/doc/guides/cryptodevs/features/aesni_mb.ini +++ b/doc/guides/cryptodevs/features/aesni_mb.ini @@ -42,3 +42,6 @@ AES XCBC MAC = Y ; Supported AEAD algorithms of the 'aesni_mb' crypto driver. ; [AEAD] +AES CCM (128) = Y +AES CCM (192) = Y +AES CCM (256) = Y diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst index 24b67bb..0da12cb 100644 --- a/doc/guides/rel_notes/release_18_02.rst +++ b/doc/guides/rel_notes/release_18_02.rst @@ -41,6 +41,11 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Updated the AESNI-MB PMD.** + + The AESNI-MB PMD has been updated with additional support for: + + * AES-CCM algorithm. API Changes ----------- diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c index 7004389..8f63402 100644 --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c @@ -110,6 +110,15 @@ aesni_mb_get_chain_order(const struct rte_crypto_sym_xform *xform) return AESNI_MB_OP_HASH_CIPHER; } + if (xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) { + if (xform->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) { + if (xform->aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT) + return AESNI_MB_OP_AEAD_CIPHER_HASH; + else + return AESNI_MB_OP_AEAD_HASH_CIPHER; + } + } + return AESNI_MB_OP_NOT_SUPPORTED; } @@ -285,6 +294,69 @@ aesni_mb_set_session_cipher_parameters(const struct aesni_mb_op_fns *mb_ops, return 0; } +static int +aesni_mb_set_session_aead_parameters(const struct aesni_mb_op_fns *mb_ops, + struct aesni_mb_session *sess, + const struct rte_crypto_sym_xform *xform) +{ + aes_keyexp_t aes_keyexp_fn; + + switch (xform->aead.op) { + case RTE_CRYPTO_AEAD_OP_ENCRYPT: + sess->cipher.direction = ENCRYPT; + sess->auth.operation = RTE_CRYPTO_AUTH_OP_GENERATE; + break; + case RTE_CRYPTO_AEAD_OP_DECRYPT: + sess->cipher.direction = DECRYPT; + sess->auth.operation = RTE_CRYPTO_AUTH_OP_VERIFY; + break; + default: + MB_LOG_ERR("Invalid aead operation parameter"); + return -EINVAL; + } + + switch (xform->aead.algo) { + case RTE_CRYPTO_AEAD_AES_CCM: + sess->cipher.mode = CCM; + sess->auth.algo = AES_CCM; + break; + default: + MB_LOG_ERR("Unsupported aead mode parameter"); + return -ENOTSUP; + } + + /* Set IV parameters */ + sess->iv.offset = xform->aead.iv.offset; + sess->iv.length = xform->aead.iv.length; + + /* Check key length and choose key expansion function for AES */ + + switch (xform->aead.key.length) { + case AES_128_BYTES: + sess->cipher.key_length_in_bytes = AES_128_BYTES; + aes_keyexp_fn = mb_ops->aux.keyexp.aes128; + break; + case AES_192_BYTES: + sess->cipher.key_length_in_bytes = AES_192_BYTES; + aes_keyexp_fn = mb_ops->aux.keyexp.aes192; + break; + case AES_256_BYTES: + sess->cipher.key_length_in_bytes = AES_256_BYTES; + aes_keyexp_fn = mb_ops->aux.keyexp.aes256; + break; + default: + MB_LOG_ERR("Invalid cipher key length"); + return -EINVAL; + } + + /* Expanded cipher keys */ + (*aes_keyexp_fn)(xform->aead.key.data, + sess->cipher.expanded_aes_keys.encode, + sess->cipher.expanded_aes_keys.decode); + + return 0; +} + /** Parse crypto xform chain and set private session parameters */ int aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops, @@ -293,6 +365,7 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops, { const struct rte_crypto_sym_xform *auth_xform = NULL; const struct rte_crypto_sym_xform *cipher_xform = NULL; + const struct rte_crypto_sym_xform *aead_xform = NULL; int ret; /* Select Crypto operation - hash then cipher / cipher then hash */ @@ -326,6 +399,16 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops, auth_xform = NULL; cipher_xform = xform; break; + case AESNI_MB_OP_AEAD_CIPHER_HASH: + sess->chain_order = CIPHER_HASH; + sess->aad_len = xform->aead.aad_length; + aead_xform = xform; + break; + case AESNI_MB_OP_AEAD_HASH_CIPHER: + sess->chain_order = HASH_CIPHER; + sess->aad_len = xform->aead.aad_length; + aead_xform = xform; + break; case AESNI_MB_OP_NOT_SUPPORTED: default: MB_LOG_ERR("Unsupported operation chain order parameter"); @@ -348,6 +431,15 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops, return ret; } + if (aead_xform) { + ret = aesni_mb_set_session_aead_parameters(mb_ops, sess, + aead_xform); + if (ret != 0) { + MB_LOG_ERR("Invalid/unsupported aead parameters"); + return ret; + } + } + return 0; } @@ -462,6 +554,9 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp, job->_k1_expanded = session->auth.xcbc.k1_expanded; job->_k2 = session->auth.xcbc.k2; job->_k3 = session->auth.xcbc.k3; + } else if (job->hash_alg == AES_CCM) { + job->u.CCM.aad = op->sym->aead.aad.data + 18; + job->u.CCM.aad_len_in_bytes = session->aad_len; } else { job->hashed_auth_key_xor_ipad = session->auth.pads.inner; job->hashed_auth_key_xor_opad = session->auth.pads.outer; @@ -485,7 +580,10 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp, rte_pktmbuf_data_len(op->sym->m_src)); } else { m_dst = m_src; - m_offset = op->sym->cipher.data.offset; + if (job->hash_alg == AES_CCM) + m_offset = op->sym->aead.data.offset; + else + m_offset = op->sym->cipher.data.offset; } /* Set digest output location */ @@ -494,7 +592,10 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp, job->auth_tag_output = qp->temp_digests[*digest_idx]; *digest_idx = (*digest_idx + 1) % MAX_JOBS; } else { - job->auth_tag_output = op->sym->auth.digest.data; + if (job->hash_alg == AES_CCM) + job->auth_tag_output = op->sym->aead.digest.data; + else + job->auth_tag_output = op->sym->auth.digest.data; } /* @@ -505,19 +606,33 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp, get_truncated_digest_byte_length(job->hash_alg); /* Set IV parameters */ - job->iv = rte_crypto_op_ctod_offset(op, uint8_t *, - session->iv.offset); + job->iv_len_in_bytes = session->iv.length; /* Data Parameter */ job->src = rte_pktmbuf_mtod(m_src, uint8_t *); job->dst = rte_pktmbuf_mtod_offset(m_dst, uint8_t *, m_offset); - job->cipher_start_src_offset_in_bytes = op->sym->cipher.data.offset; - job->msg_len_to_cipher_in_bytes = op->sym->cipher.data.length; + if (job->hash_alg == AES_CCM) { + job->cipher_start_src_offset_in_bytes = + op->sym->aead.data.offset; + job->msg_len_to_cipher_in_bytes = op->sym->aead.data.length; + job->hash_start_src_offset_in_bytes = op->sym->aead.data.offset; + job->msg_len_to_hash_in_bytes = op->sym->aead.data.length; - job->hash_start_src_offset_in_bytes = op->sym->auth.data.offset; - job->msg_len_to_hash_in_bytes = op->sym->auth.data.length; + job->iv = rte_crypto_op_ctod_offset(op, uint8_t *, + session->iv.offset + 1); + } else { + job->cipher_start_src_offset_in_bytes = + op->sym->cipher.data.offset; + job->msg_len_to_cipher_in_bytes = op->sym->cipher.data.length; + + job->hash_start_src_offset_in_bytes = op->sym->auth.data.offset; + job->msg_len_to_hash_in_bytes = op->sym->auth.data.length; + + job->iv = rte_crypto_op_ctod_offset(op, uint8_t *, + session->iv.offset); + } /* Set user data to be crypto operation data struct */ job->user_data = op; @@ -529,9 +644,15 @@ static inline void verify_digest(struct aesni_mb_qp *qp __rte_unused, JOB_AES_HMAC *job, struct rte_crypto_op *op) { /* Verify digest if required */ - if (memcmp(job->auth_tag_output, op->sym->auth.digest.data, - job->auth_tag_output_len_in_bytes) != 0) - op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; + if (job->hash_alg == AES_CCM) { + if (memcmp(job->auth_tag_output, op->sym->aead.digest.data, + job->auth_tag_output_len_in_bytes) != 0) + op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; + } else { + if (memcmp(job->auth_tag_output, op->sym->auth.digest.data, + job->auth_tag_output_len_in_bytes) != 0) + op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; + } } /** diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c index 3b3ef0c..48c7c53 100644 --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c @@ -287,7 +287,36 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { }, } }, } }, - + { /* AES CCM */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD, + {.aead = { + .algo = RTE_CRYPTO_AEAD_AES_CCM, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .digest_size = { + .min = 8, + .max = 16, + .increment = 2 + }, + .aad_size = { + .min = 0, + .max = 224, + .increment = 1 + }, + .iv_size = { + .min = 13, + .max = 13, + .increment = 0 + }, + }, } + }, } + }, RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h index fe3bd73..60a43a3 100644 --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h @@ -71,6 +71,7 @@ static const unsigned auth_blocksize[] = { [SHA_384] = 128, [SHA_512] = 128, [AES_XCBC] = 16, + [AES_CCM] = 16, }; /** @@ -93,6 +94,9 @@ static const unsigned auth_truncated_digest_byte_lengths[] = { [SHA_384] = 24, [SHA_512] = 32, [AES_XCBC] = 12, + /* Although IPSEC supports 8 and 16 in CCM,only 8 supported + * here*/ + [AES_CCM] = 8, [NULL_HASH] = 0 }; @@ -137,6 +141,8 @@ enum aesni_mb_operation { AESNI_MB_OP_CIPHER_HASH, AESNI_MB_OP_HASH_ONLY, AESNI_MB_OP_CIPHER_ONLY, + AESNI_MB_OP_AEAD_HASH_CIPHER, + AESNI_MB_OP_AEAD_CIPHER_HASH, AESNI_MB_OP_NOT_SUPPORTED }; @@ -238,6 +244,9 @@ struct aesni_mb_session { /**< Expanded XCBC authentication keys */ }; } auth; + + /** AAD data length */ + uint16_t aad_len; } __rte_cache_aligned; diff --git a/test/test/test_cryptodev.c b/test/test/test_cryptodev.c index 1bed65d..1ca49d7 100644 --- a/test/test/test_cryptodev.c +++ b/test/test/test_cryptodev.c @@ -8746,6 +8746,10 @@ static struct unit_test_suite cryptodev_aesni_mb_testsuite = { test_DES_cipheronly_mb_all), TEST_CASE_ST(ut_setup, ut_teardown, test_DES_docsis_mb_all), + TEST_CASE_ST(ut_setup, ut_teardown, + test_AES_CCM_authenticated_encryption_test_case_128_2), + TEST_CASE_ST(ut_setup, ut_teardown, + test_AES_CCM_authenticated_decryption_test_case_128_2), TEST_CASES_END() /**< NULL terminate unit test array */ }