Using single context for all operations is not thread safe: multiple
threads can access the same context in parallel, affecting its internal
state. Make AES-GCM functions use local context for en/decryption
operations.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsoleni...@linaro.org>
---
 .../linux-generic/include/odp_crypto_internal.h    |  2 +-
 platform/linux-generic/odp_crypto.c                | 84 ++++++++++------------
 2 files changed, 38 insertions(+), 48 deletions(-)

diff --git a/platform/linux-generic/include/odp_crypto_internal.h 
b/platform/linux-generic/include/odp_crypto_internal.h
index 515cefaa06cc..d1020dba3edd 100644
--- a/platform/linux-generic/include/odp_crypto_internal.h
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -53,7 +53,7 @@ struct odp_crypto_generic_session {
                                AES_KEY key;
                        } aes;
                        struct {
-                               EVP_CIPHER_CTX *ctx;
+                               uint8_t  key[EVP_MAX_KEY_LENGTH];
                        } aes_gcm;
                } data;
                crypto_func_t func;
diff --git a/platform/linux-generic/odp_crypto.c 
b/platform/linux-generic/odp_crypto.c
index 3f298485caef..3deec7de3f7c 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -265,11 +265,13 @@ 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;
        uint8_t *data  = odp_packet_data(param->out_pkt);
        uint32_t plain_len   = param->cipher_range.length;
        const uint8_t *aad_head = param->aad.ptr;
        uint32_t aad_len = param->aad.length;
        void *iv_ptr;
+       int cipher_len = 0;
        uint8_t *tag = data + param->hash_result_offset;
 
        if (param->override_iv_ptr)
@@ -280,12 +282,14 @@ odp_crypto_alg_err_t 
aes_gcm_encrypt(odp_crypto_op_param_t *param,
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
        /* Adjust pointer for beginning of area to cipher/auth */
-       uint8_t *plaindata = data + param->cipher_range.offset;
+       data += param->cipher_range.offset;
 
        /* Encrypt it */
-       EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
-       int cipher_len = 0;
-
+       ctx = EVP_CIPHER_CTX_new();
+       EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL,
+                          session->cipher.data.aes_gcm.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);
 
        /* Authenticate header data (if any) without encrypting them */
@@ -293,13 +297,14 @@ odp_crypto_alg_err_t 
aes_gcm_encrypt(odp_crypto_op_param_t *param,
                EVP_EncryptUpdate(ctx, NULL, &cipher_len,
                                  aad_head, aad_len);
 
-       EVP_EncryptUpdate(ctx, plaindata, &cipher_len,
-                         plaindata, plain_len);
+       EVP_EncryptUpdate(ctx, data, &cipher_len, data, plain_len);
 
-       EVP_EncryptFinal_ex(ctx, plaindata + cipher_len, &cipher_len);
+       EVP_EncryptFinal_ex(ctx, data + cipher_len, &cipher_len);
        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG,
                            session->p.auth_digest_len, tag);
 
+       EVP_CIPHER_CTX_free(ctx);
+
        return ODP_CRYPTO_ALG_ERR_NONE;
 }
 
@@ -307,10 +312,12 @@ 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;
        uint8_t *data  = odp_packet_data(param->out_pkt);
        uint32_t cipher_len   = param->cipher_range.length;
        const uint8_t *aad_head = param->aad.ptr;
        uint32_t aad_len = param->aad.length;
+       int plain_len = 0;
        void *iv_ptr;
        uint8_t *tag   = data + param->hash_result_offset;
 
@@ -322,11 +329,14 @@ odp_crypto_alg_err_t 
aes_gcm_decrypt(odp_crypto_op_param_t *param,
                return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
        /* Adjust pointer for beginning of area to cipher/auth */
-       uint8_t *cipherdata = data + param->cipher_range.offset;
-       /* Encrypt it */
-       EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
-       int plain_len = 0;
+       data += param->cipher_range.offset;
 
+       /* Decrypt it */
+       ctx = EVP_CIPHER_CTX_new();
+       EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL,
+                          session->cipher.data.aes_gcm.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_ctrl(ctx, EVP_CTRL_GCM_SET_TAG,
@@ -337,12 +347,13 @@ odp_crypto_alg_err_t 
aes_gcm_decrypt(odp_crypto_op_param_t *param,
                EVP_DecryptUpdate(ctx, NULL, &plain_len,
                                  aad_head, aad_len);
 
-       EVP_DecryptUpdate(ctx, cipherdata, &plain_len,
-                         cipherdata, cipher_len);
+       EVP_DecryptUpdate(ctx, data, &plain_len, data, cipher_len);
 
-       if (EVP_DecryptFinal_ex(ctx, cipherdata + plain_len, &plain_len) <= 0)
+       if (EVP_DecryptFinal_ex(ctx, data + plain_len, &plain_len) <= 0)
                return ODP_CRYPTO_ALG_ERR_ICV_CHECK;
 
+       EVP_CIPHER_CTX_free(ctx);
+
        return ODP_CRYPTO_ALG_ERR_NONE;
 }
 
@@ -352,27 +363,14 @@ static int 
process_aes_gcm_param(odp_crypto_generic_session_t *session)
        if (session->p.cipher_key.length != 16)
                return -1;
 
-       /* Set function */
-       EVP_CIPHER_CTX *ctx =
-               session->cipher.data.aes_gcm.ctx = EVP_CIPHER_CTX_new();
+       memcpy(session->cipher.data.aes_gcm.key, session->p.cipher_key.data,
+              session->p.cipher_key.length);
 
-       if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
+       /* Set function */
+       if (ODP_CRYPTO_OP_ENCODE == session->p.op)
                session->cipher.func = aes_gcm_encrypt;
-               EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
-       } else {
+       else
                session->cipher.func = aes_gcm_decrypt;
-               EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
-       }
-
-       EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN,
-                           session->p.iv.length, NULL);
-       if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
-               EVP_EncryptInit_ex(ctx, NULL, NULL,
-                                  session->p.cipher_key.data, NULL);
-       } else {
-               EVP_DecryptInit_ex(ctx, NULL, NULL,
-                                  session->p.cipher_key.data, NULL);
-       }
 
        return 0;
 }
@@ -635,17 +633,16 @@ odp_crypto_session_create(odp_crypto_session_param_t 
*param,
        /* Copy parameters */
        session->p = *param;
 
-       /* Copy IV data */
-       if (session->p.iv.data) {
-               if (session->p.iv.length > MAX_IV_LEN) {
-                       ODP_DBG("Maximum IV length exceeded\n");
-                       free_session(session);
-                       return -1;
-               }
+       if (session->p.iv.length > MAX_IV_LEN) {
+               ODP_DBG("Maximum IV length exceeded\n");
+               free_session(session);
+               return -1;
+       }
 
+       /* Copy IV data */
+       if (session->p.iv.data)
                memcpy(session->cipher.iv_data, session->p.iv.data,
                       session->p.iv.length);
-       }
 
        /* Derive order */
        if (ODP_CRYPTO_OP_ENCODE == param->op)
@@ -757,15 +754,8 @@ odp_crypto_session_create(odp_crypto_session_param_t 
*param,
 int odp_crypto_session_destroy(odp_crypto_session_t session)
 {
        odp_crypto_generic_session_t *generic;
-       int aes_gcm = 0;
 
        generic = (odp_crypto_generic_session_t *)(intptr_t)session;
-#if ODP_DEPRECATED_API
-       if (generic->p.cipher_alg == ODP_CIPHER_ALG_AES128_GCM)
-               aes_gcm = 1;
-#endif
-       if (generic->p.cipher_alg == ODP_CIPHER_ALG_AES_GCM || aes_gcm)
-               EVP_CIPHER_CTX_free(generic->cipher.data.aes_gcm.ctx);
        memset(generic, 0, sizeof(*generic));
        free_session(generic);
        return 0;
-- 
2.11.0

Reply via email to