#define AES_CCM_DIGEST_MIN_LEN 4
#define AES_CCM_DIGEST_MAX_LEN 16
-
+#define HMAC_MAX_BLOCK_SIZE 128
static uint8_t cryptodev_driver_id;
typedef void (*hash_one_block_t)(const void *data, void *digest);
const struct rte_crypto_sym_xform *xform)
{
hash_one_block_t hash_oneblock_fn;
+ unsigned int key_larger_block_size = 0;
+ uint8_t hashed_key[HMAC_MAX_BLOCK_SIZE] = { 0 };
if (xform == NULL) {
sess->auth.algo = NULL_HASH;
if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_CMAC) {
sess->auth.algo = AES_CMAC;
- sess->auth.gen_digest_len = sess->auth.req_digest_len;
+ uint16_t cmac_digest_len = get_digest_byte_length(AES_CMAC);
+
+ if (sess->auth.req_digest_len > cmac_digest_len) {
+ AESNI_MB_LOG(ERR, "Invalid digest size\n");
+ return -EINVAL;
+ }
+ /*
+ * Multi-buffer lib supports digest sizes from 4 to 16 bytes
+ * in version 0.50 and sizes of 12 and 16 bytes,
+ * in version 0.49.
+ * If size requested is different, generate the full digest
+ * (16 bytes) in a temporary location and then memcpy
+ * the requested number of bytes.
+ */
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0)
+ if (sess->auth.req_digest_len < 4)
+#else
+ uint16_t cmac_trunc_digest_len =
+ get_truncated_digest_byte_length(AES_CMAC);
+ if (sess->auth.req_digest_len != cmac_digest_len &&
+ sess->auth.req_digest_len != cmac_trunc_digest_len)
+#endif
+ sess->auth.gen_digest_len = cmac_digest_len;
+ else
+ 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);
case RTE_CRYPTO_AUTH_SHA1_HMAC:
sess->auth.algo = SHA1;
hash_oneblock_fn = mb_ops->aux.one_block.sha1;
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0)
+ if (xform->auth.key.length > get_auth_algo_blocksize(SHA1)) {
+ mb_ops->aux.multi_block.sha1(
+ xform->auth.key.data,
+ xform->auth.key.length,
+ hashed_key);
+ key_larger_block_size = 1;
+ }
+#endif
break;
case RTE_CRYPTO_AUTH_SHA224_HMAC:
sess->auth.algo = SHA_224;
hash_oneblock_fn = mb_ops->aux.one_block.sha224;
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0)
+ if (xform->auth.key.length > get_auth_algo_blocksize(SHA_224)) {
+ mb_ops->aux.multi_block.sha224(
+ xform->auth.key.data,
+ xform->auth.key.length,
+ hashed_key);
+ key_larger_block_size = 1;
+ }
+#endif
break;
case RTE_CRYPTO_AUTH_SHA256_HMAC:
sess->auth.algo = SHA_256;
hash_oneblock_fn = mb_ops->aux.one_block.sha256;
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0)
+ if (xform->auth.key.length > get_auth_algo_blocksize(SHA_256)) {
+ mb_ops->aux.multi_block.sha256(
+ xform->auth.key.data,
+ xform->auth.key.length,
+ hashed_key);
+ key_larger_block_size = 1;
+ }
+#endif
break;
case RTE_CRYPTO_AUTH_SHA384_HMAC:
sess->auth.algo = SHA_384;
hash_oneblock_fn = mb_ops->aux.one_block.sha384;
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0)
+ if (xform->auth.key.length > get_auth_algo_blocksize(SHA_384)) {
+ mb_ops->aux.multi_block.sha384(
+ xform->auth.key.data,
+ xform->auth.key.length,
+ hashed_key);
+ key_larger_block_size = 1;
+ }
+#endif
break;
case RTE_CRYPTO_AUTH_SHA512_HMAC:
sess->auth.algo = SHA_512;
hash_oneblock_fn = mb_ops->aux.one_block.sha512;
+#if IMB_VERSION_NUM >= IMB_VERSION(0, 50, 0)
+ if (xform->auth.key.length > get_auth_algo_blocksize(SHA_512)) {
+ mb_ops->aux.multi_block.sha512(
+ xform->auth.key.data,
+ xform->auth.key.length,
+ hashed_key);
+ key_larger_block_size = 1;
+ }
+#endif
break;
default:
AESNI_MB_LOG(ERR, "Unsupported authentication algorithm selection");
sess->auth.gen_digest_len = sess->auth.req_digest_len;
/* Calculate Authentication precomputes */
- calculate_auth_precomputes(hash_oneblock_fn,
+ if (key_larger_block_size) {
+ calculate_auth_precomputes(hash_oneblock_fn,
+ sess->auth.pads.inner, sess->auth.pads.outer,
+ hashed_key,
+ xform->auth.key.length,
+ get_auth_algo_blocksize(sess->auth.algo));
+ } else {
+ calculate_auth_precomputes(hash_oneblock_fn,
sess->auth.pads.inner, sess->auth.pads.outer,
xform->auth.key.data,
xform->auth.key.length,
get_auth_algo_blocksize(sess->auth.algo));
+ }
return 0;
}