net/sfc: check mbufs allocated using mempool API for Rx
[dpdk.git] / drivers / crypto / aesni_mb / rte_aesni_mb_pmd.c
index a9f8895..05f08a6 100644 (file)
@@ -14,6 +14,9 @@
 
 #include "rte_aesni_mb_pmd_private.h"
 
+#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);
@@ -101,6 +104,8 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops,
                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;
@@ -122,6 +127,12 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops,
        if (xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC) {
                sess->auth.algo = AES_XCBC;
 
+               uint16_t xcbc_mac_digest_len =
+                       get_truncated_digest_byte_length(AES_XCBC);
+               if (sess->auth.req_digest_len != xcbc_mac_digest_len) {
+                       AESNI_MB_LOG(ERR, "Invalid digest size\n");
+                       return -EINVAL;
+               }
                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,
@@ -132,7 +143,31 @@ 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;
+               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);
 
@@ -149,22 +184,67 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops,
        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");
@@ -192,11 +272,19 @@ aesni_mb_set_session_auth_parameters(const struct aesni_mb_op_fns *mb_ops,
                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;
 }
@@ -387,6 +475,13 @@ aesni_mb_set_session_aead_parameters(const struct aesni_mb_op_fns *mb_ops,
        sess->iv.length = xform->aead.iv.length;
 
        sess->auth.req_digest_len = xform->aead.digest_length;
+       /* CCM digests must be between 4 and 16 and an even number */
+       if (sess->auth.req_digest_len < AES_CCM_DIGEST_MIN_LEN ||
+                       sess->auth.req_digest_len > AES_CCM_DIGEST_MAX_LEN ||
+                       (sess->auth.req_digest_len & 1) == 1) {
+               AESNI_MB_LOG(ERR, "Invalid digest size\n");
+               return -EINVAL;
+       }
        sess->auth.gen_digest_len = sess->auth.req_digest_len;
 
        /* Check key length and choose key expansion function for AES */