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:
parent
95978a85a4
commit
763c24917d
@ -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:
|
||||
|
@ -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 }
|
||||
}, }
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user