From: Pablo de Lara Date: Tue, 14 Aug 2018 00:38:44 +0000 (+0100) Subject: crypto/aesni_mb: support all truncated HMAC digest sizes X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=763c24917d4756989d456255aa400814d18c4148;p=dpdk.git crypto/aesni_mb: support all truncated HMAC digest sizes HMAC algorithms (MD5 and SHAx) have different full digest sizes. However, they are often truncated to a smaller size (such as in IPSec). This commit allows a user to generate a digest of any size up to the full size. Signed-off-by: Pablo de Lara Acked-by: Marko Kovacevic --- diff --git a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c index e2dd834f05..a9f8895bed 100644 --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd.c @@ -112,12 +112,17 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops, return -1; } + /* Set the request digest size */ + sess->auth.req_digest_len = xform->auth.digest_length; + /* Select auth generate/verify */ sess->auth.operation = xform->auth.op; /* Set Authentication Parameters */ if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) { sess->auth.algo = AES_XCBC; + + sess->auth.gen_digest_len = sess->auth.req_digest_len; (*mb_ops->aux.keyexp.aes_xcbc)(xform->auth.key.data, sess->auth.xcbc.k1_expanded, sess->auth.xcbc.k2, sess->auth.xcbc.k3); @@ -126,6 +131,8 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops, if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_CMAC) { sess->auth.algo = AES_CMAC; + + sess->auth.gen_digest_len = sess->auth.req_digest_len; (*mb_ops->aux.keyexp.aes_cmac_expkey)(xform->auth.key.data, sess->auth.cmac.expkey); @@ -134,7 +141,6 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops, return 0; } - switch (xform->auth.algo) { case RTE_CRYPTO_AUTH_MD5_HMAC: sess->auth.algo = MD5; @@ -164,6 +170,26 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops, AESNI_MB_LOG(ERR, "Unsupported authentication algorithm selection"); return -ENOTSUP; } + uint16_t trunc_digest_size = + get_truncated_digest_byte_length(sess->auth.algo); + uint16_t full_digest_size = + get_digest_byte_length(sess->auth.algo); + +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + if (sess->auth.req_digest_len > full_digest_size || + sess->auth.req_digest_len == 0) { +#else + if (sess->auth.req_digest_len != trunc_digest_size) { +#endif + AESNI_MB_LOG(ERR, "Invalid digest size\n"); + return -EINVAL; + } + + if (sess->auth.req_digest_len != trunc_digest_size && + sess->auth.req_digest_len != full_digest_size) + sess->auth.gen_digest_len = full_digest_size; + else + sess->auth.gen_digest_len = sess->auth.req_digest_len; /* Calculate Authentication precomputes */ calculate_auth_precomputes(hash_oneblock_fn, @@ -360,6 +386,9 @@ aesni_mb_set_session_aead_parameters(const struct aesni_mb_op_fns *mb_ops, sess->iv.offset = xform->aead.iv.offset; sess->iv.length = xform->aead.iv.length; + sess->auth.req_digest_len = xform->aead.digest_length; + sess->auth.gen_digest_len = sess->auth.req_digest_len; + /* Check key length and choose key expansion function for AES */ switch (xform->aead.key.length) { @@ -397,19 +426,16 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops, sess->chain_order = HASH_CIPHER; auth_xform = xform; cipher_xform = xform->next; - sess->auth.digest_len = xform->auth.digest_length; break; case AESNI_MB_OP_CIPHER_HASH: sess->chain_order = CIPHER_HASH; auth_xform = xform->next; cipher_xform = xform; - sess->auth.digest_len = xform->auth.digest_length; break; case AESNI_MB_OP_HASH_ONLY: sess->chain_order = HASH_CIPHER; auth_xform = xform; cipher_xform = NULL; - sess->auth.digest_len = xform->auth.digest_length; break; case AESNI_MB_OP_CIPHER_ONLY: /* @@ -428,13 +454,11 @@ aesni_mb_set_session_parameters(const struct aesni_mb_op_fns *mb_ops, case AESNI_MB_OP_AEAD_CIPHER_HASH: sess->chain_order = CIPHER_HASH; sess->aead.aad_len = xform->aead.aad_length; - sess->auth.digest_len = xform->aead.digest_length; aead_xform = xform; break; case AESNI_MB_OP_AEAD_HASH_CIPHER: sess->chain_order = HASH_CIPHER; sess->aead.aad_len = xform->aead.aad_length; - sess->auth.digest_len = xform->aead.digest_length; aead_xform = xform; break; case AESNI_MB_OP_NOT_SUPPORTED: @@ -641,21 +665,17 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp, job->auth_tag_output = op->sym->aead.digest.data; else job->auth_tag_output = op->sym->auth.digest.data; - } - /* - * Multi-buffer library current only support returning a truncated - * digest length as specified in the relevant IPsec RFCs - */ - if (job->hash_alg != AES_CCM && job->hash_alg != AES_CMAC) - job->auth_tag_output_len_in_bytes = - get_truncated_digest_byte_length(job->hash_alg); - else - job->auth_tag_output_len_in_bytes = session->auth.digest_len; + if (session->auth.req_digest_len != session->auth.gen_digest_len) { + job->auth_tag_output = qp->temp_digests[*digest_idx]; + *digest_idx = (*digest_idx + 1) % MAX_JOBS; + } + } + /* Set digest length */ + job->auth_tag_output_len_in_bytes = session->auth.gen_digest_len; /* Set IV parameters */ - job->iv_len_in_bytes = session->iv.length; /* Data Parameter */ @@ -690,20 +710,37 @@ set_mb_job_params(JOB_AES_HMAC *job, struct aesni_mb_qp *qp, } static inline void -verify_digest(struct aesni_mb_qp *qp __rte_unused, JOB_AES_HMAC *job, - struct rte_crypto_op *op) { +verify_digest(JOB_AES_HMAC *job, struct rte_crypto_op *op, + struct aesni_mb_session *sess) +{ /* Verify digest if required */ 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) + sess->auth.req_digest_len) != 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) + sess->auth.req_digest_len) != 0) op->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED; } } +static inline void +generate_digest(JOB_AES_HMAC *job, struct rte_crypto_op *op, + struct aesni_mb_session *sess) +{ + /* No extra copy neeed */ + if (likely(sess->auth.req_digest_len == sess->auth.gen_digest_len)) + return; + + /* + * This can only happen for HMAC, so only digest + * for authentication algos is required + */ + memcpy(op->sym->auth.digest.data, job->auth_tag_output, + sess->auth.req_digest_len); +} + /** * Process a completed job and return rte_mbuf which job processed * @@ -730,7 +767,9 @@ post_process_mb_job(struct aesni_mb_qp *qp, JOB_AES_HMAC *job) if (job->hash_alg != NULL_HASH) { if (sess->auth.operation == RTE_CRYPTO_AUTH_OP_VERIFY) - verify_digest(qp, job, op); + verify_digest(job, op, sess); + else + generate_digest(job, op, sess); } break; default: 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 ab26e5ae4c..e8397803ef 100644 --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_ops.c @@ -25,9 +25,15 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { .increment = 1 }, .digest_size = { +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + .min = 1, + .max = 16, + .increment = 1 +#else .min = 12, .max = 12, .increment = 0 +#endif }, .iv_size = { 0 } }, } @@ -46,9 +52,15 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { .increment = 1 }, .digest_size = { +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + .min = 1, + .max = 20, + .increment = 1 +#else .min = 12, .max = 12, .increment = 0 +#endif }, .iv_size = { 0 } }, } @@ -67,9 +79,15 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { .increment = 1 }, .digest_size = { +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + .min = 1, + .max = 28, + .increment = 1 +#else .min = 14, .max = 14, .increment = 0 +#endif }, .iv_size = { 0 } }, } @@ -88,9 +106,15 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { .increment = 1 }, .digest_size = { +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + .min = 1, + .max = 32, + .increment = 1 +#else .min = 16, .max = 16, .increment = 0 +#endif }, .iv_size = { 0 } }, } @@ -109,9 +133,15 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { .increment = 1 }, .digest_size = { +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + .min = 1, + .max = 48, + .increment = 1 +#else .min = 24, .max = 24, .increment = 0 +#endif }, .iv_size = { 0 } }, } @@ -130,9 +160,15 @@ static const struct rte_cryptodev_capabilities aesni_mb_pmd_capabilities[] = { .increment = 1 }, .digest_size = { +#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0) + .min = 1, + .max = 64, + .increment = 1 +#else .min = 32, .max = 32, .increment = 0 +#endif }, .iv_size = { 0 } }, } 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 70e9d18e56..cc5822a825 100644 --- a/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h +++ b/drivers/crypto/aesni_mb/rte_aesni_mb_pmd_private.h @@ -31,8 +31,8 @@ int aesni_mb_logtype_driver; #define HMAC_IPAD_VALUE (0x36) #define HMAC_OPAD_VALUE (0x5C) -/* Maximum length for digest (SHA-512 truncated needs 32 bytes) */ -#define DIGEST_LENGTH_MAX 32 +/* Maximum length for digest */ +#define DIGEST_LENGTH_MAX 64 static const unsigned auth_blocksize[] = { [MD5] = 64, [SHA1] = 64, @@ -95,7 +95,8 @@ static const unsigned auth_digest_byte_lengths[] = { }; /** - * Get the output digest size in bytes for a specified authentication algorithm + * Get the full digest size in bytes for a specified authentication algorithm + * (if available in the Multi-buffer library) * * @Note: this function will not return a valid value for a non-valid * authentication algorithm @@ -226,8 +227,10 @@ struct aesni_mb_session { } cmac; /**< Expanded XCBC authentication keys */ }; - /** digest size */ - uint16_t digest_len; + /** Generated digest size by the Multi-buffer library */ + uint16_t gen_digest_len; + /** Requested digest size from Cryptodev */ + uint16_t req_digest_len; } auth; struct {