diff --git a/platform/linux-generic/include/odp_internal.h b/platform/linux-generic/include/odp_internal.h
index fc69cd0c5..72fe1acfa 100644
--- a/platform/linux-generic/include/odp_internal.h
+++ b/platform/linux-generic/include/odp_internal.h
@@ -108,6 +108,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(void);
 int odp_timer_term_global(void);
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index 4c708931a..ce17e2bbb 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -86,6 +86,52 @@ struct odp_crypto_global_s {
 
 static odp_crypto_global_t *global;
 
+typedef struct crypto_local_t {
+	HMAC_CTX *hmac;
+	EVP_CIPHER_CTX *cipher;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	HMAC_CTX hmac_ctx;
+#endif
+} crypto_local_t;
+
+static __thread crypto_local_t local;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+int odp_crypto_init_local(void)
+{
+	local.hmac = &local.hmac_ctx;
+	HMAC_CTX_init(local.hmac);
+	local.cipher = EVP_CIPHER_CTX_new();
+
+	return ((local.hmac == NULL) || (local.cipher == NULL)) ? -1 : 0;
+}
+
+#define HMAC_CTX_reset(ctx) HMAC_CTX_cleanup(ctx)
+
+int odp_crypto_term_local(void)
+{
+	EVP_CIPHER_CTX_free(local.cipher);
+
+	return 0;
+}
+#else
+int odp_crypto_init_local(void)
+{
+	local.hmac = HMAC_CTX_new();
+	local.cipher = EVP_CIPHER_CTX_new();
+
+	return ((local.hmac == NULL) || (local.cipher == NULL)) ? -1 : 0;
+}
+
+int odp_crypto_term_local(void)
+{
+	HMAC_CTX_free(local.hmac);
+	EVP_CIPHER_CTX_free(local.cipher);
+
+	return 0;
+}
+#endif
+
 static
 odp_crypto_generic_op_result_t *get_op_result_from_event(odp_event_t ev)
 {
@@ -157,33 +203,15 @@ void packet_hmac_calculate(HMAC_CTX *ctx,
 	HMAC_Final(ctx, hash, NULL);
 }
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L
-static
-void packet_hmac(odp_crypto_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, param, session, hash);
-	HMAC_CTX_cleanup(&ctx);
-}
-#else
 static
 void packet_hmac(odp_crypto_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, param, session, hash);
-	HMAC_CTX_free(ctx);
+	packet_hmac_calculate(local.hmac, param, session, hash);
+	HMAC_CTX_reset(local.hmac);
 }
-#endif
 
 static
 odp_crypto_alg_err_t auth_gen(odp_crypto_op_param_t *param,
@@ -347,7 +375,7 @@ static
 odp_crypto_alg_err_t cipher_encrypt(odp_crypto_op_param_t *param,
 				    odp_crypto_generic_session_t *session)
 {
-	EVP_CIPHER_CTX *ctx;
+	EVP_CIPHER_CTX *ctx = local.cipher;
 	void *iv_ptr;
 	int ret;
 
@@ -359,7 +387,6 @@ odp_crypto_alg_err_t cipher_encrypt(odp_crypto_op_param_t *param,
 		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);
@@ -367,8 +394,6 @@ odp_crypto_alg_err_t cipher_encrypt(odp_crypto_op_param_t *param,
 
 	ret = internal_encrypt(ctx, param);
 
-	EVP_CIPHER_CTX_free(ctx);
-
 	return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE :
 			  ODP_CRYPTO_ALG_ERR_NONE;
 }
@@ -377,7 +402,7 @@ static
 odp_crypto_alg_err_t cipher_decrypt(odp_crypto_op_param_t *param,
 				    odp_crypto_generic_session_t *session)
 {
-	EVP_CIPHER_CTX *ctx;
+	EVP_CIPHER_CTX *ctx = local.cipher;
 	void *iv_ptr;
 	int ret;
 
@@ -389,7 +414,6 @@ odp_crypto_alg_err_t cipher_decrypt(odp_crypto_op_param_t *param,
 		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);
@@ -397,8 +421,6 @@ odp_crypto_alg_err_t cipher_decrypt(odp_crypto_op_param_t *param,
 
 	ret = internal_decrypt(ctx, param);
 
-	EVP_CIPHER_CTX_free(ctx);
-
 	return ret <= 0 ? ODP_CRYPTO_ALG_ERR_DATA_SIZE :
 			  ODP_CRYPTO_ALG_ERR_NONE;
 }
@@ -434,7 +456,7 @@ static
 odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param,
 				     odp_crypto_generic_session_t *session)
 {
-	EVP_CIPHER_CTX *ctx;
+	EVP_CIPHER_CTX *ctx = local.cipher;
 	const uint8_t *aad_head = param->aad.ptr;
 	uint32_t aad_len = param->aad.length;
 	void *iv_ptr;
@@ -450,7 +472,6 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param,
 		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,
@@ -470,8 +491,6 @@ odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param,
 	odp_packet_copy_from_mem(param->out_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;
 }
@@ -480,7 +499,7 @@ static
 odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param,
 				     odp_crypto_generic_session_t *session)
 {
-	EVP_CIPHER_CTX *ctx;
+	EVP_CIPHER_CTX *ctx = local.cipher;
 	const uint8_t *aad_head = param->aad.ptr;
 	uint32_t aad_len = param->aad.length;
 	int dummy_len = 0;
@@ -496,7 +515,6 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param,
 		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,
@@ -516,8 +534,6 @@ odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param,
 
 	ret = internal_decrypt(ctx, param);
 
-	EVP_CIPHER_CTX_free(ctx);
-
 	return ret <= 0 ? ODP_CRYPTO_ALG_ERR_ICV_CHECK :
 			  ODP_CRYPTO_ALG_ERR_NONE;
 }
diff --git a/platform/linux-generic/odp_init.c b/platform/linux-generic/odp_init.c
index fe03709b7..809769187 100644
--- a/platform/linux-generic/odp_init.c
+++ b/platform/linux-generic/odp_init.c
@@ -300,6 +300,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;
@@ -352,6 +358,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");
