From: Dmitry Eremin-Solenikov <[email protected]>

Per idea of Janne Peltonen, do not allocate/free crypto contexts for
each operation, providing significant speed increase. Each thread
on startup allocates hmac+cipher contexts pair for each crypto session.
Then they are initialized on demand, when session is first
executed using this thread.

Signed-off-by: Dmitry Eremin-Solenikov <[email protected]>
---
/** Email created from pull request 342 (lumag:openssl-ctx)
 ** https://github.com/Linaro/odp/pull/342
 ** Patch: https://github.com/Linaro/odp/pull/342.patch
 ** Base sha: 520c170d758f2d37554631bf1467ec50e027cd3e
 ** Merge commit sha: 920a2649f23af22c398652671014a3280244542a
 **/
 platform/linux-generic/include/odp_internal.h |   2 +
 platform/linux-generic/odp_crypto.c           | 321 ++++++++++++++++++--------
 platform/linux-generic/odp_init.c             |  13 ++
 3 files changed, 234 insertions(+), 102 deletions(-)

diff --git a/platform/linux-generic/include/odp_internal.h 
b/platform/linux-generic/include/odp_internal.h
index 54f95b8b3..4fd721449 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -110,6 +110,8 @@ int odp_queue_term_global(void);
 
 int odp_crypto_init_global(void);
 int odp_crypto_term_global(void);
+int _odp_crypto_init_local(void);
+int _odp_crypto_term_local(void);
 
 int odp_timer_init_global(const odp_init_t *params);
 int odp_timer_term_global(void);
diff --git a/platform/linux-generic/odp_crypto.c 
b/platform/linux-generic/odp_crypto.c
index 3b110c191..bc2db50a9 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -9,7 +9,6 @@
 #include <odp_posix_extensions.h>
 #include <odp/api/crypto.h>
 #include <odp_internal.h>
-#include <odp/api/atomic.h>
 #include <odp/api/spinlock.h>
 #include <odp/api/sync.h>
 #include <odp/api/debug.h>
@@ -20,6 +19,8 @@
 #include <odp/api/random.h>
 #include <odp/api/plat/packet_inlines.h>
 #include <odp_packet_internal.h>
+#include <odp_atomic_internal.h>
+#include <odp_bitset.h>
 
 #include <string.h>
 #include <stdlib.h>
@@ -98,6 +99,7 @@ typedef
 odp_crypto_alg_err_t (*crypto_func_t)(odp_packet_t pkt,
                                      const odp_crypto_packet_op_param_t *param,
                                      odp_crypto_generic_session_t *session);
+typedef void (*crypto_init_func_t)(odp_crypto_generic_session_t *session);
 
 /**
  * Per crypto session data structure
@@ -117,6 +119,7 @@ struct odp_crypto_generic_session_t {
 
                const EVP_CIPHER *evp_cipher;
                crypto_func_t func;
+               crypto_init_func_t init;
        } cipher;
 
        struct {
@@ -128,7 +131,10 @@ struct odp_crypto_generic_session_t {
                        const EVP_CIPHER *evp_cipher;
                };
                crypto_func_t func;
+               crypto_init_func_t init;
        } auth;
+
+       unsigned idx;
 };
 
 typedef struct odp_crypto_global_s odp_crypto_global_t;
@@ -137,15 +143,42 @@ struct odp_crypto_global_s {
        odp_spinlock_t                lock;
        odp_crypto_generic_session_t *free;
        odp_crypto_generic_session_t  sessions[MAX_SESSIONS];
+
+       /* This bitfield is cleared at alloc_session()
+        * together with the rest of data */
+       _odp_atomic_flag_t ctx_valid[ODP_THREAD_COUNT_MAX]
+                                   [MAX_SESSIONS];
+
        odp_ticketlock_t              openssl_lock[0];
 };
 
 static odp_crypto_global_t *global;
 
+typedef struct crypto_local_t {
+       HMAC_CTX *hmac_ctx[MAX_SESSIONS];
+       EVP_CIPHER_CTX *cipher_ctx[MAX_SESSIONS];
+       EVP_CIPHER_CTX *mac_cipher_ctx[MAX_SESSIONS];
+       _odp_atomic_flag_t *ctx_valid;
+} crypto_local_t;
+
+static __thread crypto_local_t local;
+
+typedef enum { KIND_HMAC, KIND_CIPHER, KIND_MAC_CIPHER } crypto_kind_t;
+
+static inline void crypto_init(odp_crypto_generic_session_t *session)
+{
+       if (_odp_atomic_flag_tas(&local.ctx_valid[session->idx]))
+               return;
+
+       session->cipher.init(session);
+       session->auth.init(session);
+}
+
 static
 odp_crypto_generic_session_t *alloc_session(void)
 {
        odp_crypto_generic_session_t *session = NULL;
+       unsigned i;
 
        odp_spinlock_lock(&global->lock);
        session = global->free;
@@ -155,6 +188,11 @@ odp_crypto_generic_session_t *alloc_session(void)
        }
        odp_spinlock_unlock(&global->lock);
 
+       session->idx = session - global->sessions;
+
+       for (i = 0; i < ODP_THREAD_COUNT_MAX; i++)
+               _odp_atomic_flag_clear(&global->ctx_valid[i][session->idx]);
+
        return session;
 }
 
@@ -175,24 +213,57 @@ null_crypto_routine(odp_packet_t pkt ODP_UNUSED,
        return ODP_CRYPTO_ALG_ERR_NONE;
 }
 
-static
-void packet_hmac_calculate(HMAC_CTX *ctx,
-                          odp_packet_t pkt,
-                          const odp_crypto_packet_op_param_t *param,
-                          odp_crypto_generic_session_t *session,
-                          uint8_t *hash)
+static void
+null_crypto_init_routine(odp_crypto_generic_session_t *session ODP_UNUSED)
 {
-       uint32_t offset = param->auth_range.offset;
-       uint32_t len   = param->auth_range.length;
+       return;
+}
 
-       ODP_ASSERT(offset + len <= odp_packet_len(pkt));
+/* Mimic new OpenSSL 1.1.y API */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+static HMAC_CTX *HMAC_CTX_new(void)
+{
+       HMAC_CTX *ctx = malloc(sizeof(*ctx));
+
+       HMAC_CTX_init(ctx);
+       return ctx;
+}
+
+static void HMAC_CTX_free(HMAC_CTX *ctx)
+{
+       HMAC_CTX_cleanup(ctx);
+       free(ctx);
+}
+#endif
+
+static void
+auth_init(odp_crypto_generic_session_t *session)
+{
+       HMAC_CTX *ctx = local.hmac_ctx[session->idx];
 
        HMAC_Init_ex(ctx,
                     session->auth.key,
                     session->auth.key_length,
                     session->auth.evp_md,
                     NULL);
+}
+
+static
+void packet_hmac(odp_packet_t pkt,
+                const odp_crypto_packet_op_param_t *param,
+                odp_crypto_generic_session_t *session,
+                uint8_t *hash)
+{
+       HMAC_CTX *ctx = local.hmac_ctx[session->idx];
+       uint32_t offset = param->auth_range.offset;
+       uint32_t len   = param->auth_range.length;
+
+       ODP_ASSERT(offset + len <= odp_packet_len(pkt));
 
+       /* Reinitialize HMAC calculation without resetting the key */
+       HMAC_Init_ex(ctx, NULL, 0, NULL, NULL);
+
+       /* Hash it */
        while (len > 0) {
                uint32_t seglen = 0; /* GCC */
                void *mapaddr = odp_packet_offset(pkt, offset, &seglen, NULL);
@@ -206,36 +277,6 @@ void packet_hmac_calculate(HMAC_CTX *ctx,
        HMAC_Final(ctx, hash, NULL);
 }
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-static
-void packet_hmac(odp_packet_t pkt,
-                const odp_crypto_packet_op_param_t *param,
-                odp_crypto_generic_session_t *session,
-                uint8_t *hash)
-{
-       HMAC_CTX ctx;
-
-       /* Hash it */
-       HMAC_CTX_init(&ctx);
-       packet_hmac_calculate(&ctx, pkt, param, session, hash);
-       HMAC_CTX_cleanup(&ctx);
-}
-#else
-static
-void packet_hmac(odp_packet_t pkt,
-                const odp_crypto_packet_op_param_t *param,
-                odp_crypto_generic_session_t *session,
-                uint8_t *hash)
-{
-       HMAC_CTX *ctx;
-
-       /* Hash it */
-       ctx = HMAC_CTX_new();
-       packet_hmac_calculate(ctx, pkt, param, session, hash);
-       HMAC_CTX_free(ctx);
-}
-#endif
-
 static
 odp_crypto_alg_err_t auth_gen(odp_packet_t pkt,
                              const odp_crypto_packet_op_param_t *param,
@@ -425,12 +466,22 @@ int internal_decrypt(EVP_CIPHER_CTX *ctx,
        return ret;
 }
 
+static void
+cipher_encrypt_init(odp_crypto_generic_session_t *session)
+{
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
+
+       EVP_EncryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
+                          session->cipher.key_data, NULL);
+       EVP_CIPHER_CTX_set_padding(ctx, 0);
+}
+
 static
 odp_crypto_alg_err_t cipher_encrypt(odp_packet_t pkt,
                                    const odp_crypto_packet_op_param_t *param,
                                    odp_crypto_generic_session_t *session)
 {
-       EVP_CIPHER_CTX *ctx;
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
        void *iv_ptr;
        int ret;
 
@@ -441,27 +492,30 @@ odp_crypto_alg_err_t cipher_encrypt(odp_packet_t pkt,
        else
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-       /* Encrypt it */
-       ctx = EVP_CIPHER_CTX_new();
-       EVP_EncryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
-                          session->cipher.key_data, NULL);
        EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
-       EVP_CIPHER_CTX_set_padding(ctx, 0);
 
        ret = internal_encrypt(ctx, pkt, param);
 
-       EVP_CIPHER_CTX_free(ctx);
-
        return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE :
                          ODP_CRYPTO_ALG_ERR_NONE;
 }
 
+static void
+cipher_decrypt_init(odp_crypto_generic_session_t *session)
+{
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
+
+       EVP_DecryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
+                          session->cipher.key_data, NULL);
+       EVP_CIPHER_CTX_set_padding(ctx, 0);
+}
+
 static
 odp_crypto_alg_err_t cipher_decrypt(odp_packet_t pkt,
                                    const odp_crypto_packet_op_param_t *param,
                                    odp_crypto_generic_session_t *session)
 {
-       EVP_CIPHER_CTX *ctx;
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
        void *iv_ptr;
        int ret;
 
@@ -472,17 +526,10 @@ odp_crypto_alg_err_t cipher_decrypt(odp_packet_t pkt,
        else
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-       /* Decrypt it */
-       ctx = EVP_CIPHER_CTX_new();
-       EVP_DecryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
-                          session->cipher.key_data, NULL);
        EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
-       EVP_CIPHER_CTX_set_padding(ctx, 0);
 
        ret = internal_decrypt(ctx, pkt, param);
 
-       EVP_CIPHER_CTX_free(ctx);
-
        return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE :
                          ODP_CRYPTO_ALG_ERR_NONE;
 }
@@ -506,20 +553,35 @@ static int 
process_cipher_param(odp_crypto_generic_session_t *session,
               session->p.cipher_key.length);
 
        /* Set function */
-       if (ODP_CRYPTO_OP_ENCODE == session->p.op)
+       if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
                session->cipher.func = cipher_encrypt;
-       else
+               session->cipher.init = cipher_encrypt_init;
+       } else {
                session->cipher.func = cipher_decrypt;
+               session->cipher.init = cipher_decrypt_init;
+       }
 
        return 0;
 }
 
+static void
+aes_gcm_encrypt_init(odp_crypto_generic_session_t *session)
+{
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
+
+       EVP_EncryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
+                          session->cipher.key_data, NULL);
+       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+                           session->p.iv.length, NULL);
+       EVP_CIPHER_CTX_set_padding(ctx, 0);
+}
+
 static
 odp_crypto_alg_err_t aes_gcm_encrypt(odp_packet_t pkt,
                                     const odp_crypto_packet_op_param_t *param,
                                     odp_crypto_generic_session_t *session)
 {
-       EVP_CIPHER_CTX *ctx;
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
        const uint8_t *aad_head = param->aad_ptr;
        uint32_t aad_len = session->p.auth_aad_len;
        void *iv_ptr;
@@ -534,14 +596,7 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_packet_t pkt,
        else
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-       /* Encrypt it */
-       ctx = EVP_CIPHER_CTX_new();
-       EVP_EncryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
-                          session->cipher.key_data, NULL);
-       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
-                           session->p.iv.length, NULL);
        EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
-       EVP_CIPHER_CTX_set_padding(ctx, 0);
 
        /* Authenticate header data (if any) without encrypting them */
        if (aad_len > 0)
@@ -555,18 +610,28 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_packet_t pkt,
        odp_packet_copy_from_mem(pkt, param->hash_result_offset,
                                 session->p.auth_digest_len, block);
 
-       EVP_CIPHER_CTX_free(ctx);
-
        return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE :
                          ODP_CRYPTO_ALG_ERR_NONE;
 }
 
+static void
+aes_gcm_decrypt_init(odp_crypto_generic_session_t *session)
+{
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
+
+       EVP_DecryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
+                          session->cipher.key_data, NULL);
+       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+                           session->p.iv.length, NULL);
+       EVP_CIPHER_CTX_set_padding(ctx, 0);
+}
+
 static
 odp_crypto_alg_err_t aes_gcm_decrypt(odp_packet_t pkt,
                                     const odp_crypto_packet_op_param_t *param,
                                     odp_crypto_generic_session_t *session)
 {
-       EVP_CIPHER_CTX *ctx;
+       EVP_CIPHER_CTX *ctx = local.cipher_ctx[session->idx];
        const uint8_t *aad_head = param->aad_ptr;
        uint32_t aad_len = session->p.auth_aad_len;
        int dummy_len = 0;
@@ -581,14 +646,7 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_packet_t pkt,
        else
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-       /* Decrypt it */
-       ctx = EVP_CIPHER_CTX_new();
-       EVP_DecryptInit_ex(ctx, session->cipher.evp_cipher, NULL,
-                          session->cipher.key_data, NULL);
-       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
-                           session->p.iv.length, NULL);
        EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
-       EVP_CIPHER_CTX_set_padding(ctx, 0);
 
        odp_packet_copy_to_mem(pkt, param->hash_result_offset,
                               session->p.auth_digest_len, block);
@@ -602,8 +660,6 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_packet_t pkt,
 
        ret = internal_decrypt(ctx, pkt, param);
 
-       EVP_CIPHER_CTX_free(ctx);
-
        return ret <= 0 ? ODP_CRYPTO_ALG_ERR_ICV_CHECK :
                          ODP_CRYPTO_ALG_ERR_NONE;
 }
@@ -622,20 +678,35 @@ static int 
process_aes_gcm_param(odp_crypto_generic_session_t *session,
        session->cipher.evp_cipher = cipher;
 
        /* Set function */
-       if (ODP_CRYPTO_OP_ENCODE == session->p.op)
+       if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
                session->cipher.func = aes_gcm_encrypt;
-       else
+               session->cipher.init = aes_gcm_encrypt_init;
+       } else {
                session->cipher.func = aes_gcm_decrypt;
+               session->cipher.init = aes_gcm_decrypt_init;
+       }
 
        return 0;
 }
 
+static void
+aes_gmac_gen_init(odp_crypto_generic_session_t *session)
+{
+       EVP_CIPHER_CTX *ctx = local.mac_cipher_ctx[session->idx];
+
+       EVP_EncryptInit_ex(ctx, session->auth.evp_cipher, NULL,
+                          session->auth.key, NULL);
+       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+                           session->p.iv.length, NULL);
+       EVP_CIPHER_CTX_set_padding(ctx, 0);
+}
+
 static
 odp_crypto_alg_err_t aes_gmac_gen(odp_packet_t pkt,
                                  const odp_crypto_packet_op_param_t *param,
                                  odp_crypto_generic_session_t *session)
 {
-       EVP_CIPHER_CTX *ctx;
+       EVP_CIPHER_CTX *ctx = local.mac_cipher_ctx[session->idx];
        void *iv_ptr;
        uint8_t block[EVP_MAX_MD_SIZE];
        int ret;
@@ -647,14 +718,7 @@ odp_crypto_alg_err_t aes_gmac_gen(odp_packet_t pkt,
        else
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-       /* Encrypt it */
-       ctx = EVP_CIPHER_CTX_new();
-       EVP_EncryptInit_ex(ctx, session->auth.evp_cipher, NULL,
-                          session->auth.key, NULL);
-       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
-                           session->p.iv.length, NULL);
        EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
-       EVP_CIPHER_CTX_set_padding(ctx, 0);
 
        ret = internal_aad(ctx, pkt, param);
 
@@ -663,18 +727,28 @@ odp_crypto_alg_err_t aes_gmac_gen(odp_packet_t pkt,
        odp_packet_copy_from_mem(pkt, param->hash_result_offset,
                                 session->p.auth_digest_len, block);
 
-       EVP_CIPHER_CTX_free(ctx);
-
        return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE :
                          ODP_CRYPTO_ALG_ERR_NONE;
 }
 
+static void
+aes_gmac_check_init(odp_crypto_generic_session_t *session)
+{
+       EVP_CIPHER_CTX *ctx = local.mac_cipher_ctx[session->idx];
+
+       EVP_DecryptInit_ex(ctx, session->auth.evp_cipher, NULL,
+                          session->auth.key, NULL);
+       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
+                           session->p.iv.length, NULL);
+       EVP_CIPHER_CTX_set_padding(ctx, 0);
+}
+
 static
 odp_crypto_alg_err_t aes_gmac_check(odp_packet_t pkt,
                                    const odp_crypto_packet_op_param_t *param,
                                    odp_crypto_generic_session_t *session)
 {
-       EVP_CIPHER_CTX *ctx;
+       EVP_CIPHER_CTX *ctx = local.mac_cipher_ctx[session->idx];
        void *iv_ptr;
        uint8_t block[EVP_MAX_MD_SIZE];
        int ret;
@@ -686,14 +760,7 @@ odp_crypto_alg_err_t aes_gmac_check(odp_packet_t pkt,
        else
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-       /* Decrypt it */
-       ctx = EVP_CIPHER_CTX_new();
-       EVP_DecryptInit_ex(ctx, session->auth.evp_cipher, NULL,
-                          session->auth.key, NULL);
-       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
-                           session->p.iv.length, NULL);
        EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
-       EVP_CIPHER_CTX_set_padding(ctx, 0);
 
        odp_packet_copy_to_mem(pkt, param->hash_result_offset,
                               session->p.auth_digest_len, block);
@@ -704,8 +771,6 @@ odp_crypto_alg_err_t aes_gmac_check(odp_packet_t pkt,
 
        ret = internal_aad(ctx, pkt, param);
 
-       EVP_CIPHER_CTX_free(ctx);
-
        return ret <= 0 ? ODP_CRYPTO_ALG_ERR_ICV_CHECK :
                          ODP_CRYPTO_ALG_ERR_NONE;
 }
@@ -724,10 +789,13 @@ static int 
process_aes_gmac_param(odp_crypto_generic_session_t *session,
        session->auth.evp_cipher = cipher;
 
        /* Set function */
-       if (ODP_CRYPTO_OP_ENCODE == session->p.op)
+       if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
                session->auth.func = aes_gmac_gen;
-       else
+               session->auth.init = aes_gmac_gen_init;
+       } else {
                session->auth.func = aes_gmac_check;
+               session->auth.init = aes_gmac_check_init;
+       }
 
        return 0;
 }
@@ -741,6 +809,7 @@ static int process_auth_param(odp_crypto_generic_session_t 
*session,
                session->auth.func = auth_gen;
        else
                session->auth.func = auth_check;
+       session->auth.init = auth_init;
 
        session->auth.evp_md = evp_md;
 
@@ -923,6 +992,7 @@ odp_crypto_session_create(odp_crypto_session_param_t *param,
        switch (param->cipher_alg) {
        case ODP_CIPHER_ALG_NULL:
                session->cipher.func = null_crypto_routine;
+               session->cipher.init = null_crypto_init_routine;
                rc = 0;
                break;
        case ODP_CIPHER_ALG_3DES_CBC:
@@ -998,6 +1068,7 @@ odp_crypto_session_create(odp_crypto_session_param_t 
*param,
        switch (param->auth_alg) {
        case ODP_AUTH_ALG_NULL:
                session->auth.func = null_crypto_routine;
+               session->auth.init = null_crypto_init_routine;
                rc = 0;
                break;
 #if ODP_DEPRECATED_API
@@ -1037,6 +1108,7 @@ odp_crypto_session_create(odp_crypto_session_param_t 
*param,
                 * cipher at the same time */
                if (param->cipher_alg == ODP_CIPHER_ALG_AES_GCM || aes_gcm) {
                        session->auth.func = null_crypto_routine;
+                       session->auth.init = null_crypto_init_routine;
                        rc = 0;
                } else {
                        rc = -1;
@@ -1216,6 +1288,49 @@ int odp_crypto_term_global(void)
        return rc;
 }
 
+int _odp_crypto_init_local(void)
+{
+       unsigned i;
+       int id;
+
+       memset(&local, 0, sizeof(local));
+
+       for (i = 0; i < MAX_SESSIONS; i++) {
+               local.hmac_ctx[i] = HMAC_CTX_new();
+               local.cipher_ctx[i] = EVP_CIPHER_CTX_new();
+               local.mac_cipher_ctx[i] = EVP_CIPHER_CTX_new();
+
+               if (local.hmac_ctx[i] == NULL ||
+                   local.cipher_ctx[i] == NULL ||
+                   local.mac_cipher_ctx[i] == NULL) {
+                       _odp_crypto_term_local();
+                       return -1;
+               }
+       }
+
+       id = odp_thread_id();
+       local.ctx_valid = global->ctx_valid[id];
+       /* No need to clear flags here, alloc_session did the job for us */
+
+       return 0;
+}
+
+int _odp_crypto_term_local(void)
+{
+       unsigned i;
+
+       for (i = 0; i < MAX_SESSIONS; i++) {
+               if (local.hmac_ctx[i] != NULL)
+                       HMAC_CTX_free(local.hmac_ctx[i]);
+               if (local.cipher_ctx[i] != NULL)
+                       EVP_CIPHER_CTX_free(local.cipher_ctx[i]);
+               if (local.mac_cipher_ctx[i] != NULL)
+                       EVP_CIPHER_CTX_free(local.mac_cipher_ctx[i]);
+       }
+
+       return 0;
+}
+
 odp_random_kind_t odp_random_max_kind(void)
 {
        return ODP_RANDOM_CRYPTO;
@@ -1385,6 +1500,8 @@ int odp_crypto_int(odp_packet_t pkt_in,
                pkt_in = ODP_PACKET_INVALID;
        }
 
+       crypto_init(session);
+
        /* Invoke the functions */
        if (session->do_cipher_first) {
                rc_cipher = session->cipher.func(out_pkt, param, session);
diff --git a/platform/linux-generic/odp_init.c 
b/platform/linux-generic/odp_init.c
index bff8303ee..bbcbd8dd3 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -327,6 +327,12 @@ int odp_init_local(odp_instance_t instance, 
odp_thread_type_t thr_type)
        }
        stage = PKTIO_INIT;
 
+       if (_odp_crypto_init_local()) {
+               ODP_ERR("ODP crypto local init failed.\n");
+               goto init_fail;
+       }
+       stage = CRYPTO_INIT;
+
        if (odp_pool_init_local()) {
                ODP_ERR("ODP pool local init failed.\n");
                goto init_fail;
@@ -379,6 +385,13 @@ int _odp_term_local(enum init_stage stage)
                }
                /* Fall through */
 
+       case CRYPTO_INIT:
+               if (_odp_crypto_term_local()) {
+                       ODP_ERR("ODP crypto local term failed.\n");
+                       rc = -1;
+               }
+               /* Fall through */
+
        case POOL_INIT:
                if (odp_pool_term_local()) {
                        ODP_ERR("ODP buffer pool local term failed.\n");

Reply via email to