linux-generic: crypto: support OpenSSL 1.1.0

Message ID 20170206214526.6926-1-dmitry.ereminsolenikov@linaro.org
State New
Headers show

Commit Message

Dmitry Eremin-Solenikov Feb. 6, 2017, 9:45 p.m.
OpenSSL 1.1.0 uses new threading API. It is no longer necessary to set
locking callbacks to use OpenSSL in a multi-threaded environment. The
old threading API should no longer be used. Separate old locking code
into separate functions that are guarded by OPENSSL_VERSION_NUMBER
check.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
 .../linux-generic/include/odp_crypto_internal.h    |  1 +
 platform/linux-generic/odp_crypto.c                | 78 ++++++++++++++++------
 2 files changed, 59 insertions(+), 20 deletions(-)

-- 
2.11.0

Comments

Bill Fischofer Feb. 6, 2017, 9:57 p.m. | #1
The problem is not what level of OpenSSL ODP might be compiled
against, but what level is installed on the system the ODP application
is running on, since we don't distribute OpenSSL with ODP. OpenSSL
v1.1.0 is backward-compatible with the older callback structure (they
become no-ops) so there's no real penalty for using them as the
init/term calls are no-ops
and the actual lock functions will never be called by OpenSSL.

So I don't see a need for this patch.

On Mon, Feb 6, 2017 at 3:45 PM, Dmitry Eremin-Solenikov
<dmitry.ereminsolenikov@linaro.org> wrote:
> OpenSSL 1.1.0 uses new threading API. It is no longer necessary to set

> locking callbacks to use OpenSSL in a multi-threaded environment. The

> old threading API should no longer be used. Separate old locking code

> into separate functions that are guarded by OPENSSL_VERSION_NUMBER

> check.

>

> Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

> ---

>  .../linux-generic/include/odp_crypto_internal.h    |  1 +

>  platform/linux-generic/odp_crypto.c                | 78 ++++++++++++++++------

>  2 files changed, 59 insertions(+), 20 deletions(-)

>

> diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h

> index c7b893aa..f85b76ea 100644

> --- a/platform/linux-generic/include/odp_crypto_internal.h

> +++ b/platform/linux-generic/include/odp_crypto_internal.h

> @@ -13,6 +13,7 @@ extern "C" {

>

>  #include <openssl/des.h>

>  #include <openssl/aes.h>

> +#include <openssl/evp.h>

>

>  #define MAX_IV_LEN      64

>  #define OP_RESULT_MAGIC 0x91919191

> diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c

> index b53b0fc1..2145c36e 100644

> --- a/platform/linux-generic/odp_crypto.c

> +++ b/platform/linux-generic/odp_crypto.c

> @@ -26,6 +26,7 @@

>  #include <openssl/rand.h>

>  #include <openssl/hmac.h>

>  #include <openssl/evp.h>

> +#include <openssl/opensslv.h>

>

>  #define MAX_SESSIONS 32

>

> @@ -64,7 +65,6 @@ typedef struct odp_crypto_global_s odp_crypto_global_t;

>

>  struct odp_crypto_global_s {

>         odp_spinlock_t                lock;

> -       odp_ticketlock_t **openssl_lock;

>         odp_crypto_generic_session_t *free;

>         odp_crypto_generic_session_t  sessions[0];

>  };

> @@ -949,35 +949,80 @@ odp_crypto_operation(odp_crypto_op_param_t *param,

>         return 0;

>  }

>

> +#if OPENSSL_VERSION_NUMBER < 0x10100000L

>  static unsigned long openssl_thread_id(void)

>  {

>         return (unsigned long)odp_thread_id();

>  }

>

> +odp_ticketlock_t *openssl_locks;

> +

>  static void openssl_lock(int mode, int n,

>                          const char *file ODP_UNUSED,

>                          int line ODP_UNUSED)

>  {

>         if (mode & CRYPTO_LOCK)

> -               odp_ticketlock_lock((odp_ticketlock_t *)

> -                                   &global->openssl_lock[n]);

> +               odp_ticketlock_lock(&openssl_locks[n]);

>         else

> -               odp_ticketlock_unlock((odp_ticketlock_t *)

> -                                     &global->openssl_lock[n]);

> +               odp_ticketlock_unlock(&openssl_locks[n]);

> +}

> +

> +static void odp_crypto_init_openssl_locks(void)

> +{

> +       int nlocks = CRYPTO_num_locks();

> +       size_t mem_size;

> +       odp_shm_t shm;

> +       int idx;

> +

> +       if (nlocks <= 0)

> +               return;

> +

> +       mem_size = nlocks * sizeof(odp_ticketlock_t);

> +

> +       /* Allocate our globally shared memory */

> +       shm = odp_shm_reserve("crypto_openssl_locks", mem_size,

> +                             ODP_CACHE_LINE_SIZE, 0);

> +

> +       openssl_locks = odp_shm_addr(shm);

> +

> +       /* Clear it out */

> +       memset(openssl_locks, 0, mem_size);

> +

> +       for (idx = 0; idx < nlocks; idx++)

> +               odp_ticketlock_init(&openssl_locks[idx]);

> +

> +       CRYPTO_set_id_callback(openssl_thread_id);

> +       CRYPTO_set_locking_callback(openssl_lock);

>  }

>

> +static int odp_crypto_term_openssl_locks(void)

> +{

> +       CRYPTO_set_locking_callback(NULL);

> +       CRYPTO_set_id_callback(NULL);

> +

> +       return odp_shm_free(odp_shm_lookup("crypto_openssl_locks"));

> +}

> +#else

> +static void odp_crypto_init_openssl_locks(void)

> +{

> +}

> +

> +static int odp_crypto_term_openssl_locks(void)

> +{

> +       return 0;

> +}

> +#endif

> +

>  int

>  odp_crypto_init_global(void)

>  {

>         size_t mem_size;

>         odp_shm_t shm;

>         int idx;

> -       int nlocks = CRYPTO_num_locks();

>

>         /* Calculate the memory size we need */

>         mem_size  = sizeof(*global);

>         mem_size += (MAX_SESSIONS * sizeof(odp_crypto_generic_session_t));

> -       mem_size += nlocks * sizeof(odp_ticketlock_t);

>

>         /* Allocate our globally shared memory */

>         shm = odp_shm_reserve("crypto_pool", mem_size,

> @@ -995,17 +1040,7 @@ odp_crypto_init_global(void)

>         }

>         odp_spinlock_init(&global->lock);

>

> -       if (nlocks > 0) {

> -               global->openssl_lock =

> -                       (odp_ticketlock_t **)&global->sessions[MAX_SESSIONS];

> -

> -               for (idx = 0; idx < nlocks; idx++)

> -                       odp_ticketlock_init((odp_ticketlock_t *)

> -                                           &global->openssl_lock[idx]);

> -

> -               CRYPTO_set_id_callback(openssl_thread_id);

> -               CRYPTO_set_locking_callback(openssl_lock);

> -       }

> +       odp_crypto_init_openssl_locks();

>

>         return 0;

>  }

> @@ -1024,8 +1059,11 @@ int odp_crypto_term_global(void)

>                 rc = -1;

>         }

>

> -       CRYPTO_set_locking_callback(NULL);

> -       CRYPTO_set_id_callback(NULL);

> +       ret = odp_crypto_term_openssl_locks();

> +       if (ret < 0) {

> +               ODP_ERR("shm free failed for crypto_openssl_locks\n");

> +               rc = -1;

> +       }

>

>         ret = odp_shm_free(odp_shm_lookup("crypto_pool"));

>         if (ret < 0) {

> --

> 2.11.0

>
Dmitry Eremin-Solenikov Feb. 6, 2017, 11:15 p.m. | #2
On 07.02.2017 00:57, Bill Fischofer wrote:
> The problem is not what level of OpenSSL ODP might be compiled

> against, but what level is installed on the system the ODP application

> is running on, since we don't distribute OpenSSL with ODP. OpenSSL

> v1.1.0 is backward-compatible with the older callback structure (they

> become no-ops) so there's no real penalty for using them as the

> init/term calls are no-ops

> and the actual lock functions will never be called by OpenSSL.


Compiler will bug out with 'function is not used' error with OpenSSL 
1.1.0 headers. There is no way to use app compiled against 1.1.0 with 
earlier library versions or vice versa, because libssl will have 
different file/so names.

-- 
With best wishes
Dmitry
Bill Fischofer Feb. 7, 2017, 12:15 a.m. | #3
On Mon, Feb 6, 2017 at 5:15 PM, Dmitry Eremin-Solenikov
<dmitry.ereminsolenikov@linaro.org> wrote:
> On 07.02.2017 00:57, Bill Fischofer wrote:

>>

>> The problem is not what level of OpenSSL ODP might be compiled

>> against, but what level is installed on the system the ODP application

>> is running on, since we don't distribute OpenSSL with ODP. OpenSSL

>> v1.1.0 is backward-compatible with the older callback structure (they

>> become no-ops) so there's no real penalty for using them as the

>> init/term calls are no-ops

>> and the actual lock functions will never be called by OpenSSL.

>

>

> Compiler will bug out with 'function is not used' error with OpenSSL 1.1.0

> headers. There is no way to use app compiled against 1.1.0 with earlier

> library versions or vice versa, because libssl will have different file/so

> names.


If that's true then OpenSSL v1.1.0 is failing the backward
compatibility it claims to provide and I'd think that would be a bug
against OpenSSL.

Until OpenSSL v1.1.0 is part of all currently supported standard
distros (Ubuntu 16.10 still uses v1.0.2g) we cannot compile ODP
against those higher levels for distribution. If you compile against
the older version then it should work against an installed copy of
v1.1.0 as noted above since v1.1.0 is backwards-compatible.

>

> --

> With best wishes

> Dmitry
Maxim Uvarov Feb. 7, 2017, 7:14 a.m. | #4
I googled this link form compatibility for versions:

https://abi-laboratory.pro/tracker/timeline/openssl/

What is function is not used error? Is it gcc or #error in includes?

I see that functions should be empty macros:

/*
 * The old locking functions have been removed completely without
compatibility
 * macros. This is because the old functions either could not properly
report
 * errors, or the returned error values were not clearly documented.
 * Replacing the locking functions with with no-ops would cause race
condition
 * issues in the affected applications. It is far better for them to fail at
 * compile time.
 * On the other hand, the locking callbacks are no longer used.
Consequently,
 * the callback management functions can be safely replaced with no-op
macros.
 */
#  define CRYPTO_num_locks()            (1)
#  define CRYPTO_set_locking_callback(func)
#  define CRYPTO_get_locking_callback()         (NULL)
#  define CRYPTO_set_add_lock_callback(func)
#  define CRYPTO_get_add_lock_callback()        (NULL)

On 7 February 2017 at 03:15, Bill Fischofer <bill.fischofer@linaro.org>
wrote:

> On Mon, Feb 6, 2017 at 5:15 PM, Dmitry Eremin-Solenikov

> <dmitry.ereminsolenikov@linaro.org> wrote:

> > On 07.02.2017 00:57, Bill Fischofer wrote:

> >>

> >> The problem is not what level of OpenSSL ODP might be compiled

> >> against, but what level is installed on the system the ODP application

> >> is running on, since we don't distribute OpenSSL with ODP. OpenSSL

> >> v1.1.0 is backward-compatible with the older callback structure (they

> >> become no-ops) so there's no real penalty for using them as the

> >> init/term calls are no-ops

> >> and the actual lock functions will never be called by OpenSSL.

> >

> >

> > Compiler will bug out with 'function is not used' error with OpenSSL

> 1.1.0

> > headers. There is no way to use app compiled against 1.1.0 with earlier

> > library versions or vice versa, because libssl will have different

> file/so

> > names.

>

> If that's true then OpenSSL v1.1.0 is failing the backward

> compatibility it claims to provide and I'd think that would be a bug

> against OpenSSL.

>

> Until OpenSSL v1.1.0 is part of all currently supported standard

> distros (Ubuntu 16.10 still uses v1.0.2g) we cannot compile ODP

> against those higher levels for distribution. If you compile against

> the older version then it should work against an installed copy of

> v1.1.0 as noted above since v1.1.0 is backwards-compatible.

>

> >

> > --

> > With best wishes

> > Dmitry

>
Dmitry Eremin-Solenikov Feb. 7, 2017, 9:21 a.m. | #5
Hello,

On 7 February 2017 at 10:14, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
> What is function is not used error? Is it gcc or #error in includes?


First error:

In file included from ./include/odp_packet_internal.h:28:0,
                 from odp_classification.c:13:
./include/odp_crypto_internal.h:55:5: error: unknown type name ‘EVP_CIPHER_CTX’
     EVP_CIPHER_CTX *ctx;
     ^~~~~~~~~~~~~~

This is fixed by including <openssl/evp.h>

Second error:

odp_crypto.c:957:13: error: ‘openssl_lock’ defined but not used
[-Werror=unused-function]
 static void openssl_lock(int mode, int n,
             ^~~~~~~~~~~~
odp_crypto.c:952:22: error: ‘openssl_thread_id’ defined but not used
[-Werror=unused-function]
 static unsigned long openssl_thread_id(void)
                      ^~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors

-- 
With best wishes
Dmitry
Maxim Uvarov Feb. 7, 2017, 3:59 p.m. | #6
On 02/07/17 12:21, Dmitry Eremin-Solenikov wrote:
> Hello,

> 

> On 7 February 2017 at 10:14, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

>> What is function is not used error? Is it gcc or #error in includes?

> 

> First error:

> 

> In file included from ./include/odp_packet_internal.h:28:0,

>                  from odp_classification.c:13:

> ./include/odp_crypto_internal.h:55:5: error: unknown type name ‘EVP_CIPHER_CTX’

>      EVP_CIPHER_CTX *ctx;

>      ^~~~~~~~~~~~~~

> 

> This is fixed by including <openssl/evp.h>

> 

> Second error:

> 

> odp_crypto.c:957:13: error: ‘openssl_lock’ defined but not used

> [-Werror=unused-function]

>  static void openssl_lock(int mode, int n,

>              ^~~~~~~~~~~~

> odp_crypto.c:952:22: error: ‘openssl_thread_id’ defined but not used

> [-Werror=unused-function]

>  static unsigned long openssl_thread_id(void)

>                       ^~~~~~~~~~~~~~~~~

> cc1: all warnings being treated as errors

> 


ok.

It's better to split this patch on 2 patches. One for dynamic init array
and other for check for odp version.

As Bill said we need some portable solution which will work with any
version of openssl. We don't know which exactly version will be so we
cover common debian, ubuntu, openembedded and etc versions.

I see that you took define from crypto.h. So portable code might be:

instead of:
+#if OPENSSL_VERSION_NUMBER < 0x10100000L

write:

if (OPENSSL_VERSION_NUMBER < 0x10100000L)
      odp_crypto_init_openssl_locks();


also it's better to avoid ifdefs from not hot code as match as possible,
changing it to local ifs. In that case compiler will check
that not used code is valid.

btw, do not name any internal functions or macros with odp_ prefix. It
stand for api functions.

Maxim.
Dmitry Eremin-Solenikov Feb. 7, 2017, 5:52 p.m. | #7
On 07.02.2017 18:59, Maxim Uvarov wrote:
> On 02/07/17 12:21, Dmitry Eremin-Solenikov wrote:

>> Hello,

>>

>> On 7 February 2017 at 10:14, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

>>> What is function is not used error? Is it gcc or #error in includes?

>>

>> First error:

>>

>> In file included from ./include/odp_packet_internal.h:28:0,

>>                  from odp_classification.c:13:

>> ./include/odp_crypto_internal.h:55:5: error: unknown type name ‘EVP_CIPHER_CTX’

>>      EVP_CIPHER_CTX *ctx;

>>      ^~~~~~~~~~~~~~

>>

>> This is fixed by including <openssl/evp.h>

>>

>> Second error:

>>

>> odp_crypto.c:957:13: error: ‘openssl_lock’ defined but not used

>> [-Werror=unused-function]

>>  static void openssl_lock(int mode, int n,

>>              ^~~~~~~~~~~~

>> odp_crypto.c:952:22: error: ‘openssl_thread_id’ defined but not used

>> [-Werror=unused-function]

>>  static unsigned long openssl_thread_id(void)

>>                       ^~~~~~~~~~~~~~~~~

>> cc1: all warnings being treated as errors

>>

>

> ok.

>

> It's better to split this patch on 2 patches. One for dynamic init array

> and other for check for odp version.

>

> As Bill said we need some portable solution which will work with any

> version of openssl. We don't know which exactly version will be so we

> cover common debian, ubuntu, openembedded and etc versions.


As I wrote previously, there is no way to have an app to be compiled 
against OpenSSL 1.0.x and running agains 1.1.y or vice versa. SONAMEs 
are different.

> I see that you took define from crypto.h. So portable code might be:

>

> instead of:

> +#if OPENSSL_VERSION_NUMBER < 0x10100000L

>

> write:

>

> if (OPENSSL_VERSION_NUMBER < 0x10100000L)

>       odp_crypto_init_openssl_locks();

>


> also it's better to avoid ifdefs from not hot code as match as possible,

> changing it to local ifs. In that case compiler will check

> that not used code is valid.


I can mark those functions with __attribute__((unused)), if you'd prefer 
that over ifdefs. Is that better from your POV?

>

> btw, do not name any internal functions or macros with odp_ prefix. It

> stand for api functions.


ack.

-- 
With best wishes
Dmitry
Maxim Uvarov Feb. 7, 2017, 6:25 p.m. | #8
On 02/07/17 20:52, Dmitry Eremin-Solenikov wrote:
> On 07.02.2017 18:59, Maxim Uvarov wrote:

>> On 02/07/17 12:21, Dmitry Eremin-Solenikov wrote:

>>> Hello,

>>>

>>> On 7 February 2017 at 10:14, Maxim Uvarov <maxim.uvarov@linaro.org>

>>> wrote:

>>>> What is function is not used error? Is it gcc or #error in includes?

>>>

>>> First error:

>>>

>>> In file included from ./include/odp_packet_internal.h:28:0,

>>>                  from odp_classification.c:13:

>>> ./include/odp_crypto_internal.h:55:5: error: unknown type name

>>> ‘EVP_CIPHER_CTX’

>>>      EVP_CIPHER_CTX *ctx;

>>>      ^~~~~~~~~~~~~~

>>>

>>> This is fixed by including <openssl/evp.h>

>>>

>>> Second error:

>>>

>>> odp_crypto.c:957:13: error: ‘openssl_lock’ defined but not used

>>> [-Werror=unused-function]

>>>  static void openssl_lock(int mode, int n,

>>>              ^~~~~~~~~~~~

>>> odp_crypto.c:952:22: error: ‘openssl_thread_id’ defined but not used

>>> [-Werror=unused-function]

>>>  static unsigned long openssl_thread_id(void)

>>>                       ^~~~~~~~~~~~~~~~~

>>> cc1: all warnings being treated as errors

>>>

>>

>> ok.

>>

>> It's better to split this patch on 2 patches. One for dynamic init array

>> and other for check for odp version.

>>

>> As Bill said we need some portable solution which will work with any

>> version of openssl. We don't know which exactly version will be so we

>> cover common debian, ubuntu, openembedded and etc versions.

> 

> As I wrote previously, there is no way to have an app to be compiled

> against OpenSSL 1.0.x and running agains 1.1.y or vice versa. SONAMEs

> are different.

> 


Ok. That is not a problem and odp package should solve correct
dependencies with their versions. Only thing we need to care is that we
compile and work for most common versions.



>> I see that you took define from crypto.h. So portable code might be:

>>

>> instead of:

>> +#if OPENSSL_VERSION_NUMBER < 0x10100000L

>>

>> write:

>>

>> if (OPENSSL_VERSION_NUMBER < 0x10100000L)

>>       odp_crypto_init_openssl_locks();

>>

> 

>> also it's better to avoid ifdefs from not hot code as match as possible,

>> changing it to local ifs. In that case compiler will check

>> that not used code is valid.

> 

> I can mark those functions with __attribute__((unused)), if you'd prefer

> that over ifdefs. Is that better from your POV?

> 


That some times used and some times not, looks like good candidate for
macro similar to kernel like:

# define __maybe_unused         __attribute__((unused))


ODP_MAYBE_UNUSED ? What do you think?

Some functions defiantly should be under ifdef.

Maxim.

>>

>> btw, do not name any internal functions or macros with odp_ prefix. It

>> stand for api functions.

> 

> ack.

>

Patch

diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h
index c7b893aa..f85b76ea 100644
--- a/platform/linux-generic/include/odp_crypto_internal.h
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -13,6 +13,7 @@  extern "C" {
 
 #include <openssl/des.h>
 #include <openssl/aes.h>
+#include <openssl/evp.h>
 
 #define MAX_IV_LEN      64
 #define OP_RESULT_MAGIC 0x91919191
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index b53b0fc1..2145c36e 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -26,6 +26,7 @@ 
 #include <openssl/rand.h>
 #include <openssl/hmac.h>
 #include <openssl/evp.h>
+#include <openssl/opensslv.h>
 
 #define MAX_SESSIONS 32
 
@@ -64,7 +65,6 @@  typedef struct odp_crypto_global_s odp_crypto_global_t;
 
 struct odp_crypto_global_s {
 	odp_spinlock_t                lock;
-	odp_ticketlock_t **openssl_lock;
 	odp_crypto_generic_session_t *free;
 	odp_crypto_generic_session_t  sessions[0];
 };
@@ -949,35 +949,80 @@  odp_crypto_operation(odp_crypto_op_param_t *param,
 	return 0;
 }
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
 static unsigned long openssl_thread_id(void)
 {
 	return (unsigned long)odp_thread_id();
 }
 
+odp_ticketlock_t *openssl_locks;
+
 static void openssl_lock(int mode, int n,
 			 const char *file ODP_UNUSED,
 			 int line ODP_UNUSED)
 {
 	if (mode & CRYPTO_LOCK)
-		odp_ticketlock_lock((odp_ticketlock_t *)
-				    &global->openssl_lock[n]);
+		odp_ticketlock_lock(&openssl_locks[n]);
 	else
-		odp_ticketlock_unlock((odp_ticketlock_t *)
-				      &global->openssl_lock[n]);
+		odp_ticketlock_unlock(&openssl_locks[n]);
+}
+
+static void odp_crypto_init_openssl_locks(void)
+{
+	int nlocks = CRYPTO_num_locks();
+	size_t mem_size;
+	odp_shm_t shm;
+	int idx;
+
+	if (nlocks <= 0)
+		return;
+
+	mem_size = nlocks * sizeof(odp_ticketlock_t);
+
+	/* Allocate our globally shared memory */
+	shm = odp_shm_reserve("crypto_openssl_locks", mem_size,
+			      ODP_CACHE_LINE_SIZE, 0);
+
+	openssl_locks = odp_shm_addr(shm);
+
+	/* Clear it out */
+	memset(openssl_locks, 0, mem_size);
+
+	for (idx = 0; idx < nlocks; idx++)
+		odp_ticketlock_init(&openssl_locks[idx]);
+
+	CRYPTO_set_id_callback(openssl_thread_id);
+	CRYPTO_set_locking_callback(openssl_lock);
 }
 
+static int odp_crypto_term_openssl_locks(void)
+{
+	CRYPTO_set_locking_callback(NULL);
+	CRYPTO_set_id_callback(NULL);
+
+	return odp_shm_free(odp_shm_lookup("crypto_openssl_locks"));
+}
+#else
+static void odp_crypto_init_openssl_locks(void)
+{
+}
+
+static int odp_crypto_term_openssl_locks(void)
+{
+	return 0;
+}
+#endif
+
 int
 odp_crypto_init_global(void)
 {
 	size_t mem_size;
 	odp_shm_t shm;
 	int idx;
-	int nlocks = CRYPTO_num_locks();
 
 	/* Calculate the memory size we need */
 	mem_size  = sizeof(*global);
 	mem_size += (MAX_SESSIONS * sizeof(odp_crypto_generic_session_t));
-	mem_size += nlocks * sizeof(odp_ticketlock_t);
 
 	/* Allocate our globally shared memory */
 	shm = odp_shm_reserve("crypto_pool", mem_size,
@@ -995,17 +1040,7 @@  odp_crypto_init_global(void)
 	}
 	odp_spinlock_init(&global->lock);
 
-	if (nlocks > 0) {
-		global->openssl_lock =
-			(odp_ticketlock_t **)&global->sessions[MAX_SESSIONS];
-
-		for (idx = 0; idx < nlocks; idx++)
-			odp_ticketlock_init((odp_ticketlock_t *)
-					    &global->openssl_lock[idx]);
-
-		CRYPTO_set_id_callback(openssl_thread_id);
-		CRYPTO_set_locking_callback(openssl_lock);
-	}
+	odp_crypto_init_openssl_locks();
 
 	return 0;
 }
@@ -1024,8 +1059,11 @@  int odp_crypto_term_global(void)
 		rc = -1;
 	}
 
-	CRYPTO_set_locking_callback(NULL);
-	CRYPTO_set_id_callback(NULL);
+	ret = odp_crypto_term_openssl_locks();
+	if (ret < 0) {
+		ODP_ERR("shm free failed for crypto_openssl_locks\n");
+		rc = -1;
+	}
 
 	ret = odp_shm_free(odp_shm_lookup("crypto_pool"));
 	if (ret < 0) {