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 <pablo.de.lara.guarch@intel.com>
Acked-by: Marko Kovacevic <marko.kovacevic@intel.com>
This commit is contained in:
Pablo de Lara 2018-08-14 01:38:44 +01:00 committed by Akhil Goyal
parent 95978a85a4
commit 763c24917d
3 changed files with 105 additions and 27 deletions

View File

@ -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;
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;
}
}
/*
* 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;
/* 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:

View File

@ -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 }
}, }

View File

@ -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 {