diff --git a/.gitignore b/.gitignore
index 1230c18..088a728 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1 @@
-SOURCES/opencryptoki-3.16.0.tar.gz
+SOURCES/opencryptoki-3.17.0.tar.gz
diff --git a/.opencryptoki.metadata b/.opencryptoki.metadata
index 9c6b848..1ece19c 100644
--- a/.opencryptoki.metadata
+++ b/.opencryptoki.metadata
@@ -1 +1 @@
-e5d8cf8df446a9bdcb3658a8f191f5a31d3a751e SOURCES/opencryptoki-3.16.0.tar.gz
+598f43d2a04a878a4577f143251f4631625ac49b SOURCES/opencryptoki-3.17.0.tar.gz
diff --git a/SOURCES/opencryptoki-3.16.0-19f56d12b302b87e1dacf613cc61a063ad209d15.patch b/SOURCES/opencryptoki-3.16.0-19f56d12b302b87e1dacf613cc61a063ad209d15.patch
deleted file mode 100644
index e7872d6..0000000
--- a/SOURCES/opencryptoki-3.16.0-19f56d12b302b87e1dacf613cc61a063ad209d15.patch
+++ /dev/null
@@ -1,136 +0,0 @@
-commit 19f56d12b302b87e1dacf613cc61a063ad209d15
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Fri Feb 12 15:57:20 2021 +0100
-
-    Fix compile warning when compiling pkcsslotd with -DDEV and/or -DTHREADED
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/sbin/pkcsslotd/garbage_linux.c b/usr/sbin/pkcsslotd/garbage_linux.c
-index d4878c3b..a4dd9713 100644
---- a/usr/sbin/pkcsslotd/garbage_linux.c
-+++ b/usr/sbin/pkcsslotd/garbage_linux.c
-@@ -15,6 +15,7 @@
- #include <string.h>
- #include <sys/types.h>
- #include <fcntl.h>
-+#include <stdlib.h>
- 
- #include "log.h"
- #include "slotmgr.h"
-@@ -80,8 +81,8 @@ BOOL StartGCThread(Slot_Mgr_Shr_t *MemPtr)
- #ifdef DEV
-     // Only development builds
-     LogLog("StartGCThread: garbage collection thread started as ID "
--           "%d (%#x) by ID %d (%#x)",
--           GCThread, GCThread, pthread_self(), pthread_self());
-+           "%lu by ID %lu",
-+           GCThread, pthread_self());
- #endif
- 
-     return TRUE;
-@@ -115,8 +116,8 @@ BOOL StopGCThread(void *Ptr)
-         return FALSE;
-     }
- 
--    DbgLog(DL0, "StopGCThread: tid %d is stopping the garbage collection "
--           "thread (tid %d)",
-+    DbgLog(DL0, "StopGCThread: tid %lu is stopping the garbage collection "
-+           "thread (tid %lu)",
-            pthread_self(), GCThread);
- 
-     /* Cause the GC thread to be cancelled */
-@@ -245,7 +246,7 @@ void GCCancel(void *Ptr)
-     UNUSED(Ptr);
- 
-     /* Yeah, yeah.  Doesn't do anything, but I had plans */
--    DbgLog(DL3, "GCCancel: tid: %d running cleanup routine", pthread_self());
-+    DbgLog(DL3, "GCCancel: tid: %lu running cleanup routine", pthread_self());
- 
-     return;
- }
-@@ -268,7 +269,7 @@ BOOL CheckForGarbage(Slot_Mgr_Shr_t *MemPtr)
- 
-     ASSERT(MemPtr != NULL_PTR);
- #ifdef DEV
--    DbgLog(DL5, "Thread %d is checking for garbage", pthread_self());
-+    DbgLog(DL5, "Thread %lu is checking for garbage", pthread_self());
- #endif                          /* DEV */
- 
- 
-@@ -326,9 +327,9 @@ BOOL CheckForGarbage(Slot_Mgr_Shr_t *MemPtr)
-                 if (*pProcSessions > 0) {
- 
- #ifdef DEV
--                    DbgLog(DL2, "GC: Invalid pid (%d) is holding %d sessions "
-+                    DbgLog(DL2, "GC: Invalid pid (%d) is holding %u sessions "
-                            "open on slot %d.  Global session count for this "
--                           "slot is %d",
-+                           "slot is %u",
-                            pProc->proc_id, *pProcSessions, SlotIndex,
-                            *pGlobalSessions);
- #endif                          /* DEV */
-@@ -338,9 +339,9 @@ BOOL CheckForGarbage(Slot_Mgr_Shr_t *MemPtr)
-                         WarnLog("Garbage Collection: Illegal values in table "
-                                 "for defunct process");
-                         DbgLog(DL0, "Garbage collection: A process "
--                               "( Index: %d, pid: %d ) showed %d sessions "
--                               "open on slot %s, but the global count for this "
--                               "slot is only %d",
-+                               "( Index: %d, pid: %d ) showed %u sessions "
-+                               "open on slot %d, but the global count for this "
-+                               "slot is only %u",
-                                ProcIndex, pProc->proc_id, *pProcSessions,
-                                SlotIndex, *pGlobalSessions);
- #endif                          /* DEV */
-@@ -395,14 +396,8 @@ int Stat2Proc(int pid, proc_t *p)
-     char fbuf[800];         // about 40 fields, 64-bit decimal is about 20 chars
-     char *tmp;
-     int fd, num;
--    //  FILE *fp;
--
--    //  sprintf(buf, "%s/%d/stat", PROC_BASE, pid);
--    //  if( (fp = fopen(buf, "r")) == NULL )
--    //    return FALSE;
- 
-     sprintf(fbuf, "%s/%d/stat", PROC_BASE, pid);
--    printf("Buff = %s \n", fbuf);
-     fflush(stdout);
-     if ((fd = open(fbuf, O_RDONLY, 0)) == -1)
-         return FALSE;
-diff --git a/usr/sbin/pkcsslotd/log.c b/usr/sbin/pkcsslotd/log.c
-index 0214f952..0394cc7d 100644
---- a/usr/sbin/pkcsslotd/log.c
-+++ b/usr/sbin/pkcsslotd/log.c
-@@ -463,8 +463,8 @@ BOOL PKCS_Log(pLogHandle phLog, char *fmt, va_list ap)
- #endif                          /* DEV */
- 
-         if (WriteNow) {
--            fprintf(stderr, "%s[%d.%d]: %s\n", pInfo->Descrip, getpid(),
--                    (int) pthread_self(), buf);
-+            fprintf(stderr, "%s[%d.%lu]: %s\n", pInfo->Descrip, getpid(),
-+                    pthread_self(), buf);
-         }
-     }
- 
-@@ -482,7 +482,7 @@ BOOL PKCS_Log(pLogHandle phLog, char *fmt, va_list ap)
-             GetCurrentTimeString(timebuf);
- 
-             /* Date/Time stamp, descrip, Error message */
--            fprintf(fd, "%s %s[%d.%d]: ", timebuf, pInfo->Descrip, getpid(),
-+            fprintf(fd, "%s %s[%d.%lu]: ", timebuf, pInfo->Descrip, getpid(),
-                     pthread_self());
-             fprintf(fd, "%s\n", buf);
-             fflush(fd);
-diff --git a/usr/sbin/pkcsslotd/slotmgr.c b/usr/sbin/pkcsslotd/slotmgr.c
-index 94288f13..efbfe8fd 100644
---- a/usr/sbin/pkcsslotd/slotmgr.c
-+++ b/usr/sbin/pkcsslotd/slotmgr.c
-@@ -660,7 +660,6 @@ int main(int argc, char *argv[], char *envp[])
-      */
- 
- #if !defined(NOGARBAGE)
--    printf("Start garbage \n");
-     /* start garbage collection thread */
-     if (!StartGCThread(shmp)) {
-         term_socket_server();
diff --git a/SOURCES/opencryptoki-3.16.0-1fdd0e4497b0078e73e0004e3492db647c7c458b.patch b/SOURCES/opencryptoki-3.16.0-1fdd0e4497b0078e73e0004e3492db647c7c458b.patch
deleted file mode 100644
index 264f27d..0000000
--- a/SOURCES/opencryptoki-3.16.0-1fdd0e4497b0078e73e0004e3492db647c7c458b.patch
+++ /dev/null
@@ -1,2304 +0,0 @@
-commit 1fdd0e4497b0078e73e0004e3492db647c7c458b
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Feb 24 15:47:05 2021 +0100
-
-    EP11: Handle APQN events to update APQN version, CP infos and target
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
-index 52f95d7a..728fedd5 100644
---- a/usr/lib/ep11_stdll/ep11_specific.c
-+++ b/usr/lib/ep11_stdll/ep11_specific.c
-@@ -38,6 +38,7 @@
- #include "ock_syslog.h"
- #include "ec_defs.h"
- #include "p11util.h"
-+#include "events.h"
- 
- #include <sys/types.h>
- #include <sys/stat.h>
-@@ -197,19 +198,27 @@ typedef struct {
- 
- #define MAX_RETRY_COUNT 100
- 
--#define RETRY_START             do {                                     \
-+#define RETRY_START(rc, tokdata)                                         \
-+                                do {                                     \
-                                     int retry_count;                     \
-+                                    ep11_target_info_t* target_info =    \
-+                                             get_target_info((tokdata)); \
-+                                    if (target_info == NULL)             \
-+                                        (rc) = CKR_FUNCTION_FAILED;      \
-                                     for(retry_count = 0;                 \
-+                                        target_info != NULL &&           \
-                                         retry_count < MAX_RETRY_COUNT;   \
-                                         retry_count ++) {
- 
- #define RETRY_END(rc, tokdata, session)  if ((rc) != CKR_SESSION_CLOSED) \
-                                              break;                      \
-                                          (rc) = ep11tok_relogin_session( \
--                                                      tokdata, session); \
-+                                                  (tokdata), (session)); \
-                                          if ((rc) != CKR_OK)             \
-                                              break;                      \
-                                     }                                    \
-+                                    put_target_info((tokdata),           \
-+                                                    target_info);        \
-                                 } while (0);
- 
- #define CKF_EP11_HELPER_SESSION      0x80000000
-@@ -248,7 +257,6 @@ typedef struct ep11_card_version {
- } ep11_card_version_t;
- 
- static CK_RV ep11tok_get_ep11_library_version(CK_VERSION *lib_version);
--static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata);
- static void free_card_versions(ep11_card_version_t *card_version);
- static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
-                               const CK_VERSION *ep11_lib_version,
-@@ -476,16 +484,23 @@ static CK_RV handle_all_ep11_cards(ep11_target_t * ep11_targets,
- #define PKEY_MODE_ENABLE4NONEXTR    2
- 
- typedef struct {
-+    volatile unsigned long ref_count;
-     target_t target;
-+    ep11_card_version_t *card_versions;
-+    CK_ULONG used_firmware_API_version;
-+    unsigned char control_points[XCP_CP_BYTES];
-+    size_t control_points_len;
-+    size_t max_control_point_index;
-+    CK_CHAR serialNumber[16];
-+} ep11_target_info_t;
-+
-+typedef struct {
-     ep11_target_t target_list;
-     CK_BYTE raw2key_wrap_blob[MAX_BLOBSIZE];
-     size_t raw2key_wrap_blob_l;
-     int cka_sensitive_default_true;
-     char cp_filter_config_filename[PATH_MAX];
-     cp_config_t *cp_config;
--    unsigned char control_points[XCP_CP_BYTES];
--    size_t control_points_len;
--    size_t max_control_point_index;
-     int strict_mode;
-     int vhsm_mode;
-     int optimize_single_ops;
-@@ -497,12 +512,14 @@ typedef struct {
-     char digest_libica_path[PATH_MAX];
-     libica_t libica;
-     CK_VERSION ep11_lib_version;
--    ep11_card_version_t *card_versions;
--    CK_ULONG used_firmware_API_version;
--    CK_CHAR serialNumber[16];
-+    volatile ep11_target_info_t *target_info;
-+    pthread_rwlock_t target_rwlock;
- } ep11_private_data_t;
- 
--static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata);
-+static ep11_target_info_t *get_target_info(STDLL_TokData_t *tokdata);
-+static void put_target_info(STDLL_TokData_t *tokdata,
-+                            ep11_target_info_t *target_info);
-+static CK_RV refresh_target_info(STDLL_TokData_t *tokdata);
- 
- static CK_RV get_ep11_target_for_apqn(uint_32 adapter, uint_32 domain,
-                                       target_t *target, uint64_t flags);
-@@ -704,8 +721,13 @@ static CK_RV ep11tok_pkey_get_firmware_mk_vp(STDLL_TokData_t *tokdata)
-     CK_BYTE blob[MAX_BLOBSIZE];
-     size_t blobsize = sizeof(blob);
-     CK_ATTRIBUTE *pkey_attr = NULL, *blob_attr=NULL;
-+    ep11_target_info_t* target_info;
-     CK_RV ret;
- 
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-     /* Check if CPACF_WRAP mech supported */
-     if (ep11tok_is_mechanism_supported(tokdata, CKM_IBM_CPACF_WRAP) != CKR_OK) {
-         TRACE_INFO("CKM_IBM_CPACF_WRAP not supported on this system.\n");
-@@ -717,7 +739,7 @@ static CK_RV ep11tok_pkey_get_firmware_mk_vp(STDLL_TokData_t *tokdata)
- 
-     /* Create an AES testkey with CKA_IBM_PROTKEY_EXTRACTABLE */
-     ret = dll_m_GenerateKey(&mech, tmpl, tmpl_len, NULL, 0,
--                            blob, &blobsize, csum, &csum_l, ep11_data->target);
-+                            blob, &blobsize, csum, &csum_l, target_info->target);
-     if (ret != CKR_OK) {
-         TRACE_ERROR("dll_m_GenerateKey failed with rc=0x%lx\n",ret);
-         goto done;
-@@ -749,6 +771,8 @@ done:
-     if (blob_attr)
-         free(blob_attr);
- 
-+    put_target_info(tokdata, target_info);
-+
-     return ret;
- }
- 
-@@ -1337,7 +1361,7 @@ static CK_RV ab_unwrap_update_template(STDLL_TokData_t * tokdata,
-                                        OBJECT *obj,
-                                        CK_KEY_TYPE keytype)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-+    ep11_target_info_t* target_info;
-     CK_RV rc;
-     CK_BBOOL trusted, encrypt, decrypt, wrap, unwrap, sign, sign_recover,
-              verify, verify_recover, derive, extractable, local,
-@@ -1367,9 +1391,16 @@ static CK_RV ab_unwrap_update_template(STDLL_TokData_t * tokdata,
-     CK_ATTRIBUTE *attr;
-     CK_BBOOL cktrue = TRUE;
- 
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-     rc = dll_m_GetAttributeValue(blob, blob_len, attrs,
-                                  sizeof(attrs) / sizeof(CK_ATTRIBUTE),
--                                 ep11_data->target);
-+                                 target_info->target);
-+
-+    put_target_info(tokdata, target_info);
-+
-     if (rc != CKR_OK) {
-         TRACE_ERROR("Retrieving attributes from AB unwrapped key failed, rc=0x%lx\n",
-                     rc);
-@@ -2117,10 +2148,10 @@ static CK_RV rawkey_2_blob(STDLL_TokData_t * tokdata, SESSION * sess,
-      * calls the ep11 lib (which in turns sends the request to the card),
-      * all m_ function are ep11 functions
-      */
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
-                                  ep11_data->raw2key_wrap_blob_l, &mech, key,
--                                 ksize, cipher, &clen, ep11_data->target);
-+                                 ksize, cipher, &clen, target_info->target);
-     RETRY_END(rc, tokdata, sess)
- 
-     if (rc != CKR_OK) {
-@@ -2146,12 +2177,12 @@ static CK_RV rawkey_2_blob(STDLL_TokData_t * tokdata, SESSION * sess,
-     /* the encrypted key is decrypted and a blob is build,
-      * card accepts only blobs as keys
-      */
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_UnwrapKey(cipher, clen, ep11_data->raw2key_wrap_blob,
-                              ep11_data->raw2key_wrap_blob_l, NULL, ~0,
-                              ep11_pin_blob, ep11_pin_blob_len, &mech,
-                              new_p_attrs, new_attrs_len, blob, blen, csum,
--                             &cslen, ep11_data->target);
-+                             &cslen, target_info->target);
-     RETRY_END(rc, tokdata, sess)
- 
-     if (rc != CKR_OK) {
-@@ -2194,14 +2225,20 @@ rawkey_2_blob_end:
- CK_RV token_specific_rng(STDLL_TokData_t * tokdata, CK_BYTE * output,
-                          CK_ULONG bytes)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
--    CK_RV rc = dll_m_GenerateRandom(output, bytes, ep11_data->target);
-+    CK_RV rc = dll_m_GenerateRandom(output, bytes, target_info->target);
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, NULL);
-         TRACE_ERROR("%s output=%p bytes=%lu rc=0x%lx\n",
-                     __func__, (void *)output, bytes, rc);
-     }
-+
-+    put_target_info(tokdata, target_info);
-     return rc;
- }
- 
-@@ -2215,6 +2252,7 @@ static CK_RV make_wrapblob(STDLL_TokData_t * tokdata, CK_ATTRIBUTE * tmpl_in,
- {
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_MECHANISM mech = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
-+    ep11_target_info_t* target_info;
-     CK_BYTE csum[MAX_CSUMSIZE];
-     size_t csum_l = sizeof(csum);
-     CK_RV rc;
-@@ -2225,11 +2263,15 @@ static CK_RV make_wrapblob(STDLL_TokData_t * tokdata, CK_ATTRIBUTE * tmpl_in,
-         return CKR_OK;
-     }
- 
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-     ep11_data->raw2key_wrap_blob_l = sizeof(ep11_data->raw2key_wrap_blob);
-     rc = dll_m_GenerateKey(&mech, tmpl_in, tmpl_len, NULL, 0,
-                            ep11_data->raw2key_wrap_blob,
-                            &ep11_data->raw2key_wrap_blob_l, csum, &csum_l,
--                           ep11_data->target);
-+                           target_info->target);
- 
- 
-     if (rc != CKR_OK) {
-@@ -2240,6 +2282,7 @@ static CK_RV make_wrapblob(STDLL_TokData_t * tokdata, CK_ATTRIBUTE * tmpl_in,
-                    __func__, ep11_data->raw2key_wrap_blob_l, rc);
-     }
- 
-+    put_target_info(tokdata, target_info);
-     return rc;
- }
- 
-@@ -2479,6 +2522,14 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
-     if (ep11_data == NULL)
-         return CKR_HOST_MEMORY;
- 
-+    if (pthread_rwlock_init(&ep11_data->target_rwlock, NULL) != 0) {
-+        TRACE_DEVEL("Target Lock init failed.\n");
-+        OCK_SYSLOG(LOG_ERR, "%s: Failed to initialize the target lock\n",
-+                   __func__);
-+        rc = CKR_CANT_LOCK;
-+        goto error;
-+    }
-+
-     tokdata->private_data = ep11_data;
- 
-     /* read ep11 specific config file with user specified
-@@ -2513,13 +2564,28 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
-     }
- #endif
- 
--    rc = ep11tok_get_ep11_version(tokdata);
--    if (rc != CKR_OK)
-+    rc = ep11tok_get_ep11_library_version(&ep11_data->ep11_lib_version);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s Failed to get the Ep11 library version "
-+                    "(ep11tok_get_ep11_library_version rc=0x%lx)\n", __func__,
-+                    rc);
-+        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the EP11 library version "
-+                   "rc=0x%lx\n", __func__, rc);
-         goto error;
-+    }
- 
--    rc = ep11tok_setup_target(tokdata);
--    if (rc != CKR_OK)
-+    TRACE_INFO("%s Host library version: %d.%d\n", __func__,
-+               ep11_data->ep11_lib_version.major,
-+               ep11_data->ep11_lib_version.minor);
-+
-+    rc = refresh_target_info(tokdata);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s Failed to get the target info (refresh_target_info "
-+                    "rc=0x%lx)\n", __func__, rc);
-+        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the target info rc=0x%lx\n",
-+                   __func__, rc);
-         goto error;
-+    }
- 
-     if (ep11_data->digest_libica) {
-         rc = ep11tok_load_libica(tokdata);
-@@ -2530,18 +2596,6 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
-     ep11_data->msa_level = get_msa_level();
-     TRACE_INFO("MSA level = %i\n", ep11_data->msa_level);
- 
--    ep11_data->control_points_len = sizeof(ep11_data->control_points);
--    rc = get_control_points(tokdata, ep11_data->control_points,
--                            &ep11_data->control_points_len,
--                            &ep11_data->max_control_point_index);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("%s Failed to get the control points (get_control_points "
--                    "rc=0x%lx)\n", __func__, rc);
--        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the control points rc=0x%lx\n",
--                   __func__, rc);
--        goto error;
--    }
--
-     /* create an AES key needed for importing keys
-      * (encrypt by wrap_key and m_UnwrapKey by wrap key)
-      */
-@@ -2600,10 +2654,14 @@ CK_RV ep11tok_final(STDLL_TokData_t * tokdata)
-     TRACE_INFO("ep11 %s running\n", __func__);
- 
-     if (ep11_data != NULL) {
--        if (dll_m_rm_module != NULL)
--            dll_m_rm_module(NULL, ep11_data->target);
-+        if (ep11_data->target_info != NULL) {
-+            if (dll_m_rm_module != NULL)
-+                dll_m_rm_module(NULL, ep11_data->target_info->target);
-+            free_card_versions(ep11_data->target_info->card_versions);
-+            free((void* )ep11_data->target_info);
-+        }
-+        pthread_rwlock_destroy(&ep11_data->target_rwlock);
-         free_cp_config(ep11_data->cp_config);
--        free_card_versions(ep11_data->card_versions);
-         free(ep11_data);
-         tokdata->private_data = NULL;
-     }
-@@ -2619,7 +2677,6 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION * sess,
-                              CK_BYTE *spki, CK_ULONG spki_len,
-                              CK_BYTE *maced_spki, CK_ULONG *maced_spki_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     unsigned char *ep11_pin_blob = NULL;
-     CK_ULONG ep11_pin_blob_len = 0;
-     ep11_session_t *ep11_session = (ep11_session_t *) sess->private_data;
-@@ -2712,11 +2769,11 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION * sess,
-     ep11_get_pin_blob(ep11_session, object_is_session_object(pub_key_obj),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_UnwrapKey(spki, spki_len, NULL, 0, NULL, 0,
-                              ep11_pin_blob, ep11_pin_blob_len, &mech,
-                              p_attrs, attrs_len, maced_spki, maced_spki_len,
--                             csum, &cslen, ep11_data->target);
-+                             csum, &cslen, target_info->target);
-     RETRY_END(rc, tokdata, sess)
- 
-     if (rc != CKR_OK) {
-@@ -2870,11 +2927,11 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* encrypt */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
-                                      ep11_data->raw2key_wrap_blob_l, &mech_w,
-                                      data, data_len, cipher, &cipher_l,
--                                     ep11_data->target);
-+                                     target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
-@@ -2901,12 +2958,12 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         /* calls the card, it decrypts the private RSA key,
-          * reads its BER format and builds a blob.
-          */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob,
-                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
-                                  ep11_pin_blob, ep11_pin_blob_len, &mech_w,
-                                  new_p_attrs, new_attrs_len, blob, blob_size,
--                                 csum, &cslen, ep11_data->target);
-+                                 csum, &cslen, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         if (rc != CKR_OK) {
-@@ -3101,11 +3158,11 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* encrypt */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
-                                      ep11_data->raw2key_wrap_blob_l,
-                                      &mech_w, data, data_len,
--                                     cipher, &cipher_l, ep11_data->target);
-+                                     cipher, &cipher_l, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
-@@ -3133,14 +3190,14 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         /* calls the card, it decrypts the private EC key,
-          * reads its BER format and builds a blob.
-          */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_UnwrapKey(cipher, cipher_l,
-                                  ep11_data->raw2key_wrap_blob,
-                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
-                                  ep11_pin_blob,
-                                  ep11_pin_blob_len, &mech_w,
-                                  new_p_attrs, new_attrs_len, blob,
--                                 blob_size, csum, &cslen, ep11_data->target);
-+                                 blob_size, csum, &cslen, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         if (rc != CKR_OK) {
-@@ -3295,11 +3352,11 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* encrypt */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
-                                      ep11_data->raw2key_wrap_blob_l,
-                                      &mech_w, data, data_len,
--                                     cipher, &cipher_l, ep11_data->target);
-+                                     cipher, &cipher_l, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
- 
-@@ -3327,14 +3384,14 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         /* calls the card, it decrypts the private EC key,
-          * reads its BER format and builds a blob.
-          */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_UnwrapKey(cipher, cipher_l,
-                                  ep11_data->raw2key_wrap_blob,
-                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
-                                  ep11_pin_blob,
-                                  ep11_pin_blob_len, &mech_w,
-                                  new_p_attrs, new_attrs_len, blob,
--                                 blob_size, csum, &cslen, ep11_data->target);
-+                                 blob_size, csum, &cslen, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         if (rc != CKR_OK) {
-@@ -3478,11 +3535,11 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* encrypt */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
-                                      ep11_data->raw2key_wrap_blob_l,
-                                      &mech_w, data, data_len,
--                                     cipher, &cipher_l, ep11_data->target);
-+                                     cipher, &cipher_l, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
-@@ -3509,14 +3566,14 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         /* calls the card, it decrypts the private EC key,
-          * reads its BER format and builds a blob.
-          */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_UnwrapKey(cipher, cipher_l,
-                                  ep11_data->raw2key_wrap_blob,
-                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
-                                  ep11_pin_blob,
-                                  ep11_pin_blob_len, &mech_w,
-                                  new_p_attrs, new_attrs_len, blob,
--                                 blob_size, csum, &cslen, ep11_data->target);
-+                                 blob_size, csum, &cslen, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         if (rc != CKR_OK) {
-@@ -3666,11 +3723,11 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* encrypt */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
-                                      ep11_data->raw2key_wrap_blob_l,
-                                      &mech_w, data, data_len,
--                                     cipher, &cipher_l, ep11_data->target);
-+                                     cipher, &cipher_l, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
-@@ -3699,14 +3756,14 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
-         /* calls the card, it decrypts the private Dilithium key,
-          * reads its BER format and builds a blob.
-          */
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_UnwrapKey(cipher, cipher_l,
-                                  ep11_data->raw2key_wrap_blob,
-                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
-                                  ep11_pin_blob,
-                                  ep11_pin_blob_len, &mech_w,
-                                  new_p_attrs, new_attrs_len, blob,
--                                 blob_size, csum, &cslen, ep11_data->target);
-+                                 blob_size, csum, &cslen, target_info->target);
-         RETRY_END(rc, tokdata, sess)
- 
-         if (rc != CKR_OK) {
-@@ -3884,7 +3941,6 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session,
-                            CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs,
-                            CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_BYTE blob[MAX_BLOBSIZE];
-     size_t blobsize = sizeof(blob);
-     CK_BYTE csum[MAX_CSUMSIZE];
-@@ -3936,10 +3992,10 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session,
-     ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_GenerateKey(mech, new_attrs2, new_attrs2_len, ep11_pin_blob,
-                                ep11_pin_blob_len, blob, &blobsize,
--                               csum, &csum_len, ep11_data->target);
-+                               csum, &csum_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4354,6 +4410,7 @@ CK_RV token_specific_sha_init(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-     size_t state_len = MAX(MAX_DIGEST_STATE_BYTES, sizeof(libica_sha_context_t));
-     CK_BYTE *state;
-     libica_sha_context_t *libica_ctx;
-+    ep11_target_info_t* target_info;
- 
-     state = calloc(state_len, 1); /* freed by dig_mgr.c */
-     if (!state) {
-@@ -4361,15 +4418,21 @@ CK_RV token_specific_sha_init(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-         return CKR_HOST_MEMORY;
-     }
- 
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-     if (ep11tok_libica_digest_available(ep11_data, mech->mechanism)) {
-         libica_ctx = (libica_sha_context_t *)state;
-         state_len = sizeof(libica_sha_context_t);
-         libica_ctx->first = CK_TRUE;
-         rc = get_sha_block_size(mech->mechanism, &libica_ctx->block_size);
-     } else {
--        rc = dll_m_DigestInit(state, &state_len, mech, ep11_data->target);
-+        rc = dll_m_DigestInit(state, &state_len, mech, target_info->target);
-     }
- 
-+    put_target_info(tokdata, target_info);
-+
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, NULL);
-         TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
-@@ -4399,6 +4462,11 @@ CK_RV token_specific_sha(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
- {
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
-     if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) {
-         rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism,
-@@ -4408,7 +4476,7 @@ CK_RV token_specific_sha(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-                                    SHA_MSG_PART_ONLY);
-     } else {
-         rc = dll_m_Digest(c->context, c->context_len, in_data, in_data_len,
--                          out_data, out_data_len, ep11_data->target);
-+                          out_data, out_data_len, target_info->target);
-     }
- 
-     if (rc != CKR_OK) {
-@@ -4417,6 +4485,8 @@ CK_RV token_specific_sha(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-     } else {
-         TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
-     }
-+
-+    put_target_info(tokdata, target_info);
-     return rc;
- }
- 
-@@ -4430,6 +4500,11 @@ CK_RV token_specific_sha_update(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-     CK_ULONG out_len = sizeof(temp_out);
-     CK_ULONG len;
-     CK_RV rc = CKR_OK;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
-     if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) {
-         if (libica_ctx->offset > 0 || in_data_len < libica_ctx->block_size) {
-@@ -4479,7 +4554,7 @@ CK_RV token_specific_sha_update(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-         }
-     } else {
-         rc = dll_m_DigestUpdate(c->context, c->context_len,
--                                in_data, in_data_len, ep11_data->target);
-+                                in_data, in_data_len, target_info->target);
-     }
- 
- out:
-@@ -4489,6 +4564,8 @@ out:
-     } else {
-         TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
-     }
-+
-+    put_target_info(tokdata, target_info);
-     return rc;
- }
- 
-@@ -4499,6 +4576,11 @@ CK_RV token_specific_sha_final(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-     libica_sha_context_t *libica_ctx = (libica_sha_context_t *)c->context;
-     CK_RV rc;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
-     if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) {
-         rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism,
-@@ -4510,7 +4592,7 @@ CK_RV token_specific_sha_final(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-                                         SHA_MSG_PART_FINAL);
-     } else {
-         rc = dll_m_DigestFinal(c->context, c->context_len,
--                               out_data, out_data_len, ep11_data->target);
-+                               out_data, out_data_len, target_info->target);
-     }
- 
-     if (rc != CKR_OK) {
-@@ -4520,6 +4602,7 @@ CK_RV token_specific_sha_final(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
-         TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
-     }
- 
-+    put_target_info(tokdata, target_info);
-     return rc;
- }
- 
-@@ -4528,7 +4611,6 @@ CK_RV token_specific_rsa_sign(STDLL_TokData_t *tokdata, SESSION *session,
-                               CK_BYTE *out_data, CK_ULONG *out_data_len,
-                               OBJECT *key_obj)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     size_t keyblobsize = 0;
-     CK_BYTE *keyblob;
-@@ -4544,9 +4626,9 @@ CK_RV token_specific_rsa_sign(STDLL_TokData_t *tokdata, SESSION *session,
-     mech.pParameter = NULL;
-     mech.ulParameterLen = 0;
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len,
--                          out_data, out_data_len, ep11_data->target);
-+                          out_data, out_data_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4563,7 +4645,6 @@ CK_RV token_specific_rsa_verify(STDLL_TokData_t *tokdata, SESSION *session,
-                                 CK_BYTE *signature, CK_ULONG sig_len,
-                                 OBJECT *key_obj)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *spki;
-     size_t spki_len = 0;
-@@ -4579,9 +4660,9 @@ CK_RV token_specific_rsa_verify(STDLL_TokData_t *tokdata, SESSION *session,
-     mech.pParameter = NULL;
-     mech.ulParameterLen = 0;
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len,
--                            signature, sig_len, ep11_data->target);
-+                            signature, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4598,7 +4679,6 @@ CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *session,
-                                   CK_BYTE *in_data, CK_ULONG in_data_len,
-                                   CK_BYTE *sig, CK_ULONG *sig_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     size_t keyblobsize = 0;
-     CK_BYTE *keyblob;
-@@ -4616,9 +4696,9 @@ CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *session,
-     mech.ulParameterLen = ctx->mech.ulParameterLen;
-     mech.pParameter = ctx->mech.pParameter;
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len,
--                          sig, sig_len, ep11_data->target);
-+                          sig, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4638,7 +4718,6 @@ CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *session,
-                                     CK_BYTE *in_data, CK_ULONG in_data_len,
-                                     CK_BYTE *signature, CK_ULONG sig_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *spki;
-     size_t spki_len = 0;
-@@ -4656,9 +4735,9 @@ CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *session,
-     mech.ulParameterLen = ctx->mech.ulParameterLen;
-     mech.pParameter = ctx->mech.pParameter;
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len,
--                            signature, sig_len, ep11_data->target);
-+                            signature, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4678,7 +4757,6 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION  *session,
-                              CK_BYTE *out_data, CK_ULONG *out_data_len,
-                              OBJECT *key_obj )
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     SIGN_VERIFY_CONTEXT *ctx = &(session->sign_ctx);
-     CK_RV rc;
-     size_t keyblobsize = 0;
-@@ -4707,9 +4785,9 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION  *session,
-     mech.pParameter = NULL;
-     mech.ulParameterLen = 0;
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len,
--                          out_data, out_data_len, ep11_data->target);
-+                          out_data, out_data_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4728,7 +4806,6 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION  *session,
-                                CK_BYTE *out_data, CK_ULONG out_data_len,
-                                OBJECT *key_obj )
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     SIGN_VERIFY_CONTEXT *ctx = &(session->verify_ctx);
-     CK_RV rc;
-     CK_BYTE *spki;
-@@ -4757,9 +4834,9 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION  *session,
-     mech.pParameter = NULL;
-     mech.ulParameterLen = 0;
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len,
--                            out_data, out_data_len, ep11_data->target);
-+                            out_data, out_data_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4784,7 +4861,6 @@ CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata,
-                                       CK_BYTE *in_data, CK_ULONG in_data_len,
-                                       CK_BYTE *out_data, CK_ULONG *out_data_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *decr_key, *encr_key;
-     size_t decr_key_len = 0, encr_key_len = 0;
-@@ -4813,10 +4889,10 @@ CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_ReencryptSingle(decr_key, decr_key_len, encr_key, encr_key_len,
-                                decr_mech, encr_mech, in_data, in_data_len,
--                               out_data, out_data_len, ep11_data->target);
-+                               out_data, out_data_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -4892,7 +4968,6 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
-                          CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs,
-                          CK_ULONG attrs_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *keyblob;
-     size_t keyblobsize;
-@@ -4920,6 +4995,8 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_ULONG privlen;
-     int curve_type;
-     CK_BBOOL allocated = FALSE;
-+    ep11_target_info_t* target_info;
-+    CK_ULONG used_firmware_API_version;
- 
-     memset(newblob, 0, sizeof(newblob));
- 
-@@ -5009,7 +5086,15 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
-          * then we can pass the mechanism parameters as-is, otherwise we still
-          * need to use the old way.
-          */
--        if (ep11_data->used_firmware_API_version <= 2) {
-+        target_info = get_target_info(tokdata);
-+        if (target_info == NULL)
-+            return CKR_FUNCTION_FAILED;
-+
-+        used_firmware_API_version = target_info->used_firmware_API_version;
-+
-+        put_target_info(tokdata, target_info);
-+
-+        if (used_firmware_API_version <= 2) {
-             if (ecdh1_parms->kdf != CKD_NULL) {
-                 TRACE_ERROR("%s KDF for CKM_ECDH1_DERIVE not supported: %lu\n",
-                             __func__, ecdh1_parms->kdf);
-@@ -5133,11 +5218,11 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
-     ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc =
-         dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len, keyblob, keyblobsize,
-                         NULL, 0, ep11_pin_blob, ep11_pin_blob_len, newblob,
--                        &newblobsize, csum, &cslen, ep11_data->target);
-+                        &newblobsize, csum, &cslen, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -5231,7 +5316,6 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t * tokdata,
-                                  CK_ULONG ulPrivateKeyAttributeCount,
-                                  CK_SESSION_HANDLE h)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE publblob[MAX_BLOBSIZE];
-     size_t publblobsize = sizeof(publblob);
-@@ -5418,13 +5502,13 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t * tokdata,
-                                                  ulPrivateKeyAttributeCount)),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_GenerateKeyPair(pMechanism,
-                                    new_publ_attrs, new_publ_attrs_len,
-                                    new_priv_attrs, new_priv_attrs_len,
-                                    ep11_pin_blob, ep11_pin_blob_len,
-                                    privblob, &privblobsize,
--                                   publblob, &publblobsize, ep11_data->target);
-+                                   publblob, &publblobsize, target_info->target);
-     RETRY_END(rc, tokdata, sess)
- 
-     if (rc != CKR_OK) {
-@@ -5543,7 +5627,6 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t * tokdata,
-                                   CK_ULONG ulPrivateKeyAttributeCount,
-                                   CK_SESSION_HANDLE h)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE publblob[MAX_BLOBSIZE];
-     size_t publblobsize = sizeof(publblob);
-@@ -5752,13 +5835,13 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t * tokdata,
-                                                  ulPrivateKeyAttributeCount)),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_GenerateKeyPair(pMechanism,
-                                    new_publ_attrs2, new_publ_attrs2_len,
-                                    new_priv_attrs2, new_priv_attrs2_len,
-                                    ep11_pin_blob, ep11_pin_blob_len, privblob,
-                                    &privblobsize, publblob, &publblobsize,
--                                   ep11_data->target);
-+                                   target_info->target);
-     RETRY_END(rc, tokdata, sess)
- 
-     if (rc != CKR_OK) {
-@@ -5866,7 +5949,6 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata,
-                                      CK_ULONG ulPrivateKeyAttributeCount,
-                                      CK_SESSION_HANDLE h)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_ATTRIBUTE *attr = NULL;
-     CK_ATTRIBUTE *n_attr = NULL;
-@@ -5967,13 +6049,13 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata,
-                                                  ulPrivateKeyAttributeCount)),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_GenerateKeyPair(pMechanism,
-                                    new_publ_attrs2, new_publ_attrs2_len,
-                                    new_priv_attrs2, new_priv_attrs2_len,
-                                    ep11_pin_blob, ep11_pin_blob_len,
-                                    privkey_blob, &privkey_blob_len, spki,
--                                   &spki_len, ep11_data->target);
-+                                   &spki_len, target_info->target);
-     RETRY_END(rc, tokdata, sess)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, sess);
-@@ -6225,7 +6307,6 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t * tokdata,
-                                      CK_ULONG ulPrivateKeyAttributeCount,
-                                      CK_SESSION_HANDLE h)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_ATTRIBUTE *attr = NULL;
-     CK_BYTE privkey_blob[MAX_BLOBSIZE];
-@@ -6308,13 +6389,13 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t * tokdata,
-                                                  ulPrivateKeyAttributeCount)),
-                       &ep11_pin_blob, &ep11_pin_blob_len);
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_GenerateKeyPair(pMechanism,
-                                    new_publ_attrs2, new_publ_attrs2_len,
-                                    new_priv_attrs2, new_priv_attrs2_len,
-                                    ep11_pin_blob, ep11_pin_blob_len,
-                                    privkey_blob, &privkey_blob_len, spki,
--                                   &spki_len, ep11_data->target);
-+                                   &spki_len, target_info->target);
-     RETRY_END(rc, tokdata, sess)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, sess);
-@@ -6914,7 +6995,6 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
-                         CK_MECHANISM * mech, CK_BBOOL recover_mode,
-                         CK_OBJECT_HANDLE key)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     size_t keyblobsize = 0;
-     CK_BYTE *keyblob;
-@@ -6980,9 +7060,9 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_SignInit(ep11_sign_state, &ep11_sign_state_l,
--                            mech, keyblob, keyblobsize, ep11_data->target);
-+                            mech, keyblob, keyblobsize, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7017,7 +7097,6 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
-                    CK_ULONG in_data_len, CK_BYTE * signature,
-                    CK_ULONG * sig_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
-     size_t keyblobsize = 0;
-@@ -7049,9 +7128,9 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done; /* no ep11 fallback possible */
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_Sign(ctx->context, ctx->context_len, in_data, in_data_len,
--                        signature, sig_len, ep11_data->target);
-+                        signature, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7073,7 +7152,6 @@ done:
- CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
-                           CK_BYTE * in_data, CK_ULONG in_data_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
-     size_t keyblobsize = 0;
-@@ -7095,9 +7173,9 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_SignUpdate(ctx->context, ctx->context_len, in_data,
--                              in_data_len, ep11_data->target);
-+                              in_data_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7120,7 +7198,6 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
-                          CK_BBOOL length_only, CK_BYTE * signature,
-                          CK_ULONG * sig_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
-     size_t keyblobsize = 0;
-@@ -7139,9 +7216,9 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_SignFinal(ctx->context, ctx->context_len, signature, sig_len,
--                             ep11_data->target);
-+                             target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7169,7 +7246,6 @@ CK_RV ep11tok_sign_single(STDLL_TokData_t *tokdata, SESSION *session,
-     size_t keyblobsize = 0;
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
--    ep11_private_data_t *ep11_data = tokdata->private_data;
- 
-     UNUSED(length_only);
- 
-@@ -7186,9 +7262,9 @@ CK_RV ep11tok_sign_single(STDLL_TokData_t *tokdata, SESSION *session,
-         goto done;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_SignSingle(keyblob, keyblobsize, mech, in_data, in_data_len,
--                          signature, sig_len, ep11_data->target);
-+                          signature, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -7209,7 +7285,6 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
-                           CK_MECHANISM * mech, CK_BBOOL recover_mode,
-                           CK_OBJECT_HANDLE key)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *spki;
-     size_t spki_len = 0;
-@@ -7285,9 +7360,9 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_VerifyInit(ep11_sign_state, &ep11_sign_state_l, mech,
--                              spki, spki_len, ep11_data->target);
-+                              spki, spki_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7320,7 +7395,6 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
-                      CK_BYTE * in_data, CK_ULONG in_data_len,
-                      CK_BYTE * signature, CK_ULONG sig_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx;
-     size_t keyblobsize = 0;
-@@ -7353,9 +7427,9 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done; /* no ep11 fallback possible */
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_Verify(ctx->context, ctx->context_len, in_data, in_data_len,
--                          signature, sig_len, ep11_data->target);
-+                          signature, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7377,7 +7451,6 @@ done:
- CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
-                             CK_BYTE * in_data, CK_ULONG in_data_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx;
-     size_t keyblobsize = 0;
-@@ -7399,9 +7472,9 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_VerifyUpdate(ctx->context, ctx->context_len, in_data,
--                                in_data_len, ep11_data->target);
-+                                in_data_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7423,7 +7496,6 @@ done:
- CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
-                            CK_BYTE * signature, CK_ULONG sig_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx;
-     size_t keyblobsize = 0;
-@@ -7442,9 +7514,9 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_VerifyFinal(ctx->context, ctx->context_len, signature,
--                               sig_len, ep11_data->target);
-+                               sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7471,7 +7543,6 @@ CK_RV ep11tok_verify_single(STDLL_TokData_t *tokdata, SESSION *session,
-     CK_BYTE *spki;
-     size_t spki_len = 0;
-     OBJECT *key_obj = NULL;
--    ep11_private_data_t *ep11_data = tokdata->private_data;
- 
-     rc = h_opaque_2_blob(tokdata, key, &spki, &spki_len, &key_obj, READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7495,9 +7566,9 @@ CK_RV ep11tok_verify_single(STDLL_TokData_t *tokdata, SESSION *session,
-         goto done;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_VerifySingle(spki, spki_len, mech, in_data, in_data_len,
--                            signature, sig_len, ep11_data->target);
-+                            signature, sig_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -7517,7 +7588,6 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-                             CK_BYTE_PTR output_part,
-                             CK_ULONG_PTR p_output_part_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
-     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
-@@ -7538,10 +7608,10 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_DecryptFinal(ctx->context, ctx->context_len,
-                                 output_part, p_output_part_len,
--                                ep11_data->target);
-+                                target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7564,7 +7634,6 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
-                       CK_BYTE_PTR input_data, CK_ULONG input_data_len,
-                       CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
-     CK_BBOOL length_only = (output_data == NULL ? CK_TRUE : CK_FALSE);
-@@ -7586,10 +7655,10 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_Decrypt(ctx->context, ctx->context_len, input_data,
-                            input_data_len, output_data, p_output_data_len,
--                           ep11_data->target);
-+                           target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7613,7 +7682,6 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-                              CK_BYTE_PTR output_part,
-                              CK_ULONG_PTR p_output_part_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
-     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
-@@ -7640,10 +7708,10 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_DecryptUpdate(ctx->context, ctx->context_len,
-                                  input_part, input_part_len, output_part,
--                                 p_output_part_len, ep11_data->target);
-+                                 p_output_part_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7671,7 +7739,6 @@ CK_RV ep11tok_decrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
-     size_t keyblobsize = 0;
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
--    ep11_private_data_t *ep11_data = tokdata->private_data;
- 
-     UNUSED(length_only);
- 
-@@ -7688,10 +7755,10 @@ CK_RV ep11tok_decrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
-         goto done;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data,
-                              input_data_len, output_data, p_output_data_len,
--                             ep11_data->target);
-+                             target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -7711,7 +7778,6 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-                             CK_BYTE_PTR output_part,
-                             CK_ULONG_PTR p_output_part_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     ENCR_DECR_CONTEXT *ctx = &session->encr_ctx;
-     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
-@@ -7732,10 +7798,10 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_EncryptFinal(ctx->context, ctx->context_len,
-                                 output_part, p_output_part_len,
--                                ep11_data->target);
-+                                target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7758,7 +7824,6 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
-                       CK_BYTE_PTR input_data, CK_ULONG input_data_len,
-                       CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     ENCR_DECR_CONTEXT *ctx = &session->encr_ctx;
-     CK_BBOOL length_only = (output_data == NULL ? CK_TRUE : CK_FALSE);
-@@ -7780,10 +7845,10 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_Encrypt(ctx->context, ctx->context_len, input_data,
-                            input_data_len, output_data, p_output_data_len,
--                           ep11_data->target);
-+                           target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7807,7 +7872,6 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-                              CK_BYTE_PTR output_part,
-                              CK_ULONG_PTR p_output_part_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     ENCR_DECR_CONTEXT *ctx = &session->encr_ctx;
-     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
-@@ -7834,10 +7898,10 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_EncryptUpdate(ctx->context, ctx->context_len,
-                                  input_part, input_part_len, output_part,
--                                 p_output_part_len, ep11_data->target);
-+                                 p_output_part_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -7865,7 +7929,6 @@ CK_RV ep11tok_encrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
-     size_t keyblobsize = 0;
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
--    ep11_private_data_t *ep11_data = tokdata->private_data;
- 
-     UNUSED(length_only);
- 
-@@ -7893,10 +7956,10 @@ CK_RV ep11tok_encrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
-         goto done;
-     }
- 
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-     rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data,
-                              input_data_len, output_data, p_output_data_len,
--                             ep11_data->target);
-+                             target_info->target);
-     RETRY_END(rc, tokdata, session)
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -7916,7 +7979,6 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
-                                   CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key,
-                                   int op)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = CKR_OK;
-     CK_BYTE *blob;
-     size_t blob_len = 0;
-@@ -7979,9 +8041,9 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
- 
-     if (op == DECRYPT) {
-         ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_DecryptInit(ep11_state, &ep11_state_l, mech, blob,
--                                   blob_len, ep11_data->target);
-+                                   blob_len, target_info->target);
-         RETRY_END(rc, tokdata, session)
-         ctx->key = key;
-         ctx->active = TRUE;
-@@ -8012,9 +8074,9 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
-             goto error;
-         }
- 
--        RETRY_START
-+        RETRY_START(rc, tokdata)
-             rc = dll_m_EncryptInit(ep11_state, &ep11_state_l, mech, blob,
--                                   blob_len, ep11_data->target);
-+                                   blob_len, target_info->target);
-         RETRY_END(rc, tokdata, session)
-         ctx->key = key;
-         ctx->active = TRUE;
-@@ -8092,7 +8154,6 @@ CK_RV ep11tok_wrap_key(STDLL_TokData_t * tokdata, SESSION * session,
-                        CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key,
-                        CK_ULONG_PTR p_wrapped_key_len)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *wrapping_blob;
-     size_t wrapping_blob_len;
-@@ -8192,11 +8253,11 @@ CK_RV ep11tok_wrap_key(STDLL_TokData_t * tokdata, SESSION * session,
-      * (wrapping blob). The wrapped key can be processed by any PKCS11
-      * implementation.
-      */
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc =
-         dll_m_WrapKey(wrap_target_blob, wrap_target_blob_len, wrapping_blob,
-                       wrapping_blob_len, sign_blob, sign_blob_len, mech,
--                      wrapped_key, p_wrapped_key_len, ep11_data->target);
-+                      wrapped_key, p_wrapped_key_len, target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -8228,7 +8289,6 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
-                          CK_OBJECT_HANDLE wrapping_key,
-                          CK_OBJECT_HANDLE_PTR p_key)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     CK_BYTE *wrapping_blob, *temp;
-     size_t wrapping_blob_len;
-@@ -8388,13 +8448,13 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
-     /* we need a blob for the new key created by unwrapping,
-      * the wrapped key comes in BER
-      */
--    RETRY_START
-+    RETRY_START(rc, tokdata)
-         rc = dll_m_UnwrapKey(wrapped_key, wrapped_key_len, wrapping_blob,
-                              wrapping_blob_len, verifyblob, verifyblobsize,
-                              ep11_pin_blob,
-                              ep11_pin_blob_len, mech, new_attrs2, new_attrs2_len,
-                              keyblob, &keyblobsize, csum, &cslen,
--                             ep11_data->target);
-+                             target_info->target);
-     RETRY_END(rc, tokdata, session)
- 
-     if (rc != CKR_OK) {
-@@ -8657,21 +8717,25 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
-                                  CK_MECHANISM_TYPE_PTR pMechanismList,
-                                  CK_ULONG_PTR pulCount)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc = 0;
-     CK_ULONG counter = 0, size = 0;
-     CK_MECHANISM_TYPE_PTR mlist = NULL;
-     CK_ULONG i;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
-     /* size querry */
-     if (pMechanismList == NULL) {
-         rc = dll_m_GetMechanismList(0, pMechanismList, pulCount,
--                                    ep11_data->target);
-+                                    target_info->target);
-         if (rc != CKR_OK) {
-             rc = ep11_error_to_pkcs11_error(rc, NULL);
-             TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #1\n",
-                         __func__, rc);
--            return rc;
-+            goto out;
-         }
- 
-         /* adjust the size according to the ban list,
-@@ -8693,16 +8757,16 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
-                                     sizeof(CK_MECHANISM_TYPE) * counter);
-             if (!mlist) {
-                 TRACE_ERROR("%s Memory allocation failed\n", __func__);
--                return CKR_HOST_MEMORY;
-+                rc = CKR_HOST_MEMORY;
-+                goto out;
-             }
--            rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target);
-+            rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target);
-             if (rc != CKR_OK) {
-                 rc = ep11_error_to_pkcs11_error(rc, NULL);
-                 TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #2\n",
-                             __func__, rc);
--                free(mlist);
-                 if (rc != CKR_BUFFER_TOO_SMALL)
--                    return rc;
-+                    goto out;
-             }
-         } while (rc == CKR_BUFFER_TOO_SMALL);
- 
-@@ -8722,12 +8786,12 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
-          * that comes as parameter, this is a 'reduced size',
-          * ep11 would complain about insufficient list size
-          */
--        rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target);
-+        rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target);
-         if (rc != CKR_OK) {
-             rc = ep11_error_to_pkcs11_error(rc, NULL);
-             TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #3\n",
-                         __func__, rc);
--            return rc;
-+            goto out;
-         }
- 
-         /*
-@@ -8744,17 +8808,17 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
-                                     sizeof(CK_MECHANISM_TYPE) * counter);
-             if (!mlist) {
-                 TRACE_ERROR("%s Memory allocation failed\n", __func__);
--                return CKR_HOST_MEMORY;
-+                rc = CKR_HOST_MEMORY;
-+                goto out;
-             }
-             /* all the card has */
--            rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target);
-+            rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target);
-             if (rc != CKR_OK) {
-                 rc = ep11_error_to_pkcs11_error(rc, NULL);
-                 TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #4\n",
-                             __func__, rc);
--                free(mlist);
-                 if (rc != CKR_BUFFER_TOO_SMALL)
--                    return rc;
-+                    goto out;
-             }
-         } while (rc == CKR_BUFFER_TOO_SMALL);
- 
-@@ -8775,8 +8839,10 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
-             rc = CKR_BUFFER_TOO_SMALL;
-     }
- 
-+out:
-     if (mlist)
-         free(mlist);
-+    put_target_info(tokdata, target_info);
-     return rc;
- }
- 
-@@ -8790,6 +8856,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-     CK_BBOOL found = FALSE;
-     CK_ULONG i;
-     int status;
-+    CK_RV rc = CKR_OK;
-+    ep11_target_info_t* target_info;
- 
-     for (i = 0; i < supported_mech_list_len; i++) {
-         if (type == ep11_supported_mech_list[i]) {
-@@ -8804,13 +8872,18 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         return CKR_MECHANISM_INVALID;
-     }
- 
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-     if (check_cps_for_mechanism(ep11_data->cp_config,
--                                type, ep11_data->control_points,
--                                ep11_data->control_points_len,
--                                ep11_data->max_control_point_index) != CKR_OK) {
-+                                type, target_info->control_points,
-+                                target_info->control_points_len,
-+                                target_info->max_control_point_index) != CKR_OK) {
-         TRACE_INFO("%s Mech '%s' banned due to control point\n",
-                                    __func__, ep11_get_ckm(type));
--        return CKR_MECHANISM_INVALID;
-+        rc = CKR_MECHANISM_INVALID;
-+        goto out;
-     }
- 
-     switch(type) {
-@@ -8840,14 +8913,17 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         if (status == -1) {
-             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
-                         __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         break;
- 
-     case CKM_RSA_PKCS_OAEP:
-         /* CKM_RSA_PKCS_OAEP is not supported with EP11 host library <= 1.3 */
--        if (compare_ck_version(&ep11_data->ep11_lib_version, &ver1_3) <= 0)
--            return CKR_MECHANISM_INVALID;
-+        if (compare_ck_version(&ep11_data->ep11_lib_version, &ver1_3) <= 0) {
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-+        }
-         break;
- 
-     case CKM_IBM_SHA3_224:
-@@ -8863,7 +8939,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         if (status != 1) {
-             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
-                                     __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         break;
- 
-@@ -8876,7 +8953,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         if (status != 1) {
-             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
-                                     __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         break;
- 
-@@ -8887,7 +8965,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) < 0) {
-             TRACE_INFO("%s Mech '%s' banned due to host library version\n",
-                                     __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
- 
-         status = check_required_versions(tokdata, edwards_req_versions,
-@@ -8895,7 +8974,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         if (status != 1) {
-             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
-                                     __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         break;
- 
-@@ -8903,14 +8983,16 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-         if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) <= 0) {
-             TRACE_INFO("%s Mech '%s' banned due to host library version\n",
-                                      __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         status = check_required_versions(tokdata, ibm_dilithium_req_versions,
-                                          NUM_DILITHIUM_REQ);
-         if (status != 1) {
-             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
-                                     __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         break;
- 
-@@ -8919,19 +9001,23 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
-             TRACE_INFO("%s Mech '%s' banned due to host library version\n",
-                                      __func__, ep11_get_ckm(type));
- 
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         status = check_required_versions(tokdata, ibm_cpacf_wrap_req_versions,
-                                          NUM_CPACF_WRAP_REQ);
-         if (status != 1) {
-             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
-                                     __func__, ep11_get_ckm(type));
--            return CKR_MECHANISM_INVALID;
-+            rc = CKR_MECHANISM_INVALID;
-+            goto out;
-         }
-         break;
-     }
- 
--    return CKR_OK;
-+out:
-+    put_target_info(tokdata, target_info);
-+    return rc;
- }
- 
- CK_RV ep11tok_is_mechanism_supported_ex(STDLL_TokData_t *tokdata,
-@@ -8976,9 +9062,9 @@ CK_RV ep11tok_get_mechanism_info(STDLL_TokData_t * tokdata,
-                                  CK_MECHANISM_TYPE type,
-                                  CK_MECHANISM_INFO_PTR pInfo)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_RV rc;
-     int status;
-+    ep11_target_info_t* target_info;
- 
-     rc = ep11tok_is_mechanism_supported(tokdata, type);
-     if (rc != CKR_OK) {
-@@ -8987,7 +9073,14 @@ CK_RV ep11tok_get_mechanism_info(STDLL_TokData_t * tokdata,
-         return rc;
-     }
- 
--    rc = dll_m_GetMechanismInfo(0, type, pInfo, ep11_data->target);
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-+    rc = dll_m_GetMechanismInfo(0, type, pInfo, target_info->target);
-+
-+    put_target_info(tokdata, target_info);
-+
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, NULL);
-         TRACE_ERROR("%s m_GetMechanismInfo(0x%lx) failed with rc=0x%lx\n",
-@@ -10265,6 +10358,11 @@ static CK_RV generate_ep11_session_id(STDLL_TokData_t * tokdata,
-     CK_MECHANISM mech;
-     CK_ULONG len;
-     libica_sha_context_t ctx;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
-     session_id_data.handle = session->handle;
-     gettimeofday(&session_id_data.timeofday, NULL);
-@@ -10286,7 +10384,9 @@ static CK_RV generate_ep11_session_id(STDLL_TokData_t * tokdata,
-         rc = dll_m_DigestSingle(&mech, (CK_BYTE_PTR)&session_id_data,
-                                 sizeof(session_id_data),
-                                 ep11_session->session_id, &len,
--                                ep11_data->target);
-+                                target_info->target);
-+
-+    put_target_info(tokdata, target_info);
- 
-     if (rc != CKR_OK) {
-         rc = ep11_error_to_pkcs11_error(rc, session);
-@@ -10964,7 +11064,7 @@ static CK_RV get_card_type(uint_32 adapter, CK_ULONG *type)
- 
- typedef struct query_version
- {
--    ep11_private_data_t *ep11_data;
-+    ep11_target_info_t *target_info;
-     CK_CHAR serialNumber[16];
-     CK_BBOOL first;
-     CK_BBOOL error;
-@@ -11005,7 +11105,7 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
-     }
- 
-     /* Try to find existing version info for this card type */
--    card_version = qv->ep11_data->card_versions;
-+    card_version = qv->target_info->card_versions;
-     while (card_version != NULL) {
-         if (card_version->card_type == card_type)
-            break;
-@@ -11050,8 +11150,8 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
-         card_version->firmware_version = xcp_info.firmwareVersion;
- #endif
- 
--        card_version->next = qv->ep11_data->card_versions;
--        qv->ep11_data->card_versions = card_version;
-+        card_version->next = qv->target_info->card_versions;
-+        qv->target_info->card_versions = card_version;
-     } else {
-         /*
-          * Version info for this card type is already available, so check this
-@@ -11134,23 +11234,16 @@ static CK_RV ep11tok_get_ep11_library_version(CK_VERSION *lib_version)
-     return CKR_OK;
- }
- 
--static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata)
-+static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata,
-+                                      ep11_target_info_t *target_info)
- {
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-     ep11_card_version_t *card_version;
-     query_version_t qv;
-     CK_RV rc;
- 
--    rc = ep11tok_get_ep11_library_version(&ep11_data->ep11_lib_version);
--    if (rc != CKR_OK)
--        return rc;
--
--    TRACE_INFO("%s Host library version: %d.%d\n", __func__,
--               ep11_data->ep11_lib_version.major,
--               ep11_data->ep11_lib_version.minor);
--
-     memset(&qv, 0, sizeof(qv));
--    qv.ep11_data = ep11_data;
-+    qv.target_info = target_info;
-     qv.first = TRUE;
- 
-     rc = handle_all_ep11_cards(&ep11_data->target_list, version_query_handler,
-@@ -11169,18 +11262,18 @@ static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata)
-         return CKR_DEVICE_ERROR;
-     }
- 
--    memcpy(ep11_data->serialNumber, qv.serialNumber,
--           sizeof(ep11_data->serialNumber));
-+    memcpy(target_info->serialNumber, qv.serialNumber,
-+           sizeof(target_info->serialNumber));
- 
--    TRACE_INFO("%s Serial number: %.16s\n", __func__, ep11_data->serialNumber);
-+    TRACE_INFO("%s Serial number: %.16s\n", __func__, target_info->serialNumber);
- 
-     /* EP11 host lib version <= 2 only support API version 2 */
-     if (ep11_data->ep11_lib_version.major <= 2)
--        ep11_data->used_firmware_API_version = 2;
-+        target_info->used_firmware_API_version = 2;
-     else
--        ep11_data->used_firmware_API_version = 0;
-+        target_info->used_firmware_API_version = 0;
- 
--    card_version = ep11_data->card_versions;
-+    card_version = target_info->card_versions;
-     while (card_version != NULL) {
-         TRACE_INFO("%s Card type: CEX%luP\n", __func__,
-                    card_version->card_type);
-@@ -11190,19 +11283,19 @@ static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata)
-                 card_version->firmware_version.major,
-                 card_version->firmware_version.minor);
- 
--        if (ep11_data->used_firmware_API_version == 0)
--            ep11_data->used_firmware_API_version =
-+        if (target_info->used_firmware_API_version == 0)
-+            target_info->used_firmware_API_version =
-                                 card_version->firmware_API_version;
-         else
--            ep11_data->used_firmware_API_version =
--                                MIN(ep11_data->used_firmware_API_version,
-+            target_info->used_firmware_API_version =
-+                                MIN(target_info->used_firmware_API_version,
-                                     card_version->firmware_API_version);
- 
-         card_version = card_version->next;
-     }
- 
-     TRACE_INFO("%s Used Firmware API: %lu\n", __func__,
--               ep11_data->used_firmware_API_version);
-+               target_info->used_firmware_API_version);
- 
-     return CKR_OK;
- }
-@@ -11220,20 +11313,29 @@ static void free_card_versions(ep11_card_version_t *card_version)
-     }
- }
- 
--void ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
-+CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
-                                  CK_TOKEN_INFO_PTR pInfo)
- {
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-+    ep11_target_info_t* target_info;
-+
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
- 
-     /*
-      * report the EP11 firmware version as hardware version, and
-      * the EP11 host library version as firmware version
-      */
--    if (ep11_data->card_versions != NULL)
--        pInfo->hardwareVersion = ep11_data->card_versions->firmware_version;
-+    if (target_info->card_versions != NULL)
-+        pInfo->hardwareVersion = target_info->card_versions->firmware_version;
-     pInfo->firmwareVersion = ep11_data->ep11_lib_version;
--    memcpy(pInfo->serialNumber, ep11_data->serialNumber,
-+    memcpy(pInfo->serialNumber, target_info->serialNumber,
-            sizeof(pInfo->serialNumber));
-+
-+    put_target_info(tokdata, target_info);
-+
-+    return CKR_OK;
- }
- 
- /**
-@@ -11247,13 +11349,17 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
-                                    const version_req_t req[],
-                                    CK_ULONG num_req)
- {
--    ep11_private_data_t *ep11_data = tokdata->private_data;
-     CK_ULONG i, max_card_type = 0, min_card_type = 0xFFFFFFFF;
-     CK_BBOOL req_not_fullfilled = CK_FALSE;
-     CK_BBOOL req_fullfilled = CK_FALSE;
-     ep11_card_version_t *card_version;
-+    ep11_target_info_t* target_info;
-     int status;
- 
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return CKR_FUNCTION_FAILED;
-+
-     for (i = 0; i < num_req; i++) {
-         status = check_card_version(tokdata, req[i].card_type,
-                                            req[i].min_lib_version,
-@@ -11268,7 +11374,7 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
-     }
- 
-     /* Are card types < min_card_type present? */
--    card_version = ep11_data->card_versions;
-+    card_version = target_info->card_versions;
-     while (card_version != NULL) {
-          if (card_version->card_type < min_card_type)
-              req_not_fullfilled = CK_TRUE;
-@@ -11276,7 +11382,7 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
-      }
- 
-     /* Are card types > max_card_type present? */
--    card_version = ep11_data->card_versions;
-+    card_version = target_info->card_versions;
-     while (card_version != NULL) {
-         if (card_version->card_type > max_card_type) {
-             /*
-@@ -11285,9 +11391,10 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
-               * So all others must also meet the version requirements or be
-               * not present.
-               */
-+            status = 1;
-              if (req_not_fullfilled == CK_TRUE)
--                 return -1;
--             return 1;
-+                 status = -1;
-+             goto out;
-         }
-         card_version = card_version->next;
-     }
-@@ -11298,13 +11405,19 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
-          * At least one don't meet the requirements, so all other must not
-          * fulfill the requirements, too, or are not present.
-          */
-+        status = 0;
-         if (req_fullfilled == CK_TRUE)
--                return -1;
--        return 0;
-+            status = -1;
-+        goto out;
-     } else {
-         /* All of the cards that are present fulfill the requirements */
--        return 1;
-+        status = 1;
-+        goto out;
-     }
-+
-+out:
-+    put_target_info(tokdata, target_info);
-+    return status;
- }
- 
- /**
-@@ -11320,6 +11433,8 @@ static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
- {
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-     ep11_card_version_t *card_version;
-+    ep11_target_info_t* target_info;
-+    int status = 1;
- 
-     TRACE_DEBUG("%s checking versions for CEX%luP cards.\n", __func__, card_type);
- 
-@@ -11331,21 +11446,28 @@ static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
-         }
-     }
- 
--    card_version = ep11_data->card_versions;
-+    target_info = get_target_info(tokdata);
-+    if (target_info == NULL)
-+        return -1;
-+
-+    card_version = target_info->card_versions;
-     while (card_version != NULL) {
-         if (card_version->card_type == card_type)
-             break;
-         card_version = card_version->next;
-     }
- 
--    if (card_version == NULL)
--        return -1;
-+    if (card_version == NULL) {
-+        status = -1;
-+        goto out;
-+    }
- 
-     if (firmware_version != NULL) {
-         if (compare_ck_version(&card_version->firmware_version,
-                                firmware_version) < 0) {
-             TRACE_DEBUG("%s firmware_version is less than required\n", __func__);
--            return 0;
-+            status = 0;
-+            goto out;
-         }
-     }
- 
-@@ -11353,53 +11475,57 @@ static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
-         if (card_version->firmware_API_version < *firmware_API_version) {
-             TRACE_DEBUG("%s firmware_API_version is less than required\n",
-                        __func__);
--            return 0;
-+            status = 0;
-+            goto out;
-         }
-     }
- 
--    return 1;
-+ out:
-+    put_target_info(tokdata, target_info);
-+    return status;
- }
- 
--static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata)
-+static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata,
-+                                  ep11_target_info_t *target_info)
- {
-     ep11_private_data_t *ep11_data = tokdata->private_data;
-     struct XCP_Module module;
--    CK_RV rc;
-+    CK_RV rc = CKR_OK;
-     short i;
- 
-     if (dll_m_add_module == NULL) {
-         TRACE_WARNING("%s Function dll_m_add_module is not available, falling "
-                       "back to old target handling\n", __func__);
- 
--        if (ep11_data->used_firmware_API_version > 2) {
-+        if (target_info->used_firmware_API_version > 2) {
-             TRACE_ERROR("%s selecting an API version is not possible with old "
-                         "target handling\n", __func__);
-             return CKR_FUNCTION_FAILED;
-         }
- 
--        ep11_data->target = (target_t)&ep11_data->target_list;
-+        target_info->target = (target_t)&ep11_data->target_list;
-         return CKR_OK;
-     }
- 
--    if (ep11_data->used_firmware_API_version > 2 &&
-+    if (target_info->used_firmware_API_version > 2 &&
-         ep11_data->ep11_lib_version.major < 3) {
-         TRACE_ERROR("%s selecting an API version is not possible with an EP11"
-                     " host library version < 3.0\n", __func__);
-         return CKR_FUNCTION_FAILED;
-     }
- 
--    ep11_data->target = XCP_TGT_INIT;
-+    target_info->target = XCP_TGT_INIT;
-     memset(&module, 0, sizeof(module));
-     module.version = ep11_data->ep11_lib_version.major >= 3 ? XCP_MOD_VERSION_2
-                                                             : XCP_MOD_VERSION_1;
-     module.flags = XCP_MFL_VIRTUAL | XCP_MFL_MODULE;
--    module.api = ep11_data->used_firmware_API_version;
-+    module.api = target_info->used_firmware_API_version;
- 
-     TRACE_DEVEL("%s XCP_MOD_VERSION: %u\n", __func__, module.version);
- 
-     if (ep11_data->target_list.length == 0) {
-         /* APQN_ANY: Create an empty module group */
--        rc = dll_m_add_module(&module, &ep11_data->target);
-+        rc = dll_m_add_module(&module, &target_info->target);
-         if (rc != CKR_OK) {
-             TRACE_ERROR("%s dll_m_add_module (ANY) failed: rc=%ld\n",
-                         __func__, rc);
-@@ -11414,11 +11540,12 @@ static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata)
-         XCPTGTMASK_SET_DOM(module.domainmask,
-                            ep11_data->target_list.apqns[2 * i + 1]);
- 
--        rc = dll_m_add_module(&module, &ep11_data->target);
-+        rc = dll_m_add_module(&module, &target_info->target);
-         if (rc != CKR_OK) {
-             TRACE_ERROR("%s dll_m_add_module (%02x.%04x) failed: rc=%ld\n",
-                     __func__, ep11_data->target_list.apqns[2 * i],
-                     ep11_data->target_list.apqns[2 * i + 1], rc);
-+            dll_m_rm_module(NULL, target_info->target);
-             return CKR_FUNCTION_FAILED;
-         }
-     }
-@@ -11494,6 +11621,7 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata, OBJECT *obj,
-     CK_ULONG num_attributes = 0;
-     CK_ATTRIBUTE *attr;
-     CK_RV rc;
-+    ep11_target_info_t* target_info;
- 
-     rc = template_attribute_get_ulong(obj->template, CKA_CLASS, &class);
-     if (rc != CKR_OK) {
-@@ -11575,9 +11703,18 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata, OBJECT *obj,
-             goto out;
-         }
- 
-+        target_info = get_target_info(tokdata);
-+        if (target_info == NULL) {
-+            rc = CKR_FUNCTION_FAILED;
-+            goto out;
-+        }
-+
-         rc = dll_m_SetAttributeValue(ibm_opaque_attr->pValue,
-                                      ibm_opaque_attr->ulValueLen, attributes,
--                                     num_attributes, ep11_data->target);
-+                                     num_attributes, target_info->target);
-+
-+        put_target_info(tokdata, target_info);
-+
-         if (rc != CKR_OK) {
-             rc = ep11_error_to_pkcs11_error(rc, NULL);
-             TRACE_ERROR("%s m_SetAttributeValue failed rc=0x%lx\n",
-@@ -11601,3 +11738,233 @@ out:
-     return rc;
- }
- 
-+/*
-+ * ATTENTION: This function is called in a separate thread. All actions
-+ * performed by this function must be thread save and use locks to lock
-+ * against concurrent access by other threads.
-+ */
-+static CK_RV ep11tok_handle_apqn_event(STDLL_TokData_t *tokdata,
-+                                       unsigned int event_type,
-+                                       event_udev_apqn_data_t *apqn_data)
-+{
-+    ep11_private_data_t *ep11_data = tokdata->private_data;
-+    CK_BBOOL found = FALSE;
-+    CK_RV rc = CKR_OK;
-+    char name[20];
-+    int i;
-+
-+    /* Is it one of the configured APQNs ?*/
-+    if (ep11_data->target_list.length > 0) {
-+        /* APQN_WHITELIST is specified */
-+        for (i = 0; i < ep11_data->target_list.length; i++) {
-+            if (ep11_data->target_list.apqns[2 * i] == apqn_data->card &&
-+                ep11_data->target_list.apqns[2 * i + 1] == apqn_data->domain) {
-+                found = TRUE;
-+                break;
-+            }
-+        }
-+    } else {
-+        /* APQN_ANY is specified */
-+        found = TRUE;
-+        if (event_type == EVENT_TYPE_APQN_ADD) {
-+            snprintf(name, sizeof(name), "card%02x", apqn_data->card);
-+            if (is_card_ep11_and_online(name) != CKR_OK)
-+                found = FALSE; /* Not an EP11 APQN */
-+        }
-+    }
-+    if (!found)
-+        return CKR_OK;
-+
-+    TRACE_DEVEL("%s Refreshing target infos due to event for APQN %02x.%04x\n",
-+                __func__, apqn_data->card, apqn_data->domain);
-+
-+    rc = refresh_target_info(tokdata);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s Failed to get the target infos (refresh_target_info "
-+                    "rc=0x%lx)\n", __func__, rc);
-+        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the target info rc=0x%lx\n",
-+                   __func__, rc);
-+        return rc;
-+    }
-+
-+    return CKR_OK;
-+}
-+
-+/*
-+ * Called by the event thread, on receipt of an event.
-+ *
-+ * ATTENTION: This function is called in a separate thread. All actions
-+ * performed by this function must be thread save and use locks to lock
-+ * against concurrent access by other threads.
-+ */
-+CK_RV token_specific_handle_event(STDLL_TokData_t *tokdata,
-+                                  unsigned int event_type,
-+                                  unsigned int event_flags,
-+                                  const char *payload,
-+                                  unsigned int payload_len)
-+{
-+    UNUSED(event_flags);
-+
-+    switch (event_type) {
-+    case EVENT_TYPE_APQN_ADD:
-+    case EVENT_TYPE_APQN_REMOVE:
-+        if (payload_len != sizeof(event_udev_apqn_data_t))
-+            return CKR_FUNCTION_FAILED;
-+        return ep11tok_handle_apqn_event(tokdata, event_type,
-+                                         (event_udev_apqn_data_t *)payload);
-+
-+    default:
-+        return CKR_FUNCTION_NOT_SUPPORTED;
-+    }
-+
-+    return CKR_OK;
-+}
-+
-+/*
-+ * Refreshes the target info using the currently configured and available
-+ * APQNs. Registers the newly allocated target info as the current one in a
-+ * thread save way and gives back the previous one so that it is release when
-+ * no longer used (i.e. by a concurrently running thread).
-+ */
-+static CK_RV refresh_target_info(STDLL_TokData_t *tokdata)
-+{
-+    ep11_private_data_t *ep11_data = tokdata->private_data;
-+    volatile ep11_target_info_t *prev_info;
-+    ep11_target_info_t *target_info;
-+    CK_RV rc;
-+
-+    target_info = calloc(1, sizeof(ep11_target_info_t));
-+    if (target_info == NULL) {
-+        TRACE_ERROR("%s Memory allocation failed\n", __func__);
-+        return CKR_HOST_MEMORY;
-+    }
-+
-+    target_info->ref_count = 1;
-+
-+    /* Get the version info freshly with the current set of APQNs */
-+    rc = ep11tok_get_ep11_version(tokdata, target_info);
-+    if (rc != 0)
-+        goto error;
-+
-+    /* Get the control points freshly with the current set of APQNs */
-+    target_info->control_points_len = sizeof(target_info->control_points);
-+    rc = get_control_points(tokdata, target_info->control_points,
-+                            &target_info->control_points_len,
-+                            &target_info->max_control_point_index);
-+    if (rc != 0)
-+        goto error;
-+
-+    /* Setup the group target freshly with the current set of APQNs */
-+    rc = ep11tok_setup_target(tokdata, target_info);
-+    if (rc != CKR_OK)
-+        goto error;
-+
-+    /* Set the new one as the current one (locked against concurrent get's) */
-+    if (pthread_rwlock_wrlock(&ep11_data->target_rwlock) != 0) {
-+        TRACE_DEVEL("Target Write-Lock failed.\n");
-+        rc = CKR_CANT_LOCK;
-+        goto error;
-+    }
-+
-+    prev_info = ep11_data->target_info;
-+    ep11_data->target_info = target_info;
-+
-+    if (pthread_rwlock_unlock(&ep11_data->target_rwlock) != 0) {
-+        TRACE_DEVEL("Target Unlock failed.\n");
-+        return CKR_CANT_LOCK;
-+    }
-+
-+    /* Release the previous one */
-+    if (prev_info != NULL)
-+        put_target_info(tokdata, (ep11_target_info_t *)prev_info);
-+
-+    return CKR_OK;
-+
-+error:
-+    free_card_versions(target_info->card_versions);
-+    free((void *)target_info);
-+    return rc;
-+}
-+
-+/*
-+ * Get the current EP11 target info.
-+ * Do NOT use the ep11_data->target_info directly, always get a copy using
-+ * this function. This will increment the reference count of the target info,
-+ * and return the current target info in a thread save way.
-+ * When no longer needed, put it back using put_target_info().
-+ */
-+static ep11_target_info_t *get_target_info(STDLL_TokData_t *tokdata)
-+{
-+    ep11_private_data_t *ep11_data = tokdata->private_data;
-+    volatile ep11_target_info_t *target_info;
-+#ifdef DEBUG
-+    unsigned long ref_count;
-+#endif
-+
-+    /*
-+     * Lock until we have obtained the current target info and have
-+     * increased the reference counter
-+     */
-+    if (pthread_rwlock_rdlock(&ep11_data->target_rwlock) != 0) {
-+        TRACE_DEVEL("Target Read-Lock failed.\n");
-+        return NULL;
-+    }
-+
-+    target_info = *((void * volatile *)&ep11_data->target_info);
-+    if (target_info == NULL) {
-+        TRACE_ERROR("%s: target_info is NULL\n", __func__);
-+        return NULL;
-+    }
-+
-+#ifdef DEBUG
-+    ref_count = __sync_add_and_fetch(&target_info->ref_count, 1);
-+
-+    TRACE_DEBUG("%s: target_info: %p ref_count: %lu\n", __func__,
-+                (void *)target_info, ref_count);
-+#else
-+    __sync_add_and_fetch(&target_info->ref_count, 1);
-+#endif
-+
-+    if (pthread_rwlock_unlock(&ep11_data->target_rwlock) != 0) {
-+        TRACE_DEVEL("Target Unlock failed.\n");
-+        return NULL;
-+    }
-+
-+    return (ep11_target_info_t *)target_info;
-+}
-+
-+/*
-+ * Give back an EP11 target info. This will decrement the reference count,
-+ * and will free it if the reference count reaches zero.
-+ */
-+static void put_target_info(STDLL_TokData_t *tokdata,
-+                            ep11_target_info_t *target_info)
-+{
-+    ep11_private_data_t *ep11_data = tokdata->private_data;
-+    unsigned long ref_count;
-+
-+    if (target_info == NULL)
-+        return;
-+
-+    if (target_info->ref_count > 0) {
-+        ref_count = __sync_sub_and_fetch(&target_info->ref_count, 1);
-+
-+        TRACE_DEBUG("%s: target_info: %p ref_count: %lu\n", __func__,
-+                    (void *)target_info, ref_count);
-+    } else {
-+        TRACE_WARNING("%s: target_info: %p ref_count already 0.\n", __func__,
-+                      (void *)target_info);
-+        ref_count = 0;
-+    }
-+
-+    if (ref_count == 0 && target_info != ep11_data->target_info) {
-+        TRACE_DEBUG("%s: target_info: %p is freed\n", __func__,
-+                    (void *)target_info);
-+
-+        if (dll_m_rm_module != NULL)
-+            dll_m_rm_module(NULL, target_info->target);
-+        free_card_versions(target_info->card_versions);
-+        free(target_info);
-+    }
-+}
-+
-diff --git a/usr/lib/ep11_stdll/ep11_specific.h b/usr/lib/ep11_stdll/ep11_specific.h
-index 55fc023c..343f4b3d 100644
---- a/usr/lib/ep11_stdll/ep11_specific.h
-+++ b/usr/lib/ep11_stdll/ep11_specific.h
-@@ -161,7 +161,7 @@ CK_BBOOL ep11tok_libica_mech_available(STDLL_TokData_t *tokdata,
-                                        CK_MECHANISM_TYPE mech,
-                                        CK_OBJECT_HANDLE hKey);
- 
--void ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
-+CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
-                                  CK_TOKEN_INFO_PTR pInfo);
- 
- CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
-diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
-index 4e592363..cd12604e 100644
---- a/usr/lib/ep11_stdll/new_host.c
-+++ b/usr/lib/ep11_stdll/new_host.c
-@@ -298,7 +298,7 @@ CK_RV SC_GetTokenInfo(STDLL_TokData_t *tokdata, CK_SLOT_ID sid,
-         goto done;
-     }
-     copy_token_contents_sensibly(pInfo, tokdata->nv_token_data);
--    ep11tok_copy_firmware_info(tokdata, pInfo);
-+    rc = ep11tok_copy_firmware_info(tokdata, pInfo);
- 
-     /* Set the time */
-     now = time((time_t *) NULL);
-diff --git a/usr/lib/ep11_stdll/tok_struct.h b/usr/lib/ep11_stdll/tok_struct.h
-index 2c0af9cf..01268c67 100644
---- a/usr/lib/ep11_stdll/tok_struct.h
-+++ b/usr/lib/ep11_stdll/tok_struct.h
-@@ -137,7 +137,7 @@ token_spec_t token_specific = {
-     &token_specific_reencrypt_single,
-     &token_specific_set_attribute_values,
-     &token_specific_set_attrs_for_new_object,
--    NULL,                       // handle_event
-+    &token_specific_handle_event,
- };
- 
- #endif
diff --git a/SOURCES/opencryptoki-3.16.0-342dfbeb8275f5ea6ed52dd3f30126614ec1d037.patch b/SOURCES/opencryptoki-3.16.0-342dfbeb8275f5ea6ed52dd3f30126614ec1d037.patch
deleted file mode 100644
index 76ce00d..0000000
--- a/SOURCES/opencryptoki-3.16.0-342dfbeb8275f5ea6ed52dd3f30126614ec1d037.patch
+++ /dev/null
@@ -1,2159 +0,0 @@
-commit 342dfbeb8275f5ea6ed52dd3f30126614ec1d037
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Feb 15 14:33:07 2021 +0100
-
-    Event support: pkcsslotd changes
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/configure.ac b/configure.ac
-index e0ae4a82..a0b098e1 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -234,6 +234,12 @@ AC_ARG_WITH([systemd],
- 	AS_HELP_STRING([--with-systemd@<:@=DIR@:>@],[systemd system unit files location]),
- 	[],
- 	[with_systemd=no])
-+	
-+dnl --- libudev development files
-+AC_ARG_WITH([libudev],
-+	AS_HELP_STRING([--with-libudev@<:@=DIR@:>@],[libudev development files location]),
-+	[],
-+	[with_libudev=check])
- 
- dnl ---
- dnl ---
-@@ -438,6 +444,46 @@ fi
- AC_SUBST([XCRYPTOLINZ_CFLAGS])
- AC_SUBST([XCRYPTOLINZ_LIBS])
- 
-+dnl --- with_libudev
-+LIBUDEV_CFLAGS=
-+LIBUDEV_LIBS=
-+if test "x$with_libudev" != "xno"; then
-+	if test "x$with_libudev" != "xyes" -a "x$with_libudev" != "xcheck"; then
-+		LIBUDEV_CFLAGS="-I$with_libudev"
-+		LIBUDEV_LIBS="-L$with_libudev"
-+	fi
-+	old_cflags="$CFLAGS"
-+	old_libs="$LIBS"
-+	CFLAGS="$CFLAGS $LIBUDEV_CFLAGS"
-+	LIBS="$LIBS $LIBUDEV_LIBS"
-+	# Use libudev only on s390 platforms, only s390 emits AP related uevents
-+	case $target in
-+	     *s390x* | *s390*)
-+		CFLAGS="$CFLAGS -DWITH_LIBUDEV"
-+		;;
-+	     *)
-+		if test "x$with_libudev" != "xyes"; then
-+			with_libudev=no
-+			echo "Default to 'with_libudev=no' on non-s390 platforms"
-+		fi
-+		;;
-+	esac
-+	if test "x$with_libudev" != "xno"; then
-+		AC_CHECK_HEADER([libudev.h], [with_libudev=yes], [
-+			AC_MSG_ERROR([Build with libudev requested but libudev headers couldn't be found])
-+		])
-+		AC_CHECK_LIB([udev], [udev_monitor_new_from_netlink], [with_libudev=yes], [
-+			AC_MSG_ERROR([Build with libudev requested but libudev libraries couldn't be found])
-+		])
-+	fi
-+	if test "x$with_libudev" = "xno"; then
-+		CFLAGS="$old_cflags"
-+		LIBS="$old_libs"
-+	fi
-+fi
-+AC_SUBST([LIBUDEV_CFLAGS])
-+AC_SUBST([LIBUDEV_LIBS])
-+AM_CONDITIONAL([HAVE_LIBUDEV], [test "x$with_libudev" = "xyes"])
- 
- dnl ---
- dnl --- Now check enabled features, while making sure every required
-@@ -649,6 +695,7 @@ echo "	Daemon build:		$enable_daemon"
- echo "	Library build:		$enable_library"
- echo "	Systemd service:	$enable_systemd"
- echo "	Build with locks:	$enable_locks"
-+echo "	Build with libudev:	$with_libudev"
- echo "	Build p11sak tool:	$enable_p11sak"
- echo "	token migrate tool:	$enable_pkcstok_migrate"
- echo
-diff --git a/usr/include/slotmgr.h b/usr/include/slotmgr.h
-index 4d038435..e37368a5 100644
---- a/usr/include/slotmgr.h
-+++ b/usr/include/slotmgr.h
-@@ -31,6 +31,7 @@
- #define OCK_API_LOCK_FILE LOCKDIR_PATH "/LCK..APIlock"
- 
- #define PROC_SOCKET_FILE_PATH "/var/run/pkcsslotd.socket"
-+#define ADMIN_SOCKET_FILE_PATH "/var/run/pkcsslotd.admin.socket"
- 
- #define PID_FILE_PATH "/var/run/pkcsslotd.pid"
- #define OCK_CONFIG OCK_CONFDIR "/opencryptoki.conf"
-@@ -45,6 +46,7 @@
- 
- #define NUMBER_SLOTS_MANAGED 1024
- #define NUMBER_PROCESSES_ALLOWED  1000
-+#define NUMBER_ADMINS_ALLOWED     1000
- 
- //
- // Per Process Data structure
-diff --git a/usr/sbin/pkcsslotd/pkcsslotd.h b/usr/sbin/pkcsslotd/pkcsslotd.h
-index 69eb59f3..d7edcb3c 100644
---- a/usr/sbin/pkcsslotd/pkcsslotd.h
-+++ b/usr/sbin/pkcsslotd/pkcsslotd.h
-@@ -92,5 +92,8 @@ int init_socket_server();
- int term_socket_server();
- int init_socket_data(Slot_Mgr_Socket_t *sp);
- int socket_connection_handler(int timeout_secs);
-+#ifdef DEV
-+void dump_socket_handler();
-+#endif
- 
- #endif                          /* _SLOTMGR_H */
-diff --git a/usr/sbin/pkcsslotd/pkcsslotd.mk b/usr/sbin/pkcsslotd/pkcsslotd.mk
-index 2d36b4a9..c574edf8 100644
---- a/usr/sbin/pkcsslotd/pkcsslotd.mk
-+++ b/usr/sbin/pkcsslotd/pkcsslotd.mk
-@@ -8,6 +8,9 @@ CLEANFILES += usr/lib/common/parser.c usr/lib/common/parser.h	\
- 	usr/lib/common/parser.output usr/lib/common/lexer.c
- 
- usr_sbin_pkcsslotd_pkcsslotd_LDFLAGS = -lpthread -lcrypto
-+if HAVE_LIBUDEV
-+usr_sbin_pkcsslotd_pkcsslotd_LDFLAGS += -ludev
-+endif
- 
- usr_sbin_pkcsslotd_pkcsslotd_CFLAGS = -DPROGRAM_NAME=\"$(@)\"	\
- 	-I${srcdir}/usr/include -I${srcdir}/usr/lib/common	\
-diff --git a/usr/sbin/pkcsslotd/signal.c b/usr/sbin/pkcsslotd/signal.c
-index 49482a2f..17167632 100644
---- a/usr/sbin/pkcsslotd/signal.c
-+++ b/usr/sbin/pkcsslotd/signal.c
-@@ -21,7 +21,7 @@
- extern BOOL IsValidProcessEntry(pid_t_64 pid, time_t_64 RegTime);
- 
- static int SigsToIntercept[] = {
--    SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM,
-+    SIGHUP, SIGINT, SIGQUIT, SIGALRM,
-     SIGTERM, SIGTSTP, SIGTTIN,
-     SIGTTOU, SIGUSR1, SIGUSR2, SIGPROF
- };
-@@ -32,8 +32,11 @@ static int SigsToIntercept[] = {
- /* SIGCHLD - Don't want to exit.  Should never receive, but we do, apparently
-  * when something tries to cancel the GC Thread */
- 
-+/* SIGPIPE - Don't want to exit.  May happen when a connection to an admin
-+ * event sender or a process is closed before all events are delivered. */
-+
- static int SigsToIgnore[] = {
--    SIGCHLD,
-+    SIGCHLD, SIGPIPE,
- };
- 
- 
-@@ -71,6 +74,10 @@ void slotdGenericSignalHandler(int Signal)
-     CheckForGarbage(shmp);
- #endif
- 
-+#ifdef DEV
-+    dump_socket_handler();
-+#endif
-+
-     for (procindex = 0; (procindex < NUMBER_PROCESSES_ALLOWED); procindex++) {
- 
-         Slot_Mgr_Proc_t_64 *pProc = &(shmp->proc_table[procindex]);
-diff --git a/usr/sbin/pkcsslotd/socket_server.c b/usr/sbin/pkcsslotd/socket_server.c
-index 1fae0b95..41408670 100644
---- a/usr/sbin/pkcsslotd/socket_server.c
-+++ b/usr/sbin/pkcsslotd/socket_server.c
-@@ -1,4 +1,6 @@
- /*
-+ * COPYRIGHT (c) International Business Machines Corp. 2013, 2021
-+ *
-  * This program is provided under the terms of the Common Public License,
-  * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-  * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-@@ -12,6 +14,8 @@
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
-+#include <stdlib.h>
-+#include <fcntl.h>
- 
- #include <sys/time.h>
- #include <sys/socket.h>
-@@ -19,32 +23,1225 @@
- #include <sys/select.h>
- #include <sys/stat.h>
- #include <grp.h>
-+#include <sys/epoll.h>
-+
-+#if defined(__GNUC__) && __GNUC__ >= 7 || defined(__clang__) && __clang_major__ >= 12
-+    #define FALL_THROUGH __attribute__ ((fallthrough))
-+#else
-+    #define FALL_THROUGH ((void)0)
-+#endif
-+
-+#ifdef WITH_LIBUDEV
-+#include <libudev.h>
-+#endif
- 
- #include "log.h"
- #include "slotmgr.h"
- #include "pkcsslotd.h"
- #include "apictl.h"
-+#include "dlist.h"
-+#include "events.h"
-+
-+#define MAX_EPOLL_EVENTS            128
-+
-+#ifdef WITH_LIBUDEV
-+#define UDEV_RECV_BUFFFER_SIZE      512 * 1024
-+#define UDEV_SUBSYSTEM_AP           "ap"
-+#define UDEV_ACTION_BIND            "bind"
-+#define UDEV_ACTION_UNBIND          "unbind"
-+#define UDEV_ACTION_DEVTYPE_APQN    "ap_queue"
-+#define UDEV_PROERTY_DEVTYPE        "DEV_TYPE"
-+#endif
-+
-+struct epoll_info {
-+    int (* notify)(int events, void *private);
-+    void (* free)(void *private);
-+    void *private;
-+    unsigned long ref_count;
-+};
-+
-+struct listener_info {
-+    int socket;
-+    const char *file_path;
-+    int (* new_conn)(int socket, struct listener_info *listener);
-+    struct epoll_info ep_info;
-+    unsigned long num_clients;
-+    unsigned long max_num_clients;
-+};
-+
-+enum xfer_state {
-+    XFER_IDLE = 0,
-+    XFER_RECEIVE = 1,
-+    XFER_SEND = 2,
-+};
-+
-+struct client_info {
-+    int socket;
-+    int (* xfer_complete)(void *client);
-+    void (* hangup)(void *client);
-+    void (* free)(void *client);
-+    void *client;
-+    struct epoll_info ep_info;
-+    enum xfer_state xfer_state;
-+    char *xfer_buffer;
-+    size_t xfer_size;
-+    size_t xfer_offset;
-+};
-+
-+enum proc_state {
-+    PROC_INITIAL_SEND = 0,
-+    PROC_WAIT_FOR_EVENT = 1,
-+    PROC_SEND_EVENT = 2,
-+    PROC_SEND_PAYLOAD = 3,
-+    PROC_RECEIVE_REPLY = 4,
-+    PROC_HANGUP = 5,
-+};
-+
-+struct proc_conn_info {
-+    struct client_info client_info;
-+    enum proc_state state;
-+    DL_NODE *events;
-+    struct event_info *event;
-+    event_reply_t reply;
-+};
-+
-+enum admin_state {
-+    ADMIN_RECEIVE_EVENT = 0,
-+    ADMIN_RECEIVE_PAYLOAD = 1,
-+    ADMIN_EVENT_DELIVERED = 2,
-+    ADMIN_SEND_REPLY = 3,
-+    ADMIN_WAIT_FOR_EVENT_LIMIT = 4,
-+    ADMIN_HANGUP = 5,
-+};
-+
-+struct admin_conn_info {
-+    struct client_info client_info;
-+    enum admin_state state;
-+    struct event_info *event;
-+};
-+
-+#ifdef WITH_LIBUDEV
-+struct udev_mon {
-+    struct udev *udev;
-+    struct udev_monitor *mon;
-+    int socket;
-+    struct epoll_info ep_info;
-+    struct event_info *delayed_event;
-+};
-+#endif
-+
-+struct event_info {
-+    event_msg_t event;
-+    char *payload;
-+    event_reply_t reply;
-+    unsigned long proc_ref_count;      /* # of processes using this event */
-+    struct admin_conn_info *admin_ref; /* Admin connection to send reply back */
-+};
-+
-+static int epoll_fd = -1;
-+static struct listener_info proc_listener;
-+static DL_NODE *proc_connections = NULL;
-+static struct listener_info admin_listener;
-+static DL_NODE *admin_connections = NULL;
-+#ifdef WITH_LIBUDEV
-+static struct udev_mon udev_mon;
-+#endif
-+static DL_NODE *pending_events = NULL;
-+static unsigned long pending_events_count = 0;
-+
-+#define MAX_PENDING_EVENTS      1024
-+
-+/*
-+ * Iterate over all connections in a safe way. Before actually iterating,
-+ * increment the ref count of ALL connections, because any processing may
-+ * cause any of the connections to be hang-up, and thus freed and removed
-+ * from the list. We need to make sure that while we are iterating over the
-+ * connections, none of them gets removed from the list.
-+ */
-+#define FOR_EACH_CONN_SAFE_BEGIN(list, conn) {                              \
-+        DL_NODE *_node, *_next;                                             \
-+        _node = dlist_get_first(list);                                      \
-+        while (_node != NULL) {                                             \
-+            conn = _node->data;                                             \
-+            _next = dlist_next(_node);                                      \
-+            client_socket_get(&(conn)->client_info);                        \
-+            _node = _next;                                                  \
-+        }                                                                   \
-+        _node = dlist_get_first(list);                                      \
-+        while (_node != NULL) {                                             \
-+            conn = _node->data;                                             \
-+            _next = dlist_next(_node);
-+
-+#define FOR_EACH_CONN_SAFE_END(list, conn)                                  \
-+            _node = _next;                                                  \
-+        }                                                                   \
-+        _node = dlist_get_first(list);                                      \
-+        while (_node != NULL) {                                             \
-+            conn = _node->data;                                             \
-+            _next = dlist_next(_node);                                      \
-+            client_socket_put(&(conn)->client_info);                        \
-+            _node = _next;                                                  \
-+        }                                                                   \
-+    }
-+
-+
-+
-+static void listener_socket_close(int socketfd, const char *file_path);
-+static int listener_client_hangup(struct listener_info *listener);
-+static void event_delivered(struct event_info *event);
-+static int client_socket_notify(int events, void *private);
-+static void client_socket_free(void *private);
-+static int proc_xfer_complete(void *client);
-+static int proc_start_deliver_event(struct proc_conn_info *conn);
-+static int proc_deliver_event(struct proc_conn_info *conn,
-+                              struct event_info *event);
-+static int proc_event_delivered(struct proc_conn_info *conn,
-+                                struct event_info *event);
-+static inline void proc_get(struct proc_conn_info *conn);
-+static inline void proc_put(struct proc_conn_info *conn);
-+static void proc_hangup(void *client);
-+static void proc_free(void *client);
-+static int admin_xfer_complete(void *client);
-+static void admin_event_limit_underrun(struct admin_conn_info *conn);
-+static int admin_event_delivered(struct admin_conn_info *conn,
-+                                 struct event_info *event);
-+static inline void admin_get(struct admin_conn_info *conn);
-+static inline void admin_put(struct admin_conn_info *conn);
-+static void admin_hangup(void *client);
-+static void admin_free(void *client);
-+#ifdef WITH_LIBUDEV
-+static void udev_mon_term(struct udev_mon *udev_mon);
-+static int udev_mon_notify(int events, void *private);
-+#endif
-+
-+static void epoll_info_init(struct epoll_info *epoll_info,
-+                    int (* notify)(int events, void *private),
-+                    void (* free_cb)(void *private),
-+                    void *private)
-+{
-+    epoll_info->ref_count = 1;
-+    epoll_info->notify = notify;
-+    epoll_info->free = free_cb;
-+    epoll_info->private = private;
-+}
-+
-+static void epoll_info_get(struct epoll_info *epoll_info)
-+{
-+    epoll_info->ref_count++;
-+
-+    DbgLog(DL3, "%s: private: %p, ref_count: %lu", __func__,
-+           epoll_info->private, epoll_info->ref_count);
-+}
-+
-+static void epoll_info_put(struct epoll_info *epoll_info)
-+{
-+    if (epoll_info->ref_count > 0)
-+        epoll_info->ref_count--;
-+
-+    DbgLog(DL3, "%s: private: %p, ref_count: %lu", __func__,
-+           epoll_info->private, epoll_info->ref_count);
-+
-+    if (epoll_info->ref_count == 0 && epoll_info->free != NULL)
-+        epoll_info->free(epoll_info->private);
-+}
-+
-+static int client_socket_init(int socket, int (* xfer_complete)(void *client),
-+                              void (* hangup)(void *client),
-+                              void (* free_cb)(void *client), void *client,
-+                              struct client_info *client_info)
-+{
-+    struct epoll_event evt;
-+    int rc, err;
-+
-+    if (xfer_complete == NULL || hangup == NULL)
-+        return -EINVAL;
-+
-+    epoll_info_init(&client_info->ep_info, client_socket_notify,
-+                    client_socket_free, client_info);
-+    client_info->socket = socket;
-+    client_info->xfer_complete = xfer_complete;
-+    client_info->hangup = hangup;
-+    client_info->free = free_cb;
-+    client_info->client = client;
-+    client_info->xfer_state = XFER_IDLE;
-+
-+    rc = fcntl(socket, F_SETFL, O_NONBLOCK);
-+    if (rc < 0) {
-+        err = errno;
-+        InfoLog("%s: Failed to set client socket %d to non-blocking, errno "
-+                "%d (%s).", __func__, socket, err, strerror(err));
-+        return -err;
-+    }
-+
-+    evt.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP | EPOLLERR | EPOLLET;
-+    evt.data.ptr = &client_info->ep_info;
-+    rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, socket, &evt);
-+    if (rc != 0) {
-+        err = errno;
-+        InfoLog("%s: Failed to add client socket %d to epoll, errno %d (%s).",
-+                 __func__, socket, err, strerror(err));
-+        close(socket);
-+        return -err;
-+    }
-+
-+    return 0;
-+}
-+
-+static inline void client_socket_get(struct client_info *client_info)
-+{
-+    epoll_info_get(&client_info->ep_info);
-+}
-+
-+static inline void client_socket_put(struct client_info *client_info)
-+{
-+    epoll_info_put(&client_info->ep_info);
-+}
-+
-+static void client_socket_term(struct client_info *client_info)
-+{
-+    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, client_info->socket, NULL);
-+    close(client_info->socket);
-+    client_info->socket = -1;
-+}
-+
-+static int client_socket_notify(int events, void *private)
-+{
-+    struct client_info *client_info = private;
-+    ssize_t num;
-+    int rc, err, socket = client_info->socket;
-+
-+    DbgLog(DL3, "%s: Epoll event on client %p socket %d: events: 0x%x xfer: %d",
-+           __func__, client_info, socket, events, client_info->xfer_state);
-+
-+    if (socket < 0)
-+        return -ENOTCONN;
-+
-+    if (events & (EPOLLHUP | EPOLLERR)) {
-+        DbgLog(DL3, "EPOLLHUP | EPOLLERR");
-+
-+        client_info->hangup(client_info->client);
-+        client_info = NULL; /* client_info may have been freed by now */
-+        return 0;
-+    }
-+
-+    if (client_info->xfer_state == XFER_RECEIVE && (events & EPOLLIN)) {
-+        DbgLog(DL3, "%s: EPOLLIN: buffer: %p size: %lu ofs: %lu", __func__,
-+               client_info->xfer_buffer, client_info->xfer_size,
-+               client_info->xfer_offset);
-+
-+        num = read(client_info->socket,
-+                   client_info->xfer_buffer + client_info->xfer_offset,
-+                   client_info->xfer_size - client_info->xfer_offset);
-+        if (num <= 0) {
-+            err = errno;
-+
-+            DbgLog(DL3, "%s: read failed with: num: %d errno: %d (%s)",
-+                   __func__, num, num < 0 ? err : 0,
-+                   num < 0 ? strerror(err) : "none");
-+
-+            if (num < 0 && err == EWOULDBLOCK)
-+                return 0; /* Will be continued when socket becomes readable */
-+
-+            /* assume connection closed by peer */
-+            client_info->hangup(client_info->client);
-+            client_info = NULL; /* client_info may have been freed by now */
-+            return 0;
-+        } else {
-+            DbgLog(DL3, "%s: %lu bytes received", __func__, num);
-+
-+            client_info->xfer_offset += num;
-+
-+            DbgLog(DL3, "%s: %lu bytes left", __func__,
-+                   client_info->xfer_size - client_info->xfer_offset);
-+
-+            if (client_info->xfer_offset >= client_info->xfer_size) {
-+                client_info->xfer_state = XFER_IDLE;
-+                client_info->xfer_buffer = NULL;
-+                client_info->xfer_size = 0;
-+                client_info->xfer_offset = 0;
-+
-+                client_socket_get(client_info);
-+                rc = client_info->xfer_complete(client_info->client);
-+                if (rc != 0) {
-+                    InfoLog("%s: xfer_complete callback failed for client "
-+                            "socket %d, rc: %d", __func__, socket,
-+                            rc);
-+                    client_info->hangup(client_info->client);
-+                }
-+                client_socket_put(client_info);
-+                client_info = NULL; /* client_info may have been freed by now */
-+                return rc;
-+            }
-+            return 0;
-+        }
-+    }
-+
-+    if (client_info->xfer_state == XFER_SEND && (events & EPOLLOUT)) {
-+        DbgLog(DL3, "%s: EPOLLOUT: buffer: %p size: %lu ofs: %lu", __func__,
-+               client_info->xfer_buffer, client_info->xfer_size,
-+               client_info->xfer_offset);
-+
-+        num = write(client_info->socket,
-+                    client_info->xfer_buffer + client_info->xfer_offset,
-+                    client_info->xfer_size - client_info->xfer_offset);
-+        if (num < 0) {
-+            err = errno;
-+
-+            DbgLog(DL3, "%s: write failed with: errno: %d (%s)", __func__, err,
-+                   strerror(err));
-+
-+            if (err == EWOULDBLOCK)
-+                return 0; /* Will be continued when socket becomes writable */
-+
-+            /* assume connection closed by peer */
-+            client_info->hangup(client_info->client);
-+            client_info = NULL; /* client_info may have been freed by now */
-+            return 0;
-+        } else {
-+            DbgLog(DL3, "%s: %lu bytes sent", __func__, num);
-+
-+            client_info->xfer_offset += num;
-+
-+            DbgLog(DL3, "%s: %lu bytes left", __func__,
-+                   client_info->xfer_size - client_info->xfer_offset);
-+
-+            if (client_info->xfer_offset >= client_info->xfer_size) {
-+                client_info->xfer_state = XFER_IDLE;
-+                client_info->xfer_buffer = NULL;
-+                client_info->xfer_size = 0;
-+                client_info->xfer_offset = 0;
-+
-+                client_socket_get(client_info);
-+                rc = client_info->xfer_complete(client_info->client);
-+                if (rc != 0) {
-+                    InfoLog("%s: xfer_complete callback failed for client "
-+                            "socket %d, rc: %d", __func__, socket,
-+                            rc);
-+                    client_info->hangup(client_info->client);
-+                }
-+                client_socket_put(client_info);
-+                client_info = NULL; /* client_info may have been freed by now */
-+                return rc;
-+            }
-+            return 0;
-+        }
-+    }
-+
-+    return 0;
-+}
-+
-+static void client_socket_free(void *private)
-+{
-+    struct client_info *client_info = private;
-+
-+    DbgLog(DL3, "%s: %p", __func__, client_info);
-+
-+    if (client_info->free != NULL)
-+        client_info->free(client_info->client);
-+}
-+
-+static int client_socket_receive(struct client_info *client_info,
-+                                 void *buffer, size_t size)
-+{
-+    if (client_info->socket < 0)
-+        return -ENOTCONN;
-+
-+    client_info->xfer_state = XFER_RECEIVE;
-+    client_info->xfer_buffer = (char *)buffer;
-+    client_info->xfer_size = size;
-+    client_info->xfer_offset = 0;
-+
-+    DbgLog(DL3, "%s: Start receive on client socket %d: buffer: %p size: %lu",
-+            __func__, client_info->socket, buffer, size);
-+
-+    return client_socket_notify(EPOLLIN, client_info);
-+}
-+
-+
-+static int client_socket_send(struct client_info *client_info,
-+                              void *buffer, size_t size)
-+{
-+    if (client_info->socket < 0)
-+        return -ENOTCONN;
-+
-+    client_info->xfer_state = XFER_SEND;
-+    client_info->xfer_buffer = (char *)buffer;
-+    client_info->xfer_size = size;
-+    client_info->xfer_offset = 0;
-+
-+    DbgLog(DL3, "%s: Start send on client socket %d: buffer: %p size: %lu",
-+            __func__, client_info->socket, buffer, size);
-+
-+    return client_socket_notify(EPOLLOUT, client_info);
-+}
-+
-+static struct event_info *event_new(unsigned int payload_len,
-+                                    struct admin_conn_info *admin_conn)
-+{
-+    struct event_info *event;
-+
-+    event = calloc(1, sizeof(struct event_info));
-+    if (event == NULL) {
-+        ErrLog("%s: Failed to allocate the event", __func__);
-+        return NULL;
-+    }
-+
-+    event->event.version = EVENT_VERSION_1;
-+    event->event.payload_len = payload_len;
-+    if (payload_len > 0) {
-+        event->payload = malloc(payload_len);
-+        if (event->payload == NULL) {
-+            ErrLog("%s: Failed to allocate the event payload", __func__);
-+            free(event);
-+            return NULL;
-+        }
-+    }
-+
-+    event->reply.version = EVENT_VERSION_1;
-+
-+    if (admin_conn != NULL)
-+        admin_get(admin_conn);
-+    event->admin_ref = admin_conn;
-+
-+    DbgLog(DL3, "%s: allocated event: %p", __func__, event);
-+    return event;
-+}
-+
-+static void event_limit_underrun()
-+{
-+    struct admin_conn_info *conn;
-+
-+    DbgLog(DL3, "%s: pending_events_count: %lu", __func__, pending_events_count);
-+
-+#ifdef WITH_LIBUDEV
-+    /* Notify the udev monitor */
-+    udev_mon_notify(EPOLLIN, &udev_mon);
-+#endif
-+
-+    /* Notify all admin connections */
-+    FOR_EACH_CONN_SAFE_BEGIN(admin_connections, conn) {
-+        admin_event_limit_underrun(conn);
-+    }
-+    FOR_EACH_CONN_SAFE_END(admin_connections, conn)
-+}
-+
-+static void event_free(struct event_info *event)
-+{
-+    DbgLog(DL3, "%s: free event: %p", __func__, event);
-+
-+    if (event->payload != NULL)
-+        free(event->payload);
-+    free(event);
-+}
-+
-+static int event_add_to_pending_list(struct event_info *event)
-+{
-+    DL_NODE *list;
-+
-+    list = dlist_add_as_last(pending_events, event);
-+    if (list == NULL) {
-+        ErrLog("%s: failed add event to list of pending events", __func__);
-+        return -ENOMEM;
-+    }
-+    pending_events = list;
-+
-+    pending_events_count++;
-+
-+    return 0;
-+}
-+
-+static void event_remove_from_pending_list(struct event_info *event)
-+{
-+    DL_NODE *node;
-+    int trigger = 0;
-+
-+    node = dlist_find(pending_events, event);
-+    if (node != NULL) {
-+        pending_events = dlist_remove_node(pending_events, node);
-+
-+        if (pending_events_count >= MAX_PENDING_EVENTS)
-+            trigger = 1;
-+
-+        if (pending_events_count > 0)
-+            pending_events_count--;
-+
-+        if (trigger)
-+            event_limit_underrun();
-+    }
-+}
-+
-+static int event_start_deliver(struct event_info *event)
-+{
-+    struct proc_conn_info *conn;
-+    int rc;
-+
-+    DbgLog(DL3, "%s: event: %p", __func__, event);
-+
-+    if (pending_events_count >= MAX_PENDING_EVENTS) {
-+        InfoLog("%s: Max pending events reached", __func__);
-+        return -ENOSPC;
-+    }
-+
-+    /* Add event of the list of pending events */
-+    rc = event_add_to_pending_list(event);
-+    if (rc != 0)
-+        return rc;
-+
-+    /*
-+     * Need to increment the event's ref count here, proc_deliver_event() may
-+     * already complete the event delivery for one process, which then would
-+     * free the event but it needs to be passed to other processes here, too.
-+     */
-+    event->proc_ref_count++;
-+    FOR_EACH_CONN_SAFE_BEGIN(proc_connections, conn) {
-+        rc = proc_deliver_event(conn, event);
-+        if (rc != 0)
-+            proc_hangup(conn);
-+    }
-+    FOR_EACH_CONN_SAFE_END(proc_connections, conn)
-+    event->proc_ref_count--;
-+
-+    DbgLog(DL3, "%s: proc_ref_count: %u", __func__, event->proc_ref_count);
-+
-+    if (event->proc_ref_count == 0)
-+        event_delivered(event);
-+
-+    return 0;
-+}
-+
-+static void event_delivered(struct event_info *event)
-+{
-+    struct admin_conn_info *conn;
-+    int rc;
-+
-+    DbgLog(DL3, "%s: event: %p", __func__, event);
-+
-+    event_remove_from_pending_list(event);
-+
-+    /* Notify owning admin connection (if available), free otherwise */
-+    if (event->admin_ref != NULL) {
-+        conn = event->admin_ref;
-+        admin_get(conn);
-+        rc = admin_event_delivered(conn, event);
-+        if (rc != 0) {
-+            admin_hangup(conn);
-+            event_free(event);
-+        }
-+        admin_put(conn);
-+    } else {
-+        event_free(event);
-+    }
-+}
-+
-+static int proc_new_conn(int socket, struct listener_info *listener)
-+{
-+    struct proc_conn_info *conn;
-+    struct event_info *event;
-+    DL_NODE *list, *node;
-+    int rc = 0;
-+
-+    UNUSED(listener);
-+
-+    DbgLog(DL0, "%s: Accepted connection from process: socket: %d", __func__,
-+           socket);
-+
-+    conn = calloc(1, sizeof(struct proc_conn_info));
-+    if (conn == NULL) {
-+        ErrLog("%s: Failed to to allocate memory for the process connection",
-+               __func__);
-+        return -ENOMEM;
-+        /* Caller will close socket */
-+    }
-+
-+    DbgLog(DL3, "%s: process conn: %p", __func__, conn);
-+
-+    /* Add currently pending events to this connection */
-+    node = dlist_get_first(pending_events);
-+    while (node != NULL) {
-+        event = (struct event_info *)node->data;
-+        DbgLog(DL3, "%s: event: %p", __func__, event);
-+
-+        list = dlist_add_as_last(conn->events, event);
-+        if (list == NULL) {
-+            ErrLog("%s: failed add event to list of process's pending events",
-+                   __func__);
-+            rc = -ENOMEM;
-+            goto out;
-+        }
-+        conn->events = list;
-+
-+        event->proc_ref_count++;
-+
-+        node = dlist_next(node);
-+    }
-+
-+    conn->state = PROC_INITIAL_SEND;
-+
-+    rc = client_socket_init(socket, proc_xfer_complete, proc_hangup, proc_free,
-+                            conn, &conn->client_info);
-+    if (rc != 0)
-+        goto out;
-+
-+    /* Add it to the process connections list */
-+    list = dlist_add_as_first(proc_connections, conn);
-+    if (list == NULL) {
-+        rc = -ENOMEM;
-+        goto out;
-+    }
-+    proc_connections = list;
-+
-+    proc_get(conn);
-+    rc = client_socket_send(&conn->client_info, &socketData,
-+                            sizeof(socketData));
-+    proc_put(conn);
-+    conn = NULL; /* conn may have been freed by now */
-+
-+out:
-+    if (rc != 0 && conn != NULL) {
-+        proc_hangup(conn);
-+        rc = 0; /* Don't return an error, we have already handled it */
-+    }
-+
-+    return rc;
-+}
-+
-+static int proc_xfer_complete(void *client)
-+{
-+    struct proc_conn_info *conn = client;
-+    int rc;
-+
-+    DbgLog(DL0, "%s: Xfer completed: process: %p socket: %d state: %d",
-+           __func__, conn, conn->client_info.socket, conn->state);
-+
-+    /*
-+     * A non-zero return code returned by this function causes the caller to
-+     * call proc_hangup(). Thus, no need to call proc_hangup() ourselves.
-+     */
-+
-+    switch (conn->state) {
-+    case PROC_INITIAL_SEND:
-+        conn->state = PROC_WAIT_FOR_EVENT;
-+        rc = proc_start_deliver_event(conn);
-+        conn = NULL; /* conn may have been freed by now */
-+        return rc;
-+
-+    case PROC_WAIT_FOR_EVENT:
-+        /* handled in proc_start_deliver_event */
-+        break;
-+
-+    case PROC_SEND_EVENT:
-+        if (conn->event == NULL) {
-+            TraceLog("%s: No current event to handle", __func__);
-+            return -EINVAL;
-+        }
-+
-+        if (conn->event->event.payload_len > 0) {
-+            conn->state = PROC_SEND_PAYLOAD;
-+            rc = client_socket_send(&conn->client_info, conn->event->payload,
-+                                    conn->event->event.payload_len);
-+            conn = NULL; /* conn may have been freed by now */
-+            return rc;
-+        }
-+        FALL_THROUGH;
-+        /* fall through */
-+
-+    case PROC_SEND_PAYLOAD:
-+        if (conn->event == NULL) {
-+            TraceLog("%s: No current event to handle", __func__);
-+            return -EINVAL;
-+        }
-+
-+        if (conn->event->event.flags & EVENT_FLAGS_REPLY_REQ) {
-+            conn->state = PROC_RECEIVE_REPLY;
-+            rc = client_socket_receive(&conn->client_info, &conn->reply,
-+                                       sizeof(conn->reply));
-+            conn = NULL; /* conn may have been freed by now */
-+            return rc;
-+        }
-+        FALL_THROUGH;
-+        /* fall through */
-+
-+    case PROC_RECEIVE_REPLY:
-+        if (conn->event == NULL) {
-+            TraceLog("%s: No current event to handle", __func__);
-+            return -EINVAL;
-+        }
-+
-+        if (conn->event->event.flags & EVENT_FLAGS_REPLY_REQ) {
-+            if (conn->reply.version != EVENT_VERSION_1) {
-+                InfoLog("%s: Reply has a wrong version: %u", __func__,
-+                        conn->reply.version);
-+                return -EINVAL;
-+            }
-+
-+            /* Update reply counters in event */
-+            conn->event->reply.positive_replies += conn->reply.positive_replies;
-+            conn->event->reply.negative_replies += conn->reply.negative_replies;
-+            conn->event->reply.nothandled_replies +=
-+                                                conn->reply.nothandled_replies;
-+        }
-+
-+        conn->state = PROC_WAIT_FOR_EVENT;
-+
-+        rc = proc_event_delivered(conn, conn->event);
-+        conn = NULL; /* conn may have been freed by now */
-+        return rc;
-+
-+    case PROC_HANGUP:
-+        break;
-+    }
-+
-+    return 0;
-+}
-+
-+static int proc_start_deliver_event(struct proc_conn_info *conn)
-+{
-+    DL_NODE *node;
-+    int rc;
-+
-+    if (conn->state != PROC_WAIT_FOR_EVENT)
-+        return 0;
-+
-+    node = dlist_get_first(conn->events);
-+    if (node == NULL)
-+        return 0;
-+
-+    conn->event = node->data;
-+    memset(&conn->reply, 0, sizeof(conn->reply));
-+
-+    DbgLog(DL3, "%s: process: %p event: %p", __func__, conn, conn->event);
-+
-+    conn->state = PROC_SEND_EVENT;
-+    rc = client_socket_send(&conn->client_info, &conn->event->event,
-+                            sizeof(conn->event->event));
-+    conn = NULL; /* conn may have been freed by now */
-+    return rc;
-+}
-+
-+static int proc_deliver_event(struct proc_conn_info *conn,
-+                              struct event_info *event)
-+{
-+    DL_NODE *list;
-+    int rc;
-+
-+    DbgLog(DL3, "%s: process: %p event: %p", __func__, conn, event);
-+
-+    if (conn->state == PROC_HANGUP)
-+        return 0;
-+
-+    /* Add to process's event list and incr. reference count */
-+    list = dlist_add_as_last(conn->events, event);
-+    if (list == NULL) {
-+        ErrLog("%s: failed add event to list of process's pending events",
-+               __func__);
-+        return -ENOMEM;
-+    }
-+    conn->events = list;
-+
-+    event->proc_ref_count++;
-+
-+    rc = proc_start_deliver_event(conn);
-+    return rc;
-+}
-+
-+static int proc_event_delivered(struct proc_conn_info *conn,
-+                                struct event_info *event)
-+{
-+    DL_NODE *node;
-+    int rc;
-+
-+    DbgLog(DL3, "%s: process: %p event: %p", __func__, conn, event);
-+
-+    conn->event = NULL;
-+
-+    /* Remove from process's event list and decr. reference count */
-+    node = dlist_find(conn->events, event);
-+    if (node != NULL) {
-+        conn->events = dlist_remove_node(conn->events, node);
-+        event->proc_ref_count--;
-+    }
-+
-+    DbgLog(DL3, "%s: proc_ref_count: %u", __func__, event->proc_ref_count);
-+
-+    if (event->proc_ref_count == 0)
-+        event_delivered(event);
-+
-+    /* Deliver further pending events, if any */
-+    rc = proc_start_deliver_event(conn);
-+    conn = NULL; /* conn may have been freed by now */
-+    return rc;
-+}
-+
-+static inline void proc_get(struct proc_conn_info *conn)
-+{
-+    client_socket_get(&conn->client_info);
-+}
-+
-+static inline void proc_put(struct proc_conn_info *conn)
-+{
-+    client_socket_put(&conn->client_info);
-+}
-+
-+static void proc_hangup(void *client)
-+{
-+    struct proc_conn_info *conn = client;
-+    struct event_info *event;
-+    DL_NODE *node;
-+
-+    DbgLog(DL0, "%s: process: %p socket: %d state: %d", __func__, conn,
-+           conn->client_info.socket, conn->state);
-+
-+    if (conn->state == PROC_HANGUP)
-+        return;
-+    conn->state = PROC_HANGUP;
-+
-+    /* Unlink all pending events */
-+    while ((node = dlist_get_first(conn->events)) != NULL) {
-+        event = node->data;
-+        /* We did not handle this event */
-+        event->reply.nothandled_replies++;
-+        proc_event_delivered(conn, event);
-+    }
-+
-+    client_socket_term(&conn->client_info);
-+    proc_put(conn);
-+}
-+
-+static void proc_free(void *client)
-+{
-+    struct proc_conn_info *conn = client;
-+    DL_NODE *node;
-+
-+    /* Remove it from the process connections list */
-+    node = dlist_find(proc_connections, conn);
-+    if (node != NULL) {
-+        proc_connections = dlist_remove_node(proc_connections, node);
-+        listener_client_hangup(&proc_listener);
-+    }
-+
-+    DbgLog(DL0, "%s: process: %p", __func__, conn);
-+    free(conn);
-+}
-+
-+static int admin_new_conn(int socket, struct listener_info *listener)
-+{
-+    struct admin_conn_info *conn;
-+    DL_NODE *list;
-+    int rc = 0;
-+
-+    UNUSED(listener);
-+
-+    DbgLog(DL0, "%s: Accepted connection from admin: socket: %d", __func__,
-+           socket);
-+
-+    conn = calloc(1, sizeof(struct admin_conn_info));
-+    if (conn == NULL) {
-+        ErrLog("%s: Failed to to allocate memory for the admin connection",
-+               __func__);
-+        return -ENOMEM;
-+        /* Caller will close socket */
-+    }
-+
-+    DbgLog(DL3, "%s: admin conn: %p", __func__, conn);
-+
-+    conn->state = ADMIN_RECEIVE_EVENT;
-+
-+    rc = client_socket_init(socket, admin_xfer_complete, admin_hangup,
-+                            admin_free, conn, &conn->client_info);
-+    if (rc != 0)
-+        goto out;
-+
-+    conn->event = event_new(0, conn);
-+    if (conn->event == NULL) {
-+        ErrLog("%s: Failed to allocate a new event", __func__);
-+        rc = -ENOMEM;
-+        goto out;
-+    }
-+
-+    /* Add it to the admin connections list */
-+    list = dlist_add_as_first(admin_connections, conn);
-+    if (list == NULL) {
-+        ErrLog("%s: Failed to add connection to list of admin connections",
-+               __func__);
-+        rc = -ENOMEM;
-+        goto out;
-+    }
-+    admin_connections = list;
-+
-+    admin_get(conn);
-+    rc = client_socket_receive(&conn->client_info, &conn->event->event,
-+                               sizeof(conn->event->event));
-+    admin_put(conn);
-+    conn = NULL; /* conn may have been freed by now */
-+
-+out:
-+    if (rc != 0 && conn != NULL) {
-+        admin_hangup(conn);
-+        rc = 0; /* Don't return an error, we have already handled it */
-+    }
-+
-+    return rc;
-+}
-+
-+static int admin_xfer_complete(void *client)
-+{
-+    struct admin_conn_info *conn = client;
-+    int rc;
-+
-+    DbgLog(DL0, "%s: Xfer completed: admin: %p socket: %d state: %d",
-+           __func__, conn, conn->client_info.socket, conn->state);
-+
-+    /*
-+     * A non-zero return code returned by this function causes the caller to
-+     * call admin_hangup(). Thus, no need to call admin_hangup() ourselves.
-+     */
-+
-+    if (conn->event == NULL) {
-+        TraceLog("%s: No current event", __func__);
-+        return -EINVAL;
-+    }
-+
-+    switch (conn->state) {
-+    case ADMIN_RECEIVE_EVENT:
-+        /* We have received the event from the admin */
-+        DbgLog(DL3, "%s: Event version:      %u", __func__,
-+               conn->event->event.version);
-+        DbgLog(DL3, "%s: Event type:         0x%08x", __func__,
-+               conn->event->event.type);
-+        DbgLog(DL3, "%s: Event flags:        0x%08x", __func__,
-+               conn->event->event.flags);
-+        DbgLog(DL3, "%s: Event token_type:   0x%08x", __func__,
-+               conn->event->event.token_type);
-+        DbgLog(DL3, "%s: Event token_name:   '%.32s'", __func__,
-+               conn->event->event.token_label);
-+        DbgLog(DL3, "%s: Event process_id:   %u", __func__,
-+               conn->event->event.process_id);
-+        DbgLog(DL3, "%s: Event payload_len:  %u", __func__,
-+               conn->event->event.payload_len);
-+
-+        if (conn->event->event.version != EVENT_VERSION_1) {
-+            InfoLog("%s: Admin event has invalid version: %d", __func__,
-+                    conn->event->event.version);
-+            return -EINVAL;
-+        }
-+        if (conn->event->event.payload_len > EVENT_MAX_PAYLOAD_LENGTH) {
-+            InfoLog("%s: Admin event payload is too large: %u", __func__,
-+                    conn->event->event.payload_len);
-+            return -EMSGSIZE;
-+        }
-+
-+        if (conn->event->event.payload_len > 0) {
-+            conn->event->payload = malloc(conn->event->event.payload_len);
-+            if (conn->event->payload == NULL) {
-+                ErrLog("%s: Failed to allocate the payload buffer", __func__);
-+                return -ENOMEM;
-+            }
-+
-+            conn->state = ADMIN_RECEIVE_PAYLOAD;
-+            rc = client_socket_receive(&conn->client_info, conn->event->payload,
-+                                       conn->event->event.payload_len);
-+            conn = NULL; /* conn may have been freed by now */
-+            return rc;
-+        }
-+        FALL_THROUGH;
-+        /* fall through */
-+
-+    case ADMIN_RECEIVE_PAYLOAD:
-+        /* We have received the payload (if any) from the admin */
-+        conn->state = ADMIN_EVENT_DELIVERED;
-+        rc = event_start_deliver(conn->event);
-+        if (rc != 0) {
-+            if (rc == -ENOSPC) {
-+                /* Event limit reached, delay */
-+                conn->state = ADMIN_WAIT_FOR_EVENT_LIMIT;
-+                return 0;
-+            }
-+            return rc;
-+        }
-+        break;
-+
-+    case ADMIN_WAIT_FOR_EVENT_LIMIT:
-+        /* This state is handled in admin_event_limit_underrun() */
-+        break;
-+
-+    case ADMIN_EVENT_DELIVERED:
-+        /* This state is handled in admin_event_delivered() */
-+        break;
-+
-+    case ADMIN_SEND_REPLY:
-+        /* The reply has been sent to the admin */
-+        if (conn->event->admin_ref != NULL)
-+            admin_put(conn->event->admin_ref);
-+        conn->event->admin_ref = NULL;
-+        event_free(conn->event);
-+
-+        conn->event = event_new(0, conn);
-+        if (conn->event == NULL) {
-+            ErrLog("%s: Failed to allocate a new event", __func__);
-+            return -ENOMEM;
-+        }
-+
-+        conn->state = ADMIN_RECEIVE_EVENT;
-+        rc = client_socket_receive(&conn->client_info, &conn->event->event,
-+                                   sizeof(conn->event->event));
-+        conn = NULL; /* conn may have been freed by now */
-+        return rc;
-+
-+    case ADMIN_HANGUP:
-+        break;
-+    }
-+
-+    return 0;
-+}
-+
-+static void admin_event_limit_underrun(struct admin_conn_info *conn)
-+{
-+    int rc;
-+
-+    DbgLog(DL3, "%s: admin: %p state: %d", __func__, conn, conn->state);
-+
-+    if (conn->state != ADMIN_WAIT_FOR_EVENT_LIMIT)
-+        return;
-+
-+    conn->state = ADMIN_EVENT_DELIVERED;
-+
-+    rc = event_start_deliver(conn->event);
-+    if (rc != 0) {
-+        if (rc == -ENOSPC) {
-+            /* Event limit reached, delay */
-+            conn->state = ADMIN_WAIT_FOR_EVENT_LIMIT;
-+            return;
-+        }
-+        admin_hangup(conn);
-+    }
-+}
-+
-+static int admin_event_delivered(struct admin_conn_info *conn,
-+                                 struct event_info *event)
-+{
-+    int rc;
-+
-+    DbgLog(DL3, "%s: admin: %p event: %p", __func__, conn, event);
-+
-+    /*
-+     * A non-zero return code returned by this function causes the caller to
-+     * call admin_hangup(). Thus, no need to call admin_hangup() ourselves.
-+     */
-+
-+    if (conn->state != ADMIN_EVENT_DELIVERED) {
-+        TraceLog("%s: wrong state: %d", __func__, conn->state);
-+        return -EINVAL;
-+    }
-+
-+    if (event->event.flags & EVENT_FLAGS_REPLY_REQ) {
-+        if (conn->event != event) {
-+            TraceLog("%s: event not the current event", __func__);
-+            return -EINVAL;
-+        }
-+
-+        DbgLog(DL3, "%s: Reply version:      %u", __func__,
-+               event->reply.version);
-+        DbgLog(DL3, "%s: Reply positive:     %lu", __func__,
-+               event->reply.positive_replies);
-+        DbgLog(DL3, "%s: Reply negative:     %lu", __func__,
-+               event->reply.negative_replies);
-+        DbgLog(DL3, "%s: Reply not-handled:  %lu", __func__,
-+               event->reply.nothandled_replies);
-+
-+        conn->state = ADMIN_SEND_REPLY;
-+        rc = client_socket_send(&conn->client_info, &event->reply,
-+                                sizeof(event->reply));
-+        return rc;
-+    }
-+
-+    /* No reply required, free the event, and receive the next one */
-+    if (event->admin_ref != NULL)
-+        admin_put(event->admin_ref);
-+    event->admin_ref = NULL;
-+    event_free(event);
-+
-+    conn->event = event_new(0, conn);
-+    if (conn->event == NULL) {
-+        ErrLog("%s: Failed to allocate a new event", __func__);
-+        return -ENOMEM;
-+    }
-+
-+    conn->state = ADMIN_RECEIVE_EVENT;
-+    rc = client_socket_receive(&conn->client_info, &conn->event->event,
-+                               sizeof(conn->event->event));
-+    return rc;
-+}
-+
-+static inline void admin_get(struct admin_conn_info *conn)
-+{
-+    client_socket_get(&conn->client_info);
-+}
-+
-+static inline void admin_put(struct admin_conn_info *conn)
-+{
-+    client_socket_put(&conn->client_info);
-+}
-+
-+static void admin_hangup(void *client)
-+{
-+    struct admin_conn_info *conn = client;
-+
-+    DbgLog(DL0, "%s: admin: %p socket: %d state: %d", __func__, conn,
-+           conn->client_info.socket, conn->state);
-+
-+    if (conn->state == ADMIN_HANGUP)
-+        return;
-+    conn->state = ADMIN_HANGUP;
-+
-+    /* Unlink pending event (if any) */
-+    if (conn->event != NULL) {
-+        if (conn->event->admin_ref != NULL)
-+            admin_put(conn->event->admin_ref);
-+        conn->event->admin_ref = NULL;
-+        if (conn->event->proc_ref_count == 0) {
-+            event_remove_from_pending_list(conn->event);
-+            event_free(conn->event);
-+        }
-+        conn->event = NULL;
-+    }
-+
-+    client_socket_term(&conn->client_info);
-+    admin_put(conn);
-+}
-+
-+static void admin_free(void *client)
-+{
-+    struct admin_conn_info *conn = client;
-+    DL_NODE *node;
- 
--int proc_listener_socket = -1;
-+    /* Remove it from the admin connections list */
-+    node = dlist_find(admin_connections, conn);
-+    if (node != NULL) {
-+        admin_connections = dlist_remove_node(admin_connections, node);
-+        listener_client_hangup(&admin_listener);
-+    }
- 
--static void close_listener_socket(int socketfd, const char *file_path);
-+    DbgLog(DL0, "%s: admin: %p", __func__, conn);
-+    free(conn);
-+}
- 
--// Creates the daemon's listener socket, to which clients will connect and
--// retrieve slot information through.  Returns the file descriptor of the
--// created socket.
--static int create_listener_socket(const char *file_path)
-+static int listener_socket_create(const char *file_path)
- {
-     struct sockaddr_un address;
-     struct group *grp;
--    int socketfd;
-+    int listener_socket, err;
- 
--    socketfd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
--    if (socketfd < 0) {
--        ErrLog("Failed to create listener socket, errno 0x%X.", errno);
-+    listener_socket = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
-+    if (listener_socket < 0) {
-+        err = errno;
-+        ErrLog("%s: Failed to create listener socket, errno %d (%s).",
-+               __func__, err, strerror(err));
-         return -1;
-     }
-     if (unlink(file_path) && errno != ENOENT) {
--        ErrLog("Failed to unlink socket file, errno 0x%X.", errno);
-+        err = errno;
-+        ErrLog("%s: Failed to unlink socket file, errno %d (%s).", __func__,
-+               err, strerror(err));
-         goto error;
-     }
- 
-@@ -52,50 +1249,389 @@ static int create_listener_socket(const char *file_path)
-     address.sun_family = AF_UNIX;
-     strcpy(address.sun_path, file_path);
- 
--    if (bind(socketfd,
-+    if (bind(listener_socket,
-              (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) {
--        ErrLog("Failed to bind to socket, errno 0x%X.", errno);
-+        err = errno;
-+        ErrLog("%s: Failed to bind to socket, errno %d (%s).", __func__, err,
-+               strerror(err));
-         goto error;
-     }
-     // make socket file part of the pkcs11 group, and write accessable
-     // for that group
-     grp = getgrnam("pkcs11");
-     if (!grp) {
--        ErrLog("Group PKCS#11 does not exist");
-+        ErrLog("%s: Group PKCS#11 does not exist", __func__);
-         goto error;
-     }
-     if (chown(file_path, 0, grp->gr_gid)) {
--        ErrLog("Could not change file group on socket, errno 0x%X.", errno);
-+        err = errno;
-+        ErrLog("%s: Could not change file group on socket, errno %d (%s).",
-+               __func__, err, strerror(err));
-         goto error;
-     }
-     if (chmod(file_path,
--              S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP | S_IXUSR | S_IXGRP)) {
--        ErrLog("Could not change file permissions on socket, errno 0x%X.",
--               errno);
-+              S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP)) {
-+        err = errno;
-+        ErrLog("%s: Could not change file permissions on socket, errno %d (%s).",
-+                __func__, err, strerror(err));
-         goto error;
-     }
- 
--    if (listen(socketfd, 20) != 0) {
--        ErrLog("Failed to listen to socket, errno 0x%X.", errno);
-+    if (listen(listener_socket, 20) != 0) {
-+        err = errno;
-+        ErrLog("%s: Failed to listen to socket, errno %d (%s).", __func__, err,
-+               strerror(err));
-         goto error;
-     }
- 
--    return socketfd;
-+    return listener_socket;
- 
- error:
--    if (socketfd >= 0)
--        close_listener_socket(socketfd, file_path);
-+    if (listener_socket >= 0)
-+        listener_socket_close(listener_socket, file_path);
- 
-     return -1;
- }
- 
- 
--static void close_listener_socket(int socketfd, const char *file_path)
-+static void listener_socket_close(int listener_socket, const char *file_path)
- {
--    close(socketfd);
-+    close(listener_socket);
-     unlink(file_path);
- }
- 
-+
-+
-+static int listener_notify(int events, void *private)
-+{
-+    struct listener_info *listener = private;
-+    struct sockaddr_un address;
-+    socklen_t address_length = sizeof(address);
-+    int client_socket, rc, err;
-+
-+    if ((events & EPOLLIN) == 0)
-+        return 0;
-+
-+    /* epoll is edge triggered. We must call accept until we get EWOULDBLOCK */
-+    while (listener->num_clients < listener->max_num_clients) {
-+        client_socket = accept(listener->socket, (struct sockaddr *) &address,
-+                               &address_length);
-+        if (client_socket < 0) {
-+            err = errno;
-+            if (err == EWOULDBLOCK)
-+                break;
-+            InfoLog("%s: Failed to accept connection on socket %d, errno %d (%s).",
-+                    __func__, listener->socket, err, strerror(err));
-+            return -err;
-+        }
-+
-+        rc = listener->new_conn(client_socket, listener);
-+        if (rc != 0) {
-+            TraceLog("%s: new_conn callback failed for client socket %d, rc: %d",
-+                      __func__, client_socket, rc);
-+            close(client_socket);
-+            continue;
-+        }
-+
-+        listener->num_clients++;
-+    }
-+
-+    return 0;
-+}
-+
-+static int listener_client_hangup(struct listener_info *listener)
-+{
-+    int rc, trigger = 0;
-+
-+    if (listener->num_clients >= listener->max_num_clients)
-+        trigger = 1; /* We were at max clients, trigger accept now */
-+
-+    if (listener->num_clients > 0)
-+        listener->num_clients--;
-+
-+    if (trigger && listener->num_clients < listener->max_num_clients) {
-+        rc = listener_notify(EPOLLIN, listener);
-+        if (rc != 0)
-+            return rc;
-+    }
-+
-+    return 0;
-+}
-+
-+static int listener_create(const char *file_path,
-+                           struct listener_info *listener,
-+                           int (* new_conn)(int socket,
-+                                            struct listener_info *listener),
-+                           unsigned long max_num_clients)
-+{
-+    struct epoll_event evt;
-+    int rc, err;
-+
-+    if (listener == NULL || new_conn == NULL)
-+        return FALSE;
-+
-+    memset(listener, 0, sizeof(*listener));
-+    epoll_info_init(&listener->ep_info, listener_notify, NULL, listener);
-+    listener->file_path = file_path;
-+    listener->new_conn = new_conn;
-+    listener->max_num_clients = max_num_clients;
-+
-+    listener->socket = listener_socket_create(file_path);
-+    if (listener->socket < 0)
-+        return FALSE;
-+
-+    evt.events = EPOLLIN | EPOLLET;
-+    evt.data.ptr = &listener->ep_info;
-+    rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listener->socket, &evt);
-+    if (rc != 0) {
-+        err = errno;
-+        TraceLog("%s: Failed add listener socket %d to epoll, errno %d (%s).",
-+                  __func__, listener->socket, err, strerror(err));
-+        return FALSE;
-+    }
-+
-+    return TRUE;
-+}
-+
-+static void listener_term(struct listener_info *listener)
-+{
-+    if (listener == NULL || listener->socket < 0)
-+        return;
-+
-+    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, listener->socket, NULL);
-+    listener_socket_close(listener->socket, listener->file_path);
-+}
-+
-+#ifdef WITH_LIBUDEV
-+
-+static int udev_mon_init(const char *subsystem, struct udev_mon *udev_mon)
-+{
-+    struct epoll_event evt;
-+    int rc, err;
-+
-+    if (subsystem == NULL || udev_mon == NULL)
-+        return FALSE;
-+
-+    udev_mon->delayed_event = 0;
-+
-+    udev_mon->udev = udev_new();
-+    if (udev_mon->udev == NULL) {
-+        ErrLog("%s: udev_new failed", __func__);
-+        goto error;
-+    }
-+
-+    udev_mon->mon = udev_monitor_new_from_netlink(udev_mon->udev, "udev");
-+    if (udev_mon->mon == NULL) {
-+        ErrLog("%s: udev_monitor_new_from_netlink failed", __func__);
-+        goto error;
-+    }
-+
-+    /*
-+     * Try to increase the receive buffer size. This may fail if the required
-+     * privileges are not given. Ignore if it fails.
-+     */
-+    udev_monitor_set_receive_buffer_size(udev_mon->mon, UDEV_RECV_BUFFFER_SIZE);
-+
-+    rc = udev_monitor_filter_add_match_subsystem_devtype(udev_mon->mon,
-+                                                         subsystem, NULL);
-+    if (rc != 0) {
-+        ErrLog("%s: udev_monitor_filter_add_match_subsystem_devtype failed: "
-+               "rc=%d", __func__, rc);
-+        goto error;
-+    }
-+
-+    rc = udev_monitor_enable_receiving(udev_mon->mon);
-+    if (rc != 0) {
-+        ErrLog("%s: udev_monitor_enable_receiving failed: rc=%d", __func__, rc);
-+        goto error;
-+    }
-+
-+    udev_mon->socket = udev_monitor_get_fd(udev_mon->mon);
-+    if (udev_mon->socket < 0) {
-+        ErrLog("%s: udev_monitor_get_fd failed", __func__);
-+        goto error;
-+    }
-+
-+    epoll_info_init(&udev_mon->ep_info, udev_mon_notify, NULL, udev_mon);
-+
-+    evt.events = EPOLLIN | EPOLLET;
-+    evt.data.ptr = &udev_mon->ep_info;
-+    rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, udev_mon->socket, &evt);
-+    if (rc != 0) {
-+        err = errno;
-+        ErrLog("%s: Failed add udev_mon socket %d to epoll, errno %d (%s).",
-+                __func__, udev_mon->socket, err, strerror(err));
-+        goto error;
-+    }
-+
-+    /* Epoll is edge triggered, thus try to receive once */
-+    rc = udev_mon_notify(EPOLLIN, udev_mon);
-+    if (rc != 0)
-+        goto error;
-+
-+    return TRUE;
-+
-+error:
-+    udev_mon_term(udev_mon);
-+    return FALSE;
-+}
-+
-+
-+static int udev_mon_handle_device(struct udev_mon *udev_mon,
-+                                  struct udev_device *dev)
-+{
-+    const char *action, *devname, *devpath, *devtype, *dev_type_prop;
-+    unsigned int card, domain, dev_type;
-+    struct event_info *event;
-+    event_udev_apqn_data_t *apqn_data;
-+    int rc;
-+
-+    UNUSED(udev_mon);
-+
-+    action = udev_device_get_action(dev);
-+    devname = udev_device_get_sysname(dev);
-+    devpath = udev_device_get_devpath(dev);
-+    devtype = udev_device_get_devtype(dev);
-+    dev_type_prop = udev_device_get_property_value(dev, UDEV_PROERTY_DEVTYPE);
-+
-+    if (action == NULL || devname == NULL || devpath == NULL ||
-+        devtype == NULL || dev_type_prop == NULL)
-+        return 0;
-+
-+    DbgLog(DL3, "%s: Uevent: ACTION=%s DEVNAME=%s DEVPATH=%s DEVTYPE=%s "
-+           "DEV_TYPE=%s", __func__, action, devname, devpath, devtype,
-+           dev_type_prop);
-+
-+    /* We are only interested in bind and unbind events ... */
-+    if (strcmp(action, UDEV_ACTION_BIND) != 0 &&
-+        strcmp(action, UDEV_ACTION_UNBIND) != 0)
-+        return 0;
-+
-+    /* ... for an APQN device */
-+    if (strcmp(devtype, UDEV_ACTION_DEVTYPE_APQN) != 0)
-+        return 0;
-+
-+    if (sscanf(devname, "%x.%x", &card, &domain) != 2) {
-+        TraceLog("%s: failed to parse APQN from DEVNAME: %s", __func__, devname);
-+        return -EIO;
-+    }
-+    if (sscanf(dev_type_prop, "%x", &dev_type) != 1) {
-+        TraceLog("%s: failed to parse DEV_TYPE: %s", __func__, dev_type_prop);
-+        return -EIO;
-+    }
-+
-+    event = event_new(sizeof(event_udev_apqn_data_t), NULL);
-+    if (event == NULL) {
-+        ErrLog("%s: failed to allocate an event", __func__);
-+        return -ENOMEM;
-+    }
-+
-+    if (strcmp(udev_device_get_action(dev), UDEV_ACTION_BIND) == 0)
-+        event->event.type = EVENT_TYPE_APQN_ADD;
-+    else
-+        event->event.type = EVENT_TYPE_APQN_REMOVE;
-+    event->event.flags = EVENT_FLAGS_NONE;
-+    event->event.token_type = EVENT_TOK_TYPE_ALL;
-+    memset(event->event.token_label, ' ',
-+           sizeof(event->event.token_label));
-+
-+    apqn_data = (event_udev_apqn_data_t *)event->payload;
-+    apqn_data->card = card;
-+    apqn_data->domain = domain;
-+    apqn_data->device_type = dev_type;
-+
-+    DbgLog(DL3, "%s: Event version:      %u", __func__, event->event.version);
-+    DbgLog(DL3, "%s: Event type:         0x%08x", __func__, event->event.type);
-+    DbgLog(DL3, "%s: Event flags:        0x%08x", __func__, event->event.flags);
-+    DbgLog(DL3, "%s: Event token_type:   0x%08x", __func__,
-+           event->event.token_type);
-+    DbgLog(DL3, "%s: Event token_name:   '%.32s'", __func__,
-+           event->event.token_label);
-+    DbgLog(DL3, "%s: Event process_id:   %u", __func__, event->event.process_id);
-+    DbgLog(DL3, "%s: Event payload_len:  %u", __func__,
-+           event->event.payload_len);
-+
-+    DbgLog(DL3, "%s: Payload: card:      %u", __func__, apqn_data->card);
-+    DbgLog(DL3, "%s: Payload: domain:    %u", __func__, apqn_data->domain);
-+    DbgLog(DL3, "%s: Payload: dev.type:  %u", __func__, apqn_data->device_type);
-+
-+    rc = event_start_deliver(event);
-+    if (rc != 0) {
-+        if (rc == -ENOSPC) {
-+            /* Event limit reached, delay event delivery */
-+            udev_mon->delayed_event = event;
-+            return -ENOSPC;
-+        }
-+        event_free(event);
-+        return rc;
-+    }
-+
-+    return 0;
-+}
-+
-+static int udev_mon_notify(int events, void *private)
-+{
-+    struct udev_mon *udev_mon = private;
-+    struct udev_device *dev;
-+    struct event_info *event;
-+    int rc;
-+
-+    DbgLog(DL3, "%s: Epoll event on udev_mon socket %d: events: 0x%x",
-+           __func__, udev_mon->socket, events);
-+
-+    if (udev_mon->delayed_event != NULL) {
-+        /* Deliver delayed event first */
-+        event = udev_mon->delayed_event;
-+        udev_mon->delayed_event = NULL;
-+
-+        rc = event_start_deliver(event);
-+        if (rc != 0) {
-+            if (rc == -ENOSPC) {
-+                /* Event limit reached, delay event delivery */
-+                udev_mon->delayed_event = event;
-+                return 0;
-+            }
-+            event_free(event);
-+            return rc;
-+        }
-+    }
-+
-+    while (1) {
-+        dev = udev_monitor_receive_device(udev_mon->mon);
-+        if (dev == NULL)
-+            break; /* this is just like EWOULDBLOCK */
-+
-+        rc = udev_mon_handle_device(udev_mon, dev);
-+        if (rc != 0)
-+            TraceLog("%s: udev_mon_handle_device failed, rc: %d", __func__, rc);
-+
-+        udev_device_unref(dev);
-+
-+        /* If event limit reached, stop receiving more events */
-+        if (rc == -ENOSPC)
-+            break;
-+    };
-+
-+    return 0;
-+}
-+
-+static void udev_mon_term(struct udev_mon *udev_mon)
-+{
-+    if (udev_mon == NULL)
-+        return;
-+
-+    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, udev_mon->socket, NULL);
-+    if (udev_mon->udev != NULL)
-+        udev_unref(udev_mon->udev);
-+    if (udev_mon->mon != NULL)
-+        udev_monitor_unref(udev_mon->mon);
-+
-+    if (udev_mon->delayed_event != NULL)
-+        event_free(udev_mon->delayed_event);
-+}
-+
-+#endif
-+
- int init_socket_data(Slot_Mgr_Socket_t *socketData)
- {
-     unsigned int processed = 0;
-@@ -106,7 +1642,7 @@ int init_socket_data(Slot_Mgr_Socket_t *socketData)
- 
-     /* check that we read in correct amount of slots */
-     if (processed != NumberSlotsInDB) {
--        ErrLog("Failed to populate slot info.\n");
-+        ErrLog("%s: Failed to populate slot info.", __func__);
-         return FALSE;
-     }
- 
-@@ -115,72 +1651,277 @@ int init_socket_data(Slot_Mgr_Socket_t *socketData)
- 
- int socket_connection_handler(int timeout_secs)
- {
--    int returnVal;
--    fd_set set;
--    struct timeval timeout;
--
--    FD_ZERO(&set);
--    FD_SET(proc_listener_socket, &set);
-+    struct epoll_event events[MAX_EPOLL_EVENTS];
-+    int num_events, i, rc, err;
-+    struct epoll_info *info;
- 
--    timeout.tv_sec = timeout_secs;
--    timeout.tv_usec = 0;
--
--    returnVal = select(proc_listener_socket + 1, &set, NULL, NULL, &timeout);
--    if (returnVal == -1) {
--        ErrLog("select failed on socket connection, errno 0x%X.", errno);
--        return FALSE;
--    } else if (returnVal == 0) {
--        // select call timed out, return
--        return FALSE;
--    } else {
--        struct sockaddr_un address;
--        socklen_t address_length = sizeof(address);
--
--        int connectionfd = accept(proc_listener_socket,
--                                  (struct sockaddr *) &address,
--                                  &address_length);
--        if (connectionfd < 0) {
--            if (errno != EAGAIN && errno != EWOULDBLOCK) {
--                /* These errors are allowed since
--                 * socket is non-blocking
--                 */
--                ErrLog("Failed to accept socket connection, errno 0x%X.",
--                       errno);
--            }
-+    do {
-+        num_events = epoll_wait(epoll_fd, events, MAX_EPOLL_EVENTS,
-+                                timeout_secs * 1000);
-+        if (num_events < 0) {
-+            err = errno;
-+            if (err == EINTR)
-+                continue;
-+            ErrLog("%s: epoll_wait failed, errno %d (%s).", __func__, err,
-+                   strerror(err));
-             return FALSE;
-         }
- 
--        DbgLog(DL0, "Accepted connection from process: socket: %d", 
--               connectionfd);
-+        /*
-+         * Inc ref count of all epoll_infos returned by epoll before handling
-+         * any of them via notify. The notify callback may hangup any of
-+         * the connections associated with the returned epoll_infos, and we
-+         * need to avoid them getting freed before we all handled them.
-+         */
-+        for (i = 0; i < num_events; i++)
-+            epoll_info_get(events[i].data.ptr);
- 
--        if (write(connectionfd, &socketData, sizeof(socketData)) !=
--            sizeof(socketData)) {
--            ErrLog("Failed to write socket data, errno 0x%X.", errno);
--            close(connectionfd);
--            return FALSE;
-+        for (i = 0; i < num_events; i++) {
-+            info = events[i].data.ptr;
-+            if (info == NULL || info->notify == NULL)
-+                continue;
-+
-+            rc = info->notify(events[i].events, info->private);
-+            if (rc != 0)
-+                TraceLog("%s: notify callback failed, rc: %d", __func__, rc);
-+
-+            epoll_info_put(info);
-         }
--        close(connectionfd);
--        return TRUE;
--    }
-+    } while (num_events > 0 && rc == 0); /* num_events = 0: timeout */
-+
-+    return TRUE;
- }
- 
- int init_socket_server()
- {
--    proc_listener_socket = create_listener_socket(PROC_SOCKET_FILE_PATH);
--    if (proc_listener_socket < 0)
-+    int err;
-+
-+    epoll_fd = epoll_create1(0);
-+    if (epoll_fd < 0) {
-+        err = errno;
-+        ErrLog("%s: Failed to open epoll socket, errno %d (%s).", __func__, err,
-+               strerror(err));
-+        return FALSE;
-+    }
-+
-+    if (!listener_create(PROC_SOCKET_FILE_PATH, &proc_listener,
-+                         proc_new_conn, NUMBER_PROCESSES_ALLOWED)) {
-+        term_socket_server();
-+        return FALSE;
-+    }
-+
-+    if (!listener_create(ADMIN_SOCKET_FILE_PATH, &admin_listener,
-+                         admin_new_conn, NUMBER_ADMINS_ALLOWED)) {
-+        term_socket_server();
-         return FALSE;
-+    }
-+
-+#ifdef WITH_LIBUDEV
-+    if (!udev_mon_init(UDEV_SUBSYSTEM_AP, &udev_mon)) {
-+        term_socket_server();
-+        return FALSE;
-+    }
-+#endif
- 
--    DbgLog(DL0, "Socket server started");
-+    DbgLog(DL0, "%s: Socket server started", __func__);
- 
-     return TRUE;
- }
- 
- int term_socket_server()
- {
--    if (proc_listener_socket >= 0)
--        close_listener_socket(proc_listener_socket, PROC_SOCKET_FILE_PATH);
-+    DL_NODE *node, *next;
-+
-+#ifdef WITH_LIBUDEV
-+    udev_mon_term(&udev_mon);
-+#endif
-+
-+    listener_term(&proc_listener);
-+    listener_term(&admin_listener);
-+
-+    node = dlist_get_first(proc_connections);
-+    while (node != NULL) {
-+        next = dlist_next(node);
-+        proc_hangup(node->data);
-+        node = next;
-+    }
-+    dlist_purge(proc_connections);
- 
--    DbgLog(DL0, "Socket server stopped");
-+    node = dlist_get_first(admin_connections);
-+    while (node != NULL) {
-+        next = dlist_next(node);
-+        admin_hangup(node->data);
-+        node = next;
-+    }
-+    dlist_purge(admin_connections);
-+
-+    node = dlist_get_first(pending_events);
-+    while (node != NULL) {
-+        next = dlist_next(node);
-+        event_free((struct event_info *)node->data);
-+        node = next;
-+    }
-+    dlist_purge(pending_events);
-+
-+    if (epoll_fd >= 0)
-+        close(epoll_fd);
-+    epoll_fd = -1;
-+
-+    DbgLog(DL0, "%s: Socket server stopped", __func__);
- 
-     return TRUE;
- }
-+
-+#ifdef DEV
-+
-+static void dump_listener(struct listener_info *listener)
-+{
-+    DbgLog(DL0, "    socket: %d", listener->socket);
-+    DbgLog(DL0, "    file_path: %s", listener->file_path);
-+    DbgLog(DL0, "    ep_info.ref_count: %lu", listener->ep_info.ref_count);
-+    DbgLog(DL0, "    num_clients: %lu", listener->num_clients);
-+    DbgLog(DL0, "    max_num_clients: %lu", listener->max_num_clients);
-+}
-+
-+static void dump_event_msg(event_msg_t *event, int indent)
-+{
-+    DbgLog(DL0, "%*sevent version: %u", indent, "", event->version);
-+    DbgLog(DL0, "%*sevent type: %08x", indent, "", event->type);
-+    DbgLog(DL0, "%*sevent flags: %08x", indent, "", event->flags);
-+    DbgLog(DL0, "%*sevent token_type: %08x", indent, "", event->token_type);
-+    DbgLog(DL0, "%*sevent token_label: '%.32s'", indent, "", event->token_label);
-+    DbgLog(DL0, "%*sevent process_id: %lu", indent, "", event->process_id);
-+    DbgLog(DL0, "%*sevent payload_len: %u", indent, "", event->payload_len);
-+}
-+
-+static void dump_event_reply(event_reply_t *reply, int indent)
-+{
-+    DbgLog(DL0, "%*sreply version: %u", indent, "", reply->version);
-+    DbgLog(DL0, "%*sreply positive_replies: %u", indent, "", reply->positive_replies);
-+    DbgLog(DL0, "%*sreply negative_replies: %u", indent, "", reply->negative_replies);
-+    DbgLog(DL0, "%*sreply nothandled_replies: %u", indent, "", reply->nothandled_replies);
-+}
-+
-+static void dump_event_info(struct event_info *event, int indent)
-+{
-+    dump_event_msg(&event->event, indent);
-+    dump_event_reply(&event->reply, indent);
-+    DbgLog(DL0, "%*sproc_ref_count: %lu", indent, "", event->proc_ref_count);
-+    if (event->admin_ref != NULL)
-+        DbgLog(DL0, "%*sadmin_ref: %p", indent, "", event->admin_ref);
-+    else
-+        DbgLog(DL0, "%*sadmin_ref: None", indent, "");
-+}
-+
-+static void dump_proc_conn(struct proc_conn_info *proc_conn)
-+{
-+    DL_NODE *node;
-+    unsigned long i;
-+
-+    DbgLog(DL0, "      socket: %d", proc_conn->client_info.socket);
-+    DbgLog(DL0, "      state: %d", proc_conn->state);
-+    DbgLog(DL0, "      ref-count: %lu", proc_conn->client_info.ep_info.ref_count);
-+    DbgLog(DL0, "      xfer state: %d", proc_conn->client_info.xfer_state);
-+    DbgLog(DL0, "      xfer size: %d", proc_conn->client_info.xfer_size);
-+    DbgLog(DL0, "      xfer offset: %d", proc_conn->client_info.xfer_offset);
-+    DbgLog(DL0, "      pending events:");
-+    node = dlist_get_first(proc_conn->events);
-+    i = 1;
-+    while (node != NULL) {
-+        DbgLog(DL0, "        event %lu (%p):", i, node->data);
-+        dump_event_info(node->data, 10);
-+        node = dlist_next(node);
-+        i++;
-+    }
-+    if (proc_conn->event != NULL) {
-+        DbgLog(DL0, "      current event:");
-+        dump_event_info(proc_conn->event, 8);
-+        DbgLog(DL0, "      current reply:");
-+        dump_event_reply(&proc_conn->reply, 8);
-+    } else {
-+        DbgLog(DL0, "      current event: none");
-+    }
-+}
-+
-+static void dump_admin_conn(struct admin_conn_info *admin_conn)
-+{
-+    DbgLog(DL0, "      socket: %d", admin_conn->client_info.socket);
-+    DbgLog(DL0, "      state: %d", admin_conn->state);
-+    DbgLog(DL0, "      ref-count: %lu", admin_conn->client_info.ep_info.ref_count);
-+    DbgLog(DL0, "      xfer state: %d", admin_conn->client_info.xfer_state);
-+    DbgLog(DL0, "      xfer size: %d", admin_conn->client_info.xfer_size);
-+    DbgLog(DL0, "      xfer offset: %d", admin_conn->client_info.xfer_offset);
-+    if (admin_conn->event != NULL) {
-+        DbgLog(DL0, "      current event (%p):", admin_conn->event);
-+        dump_event_info(admin_conn->event, 8);
-+    } else {
-+        DbgLog(DL0, "      current event: none");
-+    }
-+}
-+
-+#ifdef WITH_LIBUDEV
-+void dump_udev_mon(struct udev_mon *udev_mon)
-+{
-+    DbgLog(DL0, "    socket: %d", udev_mon->socket);
-+    DbgLog(DL0, "    udev: %p", udev_mon->udev);
-+    DbgLog(DL0, "    mon: %p", udev_mon->mon);
-+    DbgLog(DL0, "    ep_info.ref_count: %lu", udev_mon->ep_info.ref_count);
-+    if (udev_mon->delayed_event != NULL) {
-+        DbgLog(DL0, "    delayed_event (%p):", udev_mon->delayed_event);
-+        dump_event_info(udev_mon->delayed_event, 6);
-+    } else {
-+        DbgLog(DL0, "    delayed_event: node");
-+    }
-+}
-+#endif
-+
-+void dump_socket_handler()
-+{
-+    DL_NODE *node;
-+    unsigned long i;
-+
-+    DbgLog(DL0, "%s: Dump of socket handler data:", __func__);
-+    DbgLog(DL0, "  epoll_fd: %d", epoll_fd);
-+
-+    DbgLog(DL0, "  proc_listener (%p): ", &proc_listener);
-+    dump_listener(&proc_listener);
-+
-+    DbgLog(DL0, "  proc_connections: ");
-+    node = dlist_get_first(proc_connections);
-+    i = 1;
-+    while (node != NULL) {
-+        DbgLog(DL0, "    proc_connection %lu (%p): ", i, node->data);
-+        dump_proc_conn(node->data);
-+        i++;
-+        node = dlist_next(node);
-+    }
-+
-+    DbgLog(DL0, "  admin_listener (%p): ", &admin_listener);
-+    dump_listener(&admin_listener);
-+
-+    DbgLog(DL0, "  admin_connections: ");
-+    node = dlist_get_first(admin_connections);
-+    i = 1;
-+    while (node != NULL) {
-+        DbgLog(DL0, "    admin_connection %lu (%p): ", i, node->data);
-+        dump_admin_conn(node->data);
-+        i++;
-+        node = dlist_next(node);
-+    }
-+
-+#ifdef WITH_LIBUDEV
-+    DbgLog(DL0, "  udev_mon (%p): ", &udev_mon);
-+    dump_udev_mon(&udev_mon);
-+#endif
-+
-+    DbgLog(DL0, "  pending events (%lu): ", pending_events_count);
-+    node = dlist_get_first(pending_events);
-+    i = 1;
-+    while (node != NULL) {
-+        DbgLog(DL0, "    event %lu (%p): ", i, node->data);
-+        dump_event_info(node->data, 6);
-+        i++;
-+        node = dlist_next(node);
-+    }
-+}
-+#endif
diff --git a/SOURCES/opencryptoki-3.16.0-4e3b43c3d8844402c04a66b55c6c940f965109f0.patch b/SOURCES/opencryptoki-3.16.0-4e3b43c3d8844402c04a66b55c6c940f965109f0.patch
deleted file mode 100644
index 8a3d581..0000000
--- a/SOURCES/opencryptoki-3.16.0-4e3b43c3d8844402c04a66b55c6c940f965109f0.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-commit 4e3b43c3d8844402c04a66b55c6c940f965109f0
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon May 3 10:05:07 2021 +0200
-
-    SOFT: Check the EC Key on C_CreateObject and C_DeriveKey
-    
-    When constructing an OpenSSL EC public or private key from PKCS#11
-    attributes or ECDH public data, check that the key is valid, i.e. that
-    the point is on the curve.
-    
-    This prevents one from creating an EC key object via C_CreateObject with
-    invalid key data. It also prevents C_DeriveKey to derive a secret using
-    ECDH with an EC public key (public data) that uses a different curve
-    or is invalid by other means.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c
-index c30be1da..aeff39a9 100644
---- a/usr/lib/soft_stdll/soft_specific.c
-+++ b/usr/lib/soft_stdll/soft_specific.c
-@@ -4365,6 +4365,12 @@ static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data,
-         goto out;
-     }
- 
-+    if (!EC_KEY_check_key(ec_key)) {
-+        TRACE_ERROR("EC_KEY_check_key failed\n");
-+        rc = CKR_PUBLIC_KEY_INVALID;
-+        goto out;
-+    }
-+
- out:
-     if (allocated && ecpoint != NULL)
-         free(ecpoint);
-@@ -4404,6 +4410,12 @@ static CK_RV fill_ec_key_from_privkey(EC_KEY *ec_key, const CK_BYTE *data,
-         goto out;
-     }
- 
-+    if (!EC_KEY_check_key(ec_key)) {
-+        TRACE_ERROR("EC_KEY_check_key failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
- out:
-     if (point != NULL)
-         EC_POINT_free(point);
diff --git a/SOURCES/opencryptoki-3.16.0-5824364d995e5d2418f885ee57e377e11d1b3302.patch b/SOURCES/opencryptoki-3.16.0-5824364d995e5d2418f885ee57e377e11d1b3302.patch
deleted file mode 100644
index c38fef0..0000000
--- a/SOURCES/opencryptoki-3.16.0-5824364d995e5d2418f885ee57e377e11d1b3302.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-commit 5824364d995e5d2418f885ee57e377e11d1b3302
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jul 7 13:44:46 2021 +0200
-
-    pkcstok_migrate: Quote strings with spaces in opencryptoki.conf
-    
-    When modifying opencryptoki.conf during token migration, put quotes
-    around strings that contain spaces, e.g. for the slot description and
-    manufacturer.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-index 94fd1196..3df1596e 100644
---- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-@@ -2107,7 +2107,10 @@ static int parseupdate_key_str(void *private, int tok, const char *val)
- {
- 	struct parseupdate *u = (struct parseupdate *)private;
- 
--    if (tok != KW_TOKVERSION)
-+    if (tok != KW_HWVERSION && tok != KW_FWVERSION &&
-+        strchr(val, ' ') != NULL)
-+        fprintf(u->f, "  %s = \"%s\"", keyword_token_to_str(tok), val);
-+    else if (tok != KW_TOKVERSION)
-         fprintf(u->f, "  %s = %s", keyword_token_to_str(tok), val);
-     return 0;
- }
diff --git a/SOURCES/opencryptoki-3.16.0-69244a5e0d9dfec3ef534b19b89a541576bb17dc.patch b/SOURCES/opencryptoki-3.16.0-69244a5e0d9dfec3ef534b19b89a541576bb17dc.patch
deleted file mode 100644
index 0494a35..0000000
--- a/SOURCES/opencryptoki-3.16.0-69244a5e0d9dfec3ef534b19b89a541576bb17dc.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-commit 69244a5e0d9dfec3ef534b19b89a541576bb17dc
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Feb 9 10:47:57 2021 +0100
-
-    TRACE: Use gettid() if SYS_gettid is not defined
-    
-    Also print the thread ID in the trace, if SYS_gettid is not defined.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/trace.c b/usr/lib/common/trace.c
-index 678c0b96..bdc5256a 100644
---- a/usr/lib/common/trace.c
-+++ b/usr/lib/common/trace.c
-@@ -33,6 +33,8 @@
- 
- #ifdef SYS_gettid
- #define __gettid() syscall(SYS_gettid)
-+#else
-+#define __gettid() gettid()
- #endif
- 
- pthread_mutex_t tlmtx = PTHREAD_MUTEX_INITIALIZER;
diff --git a/SOURCES/opencryptoki-3.16.0-7b7d83c571ceb3050969359817d4145600f14ae8.patch b/SOURCES/opencryptoki-3.16.0-7b7d83c571ceb3050969359817d4145600f14ae8.patch
deleted file mode 100644
index 86ba3f0..0000000
--- a/SOURCES/opencryptoki-3.16.0-7b7d83c571ceb3050969359817d4145600f14ae8.patch
+++ /dev/null
@@ -1,367 +0,0 @@
-commit 7b7d83c571ceb3050969359817d4145600f14ae8
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Fri Apr 9 17:07:31 2021 +0200
-
-    Check CKF_LIBRARY_CANT_CREATE_OS_THREADS at C_Initialize
-    
-    Fail if flag CKF_LIBRARY_CANT_CREATE_OS_THREADS is set at C_Initialize,
-    and event support is enabled (this is the default). We need to use pthreads
-    for the event thread, so we can't work if CKF_LIBRARY_CANT_CREATE_OS_THREADS
-    is set. Fail with CKR_NEED_TO_CREATE_THREADS if so.
-    
-    The event support can be globally disabled using keyword 'disable-event-support'
-    in opencryptoki.conf. This disables pkcsslots to accept admin connections,
-    and it does not monitor for AP UDEV events (on s390 platform). No event
-    thread is started in the opencryptoki processes, thus we can accept if flag
-    CKF_LIBRARY_CANT_CREATE_OS_THREADS is set in that case.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/man/man5/opencryptoki.conf.5.in b/man/man5/opencryptoki.conf.5.in
-index 71218f79..7dc676ab 100644
---- a/man/man5/opencryptoki.conf.5.in
-+++ b/man/man5/opencryptoki.conf.5.in
-@@ -10,8 +10,16 @@ pkcs#11 slots. At startup, the pkcsslotd daemon parses this file to
- determine which slots will be made available.
- 
- .SH SYNTAX
--This file is made up of slot descriptions. Each slot description
--is composed of a slot number, brackets and key-value pairs.
-+This file is made up of optional global definitions, and slot descriptions.
-+
-+The following global definitions are valid:
-+
-+.TP
-+.BR disable-event-support
-+If this keyword is specified the openCryptoki event support is disabled.
-+
-+.P
-+Each slot description is composed of a slot number, brackets and key-value pairs.
- 
-  slot number
-  {
-diff --git a/usr/include/slotmgr.h b/usr/include/slotmgr.h
-index e37368a5..451a8cf1 100644
---- a/usr/include/slotmgr.h
-+++ b/usr/include/slotmgr.h
-@@ -99,6 +99,7 @@ typedef struct {
-     LW_SHM_TYPE *shm_addr;      // token specific shm address
- } Slot_Info_t;
- 
-+#define FLAG_EVENT_SUPPORT_DISABLED   0x01
- 
- #ifdef PKCS64
- 
-@@ -200,6 +201,7 @@ typedef struct {
- 
- typedef struct {
-     uint8 num_slots;
-+    uint8 flags;
-     CK_INFO_64 ck_info;
-     Slot_Info_t_64 slot_info[NUMBER_SLOTS_MANAGED];
- } Slot_Mgr_Socket_t;
-@@ -214,6 +216,7 @@ typedef struct {
- 
- typedef struct {
-     uint8 num_slots;
-+    uint8 flags;
-     CK_INFO ck_info;
-     Slot_Info_t slot_info[NUMBER_SLOTS_MANAGED];
- } Slot_Mgr_Socket_t;
-diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c
-index 2873a20a..6517ca6c 100644
---- a/usr/lib/api/api_interface.c
-+++ b/usr/lib/api/api_interface.c
-@@ -308,7 +308,8 @@ void parent_fork_after()
-         return;
- 
-     /* Restart the event thread in the parent when fork is complete */
--    if (Anchor->event_thread == 0)
-+    if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 &&
-+        Anchor->event_thread == 0)
-         start_event_thread();
- }
- 
-@@ -2752,13 +2753,7 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-                 goto error;
-             }
-         }
--        // If we EVER need to create threads from this library we must
--        // check the Flags for the Can_Create_OS_Threads flag
--        // Right now the library DOES NOT create threads and therefore this
--        // check is irrelavant.
--        if (pArg->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) {
--            TRACE_DEVEL("Can't create OS threads...This is OK\n");
--        }
-+
-         // Since this is an initialization path, we will be verbose in the
-         // code rather than efficient.
-         //
-@@ -2848,7 +2843,21 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-         rc = CKR_FUNCTION_FAILED;
-         goto error_shm;
-     }
--    // Initialize structure values
-+
-+    if (pVoid != NULL) {
-+        pArg = (CK_C_INITIALIZE_ARGS *) pVoid;
-+
-+        if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 &&
-+            (pArg->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS) != 0) {
-+            TRACE_ERROR("Flag CKF_LIBRARY_CANT_CREATE_OS_THREADS is set and "
-+                        "event support is enabled\n");
-+            OCK_SYSLOG(LOG_ERR, "C_Initialize: Application specified that "
-+                       "library can't create OS threads. PKCS11 Module requires "
-+                       "to create threads when event support is enabled.\n");
-+            rc = CKR_NEED_TO_CREATE_THREADS;
-+            goto error;
-+        }
-+    }
- 
-     //Register with pkcsslotd
-     if (!API_Register()) {
-@@ -2867,7 +2876,8 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     }
- 
-     /* Start event receiver thread */
--    if (start_event_thread() != 0) {
-+    if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 &&
-+        start_event_thread() != 0) {
-         TRACE_ERROR("Failed to start event thread\n");
- 
-         // unload all the STDLL's from the application
-diff --git a/usr/lib/common/configparser.h b/usr/lib/common/configparser.h
-index 13ca648d..b3c32496 100644
---- a/usr/lib/common/configparser.h
-+++ b/usr/lib/common/configparser.h
-@@ -35,6 +35,7 @@ typedef int  (*end_slot_f)(void *private);
- typedef int  (*key_str_f)(void *private, int tok, const char *val);
- typedef int  (*key_vers_f)(void *private, int tok, unsigned int vers);
- typedef void (*eolcomment_f)(void *private, const char *comment);
-+typedef void (*disab_event_supp_f)(void *private);
- /*
-  * Report an error.  If the error is not reported by the parser itself
-  * but via one of the parse functions, \c parsermsg will be \c NULL.
-@@ -52,6 +53,7 @@ typedef void (*error_f)(void *private, int line, const char *parsermsg);
-  */
- struct parsefuncs {
-     ockversion_f  version;
-+    disab_event_supp_f disab_event_supp;
-     eol_f         eol;
-     begin_slot_f  begin_slot;
-     end_slot_f    end_slot;
-diff --git a/usr/lib/common/lexer.l b/usr/lib/common/lexer.l
-index b35a0b72..38cbcb70 100644
---- a/usr/lib/common/lexer.l
-+++ b/usr/lib/common/lexer.l
-@@ -69,6 +69,7 @@ extern char *configparse_strdup(const char *s);
- 
- version                 return OCKVERSION;
- slot                    return SLOT;
-+disable-event-support   return DISABLE_EVENT_SUPPORT;
- 
- [^\"= \t\n]+		{
- 			  yylval.str = configparse_strdup(yytext);
-diff --git a/usr/lib/common/parser.y b/usr/lib/common/parser.y
-index 86806fcb..40c3994d 100644
---- a/usr/lib/common/parser.y
-+++ b/usr/lib/common/parser.y
-@@ -65,7 +65,7 @@ int lookup_keyword(const char *key);
-     int err;
- }
- 
--%token EQUAL DOT SLOT EOL OCKVERSION BEGIN_DEF END_DEF
-+%token EQUAL DOT SLOT EOL OCKVERSION BEGIN_DEF END_DEF DISABLE_EVENT_SUPPORT
- %token <str> STRING
- %token <str> KEYWORD
- %token <num> INTEGER
-@@ -81,6 +81,7 @@ config_file:
- 
- sections:
- 	version_def eolcomment
-+	| disable_event_support_def eolcomment
- 	| SLOT INTEGER BEGIN_DEF
- 	{
-         if (parsefuncs->begin_slot && parsefuncs->begin_slot(parsedata, $2, 0)) {
-@@ -125,6 +126,13 @@ version_def:
-         }
-         configparse_freestringsfrom($2);
-     }
-+    
-+disable_event_support_def:
-+    DISABLE_EVENT_SUPPORT
-+    {
-+        if (parsefuncs->disab_event_supp)
-+            parsefuncs->disab_event_supp(parsedata);
-+    }
- 
- line_def:
-     STRING EQUAL TOKVERSION
-diff --git a/usr/sbin/pkcsslotd/pkcsslotd.h b/usr/sbin/pkcsslotd/pkcsslotd.h
-index d7edcb3c..1dd0bac9 100644
---- a/usr/sbin/pkcsslotd/pkcsslotd.h
-+++ b/usr/sbin/pkcsslotd/pkcsslotd.h
-@@ -88,7 +88,7 @@ int XProcLock(void);
- int XProcUnLock(void);
- int CreateXProcLock(void);
- 
--int init_socket_server();
-+int init_socket_server(int event_support_disabled);
- int term_socket_server();
- int init_socket_data(Slot_Mgr_Socket_t *sp);
- int socket_connection_handler(int timeout_secs);
-diff --git a/usr/sbin/pkcsslotd/slotmgr.c b/usr/sbin/pkcsslotd/slotmgr.c
-index efbfe8fd..3b328a6c 100644
---- a/usr/sbin/pkcsslotd/slotmgr.c
-+++ b/usr/sbin/pkcsslotd/slotmgr.c
-@@ -34,6 +34,7 @@ int shmid;
- key_t tok;
- Slot_Info_t_64 sinfo[NUMBER_SLOTS_MANAGED];
- unsigned int NumberSlotsInDB = 0;
-+int event_support_disabled = 0;
- 
- Slot_Info_t_64 *psinfo;
- 
-@@ -467,6 +468,13 @@ static int slotmgr_key_vers(void *private, int tok, unsigned int vers)
-     return 1;
- }
- 
-+static void slotmgr_disab_event_supp(void *private)
-+{
-+    UNUSED(private);
-+
-+    event_support_disabled = 1;
-+}
-+
- static void slotmgr_parseerror(void *private, int line, const char *parsermsg)
- {
-     struct parse_data *d = (struct parse_data *)private;
-@@ -480,6 +488,7 @@ static struct parsefuncs slotmgr_parsefuncs = {
-     .end_slot   = slotmgr_end_slot,
-     .key_str    = slotmgr_key_str,
-     .key_vers   = slotmgr_key_vers,
-+    .disab_event_supp = slotmgr_disab_event_supp,
-     .parseerror = slotmgr_parseerror
- };
- 
-@@ -568,7 +577,7 @@ int main(int argc, char *argv[], char *envp[])
-     if (!XProcUnLock())
-         return 4;
- 
--    if (!init_socket_server()) {
-+    if (!init_socket_server(event_support_disabled)) {
-         DestroyMutexes();
-         DetachFromSharedMemory();
-         DestroySharedMemory();
-@@ -582,6 +591,8 @@ int main(int argc, char *argv[], char *envp[])
-         DestroySharedMemory();
-         return 6;
-     }
-+    if (event_support_disabled)
-+        socketData.flags |= FLAG_EVENT_SUPPORT_DISABLED;
- 
-     /* Create customized token directories */
-     psinfo = &socketData.slot_info[0];
-diff --git a/usr/sbin/pkcsslotd/socket_server.c b/usr/sbin/pkcsslotd/socket_server.c
-index 41408670..3aa40267 100644
---- a/usr/sbin/pkcsslotd/socket_server.c
-+++ b/usr/sbin/pkcsslotd/socket_server.c
-@@ -139,12 +139,12 @@ struct event_info {
- };
- 
- static int epoll_fd = -1;
--static struct listener_info proc_listener;
-+static struct listener_info proc_listener = { .socket = -1 };
- static DL_NODE *proc_connections = NULL;
--static struct listener_info admin_listener;
-+static struct listener_info admin_listener = { .socket = -1 };
- static DL_NODE *admin_connections = NULL;
- #ifdef WITH_LIBUDEV
--static struct udev_mon udev_mon;
-+static struct udev_mon udev_mon = { .socket = -1 };
- #endif
- static DL_NODE *pending_events = NULL;
- static unsigned long pending_events_count = 0;
-@@ -1620,6 +1620,9 @@ static void udev_mon_term(struct udev_mon *udev_mon)
-     if (udev_mon == NULL)
-         return;
- 
-+    if (udev_mon->socket < 0)
-+        return;
-+
-     epoll_ctl(epoll_fd, EPOLL_CTL_DEL, udev_mon->socket, NULL);
-     if (udev_mon->udev != NULL)
-         udev_unref(udev_mon->udev);
-@@ -1636,6 +1639,7 @@ int init_socket_data(Slot_Mgr_Socket_t *socketData)
- {
-     unsigned int processed = 0;
- 
-+    socketData->flags = 0;
-     PopulateCKInfo(&(socketData->ck_info));
-     socketData->num_slots = NumberSlotsInDB;
-     PopulateSlotInfo(socketData->slot_info, &processed);
-@@ -1692,7 +1696,7 @@ int socket_connection_handler(int timeout_secs)
-     return TRUE;
- }
- 
--int init_socket_server()
-+int init_socket_server(int event_support_disabled)
- {
-     int err;
- 
-@@ -1710,18 +1714,20 @@ int init_socket_server()
-         return FALSE;
-     }
- 
--    if (!listener_create(ADMIN_SOCKET_FILE_PATH, &admin_listener,
--                         admin_new_conn, NUMBER_ADMINS_ALLOWED)) {
--        term_socket_server();
--        return FALSE;
--    }
-+    if (!event_support_disabled) {
-+        if (!listener_create(ADMIN_SOCKET_FILE_PATH, &admin_listener,
-+                             admin_new_conn, NUMBER_ADMINS_ALLOWED)) {
-+            term_socket_server();
-+            return FALSE;
-+        }
- 
- #ifdef WITH_LIBUDEV
--    if (!udev_mon_init(UDEV_SUBSYSTEM_AP, &udev_mon)) {
--        term_socket_server();
--        return FALSE;
--    }
-+        if (!udev_mon_init(UDEV_SUBSYSTEM_AP, &udev_mon)) {
-+            term_socket_server();
-+            return FALSE;
-+        }
- #endif
-+    }
- 
-     DbgLog(DL0, "%s: Socket server started", __func__);
- 
-diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-index 7c225730..94fd1196 100644
---- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-@@ -2066,6 +2066,13 @@ static int parseupdate_ockversion(void *private, const char *version)
-     return 0;
- }
- 
-+static void parseupdate_disab_event_supp(void *private)
-+{
-+    struct parseupdate *u = (struct parseupdate *)private;
-+
-+    fprintf(u->f, "disable-event-support");
-+}
-+
- static void parseupdate_eol(void *private)
- {
- 	struct parseupdate *u = (struct parseupdate *)private;
-@@ -2124,6 +2131,7 @@ static void parseupdate_eolcomment(void *private, const char *comment)
- 
- static struct parsefuncs parseupdatefuncs = {
-     .version    = parseupdate_ockversion,
-+    .disab_event_supp = parseupdate_disab_event_supp,
-     .eol        = parseupdate_eol,
-     .begin_slot = parseupdate_begin_slot,
-     .end_slot   = parseupdate_end_slot,
diff --git a/SOURCES/opencryptoki-3.16.0-b048be548508dd1958bb7271568f388d0f6cbcf8.patch b/SOURCES/opencryptoki-3.16.0-b048be548508dd1958bb7271568f388d0f6cbcf8.patch
deleted file mode 100644
index fd0c13c..0000000
--- a/SOURCES/opencryptoki-3.16.0-b048be548508dd1958bb7271568f388d0f6cbcf8.patch
+++ /dev/null
@@ -1,1023 +0,0 @@
-commit b048be548508dd1958bb7271568f388d0f6cbcf8
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Feb 8 16:50:00 2021 +0100
-
-    Event support: API and token level changes
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/include/apictl.h b/usr/include/apictl.h
-index 8898cae3..81c65dad 100644
---- a/usr/include/apictl.h
-+++ b/usr/include/apictl.h
-@@ -57,6 +57,8 @@ typedef struct {
-     API_Slot_t SltList[NUMBER_SLOTS_MANAGED];
-     DLL_Load_t DLLs[NUMBER_SLOTS_MANAGED];  // worst case we have a separate DLL
-                                             // per slot
-+    int socketfd;
-+    pthread_t event_thread;
- } API_Proc_Struct_t;
- 
- #endif
-diff --git a/usr/include/events.h b/usr/include/events.h
-new file mode 100644
-index 00000000..dac6ad52
---- /dev/null
-+++ b/usr/include/events.h
-@@ -0,0 +1,83 @@
-+/*
-+ * COPYRIGHT (c) International Business Machines Corp. 2021
-+ *
-+ * This program is provided under the terms of the Common Public License,
-+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-+ * found in the file LICENSE file or at
-+ * https://opensource.org/licenses/cpl1.0.php
-+ */
-+
-+#include <stdint.h>
-+#include <pkcs11types.h>
-+#include <limits.h>
-+#include <stdio.h>
-+
-+#include "local_types.h"
-+#include "pkcs32.h"
-+
-+#ifndef _EVENTS_H
-+#define _EVENTS_H
-+
-+typedef struct {
-+    unsigned int version;       /* EVENT_VERSION_xxx */
-+    unsigned int type;          /* EVENT_TYPE_xxx */
-+    unsigned int flags;         /* EVENT_FLAGS_xxx */
-+    unsigned int token_type;    /* Destination token type: EVENT_TOK_TYPE_xxx */
-+    char token_label[member_size(CK_TOKEN_INFO_32, label)];
-+                                /* Label of destination token (or blanks) */
-+    pid_t process_id;           /* Process ID of destination process (or 0) */
-+    unsigned int payload_len;   /* Length of payload in bytes */
-+    /* Followed by payload_len bytes of payload (event specific) */
-+} __attribute__ ((__packed__)) event_msg_t;
-+
-+typedef struct {
-+    unsigned int version;               /* EVENT_VERSION_xxx */
-+    unsigned int positive_replies;      /* Number of tokens that replied a */
-+    unsigned int negative_replies;      /* positive, or negative feedback, */
-+    unsigned int nothandled_replies;    /* or that did not handle the event. */
-+                                        /* Note: Only tokens matching the event
-+                                         * destination fields (pid, label,
-+                                         * token-type) are counted. */
-+} __attribute__ ((__packed__)) event_reply_t;
-+
-+/* Event and reply versions */
-+#define EVENT_VERSION_1         1
-+
-+/* Event classes (encoded into event type) */
-+#define EVENT_CLASS_MASK        0xffff0000
-+#define EVENT_CLASS_UDEV        0x00010000
-+#define EVENT_CLASS_ADMIN       0x00020000
-+
-+/* Event types */
-+#define EVENT_TYPE_APQN_ADD     EVENT_CLASS_UDEV + 0x00000001
-+#define EVENT_TYPE_APQN_REMOVE  EVENT_CLASS_UDEV + 0x00000002
-+
-+/* Event flags */
-+#define EVENT_FLAGS_NONE        0x00000000
-+#define EVENT_FLAGS_REPLY_REQ   0x00000001
-+
-+/* Event token destination types */
-+#define EVENT_TOK_TYPE_ALL      0x00000000
-+#define EVENT_TOK_TYPE_CCA      0x00000001
-+#define EVENT_TOK_TYPE_EP11     0x00000002
-+
-+/* Maximum event payload length 128k */
-+#define EVENT_MAX_PAYLOAD_LENGTH    (128 * 1024)
-+
-+/* Event payload for EVENT_TYPE_APQN_ADD and EVENT_TYPE_APQN_REMOVE */
-+typedef struct {
-+    unsigned short card;
-+    unsigned short domain;
-+    unsigned int device_type;            /* from uevent DEV_TYPE property */
-+} __attribute__ ((__packed__)) event_udev_apqn_data_t;
-+
-+/* AP device types */
-+#define AP_DEVICE_TYPE_CEX3A        8
-+#define AP_DEVICE_TYPE_CEX3C        9
-+#define AP_DEVICE_TYPE_CEX4         10
-+#define AP_DEVICE_TYPE_CEX5         11
-+#define AP_DEVICE_TYPE_CEX6         12
-+#define AP_DEVICE_TYPE_CEX7         13
-+
-+#endif
-diff --git a/usr/include/include.mk b/usr/include/include.mk
-index a36afb25..79e593d7 100644
---- a/usr/include/include.mk
-+++ b/usr/include/include.mk
-@@ -7,4 +7,5 @@ opencryptokiinclude_HEADERS =						\
- 
- noinst_HEADERS +=							\
- 	usr/include/apictl.h usr/include/local_types.h			\
--	usr/include/pkcs32.h usr/include/slotmgr.h usr/include/stdll.h
-+	usr/include/pkcs32.h usr/include/slotmgr.h usr/include/stdll.h	\
-+	usr/include/events.h
-diff --git a/usr/include/local_types.h b/usr/include/local_types.h
-index f03c6629..c7c7f5ec 100644
---- a/usr/include/local_types.h
-+++ b/usr/include/local_types.h
-@@ -11,6 +11,8 @@
- #ifndef __LOCAL_TYPES
- #define __LOCAL_TYPES
- 
-+#define member_size(type, member) sizeof(((type *)0)->member)
-+
- typedef unsigned char uint8;
- 
- typedef unsigned short uint16;
-diff --git a/usr/include/stdll.h b/usr/include/stdll.h
-index 57f6c6e8..9a3b760c 100644
---- a/usr/include/stdll.h
-+++ b/usr/include/stdll.h
-@@ -350,6 +350,11 @@ typedef CK_RV (CK_PTR ST_C_IBM_ReencryptSingle)(STDLL_TokData_t *tokdata,
-                                                 CK_BYTE_PTR pReencryptedData,
-                                             CK_ULONG_PTR pulReencryptedDataLen);
- 
-+typedef CK_RV (CK_PTR ST_C_HandleEvent)(STDLL_TokData_t *tokdata,
-+                                        unsigned int event_type,
-+                                        unsigned int event_flags,
-+                                        const char *payload,
-+                                        unsigned int payload_len);
- 
- struct ST_FCN_LIST {
- 
-@@ -424,6 +429,9 @@ struct ST_FCN_LIST {
-     ST_C_CancelFunction ST_CancelFunction;
- 
-     ST_C_IBM_ReencryptSingle ST_IBM_ReencryptSingle;
-+
-+    /* The functions defined below are not part of the external API */
-+    ST_C_HandleEvent ST_HandleEvent;
- };
- 
- typedef struct ST_FCN_LIST STDLL_FcnList_t;
-diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c
-index f1ee9132..b74b763f 100644
---- a/usr/lib/api/api_interface.c
-+++ b/usr/lib/api/api_interface.c
-@@ -286,7 +286,31 @@ void child_fork_initializer()
-     if (Anchor != NULL)
-         C_Finalize(NULL);
-     in_child_fork_initializer = FALSE;
-- }
-+}
-+
-+void parent_fork_prepare()
-+{
-+    if (Anchor == NULL)
-+        return;
-+
-+    /*
-+     * Stop the event thread in the fork parent, since having the event thread
-+     * active when a fork is performed causes various problems (e.g. deadlocks
-+     * in glibc).
-+     */
-+    if (Anchor->event_thread > 0)
-+        stop_event_thread();
-+}
-+
-+void parent_fork_after()
-+{
-+    if (Anchor == NULL)
-+        return;
-+
-+    /* Restart the event thread in the parent when fork is complete */
-+    if (Anchor->event_thread == 0)
-+        start_event_thread();
-+}
- 
- //------------------------------------------------------------------------
- // API function C_CancelFunction
-@@ -1501,6 +1525,20 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
- 
-     shData = &(Anchor->SocketDataP);
- 
-+    /*
-+     * Stop the event thread and close the socket.
-+     * If C_Finalize is called as part of the fork initializer, don't stop
-+     * the thread, since a forked process does not have any threads, and don't
-+     * close the socket, as this would close the connection of the parent
-+     * process to the pkcsslotd as well.
-+     * */
-+    if (!in_child_fork_initializer) {
-+        if (Anchor->event_thread > 0)
-+            stop_event_thread();
-+        if (Anchor->socketfd >= 0)
-+            close(Anchor->socketfd);
-+    }
-+
-     // unload all the STDLL's from the application
-     // This is in case the APP decides to do the re-initialize and
-     // continue on
-@@ -2642,6 +2680,8 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     CK_C_INITIALIZE_ARGS *pArg;
-     char fcnmap = 0;
-     CK_RV rc = CKR_OK;
-+    CK_SLOT_ID slotID;
-+    API_Slot_t *sltp;
- 
-     /*
-      * Lock so that only one thread can run C_Initialize or C_Finalize at
-@@ -2674,6 +2714,7 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     // This must be done prior to all goto error calls, else bt_destroy()
-     // will fail because it accesses uninitialized memory when t->size > 0.
-     memset(Anchor, 0, sizeof(API_Proc_Struct_t));
-+    Anchor->socketfd = -1;
- 
-     TRACE_DEBUG("Anchor allocated at %s\n", (char *) Anchor);
- 
-@@ -2789,11 +2830,21 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     }
-     TRACE_DEBUG("Shared memory %p \n", Anchor->SharedMemP);
- 
--    if (!init_socket_data()) {
-+    /* Connect to slot daemon and retrieve slot infos */
-+    Anchor->socketfd = connect_socket(SOCKET_FILE_PATH);
-+    if (Anchor->socketfd < 0) {
-         OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to create a "
-                    "socket. Verify that the slot management daemon is "
-                    "running.\n");
--        TRACE_ERROR("Cannot attach to socket.\n");
-+        TRACE_ERROR("Failed to connect to slot daemon\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto error_shm;
-+    }
-+
-+    if (!init_socket_data(Anchor->socketfd)) {
-+        OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to retrieve slot "
-+                   "infos from slot deamon.\n");
-+        TRACE_ERROR("Failed to receive slot infos from socket.\n");
-         rc = CKR_FUNCTION_FAILED;
-         goto error_shm;
-     }
-@@ -2810,15 +2861,35 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     }
-     //
-     // load all the slot DLL's here
--    {
--        CK_SLOT_ID slotID;
--        API_Slot_t *sltp;
-+    for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
-+        sltp = &(Anchor->SltList[slotID]);
-+        slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID);
-+    }
- 
-+    /* Start event receiver thread */
-+    if (start_event_thread() != 0) {
-+        TRACE_ERROR("Failed to start event thread\n");
-+
-+        // unload all the STDLL's from the application
-+        // This is in case the APP decides to do the re-initialize and
-+        // continue on
-         for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
-             sltp = &(Anchor->SltList[slotID]);
--            slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID);
-+            if (slot_loaded[slotID]) {
-+                if (sltp->pSTfini) {
-+                    // call the terminate function..
-+                    sltp->pSTfini(sltp->TokData, slotID,
-+                                  &Anchor->SocketDataP.slot_info[slotID],
-+                                  &trace, 0);
-+                }
-+            }
-+            DL_UnLoad(sltp, slotID);
-         }
- 
-+        API_UnRegister();
-+
-+        rc = CKR_FUNCTION_FAILED;
-+        goto error_shm;
-     }
- 
-     pthread_mutex_unlock(&GlobMutex);
-@@ -2829,6 +2900,8 @@ error_shm:
- 
- error:
-     bt_destroy(&Anchor->sess_btree);
-+    if (Anchor->socketfd >= 0)
-+        close(Anchor->socketfd);
- 
-     free((void *) Anchor);
-     Anchor = NULL;
-@@ -5052,7 +5125,8 @@ void api_init(void)
- {
-     // Should only have to do the atfork stuff at load time...
-     if (!Initialized) {
--        pthread_atfork(NULL, NULL, (void (*)()) child_fork_initializer);
-+        pthread_atfork(parent_fork_prepare, parent_fork_after,
-+                       child_fork_initializer);
-         Initialized = 1;
-     }
- }
-diff --git a/usr/lib/api/apiproto.h b/usr/lib/api/apiproto.h
-index 871f3778..8523fb8e 100644
---- a/usr/lib/api/apiproto.h
-+++ b/usr/lib/api/apiproto.h
-@@ -50,6 +50,9 @@ void CK_Info_From_Internal(CK_INFO_PTR dest, CK_INFO_PTR_64 src);
- int sessions_exist(CK_SLOT_ID);
- 
- void CloseAllSessions(CK_SLOT_ID slot_id, CK_BBOOL in_fork_initializer);
--int init_socket_data();
-+int connect_socket(const char *file_path);
-+int init_socket_data(int socketfd);
-+int start_event_thread();
-+int stop_event_thread();
- 
- #endif
-diff --git a/usr/lib/api/socket_client.c b/usr/lib/api/socket_client.c
-index 6bacf151..e344ddbf 100644
---- a/usr/lib/api/socket_client.c
-+++ b/usr/lib/api/socket_client.c
-@@ -23,114 +23,421 @@
- #include <grp.h>
- #include <errno.h>
- #include <stdlib.h>
-+#include <stdbool.h>
-+#include <poll.h>
- 
- #include "apiproto.h"
- #include "slotmgr.h"
- #include "apictl.h"
-+#include "trace.h"
- #include "ock_syslog.h"
-+#include "events.h"
- 
- extern API_Proc_Struct_t *Anchor;
--//
--// Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data
--// structure with the values passed by the pkcsslotd via a socket RPC.
--int init_socket_data()
-+
-+int connect_socket(const char *file_path)
- {
-     int socketfd;
-     struct sockaddr_un daemon_address;
-     struct stat file_info;
-     struct group *grp;
--    int n;
--    unsigned int bytes_received = 0;
--    Slot_Mgr_Socket_t *daemon_socket_data = NULL;
--    int ret = FALSE;
- 
--    if (stat(SOCKET_FILE_PATH, &file_info)) {
-+    if (stat(file_path, &file_info)) {
-         OCK_SYSLOG(LOG_ERR,
--                   "init_socket_data: failed to find socket file, errno=%d",
-+                   "connect_socket: failed to find socket file, errno=%d",
-                    errno);
--        return FALSE;
-+        return -1;
-     }
- 
-     grp = getgrnam("pkcs11");
-     if (!grp) {
-         OCK_SYSLOG(LOG_ERR,
--                   "init_socket_data: pkcs11 group does not exist, errno=%d",
-+                   "connect_socket: pkcs11 group does not exist, errno=%d",
-                    errno);
--        return FALSE;
-+        return -1;
-     }
- 
-     if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid) {
-         OCK_SYSLOG(LOG_ERR,
--                   "init_socket_data: incorrect permissions on socket file");
--        return FALSE;
-+                   "connect_socket: incorrect permissions on socket file");
-+        return -1;
-     }
- 
-     if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
-         OCK_SYSLOG(LOG_ERR,
--                   "init_socket_data: failed to create socket, errno=%d",
-+                   "connect_socket: failed to create socket, errno=%d",
-                    errno);
--        return FALSE;
-+        return -1;
-     }
- 
-     memset(&daemon_address, 0, sizeof(struct sockaddr_un));
-     daemon_address.sun_family = AF_UNIX;
--    strcpy(daemon_address.sun_path, SOCKET_FILE_PATH);
-+    strcpy(daemon_address.sun_path, file_path);
- 
-     if (connect(socketfd, (struct sockaddr *) &daemon_address,
-                 sizeof(struct sockaddr_un)) != 0) {
-         OCK_SYSLOG(LOG_ERR,
--                   "init_socket_data: failed to connect to slotmanager daemon, "
-+                   "connect_socket: failed to connect to slotmanager daemon, "
-                    "errno=%d",
-                    errno);
--        goto exit;
--    }
--    // allocate data buffer
--    daemon_socket_data =
--        (Slot_Mgr_Socket_t *) malloc(sizeof(*daemon_socket_data));
--    if (!daemon_socket_data) {
--        OCK_SYSLOG(LOG_ERR, "init_socket_data: failed to \
--                   allocate %lu bytes \
--                   for daemon data, errno=%d",
--                   sizeof(*daemon_socket_data), errno);
--        goto exit;
-+        goto error;
-     }
- 
--    while (bytes_received < sizeof(*daemon_socket_data)) {
--        n = read(socketfd, ((char *) daemon_socket_data) + bytes_received,
--                 sizeof(*daemon_socket_data) - bytes_received);
-+    return socketfd;
-+
-+error:
-+    close(socketfd);
-+    return -1;
-+}
-+
-+static ssize_t read_all(int socketfd, char *buffer, size_t size)
-+{
-+    size_t bytes_received = 0;
-+    ssize_t n;
-+
-+    while (bytes_received < size) {
-+        n = read(socketfd, buffer + bytes_received, size - bytes_received);
-         if (n < 0) {
-             // read error
-             if (errno == EINTR)
-                 continue;
--            OCK_SYSLOG(LOG_ERR, "init_socket_data: read error \
--                       on daemon socket, errno=%d", errno);
--            goto exit;
--        } else if (n == 0) {
--            // eof but we still expect some bytes
--            OCK_SYSLOG(LOG_ERR, "init_socket_data: read returned \
--                       with eof but we still \
--                       expect %lu bytes from daemon",
--                       sizeof(*daemon_socket_data) - bytes_received);
--            goto exit;
--        } else {
--            // n > 0, we got some bytes
--            bytes_received += n;
-+            return -errno;
-         }
-+        if (n == 0)
-+            break;
-+
-+        bytes_received += n;
-     }
- 
--    ret = TRUE;
-+    return bytes_received;
-+}
-+
-+static ssize_t send_all(int socketfd, char *buffer, size_t size)
-+{
-+    size_t bytes_sent = 0;
-+    ssize_t n;
- 
--    // copy the Slot_Mgr_Socket_t struct into global
--    // Anchor SocketDataPdata buffer
--    memcpy(&(Anchor->SocketDataP), daemon_socket_data,
--           sizeof(*daemon_socket_data));
-+    while (bytes_sent < size) {
-+        n = send(socketfd, buffer + bytes_sent, size - bytes_sent, 0);
-+        if (n < 0) {
-+            // send error
-+            if (errno == EINTR)
-+                continue;
-+            return -errno;
-+        }
-+        if (n == 0)
-+            break;
- 
--exit:
--    //free the data buffer after copy
--    if (daemon_socket_data)
--        free(daemon_socket_data);
-+        bytes_sent += n;
-+    }
- 
--    close(socketfd);
-+    return bytes_sent;
-+}
-+
-+//
-+// Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data
-+// structure with the values passed by the pkcsslotd via a socket RPC.
-+int init_socket_data(int socketfd)
-+{
-+    ssize_t n;
-+    int ret = TRUE;
-+
-+    n = read_all(socketfd, (char *)&Anchor->SocketDataP,
-+                 sizeof(Anchor->SocketDataP));
-+    if (n < 0) {
-+        // read error
-+        OCK_SYSLOG(LOG_ERR, "init_socket_data: read error \
-+                   on daemon socket, errno=%d", -n);
-+        ret = FALSE;
-+    }
-+    if (n != sizeof(Anchor->SocketDataP)) {
-+        // eof but we still expect some bytes
-+        OCK_SYSLOG(LOG_ERR, "init_socket_data: read returned \
-+                   with eof but we still \
-+                   expect %lu bytes from daemon",
-+                   sizeof(Anchor->SocketDataP) - n);
-+        ret = FALSE;
-+    }
- 
-     return ret;
- }
-+
-+static bool match_token_label_filter(event_msg_t *event, API_Slot_t *sltp)
-+{
-+    if (event->token_label[0] == ' ' || event->token_label[0] == '\0')
-+        return true;
-+
-+    return memcmp(event->token_label,
-+                  sltp->TokData->nv_token_data->token_info.label,
-+                  sizeof(event->token_label)) == 0;
-+}
-+
-+struct type_model {
-+    unsigned int type;
-+    char model[member_size(CK_TOKEN_INFO_32, model)];
-+};
-+
-+static const struct type_model type_model_flt[] = {
-+        { .type = EVENT_TOK_TYPE_CCA,  .model = "CCA             " },
-+        { .type = EVENT_TOK_TYPE_EP11, .model = "EP11            " },
-+};
-+
-+static bool match_token_type_filter(event_msg_t *event, API_Slot_t *sltp)
-+{
-+    size_t i;
-+
-+    if (event->token_type == EVENT_TOK_TYPE_ALL)
-+        return true;
-+
-+    for (i = 0; i < sizeof(type_model_flt) / sizeof(struct type_model); i++) {
-+        if (memcmp(sltp->TokData->nv_token_data->token_info.model,
-+                   type_model_flt[i].model,
-+                   sizeof(type_model_flt[i].model)) == 0 &&
-+            (event->token_type & type_model_flt[i].type) != 0)
-+            return true;
-+    }
-+
-+    return false;
-+}
-+
-+static int handle_event(API_Proc_Struct_t *anchor, event_msg_t *event,
-+                        char *payload, event_reply_t *reply)
-+{
-+    CK_SLOT_ID slotID;
-+    API_Slot_t *sltp;
-+    CK_RV rc;
-+
-+    /* If its not for our process, ignore it, don't increment reply counters */
-+    if (event->process_id != 0 && event->process_id != anchor->Pid)
-+        return 0;
-+
-+    for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
-+        sltp = &anchor->SltList[slotID];
-+        if (sltp->DLLoaded == FALSE || sltp->FcnList == NULL)
-+            continue;
-+
-+        if (!match_token_label_filter(event, sltp))
-+            continue;
-+        if (!match_token_type_filter(event, sltp))
-+            continue;
-+
-+        if (sltp->FcnList->ST_HandleEvent != NULL)
-+            rc = sltp->FcnList->ST_HandleEvent(sltp->TokData, event->type,
-+                                               event->flags, payload,
-+                                               event->payload_len);
-+        else
-+            rc = CKR_FUNCTION_NOT_SUPPORTED;
-+
-+        TRACE_DEVEL("Slot %lu ST_HandleEvent rc: 0x%lx\n", slotID, rc);
-+        switch (rc) {
-+        case CKR_OK:
-+            reply->positive_replies++;
-+            break;
-+        case CKR_FUNCTION_NOT_SUPPORTED:
-+            reply->nothandled_replies++;
-+            break;
-+        default:
-+            reply->negative_replies++;
-+            break;
-+        }
-+    }
-+
-+    return 0;
-+}
-+
-+static void event_thread_cleanup(void *arg)
-+{
-+    API_Proc_Struct_t *anchor = arg;
-+
-+    UNUSED(anchor);
-+
-+    TRACE_DEVEL("Event thread %lu terminating\n", pthread_self());
-+}
-+
-+static void *event_thread(void *arg)
-+{
-+    API_Proc_Struct_t *anchor = arg;
-+    int oldstate, oldtype;
-+    struct pollfd pollfd;
-+    event_msg_t event;
-+    char *payload;
-+    event_reply_t reply;
-+    ssize_t num;
-+    int rc;
-+
-+    UNUSED(arg);
-+
-+    TRACE_DEVEL("Event thread %lu running\n", pthread_self());
-+
-+    if (anchor->socketfd < 0) {
-+        TRACE_ERROR("socket is already closed.\n");
-+        TRACE_DEVEL("Event thread %lu terminating\n", pthread_self());
-+        return NULL;
-+    }
-+
-+    /* Enable cancellation */
-+    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-+    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
-+    pthread_cleanup_push(event_thread_cleanup, anchor);
-+
-+    pollfd.fd = anchor->socketfd;
-+    pollfd.events = POLLIN | POLLHUP | POLLERR;
-+
-+    while (1) {
-+        pollfd.revents = 0;
-+        rc = poll(&pollfd, 1, -1);
-+        if (rc < 0) {
-+            if (errno == EINTR)
-+                continue;
-+            TRACE_ERROR("poll failed: %d\n", errno);
-+            break;
-+        }
-+
-+        if (rc == 0)
-+            continue;
-+
-+        if (pollfd.revents & (POLLHUP | POLLERR)) {
-+            TRACE_ERROR("Error on socket, possibly closed by slot daemon\n");
-+            break;
-+        }
-+        if ((pollfd.revents & POLLIN) == 0)
-+            continue;
-+
-+        /* Disable for cancellation while we are working on an event */
-+        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
-+
-+        TRACE_DEVEL("Receive new event ....\n");
-+
-+        num = read_all(anchor->socketfd, (char *)&event, sizeof(event));
-+        if (num != sizeof(event)) {
-+            TRACE_ERROR("Error receiving the event, rc: %ld\n", num);
-+            break;
-+        }
-+
-+        TRACE_DEBUG("Event version:      %u\n", event.version);
-+        TRACE_DEBUG("Event type:         0x%08x\n", event.type);
-+        TRACE_DEBUG("Event flags:        0x%08x\n", event.flags);
-+        TRACE_DEBUG("Event token_type:   0x%08x\n", event.token_type);
-+        TRACE_DEBUG("Event token_name:   '%.32s'\n", event.token_label);
-+        TRACE_DEBUG("Event process_id:   %u\n", event.process_id);
-+        TRACE_DEBUG("Event payload_len:  %u\n", event.payload_len);
-+
-+        if (event.version != EVENT_VERSION_1) {
-+            TRACE_ERROR("Event version invalid: %u\n", event.version);
-+            break;
-+        }
-+
-+        payload = NULL;
-+        if (event.payload_len > 0) {
-+            payload = malloc(event.payload_len);
-+            if (payload == NULL) {
-+                TRACE_ERROR("Failed to allocate buffer for event payload\n");
-+                break;
-+            }
-+
-+            num = read_all(anchor->socketfd, payload, event.payload_len);
-+            if (num != event.payload_len) {
-+                TRACE_ERROR("Error receiving the event payload, rc: %ld\n", num);
-+                if (payload != NULL)
-+                    free(payload);
-+                break;
-+            }
-+
-+            TRACE_DEBUG("Event payload:\n");
-+            TRACE_DEBUG_DUMP("  ", payload, event.payload_len);
-+        }
-+
-+        memset(&reply, 0, sizeof(reply));
-+        reply.version = EVENT_VERSION_1;
-+        rc = handle_event(anchor, &event, payload, &reply);
-+        if (rc != 0) {
-+            TRACE_ERROR("Error handling the event, rc: %d\n", rc);
-+            if (payload != NULL)
-+                free(payload);
-+            break;
-+        }
-+
-+        TRACE_DEBUG("Reply version:      %u\n", reply.version);
-+        TRACE_DEBUG("Reply positive:     %u\n", reply.positive_replies);
-+        TRACE_DEBUG("Reply negative:     %u\n", reply.negative_replies);
-+        TRACE_DEBUG("Reply not-handled:  %u\n", reply.nothandled_replies);
-+
-+        if (event.flags & EVENT_FLAGS_REPLY_REQ) {
-+            num = send_all(anchor->socketfd, (char *)&reply, sizeof(reply));
-+            if (num != sizeof(reply)) {
-+                TRACE_ERROR("Error sending the event reply, rc: %ld\n", num);
-+                if (payload != NULL)
-+                    free(payload);
-+                break;
-+            }
-+        }
-+
-+        if (payload != NULL)
-+            free(payload);
-+
-+        /* Re-enable for  and test if we got canceled in the meantime */
-+        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-+        pthread_testcancel();
-+    }
-+
-+    /*
-+     * Close the socket if we encounter an unrecoverable error (e.g. received
-+     * invalid event) and stop the thread because of that.
-+     * If the thread is stopped via stop_event_thread(), then it gets canceled
-+     * via pthread_cancel(), and will not reach this place, thus the socket is
-+     * not closed. This is intended, and the socket will then be closed by
-+     * C_Finalize(). The atfork 'prepare' handler in the parent process also
-+     * stops the thread (via stop_event_thread()), and the socket must not be
-+     * closed in this case, because the thread is restarted in the atfork
-+     * 'parent' handler, and should continue to receive events from the
-+     * socket.
-+     */
-+    close(anchor->socketfd);
-+    anchor->socketfd = -1;
-+
-+    pthread_cleanup_pop(1);
-+    return NULL;
-+}
-+
-+int start_event_thread()
-+{
-+    int rc;
-+
-+    rc =  pthread_create(&Anchor->event_thread, NULL, event_thread, Anchor);
-+    if (rc != 0) {
-+        OCK_SYSLOG(LOG_ERR, "start_event_thread: pthread_create failed, "
-+                   "errno=%d", rc);
-+        TRACE_ERROR("Failed to start event thread, errno=%d\n", rc);
-+        return rc;
-+    }
-+
-+    TRACE_DEVEL("Event thread %lu has been started\n", Anchor->event_thread);
-+    return 0;
-+}
-+
-+int stop_event_thread()
-+{
-+    int rc;
-+    void *status;
-+
-+    TRACE_DEVEL("Canceling event thread %lu\n", Anchor->event_thread);
-+    rc = pthread_cancel(Anchor->event_thread);
-+    if (rc != 0 && rc != ESRCH)
-+        return rc;
-+
-+    TRACE_DEVEL("Waiting for event thread %lu to terminate\n",
-+                Anchor->event_thread);
-+    rc = pthread_join(Anchor->event_thread, &status);
-+    if (rc != 0)
-+        return rc;
-+
-+    if (status != PTHREAD_CANCELED) {
-+        TRACE_ERROR("Event thread was stopped, but did not return the "
-+                   "expected status\n");
-+    }
-+
-+    TRACE_DEVEL("Event thread %lu has terminated\n", Anchor->event_thread);
-+
-+    Anchor->event_thread = 0;
-+    return 0;
-+}
-diff --git a/usr/lib/cca_stdll/tok_struct.h b/usr/lib/cca_stdll/tok_struct.h
-index 2b43fa8e..182e2ac2 100644
---- a/usr/lib/cca_stdll/tok_struct.h
-+++ b/usr/lib/cca_stdll/tok_struct.h
-@@ -134,6 +134,7 @@ token_spec_t token_specific = {
-     &token_specific_reencrypt_single,
-     NULL,                       // set_attribute_values
-     NULL,                       // set_attrs_for_new_object
-+    NULL,                       // handle_event
- };
- 
- #endif
-diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c
-index aae00984..a3749d26 100644
---- a/usr/lib/common/new_host.c
-+++ b/usr/lib/common/new_host.c
-@@ -4039,6 +4039,24 @@ done:
-     return rc;
- }
- 
-+CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
-+                     unsigned int event_flags, const char *payload,
-+                     unsigned int payload_len)
-+{
-+    CK_RV rc;
-+
-+    if (token_specific.t_handle_event == NULL)
-+        return CKR_FUNCTION_NOT_SUPPORTED;
-+
-+    rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
-+                                       payload, payload_len);
-+
-+    TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
-+               "event_flags = 0x%08x\n", rc, event_type, event_flags);
-+
-+    return rc;
-+}
-+
- void SC_SetFunctionList(void)
- {
-     function_list.ST_Initialize = ST_Initialize;
-@@ -4104,4 +4122,6 @@ void SC_SetFunctionList(void)
-     function_list.ST_CancelFunction = NULL;     // SC_CancelFunction;
- 
-     function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
-+
-+    function_list.ST_HandleEvent = SC_HandleEvent;
- }
-diff --git a/usr/lib/common/tok_spec_struct.h b/usr/lib/common/tok_spec_struct.h
-index 30ffcf02..0e90d411 100644
---- a/usr/lib/common/tok_spec_struct.h
-+++ b/usr/lib/common/tok_spec_struct.h
-@@ -278,6 +278,10 @@ struct token_specific_struct {
- 
-     CK_RV(*t_set_attrs_for_new_object) (STDLL_TokData_t *, CK_OBJECT_CLASS,
-                                         CK_ULONG, TEMPLATE *);
-+
-+    CK_RV(*t_handle_event) (STDLL_TokData_t *tokdata, unsigned int event_type,
-+                            unsigned int event_flags, const char *payload,
-+                            unsigned int payload_len);
- };
- 
- typedef struct token_specific_struct token_spec_t;
-diff --git a/usr/lib/common/tok_specific.h b/usr/lib/common/tok_specific.h
-index ffb72909..997fa7e1 100644
---- a/usr/lib/common/tok_specific.h
-+++ b/usr/lib/common/tok_specific.h
-@@ -326,4 +326,10 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *,
-                                               CK_OBJECT_CLASS, CK_ULONG,
-                                               TEMPLATE *);
- 
-+CK_RV token_specific_handle_event(STDLL_TokData_t *tokdata,
-+                                  unsigned int event_type,
-+                                  unsigned int event_flags,
-+                                  const char *payload,
-+                                  unsigned int payload_len);
-+
- #endif
-diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
-index 6fcef68a..4e592363 100644
---- a/usr/lib/ep11_stdll/new_host.c
-+++ b/usr/lib/ep11_stdll/new_host.c
-@@ -4262,6 +4262,24 @@ done:
-     return rc;
- }
- 
-+CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
-+                     unsigned int event_flags, const char *payload,
-+                     unsigned int payload_len)
-+{
-+    CK_RV rc;
-+
-+    if (token_specific.t_handle_event == NULL)
-+        return CKR_FUNCTION_NOT_SUPPORTED;
-+
-+    rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
-+                                       payload, payload_len);
-+
-+    TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
-+               "event_flags = 0x%08x\n", rc, event_type, event_flags);
-+
-+    return rc;
-+}
-+
- void SC_SetFunctionList(void)
- {
-     function_list.ST_Initialize = ST_Initialize;
-@@ -4327,4 +4345,6 @@ void SC_SetFunctionList(void)
-     function_list.ST_CancelFunction = NULL;     // SC_CancelFunction;
- 
-     function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
-+
-+    function_list.ST_HandleEvent = SC_HandleEvent;
- }
-diff --git a/usr/lib/ep11_stdll/tok_struct.h b/usr/lib/ep11_stdll/tok_struct.h
-index 51aae6fb..2c0af9cf 100644
---- a/usr/lib/ep11_stdll/tok_struct.h
-+++ b/usr/lib/ep11_stdll/tok_struct.h
-@@ -137,6 +137,7 @@ token_spec_t token_specific = {
-     &token_specific_reencrypt_single,
-     &token_specific_set_attribute_values,
-     &token_specific_set_attrs_for_new_object,
-+    NULL,                       // handle_event
- };
- 
- #endif
-diff --git a/usr/lib/ica_s390_stdll/tok_struct.h b/usr/lib/ica_s390_stdll/tok_struct.h
-index 13ee72c9..a260a276 100644
---- a/usr/lib/ica_s390_stdll/tok_struct.h
-+++ b/usr/lib/ica_s390_stdll/tok_struct.h
-@@ -147,6 +147,7 @@ token_spec_t token_specific = {
-     NULL,                       // reencrypt_single
-     NULL,                       // set_attribute_values
-     NULL,                       // set_attrs_for_new_object
-+    NULL,                       // handle_event
- };
- 
- #endif
-diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c
-index 0f93ce5c..cfef7425 100644
---- a/usr/lib/icsf_stdll/new_host.c
-+++ b/usr/lib/icsf_stdll/new_host.c
-@@ -3332,6 +3332,24 @@ done:
-     return rc;
- }
- 
-+CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
-+                     unsigned int event_flags, const char *payload,
-+                     unsigned int payload_len)
-+{
-+    CK_RV rc;
-+
-+    if (token_specific.t_handle_event == NULL)
-+        return CKR_FUNCTION_NOT_SUPPORTED;
-+
-+    rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
-+                                       payload, payload_len);
-+
-+    TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
-+               "event_flags = 0x%08x\n", rc, event_type, event_flags);
-+
-+    return rc;
-+}
-+
- void SC_SetFunctionList(void)
- {
-     function_list.ST_Initialize = ST_Initialize;
-@@ -3397,4 +3415,6 @@ void SC_SetFunctionList(void)
-     function_list.ST_CancelFunction = NULL;     // SC_CancelFunction;
- 
-     function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
-+
-+    function_list.ST_HandleEvent = SC_HandleEvent;
- }
-diff --git a/usr/lib/icsf_stdll/tok_struct.h b/usr/lib/icsf_stdll/tok_struct.h
-index fb1619ee..0f930a29 100644
---- a/usr/lib/icsf_stdll/tok_struct.h
-+++ b/usr/lib/icsf_stdll/tok_struct.h
-@@ -129,6 +129,7 @@ token_spec_t token_specific = {
-     NULL,                       // reencrypt_single
-     NULL,                       // set_attribute_values
-     NULL,                       // set_attrs_for_new_object
-+    NULL,                       // handle_event
- };
- 
- #endif
-diff --git a/usr/lib/soft_stdll/tok_struct.h b/usr/lib/soft_stdll/tok_struct.h
-index acf7c5d7..e43df038 100644
---- a/usr/lib/soft_stdll/tok_struct.h
-+++ b/usr/lib/soft_stdll/tok_struct.h
-@@ -172,6 +172,7 @@ token_spec_t token_specific = {
-     NULL,                       // reencrypt_single
-     NULL,                       // set_attribute_values
-     NULL,                       // set_attrs_for_new_object
-+    NULL,                       // handle_event
- };
- 
- #endif
-diff --git a/usr/lib/tpm_stdll/tok_struct.h b/usr/lib/tpm_stdll/tok_struct.h
-index d48b93e5..8903f123 100644
---- a/usr/lib/tpm_stdll/tok_struct.h
-+++ b/usr/lib/tpm_stdll/tok_struct.h
-@@ -120,4 +120,5 @@ struct token_specific_struct token_specific = {
-     NULL,                       // reencrypt_single
-     NULL,                       // set_attribute_values
-     NULL,                       // set_attrs_for_new_object
-+    NULL,                       // handle_event
- };
diff --git a/SOURCES/opencryptoki-3.16.0-b07505993dd8b2f367cf3b630f6da186e4e8550d.patch b/SOURCES/opencryptoki-3.16.0-b07505993dd8b2f367cf3b630f6da186e4e8550d.patch
deleted file mode 100644
index 6936783..0000000
--- a/SOURCES/opencryptoki-3.16.0-b07505993dd8b2f367cf3b630f6da186e4e8550d.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-commit b07505993dd8b2f367cf3b630f6da186e4e8550d
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Feb 10 15:12:25 2021 +0100
-
-    Avoid deadlock in dlclose() after a fork
-    
-    Calling dlclose() in a atfork handler may cause a deadlock.
-    dlclose() may itself modify the atfork handler table to remove
-    any fork handlers that the to be unloaded library has registered.
-    Since the atfork handler table is currently locked when we are in
-    an atfork handler, this would produce a deadlock.
-    
-    Skip the dlclose() if we are in an atfork handler to avoid the deadlock.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c
-index 3ccb6d41..f1ee9132 100644
---- a/usr/lib/api/api_interface.c
-+++ b/usr/lib/api/api_interface.c
-@@ -1516,7 +1516,15 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
-             }
-         }
- 
--        DL_UnLoad(sltp, slotID);
-+        /*
-+         * Calling dlclose() in a atfork handler may cause a deadlock.
-+         * dlclose() may itself modify the atfork handler table to remove
-+         * any fork handlers that the to be unloaded library has registered.
-+         * Since the atfork handler table is currently locked when we are in
-+         * an atfork handler, this would produce a deadlock.
-+         */
-+        if (!in_child_fork_initializer)
-+            DL_UnLoad(sltp, slotID);
-     }
- 
-     // Un register from Slot D
diff --git a/SOURCES/opencryptoki-3.16.0-bf812c652c49d7e248b115d121a4f7f6568941a2.patch b/SOURCES/opencryptoki-3.16.0-bf812c652c49d7e248b115d121a4f7f6568941a2.patch
deleted file mode 100644
index f5a7617..0000000
--- a/SOURCES/opencryptoki-3.16.0-bf812c652c49d7e248b115d121a4f7f6568941a2.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-commit bf812c652c49d7e248b115d121a4f7f6568941a2
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Apr 6 13:41:55 2021 +0200
-
-    Update travis yaml file to install libudev development files
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/.travis.yml b/.travis.yml
-index d2907246..fd4092e3 100644
---- a/.travis.yml
-+++ b/.travis.yml
-@@ -5,7 +5,7 @@ language: c
- 
- before_install:
-     - sudo apt-get -qq update
--    - sudo apt-get install -y expect trousers libldap2-dev libtspi-dev wget
-+    - sudo apt-get install -y expect trousers libldap2-dev libtspi-dev wget libudev-dev
-     - sudo wget https://launchpad.net/ubuntu/+archive/primary/+files/libica3_3.4.0-0ubuntu1_s390x.deb
-     - sudo wget https://launchpad.net/ubuntu/+archive/primary/+files/libica-dev_3.4.0-0ubuntu1_s390x.deb
-     - sudo dpkg -i libica3_3.4.0-0ubuntu1_s390x.deb || true    # icatok needs libica >= 3.3
diff --git a/SOURCES/opencryptoki-3.16.0-c79e899d77a5724635a9d4451a34a240e2c7e891.patch b/SOURCES/opencryptoki-3.16.0-c79e899d77a5724635a9d4451a34a240e2c7e891.patch
deleted file mode 100644
index d515e15..0000000
--- a/SOURCES/opencryptoki-3.16.0-c79e899d77a5724635a9d4451a34a240e2c7e891.patch
+++ /dev/null
@@ -1,462 +0,0 @@
-commit c79e899d77a5724635a9d4451a34a240e2c7e891
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Fri Apr 16 13:41:41 2021 +0200
-
-    Fix potential deadlock situation with double read-locks
-    
-    Do not get and read-lock an object twice within the same thread via
-    function object_mgr_find_in_map1(), as this would read-lock the object
-    twice.
-    
-    This could cause a deadlock situation, when in-between the first
-    and the second call to object_mgr_find_in_map1() the token object is
-    modified by another process. The second object_mgr_find_in_map1() would
-    detect that the object has been modified (object_mgr_check_shm()), and
-    would try to re-load the object from the disk. For re-loading, the
-    object is unlocked once, and a write-lock is acquired instead.
-    However, if the current thread has read-locked the object twice, but
-    releases only one read-lock, then it will never get the write lock,
-    because it still owns the read lock itself.
-    
-    To avoid this situation, release the read-lock before calling another
-    function that also acquires the read lock of the object. That way, only
-    one read-lock is held by the current thread, and re-loading the object
-    will not cause a deadlock.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/decr_mgr.c b/usr/lib/common/decr_mgr.c
-index 317ef995..9842302b 100644
---- a/usr/lib/common/decr_mgr.c
-+++ b/usr/lib/common/decr_mgr.c
-@@ -540,6 +540,10 @@ CK_RV decr_mgr_init(STDLL_TokData_t *tokdata,
-         }
-         memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT));
- 
-+        /* Release obj lock, token specific aes-gcm may re-acquire the lock */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         rc = aes_gcm_init(tokdata, sess, ctx, mech, key_handle, 0);
-         if (rc) {
-             TRACE_ERROR("Could not initialize AES_GCM parms.\n");
-diff --git a/usr/lib/common/encr_mgr.c b/usr/lib/common/encr_mgr.c
-index d3ecdeee..3e85ceab 100644
---- a/usr/lib/common/encr_mgr.c
-+++ b/usr/lib/common/encr_mgr.c
-@@ -537,6 +537,10 @@ CK_RV encr_mgr_init(STDLL_TokData_t *tokdata,
-         }
-         memset(ctx->context, 0x0, sizeof(AES_GCM_CONTEXT));
- 
-+        /* Release obj lock, token specific aes-gcm may re-acquire the lock */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         rc = aes_gcm_init(tokdata, sess, ctx, mech, key_handle, 1);
-         if (rc != CKR_OK) {
-             TRACE_ERROR("Could not initialize AES_GCM parms.\n");
-diff --git a/usr/lib/common/mech_rsa.c b/usr/lib/common/mech_rsa.c
-index 1652f90a..e35b383c 100644
---- a/usr/lib/common/mech_rsa.c
-+++ b/usr/lib/common/mech_rsa.c
-@@ -602,6 +602,10 @@ CK_RV rsa_oaep_crypt(STDLL_TokData_t *tokdata, SESSION *sess,
-             goto done;
-         }
- 
-+        /* Release obj lock, token specific rsa-oaep may re-acquire the lock */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         rc = token_specific.t_rsa_oaep_encrypt(tokdata, ctx, in_data,
-                                                in_data_len, out_data,
-                                                out_data_len, hash, hlen);
-@@ -625,6 +629,10 @@ CK_RV rsa_oaep_crypt(STDLL_TokData_t *tokdata, SESSION *sess,
-             goto done;
-         }
- 
-+        /* Release obj lock, token specific rsa-oaep may re-acquire the lock */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         rc = token_specific.t_rsa_oaep_decrypt(tokdata, ctx, in_data,
-                                                in_data_len, out_data,
-                                                out_data_len, hash, hlen);
-@@ -1331,6 +1339,10 @@ CK_RV rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess,
-         goto done;
-     }
- 
-+    /* Release obj lock, token specific rsa_pss may re-acquire the lock */
-+    object_put(tokdata, key_obj, TRUE);
-+    key_obj = NULL;
-+
-     rc = token_specific.t_rsa_pss_sign(tokdata, sess, ctx, in_data, in_data_len,
-                                        out_data, out_data_len);
-     if (rc != CKR_OK)
-@@ -1389,6 +1401,10 @@ CK_RV rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess,
-         goto done;
-     }
- 
-+    /* Release obj lock, token specific rsa_pss may re-acquire the lock */
-+    object_put(tokdata, key_obj, TRUE);
-+    key_obj = NULL;
-+
-     rc = token_specific.t_rsa_pss_verify(tokdata, sess, ctx, in_data,
-                                          in_data_len, signature, sig_len);
-     if (rc != CKR_OK)
-diff --git a/usr/lib/common/sign_mgr.c b/usr/lib/common/sign_mgr.c
-index 937a371a..c7268e01 100644
---- a/usr/lib/common/sign_mgr.c
-+++ b/usr/lib/common/sign_mgr.c
-@@ -424,6 +424,10 @@ CK_RV sign_mgr_init(STDLL_TokData_t *tokdata,
-         ctx->context_len = 0;
-         ctx->context = NULL;
- 
-+        /* Release obj lock, token specific hmac-sign may re-acquire the lock */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         rc = hmac_sign_init(tokdata, sess, mech, key);
-         if (rc != CKR_OK) {
-             TRACE_ERROR("Failed to initialize hmac.\n");
-diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
-index 3ac3768a..52f95d7a 100644
---- a/usr/lib/ep11_stdll/ep11_specific.c
-+++ b/usr/lib/ep11_stdll/ep11_specific.c
-@@ -6948,6 +6948,13 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
-     rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
-     switch (rc) {
-     case CKR_OK:
-+        /*
-+         * Release obj lock, sign_mgr_init or ep11tok_sign_verify_init_ibm_ed
-+         * may re-acquire the lock
-+         */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         /* Note that Edwards curves in general are not yet supported in
-          * opencryptoki. These two special IBM specific ED mechs are only
-          * supported by the ep11token, so let's keep them local here. */
-@@ -7029,11 +7036,16 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
-          * opencryptoki. These two special IBM specific ED mechs are only
-          * supported by the ep11token, so let's keep them local here. */
-         if (ctx->mech.mechanism == CKM_IBM_ED25519_SHA512 ||
--            ctx->mech.mechanism == CKM_IBM_ED448_SHA3)
-+            ctx->mech.mechanism == CKM_IBM_ED448_SHA3) {
-             rc = pkey_ibm_ed_sign(key_obj, in_data, in_data_len, signature, sig_len);
--        else
-+        } else {
-+            /* Release obj lock, sign_mgr_sign may re-acquire the lock */
-+            object_put(tokdata, key_obj, TRUE);
-+            key_obj = NULL;
-+
-             rc = sign_mgr_sign(tokdata, session, length_only, ctx, in_data,
-                                in_data_len, signature, sig_len);
-+        }
-         goto done; /* no ep11 fallback possible */
-     }
- 
-@@ -7071,6 +7083,11 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
-     if (!in_data || !in_data_len)
-         return CKR_OK;
- 
-+    if (ctx->pkey_active) {
-+        rc = sign_mgr_sign_update(tokdata, session, ctx, in_data, in_data_len);
-+        goto done; /* no ep11 fallback possible */
-+    }
-+
-     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                           READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7078,11 +7095,6 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    if (ctx->pkey_active) {
--        rc = sign_mgr_sign_update(tokdata, session, ctx, in_data, in_data_len);
--        goto done; /* no ep11 fallback possible */
--    }
--
-     RETRY_START
-         rc = dll_m_SignUpdate(ctx->context, ctx->context_len, in_data,
-                               in_data_len, ep11_data->target);
-@@ -7115,6 +7127,11 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
- 
-+    if (ctx->pkey_active) {
-+        rc = sign_mgr_sign_final(tokdata, session, length_only, ctx, signature, sig_len);
-+        goto done; /* no ep11 fallback possible */
-+    }
-+
-     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                           READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7122,11 +7139,6 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    if (ctx->pkey_active) {
--        rc = sign_mgr_sign_final(tokdata, session, length_only, ctx, signature, sig_len);
--        goto done; /* no ep11 fallback possible */
--    }
--
-     RETRY_START
-         rc = dll_m_SignFinal(ctx->context, ctx->context_len, signature, sig_len,
-                              ep11_data->target);
-@@ -7241,6 +7253,13 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
-     rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
-     switch (rc) {
-     case CKR_OK:
-+        /*
-+         * Release obj lock, verify_mgr_init or ep11tok_sign_verify_init_ibm_ed
-+         * may re-acquire the lock
-+         */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         /* Note that Edwards curves in general are not yet supported in
-          * opencryptoki. These two special IBM specific ED mechs are only
-          * supported by the ep11token, so let's keep them local here. */
-@@ -7320,12 +7339,17 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
-          * opencryptoki. These two special IBM specific ED mechs are only
-          * supported by the ep11token, so let's keep them local here. */
-         if (ctx->mech.mechanism == CKM_IBM_ED25519_SHA512 ||
--            ctx->mech.mechanism == CKM_IBM_ED448_SHA3)
-+            ctx->mech.mechanism == CKM_IBM_ED448_SHA3) {
-             rc = pkey_ibm_ed_verify(key_obj, in_data, in_data_len,
-                                     signature, sig_len);
--        else
-+        } else {
-+            /* Release obj lock, verify_mgr_verify may re-acquire the lock */
-+            object_put(tokdata, key_obj, TRUE);
-+            key_obj = NULL;
-+
-             rc = verify_mgr_verify(tokdata, session, ctx, in_data,
-                                    in_data_len, signature, sig_len);
-+        }
-         goto done; /* no ep11 fallback possible */
-     }
- 
-@@ -7363,6 +7387,11 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
-     if (!in_data || !in_data_len)
-         return CKR_OK;
- 
-+    if (ctx->pkey_active) {
-+        rc = verify_mgr_verify_update(tokdata, session, ctx, in_data, in_data_len);
-+        goto done; /* no ep11 fallback possible */
-+    }
-+
-     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                          READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7370,11 +7399,6 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    if (ctx->pkey_active) {
--        rc = verify_mgr_verify_update(tokdata, session, ctx, in_data, in_data_len);
--        goto done; /* no ep11 fallback possible */
--    }
--
-     RETRY_START
-         rc = dll_m_VerifyUpdate(ctx->context, ctx->context_len, in_data,
-                                 in_data_len, ep11_data->target);
-@@ -7406,6 +7430,11 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
- 
-+    if (ctx->pkey_active) {
-+        rc = verify_mgr_verify_final(tokdata, session, ctx, signature, sig_len);
-+        goto done; /* no ep11 fallback possible */
-+    }
-+
-     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                          READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7413,11 +7442,6 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    if (ctx->pkey_active) {
--        rc = verify_mgr_verify_final(tokdata, session, ctx, signature, sig_len);
--        goto done; /* no ep11 fallback possible */
--    }
--
-     RETRY_START
-         rc = dll_m_VerifyFinal(ctx->context, ctx->context_len, signature,
-                                sig_len, ep11_data->target);
-@@ -7501,6 +7525,12 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
- 
-+    if (ctx->pkey_active) {
-+        rc = decr_mgr_decrypt_final(tokdata, session, length_only,
-+                                    ctx, output_part, p_output_part_len);
-+        goto done; /* no ep11 fallback possible */
-+    }
-+
-     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                          READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7508,12 +7538,6 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    if (ctx->pkey_active) {
--        rc = decr_mgr_decrypt_final(tokdata, session, length_only,
--                                    ctx, output_part, p_output_part_len);
--        goto done; /* no ep11 fallback possible */
--    }
--
-     RETRY_START
-         rc = dll_m_DecryptFinal(ctx->context, ctx->context_len,
-                                 output_part, p_output_part_len,
-@@ -7548,13 +7572,6 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
- 
--    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
--                         READ_LOCK);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
--        return rc;
--    }
--
-     if (ctx->pkey_active) {
-         rc = decr_mgr_decrypt(tokdata, session, length_only, ctx,
-                               input_data, input_data_len, output_data,
-@@ -7562,6 +7579,13 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done; /* no ep11 fallback possible */
-     }
- 
-+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-+                         READ_LOCK);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-+        return rc;
-+    }
-+
-     RETRY_START
-         rc = dll_m_Decrypt(ctx->context, ctx->context_len, input_data,
-                            input_data_len, output_data, p_output_data_len,
-@@ -7602,13 +7626,6 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return CKR_OK;          /* nothing to update, keep context */
-     }
- 
--    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
--                         READ_LOCK);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
--        return rc;
--    }
--
-     if (ctx->pkey_active) {
-         rc = decr_mgr_decrypt_update(tokdata, session, length_only,
-                                      ctx, input_part, input_part_len,
-@@ -7616,6 +7633,13 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done; /* no ep11 fallback possible */
-     }
- 
-+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-+                         READ_LOCK);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-+        return rc;
-+    }
-+
-     RETRY_START
-         rc = dll_m_DecryptUpdate(ctx->context, ctx->context_len,
-                                  input_part, input_part_len, output_part,
-@@ -7695,6 +7719,12 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
- 
-+    if (ctx->pkey_active) {
-+        rc = encr_mgr_encrypt_final(tokdata, session, length_only,
-+                                    ctx, output_part, p_output_part_len);
-+        goto done; /* no ep11 fallback possible */
-+    }
-+
-     rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-                          READ_LOCK);
-     if (rc != CKR_OK) {
-@@ -7702,12 +7732,6 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
-         return rc;
-     }
- 
--    if (ctx->pkey_active) {
--        rc = encr_mgr_encrypt_final(tokdata, session, length_only,
--                                    ctx, output_part, p_output_part_len);
--        goto done; /* no ep11 fallback possible */
--    }
--
-     RETRY_START
-         rc = dll_m_EncryptFinal(ctx->context, ctx->context_len,
-                                 output_part, p_output_part_len,
-@@ -7742,13 +7766,6 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
-     CK_BYTE *keyblob;
-     OBJECT *key_obj = NULL;
- 
--    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
--                         READ_LOCK);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
--        return rc;
--    }
--
-     if (ctx->pkey_active) {
-         rc = encr_mgr_encrypt(tokdata, session, length_only, ctx,
-                               input_data, input_data_len, output_data,
-@@ -7756,6 +7773,13 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done; /* no ep11 fallback possible */
-     }
- 
-+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-+                         READ_LOCK);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-+        return rc;
-+    }
-+
-     RETRY_START
-         rc = dll_m_Encrypt(ctx->context, ctx->context_len, input_data,
-                            input_data_len, output_data, p_output_data_len,
-@@ -7796,13 +7820,6 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-         return CKR_OK;          /* nothing to update, keep context */
-     }
- 
--    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
--                         READ_LOCK);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
--        return rc;
--    }
--
-     if (ctx->pkey_active) {
-         rc = encr_mgr_encrypt_update(tokdata, session, length_only, ctx,
-                                      input_part, input_part_len, output_part,
-@@ -7810,6 +7827,13 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
-         goto done; /* no ep11 fallback possible */
-     }
- 
-+    rc = h_opaque_2_blob(tokdata, ctx->key, &keyblob, &keyblobsize, &key_obj,
-+                         READ_LOCK);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("%s h_opaque_2_blob, rc=0x%lx\n", __func__, rc);
-+        return rc;
-+    }
-+
-     RETRY_START
-         rc = dll_m_EncryptUpdate(ctx->context, ctx->context_len,
-                                  input_part, input_part_len, output_part,
-@@ -7921,6 +7945,10 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
-     rc = ep11tok_pkey_check(tokdata, session, key_obj, mech);
-     switch (rc) {
-     case CKR_OK:
-+        /* Release obj lock, encr/decr_mgr_init may re-acquire the lock */
-+        object_put(tokdata, key_obj, TRUE);
-+        key_obj = NULL;
-+
-         if (op == DECRYPT) {
-             rc = decr_mgr_init(tokdata, session, &session->decr_ctx,
-                                OP_DECRYPT_INIT, mech, key);
diff --git a/SOURCES/opencryptoki-3.16.0-d2f137cce5e6efb123842509352c7c49f889c67f.patch b/SOURCES/opencryptoki-3.16.0-d2f137cce5e6efb123842509352c7c49f889c67f.patch
deleted file mode 100644
index 8f1477c..0000000
--- a/SOURCES/opencryptoki-3.16.0-d2f137cce5e6efb123842509352c7c49f889c67f.patch
+++ /dev/null
@@ -1,104 +0,0 @@
-commit d2f137cce5e6efb123842509352c7c49f889c67f
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Thu Jul 22 15:55:02 2021 +0200
-
-    pkcstok_migrate: Rework string quoting for opencryptoki.conf migration
-    
-    Due to the way the parser works, a slot description like
-    'description = "slot"' works, but not without quotes ('description = slot').
-    The word 'slot' is treated as a keyword if not quoted (besides other keywords,
-    too), so if the word 'slot' would appear in an unquoted string, the
-    configuration file would fail to parse.
-    
-    Always quote the value of 'description' and 'manufacturer'. Quote the
-    value of 'stdll', 'confname', and 'tokname' if it contains spaces, and
-    never quote the value of 'hwversion', 'firmwareversion', and 'tokversion'.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-index a29dc8f7..853986e8 100644
---- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-@@ -2060,7 +2060,7 @@ done:
-  */
- static int parseupdate_ockversion(void *private, const char *version)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
-     fprintf(u->f, "version %s", version);
-     return 0;
-@@ -2075,14 +2075,14 @@ static void parseupdate_disab_event_supp(void *private)
- 
- static void parseupdate_eol(void *private)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
-     fputc('\n', u->f);
- }
- 
- static int parseupdate_begin_slot(void *private, int slot, int nl_before_begin)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
-     u->activeslot = (slot == u->slotnum);
-     if (nl_before_begin)
-@@ -2094,7 +2094,7 @@ static int parseupdate_begin_slot(void *private, int slot, int nl_before_begin)
- 
- static int parseupdate_end_slot(void *private)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
-     if (u->activeslot)
-         fprintf(u->f, "  tokversion = 3.12\n");
-@@ -2105,19 +2105,32 @@ static int parseupdate_end_slot(void *private)
- 
- static int parseupdate_key_str(void *private, int tok, const char *val)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
--    if (tok != KW_HWVERSION && tok != KW_FWVERSION &&
--        strchr(val, ' ') != NULL)
-+    switch (tok) {
-+    case KW_SLOTDESC:
-+    case KW_MANUFID:
-         fprintf(u->f, "  %s = \"%s\"", keyword_token_to_str(tok), val);
--    else if (tok != KW_TOKVERSION)
-+        break;
-+    case KW_STDLL:
-+    case KW_CONFNAME:
-+    case KW_TOKNAME:
-+        if (strchr(val, ' ') != NULL)
-+            fprintf(u->f, "  %s = \"%s\"", keyword_token_to_str(tok), val);
-+        else
-+            fprintf(u->f, "  %s = %s", keyword_token_to_str(tok), val);
-+        break;
-+    case KW_HWVERSION:
-+    case KW_FWVERSION:
-         fprintf(u->f, "  %s = %s", keyword_token_to_str(tok), val);
-+        break;
-+	}
-     return 0;
- }
- 
- static int parseupdate_key_vers(void *private, int tok, unsigned int vers)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
-     if (tok == KW_TOKVERSION && !u->activeslot)
-         fprintf(u->f, "  %s = %d.%d", keyword_token_to_str(tok),
-@@ -2127,7 +2140,7 @@ static int parseupdate_key_vers(void *private, int tok, unsigned int vers)
- 
- static void parseupdate_eolcomment(void *private, const char *comment)
- {
--	struct parseupdate *u = (struct parseupdate *)private;
-+    struct parseupdate *u = (struct parseupdate *)private;
- 
-     fprintf(u->f, "#%s", comment);
- }
diff --git a/SOURCES/opencryptoki-3.16.0-d7de5092247a0efc2c397f12977a7c9925420143.patch b/SOURCES/opencryptoki-3.16.0-d7de5092247a0efc2c397f12977a7c9925420143.patch
deleted file mode 100644
index 40a4962..0000000
--- a/SOURCES/opencryptoki-3.16.0-d7de5092247a0efc2c397f12977a7c9925420143.patch
+++ /dev/null
@@ -1,239 +0,0 @@
-commit d7de5092247a0efc2c397f12977a7c9925420143
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Feb 16 17:15:20 2021 +0100
-
-    TESTCASES: Add event support tests
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/testcases/misc_tests/events.c b/testcases/misc_tests/events.c
-new file mode 100644
-index 00000000..fecc7bfe
---- /dev/null
-+++ b/testcases/misc_tests/events.c
-@@ -0,0 +1,190 @@
-+/*
-+ * COPYRIGHT (c) International Business Machines Corp. 2021
-+ *
-+ * This program is provided under the terms of the Common Public License,
-+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-+ * found in the file LICENSE file or at
-+ * https://opensource.org/licenses/cpl1.0.php
-+ */
-+
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+
-+#include "event_client.h"
-+#include "regress.h"
-+#include "defs.h"
-+
-+const char payload[20] = "12345678901234567890";
-+
-+static inline void init_event_destination(struct event_destination *dest,
-+                                          unsigned int token_type,
-+                                          const char *label,
-+                                          pid_t process_id)
-+{
-+    size_t len;
-+
-+    dest->token_type = token_type;
-+    dest->process_id = process_id;
-+
-+    memset(dest->token_label, ' ', sizeof(dest->token_label));
-+    if (label != NULL) {
-+        len = strlen(label);
-+        memcpy(dest->token_label, label, len > sizeof(dest->token_label) ?
-+                                    sizeof(dest->token_label) : len);
-+    }
-+}
-+
-+int main(int argc, char **argv)
-+{
-+    CK_C_INITIALIZE_ARGS cinit_args;
-+    int rc, fd = -1, ret = 1;
-+    struct event_destination dest;
-+    struct event_reply reply;
-+
-+    UNUSED(argc);
-+    UNUSED(argv);
-+
-+    rc = do_GetFunctionList();
-+    if (!rc) {
-+        testcase_error("do_getFunctionList(), rc=%s", p11_get_ckr(rc));
-+        return rc;
-+    }
-+
-+    /*
-+     * Initialize Opencryptoki in this process, so that at least one
-+     * process is receiving the events.
-+     */
-+    memset(&cinit_args, 0x0, sizeof(cinit_args));
-+    cinit_args.flags = CKF_OS_LOCKING_OK;
-+    funcs->C_Initialize(&cinit_args);
-+
-+    testcase_setup(0);
-+    testcase_begin("Starting event tests");
-+
-+    // Test fork before C_Initialize
-+    testcase_new_assertion();
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, NULL, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (simple, one-shot) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (simple, one-shot)");
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, sizeof(payload), payload,
-+                    NULL, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (payload, one-shot) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (payload, one-shot)");
-+
-+    init_event_destination(&dest, EVENT_TOK_TYPE_CCA, NULL, 0);
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, &dest, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (token-type, one-shot) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (token-type, one-shot)");
-+
-+    init_event_destination(&dest, EVENT_TOK_TYPE_ALL, "cca", 0);
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, &dest, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (token-label, one-shot) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (token-label, one-shot)");
-+
-+    init_event_destination(&dest, EVENT_TOK_TYPE_ALL, NULL, 12345);
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_NONE, 0, NULL, &dest, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (pid, one-shot) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (pid, one-shot)");
-+
-+    memset(&reply, 0, sizeof(reply));
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_REPLY_REQ, 0, NULL, NULL, &reply);
-+    if (rc != 0) {
-+        testcase_fail("send_event (reply, one-shot) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    printf("Reply: positive_replies:    %lu\n", reply.positive_replies);
-+    printf("       negative_replies:    %lu\n", reply.negative_replies);
-+    printf("       nothandled_replies:  %lu\n", reply.nothandled_replies);
-+    if (reply.positive_replies + reply.negative_replies +
-+            reply.nothandled_replies == 0) {
-+        testcase_fail("send_event (reply, one-shot) replies all zero");
-+        goto out;
-+    }
-+    testcase_pass("send_event (reply, one-shot)");
-+
-+
-+    fd = init_event_client();
-+    if (fd < 0) {
-+        testcase_fail("init_event_client rc = %d (%s)", fd, strerror(-fd));
-+        goto out;
-+    }
-+    testcase_pass("init_event_client()");
-+
-+    rc = send_event(fd, 0x12345, EVENT_FLAGS_NONE, 0, NULL, NULL, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (simple) rc = %d (%s)", rc, strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (simple)");
-+
-+    rc = send_event(fd, 0x12345, EVENT_FLAGS_NONE, sizeof(payload), payload,
-+                    NULL, NULL);
-+    if (rc != 0) {
-+        testcase_fail("send_event (payload) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    testcase_pass("send_event (payload)");
-+
-+    memset(&reply, 0, sizeof(reply));
-+
-+    rc = send_event(-1, 0x12345, EVENT_FLAGS_REPLY_REQ, 0, NULL, NULL, &reply);
-+    if (rc != 0) {
-+        testcase_fail("send_event (reply) rc = %d (%s)", rc,
-+                      strerror(-rc));
-+        goto out;
-+    }
-+    printf("Reply: positive_replies:    %lu\n", reply.positive_replies);
-+    printf("       negative_replies:    %lu\n", reply.negative_replies);
-+    printf("       nothandled_replies:  %lu\n", reply.nothandled_replies);
-+    if (reply.positive_replies + reply.negative_replies +
-+            reply.nothandled_replies == 0) {
-+        testcase_fail("send_event (reply) replies all zero");
-+        goto out;
-+    }
-+    testcase_pass("send_event (reply)");
-+
-+    term_event_client(fd);
-+    fd = -1;
-+
-+    ret = 0;
-+
-+out:
-+    if (fd >= 0)
-+        term_event_client(fd);
-+
-+    funcs->C_Finalize(NULL);
-+
-+    testcase_print_result();
-+    return ret;
-+}
-diff --git a/testcases/misc_tests/misc_tests.mk b/testcases/misc_tests/misc_tests.mk
-index 3de11ebe..fb7cc0a1 100644
---- a/testcases/misc_tests/misc_tests.mk
-+++ b/testcases/misc_tests/misc_tests.mk
-@@ -7,7 +7,8 @@ noinst_PROGRAMS +=							\
- 	testcases/misc_tests/fork testcases/misc_tests/multi_instance   \
- 	testcases/misc_tests/obj_lock testcases/misc_tests/tok2tok_transport \
- 	testcases/misc_tests/obj_lock testcases/misc_tests/reencrypt    \
--	testcases/misc_tests/cca_export_import_test
-+	testcases/misc_tests/cca_export_import_test			\
-+	testcases/misc_tests/events
- 
- testcases_misc_tests_obj_mgmt_tests_CFLAGS = ${testcases_inc}
- testcases_misc_tests_obj_mgmt_tests_LDADD =				\
-@@ -73,3 +74,8 @@ testcases_misc_tests_cca_export_import_test_LDADD =			\
- 	testcases/common/libcommon.la
- testcases_misc_tests_cca_export_import_test_SOURCES =			\
- 	testcases/misc_tests/cca_export_import_test.c
-+	
-+testcases_misc_tests_events_CFLAGS = ${testcases_inc}
-+testcases_misc_tests_events_LDADD = testcases/common/libcommon.la
-+testcases_misc_tests_events_SOURCES = testcases/misc_tests/events.c	\
-+	usr/lib/common/event_client.c
-diff --git a/testcases/ock_tests.sh.in b/testcases/ock_tests.sh.in
-index 64c77a7d..6558b031 100755
---- a/testcases/ock_tests.sh.in
-+++ b/testcases/ock_tests.sh.in
-@@ -53,6 +53,7 @@ OCK_TESTS+=" pkcs11/findobjects pkcs11/generate_keypair"
- OCK_TESTS+=" pkcs11/get_interface pkcs11/getobjectsize pkcs11/sess_opstate"
- OCK_TESTS+=" misc_tests/fork misc_tests/obj_mgmt_tests" 
- OCK_TESTS+=" misc_tests/obj_mgmt_lock_tests misc_tests/reencrypt"
-+OCK_TESTS+=" misc_tests/events"
- OCK_TEST=""
- OCK_BENCHS="pkcs11/*bench"
- 
diff --git a/SOURCES/opencryptoki-3.16.0-d929fe8470e99f4dcbbd889e7aa87e147d0d5b48.patch b/SOURCES/opencryptoki-3.16.0-d929fe8470e99f4dcbbd889e7aa87e147d0d5b48.patch
deleted file mode 100644
index 5e9a346..0000000
--- a/SOURCES/opencryptoki-3.16.0-d929fe8470e99f4dcbbd889e7aa87e147d0d5b48.patch
+++ /dev/null
@@ -1,619 +0,0 @@
-commit d929fe8470e99f4dcbbd889e7aa87e147d0d5b48
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Fri Feb 12 11:25:21 2021 +0100
-
-    Externalize linked list functions
-    
-    Externalize the linked list functions (dlist_xxx), so that they
-    can also be used on pkcsslotd.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/cca_stdll/cca_stdll.mk b/usr/lib/cca_stdll/cca_stdll.mk
-index bd230b9f..c5e86fa7 100644
---- a/usr/lib/cca_stdll/cca_stdll.mk
-+++ b/usr/lib/cca_stdll/cca_stdll.mk
-@@ -35,7 +35,8 @@ opencryptoki_stdll_libpkcs11_cca_la_SOURCES =				\
- 	usr/lib/common/mech_ssl3.c usr/lib/common/verify_mgr.c		\
- 	usr/lib/common/p11util.c usr/lib/common/sw_crypt.c		\
- 	usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c	\
--	usr/lib/cca_stdll/cca_specific.c usr/lib/common/attributes.c
-+	usr/lib/cca_stdll/cca_specific.c usr/lib/common/attributes.c	\
-+	usr/lib/common/dlist.c
- 
- if ENABLE_LOCKS
- opencryptoki_stdll_libpkcs11_cca_la_SOURCES +=				\
-diff --git a/usr/lib/common/dlist.c b/usr/lib/common/dlist.c
-new file mode 100644
-index 00000000..1fee1ea9
---- /dev/null
-+++ b/usr/lib/common/dlist.c
-@@ -0,0 +1,218 @@
-+/*
-+ * COPYRIGHT (c) International Business Machines Corp. 2021
-+ *
-+ * This program is provided under the terms of the Common Public License,
-+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-+ * found in the file LICENSE file or at
-+ * https://opensource.org/licenses/cpl1.0.php
-+ */
-+
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <unistd.h>
-+#include <sys/types.h>
-+#include <errno.h>
-+
-+#include "dlist.h"
-+#include "host_defs.h"
-+#include "h_extern.h"
-+
-+
-+// Function:  dlist_add_as_first()
-+//
-+// Adds the specified node to the start of the list
-+//
-+// Returns:  pointer to the start of the list
-+//
-+DL_NODE *dlist_add_as_first(DL_NODE *list, void *data)
-+{
-+    DL_NODE *node = NULL;
-+
-+    if (!data)
-+        return list;
-+
-+    node = (DL_NODE *) malloc(sizeof(DL_NODE));
-+    if (!node)
-+        return NULL;
-+
-+    node->data = data;
-+    node->prev = NULL;
-+    node->next = list;
-+    if (list)
-+        list->prev = node;
-+
-+    return node;
-+}
-+
-+// Function:  dlist_add_as_last()
-+//
-+// Adds the specified node to the end of the list
-+//
-+// Returns:  pointer to the start of the list
-+//
-+DL_NODE *dlist_add_as_last(DL_NODE *list, void *data)
-+{
-+    DL_NODE *node = NULL;
-+
-+    if (!data)
-+        return list;
-+
-+    node = (DL_NODE *) malloc(sizeof(DL_NODE));
-+    if (!node)
-+        return NULL;
-+
-+    node->data = data;
-+    node->next = NULL;
-+
-+    if (!list) {
-+        node->prev = NULL;
-+        return node;
-+    } else {
-+        DL_NODE *temp = dlist_get_last(list);
-+        temp->next = node;
-+        node->prev = temp;
-+
-+        return list;
-+    }
-+}
-+
-+// Function:  dlist_find()
-+//
-+DL_NODE *dlist_find(DL_NODE *list, void *data)
-+{
-+    DL_NODE *node = list;
-+
-+    while (node && node->data != data)
-+        node = node->next;
-+
-+    return node;
-+}
-+
-+// Function:  dlist_get_first()
-+//
-+// Returns the last node in the list or NULL if list is empty
-+//
-+DL_NODE *dlist_get_first(DL_NODE *list)
-+{
-+    DL_NODE *temp = list;
-+
-+    if (!list)
-+        return NULL;
-+
-+    while (temp->prev != NULL)
-+        temp = temp->prev;
-+
-+    return temp;
-+}
-+
-+// Function:  dlist_get_last()
-+//
-+// Returns the last node in the list or NULL if list is empty
-+//
-+DL_NODE *dlist_get_last(DL_NODE *list)
-+{
-+    DL_NODE *temp = list;
-+
-+    if (!list)
-+        return NULL;
-+
-+    while (temp->next != NULL)
-+        temp = temp->next;
-+
-+    return temp;
-+}
-+
-+//
-+//
-+CK_ULONG dlist_length(DL_NODE *list)
-+{
-+    DL_NODE *temp = list;
-+    CK_ULONG len = 0;
-+
-+    while (temp) {
-+        len++;
-+        temp = temp->next;
-+    }
-+
-+    return len;
-+}
-+
-+//
-+//
-+DL_NODE *dlist_next(DL_NODE *node)
-+{
-+    if (!node)
-+        return NULL;
-+
-+    return node->next;
-+}
-+
-+//
-+//
-+DL_NODE *dlist_prev(DL_NODE *node)
-+{
-+    if (!node)
-+        return NULL;
-+
-+    return node->prev;
-+}
-+
-+//
-+//
-+void dlist_purge(DL_NODE *list)
-+{
-+    DL_NODE *node;
-+
-+    if (!list)
-+        return;
-+
-+    do {
-+        node = list->next;
-+        free(list);
-+        list = node;
-+    } while (list);
-+}
-+
-+// Function:  dlist_remove_node()
-+//
-+// Attempts to remove the specified node from the list.  The caller is
-+// responsible for freeing the data associated with the node prior to
-+// calling this routine
-+//
-+DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node)
-+{
-+    DL_NODE *temp = list;
-+
-+    if (!list || !node)
-+        return NULL;
-+
-+    // special case:  removing head of the list
-+    //
-+    if (list == node) {
-+        temp = list->next;
-+        if (temp)
-+            temp->prev = NULL;
-+
-+        free(list);
-+        return temp;
-+    }
-+    // we have no guarantee that the node is in the list
-+    // so search through the list to find it
-+    //
-+    while ((temp != NULL) && (temp->next != node))
-+        temp = temp->next;
-+
-+    if (temp != NULL) {
-+        DL_NODE *next = node->next;
-+
-+        temp->next = next;
-+        if (next)
-+            next->prev = temp;
-+
-+        free(node);
-+    }
-+
-+    return list;
-+}
-diff --git a/usr/lib/common/dlist.h b/usr/lib/common/dlist.h
-new file mode 100644
-index 00000000..eda4af9c
---- /dev/null
-+++ b/usr/lib/common/dlist.h
-@@ -0,0 +1,32 @@
-+/*
-+ * COPYRIGHT (c) International Business Machines Corp. 2021
-+ *
-+ * This program is provided under the terms of the Common Public License,
-+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-+ * found in the file LICENSE file or at
-+ * https://opensource.org/licenses/cpl1.0.php
-+ */
-+
-+
-+
-+#ifndef _DLIST_H_
-+#define _DLIST_H_
-+
-+#include "pkcs11types.h"
-+#include "defs.h"
-+
-+// linked-list routines
-+//
-+DL_NODE *dlist_add_as_first(DL_NODE *list, void *data);
-+DL_NODE *dlist_add_as_last(DL_NODE *list, void *data);
-+DL_NODE *dlist_find(DL_NODE *list, void *data);
-+DL_NODE *dlist_get_first(DL_NODE *list);
-+DL_NODE *dlist_get_last(DL_NODE *list);
-+CK_ULONG dlist_length(DL_NODE *list);
-+DL_NODE *dlist_next(DL_NODE *list);
-+DL_NODE *dlist_prev(DL_NODE *list);
-+void dlist_purge(DL_NODE *list);
-+DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node);
-+
-+#endif
-diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
-index 63aff79f..5e251d95 100644
---- a/usr/lib/common/h_extern.h
-+++ b/usr/lib/common/h_extern.h
-@@ -24,6 +24,7 @@
- #define _H_EXTERN_H
- 
- #include <stdio.h>
-+#include "dlist.h"
- 
- // global variables
- //
-@@ -1759,19 +1760,6 @@ int ec_point_from_public_data(const CK_BYTE *data, CK_ULONG data_len,
-                               CK_BBOOL *allocated, CK_BYTE **ec_point,
-                               CK_ULONG *ec_point_len);
- 
--// linked-list routines
--//
--DL_NODE *dlist_add_as_first(DL_NODE *list, void *data);
--DL_NODE *dlist_add_as_last(DL_NODE *list, void *data);
--DL_NODE *dlist_find(DL_NODE *list, void *data);
--DL_NODE *dlist_get_first(DL_NODE *list);
--DL_NODE *dlist_get_last(DL_NODE *list);
--CK_ULONG dlist_length(DL_NODE *list);
--DL_NODE *dlist_next(DL_NODE *list);
--DL_NODE *dlist_prev(DL_NODE *list);
--void dlist_purge(DL_NODE *list);
--DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node);
--
- CK_RV attach_shm(STDLL_TokData_t *tokdata, CK_SLOT_ID slot_id);
- CK_RV detach_shm(STDLL_TokData_t *tokdata, CK_BBOOL ignore_ref_count);
- 
-diff --git a/usr/lib/common/utility.c b/usr/lib/common/utility.c
-index 38d8d959..b2c6ee50 100644
---- a/usr/lib/common/utility.c
-+++ b/usr/lib/common/utility.c
-@@ -40,203 +40,6 @@
- #include <sys/file.h>
- #include <syslog.h>
- 
--// Function:  dlist_add_as_first()
--//
--// Adds the specified node to the start of the list
--//
--// Returns:  pointer to the start of the list
--//
--DL_NODE *dlist_add_as_first(DL_NODE *list, void *data)
--{
--    DL_NODE *node = NULL;
--
--    if (!data)
--        return list;
--
--    node = (DL_NODE *) malloc(sizeof(DL_NODE));
--    if (!node)
--        return NULL;
--
--    node->data = data;
--    node->prev = NULL;
--    node->next = list;
--    if (list)
--        list->prev = node;
--
--    return node;
--}
--
--// Function:  dlist_add_as_last()
--//
--// Adds the specified node to the end of the list
--//
--// Returns:  pointer to the start of the list
--//
--DL_NODE *dlist_add_as_last(DL_NODE *list, void *data)
--{
--    DL_NODE *node = NULL;
--
--    if (!data)
--        return list;
--
--    node = (DL_NODE *) malloc(sizeof(DL_NODE));
--    if (!node)
--        return NULL;
--
--    node->data = data;
--    node->next = NULL;
--
--    if (!list) {
--        node->prev = NULL;
--        return node;
--    } else {
--        DL_NODE *temp = dlist_get_last(list);
--        temp->next = node;
--        node->prev = temp;
--
--        return list;
--    }
--}
--
--// Function:  dlist_find()
--//
--DL_NODE *dlist_find(DL_NODE *list, void *data)
--{
--    DL_NODE *node = list;
--
--    while (node && node->data != data)
--        node = node->next;
--
--    return node;
--}
--
--// Function:  dlist_get_first()
--//
--// Returns the last node in the list or NULL if list is empty
--//
--DL_NODE *dlist_get_first(DL_NODE *list)
--{
--    DL_NODE *temp = list;
--
--    if (!list)
--        return NULL;
--
--    while (temp->prev != NULL)
--        temp = temp->prev;
--
--    return temp;
--}
--
--// Function:  dlist_get_last()
--//
--// Returns the last node in the list or NULL if list is empty
--//
--DL_NODE *dlist_get_last(DL_NODE *list)
--{
--    DL_NODE *temp = list;
--
--    if (!list)
--        return NULL;
--
--    while (temp->next != NULL)
--        temp = temp->next;
--
--    return temp;
--}
--
--//
--//
--CK_ULONG dlist_length(DL_NODE *list)
--{
--    DL_NODE *temp = list;
--    CK_ULONG len = 0;
--
--    while (temp) {
--        len++;
--        temp = temp->next;
--    }
--
--    return len;
--}
--
--//
--//
--DL_NODE *dlist_next(DL_NODE *node)
--{
--    if (!node)
--        return NULL;
--
--    return node->next;
--}
--
--//
--//
--DL_NODE *dlist_prev(DL_NODE *node)
--{
--    if (!node)
--        return NULL;
--
--    return node->prev;
--}
--
--//
--//
--void dlist_purge(DL_NODE *list)
--{
--    DL_NODE *node;
--
--    if (!list)
--        return;
--
--    do {
--        node = list->next;
--        free(list);
--        list = node;
--    } while (list);
--}
--
--// Function:  dlist_remove_node()
--//
--// Attempts to remove the specified node from the list.  The caller is
--// responsible for freeing the data associated with the node prior to
--// calling this routine
--//
--DL_NODE *dlist_remove_node(DL_NODE *list, DL_NODE *node)
--{
--    DL_NODE *temp = list;
--
--    if (!list || !node)
--        return NULL;
--
--    // special case:  removing head of the list
--    //
--    if (list == node) {
--        temp = list->next;
--        if (temp)
--            temp->prev = NULL;
--
--        free(list);
--        return temp;
--    }
--    // we have no guarantee that the node is in the list
--    // so search through the list to find it
--    //
--    while ((temp != NULL) && (temp->next != node))
--        temp = temp->next;
--
--    if (temp != NULL) {
--        DL_NODE *next = node->next;
--
--        temp->next = next;
--        if (next)
--            next->prev = temp;
--
--        free(node);
--    }
--
--    return list;
--}
--
- CK_RV CreateXProcLock(char *tokname, STDLL_TokData_t *tokdata)
- {
-     char lockfile[PATH_MAX];
-diff --git a/usr/lib/ep11_stdll/ep11_stdll.mk b/usr/lib/ep11_stdll/ep11_stdll.mk
-index bc617124..b5574d9e 100644
---- a/usr/lib/ep11_stdll/ep11_stdll.mk
-+++ b/usr/lib/ep11_stdll/ep11_stdll.mk
-@@ -36,7 +36,7 @@ opencryptoki_stdll_libpkcs11_ep11_la_SOURCES =				\
- 	usr/lib/common/utility.c usr/lib/common/trace.c			\
- 	usr/lib/common/mech_list.c usr/lib/common/shared_memory.c	\
- 	usr/lib/common/attributes.c usr/lib/common/sw_crypt.c		\
--	usr/lib/common/profile_obj.c					\
-+	usr/lib/common/profile_obj.c usr/lib/common/dlist.c		\
- 	usr/lib/common/pkey_utils.c					\
- 	usr/lib/ep11_stdll/new_host.c usr/lib/ep11_stdll/ep11_specific.c
- 
-diff --git a/usr/lib/ica_s390_stdll/ica_s390_stdll.mk b/usr/lib/ica_s390_stdll/ica_s390_stdll.mk
-index d8448486..8f467e11 100644
---- a/usr/lib/ica_s390_stdll/ica_s390_stdll.mk
-+++ b/usr/lib/ica_s390_stdll/ica_s390_stdll.mk
-@@ -34,7 +34,7 @@ opencryptoki_stdll_libpkcs11_ica_la_SOURCES =				\
- 	usr/lib/common/verify_mgr.c usr/lib/common/trace.c		\
- 	usr/lib/common/mech_list.c usr/lib/common/shared_memory.c	\
- 	usr/lib/common/profile_obj.c usr/lib/common/attributes.c	\
--	usr/lib/ica_s390_stdll/ica_specific.c
-+	usr/lib/ica_s390_stdll/ica_specific.c usr/lib/common/dlist.c
- 
- if ENABLE_LOCKS
- opencryptoki_stdll_libpkcs11_ica_la_SOURCES +=				\
-diff --git a/usr/lib/icsf_stdll/icsf_stdll.mk b/usr/lib/icsf_stdll/icsf_stdll.mk
-index 788478c2..21c64f9a 100644
---- a/usr/lib/icsf_stdll/icsf_stdll.mk
-+++ b/usr/lib/icsf_stdll/icsf_stdll.mk
-@@ -43,7 +43,7 @@ opencryptoki_stdll_libpkcs11_icsf_la_SOURCES =				\
- 	usr/lib/common/mech_ssl3.c usr/lib/common/verify_mgr.c		\
- 	usr/lib/common/mech_list.c usr/lib/common/shared_memory.c	\
- 	usr/lib/common/attributes.c usr/lib/icsf_stdll/new_host.c	\
--	usr/lib/common/profile_obj.c					\
-+	usr/lib/common/profile_obj.c usr/lib/common/dlist.c		\
- 	usr/lib/icsf_stdll/pbkdf.c usr/lib/icsf_stdll/icsf_specific.c	\
- 	usr/lib/icsf_stdll/icsf_config_parse.y				\
- 	usr/lib/icsf_stdll/icsf_config_lexer.l				\
-diff --git a/usr/lib/soft_stdll/soft_stdll.mk b/usr/lib/soft_stdll/soft_stdll.mk
-index cea802b5..ac401539 100644
---- a/usr/lib/soft_stdll/soft_stdll.mk
-+++ b/usr/lib/soft_stdll/soft_stdll.mk
-@@ -32,7 +32,8 @@ opencryptoki_stdll_libpkcs11_sw_la_SOURCES =				\
- 	usr/lib/common/utility.c usr/lib/common/verify_mgr.c		\
- 	usr/lib/common/trace.c usr/lib/common/mech_list.c		\
- 	usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c	\
--	usr/lib/soft_stdll/soft_specific.c usr/lib/common/attributes.c
-+	usr/lib/soft_stdll/soft_specific.c usr/lib/common/attributes.c	\
-+	usr/lib/common/dlist.c
- 
- if ENABLE_LOCKS
- opencryptoki_stdll_libpkcs11_sw_la_SOURCES +=				\
-diff --git a/usr/lib/tpm_stdll/tpm_stdll.mk b/usr/lib/tpm_stdll/tpm_stdll.mk
-index f199a103..0e0eb024 100644
---- a/usr/lib/tpm_stdll/tpm_stdll.mk
-+++ b/usr/lib/tpm_stdll/tpm_stdll.mk
-@@ -34,7 +34,8 @@ opencryptoki_stdll_libpkcs11_tpm_la_SOURCES =				\
- 	usr/lib/common/verify_mgr.c usr/lib/common/mech_list.c		\
- 	usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c	\
- 	usr/lib/tpm_stdll/tpm_specific.c usr/lib/common/attributes.c	\
--	usr/lib/tpm_stdll/tpm_openssl.c usr/lib/tpm_stdll/tpm_util.c
-+	usr/lib/tpm_stdll/tpm_openssl.c usr/lib/tpm_stdll/tpm_util.c	\
-+	usr/lib/common/dlist.c
- 
- if ENABLE_LOCKS
- opencryptoki_stdll_libpkcs11_tpm_la_SOURCES +=				\
-diff --git a/usr/sbin/pkcscca/pkcscca.mk b/usr/sbin/pkcscca/pkcscca.mk
-index a223265f..cc40f819 100644
---- a/usr/sbin/pkcscca/pkcscca.mk
-+++ b/usr/sbin/pkcscca/pkcscca.mk
-@@ -36,7 +36,7 @@ usr_sbin_pkcscca_pkcscca_SOURCES =					\
- 	usr/lib/common/p11util.c usr/lib/common/sw_crypt.c		\
- 	usr/lib/common/shared_memory.c usr/lib/common/profile_obj.c	\
- 	usr/lib/common/attributes.c usr/lib/common/mech_rng.c		\
--	usr/lib/common/pkcs_utils.c 					\
-+	usr/lib/common/pkcs_utils.c  usr/lib/common/dlist.c		\
- 	usr/sbin/pkcscca/pkcscca.c
- 	
- 	
-diff --git a/usr/sbin/pkcsslotd/pkcsslotd.mk b/usr/sbin/pkcsslotd/pkcsslotd.mk
-index 4f0e3c56..2d36b4a9 100644
---- a/usr/sbin/pkcsslotd/pkcsslotd.mk
-+++ b/usr/sbin/pkcsslotd/pkcsslotd.mk
-@@ -21,5 +21,6 @@ usr_sbin_pkcsslotd_pkcsslotd_SOURCES =							\
- 	usr/sbin/pkcsslotd/socket_server.c
- 
- nodist_usr_sbin_pkcsslotd_pkcsslotd_SOURCES = \
--	usr/lib/common/parser.h usr/lib/common/parser.c	usr/lib/common/lexer.c
-+	usr/lib/common/parser.h usr/lib/common/parser.c	usr/lib/common/lexer.c		\
-+	usr/lib/common/dlist.c
- usr/sbin/pkcsslotd/slotmgr.$(OBJEXT): usr/lib/common/parser.h
diff --git a/SOURCES/opencryptoki-3.16.0-e88a9de3128df1c4b89bd4c7312c15bb3eb34593.patch b/SOURCES/opencryptoki-3.16.0-e88a9de3128df1c4b89bd4c7312c15bb3eb34593.patch
deleted file mode 100644
index a3bf6ea..0000000
--- a/SOURCES/opencryptoki-3.16.0-e88a9de3128df1c4b89bd4c7312c15bb3eb34593.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-commit e88a9de3128df1c4b89bd4c7312c15bb3eb34593
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Thu Jul 8 15:18:30 2021 +0200
-
-    pkcstok_migrate: Don't remove 'tokversion = x.y' during migration
-    
-    When migrating a slot the opencryptoki.conf file is modified. If it
-    contains slots that already contain the 'tokversion = x.y' keyword,
-    this is accidentally removed when migrating another slot.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-index 3df1596e..05081aff 100644
---- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-@@ -2119,7 +2119,7 @@ static int parseupdate_key_vers(void *private, int tok, unsigned int vers)
- {
- 	struct parseupdate *u = (struct parseupdate *)private;
- 
--    if (tok != KW_TOKVERSION)
-+    if (tok == KW_TOKVERSION && !u->activeslot)
-         fprintf(u->f, "  %s = %d.%d", keyword_token_to_str(tok),
-                 vers >> 16, vers & 0xffu);
-     return 0;
diff --git a/SOURCES/opencryptoki-3.16.0-e9548127edae313da7840bcb87fd0afd04549c2e.patch b/SOURCES/opencryptoki-3.16.0-e9548127edae313da7840bcb87fd0afd04549c2e.patch
deleted file mode 100644
index 8e81324..0000000
--- a/SOURCES/opencryptoki-3.16.0-e9548127edae313da7840bcb87fd0afd04549c2e.patch
+++ /dev/null
@@ -1,310 +0,0 @@
-commit e9548127edae313da7840bcb87fd0afd04549c2e
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Feb 8 15:26:23 2021 +0100
-
-    pkcsslotd: Refactoring in preparation for event support
-    
-    No functional change so far, just making things a bit bore clearer.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/include/slotmgr.h b/usr/include/slotmgr.h
-index 3950a9a3..4d038435 100644
---- a/usr/include/slotmgr.h
-+++ b/usr/include/slotmgr.h
-@@ -30,7 +30,7 @@
- #define TOK_PATH  SBIN_PATH "/pkcsslotd"
- #define OCK_API_LOCK_FILE LOCKDIR_PATH "/LCK..APIlock"
- 
--#define SOCKET_FILE_PATH "/var/run/pkcsslotd.socket"
-+#define PROC_SOCKET_FILE_PATH "/var/run/pkcsslotd.socket"
- 
- #define PID_FILE_PATH "/var/run/pkcsslotd.pid"
- #define OCK_CONFIG OCK_CONFDIR "/opencryptoki.conf"
-diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c
-index b74b763f..2873a20a 100644
---- a/usr/lib/api/api_interface.c
-+++ b/usr/lib/api/api_interface.c
-@@ -2831,7 +2831,7 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     TRACE_DEBUG("Shared memory %p \n", Anchor->SharedMemP);
- 
-     /* Connect to slot daemon and retrieve slot infos */
--    Anchor->socketfd = connect_socket(SOCKET_FILE_PATH);
-+    Anchor->socketfd = connect_socket(PROC_SOCKET_FILE_PATH);
-     if (Anchor->socketfd < 0) {
-         OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to create a "
-                    "socket. Verify that the slot management daemon is "
-diff --git a/usr/sbin/pkcsslotd/pkcsslotd.h b/usr/sbin/pkcsslotd/pkcsslotd.h
-index 813db9f4..69eb59f3 100644
---- a/usr/sbin/pkcsslotd/pkcsslotd.h
-+++ b/usr/sbin/pkcsslotd/pkcsslotd.h
-@@ -61,7 +61,6 @@ extern key_t tok;
- extern Slot_Info_t_64 sinfo[NUMBER_SLOTS_MANAGED];
- extern unsigned int NumberSlotsInDB;
- 
--extern int socketfd;
- extern Slot_Mgr_Socket_t socketData;
- 
- 
-@@ -89,9 +88,9 @@ int XProcLock(void);
- int XProcUnLock(void);
- int CreateXProcLock(void);
- 
--int CreateListenerSocket(void);
--int InitSocketData(Slot_Mgr_Socket_t *sp);
--int SocketConnectionHandler(int socketfd, int timeout_secs);
--void DetachSocketListener(int socketfd);
-+int init_socket_server();
-+int term_socket_server();
-+int init_socket_data(Slot_Mgr_Socket_t *sp);
-+int socket_connection_handler(int timeout_secs);
- 
- #endif                          /* _SLOTMGR_H */
-diff --git a/usr/sbin/pkcsslotd/signal.c b/usr/sbin/pkcsslotd/signal.c
-index cf7b9087..49482a2f 100644
---- a/usr/sbin/pkcsslotd/signal.c
-+++ b/usr/sbin/pkcsslotd/signal.c
-@@ -101,7 +101,7 @@ void slotdGenericSignalHandler(int Signal)
- 
-     InfoLog("Exiting on %s (%d; %#x)", SignalConst(Signal), Signal, Signal);
- 
--    DetachSocketListener(socketfd);
-+    term_socket_server();
-     DestroyMutexes();
-     DetachFromSharedMemory();
-     DestroySharedMemory();
-diff --git a/usr/sbin/pkcsslotd/slotmgr.c b/usr/sbin/pkcsslotd/slotmgr.c
-index ea5c86f5..94288f13 100644
---- a/usr/sbin/pkcsslotd/slotmgr.c
-+++ b/usr/sbin/pkcsslotd/slotmgr.c
-@@ -37,7 +37,6 @@ unsigned int NumberSlotsInDB = 0;
- 
- Slot_Info_t_64 *psinfo;
- 
--int socketfd;
- Slot_Mgr_Socket_t socketData;
- 
- struct dircheckinfo_s {
-@@ -569,15 +568,15 @@ int main(int argc, char *argv[], char *envp[])
-     if (!XProcUnLock())
-         return 4;
- 
--    if ((socketfd = CreateListenerSocket()) < 0) {
-+    if (!init_socket_server()) {
-         DestroyMutexes();
-         DetachFromSharedMemory();
-         DestroySharedMemory();
-         return 5;
-     }
- 
--    if (!InitSocketData(&socketData)) {
--        DetachSocketListener(socketfd);
-+    if (!init_socket_data(&socketData)) {
-+        term_socket_server();
-         DestroyMutexes();
-         DetachFromSharedMemory();
-         DestroySharedMemory();
-@@ -598,7 +597,7 @@ int main(int argc, char *argv[], char *envp[])
-     if (Daemon) {
-         pid_t pid;
-         if ((pid = fork()) < 0) {
--            DetachSocketListener(socketfd);
-+            term_socket_server();
-             DestroyMutexes();
-             DetachFromSharedMemory();
-             DestroySharedMemory();
-@@ -643,7 +642,7 @@ int main(int argc, char *argv[], char *envp[])
-      * the daemonization process redefines our handler for (at least) SIGTERM
-      */
-     if (!SetupSignalHandlers()) {
--        DetachSocketListener(socketfd);
-+        term_socket_server();
-         DestroyMutexes();
-         DetachFromSharedMemory();
-         DestroySharedMemory();
-@@ -664,7 +663,7 @@ int main(int argc, char *argv[], char *envp[])
-     printf("Start garbage \n");
-     /* start garbage collection thread */
-     if (!StartGCThread(shmp)) {
--        DetachSocketListener(socketfd);
-+        term_socket_server();
-         DestroyMutexes();
-         DetachFromSharedMemory();
-         DestroySharedMemory();
-@@ -684,7 +683,7 @@ int main(int argc, char *argv[], char *envp[])
- #if !(THREADED) && !(NOGARBAGE)
-         CheckForGarbage(shmp);
- #endif
--        SocketConnectionHandler(socketfd, 10);
-+        socket_connection_handler(10);
-     }
- 
-     /*************************************************************
-diff --git a/usr/sbin/pkcsslotd/socket_server.c b/usr/sbin/pkcsslotd/socket_server.c
-index ae0eff92..1fae0b95 100644
---- a/usr/sbin/pkcsslotd/socket_server.c
-+++ b/usr/sbin/pkcsslotd/socket_server.c
-@@ -25,10 +25,14 @@
- #include "pkcsslotd.h"
- #include "apictl.h"
- 
-+int proc_listener_socket = -1;
-+
-+static void close_listener_socket(int socketfd, const char *file_path);
-+
- // Creates the daemon's listener socket, to which clients will connect and
- // retrieve slot information through.  Returns the file descriptor of the
- // created socket.
--int CreateListenerSocket(void)
-+static int create_listener_socket(const char *file_path)
- {
-     struct sockaddr_un address;
-     struct group *grp;
-@@ -39,53 +43,60 @@ int CreateListenerSocket(void)
-         ErrLog("Failed to create listener socket, errno 0x%X.", errno);
-         return -1;
-     }
--    if (unlink(SOCKET_FILE_PATH) && errno != ENOENT) {
-+    if (unlink(file_path) && errno != ENOENT) {
-         ErrLog("Failed to unlink socket file, errno 0x%X.", errno);
--        close(socketfd);
--        return -1;
-+        goto error;
-     }
- 
-     memset(&address, 0, sizeof(struct sockaddr_un));
-     address.sun_family = AF_UNIX;
--    strcpy(address.sun_path, SOCKET_FILE_PATH);
-+    strcpy(address.sun_path, file_path);
- 
-     if (bind(socketfd,
-              (struct sockaddr *) &address, sizeof(struct sockaddr_un)) != 0) {
-         ErrLog("Failed to bind to socket, errno 0x%X.", errno);
--        close(socketfd);
--        return -1;
-+        goto error;
-     }
-     // make socket file part of the pkcs11 group, and write accessable
-     // for that group
-     grp = getgrnam("pkcs11");
-     if (!grp) {
-         ErrLog("Group PKCS#11 does not exist");
--        DetachSocketListener(socketfd);
--        return -1;
-+        goto error;
-     }
--    if (chown(SOCKET_FILE_PATH, 0, grp->gr_gid)) {
-+    if (chown(file_path, 0, grp->gr_gid)) {
-         ErrLog("Could not change file group on socket, errno 0x%X.", errno);
--        DetachSocketListener(socketfd);
--        return -1;
-+        goto error;
-     }
--    if (chmod(SOCKET_FILE_PATH,
-+    if (chmod(file_path,
-               S_IRUSR | S_IRGRP | S_IWUSR | S_IWGRP | S_IXUSR | S_IXGRP)) {
-         ErrLog("Could not change file permissions on socket, errno 0x%X.",
-                errno);
--        DetachSocketListener(socketfd);
--        return -1;
-+        goto error;
-     }
- 
-     if (listen(socketfd, 20) != 0) {
-         ErrLog("Failed to listen to socket, errno 0x%X.", errno);
--        DetachSocketListener(socketfd);
--        return -1;
-+        goto error;
-     }
- 
-     return socketfd;
-+
-+error:
-+    if (socketfd >= 0)
-+        close_listener_socket(socketfd, file_path);
-+
-+    return -1;
-+}
-+
-+
-+static void close_listener_socket(int socketfd, const char *file_path)
-+{
-+    close(socketfd);
-+    unlink(file_path);
- }
- 
--int InitSocketData(Slot_Mgr_Socket_t *socketData)
-+int init_socket_data(Slot_Mgr_Socket_t *socketData)
- {
-     unsigned int processed = 0;
- 
-@@ -102,19 +113,19 @@ int InitSocketData(Slot_Mgr_Socket_t *socketData)
-     return TRUE;
- }
- 
--int SocketConnectionHandler(int socketfd, int timeout_secs)
-+int socket_connection_handler(int timeout_secs)
- {
-     int returnVal;
-     fd_set set;
-     struct timeval timeout;
- 
-     FD_ZERO(&set);
--    FD_SET(socketfd, &set);
-+    FD_SET(proc_listener_socket, &set);
- 
-     timeout.tv_sec = timeout_secs;
-     timeout.tv_usec = 0;
- 
--    returnVal = select(socketfd + 1, &set, NULL, NULL, &timeout);
-+    returnVal = select(proc_listener_socket + 1, &set, NULL, NULL, &timeout);
-     if (returnVal == -1) {
-         ErrLog("select failed on socket connection, errno 0x%X.", errno);
-         return FALSE;
-@@ -125,7 +136,7 @@ int SocketConnectionHandler(int socketfd, int timeout_secs)
-         struct sockaddr_un address;
-         socklen_t address_length = sizeof(address);
- 
--        int connectionfd = accept(socketfd,
-+        int connectionfd = accept(proc_listener_socket,
-                                   (struct sockaddr *) &address,
-                                   &address_length);
-         if (connectionfd < 0) {
-@@ -138,6 +149,10 @@ int SocketConnectionHandler(int socketfd, int timeout_secs)
-             }
-             return FALSE;
-         }
-+
-+        DbgLog(DL0, "Accepted connection from process: socket: %d", 
-+               connectionfd);
-+
-         if (write(connectionfd, &socketData, sizeof(socketData)) !=
-             sizeof(socketData)) {
-             ErrLog("Failed to write socket data, errno 0x%X.", errno);
-@@ -149,8 +164,23 @@ int SocketConnectionHandler(int socketfd, int timeout_secs)
-     }
- }
- 
--void DetachSocketListener(int socketfd)
-+int init_socket_server()
- {
--    close(socketfd);
--    unlink(SOCKET_FILE_PATH);
-+    proc_listener_socket = create_listener_socket(PROC_SOCKET_FILE_PATH);
-+    if (proc_listener_socket < 0)
-+        return FALSE;
-+
-+    DbgLog(DL0, "Socket server started");
-+
-+    return TRUE;
-+}
-+
-+int term_socket_server()
-+{
-+    if (proc_listener_socket >= 0)
-+        close_listener_socket(proc_listener_socket, PROC_SOCKET_FILE_PATH);
-+
-+    DbgLog(DL0, "Socket server stopped");
-+
-+    return TRUE;
- }
diff --git a/SOURCES/opencryptoki-3.16.0-fa94a16116d8382a987ddf9e8cdd88027dd1f647.patch b/SOURCES/opencryptoki-3.16.0-fa94a16116d8382a987ddf9e8cdd88027dd1f647.patch
deleted file mode 100644
index 30a506a..0000000
--- a/SOURCES/opencryptoki-3.16.0-fa94a16116d8382a987ddf9e8cdd88027dd1f647.patch
+++ /dev/null
@@ -1,287 +0,0 @@
-commit fa94a16116d8382a987ddf9e8cdd88027dd1f647
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Feb 16 17:13:34 2021 +0100
-
-    Event support: Add event client
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/common.mk b/usr/lib/common/common.mk
-index 2178ad45..882c84f4 100644
---- a/usr/lib/common/common.mk
-+++ b/usr/lib/common/common.mk
-@@ -4,7 +4,7 @@ noinst_HEADERS +=							\
- 	usr/lib/common/shared_memory.h usr/lib/common/tok_spec_struct.h	\
- 	usr/lib/common/trace.h usr/lib/common/h_extern.h		\
- 	usr/lib/common/sw_crypt.h usr/lib/common/defs.h			\
--	usr/lib/common/p11util.h					\
-+	usr/lib/common/p11util.h usr/lib/common/event_client.h		\
- 	usr/lib/common/list.h usr/lib/common/tok_specific.h
- 
- usr/lib/common/lexer.c: usr/lib/common/parser.h
-diff --git a/usr/lib/common/event_client.c b/usr/lib/common/event_client.c
-new file mode 100644
-index 00000000..86117b84
---- /dev/null
-+++ b/usr/lib/common/event_client.c
-@@ -0,0 +1,215 @@
-+/*
-+ * COPYRIGHT (c) International Business Machines Corp. 2021
-+ *
-+ * This program is provided under the terms of the Common Public License,
-+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-+ * found in the file LICENSE file or at
-+ * https://opensource.org/licenses/cpl1.0.php
-+ */
-+
-+#include <stdlib.h>
-+#include <string.h>
-+#include <errno.h>
-+#include <sys/un.h>
-+#include <sys/socket.h>
-+#include <sys/stat.h>
-+#include <stdio.h>
-+#include <unistd.h>
-+#include <grp.h>
-+
-+#include "slotmgr.h"
-+#include "event_client.h"
-+
-+static int connect_socket(const char *file_path)
-+{
-+    int socketfd;
-+    struct sockaddr_un daemon_address;
-+    struct stat file_info;
-+    struct group *grp;
-+    int rc;
-+
-+    if (stat(file_path, &file_info))
-+        return -errno;
-+
-+    grp = getgrnam("pkcs11");
-+    if (!grp)
-+        return -errno;
-+
-+    if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid)
-+        return -EPERM;
-+
-+    if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
-+        return -errno;
-+
-+    memset(&daemon_address, 0, sizeof(struct sockaddr_un));
-+    daemon_address.sun_family = AF_UNIX;
-+    strcpy(daemon_address.sun_path, file_path);
-+
-+    if (connect(socketfd, (struct sockaddr *) &daemon_address,
-+                sizeof(struct sockaddr_un)) != 0) {
-+        rc = -errno;
-+        goto error;
-+    }
-+
-+    return socketfd;
-+
-+error:
-+    close(socketfd);
-+    return rc;
-+}
-+
-+static ssize_t read_all(int socketfd, char *buffer, size_t size)
-+{
-+    size_t bytes_received = 0;
-+    ssize_t n;
-+
-+    while (bytes_received < size) {
-+        n = read(socketfd, buffer + bytes_received, size - bytes_received);
-+        if (n < 0) {
-+            // read error
-+            if (errno == EINTR)
-+                continue;
-+            return -errno;
-+        }
-+        if (n == 0)
-+            break;
-+
-+        bytes_received += n;
-+    }
-+
-+    return bytes_received;
-+}
-+
-+static ssize_t send_all(int socketfd, char *buffer, size_t size)
-+{
-+    size_t bytes_sent = 0;
-+    ssize_t n;
-+
-+    while (bytes_sent < size) {
-+        n = send(socketfd, buffer + bytes_sent, size - bytes_sent, 0);
-+        if (n < 0) {
-+            // send error
-+            if (errno == EINTR)
-+                continue;
-+            return -errno;
-+        }
-+        if (n == 0)
-+            break;
-+
-+        bytes_sent += n;
-+    }
-+
-+    return bytes_sent;
-+}
-+
-+/*
-+ * Initialize an admin connection to the pkcsslotd.
-+ * Returns a file descriptor representing the connection, or a negative errno
-+ * in case of an error.
-+ */
-+int init_event_client()
-+{
-+    int fd;
-+
-+    fd = connect_socket(ADMIN_SOCKET_FILE_PATH);
-+
-+    return fd;
-+}
-+
-+/*
-+ * Send an event though the admin connection to the pkcsslotd, and thus to
-+ * all active token instances.
-+ * If parameter fd is < 0, then a connection to pkcsslotd is established
-+ * inside the function and closed before return. This is for a one shot event.
-+ * Otherwise, pass a file descriptor received from init_event_client(). This
-+ * is to send multiple events.
-+ * Event type is mandatory, flags can be zero.
-+ * The event payload is optional, if payload_len is non-zero, then payload must
-+ * point to a buffer containing the payload to send with the event.
-+ * The event destination can be used to selectively send the event to certain
-+ * token instances only. If destination is NULL, it is sent to all token
-+ * instances.
-+ * If flag EVENT_FLAGS_REPLY_REQ is on in the flags parameter, then it is waited
-+ * until all active token instances have replied. The combined result of the
-+ * replies from the token instances is returned in the reply structure.
-+ * Parameter reply must be non-NULL if flag EVENT_FLAGS_REPLY_REQ is set.
-+ * Returns zero for success, or a negative errno in case of an error. In most
-+ * error cases the connection to the pkcsslotd is out of sequence and can no
-+ * longer be used to send further events.
-+ */
-+int send_event(int fd, unsigned int type, unsigned int flags,
-+               unsigned int payload_len, const char *payload,
-+               const struct event_destination *destination,
-+               struct event_reply *reply)
-+{
-+    event_msg_t event_msg;
-+    event_reply_t event_reply;
-+    int rc, term = 0;
-+
-+    if (payload_len > 0 && payload == NULL)
-+        return -EINVAL;
-+    if ((flags & EVENT_FLAGS_REPLY_REQ) && reply == NULL)
-+        return -EINVAL;
-+    if (payload_len > EVENT_MAX_PAYLOAD_LENGTH)
-+        return -EMSGSIZE;
-+
-+    if (fd < 0) {
-+        fd = init_event_client();
-+        if (fd < 0)
-+            return fd;
-+        term = 1;
-+    }
-+
-+    memset(&event_msg, 0, sizeof(event_msg));
-+    event_msg.version = EVENT_VERSION_1;
-+    event_msg.type = type;
-+    event_msg.flags = flags;
-+    if (destination != NULL) {
-+        event_msg.token_type = destination->token_type;
-+        memcpy(event_msg.token_label, destination->token_label,
-+               sizeof(event_msg.token_label));
-+        event_msg.process_id = destination->process_id;
-+    } else {
-+        memset(event_msg.token_label, ' ', sizeof(event_msg.token_label));
-+    }
-+    event_msg.payload_len = payload_len;
-+
-+    rc = send_all(fd, (char *)&event_msg, sizeof(event_msg));
-+    if (rc < 0)
-+        goto out;
-+
-+    if (payload_len > 0) {
-+        rc = send_all(fd, (char *)payload, payload_len);
-+        if (rc < 0)
-+            goto out;
-+    }
-+
-+    if (flags & EVENT_FLAGS_REPLY_REQ) {
-+        rc = read_all(fd, (char *)&event_reply, sizeof(event_reply));
-+        if (rc < 0)
-+            goto out;
-+
-+        reply->positive_replies = event_reply.positive_replies;
-+        reply->negative_replies = event_reply.negative_replies;
-+        reply->nothandled_replies = event_reply.nothandled_replies;
-+    }
-+
-+    rc = 0;
-+
-+out:
-+    if (term)
-+        term_event_client(fd);
-+
-+    return rc;
-+}
-+
-+/*
-+ * Terminate the admin connection to the pkcsslotd.
-+ */
-+void term_event_client(int fd)
-+{
-+    if (fd >= 0)
-+        close(fd);
-+}
-+
-diff --git a/usr/lib/common/event_client.h b/usr/lib/common/event_client.h
-new file mode 100644
-index 00000000..2e4917b0
---- /dev/null
-+++ b/usr/lib/common/event_client.h
-@@ -0,0 +1,39 @@
-+/*
-+ * COPYRIGHT (c) International Business Machines Corp. 2021
-+ *
-+ * This program is provided under the terms of the Common Public License,
-+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
-+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
-+ * found in the file LICENSE file or at
-+ * https://opensource.org/licenses/cpl1.0.php
-+ */
-+
-+
-+#ifndef _EVENT_CLIENT_H_
-+#define _EVENT_CLIENT_H_
-+
-+#include "events.h"
-+
-+struct event_destination {
-+    unsigned int token_type;    /* Destination token type: EVENT_TOK_TYPE_xxx */
-+    char token_label[member_size(event_msg_t, token_label)];
-+                                /* Label of destination token (or blanks) */
-+    pid_t process_id;           /* Process ID of destination process (or 0) */
-+};
-+
-+struct event_reply {
-+    unsigned long positive_replies;
-+    unsigned long negative_replies;
-+    unsigned long nothandled_replies;
-+};
-+
-+int init_event_client();
-+
-+int send_event(int fd, unsigned int type, unsigned int flags,
-+               unsigned int payload_len, const char *payload,
-+               const struct event_destination *destination,
-+               struct event_reply *reply);
-+
-+void term_event_client(int fd);
-+
-+#endif
diff --git a/SOURCES/opencryptoki-3.16.0-pkcstok_migrate-detection_if_pkcsslotd_is_still_running.patch b/SOURCES/opencryptoki-3.16.0-pkcstok_migrate-detection_if_pkcsslotd_is_still_running.patch
deleted file mode 100644
index 128ea06..0000000
--- a/SOURCES/opencryptoki-3.16.0-pkcstok_migrate-detection_if_pkcsslotd_is_still_running.patch
+++ /dev/null
@@ -1,106 +0,0 @@
-commit 5951869263b556280da53498270cf4826f779c5b
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Jul 13 09:05:22 2021 +0200
-
-    pkcstok_migrate: Fix detection if pkcsslotd is still running
-    
-    Change the code to use the pid file that pkcsslotd creates, and check
-    if the process with the pid contained in the pid file still exists and
-    runs pkcsslotd.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-index 05081aff..a29dc8f7 100644
---- a/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-+++ b/usr/sbin/pkcstok_migrate/pkcstok_migrate.c
-@@ -2474,54 +2474,53 @@ static CK_RV backup_repository(const char *data_store)
-  */
- static CK_BBOOL pkcsslotd_running(void)
- {
--    DIR *dir;
-     FILE *fp;
--    struct dirent* ent;
-     char* endptr;
--    char buf[PATH_MAX];
-+    long lpid;
-     char fname[PATH_MAX];
-+    char buf[PATH_MAX];
-+    char* first;
- 
-     TRACE_INFO("Checking if pkcsslotd is running ...\n");
--    if (!(dir = opendir("/proc"))) {
--        TRACE_WARN("Cannot open /proc, i.e. cannot check if pkcsslotd is running.\n");
--        return CK_TRUE;
-+
-+    fp = fopen(PID_FILE_PATH, "r");
-+    if (fp == NULL) {
-+        TRACE_INFO("Pid file '%s' not existent, pkcsslotd is not running\n",
-+                   PID_FILE_PATH);
-+        return CK_FALSE;
-     }
- 
--    while ((ent = readdir(dir)) != NULL) {
--        /* if endptr is not a null character, the directory is not
--         * entirely numeric, so ignore it */
--        long lpid = strtol(ent->d_name, &endptr, 10);
--        if (*endptr != '\0') {
--            continue;
--        }
-+    if (fgets(buf, sizeof(buf), fp) == NULL) {
-+        TRACE_WARN("Cannot read pid file '%s': %s\n", PID_FILE_PATH,
-+                   strerror(errno));
-+        fclose(fp);
-+        return CK_FALSE;
-+    }
-+    fclose(fp);
- 
--        /* try to open the cmdline file */
--        snprintf(fname, sizeof(fname), "/proc/%ld/cmdline", lpid);
--        fp = fopen(fname, "r");
--        if (!fp) {
--            warnx("fopen(%s) failed, errno=%s", fname, strerror(errno));
--            return CK_TRUE;
--        }
-+    lpid = strtol(buf, &endptr, 10);
-+    if (*endptr != '\0' && *endptr != '\n') {
-+        TRACE_WARN("Failed to parse pid file '%s': %s\n", PID_FILE_PATH,
-+                           buf);
-+        return CK_FALSE;
-+    }
- 
--        /* check the first token in the file: the program pathname */
--        if (fgets(buf, sizeof(buf), fp) != NULL) {
--            char* first = strtok(buf, " ");
--            if (!first) {
--                TRACE_WARN("Cannot read program name from %s, i.e. cannot check if pkcsslotd is running.\n",
--                           fname);
--                return CK_TRUE;
--            }
--            if (strstr(first, "pkcsslotd") != NULL) {
--                fclose(fp);
--                closedir(dir);
--                return CK_TRUE;
--            }
--        }
-+    snprintf(fname, sizeof(fname), "/proc/%ld/cmdline", lpid);
-+    fp = fopen(fname, "r");
-+    if (fp == NULL) {
-+        TRACE_INFO("Stale pid file, pkcsslotd is not running\n");
-+        return CK_FALSE;
-+    }
-+
-+    if (fgets(buf, sizeof(buf), fp) == NULL) {
-+        TRACE_INFO("Failed to read '%s'\n", fname);
-         fclose(fp);
-+        return CK_FALSE;
-     }
-+    fclose(fp);
- 
--    closedir(dir);
--    return CK_FALSE;
-+    first = strtok(buf, " ");
-+    return (first != NULL && strstr(first, "pkcsslotd") != NULL);
- }
- 
- /**
diff --git a/SOURCES/opencryptoki-3.17.0-p11sak.patch b/SOURCES/opencryptoki-3.17.0-p11sak.patch
new file mode 100644
index 0000000..62ccf2a
--- /dev/null
+++ b/SOURCES/opencryptoki-3.17.0-p11sak.patch
@@ -0,0 +1,12 @@
+diff -up opencryptoki-3.17.0/Makefile.am.me opencryptoki-3.17.0/Makefile.am
+--- opencryptoki-3.17.0/Makefile.am.me	2021-11-09 09:45:49.032661898 +0100
++++ opencryptoki-3.17.0/Makefile.am	2021-11-09 09:46:41.353400986 +0100
+@@ -76,7 +76,7 @@ if ENABLE_EP11TOK
+ endif
+ if ENABLE_P11SAK
+ 	test -f $(DESTDIR)$(sysconfdir)/opencryptoki || $(MKDIR_P) $(DESTDIR)$(sysconfdir)/opencryptoki || true
+-	test -f $(DESTDIR)$(sysconfdir)/opencryptoki/p11sak_defined_attrs.conf || $(INSTALL) -g pkcs11 -m 0640 $(srcdir)/usr/sbin/p11sak/p11sak_defined_attrs.conf $(DESTDIR)$(sysconfdir)/opencryptoki/p11sak_defined_attrs.conf || true
++	test -f $(DESTDIR)$(sysconfdir)/opencryptoki/p11sak_defined_attrs.conf || $(INSTALL) -m 0644 $(srcdir)/usr/sbin/p11sak/p11sak_defined_attrs.conf $(DESTDIR)$(sysconfdir)/opencryptoki/p11sak_defined_attrs.conf || true
+ endif
+ if ENABLE_ICATOK
+ 	cd $(DESTDIR)$(libdir)/opencryptoki/stdll && \
diff --git a/SOURCES/opencryptoki-openssl3-11196c4d7e221d29f0d385bd48ae4d6023a6e874.patch b/SOURCES/opencryptoki-openssl3-11196c4d7e221d29f0d385bd48ae4d6023a6e874.patch
deleted file mode 100644
index 3448bff..0000000
--- a/SOURCES/opencryptoki-openssl3-11196c4d7e221d29f0d385bd48ae4d6023a6e874.patch
+++ /dev/null
@@ -1,24 +0,0 @@
-commit 11196c4d7e221d29f0d385bd48ae4d6023a6e874
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 10:56:17 2021 +0200
-
-    CONFIGURE: fix configure.ac for --with-openssl
-    
-    The openSSL include files are in <openssl-path>/include while
-    the libraries are in <openssl-path> directly.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/configure.ac b/configure.ac
-index e2cc537a..d3374476 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -272,7 +272,7 @@ OPENSSL_CFLAGS=
- OPENSSL_LIBS=
- if test "x$with_openssl" != "xno"; then
- 	if test "x$with_openssl" != "xyes" -a "x$with_openssl" != "xcheck"; then
--		OPENSSL_CFLAGS="-I$with_openssl"
-+		OPENSSL_CFLAGS="-I$with_openssl/include"
- 		OPENSSL_LIBS="-L$with_openssl"
- 	fi
- 	old_cflags="$CFLAGS"
diff --git a/SOURCES/opencryptoki-openssl3-11a53055b22d590bd3c197908b0ff63f6fd3c520.patch b/SOURCES/opencryptoki-openssl3-11a53055b22d590bd3c197908b0ff63f6fd3c520.patch
deleted file mode 100644
index 996eb6a..0000000
--- a/SOURCES/opencryptoki-openssl3-11a53055b22d590bd3c197908b0ff63f6fd3c520.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-commit 11a53055b22d590bd3c197908b0ff63f6fd3c520
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Jun 29 17:35:18 2021 +0200
-
-    COMMON: mech_ec: Remove deprecated OpenSSL functions
-    
-    All low level EC_KEY functions are deprecated in OpenSSL 3.0.
-    Update the code to not use any of those.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/ec_defs.h b/usr/lib/common/ec_defs.h
-index 1f48794b..897cf891 100644
---- a/usr/lib/common/ec_defs.h
-+++ b/usr/lib/common/ec_defs.h
-@@ -14,13 +14,6 @@
- #include <openssl/opensslv.h>
- #include "ec_curves.h"
- 
--/* OpenSSL compat */
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--# define EC_POINT_get_affine_coordinates EC_POINT_get_affine_coordinates_GFp
--# define EC_POINT_set_compressed_coordinates \
--                                     EC_POINT_set_compressed_coordinates_GFp
--#endif
--
- // Elliptic Curve type
- //
- #define PRIME_CURVE         0x00
-diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c
-index b54e2db9..a0a06302 100644
---- a/usr/lib/common/mech_ec.c
-+++ b/usr/lib/common/mech_ec.c
-@@ -32,34 +32,6 @@
- #include "openssl/obj_mac.h"
- #include <openssl/ec.h>
- 
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--/*
-- * Older OpenSLL versions do not have BN_bn2binpad, so implement it here
-- */
--static int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
--{
--    int len, pad;
--    unsigned char *buf;
--
--    len = BN_num_bytes(a);
--    buf = (unsigned char *)malloc(len);
--    if (buf == NULL)
--        return -1;
--    BN_bn2bin(a, buf);
--
--    if (len >= tolen) {
--        memcpy(to, buf, tolen);
--    } else {
--        pad = tolen - len;
--        memset(to, 0, pad);
--        memcpy(to + pad, buf, len);
--    }
--
--    free(buf);
--    return tolen;
--}
--#endif
--
- #ifndef NID_brainpoolP160r1
- /*
-  * Older OpenSLL versions may not have the brainpool NIDs defined, define them
-@@ -1522,9 +1494,8 @@ CK_RV ec_point_from_priv_key(CK_BYTE *parms, CK_ULONG parms_len,
-                              CK_BYTE *d, CK_ULONG d_len,
-                              CK_BYTE **point, CK_ULONG *point_len)
- {
--    EC_KEY *eckey = NULL;
-     EC_POINT *pub_key = NULL;
--    const EC_GROUP *group = NULL;
-+    EC_GROUP *group = NULL;
-     int nid, p_len;
-     BIGNUM *bn_d = NULL, *bn_x = NULL, *bn_y = NULL;
-     CK_RV rc = CKR_OK;
-@@ -1541,17 +1512,7 @@ CK_RV ec_point_from_priv_key(CK_BYTE *parms, CK_ULONG parms_len,
-         goto done;
-     }
- 
--    eckey = EC_KEY_new_by_curve_name(nid);
--    if (eckey == NULL) {
--        rc = CKR_FUNCTION_FAILED;
--        goto done;
--    }
--    if (EC_KEY_set_private_key(eckey, bn_d) != 1) {
--        rc = CKR_FUNCTION_FAILED;
--        goto done;
--    }
--
--    group = EC_KEY_get0_group(eckey);
-+    group = EC_GROUP_new_by_curve_name(nid);
-     if (group == NULL) {
-         rc = CKR_FUNCTION_FAILED;
-         goto done;
-@@ -1576,7 +1537,7 @@ CK_RV ec_point_from_priv_key(CK_BYTE *parms, CK_ULONG parms_len,
-         rc = CKR_HOST_MEMORY;
-         goto done;
-     }
--    if (!EC_POINT_get_affine_coordinates_GFp(group, pub_key, bn_x, bn_y, NULL)) {
-+    if (!EC_POINT_get_affine_coordinates(group, pub_key, bn_x, bn_y, NULL)) {
-         rc = CKR_FUNCTION_FAILED;
-         goto done;
-     }
-@@ -1599,13 +1560,13 @@ CK_RV ec_point_from_priv_key(CK_BYTE *parms, CK_ULONG parms_len,
- done:
-     if (pub_key)
-         EC_POINT_free(pub_key);
--    if (eckey)
--        EC_KEY_free(eckey);
-     BN_clear_free(bn_x);
-     BN_clear_free(bn_y);
-     BN_clear_free(bn_d);
-     if (ec_point != NULL)
-         free(ec_point);
-+    if (group != NULL)
-+        EC_GROUP_free(group);
- 
-     return rc;
- }
diff --git a/SOURCES/opencryptoki-openssl3-145a696d478a1694ef314659a3d374f03f75c1b1.patch b/SOURCES/opencryptoki-openssl3-145a696d478a1694ef314659a3d374f03f75c1b1.patch
deleted file mode 100644
index 9f87102..0000000
--- a/SOURCES/opencryptoki-openssl3-145a696d478a1694ef314659a3d374f03f75c1b1.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-commit 145a696d478a1694ef314659a3d374f03f75c1b1
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Jul 5 13:49:09 2021 +0200
-
-    CONFIGURE: Remove AC_FUNC_MALLOC and AC_FUNC_REALLOC
-    
-    The AC_FUNC_MALLOC configure check might add the rpl_malloc() entry if it
-    does not like the default malloc implementation. The user would need to
-    provide the rpl_malloc implementation. This happens depending on compiler and
-    OS/distro being used. Same applies for AC_FUNC_REALLOC and rpl_realloc.
-    It happened for me when I configured it with address sanitizer (libubsan,
-    libasan) activated.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/configure.ac b/configure.ac
-index d3374476..286b7408 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -39,10 +39,8 @@ dnl Checks for library functions.
- AC_FUNC_ALLOCA
- AC_FUNC_CHOWN
- AC_FUNC_FORK
--AC_FUNC_MALLOC
- AC_FUNC_MKTIME
- AC_FUNC_MMAP
--AC_FUNC_REALLOC
- AC_FUNC_STRERROR_R
- AC_CHECK_FUNCS([atexit ftruncate gettimeofday localtime_r memchr memmove \
- 		memset mkdir munmap regcomp select socket strchr strcspn \
diff --git a/SOURCES/opencryptoki-openssl3-2c116d49359a5eb91ad7f1483c64650c7874a513.patch b/SOURCES/opencryptoki-openssl3-2c116d49359a5eb91ad7f1483c64650c7874a513.patch
deleted file mode 100644
index 171c080..0000000
--- a/SOURCES/opencryptoki-openssl3-2c116d49359a5eb91ad7f1483c64650c7874a513.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-commit 2c116d49359a5eb91ad7f1483c64650c7874a513
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 14:08:03 2021 +0200
-
-    TESTCASES: Skip test if operation state is not savable
-    
-    The sess_opstate testcase now handles the return code of CKR_STATE_UNSAVEABLE
-    from C_GetOperationState() and skips the test if that return code is
-    encountered.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/testcases/pkcs11/sess_opstate.c b/testcases/pkcs11/sess_opstate.c
-index 3235b450..3d1ab9d7 100644
---- a/testcases/pkcs11/sess_opstate.c
-+++ b/testcases/pkcs11/sess_opstate.c
-@@ -123,6 +123,10 @@ int sess_opstate_funcs(int loops)
-         opstatelen = 0;
-         rc = funcs->C_GetOperationState(s2, NULL, &opstatelen);
-         if (rc != CKR_OK) {
-+            if (rc == CKR_STATE_UNSAVEABLE) {
-+                testcase_skip("Get/SetOperationState digest test: state unsavable");
-+                goto out;
-+            }
-             testcase_error("C_GetOperationState rc=%s", p11_get_ckr(rc));
-             goto out;
-         }
-@@ -135,6 +139,10 @@ int sess_opstate_funcs(int loops)
- 
-         rc = funcs->C_GetOperationState(s2, opstate, &opstatelen);
-         if (rc != CKR_OK) {
-+            if (rc == CKR_STATE_UNSAVEABLE) {
-+                testcase_skip("Get/SetOperationState digest test: state unsavable");
-+                goto out;
-+            }
-             testcase_error("C_GetOperationState rc=%s", p11_get_ckr(rc));
-             goto out;
-         }
diff --git a/SOURCES/opencryptoki-openssl3-376e664f082b66de970b62a81588b034fd560d27.patch b/SOURCES/opencryptoki-openssl3-376e664f082b66de970b62a81588b034fd560d27.patch
deleted file mode 100644
index 8c81fe6..0000000
--- a/SOURCES/opencryptoki-openssl3-376e664f082b66de970b62a81588b034fd560d27.patch
+++ /dev/null
@@ -1,41 +0,0 @@
-commit 376e664f082b66de970b62a81588b034fd560d27
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Fri Aug 13 10:54:44 2021 +0200
-
-    TESTCASES: Remove RSA public exponent restriction for Soft token
-    
-    Since commit "Allow small RSA exponents in the default provider"
-    https://github.com/openssl/openssl/commit/254957f768a61c91c14d89566224173d0831c2ce
-    in OpenSSL 3.0, we do no longer need to restrict the tests for the Soft
-    token to RSA public exponents of 3 and 65537 only.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/testcases/common/common.c b/testcases/common/common.c
-index 0a64ecf2..abbe354f 100644
---- a/testcases/common/common.c
-+++ b/testcases/common/common.c
-@@ -16,6 +16,8 @@
- #include "pkcs11types.h"
- #include "regress.h"
- 
-+#define UNUSED(var)            ((void)(var))
-+
- CK_FUNCTION_LIST *funcs;
- CK_FUNCTION_LIST_3_0 *funcs3;
- CK_INTERFACE *ifs;
-@@ -879,11 +881,10 @@ int is_valid_cca_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len)
- /** Returns true if pubexp is valid for Soft Tokens **/
- int is_valid_soft_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len)
- {
--    CK_BYTE exp3[] = { 0x03 };  // 3
--    CK_BYTE exp65537[] = { 0x01, 0x00, 0x01 };  // 65537
-+    UNUSED(pubexp);
-+    UNUSED(pubexp_len);
- 
--    return (pubexp_len == 1 && (!memcmp(pubexp, exp3, 1)))
--        || (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3)));
-+    return TRUE;
- }
- 
- /** Returns true if slot_id is an ICSF token
diff --git a/SOURCES/opencryptoki-openssl3-4dd8a952fc00dd54cce090e4c053de408ba3884b.patch b/SOURCES/opencryptoki-openssl3-4dd8a952fc00dd54cce090e4c053de408ba3884b.patch
deleted file mode 100644
index 66e0bba..0000000
--- a/SOURCES/opencryptoki-openssl3-4dd8a952fc00dd54cce090e4c053de408ba3884b.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-commit 4dd8a952fc00dd54cce090e4c053de408ba3884b
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Aug 24 10:14:39 2021 +0200
-
-    SOFT: Detect unsupported EC curves with OpenSSL 3.0
-    
-    OpenSSL 3.0 behaves different in reporting an error when an unsupported
-    EC curve is used to generate an EC key. OpenSSL 1.1.1 returns an error
-    at EVP_PKEY_CTX_set_ec_paramgen_curve_nid() already, but OpenSSL 3.0 returns
-    an error only at EVP_PKEY_keygen().
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c
-index 43fd17c3..03767ec8 100644
---- a/usr/lib/soft_stdll/soft_specific.c
-+++ b/usr/lib/soft_stdll/soft_specific.c
-@@ -51,6 +51,7 @@
- #include <openssl/cmac.h>
- #include <openssl/ec.h>
- #include <openssl/bn.h>
-+#include <openssl/err.h>
- #if OPENSSL_VERSION_PREREQ(3, 0)
- #include <openssl/core_names.h>
- #include <openssl/param_build.h>
-@@ -4548,7 +4549,10 @@ CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata,
- 
-     if (EVP_PKEY_keygen(ctx, &ec_pkey) <= 0) {
-         TRACE_ERROR("EVP_PKEY_keygen failed\n");
--        rc = CKR_FUNCTION_FAILED;
-+        if (ERR_GET_REASON(ERR_peek_last_error()) == EC_R_INVALID_CURVE)
-+            rc = CKR_CURVE_NOT_SUPPORTED;
-+        else
-+            rc = CKR_FUNCTION_FAILED;
-         goto out;
-     }
- 
diff --git a/SOURCES/opencryptoki-openssl3-50408fc3ae0f25b256dda2033d538f88c9b4f903.patch b/SOURCES/opencryptoki-openssl3-50408fc3ae0f25b256dda2033d538f88c9b4f903.patch
deleted file mode 100644
index 3070552..0000000
--- a/SOURCES/opencryptoki-openssl3-50408fc3ae0f25b256dda2033d538f88c9b4f903.patch
+++ /dev/null
@@ -1,322 +0,0 @@
-commit 50408fc3ae0f25b256dda2033d538f88c9b4f903
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Jul 5 16:02:28 2021 +0200
-
-    COMMON: Fix memory leaks
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/mech_aes.c b/usr/lib/common/mech_aes.c
-index 59f82482..a1241693 100644
---- a/usr/lib/common/mech_aes.c
-+++ b/usr/lib/common/mech_aes.c
-@@ -2359,6 +2359,8 @@ CK_RV aes_mac_sign(STDLL_TokData_t *tokdata,
-         memcpy(out_data, ((AES_DATA_CONTEXT *) ctx->context)->iv, mac_len);
-         *out_data_len = mac_len;
- 
-+        sign_mgr_cleanup(tokdata, sess, ctx);
-+
-         return rc;
-     }
- }
-@@ -2497,6 +2499,8 @@ CK_RV aes_mac_sign_final(STDLL_TokData_t *tokdata,
-     memcpy(out_data, context->iv, mac_len);
-     *out_data_len = mac_len;
- 
-+    sign_mgr_cleanup(tokdata, sess, ctx);
-+
-     return rc;
- }
- 
-@@ -2554,8 +2558,12 @@ CK_RV aes_mac_verify(STDLL_TokData_t *tokdata,
-         }
- 
-         if (CRYPTO_memcmp(out_data, ((AES_DATA_CONTEXT *) ctx->context)->iv,
--                          out_data_len) == 0)
-+                          out_data_len) == 0) {
-+            verify_mgr_cleanup(tokdata, sess, ctx);
-             return CKR_OK;
-+        }
-+
-+        verify_mgr_cleanup(tokdata, sess, ctx);
- 
-         return CKR_SIGNATURE_INVALID;
-     }
-@@ -2685,8 +2693,12 @@ CK_RV aes_mac_verify_final(STDLL_TokData_t *tokdata,
-         }
-     }
- 
--    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) 
-+    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) {
-+        verify_mgr_cleanup(tokdata, sess, ctx);
-         return CKR_OK;
-+    }
-+
-+    verify_mgr_cleanup(tokdata, sess, ctx);
- 
-     return CKR_SIGNATURE_INVALID;
- }
-@@ -2766,6 +2778,8 @@ CK_RV aes_cmac_sign(STDLL_TokData_t *tokdata,
-     memcpy(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv, mac_len);
-     *out_data_len = mac_len;
- 
-+    sign_mgr_cleanup(tokdata, sess, ctx);
-+
- done:
-     object_put(tokdata, key_obj, TRUE);
-     key_obj = NULL;
-@@ -2913,6 +2927,8 @@ done:
-     object_put(tokdata, key_obj, TRUE);
-     key_obj = NULL;
- 
-+    sign_mgr_cleanup(tokdata, sess, ctx);
-+
-     return rc;
- }
- 
-@@ -2969,9 +2985,12 @@ CK_RV aes_cmac_verify(STDLL_TokData_t *tokdata,
- 
-     if (CRYPTO_memcmp(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv,
-                       out_data_len) == 0) {
-+        verify_mgr_cleanup(tokdata, sess, ctx);
-         return CKR_OK;
-     }
- 
-+    verify_mgr_cleanup(tokdata, sess, ctx);
-+
-     return CKR_SIGNATURE_INVALID;
- }
- 
-@@ -3105,8 +3124,12 @@ CK_RV aes_cmac_verify_final(STDLL_TokData_t *tokdata,
-         return rc;
-     }
- 
--    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0)
-+    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) {
-+        verify_mgr_cleanup(tokdata, sess, ctx);
-         return CKR_OK;
-+    }
-+
-+    verify_mgr_cleanup(tokdata, sess, ctx);
- 
-     return CKR_SIGNATURE_INVALID;
- }
-diff --git a/usr/lib/common/mech_des3.c b/usr/lib/common/mech_des3.c
-index 591ad3fa..3582102a 100644
---- a/usr/lib/common/mech_des3.c
-+++ b/usr/lib/common/mech_des3.c
-@@ -2006,6 +2006,8 @@ CK_RV des3_mac_sign(STDLL_TokData_t *tokdata,
- 
-         *out_data_len = mac_len;
- 
-+        sign_mgr_cleanup(tokdata, sess, ctx);
-+
-         return rc;
-     }
- }
-@@ -2144,6 +2146,8 @@ CK_RV des3_mac_sign_final(STDLL_TokData_t *tokdata,
- 
-     *out_data_len = mac_len;
- 
-+    sign_mgr_cleanup(tokdata, sess, ctx);
-+
-     return rc;
- }
- 
-@@ -2197,8 +2201,12 @@ CK_RV des3_mac_verify(STDLL_TokData_t *tokdata,
-         key_obj = NULL;
- 
-         if (CRYPTO_memcmp(out_data, ((DES_DATA_CONTEXT *) ctx->context)->iv,
--                          out_data_len) == 0)
-+                          out_data_len) == 0) {
-+            verify_mgr_cleanup(tokdata, sess, ctx);
-             return CKR_OK;
-+        }
-+
-+        verify_mgr_cleanup(tokdata, sess, ctx);
- 
-         return CKR_SIGNATURE_INVALID;
-     }
-@@ -2328,8 +2336,12 @@ CK_RV des3_mac_verify_final(STDLL_TokData_t *tokdata,
-         }
-     }
- 
--    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) 
-+    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) {
-+        verify_mgr_cleanup(tokdata, sess, ctx);
-         return CKR_OK;
-+    }
-+
-+    verify_mgr_cleanup(tokdata, sess, ctx);
- 
-     return CKR_SIGNATURE_INVALID;
- }
-@@ -2410,6 +2422,8 @@ CK_RV des3_cmac_sign(STDLL_TokData_t *tokdata,
-     object_put(tokdata, key_obj, TRUE);
-     key_obj = NULL;
- 
-+    sign_mgr_cleanup(tokdata, sess, ctx);
-+
-     return rc;
- }
- 
-@@ -2553,6 +2567,8 @@ done:
-     object_put(tokdata, key_obj, TRUE);
-     key_obj = NULL;
- 
-+   sign_mgr_cleanup(tokdata, sess, ctx);
-+
-     return rc;
- }
- 
-@@ -2605,8 +2621,12 @@ CK_RV des3_cmac_verify(STDLL_TokData_t *tokdata,
- 
-     if (CRYPTO_memcmp(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv,
-                       out_data_len) == 0) {
-+        verify_mgr_cleanup(tokdata, sess, ctx);
-         return CKR_OK;
-     }
-+
-+    verify_mgr_cleanup(tokdata, sess, ctx);
-+
-     return CKR_SIGNATURE_INVALID;
- }
- 
-@@ -2739,8 +2759,12 @@ CK_RV des3_cmac_verify_final(STDLL_TokData_t *tokdata,
- 
-     ctx->context_free_func = des3_cmac_cleanup;
- 
--    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0)
-+    if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0) {
-+        verify_mgr_cleanup(tokdata, sess, ctx);
-         return CKR_OK;
-+    }
-+
-+    verify_mgr_cleanup(tokdata, sess, ctx);
- 
-     return CKR_SIGNATURE_INVALID;
- }
-diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c
-index d01091f9..8bff6ada 100644
---- a/usr/lib/common/new_host.c
-+++ b/usr/lib/common/new_host.c
-@@ -174,6 +174,7 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
-         if (rc != 0) {
-             sltp->FcnList = NULL;
-             detach_shm(sltp->TokData, 0);
-+            final_data_store(sltp->TokData);
-             if (sltp->TokData)
-                 free(sltp->TokData);
-             sltp->TokData = NULL;
-@@ -186,6 +187,7 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
-     rc = load_token_data(sltp->TokData, SlotNumber);
-     if (rc != CKR_OK) {
-         sltp->FcnList = NULL;
-+        final_data_store(sltp->TokData);
-         if (sltp->TokData)
-             free(sltp->TokData);
-         sltp->TokData = NULL;
-@@ -218,6 +220,7 @@ done:
-             SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0);
-         } else {
-             CloseXProcLock(sltp->TokData);
-+            final_data_store(sltp->TokData);
-             free(sltp->TokData);
-             sltp->TokData = NULL;
-         }
-diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
-index a0e7517c..45f13551 100644
---- a/usr/lib/ep11_stdll/new_host.c
-+++ b/usr/lib/ep11_stdll/new_host.c
-@@ -164,6 +164,7 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
-         if (rc != 0) {
-             sltp->FcnList = NULL;
-             detach_shm(sltp->TokData, 0);
-+            final_data_store(sltp->TokData);
-             if (sltp->TokData)
-                 free(sltp->TokData);
-             sltp->TokData = NULL;
-@@ -176,6 +177,7 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
-     rc = load_token_data(sltp->TokData, SlotNumber);
-     if (rc != CKR_OK) {
-         sltp->FcnList = NULL;
-+        final_data_store(sltp->TokData);
-         if (sltp->TokData)
-             free(sltp->TokData);
-         sltp->TokData = NULL;
-@@ -208,6 +210,7 @@ done:
-             SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0);
-         } else {
-             CloseXProcLock(sltp->TokData);
-+            final_data_store(sltp->TokData);
-             free(sltp->TokData);
-             sltp->TokData = NULL;
-         }
-diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c
-index 09e9d27a..eed632c3 100644
---- a/usr/lib/icsf_stdll/new_host.c
-+++ b/usr/lib/icsf_stdll/new_host.c
-@@ -162,6 +162,7 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
-         if (rc != 0) {
-             sltp->FcnList = NULL;
-             detach_shm(sltp->TokData, 0);
-+            final_data_store(sltp->TokData);
-             if (sltp->TokData)
-                 free(sltp->TokData);
-             sltp->TokData = NULL;
-@@ -174,6 +175,7 @@ CK_RV ST_Initialize(API_Slot_t *sltp, CK_SLOT_ID SlotNumber,
-     rc = load_token_data(sltp->TokData, SlotNumber);
-     if (rc != CKR_OK) {
-         sltp->FcnList = NULL;
-+        final_data_store(sltp->TokData);
-         if (sltp->TokData)
-             free(sltp->TokData);
-         sltp->TokData = NULL;
-@@ -206,6 +208,7 @@ done:
-             SC_Finalize(sltp->TokData, SlotNumber, sinfp, NULL, 0);
-         } else {
-             CloseXProcLock(sltp->TokData);
-+            final_data_store(sltp->TokData);
-             free(sltp->TokData);
-             sltp->TokData = NULL;
-         }
-diff --git a/usr/lib/tpm_stdll/tpm_specific.c b/usr/lib/tpm_stdll/tpm_specific.c
-index 45bc4b78..c7557108 100644
---- a/usr/lib/tpm_stdll/tpm_specific.c
-+++ b/usr/lib/tpm_stdll/tpm_specific.c
-@@ -213,6 +213,10 @@ CK_RV token_specific_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
-     }
- 
-     tpm_data = (tpm_private_data_t *)calloc(1, sizeof(tpm_private_data_t));
-+    if (tpm_data == NULL) {
-+        TRACE_ERROR("calloc failed\n");
-+        return CKR_HOST_MEMORY;
-+    }
-     tokdata->private_data = tpm_data;
- 
-     tpm_data->tspContext = NULL_HCONTEXT;
-@@ -221,12 +225,15 @@ CK_RV token_specific_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
-     result = Tspi_Context_Create(&tpm_data->tspContext);
-     if (result) {
-         TRACE_ERROR("Tspi_Context_Create failed. rc=0x%x\n", result);
-+        free(tpm_data);
-         return CKR_FUNCTION_FAILED;
-     }
- 
-     result = Tspi_Context_Connect(tpm_data->tspContext, NULL);
-     if (result) {
-         TRACE_ERROR("Tspi_Context_Connect failed. rc=0x%x\n", result);
-+        Tspi_Context_Close(tpm_data->tspContext);
-+        free(tpm_data);
-         return CKR_FUNCTION_FAILED;
-     }
- 
-@@ -234,6 +241,8 @@ CK_RV token_specific_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
-                                            &tpm_data->hDefaultPolicy);
-     if (result) {
-         TRACE_ERROR("Tspi_Context_GetDefaultPolicy failed. rc=0x%x\n", result);
-+        Tspi_Context_Close(tpm_data->tspContext);
-+        free(tpm_data);
-         return CKR_FUNCTION_FAILED;
-     }
- 
diff --git a/SOURCES/opencryptoki-openssl3-50e3f06823696c74eea90a77e16b28da1f79cd47.patch b/SOURCES/opencryptoki-openssl3-50e3f06823696c74eea90a77e16b28da1f79cd47.patch
deleted file mode 100644
index 08998cc..0000000
--- a/SOURCES/opencryptoki-openssl3-50e3f06823696c74eea90a77e16b28da1f79cd47.patch
+++ /dev/null
@@ -1,3420 +0,0 @@
-commit 50e3f06823696c74eea90a77e16b28da1f79cd47
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 14:33:33 2021 +0200
-
-    SOFT: Remove deprecated OpenSSL functions
-    
-    All low level RSA, EC_KEY, and DH functions are deprecated in OpenSSL 3.0.
-    Update the code to not use any of those.
-    
-    Change the digest operation context to store the OpenSSL digest context,
-    instead of the deprecated way of retrieving and restoring the digest state.
-    This makes the digest operation context 'non savable'.
-    
-    Also remove support for OpenSSL < v1.1.1. This code used even more
-    low level OpenSSL functions.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c
-index 5ca22693..43fd17c3 100644
---- a/usr/lib/soft_stdll/soft_specific.c
-+++ b/usr/lib/soft_stdll/soft_specific.c
-@@ -26,10 +26,6 @@
- 
- #include <openssl/opensslv.h>
- 
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--#define NO_EC 1
--#endif
--
- #include "pkcs11types.h"
- #include "defs.h"
- #include "host_defs.h"
-@@ -54,14 +50,10 @@
- #include <openssl/crypto.h>
- #include <openssl/cmac.h>
- #include <openssl/ec.h>
--
--/*
-- * In order to make opencryptoki compatible with
-- * OpenSSL 1.1 API Changes and backward compatible
-- * we need to check for its version
-- */
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--#define OLDER_OPENSSL
-+#include <openssl/bn.h>
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+#include <openssl/core_names.h>
-+#include <openssl/param_build.h>
- #endif
- 
- #define MAX_GENERIC_KEY_SIZE 256
-@@ -76,7 +68,10 @@ static const MECH_LIST_ELEMENT soft_mech_list[] = {
- #if !(NODSA)
-     {CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_GENERATE_KEY_PAIR}},
- #endif
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    /* OpenSSL 3.0 supports single-DES only with the legacy provider */
-     {CKM_DES_KEY_GEN, {8, 8, CKF_GENERATE}},
-+#endif
-     {CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}},
- #if !(NOCDMF)
-     {CKM_CDMF_KEY_GEN, {0, 0, CKF_GENERATE}},
-@@ -120,10 +115,13 @@ static const MECH_LIST_ELEMENT soft_mech_list[] = {
-     {CKM_DH_PKCS_KEY_PAIR_GEN, {512, 2048, CKF_GENERATE_KEY_PAIR}},
- #endif
- /* End code contributed by Corrent corp. */
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    /* OpenSSL 3.0 supports single-DES only with the legacy provider */
-     {CKM_DES_ECB, {8, 8, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}},
-     {CKM_DES_CBC, {8, 8, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}},
-     {CKM_DES_CBC_PAD,
-      {8, 8, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}},
-+#endif
- #if !(NOCDMF)
-     {CKM_CDMF_ECB, {0, 0, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}},
-     {CKM_CDMF_CBC, {0, 0, CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP}},
-@@ -286,58 +284,6 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t *tokdata,
-                              CK_ULONG *out_data_len,
-                              OBJECT *key, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc;
--    DES_key_schedule des_key2;
--    const_DES_cblock key_val_SSL, in_key_data;
--    DES_cblock out_key_data;
--    unsigned int i, j;
--    CK_ATTRIBUTE *attr = NULL;
--
--    UNUSED(tokdata);
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--    // Create the key schedule
--    memcpy(&key_val_SSL, attr->pValue, 8);
--    DES_set_key_unchecked(&key_val_SSL, &des_key2);
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // Both the encrypt and the decrypt are done 8 bytes at a time
--    if (encrypt) {
--        for (i = 0; i < in_data_len; i = i + 8) {
--            memcpy(in_key_data, in_data + i, 8);
--            DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2,
--                            DES_ENCRYPT);
--            memcpy(out_data + i, out_key_data, 8);
--        }
--
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--
--        for (j = 0; j < in_data_len; j = j + 8) {
--            memcpy(in_key_data, in_data + j, 8);
--            DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2,
--                            DES_DECRYPT);
--            memcpy(out_data + j, out_key_data, 8);
--        }
--
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_ecb();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -384,7 +330,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata,
-@@ -394,47 +339,6 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t *tokdata,
-                              CK_ULONG *out_data_len,
-                              OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc;
--    CK_ATTRIBUTE *attr = NULL;
--    DES_cblock ivec;
--    DES_key_schedule des_key2;
--    const_DES_cblock key_val_SSL;
--
--    UNUSED(tokdata);
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--    // Create the key schedule
--    memcpy(&key_val_SSL, attr->pValue, 8);
--    DES_set_key_unchecked(&key_val_SSL, &des_key2);
--
--    memcpy(&ivec, init_v, 8);
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--
--    if (encrypt) {
--        DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec,
--                         DES_ENCRYPT);
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--        DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec,
--                         DES_DECRYPT);
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_cbc();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -481,7 +385,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata,
-@@ -491,80 +394,6 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t *tokdata,
-                               CK_ULONG *out_data_len,
-                               OBJECT *key, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc;
--    CK_ATTRIBUTE *attr = NULL;
--    CK_BYTE key_value[3 * DES_KEY_SIZE];
--    CK_KEY_TYPE keytype;
--    unsigned int k, j;
--    DES_key_schedule des_key1;
--    DES_key_schedule des_key2;
--    DES_key_schedule des_key3;
--    const_DES_cblock key_SSL1, key_SSL2, key_SSL3, in_key_data;
--    DES_cblock out_key_data;
--
--    UNUSED(tokdata);
--
--    // get the key type
--    rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n");
--        return rc;
--    }
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--    if (keytype == CKK_DES2) {
--        memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE);
--        memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE);
--    } else {
--        memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE);
--    }
--
--    // The key as passed is a 24 byte long string containing three des keys
--    // pick them apart and create the 3 corresponding key schedules
--    memcpy(&key_SSL1, key_value, 8);
--    memcpy(&key_SSL2, key_value + 8, 8);
--    memcpy(&key_SSL3, key_value + 16, 8);
--    DES_set_key_unchecked(&key_SSL1, &des_key1);
--    DES_set_key_unchecked(&key_SSL2, &des_key2);
--    DES_set_key_unchecked(&key_SSL3, &des_key3);
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // the encrypt and decrypt are done 8 bytes at a time
--    if (encrypt) {
--        for (k = 0; k < in_data_len; k = k + 8) {
--            memcpy(in_key_data, in_data + k, 8);
--            DES_ecb3_encrypt((const_DES_cblock *) & in_key_data,
--                             (DES_cblock *) & out_key_data,
--                             &des_key1, &des_key2, &des_key3, DES_ENCRYPT);
--            memcpy(out_data + k, out_key_data, 8);
--        }
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--        for (j = 0; j < in_data_len; j = j + 8) {
--            memcpy(in_key_data, in_data + j, 8);
--            DES_ecb3_encrypt((const_DES_cblock *) & in_key_data,
--                             (DES_cblock *) & out_key_data,
--                             &des_key1, &des_key2, &des_key3, DES_DECRYPT);
--            memcpy(out_data + j, out_key_data, 8);
--        }
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_ede3_ecb();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -624,7 +453,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata,
-@@ -634,78 +462,6 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t *tokdata,
-                               CK_ULONG *out_data_len,
-                               OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_ATTRIBUTE *attr = NULL;
--    CK_RV rc = CKR_OK;
--    CK_BYTE key_value[3 * DES_KEY_SIZE];
--    CK_KEY_TYPE keytype;
--    DES_key_schedule des_key1;
--    DES_key_schedule des_key2;
--    DES_key_schedule des_key3;
--    const_DES_cblock key_SSL1, key_SSL2, key_SSL3;
--    DES_cblock ivec;
--
--    UNUSED(tokdata);
--
--    // get the key type
--    rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n");
--        return rc;
--    }
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--    if (keytype == CKK_DES2) {
--        memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE);
--        memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE);
--    } else {
--        memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE);
--    }
--
--    // The key as passed in is a 24 byte string containing 3 keys
--    // pick it apart and create the key schedules
--    memcpy(&key_SSL1, key_value, 8);
--    memcpy(&key_SSL2, key_value + 8, 8);
--    memcpy(&key_SSL3, key_value + 16, 8);
--    DES_set_key_unchecked(&key_SSL1, &des_key1);
--    DES_set_key_unchecked(&key_SSL2, &des_key2);
--    DES_set_key_unchecked(&key_SSL3, &des_key3);
--
--    memcpy(ivec, init_v, sizeof(ivec));
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // Encrypt or decrypt the data
--    if (encrypt) {
--        DES_ede3_cbc_encrypt(in_data,
--                             out_data,
--                             in_data_len,
--                             &des_key1,
--                             &des_key2, &des_key3, &ivec, DES_ENCRYPT);
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--        DES_ede3_cbc_encrypt(in_data,
--                             out_data,
--                             in_data_len,
--                             &des_key1,
--                             &des_key2, &des_key3, &ivec, DES_DECRYPT);
--
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -765,7 +521,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-@@ -795,14 +550,20 @@ CK_RV token_specific_tdes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message,
- // convert from the local PKCS11 template representation to
- // the underlying requirement
- // returns the pointer to the local key representation
--static void *rsa_convert_public_key(OBJECT *key_obj)
-+static EVP_PKEY *rsa_convert_public_key(OBJECT *key_obj)
- {
-     CK_BBOOL rc;
-     CK_ATTRIBUTE *modulus = NULL;
-     CK_ATTRIBUTE *pub_exp = NULL;
--
--    RSA *rsa;
-+    EVP_PKEY *pkey = NULL;
-     BIGNUM *bn_mod, *bn_exp;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    EVP_PKEY_CTX *pctx = NULL;
-+    OSSL_PARAM_BLD *tmpl = NULL;
-+    OSSL_PARAM *params = NULL;
-+#else
-+    RSA *rsa;
-+#endif
- 
-     rc = template_attribute_get_non_empty(key_obj->template, CKA_MODULUS,
-                                           &modulus);
-@@ -813,12 +574,7 @@ static void *rsa_convert_public_key(OBJECT *key_obj)
-     if (rc != CKR_OK)
-         return NULL;
- 
--    // Create an RSA key struct to return
--    rsa = RSA_new();
--    if (rsa == NULL)
--        return NULL;
--
--    // Create and init BIGNUM structs to stick in the RSA struct
-+    // Create and init BIGNUM structs
-     bn_mod = BN_new();
-     bn_exp = BN_new();
- 
-@@ -827,24 +583,74 @@ static void *rsa_convert_public_key(OBJECT *key_obj)
-             free(bn_mod);
-         if (bn_exp)
-             free(bn_exp);
--        RSA_free(rsa);
-         return NULL;
-     }
--    // Convert from strings to BIGNUMs and stick them in the RSA struct
-+    // Convert from strings to BIGNUMs
-     BN_bin2bn((unsigned char *) modulus->pValue, modulus->ulValueLen, bn_mod);
-     BN_bin2bn((unsigned char *) pub_exp->pValue, pub_exp->ulValueLen, bn_exp);
- 
--#ifdef OLDER_OPENSSL
--    rsa->n = bn_mod;
--    rsa->e = bn_exp;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    // Create an RSA key struct to return
-+    rsa = RSA_new();
-+    if (rsa == NULL) {
-+        if (bn_mod)
-+             free(bn_mod);
-+         if (bn_exp)
-+             free(bn_exp);
-+        return NULL;
-+    }
-+
-     RSA_set0_key(rsa, bn_mod, bn_exp, NULL);
-+
-+    pkey = EVP_PKEY_new();
-+    if (pkey == NULL) {
-+       RSA_free(rsa);
-+       return NULL;
-+    }
-+
-+    if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
-+        RSA_free(rsa);
-+        EVP_PKEY_free(pkey);
-+        return NULL;
-+    }
-+#else
-+    tmpl = OSSL_PARAM_BLD_new();
-+    if (tmpl == NULL)
-+        goto out;
-+
-+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, bn_mod) ||
-+        !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, bn_exp))
-+        goto out;
-+
-+    params = OSSL_PARAM_BLD_to_param(tmpl);
-+    if (params == NULL)
-+        goto out;
-+
-+    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
-+    if (pctx == NULL)
-+        goto out;
-+
-+    if (!EVP_PKEY_fromdata_init(pctx) ||
-+        !EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_PUBLIC_KEY, params))
-+        goto out;
-+
-+out:
-+    if (pctx != NULL)
-+        EVP_PKEY_CTX_free(pctx);
-+    if (tmpl != NULL)
-+        OSSL_PARAM_BLD_free(tmpl);
-+    if (params != NULL)
-+        OSSL_PARAM_free(params);
-+    if (bn_mod != NULL)
-+        BN_free(bn_mod);
-+    if (bn_exp != NULL)
-+        BN_free(bn_exp);
- #endif
- 
--    return (void *) rsa;
-+    return pkey;
- }
- 
--static void *rsa_convert_private_key(OBJECT *key_obj)
-+static EVP_PKEY *rsa_convert_private_key(OBJECT *key_obj)
- {
-     CK_ATTRIBUTE *modulus = NULL;
-     CK_ATTRIBUTE *pub_exp = NULL;
-@@ -854,9 +660,15 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
-     CK_ATTRIBUTE *exp1 = NULL;
-     CK_ATTRIBUTE *exp2 = NULL;
-     CK_ATTRIBUTE *coeff = NULL;
--
-+    EVP_PKEY *pkey = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    EVP_PKEY_CTX *pctx = NULL;
-+    OSSL_PARAM_BLD *tmpl = NULL;
-+    OSSL_PARAM *params = NULL;
-+#else
-     RSA *rsa;
-     RSA_METHOD *meth;
-+#endif
-     BIGNUM *bn_mod, *bn_pub_exp, *bn_priv_exp, *bn_p1, *bn_p2, *bn_e1, *bn_e2,
-         *bn_cf;
- 
-@@ -873,6 +685,8 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
-     if (!prime2 && !modulus) {
-         return NULL;
-     }
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     // Create and init all the RSA and BIGNUM structs we need.
-     rsa = RSA_new();
-     if (rsa == NULL)
-@@ -884,17 +698,6 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
-      * Token doesn't implement RSA and, instead, calls OpenSSL for it.
-      * So to avoid it we set RSA methods to the default rsa methods.
-      */
--#ifdef OLDER_OPENSSL
--    if (rsa->engine) {
--        meth = (RSA_METHOD *) rsa->meth;
--        const RSA_METHOD *meth2 = RSA_PKCS1_SSLeay();
--        meth->rsa_pub_enc = meth2->rsa_pub_enc;
--        meth->rsa_pub_dec = meth2->rsa_pub_dec;
--        meth->rsa_priv_enc = meth2->rsa_priv_enc;
--        meth->rsa_priv_dec = meth2->rsa_priv_dec;
--        meth->rsa_mod_exp = meth2->rsa_mod_exp;
--        meth->bn_mod_exp = meth2->bn_mod_exp;
--#else
- /*
-  * XXX I dont see a better way than to ignore this warning for now.
-  * Note that the GCC pragma also works for clang.
-@@ -912,8 +715,8 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
-         RSA_meth_set_mod_exp(meth, RSA_meth_get_mod_exp(meth2));
-         RSA_meth_set_bn_mod_exp(meth, RSA_meth_get_bn_mod_exp(meth2));
- # pragma GCC diagnostic pop
--#endif
-     }
-+#endif
- 
-     bn_mod = BN_new();
-     bn_pub_exp = BN_new();
-@@ -926,33 +729,14 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
- 
-     if ((bn_cf == NULL) || (bn_e2 == NULL) || (bn_e1 == NULL) ||
-         (bn_p2 == NULL) || (bn_p1 == NULL) || (bn_priv_exp == NULL) ||
--        (bn_pub_exp == NULL) || (bn_mod == NULL)) {
--        if (rsa)
--            RSA_free(rsa);
--        if (bn_mod)
--            BN_free(bn_mod);
--        if (bn_pub_exp)
--            BN_free(bn_pub_exp);
--        if (bn_priv_exp)
--            BN_free(bn_priv_exp);
--        if (bn_p1)
--            BN_free(bn_p1);
--        if (bn_p2)
--            BN_free(bn_p2);
--        if (bn_e1)
--            BN_free(bn_e1);
--        if (bn_e2)
--            BN_free(bn_e2);
--        if (bn_cf)
--            BN_free(bn_cf);
--        return NULL;
--    }
-+        (bn_pub_exp == NULL) || (bn_mod == NULL))
-+        goto out;
- 
-     // CRT key?
-     if (prime1) {
--        if (!prime2 || !exp1 || !exp2 || !coeff) {
--            return NULL;
--        }
-+        if (!prime2 || !exp1 || !exp2 || !coeff)
-+            goto out;
-+
-         // Even though this is CRT key, OpenSSL requires the
-         // modulus and exponents filled in or encrypt and decrypt will
-         // not work
-@@ -969,20 +753,44 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
-         BN_bin2bn((unsigned char *) exp1->pValue, exp1->ulValueLen, bn_e1);
-         BN_bin2bn((unsigned char *) exp2->pValue, exp2->ulValueLen, bn_e2);
-         BN_bin2bn((unsigned char *) coeff->pValue, coeff->ulValueLen, bn_cf);
--#ifdef OLDER_OPENSSL
--        rsa->n = bn_mod;
--        rsa->d = bn_priv_exp;
--        rsa->p = bn_p1;
--        rsa->q = bn_p2;
--        rsa->dmp1 = bn_e1;
--        rsa->dmq1 = bn_e2;
--        rsa->iqmp = bn_cf;
--#else
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         RSA_set0_key(rsa, bn_mod, bn_pub_exp, bn_priv_exp);
-+        bn_mod = NULL;
-+        bn_pub_exp = NULL;
-+        bn_priv_exp = NULL;
-         RSA_set0_factors(rsa, bn_p1, bn_p2);
-+        bn_p1 = NULL;
-+        bn_p2 = NULL;
-         RSA_set0_crt_params(rsa, bn_e1, bn_e2, bn_cf);
-+        bn_e1 = NULL;
-+        bn_e2 = NULL;
-+        bn_cf = NULL;
-+
-+        pkey = EVP_PKEY_new();
-+        if (pkey == NULL)
-+            goto out;
-+
-+        if (EVP_PKEY_assign_RSA(pkey, rsa) != 1)
-+            goto out;
-+#else
-+        tmpl = OSSL_PARAM_BLD_new();
-+        if (tmpl == NULL)
-+            goto out;
-+
-+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, bn_mod) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, bn_pub_exp) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, bn_priv_exp) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR1, bn_p1) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_FACTOR2, bn_p2) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT1,
-+                                                                       bn_e1) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_EXPONENT2,
-+                                                                       bn_e2) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
-+                                                                       bn_cf))
-+            goto out;
- #endif
--        return rsa;
-     } else {                    // must be a non-CRT key
-         if (!priv_exp) {
-             return NULL;
-@@ -993,15 +801,90 @@ static void *rsa_convert_private_key(OBJECT *key_obj)
-                   bn_pub_exp);
-         BN_bin2bn((unsigned char *) priv_exp->pValue, priv_exp->ulValueLen,
-                   bn_priv_exp);
--#ifdef OLDER_OPENSSL
--        rsa->n = bn_mod;
--        rsa->d = bn_priv_exp;
--#else
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         RSA_set0_key(rsa, bn_mod, bn_pub_exp, bn_priv_exp);
-+        bn_mod = NULL;
-+        bn_pub_exp = NULL;
-+        bn_priv_exp = NULL;
-+
-+        pkey = EVP_PKEY_new();
-+        if (pkey == NULL)
-+            goto out;
-+
-+        if (EVP_PKEY_assign_RSA(pkey, rsa) != 1)
-+            goto out;
-+#else
-+        tmpl = OSSL_PARAM_BLD_new();
-+        if (tmpl == NULL)
-+            goto out;
-+
-+        if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_N, bn_mod) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_E, bn_pub_exp) ||
-+            !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_RSA_D, bn_priv_exp))
-+            goto out;
- #endif
-     }
- 
--    return (void *) rsa;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    params = OSSL_PARAM_BLD_to_param(tmpl);
-+    if (params == NULL)
-+        goto out;
-+
-+    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
-+    if (pctx == NULL)
-+        goto out;
-+
-+    if (!EVP_PKEY_fromdata_init(pctx) ||
-+        !EVP_PKEY_fromdata(pctx, &pkey, EVP_PKEY_PUBLIC_KEY, params))
-+        goto out;
-+
-+    EVP_PKEY_CTX_free(pctx);
-+    OSSL_PARAM_BLD_free(tmpl);
-+    OSSL_PARAM_free(params);
-+    BN_free(bn_mod);
-+    BN_free(bn_pub_exp);
-+    BN_free(bn_priv_exp);
-+    BN_free(bn_p1);
-+    BN_free(bn_p2);
-+    BN_free(bn_e1);
-+    BN_free(bn_e2);
-+    BN_free(bn_cf);
-+#endif
-+
-+    return pkey;
-+out:
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    if (rsa)
-+        RSA_free(rsa);
-+#else
-+    if (pctx != NULL)
-+        EVP_PKEY_CTX_free(pctx);
-+    if (tmpl != NULL)
-+        OSSL_PARAM_BLD_free(tmpl);
-+    if (params != NULL)
-+        OSSL_PARAM_free(params);
-+#endif
-+    if (pkey)
-+        EVP_PKEY_free(pkey);
-+    if (bn_mod)
-+        BN_free(bn_mod);
-+    if (bn_pub_exp)
-+        BN_free(bn_pub_exp);
-+    if (bn_priv_exp)
-+        BN_free(bn_priv_exp);
-+    if (bn_p1)
-+        BN_free(bn_p1);
-+    if (bn_p2)
-+        BN_free(bn_p2);
-+    if (bn_e1)
-+        BN_free(bn_e1);
-+    if (bn_e2)
-+        BN_free(bn_e2);
-+    if (bn_cf)
-+        BN_free(bn_cf);
-+
-+    return NULL;
- }
- 
- static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-@@ -1012,14 +895,16 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     CK_BBOOL flag;
-     CK_RV rc;
-     CK_ULONG BNLength;
--    RSA *rsa = NULL;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    const RSA *rsa = NULL;
-     const BIGNUM *bignum = NULL;
-+#else
-+    BIGNUM *bignum = NULL;
-+#endif
-     CK_BYTE *ssl_ptr = NULL;
-     BIGNUM *e = NULL;
--#ifndef OLDER_OPENSSL
-     EVP_PKEY *pkey = NULL;
-     EVP_PKEY_CTX *ctx = NULL;
--#endif
- 
-     rc = template_attribute_get_ulong(publ_tmpl, CKA_MODULUS_BITS, &mod_bits);
-     if (rc != CKR_OK) {
-@@ -1052,20 +937,6 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     }
-     BN_bin2bn(publ_exp->pValue, publ_exp->ulValueLen, e);
- 
--#ifdef OLDER_OPENSSL
--    rsa = RSA_new();
--    if (rsa == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        return CKR_HOST_MEMORY;
--    }
--
--    if (!RSA_generate_key_ex(rsa, mod_bits, e, NULL)) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_FUNCTION_FAILED;
--        goto done;
--    }
--    bignum = rsa->n;
--#else
-     ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
-     if (ctx == NULL) {
-         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-@@ -1084,22 +955,36 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-         rc = CKR_FUNCTION_FAILED;
-         goto done;
-     }
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     if (EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, e) != 1) {
-+#else
-+    if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, e) != 1) {
-+#endif
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         rc = CKR_FUNCTION_FAILED;
-         goto done;
-     }
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    e = NULL; // will be freed as part of the context
-+#endif
-     if (EVP_PKEY_keygen(ctx, &pkey) != 1) {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         rc = CKR_FUNCTION_FAILED;
-         goto done;
-     }
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     if ((rsa = EVP_PKEY_get0_RSA(pkey)) == NULL) {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         rc = CKR_FUNCTION_FAILED;
-         goto done;
-     }
-     RSA_get0_key(rsa, &bignum, NULL, NULL);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1122,12 +1007,20 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     }
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // Public Exponent
--#ifdef OLDER_OPENSSL
--    bignum = rsa->e;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_key(rsa, NULL, &bignum, NULL);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_E, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1166,6 +1059,10 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     }
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // local = TRUE
-     //
-@@ -1189,10 +1086,14 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     // to force the system to not return this for RSA keys..
- 
-     // Add the modulus to the private key information
--#ifdef OLDER_OPENSSL
--    bignum = rsa->n;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_key(rsa, &bignum, NULL, NULL);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1215,12 +1116,20 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     }
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // Private Exponent
--#ifdef OLDER_OPENSSL
--    bignum = rsa->d;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_key(rsa, NULL, NULL, &bignum);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_D, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1245,13 +1154,20 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     OPENSSL_cleanse(ssl_ptr, BNLength);
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // prime #1: p
--    //
--#ifdef OLDER_OPENSSL
--    bignum = rsa->p;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_factors(rsa, &bignum, NULL);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1276,13 +1192,20 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     OPENSSL_cleanse(ssl_ptr, BNLength);
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // prime #2: q
--    //
--#ifdef OLDER_OPENSSL
--    bignum = rsa->q;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_factors(rsa, NULL, &bignum);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1307,13 +1230,20 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     OPENSSL_cleanse(ssl_ptr, BNLength);
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // exponent 1: d mod(p-1)
--    //
--#ifdef OLDER_OPENSSL
--    bignum = rsa->dmp1;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_crt_params(rsa, &bignum, NULL, NULL);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT1, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1338,13 +1268,20 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     OPENSSL_cleanse(ssl_ptr, BNLength);
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // exponent 2: d mod(q-1)
--    //
--#ifdef OLDER_OPENSSL
--    bignum = rsa->dmq1;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_crt_params(rsa, NULL, &bignum, NULL);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_EXPONENT2, &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1369,13 +1306,21 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     OPENSSL_cleanse(ssl_ptr, BNLength);
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     // CRT coefficient:  q_inverse mod(p)
--    //
--#ifdef OLDER_OPENSSL
--    bignum = rsa->iqmp;
--#else
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     RSA_get0_crt_params(rsa, NULL, NULL, &bignum);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_COEFFICIENT1,
-+                               &bignum)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
- #endif
-     BNLength = BN_num_bytes(bignum);
-     ssl_ptr = malloc(BNLength);
-@@ -1400,6 +1345,10 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     OPENSSL_cleanse(ssl_ptr, BNLength);
-     free(ssl_ptr);
-     ssl_ptr = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(bignum);
-+    bignum = NULL;
-+#endif
- 
-     flag = TRUE;
-     rc = build_attribute(CKA_LOCAL, &flag, sizeof(CK_BBOOL), &attr);
-@@ -1415,16 +1364,6 @@ static CK_RV os_specific_rsa_keygen(TEMPLATE *publ_tmpl, TEMPLATE *priv_tmpl)
-     }
- 
- done:
--#ifdef OLDER_OPENSSL
--    if (e != NULL)
--        BN_free(e);
--    if (rsa != NULL)
--        RSA_free(rsa);
--    if (ssl_ptr != NULL) {
--        OPENSSL_cleanse(ssl_ptr, BNLength);
--        free(ssl_ptr);
--    }
--#else
-     if (ssl_ptr != NULL) {
-         OPENSSL_cleanse(ssl_ptr, BNLength);
-         free(ssl_ptr);
-@@ -1433,6 +1372,11 @@ done:
-         EVP_PKEY_free(pkey);
-     if (ctx != NULL)
-         EVP_PKEY_CTX_free(ctx);
-+    if (e != NULL)
-+        BN_free(e);
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    if (bignum != NULL)
-+        BN_free(bignum);
- #endif
-     return rc;
- }
-@@ -1457,60 +1401,17 @@ static CK_RV os_specific_rsa_encrypt(CK_BYTE *in_data,
-                                      CK_ULONG in_data_len,
-                                      CK_BYTE *out_data, OBJECT *key_obj)
- {
--#ifdef OLDER_OPENSSL
--    CK_RV rc;
--    RSA *rsa;
--    int size;
--
--    // Convert the local representation to an RSA representation
--    rsa = (RSA *) rsa_convert_public_key(key_obj);
--    if (rsa == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_FUNCTION_FAILED;
--        return rc;
--    }
--    // Do an RSA public encryption
--    size =
--        RSA_public_encrypt(in_data_len, in_data, out_data, rsa, RSA_NO_PADDING);
--    if (size == -1) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_ARGUMENTS_BAD;
--        goto done;
--    }
--
--    rc = CKR_OK;
--
--done:
--    RSA_free(rsa);
--
--    return rc;
--#else
-     EVP_PKEY_CTX *ctx = NULL;
-     EVP_PKEY *pkey = NULL;
--    RSA *rsa = NULL;
-     CK_RV rc;
-     size_t outlen = in_data_len;
- 
--    rsa = (RSA *)rsa_convert_public_key(key_obj);
--    if (rsa == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_FUNCTION_FAILED;
--        return rc;
--    }
--
--    pkey = EVP_PKEY_new();
-+    pkey = rsa_convert_public_key(key_obj);
-     if (pkey == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        rc = CKR_HOST_MEMORY;
--        goto done;
--    }
--
--    if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         rc = CKR_FUNCTION_FAILED;
--        goto done;
-+        return rc;
-     }
--    rsa = NULL; /* freed together with pkey */
- 
-     ctx = EVP_PKEY_CTX_new(pkey, NULL);
-     if (ctx == NULL) {
-@@ -1538,76 +1439,28 @@ done:
- 
-     rc = CKR_OK;
- done:
--    if (rsa != NULL)
--        RSA_free(rsa);
-     if (pkey != NULL)
-         EVP_PKEY_free(pkey);
-     if (ctx != NULL)
-         EVP_PKEY_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- static CK_RV os_specific_rsa_decrypt(CK_BYTE *in_data,
-                                      CK_ULONG in_data_len,
-                                      CK_BYTE *out_data, OBJECT *key_obj)
- {
--#ifdef OLDER_OPENSSL
--    CK_RV rc;
--    RSA *rsa;
--    int size;
--
--    // Convert the local key representation to an RSA key representaion
--    rsa = (RSA *) rsa_convert_private_key(key_obj);
--    if (rsa == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_FUNCTION_FAILED;
--        return rc;
--    }
--    // Do the private decryption
--    size =
--        RSA_private_decrypt(in_data_len, in_data, out_data, rsa,
--                            RSA_NO_PADDING);
--
--    if (size == -1) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_FUNCTION_FAILED;
--        goto done;
--    }
--
--    rc = CKR_OK;
--
--done:
--    RSA_free(rsa);
--
--    return rc;
--#else
-     EVP_PKEY_CTX *ctx = NULL;
-     EVP_PKEY *pkey = NULL;
--    RSA *rsa = NULL;
-     size_t outlen = in_data_len;
-     CK_RV rc;
- 
--    rsa = (RSA *)rsa_convert_private_key(key_obj);
--    if (rsa == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rc = CKR_FUNCTION_FAILED;
--        return rc;
--    }
--
--    pkey = EVP_PKEY_new();
-+    pkey = rsa_convert_private_key(key_obj);
-     if (pkey == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        rc = CKR_HOST_MEMORY;
--        goto done;
--    }
--
--    if (EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         rc = CKR_FUNCTION_FAILED;
--        goto done;
-+        return rc;
-     }
--    rsa = NULL; /* freed together with pkey */
- 
-     ctx = EVP_PKEY_CTX_new(pkey, NULL);
-     if (ctx == NULL) {
-@@ -1635,14 +1488,11 @@ done:
- 
-     rc = CKR_OK;
- done:
--    if (rsa != NULL)
--        RSA_free(rsa);
-     if (pkey != NULL)
-         EVP_PKEY_free(pkey);
-     if (ctx != NULL)
-         EVP_PKEY_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_rsa_encrypt(STDLL_TokData_t *tokdata, CK_BYTE *in_data,
-@@ -2407,48 +2257,6 @@ CK_RV token_specific_aes_ecb(STDLL_TokData_t *tokdata,
-                              CK_ULONG *out_data_len,
-                              OBJECT *key, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    AES_KEY ssl_aes_key;
--    unsigned int i;
--    CK_ATTRIBUTE *attr = NULL;
--    /* There's a previous check that in_data_len % AES_BLOCK_SIZE == 0,
--     * so this is fine */
--    CK_ULONG loops = (CK_ULONG) (in_data_len / AES_BLOCK_SIZE);
--    CK_RV rc;
--
--    UNUSED(tokdata);
--
--    memset(&ssl_aes_key, 0, sizeof(AES_KEY));
--
--    // get key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--    // AES_ecb_encrypt encrypts only a single block, so we have to break up the
--    // input data here
--    if (encrypt) {
--        AES_set_encrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        for (i = 0; i < loops; i++) {
--            AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE),
--                            (unsigned char *) out_data + (i * AES_BLOCK_SIZE),
--                            &ssl_aes_key, AES_ENCRYPT);
--        }
--    } else {
--        AES_set_decrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        for (i = 0; i < loops; i++) {
--            AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE),
--                            (unsigned char *) out_data + (i * AES_BLOCK_SIZE),
--                            &ssl_aes_key, AES_DECRYPT);
--        }
--    }
--    *out_data_len = in_data_len;
--
--    return CKR_OK;
--#else
-     CK_RV rc;
-     int outlen;
-     unsigned char akey[32];
-@@ -2505,7 +2313,6 @@ done:
-     OPENSSL_cleanse(akey, sizeof(akey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata,
-@@ -2515,38 +2322,6 @@ CK_RV token_specific_aes_cbc(STDLL_TokData_t *tokdata,
-                              CK_ULONG *out_data_len,
-                              OBJECT *key, CK_BYTE *init_v, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    AES_KEY ssl_aes_key;
--    CK_ATTRIBUTE *attr = NULL;
--    CK_RV rc;
--
--    UNUSED(tokdata);
--
--    memset(&ssl_aes_key, 0, sizeof(AES_KEY));
--
--    // get key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--    // AES_cbc_encrypt chunks the data into AES_BLOCK_SIZE blocks, unlike
--    // AES_ecb_encrypt, so no looping required.
--    if (encrypt) {
--        AES_set_encrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data,
--                        in_data_len, &ssl_aes_key, init_v, AES_ENCRYPT);
--    } else {
--        AES_set_decrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data,
--                        in_data_len, &ssl_aes_key, init_v, AES_DECRYPT);
--    }
--    *out_data_len = in_data_len;
--
--    return CKR_OK;
--#else
-     CK_RV rc;
-     int outlen;
-     unsigned char akey[32];
-@@ -2603,7 +2378,6 @@ done:
-     OPENSSL_cleanse(akey, sizeof(akey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_aes_mac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-@@ -2716,275 +2490,145 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata,
-                                           TEMPLATE *publ_tmpl,
-                                           TEMPLATE *priv_tmpl)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
-     CK_RV rv;
-     CK_BBOOL rc;
-     CK_ATTRIBUTE *prime_attr = NULL;
-     CK_ATTRIBUTE *base_attr = NULL;
-     CK_ATTRIBUTE *temp_attr = NULL;
-     CK_ATTRIBUTE *value_bits_attr = NULL;
--    CK_BYTE *temp_byte;
-+    CK_BYTE *temp_byte = NULL, *temp_byte2 = NULL;
-     CK_ULONG temp_bn_len;
--    DH *dh;
--    BIGNUM *bn_p;
--    BIGNUM *bn_g;
--    const BIGNUM *temp_bn;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    DH *dh = NULL;
-+#else
-+    EVP_PKEY_CTX *pctx = NULL;
-+    OSSL_PARAM_BLD *tmpl = NULL;
-+    OSSL_PARAM *osparams = NULL;
-+#endif
-+    BIGNUM *bn_p = NULL;
-+    BIGNUM *bn_g = NULL;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    const BIGNUM *temp_bn = NULL;
-+#else
-+    BIGNUM *temp_bn = NULL;
-+#endif
-+    EVP_PKEY *params = NULL, *pkey = NULL;
-+    EVP_PKEY_CTX *ctx = NULL;
- 
-     UNUSED(tokdata);
- 
-     rv = template_attribute_get_non_empty(publ_tmpl, CKA_PRIME, &prime_attr);
-     if (rv != CKR_OK) {
-         TRACE_ERROR("Could not find CKA_PRIME for the key.\n");
--        return rv;
-+        goto done;
-     }
-     rv = template_attribute_get_non_empty(publ_tmpl, CKA_BASE, &base_attr);
-     if (rv != CKR_OK) {
-         TRACE_ERROR("Could not find CKA_BASE for the key.\n");
--        return rv;
-+        goto done;
-     }
- 
-     if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) {
-         TRACE_ERROR("CKA_PRIME attribute value is invalid.\n");
--        return CKR_ATTRIBUTE_VALUE_INVALID;
-+        rv = CKR_ATTRIBUTE_VALUE_INVALID;
-+        goto done;
-     }
- 
--    dh = DH_new();
--    if (dh == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        return CKR_FUNCTION_FAILED;
--    }
--    // Create and init BIGNUM structs to stick in the DH struct
-+    // Create and init BIGNUM structs
-     bn_p = BN_new();
-     bn_g = BN_new();
-     if (bn_g == NULL || bn_p == NULL) {
--        if (bn_g)
--            BN_free(bn_g);
--        if (bn_p)
--            BN_free(bn_p);
-         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        return CKR_HOST_MEMORY;
-+        rv = CKR_HOST_MEMORY;
-+        goto done;
-     }
--    // Convert from strings to BIGNUMs and stick them in the DH struct
-+    // Convert from strings to BIGNUMs
-     BN_bin2bn((unsigned char *) prime_attr->pValue, prime_attr->ulValueLen,
-               bn_p);
-     BN_bin2bn((unsigned char *) base_attr->pValue, base_attr->ulValueLen, bn_g);
--    dh->p = bn_p;
--    dh->g = bn_g;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    dh = DH_new();
-+    if (dh == NULL) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rv = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
-+
-+    DH_set0_pqg(dh, bn_p, NULL, bn_g);
-+    /* bn_p and bn_q freed together with dh */
-+    bn_p = NULL;
-+    bn_g = NULL;
-+
-+    params = EVP_PKEY_new();
-+    if (params == NULL) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-+        rv = CKR_HOST_MEMORY;
-+        goto done;
-+    }
- 
--    // Generate the DH Key
--    if (!DH_generate_key(dh)) {
-+    if (EVP_PKEY_assign_DH(params, dh) != 1) {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        DH_free(dh);
--        return CKR_FUNCTION_FAILED;
-+        rv = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
-+    dh = NULL; /* freed together with params */
-+#else
-+    tmpl = OSSL_PARAM_BLD_new();
-+    if (tmpl == NULL)
-+        goto done;
-+
-+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, bn_p) ||
-+        !OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, bn_g))
-+        goto done;
-+
-+    osparams = OSSL_PARAM_BLD_to_param(tmpl);
-+    if (osparams == NULL)
-+        goto done;
-+
-+    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL);
-+    if (pctx == NULL)
-+        goto done;
-+
-+    if (!EVP_PKEY_fromdata_init(pctx) ||
-+        !EVP_PKEY_fromdata(pctx, &params, EVP_PKEY_PUBLIC_KEY, osparams))
-+        goto done;
-+#endif
-+
-+    ctx = EVP_PKEY_CTX_new(params, NULL);
-+    if (ctx == NULL) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-+        rv = CKR_HOST_MEMORY;
-+        goto done;
-+    }
-+
-+    if (EVP_PKEY_keygen_init(ctx) != 1
-+        || EVP_PKEY_keygen(ctx, &pkey) != 1
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+        /* dh is freed together with pkey */
-+        || (dh = (DH *)EVP_PKEY_get0_DH(pkey)) == NULL) {
-+#else
-+        ) {
-+#endif
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rv = CKR_FUNCTION_FAILED;
-+        goto done;
-     }
-+
-     // Extract the public and private key components from the DH struct,
-     // and insert them in the publ_tmpl and priv_tmpl
- 
-     //
-     // pub_key
-     //
--    //temp_bn = BN_new();
--    temp_bn = dh->pub_key;
--    temp_bn_len = BN_num_bytes(temp_bn);
--    temp_byte = malloc(temp_bn_len);
--    temp_bn_len = BN_bn2bin(temp_bn, temp_byte);
--    // in bytes
--    rc = build_attribute(CKA_VALUE, temp_byte, temp_bn_len, &temp_attr);
--    if (rc != CKR_OK) {
--        TRACE_DEVEL("build_attribute failed\n");
--        DH_free(dh);
--        free(temp_byte);
--        return CKR_FUNCTION_FAILED;
--    }
--    rc = template_update_attribute(publ_tmpl, temp_attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("template_update_attribute failed\n");
--        free(temp_attr);
--        DH_free(dh);
--        free(temp_byte);
--        return rc;
--    }
--    free(temp_byte);
--
--    //
--    // priv_key
--    //
--    //temp_bn = BN_new();
--    temp_bn = dh->priv_key;
--    temp_bn_len = BN_num_bytes(temp_bn);
--    temp_byte = malloc(temp_bn_len);
--    temp_bn_len = BN_bn2bin(temp_bn, temp_byte);
--    // in bytes
--    rc = build_attribute(CKA_VALUE, temp_byte, temp_bn_len, &temp_attr);
--    if (rc != CKR_OK) {
--        TRACE_DEVEL("build_attribute failed\n");
--        DH_free(dh);
--        free(temp_byte);
--        return CKR_FUNCTION_FAILED;
--    }
--    rc = template_update_attribute(priv_tmpl, temp_attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("template_update_attribute failed\n");
--        free(temp_attr);
--        DH_free(dh);
--        free(temp_byte);
--        return rc;
--    }
--    free(temp_byte);
--
--    // Update CKA_VALUE_BITS attribute in the private key
--    value_bits_attr =
--        (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
--    if (value_bits_attr == NULL) {
--        TRACE_ERROR("malloc failed\n");
--        DH_free(dh);
--        return CKR_HOST_MEMORY;
--    }
--    value_bits_attr->type = CKA_VALUE_BITS;
--    value_bits_attr->ulValueLen = sizeof(CK_ULONG);
--    value_bits_attr->pValue =
--        (CK_BYTE *) value_bits_attr + sizeof(CK_ATTRIBUTE);
--    *(CK_ULONG *) value_bits_attr->pValue = 8 * temp_bn_len;
--    rc = template_update_attribute(priv_tmpl, value_bits_attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("template_update_attribute failed\n");
--        free(value_bits_attr);
--        DH_free(dh);
--        return rc;
--    }
--
--    // Add prime and base to the private key template
--    rc = build_attribute(CKA_PRIME,
--                         (unsigned char *) prime_attr->pValue,
--                         prime_attr->ulValueLen, &temp_attr);  // in bytes
--    if (rc != CKR_OK) {
--        TRACE_DEVEL("build_attribute failed\n");
--        DH_free(dh);
--        return CKR_FUNCTION_FAILED;
--    }
--    rc = template_update_attribute(priv_tmpl, temp_attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("template_update_attribute failed\n");
--        free(temp_attr);
--        DH_free(dh);
--        return rc;
--    }
--
--    rc = build_attribute(CKA_BASE,
--                         (unsigned char *) base_attr->pValue,
--                         base_attr->ulValueLen, &temp_attr);     // in bytes
--    if (rc != CKR_OK) {
--        TRACE_DEVEL("build_attribute failed\n");
--        DH_free(dh);
--        return CKR_FUNCTION_FAILED;
--    }
--    rc = template_update_attribute(priv_tmpl, temp_attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("template_update_attribute failed\n");
--        free(temp_attr);
--        DH_free(dh);
--        return rc;
--    }
--
--    // Cleanup DH key
--    DH_free(dh);
--
--    return CKR_OK;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    DH_get0_key(dh, &temp_bn, NULL);
- #else
--    CK_RV rv;
--    CK_BBOOL rc;
--    CK_ATTRIBUTE *prime_attr = NULL;
--    CK_ATTRIBUTE *base_attr = NULL;
--    CK_ATTRIBUTE *temp_attr = NULL;
--    CK_ATTRIBUTE *value_bits_attr = NULL;
--    CK_BYTE *temp_byte = NULL, *temp_byte2 = NULL;
--    CK_ULONG temp_bn_len;
--    DH *dh = NULL;
--    BIGNUM *bn_p = NULL;
--    BIGNUM *bn_g = NULL;
--    const BIGNUM *temp_bn = NULL;
--    EVP_PKEY *params = NULL, *pkey = NULL;
--    EVP_PKEY_CTX *ctx = NULL;
--
--    UNUSED(tokdata);
--
--    rv = template_attribute_get_non_empty(publ_tmpl, CKA_PRIME, &prime_attr);
--    if (rv != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_PRIME for the key.\n");
--        goto done;
--    }
--    rv = template_attribute_get_non_empty(publ_tmpl, CKA_BASE, &base_attr);
--    if (rv != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_BASE for the key.\n");
--        goto done;
--    }
--
--    if ((prime_attr->ulValueLen > 256) || (prime_attr->ulValueLen < 64)) {
--        TRACE_ERROR("CKA_PRIME attribute value is invalid.\n");
--        rv = CKR_ATTRIBUTE_VALUE_INVALID;
--        goto done;
--    }
--
--    dh = DH_new();
--    if (dh == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rv = CKR_FUNCTION_FAILED;
--        goto done;
--    }
--    // Create and init BIGNUM structs to stick in the DH struct
--    bn_p = BN_new();
--    bn_g = BN_new();
--    if (bn_g == NULL || bn_p == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        rv = CKR_HOST_MEMORY;
--        goto done;
--    }
--    // Convert from strings to BIGNUMs and stick them in the DH struct
--    BN_bin2bn((unsigned char *) prime_attr->pValue, prime_attr->ulValueLen,
--              bn_p);
--    BN_bin2bn((unsigned char *) base_attr->pValue, base_attr->ulValueLen, bn_g);
--    DH_set0_pqg(dh, bn_p, NULL, bn_g);
--    /* bn_p and bn_q freed together with dh */
--    bn_p = NULL;
--    bn_g = NULL;
--
--    params = EVP_PKEY_new();
--    if (params == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        rv = CKR_HOST_MEMORY;
--        goto done;
--    }
--
--    if (EVP_PKEY_assign_DH(params, dh) != 1) {
--        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rv = CKR_FUNCTION_FAILED;
--        goto done;
--    }
--    dh = NULL; /* freed together with params */
--
--    ctx = EVP_PKEY_CTX_new(params, NULL);
--    if (ctx == NULL) {
--        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        rv = CKR_HOST_MEMORY;
--        goto done;
--    }
--
--    if (EVP_PKEY_keygen_init(ctx) != 1
--        || EVP_PKEY_keygen(ctx, &pkey) != 1
--        /* dh is freed together with pkey */
--        || (dh = EVP_PKEY_get0_DH(pkey)) == NULL) {
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &temp_bn)) {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
--        rv = CKR_FUNCTION_FAILED;
-+        rc = CKR_FUNCTION_FAILED;
-         goto done;
-     }
--
--    // Extract the public and private key components from the DH struct,
--    // and insert them in the publ_tmpl and priv_tmpl
--
--    //
--    // pub_key
--    //
--    DH_get0_key(dh, &temp_bn, NULL);
-+#endif
- 
-     temp_bn_len = BN_num_bytes(temp_bn);
-     temp_byte = malloc(temp_bn_len);
-@@ -3001,11 +2645,23 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata,
-         free(temp_attr);
-         goto done;
-     }
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(temp_bn);
-+    temp_bn = NULL;
-+#endif
- 
-     //
-     // priv_key
-     //
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     DH_get0_key(dh, NULL, &temp_bn);
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &temp_bn)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        rc = CKR_FUNCTION_FAILED;
-+        goto done;
-+    }
-+#endif
-     temp_bn_len = BN_num_bytes(temp_bn);
-     temp_byte2 = malloc(temp_bn_len);
-     temp_bn_len = BN_bn2bin(temp_bn, temp_byte2);
-@@ -3022,6 +2678,10 @@ CK_RV token_specific_dh_pkcs_key_pair_gen(STDLL_TokData_t *tokdata,
-         free(temp_attr);
-         goto done;
-     }
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    BN_free(temp_bn);
-+    temp_bn = NULL;
-+#endif
- 
-     // Update CKA_VALUE_BITS attribute in the private key
-     value_bits_attr =
-@@ -3086,8 +2746,17 @@ done:
-         EVP_PKEY_free(params);
-     free(temp_byte);
-     free(temp_byte2);
--    return rv;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    if (pctx != NULL)
-+        EVP_PKEY_CTX_free(pctx);
-+    if (tmpl != NULL)
-+        OSSL_PARAM_BLD_free(tmpl);
-+    if (osparams != NULL)
-+        OSSL_PARAM_free(osparams);
-+    if (temp_bn != NULL)
-+        BN_free(temp_bn);
- #endif
-+    return rv;
- }                               /* end token_specific_dh_key_pair_gen() */
- #endif
- /* End code contributed by Corrent corp. */
-@@ -3106,11 +2775,6 @@ CK_RV token_specific_get_mechanism_info(STDLL_TokData_t *tokdata,
-     return ock_generic_get_mechanism_info(tokdata, type, pInfo);
- }
- 
--#ifdef OLDER_OPENSSL
--#define EVP_MD_meth_get_app_datasize(md)        md->ctx_size
--#define EVP_MD_CTX_md_data(ctx)                 ctx->md_data
--#endif
--
- static const EVP_MD *md_from_mech(CK_MECHANISM *mech)
- {
-     const EVP_MD *md = NULL;
-@@ -3168,16 +2832,13 @@ static const EVP_MD *md_from_mech(CK_MECHANISM *mech)
-     return md;
- }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
- static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx)
- {
-     const EVP_MD *md;
-     EVP_MD_CTX *md_ctx;
- 
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    md_ctx = EVP_MD_CTX_create();
--#else
-     md_ctx = EVP_MD_CTX_new();
--#endif
-     if (md_ctx == NULL)
-         return NULL;
- 
-@@ -3185,11 +2846,7 @@ static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx)
-     if (md == NULL ||
-         !EVP_DigestInit_ex(md_ctx, md, NULL)) {
-         TRACE_ERROR("md_from_mech or EVP_DigestInit_ex failed\n");
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--        EVP_MD_CTX_destroy(md_ctx);
--#else
-         EVP_MD_CTX_free(md_ctx);
--#endif
-         return NULL;
-     }
- 
-@@ -3198,11 +2855,7 @@ static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx)
-         ctx->context = malloc(ctx->context_len);
-         if (ctx->context == NULL) {
-             TRACE_ERROR("malloc failed\n");
--    #if OPENSSL_VERSION_NUMBER < 0x10101000L
--            EVP_MD_CTX_destroy(md_ctx);
--    #else
-             EVP_MD_CTX_free(md_ctx);
--    #endif
-             ctx->context_len = 0;
-             return NULL;
-         }
-@@ -3221,27 +2874,60 @@ static EVP_MD_CTX *md_ctx_from_context(DIGEST_CONTEXT *ctx)
- 
-     return md_ctx;
- }
-+#endif
-+
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+static void token_specific_sha_free(STDLL_TokData_t *tokdata, SESSION *sess,
-+                                    CK_BYTE *context, CK_ULONG context_len)
-+{
-+    UNUSED(tokdata);
-+    UNUSED(sess);
-+    UNUSED(context_len);
-+
-+    EVP_MD_CTX_free((EVP_MD_CTX *)context);
-+}
-+#endif
- 
- CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-                               CK_MECHANISM *mech)
- {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     EVP_MD_CTX *md_ctx;
-+#else
-+    const EVP_MD *md;
-+#endif
- 
-     UNUSED(tokdata);
- 
-     ctx->mech.ulParameterLen = mech->ulParameterLen;
-     ctx->mech.mechanism = mech->mechanism;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     md_ctx = md_ctx_from_context(ctx);
-     if (md_ctx == NULL) {
-         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-         return CKR_HOST_MEMORY;
-     }
- 
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    EVP_MD_CTX_destroy(md_ctx);
--#else
-     EVP_MD_CTX_free(md_ctx);
-+#else
-+    ctx->context_len = 1;
-+    ctx->context = (CK_BYTE *)EVP_MD_CTX_new();
-+    if (ctx->context == NULL) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-+        return CKR_HOST_MEMORY;
-+    }
-+
-+    md = md_from_mech(&ctx->mech);
-+    if (md == NULL ||
-+        !EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, md, NULL)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-+    ctx->state_unsaveable = CK_TRUE;
-+    ctx->context_free_func = token_specific_sha_free;
- #endif
- 
-     return CKR_OK;
-@@ -3253,7 +2939,9 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
- {
-     unsigned int len;
-     CK_RV rc = CKR_OK;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     EVP_MD_CTX *md_ctx;
-+#endif
- 
-     UNUSED(tokdata);
- 
-@@ -3263,6 +2951,7 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-     if (!in_data || !out_data)
-         return CKR_ARGUMENTS_BAD;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     /* Recreate the OpenSSL MD context from the saved context */
-     md_ctx = md_ctx_from_context(ctx);
-     if (md_ctx == NULL) {
-@@ -3275,21 +2964,38 @@ CK_RV token_specific_sha(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
- 
-     if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len) ||
-         !EVP_DigestFinal(md_ctx, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         rc = CKR_FUNCTION_FAILED;
-         goto out;
-     }
- 
-     *out_data_len = len;
-+#else
-+    if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
-+        return CKR_BUFFER_TOO_SMALL;
-+    }
-+
-+    len = *out_data_len;
-+    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) ||
-+        !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-+    *out_data_len = len;
-+#endif
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
- out:
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    EVP_MD_CTX_destroy(md_ctx);
--#else
-     EVP_MD_CTX_free(md_ctx);
--#endif
-     free(ctx->context);
-+#else
-+    EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-+#endif
-     ctx->context = NULL;
-     ctx->context_len = 0;
-+    ctx->context_free_func = NULL;
- 
-     return rc;
- }
-@@ -3297,7 +3003,9 @@ out:
- CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-                                 CK_BYTE *in_data, CK_ULONG in_data_len)
- {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     EVP_MD_CTX *md_ctx;
-+#endif
- 
-     UNUSED(tokdata);
- 
-@@ -3307,6 +3015,7 @@ CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-     if (!in_data)
-         return CKR_ARGUMENTS_BAD;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     /* Recreate the OpenSSL MD context from the saved context */
-     md_ctx = md_ctx_from_context(ctx);
-     if (md_ctx == NULL) {
-@@ -3315,24 +3024,24 @@ CK_RV token_specific_sha_update(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-     }
- 
-     if (!EVP_DigestUpdate(md_ctx, in_data, in_data_len)) {
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--        EVP_MD_CTX_destroy(md_ctx);
--#else
-         EVP_MD_CTX_free(md_ctx);
--#endif
-         free(ctx->context);
-         ctx->context = NULL;
-         ctx->context_len = 0;
-+        ctx->context_free_func = NULL;
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-         return CKR_FUNCTION_FAILED;
-     }
- 
-     /* Save context data for later use */
-     memcpy(ctx->context,  EVP_MD_CTX_md_data(md_ctx), ctx->context_len);
- 
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    EVP_MD_CTX_destroy(md_ctx);
--#else
-     EVP_MD_CTX_free(md_ctx);
-+#else
-+    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
- #endif
- 
-     return CKR_OK;
-@@ -3343,7 +3052,9 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
- {
-     unsigned int len;
-     CK_RV rc = CKR_OK;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     EVP_MD_CTX *md_ctx;
-+#endif
- 
-     UNUSED(tokdata);
- 
-@@ -3353,6 +3064,7 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-     if (!out_data)
-         return CKR_ARGUMENTS_BAD;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     /* Recreate the OpenSSL MD context from the saved context */
-     md_ctx = md_ctx_from_context(ctx);
-     if (md_ctx == NULL) {
-@@ -3370,14 +3082,30 @@ CK_RV token_specific_sha_final(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-     *out_data_len = len;
- 
- out:
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    EVP_MD_CTX_destroy(md_ctx);
--#else
-     EVP_MD_CTX_free(md_ctx);
--#endif
-     free(ctx->context);
-     ctx->context = NULL;
-     ctx->context_len = 0;
-+    ctx->context_free_func = NULL;
-+#else
-+    if (*out_data_len < (CK_ULONG)EVP_MD_CTX_size((EVP_MD_CTX *)ctx->context)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
-+        return CKR_BUFFER_TOO_SMALL;
-+    }
-+
-+    len = *out_data_len;
-+    if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-+    *out_data_len = len;
-+
-+    EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-+    ctx->context = NULL;
-+    ctx->context_len = 0;
-+    ctx->context_free_func = NULL;
-+#endif
- 
-     return rc;
- }
-@@ -3897,99 +3625,26 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-                                CK_ULONG message_len, OBJECT *key, CK_BYTE *mac,
-                                CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
-     int rc;
--    CK_RV rv = CKR_OK;
--    CK_ATTRIBUTE *attr = NULL;
--    CK_KEY_TYPE keytype;
--    CMAC_CTX *cmac_ctx;
--    const EVP_CIPHER *cipher;
--    size_t maclen;
--
--    UNUSED(tokdata);
--
--    if (first) {
--        // get the key type
--        rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
--        if (rc != CKR_OK) {
--            TRACE_ERROR("Could not find CKA_KEY_TYPE for the key.\n");
--            return CKR_FUNCTION_FAILED;
--        }
--
--        // get the key value
--        rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--        if (rc != CKR_OK) {
--            TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
--            return rc;
--        }
--        switch (keytype) {
--        case CKK_DES2:
--            cipher = EVP_des_ede_cbc();
--            break;
--        case CKK_DES3:
--            cipher = EVP_des_ede3_cbc();
--            break;
--        default:
--            TRACE_ERROR("Invalid key type: %lu\n", keytype);
--            return CKR_KEY_TYPE_INCONSISTENT;
--        }
--        if (cipher == NULL) {
--            TRACE_ERROR("Failed to allocate cipher\n");
--            return CKR_HOST_MEMORY;
--        }
--
--        cmac_ctx = CMAC_CTX_new();
--        if (cmac_ctx == NULL) {
--            TRACE_ERROR("Failed to allocate CMAC context\n");
--            return CKR_HOST_MEMORY;
--        }
--
--        rc = CMAC_Init(cmac_ctx, attr->pValue, attr->ulValueLen, cipher, NULL);
--        if (rc != 1) {
--            TRACE_ERROR("CMAC_Init failed\n");
--            CMAC_CTX_free(cmac_ctx);
--            return CKR_FUNCTION_FAILED;
--        }
--
--        *ctx = cmac_ctx;
--    }
--
--    cmac_ctx = (CMAC_CTX *)*ctx;
--
--    rc = CMAC_Update(cmac_ctx, message, message_len);
--    if (rc != 1) {
--        TRACE_ERROR("CMAC_Update failed\n");
--        rv =  CKR_FUNCTION_FAILED;
--    }
--
--    if (last) {
--        maclen = AES_BLOCK_SIZE;
--        rc = CMAC_Final(cmac_ctx, mac, &maclen);
--        if (rc != 1) {
--            TRACE_ERROR("CMAC_Final failed\n");
--            rv = CKR_FUNCTION_FAILED;
--        }
--    }
--
--    if (last || (first && rv != CKR_OK)) {
--        CMAC_CTX_free(cmac_ctx);
--        *ctx = NULL;
--    }
--
--    return rv;
--#else
--    int rc;
--    size_t maclen;
-+    size_t maclen;
-     CK_RV rv = CKR_OK;
-     CK_ATTRIBUTE *attr = NULL;
-     CK_KEY_TYPE keytype;
-     const EVP_CIPHER *cipher;
-     struct cmac_ctx {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         EVP_MD_CTX *mctx;
-         EVP_PKEY_CTX *pctx;
-         EVP_PKEY *pkey;
-+#else
-+        EVP_MAC *mac;
-+        EVP_MAC_CTX *mctx;
-+#endif
-     };
-     struct cmac_ctx *cmac = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_PARAM params[2];
-+#endif
- 
-     UNUSED(tokdata);
- 
-@@ -4031,10 +3686,11 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-             goto err;
-         }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         cmac->mctx = EVP_MD_CTX_new();
-         if (cmac->mctx == NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--            rv = ERR_HOST_MEMORY;
-+            rv = CKR_HOST_MEMORY;
-             goto err;
-         }
- 
-@@ -4053,6 +3709,31 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-             rv = CKR_FUNCTION_FAILED;
-             goto err;
-         }
-+#else
-+        cmac->mac = EVP_MAC_fetch(NULL, "CMAC", NULL);
-+        if (cmac->mac == NULL) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+            rv = CKR_FUNCTION_FAILED;
-+            goto err;
-+        }
-+
-+        cmac->mctx = EVP_MAC_CTX_new(cmac->mac);
-+        if (cmac->mctx == NULL) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-+            rv = CKR_HOST_MEMORY;
-+            goto err;
-+        }
-+
-+        params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
-+                                      (char *)EVP_CIPHER_get0_name(cipher), 0);
-+        params[1] = OSSL_PARAM_construct_end();
-+
-+        if (!EVP_MAC_init(cmac->mctx, attr->pValue, attr->ulValueLen, params)) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+            rv = CKR_FUNCTION_FAILED;
-+            goto err;
-+        }
-+#endif
- 
-         *ctx = cmac;
-     }
-@@ -4064,9 +3745,17 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-         goto err;
-     }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     rc = EVP_DigestSignUpdate(cmac->mctx, message, message_len);
-+#else
-+    rc = EVP_MAC_update(cmac->mctx, message, message_len);
-+#endif
-     if (rc != 1 || message_len > INT_MAX) {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         TRACE_ERROR("EVP_DigestSignUpdate failed\n");
-+#else
-+        TRACE_ERROR("EVP_MAC_update failed\n");
-+#endif
-         rv =  CKR_FUNCTION_FAILED;
-         goto err;
-     }
-@@ -4074,15 +3763,28 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     if (last) {
-         maclen = AES_BLOCK_SIZE;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         rc = EVP_DigestSignFinal(cmac->mctx, mac, &maclen);
-+#else
-+        rc = EVP_MAC_final(cmac->mctx, mac, &maclen, maclen);
-+#endif
-         if (rc != 1) {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-             TRACE_ERROR("EVP_DigestSignFinal failed\n");
-+#else
-+            TRACE_ERROR("EVP_MAC_final failed\n");
-+#endif
-             rv = CKR_FUNCTION_FAILED;
-             goto err;
-         }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         EVP_MD_CTX_free(cmac->mctx); /* frees pctx */
-         EVP_PKEY_free(cmac->pkey);
-+#else
-+        EVP_MAC_CTX_free(cmac->mctx);
-+        EVP_MAC_free(cmac->mac);
-+#endif
-         free(cmac);
-         *ctx = NULL;
-     }
-@@ -4090,15 +3792,21 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     return CKR_OK;
- err:
-     if (cmac != NULL) {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         if (cmac->mctx != NULL)
-             EVP_MD_CTX_free(cmac->mctx); /* frees pctx */
-         if (cmac->pkey != NULL)
-             EVP_PKEY_free(cmac->pkey);
-+#else
-+        if (cmac->mctx != NULL)
-+            EVP_MAC_CTX_free(cmac->mctx);
-+        if (cmac->mac != NULL)
-+            EVP_MAC_free(cmac->mac);
-+#endif
-         free(cmac);
-     }
-     *ctx = NULL;
-     return rv;
--#endif
- }
- 
- 
-@@ -4106,93 +3814,25 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-                               CK_ULONG message_len, OBJECT *key, CK_BYTE *mac,
-                               CK_BBOOL first, CK_BBOOL last, CK_VOID_PTR *ctx)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    int rc;
--    CK_RV rv = CKR_OK;
--    CK_ATTRIBUTE *attr = NULL;
--    CMAC_CTX *cmac_ctx;
--    const EVP_CIPHER *cipher;
--    size_t maclen;
--
--    UNUSED(tokdata);
--
--    if (first) {
--        rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--        if (rc != CKR_OK) {
--            TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
--            return rc;
--        }
--
--        switch (attr->ulValueLen * 8) {
--        case 128:
--            cipher = EVP_aes_128_cbc();
--            break;
--        case 192:
--            cipher = EVP_aes_192_cbc();
--            break;
--        case 256:
--            cipher = EVP_aes_256_cbc();
--            break;
--        default:
--            TRACE_ERROR("Invalid key size: %lu\n", attr->ulValueLen);
--            return CKR_KEY_TYPE_INCONSISTENT;
--        }
--        if (cipher == NULL) {
--            TRACE_ERROR("Failed to allocate cipher\n");
--            return CKR_HOST_MEMORY;
--        }
--
--        cmac_ctx = CMAC_CTX_new();
--        if (cmac_ctx == NULL) {
--            TRACE_ERROR("Failed to allocate CMAC context\n");
--            return CKR_HOST_MEMORY;
--        }
--
--        rc = CMAC_Init(cmac_ctx, attr->pValue, attr->ulValueLen, cipher, NULL);
--        if (rc != 1) {
--            TRACE_ERROR("CMAC_Init failed\n");
--            CMAC_CTX_free(cmac_ctx);
--            return CKR_FUNCTION_FAILED;
--        }
--
--        *ctx = cmac_ctx;
--    }
--
--    cmac_ctx = (CMAC_CTX *)*ctx;
--
--    rc = CMAC_Update(cmac_ctx, message, message_len);
--    if (rc != 1) {
--        TRACE_ERROR("CMAC_Update failed\n");
--        rv =  CKR_FUNCTION_FAILED;
--    }
--
--    if (last) {
--        maclen = AES_BLOCK_SIZE;
--        rc = CMAC_Final(cmac_ctx, mac, &maclen);
--        if (rc != 1) {
--            TRACE_ERROR("CMAC_Final failed\n");
--            rv = CKR_FUNCTION_FAILED;
--        }
--    }
--
--    if (last || (first && rv != CKR_OK)) {
--        CMAC_CTX_free(cmac_ctx);
--        *ctx = NULL;
--    }
--
--    return rv;
--#else
-     int rc;
-     size_t maclen;
-     CK_RV rv = CKR_OK;
-     CK_ATTRIBUTE *attr = NULL;
-     const EVP_CIPHER *cipher;
-     struct cmac_ctx {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         EVP_MD_CTX *mctx;
-         EVP_PKEY_CTX *pctx;
-         EVP_PKEY *pkey;
-+#else
-+        EVP_MAC *mac;
-+        EVP_MAC_CTX *mctx;
-+#endif
-     };
-     struct cmac_ctx *cmac = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_PARAM params[2];
-+#endif
- 
-     UNUSED(tokdata);
- 
-@@ -4229,6 +3869,7 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-             goto err;
-         }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         cmac->mctx = EVP_MD_CTX_new();
-         if (cmac->mctx == NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-@@ -4251,6 +3892,31 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-             rv = CKR_FUNCTION_FAILED;
-             goto err;
-         }
-+#else
-+        cmac->mac = EVP_MAC_fetch(NULL, "CMAC", NULL);
-+        if (cmac->mac == NULL) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+            rv = CKR_FUNCTION_FAILED;
-+            goto err;
-+        }
-+
-+        cmac->mctx = EVP_MAC_CTX_new(cmac->mac);
-+        if (cmac->mctx == NULL) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-+            rv = CKR_HOST_MEMORY;
-+            goto err;
-+        }
-+
-+        params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
-+                                      (char *)EVP_CIPHER_get0_name(cipher), 0);
-+        params[1] = OSSL_PARAM_construct_end();
-+
-+        if (!EVP_MAC_init(cmac->mctx, attr->pValue, attr->ulValueLen, params)) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+            rv = CKR_FUNCTION_FAILED;
-+            goto err;
-+        }
-+#endif
- 
-         *ctx = cmac;
-     }
-@@ -4262,9 +3928,17 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-         goto err;
-     }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     rc = EVP_DigestSignUpdate(cmac->mctx, message, message_len);
-+#else
-+    rc = EVP_MAC_update(cmac->mctx, message, message_len);
-+#endif
-     if (rc != 1 || message_len > INT_MAX) {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         TRACE_ERROR("EVP_DigestSignUpdate failed\n");
-+#else
-+        TRACE_ERROR("EVP_MAC_update failed\n");
-+#endif
-         rv =  CKR_FUNCTION_FAILED;
-         goto err;
-     }
-@@ -4272,15 +3946,28 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     if (last) {
-         maclen = AES_BLOCK_SIZE;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         rc = EVP_DigestSignFinal(cmac->mctx, mac, &maclen);
-+#else
-+        rc = EVP_MAC_final(cmac->mctx, mac, &maclen, maclen);
-+#endif
-         if (rc != 1) {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-             TRACE_ERROR("EVP_DigestSignFinal failed\n");
-+#else
-+            TRACE_ERROR("EVP_MAC_final failed\n");
-+#endif
-             rv = CKR_FUNCTION_FAILED;
-             goto err;
-         }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         EVP_MD_CTX_free(cmac->mctx); /* frees pctx */
-         EVP_PKEY_free(cmac->pkey);
-+#else
-+        EVP_MAC_CTX_free(cmac->mctx);
-+        EVP_MAC_free(cmac->mac);
-+#endif
-         free(cmac);
-         *ctx = NULL;
-     }
-@@ -4288,37 +3975,90 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     return CKR_OK;
- err:
-     if (cmac != NULL) {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         if (cmac->mctx != NULL)
-             EVP_MD_CTX_free(cmac->mctx); /* frees pctx */
-         if (cmac->pkey != NULL)
-             EVP_PKEY_free(cmac->pkey);
-+#else
-+        if (cmac->mctx != NULL)
-+            EVP_MAC_CTX_free(cmac->mctx);
-+        if (cmac->mac != NULL)
-+            EVP_MAC_free(cmac->mac);
-+#endif
-         free(cmac);
-     }
-     *ctx = NULL;
-     return rv;
--#endif
- }
- 
- #ifndef NO_EC
- 
--static CK_RV make_ec_key_from_params(const CK_BYTE *params, CK_ULONG params_len,
--                                     EC_KEY **key)
-+static int curve_nid_from_params(const CK_BYTE *params, CK_ULONG params_len)
- {
-     const unsigned char *oid;
-     ASN1_OBJECT *obj = NULL;
--    EC_KEY *ec_key = NULL;
-     int nid;
--    CK_RV rc = CKR_OK;
- 
-     oid = params;
-     obj = d2i_ASN1_OBJECT(NULL, &oid, params_len);
-     if (obj == NULL) {
-         TRACE_ERROR("curve not supported by OpenSSL.\n");
--        rc = CKR_CURVE_NOT_SUPPORTED;
--        goto out;
-+        return NID_undef;
-     }
- 
-     nid = OBJ_obj2nid(obj);
-+    ASN1_OBJECT_free(obj);
-+
-+    return nid;
-+}
-+
-+static int ec_prime_len_from_nid(int nid)
-+{
-+    EC_GROUP *group;
-+    int primelen;
-+
-+    group = EC_GROUP_new_by_curve_name(nid);
-+    if (group == NULL)
-+        return -1;
-+
-+    primelen = EC_GROUP_order_bits(group);
-+
-+    EC_GROUP_free(group);
-+
-+    if ((primelen % 8) == 0)
-+        return primelen / 8;
-+    else
-+        return (primelen / 8) + 1;
-+}
-+
-+int ec_prime_len_from_pkey(EVP_PKEY *pkey)
-+{
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    return (EC_GROUP_order_bits(EC_KEY_get0_group(
-+                             EVP_PKEY_get0_EC_KEY(pkey))) + 7) / 8;
-+#else
-+    size_t curve_len;
-+    char curve[80];
-+
-+    if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
-+                                        curve, sizeof(curve), &curve_len))
-+        return -1;
-+
-+    return ec_prime_len_from_nid(OBJ_sn2nid(curve));
-+#endif
-+}
-+
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+static CK_RV make_ec_key_from_params(const CK_BYTE *params, CK_ULONG params_len,
-+                                     EC_KEY **key)
-+{
-+    EC_KEY *ec_key = NULL;
-+    int nid;
-+    CK_RV rc = CKR_OK;
-+
-+    nid = curve_nid_from_params(params, params_len);
-     if (nid == NID_undef) {
-         TRACE_ERROR("curve not supported by OpenSSL.\n");
-         rc = CKR_CURVE_NOT_SUPPORTED;
-@@ -4333,9 +4073,6 @@ static CK_RV make_ec_key_from_params(const CK_BYTE *params, CK_ULONG params_len,
-     }
- 
- out:
--    if (obj != NULL)
--        ASN1_OBJECT_free(obj);
--
-     if (rc != CKR_OK) {
-         if (ec_key != NULL)
-             EC_KEY_free(ec_key);
-@@ -4347,16 +4084,97 @@ out:
- 
-     return CKR_OK;
- }
-+#endif
-+
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+static CK_RV build_pkey_from_params(OSSL_PARAM_BLD *tmpl, int selection,
-+                                    EVP_PKEY **pkey)
-+{
-+
-+    OSSL_PARAM *params = NULL;
-+    EVP_PKEY_CTX *pctx = NULL;
-+    CK_RV rc = CKR_OK;
-+
-+    params = OSSL_PARAM_BLD_to_param(tmpl);
-+    if (params == NULL) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_to_param failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
-+    if (pctx == NULL) {
-+        TRACE_ERROR("EVP_PKEY_CTX_new_id failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (!EVP_PKEY_fromdata_init(pctx) ||
-+        !EVP_PKEY_fromdata(pctx, pkey, selection, params)) {
-+        TRACE_ERROR("EVP_PKEY_fromdata failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    EVP_PKEY_CTX_free(pctx);
-+    pctx = EVP_PKEY_CTX_new(*pkey, NULL);
-+    if (pctx == NULL) {
-+        TRACE_ERROR("EVP_PKEY_CTX_new failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
-+        if (EVP_PKEY_check(pctx) != 1) {
-+            TRACE_ERROR("EVP_PKEY_check failed\n");
-+            rc = CKR_FUNCTION_FAILED;
-+            goto out;
-+        }
-+    } else {
-+        if (EVP_PKEY_public_check(pctx) != 1) {
-+            TRACE_ERROR("EVP_PKEY_public_check failed\n");
-+            rc = CKR_FUNCTION_FAILED;
-+            goto out;
-+        }
-+    }
-+
-+out:
-+    if (pctx != NULL)
-+        EVP_PKEY_CTX_free(pctx);
-+    if (params != NULL)
-+        OSSL_PARAM_free(params);
-+
-+    if (rc != 0 && *pkey != NULL) {
-+        EVP_PKEY_free(*pkey);
-+        *pkey = NULL;
-+    }
-+
-+    return rc;
-+}
-+#endif
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
- static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data,
--                                     CK_ULONG data_len, CK_BBOOL allow_raw)
-+                                     CK_ULONG data_len, CK_BBOOL allow_raw,
-+                                     int nid, EVP_PKEY **ec_pkey)
-+#else
-+static CK_RV fill_ec_key_from_pubkey(OSSL_PARAM_BLD *tmpl, const CK_BYTE *data,
-+                                     CK_ULONG data_len, CK_BBOOL allow_raw,
-+                                     int nid, EVP_PKEY **ec_pkey)
-+#endif
- {
-     CK_BYTE *ecpoint = NULL;
-     CK_ULONG ecpoint_len, privlen;
-     CK_BBOOL allocated = FALSE;
-+
-     CK_RV rc;
- 
--    privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8;
-+    privlen = ec_prime_len_from_nid(nid);
-+    if (privlen <= 0) {
-+        TRACE_ERROR("ec_prime_len_from_nid failed\n");
-+        rc = CKR_CURVE_NOT_SUPPORTED;
-+        goto out;
-+    }
- 
-     rc = ec_point_from_public_data(data, data_len, privlen, allow_raw,
-                                    &allocated, &ecpoint, &ecpoint_len);
-@@ -4365,6 +4183,7 @@ static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data,
-         goto out;
-     }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     if (!EC_KEY_oct2key(ec_key, ecpoint, ecpoint_len, NULL)) {
-         TRACE_ERROR("EC_KEY_oct2key failed\n");
-         rc = CKR_FUNCTION_FAILED;
-@@ -4377,6 +4196,34 @@ static CK_RV fill_ec_key_from_pubkey(EC_KEY *ec_key, const CK_BYTE *data,
-         goto out;
-     }
- 
-+    *ec_pkey = EVP_PKEY_new();
-+    if (*ec_pkey == NULL) {
-+       TRACE_ERROR("EVP_PKEY_CTX_new failed.\n");
-+       rc = CKR_HOST_MEMORY;
-+       goto out;
-+    }
-+
-+    if (!EVP_PKEY_assign_EC_KEY(*ec_pkey, ec_key)) {
-+        TRACE_ERROR("EVP_PKEY_assign_EC_KEY failed.\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+#else
-+    if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
-+                                          OSSL_PKEY_PARAM_PUB_KEY,
-+                                          ecpoint, ecpoint_len)) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_push_octet_string failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    rc = build_pkey_from_params(tmpl, EVP_PKEY_PUBLIC_KEY, ec_pkey);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("build_pkey_from_params failed\n");
-+        goto out;
-+    }
-+ #endif
-+
- out:
-     if (allocated && ecpoint != NULL)
-         free(ecpoint);
-@@ -4384,12 +4231,26 @@ out:
-     return rc;
- }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
- static CK_RV fill_ec_key_from_privkey(EC_KEY *ec_key, const CK_BYTE *data,
--                                      CK_ULONG data_len)
-+                                      CK_ULONG data_len, EVP_PKEY **ec_pkey)
-+#else
-+static CK_RV fill_ec_key_from_privkey(OSSL_PARAM_BLD *tmpl, const CK_BYTE *data,
-+                                      CK_ULONG data_len, int nid,
-+                                      EVP_PKEY **ec_pkey)
-+#endif
- {
-     EC_POINT *point = NULL;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    EC_GROUP *group = NULL;
-+    BIGNUM *bn_priv = NULL;
-+    unsigned char *pub_key = NULL;
-+    unsigned int pub_key_len;
-+    point_conversion_form_t form;
-+#endif
-     CK_RV rc = CKR_OK;
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     if (!EC_KEY_oct2priv(ec_key, data, data_len)) {
-         TRACE_ERROR("EC_KEY_oct2priv failed\n");
-         rc = CKR_FUNCTION_FAILED;
-@@ -4422,18 +4283,102 @@ static CK_RV fill_ec_key_from_privkey(EC_KEY *ec_key, const CK_BYTE *data,
-         goto out;
-     }
- 
-+    *ec_pkey = EVP_PKEY_new();
-+    if (*ec_pkey == NULL) {
-+       TRACE_ERROR("EVP_PKEY_CTX_new failed.\n");
-+       rc = CKR_HOST_MEMORY;
-+       goto out;
-+    }
-+
-+    if (!EVP_PKEY_assign_EC_KEY(*ec_pkey, ec_key)) {
-+        TRACE_ERROR("EVP_PKEY_assign_EC_KEY failed.\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+#else
-+    group = EC_GROUP_new_by_curve_name(nid);
-+    if (group == NULL) {
-+        TRACE_ERROR("EC_GROUP_new_by_curve_name failed\n");
-+        rc = CKR_CURVE_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+    point = EC_POINT_new(group);
-+    if (point == NULL) {
-+        TRACE_ERROR("EC_POINT_new failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    bn_priv = BN_bin2bn(data, data_len, NULL);
-+    if (bn_priv == NULL) {
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (!EC_POINT_mul(group, point, bn_priv, NULL, NULL, NULL)) {
-+        TRACE_ERROR("EC_POINT_mul failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    form = EC_GROUP_get_point_conversion_form(group);
-+    pub_key_len = EC_POINT_point2buf(group, point, form, &pub_key,
-+                                     NULL);
-+    if (pub_key_len == 0) {
-+        TRACE_ERROR("EC_POINT_point2buf failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
-+                                          pub_key, pub_key_len)) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_push_octet_string failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (!OSSL_PARAM_BLD_push_BN(tmpl, OSSL_PKEY_PARAM_PRIV_KEY, bn_priv)) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_push_BN failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    rc = build_pkey_from_params(tmpl, EVP_PKEY_KEYPAIR, ec_pkey);
-+    if (rc != CKR_OK) {
-+        TRACE_ERROR("build_pkey_from_params failed\n");
-+        goto out;
-+    }
-+#endif
-+
- out:
-     if (point != NULL)
-         EC_POINT_free(point);
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    if (group != NULL)
-+        EC_GROUP_free(group);
-+    if (bn_priv != NULL)
-+        BN_free(bn_priv);
-+    if (pub_key != NULL)
-+        OPENSSL_free(pub_key);
-+#endif
- 
-     return rc;
- }
- 
--static CK_RV make_ec_key_from_template(TEMPLATE *template, EC_KEY **key)
-+
-+
-+static CK_RV make_ec_key_from_template(TEMPLATE *template, EVP_PKEY **pkey)
- {
-     CK_ATTRIBUTE *attr = NULL;
-     CK_OBJECT_CLASS keyclass;
-+    EVP_PKEY *ec_pkey = NULL;
-+    int nid;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     EC_KEY *ec_key = NULL;
-+#else
-+    OSSL_PARAM_BLD *tmpl = NULL;
-+#endif
-     CK_RV rc;
- 
-     rc = template_attribute_get_ulong(template, CKA_CLASS, &keyclass);
-@@ -4448,9 +4393,32 @@ static CK_RV make_ec_key_from_template(TEMPLATE *template, EC_KEY **key)
-         goto out;
-     }
- 
-+    nid = curve_nid_from_params(attr->pValue, attr->ulValueLen);
-+    if (nid == NID_undef) {
-+        TRACE_ERROR("curve not supported by OpenSSL.\n");
-+        rc = CKR_CURVE_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     rc = make_ec_key_from_params(attr->pValue, attr->ulValueLen, &ec_key);
-     if (rc != CKR_OK)
-         goto out;
-+#else
-+    tmpl = OSSL_PARAM_BLD_new();
-+    if (tmpl == NULL) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_new failed\n");
-+        rc = CKR_HOST_MEMORY;
-+        goto out;
-+    }
-+
-+    if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME,
-+                                         OBJ_nid2sn(nid), 0)) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_push_utf8_string failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+#endif
- 
-     switch (keyclass) {
-     case CKO_PUBLIC_KEY:
-@@ -4460,8 +4428,13 @@ static CK_RV make_ec_key_from_template(TEMPLATE *template, EC_KEY **key)
-             goto out;
-         }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         rc = fill_ec_key_from_pubkey(ec_key, attr->pValue, attr->ulValueLen,
--                                     FALSE);
-+                                     FALSE, nid, &ec_pkey);
-+#else
-+        rc = fill_ec_key_from_pubkey(tmpl, attr->pValue, attr->ulValueLen,
-+                                     FALSE, nid, &ec_pkey);
-+#endif
-         if (rc != CKR_OK) {
-             TRACE_DEVEL("fill_ec_key_from_pubkey failed\n");
-             goto out;
-@@ -4475,7 +4448,14 @@ static CK_RV make_ec_key_from_template(TEMPLATE *template, EC_KEY **key)
-             goto out;
-         }
- 
--        rc = fill_ec_key_from_privkey(ec_key, attr->pValue, attr->ulValueLen);
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+        rc = fill_ec_key_from_privkey(ec_key, attr->pValue, attr->ulValueLen,
-+                                      &ec_pkey);
-+#else
-+        rc = fill_ec_key_from_privkey(tmpl, attr->pValue, attr->ulValueLen,
-+                                      nid, &ec_pkey);
-+
-+#endif
-         if (rc != CKR_OK) {
-             TRACE_DEVEL("fill_ec_key_from_privkey failed\n");
-             goto out;
-@@ -4487,17 +4467,30 @@ static CK_RV make_ec_key_from_template(TEMPLATE *template, EC_KEY **key)
-         goto out;
-     }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    ec_key = NULL;
-+#endif
-+
-     rc = CKR_OK;
- 
- out:
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    if (tmpl != NULL)
-+        OSSL_PARAM_BLD_free(tmpl);
-+#endif
-+
-     if (rc != CKR_OK) {
-+        if (ec_pkey != NULL)
-+            EVP_PKEY_free(ec_pkey);
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         if (ec_key != NULL)
-             EC_KEY_free(ec_key);
-+#endif
- 
-         return rc;
-     }
- 
--    *key = ec_key;
-+    *pkey = ec_pkey;
- 
-     return CKR_OK;
- }
-@@ -4508,10 +4501,17 @@ CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata,
- {
- 
-     CK_ATTRIBUTE *attr = NULL, *ec_point_attr, *value_attr, *parms_attr;
--    EC_KEY *ec_key = NULL;
--    BN_CTX *ctx = NULL;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    const EC_KEY *ec_key = NULL;
-+    BN_CTX *bnctx = NULL;
-+#else
-+    BIGNUM *bn_d = NULL;
-+#endif
-     CK_BYTE *ecpoint = NULL, *enc_ecpoint = NULL, *d = NULL;
-     CK_ULONG ecpoint_len, enc_ecpoint_len, d_len;
-+    EVP_PKEY_CTX *ctx = NULL;
-+    EVP_PKEY *ec_pkey = NULL;
-+    int nid;
-     CK_RV rc;
- 
-     UNUSED(tokdata);
-@@ -4520,29 +4520,83 @@ CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata,
-     if (rc != CKR_OK)
-         goto out;
- 
--    rc = make_ec_key_from_params(attr->pValue, attr->ulValueLen, &ec_key);
--    if (rc != CKR_OK)
-+    nid = curve_nid_from_params(attr->pValue, attr->ulValueLen);
-+    if (nid == NID_undef) {
-+        TRACE_ERROR("curve not supported by OpenSSL.\n");
-+        rc = CKR_CURVE_NOT_SUPPORTED;
-         goto out;
-+    }
- 
--    if (!EC_KEY_generate_key(ec_key)) {
--        TRACE_ERROR("Failed to generate an EC key.\n");
-+    ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
-+    if (ctx == NULL) {
-+        TRACE_ERROR("EVP_PKEY_CTX_new failed\n");
-         rc = CKR_FUNCTION_FAILED;
-         goto out;
-     }
- 
--    ctx = BN_CTX_new();
--    if (ctx == NULL) {
-+    if (EVP_PKEY_keygen_init(ctx) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_keygen_init failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_CTX_set_ec_paramgen_curve_nid failed\n");
-+        rc = CKR_CURVE_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+    if (EVP_PKEY_keygen(ctx, &ec_pkey) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_keygen failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    ec_key = EVP_PKEY_get0_EC_KEY(ec_pkey);
-+    if (ec_key == NULL) {
-+       TRACE_ERROR("EVP_PKEY_get0_EC_KEY failed\n");
-+       rc = CKR_FUNCTION_FAILED;
-+       goto out;
-+   }
-+
-+    bnctx = BN_CTX_new();
-+    if (bnctx == NULL) {
-         rc = CKR_HOST_MEMORY;
-         goto out;
-     }
- 
-     ecpoint_len = EC_KEY_key2buf(ec_key, POINT_CONVERSION_UNCOMPRESSED,
--                                 &ecpoint, ctx);
-+                                 &ecpoint, bnctx);
-     if (ecpoint_len == 0) {
-         TRACE_ERROR("Failed to get the EC Point compressed.\n");
-         rc = CKR_FUNCTION_FAILED;
-         goto out;
-     }
-+#else
-+    if (!EVP_PKEY_get_octet_string_param(ec_pkey,
-+                                         OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
-+                                         NULL, 0, &ecpoint_len)) {
-+        TRACE_ERROR("EVP_PKEY_get_octet_string_param failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    ecpoint = OPENSSL_zalloc(ecpoint_len);
-+    if (ecpoint == NULL) {
-+        TRACE_ERROR("OPENSSL_zalloc failed\n");
-+        rc = CKR_HOST_MEMORY;
-+        goto out;
-+    }
-+
-+    if (!EVP_PKEY_get_octet_string_param(ec_pkey,
-+                                         OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
-+                                         ecpoint, ecpoint_len, &ecpoint_len)) {
-+        TRACE_ERROR("EVP_PKEY_get_octet_string_param failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+#endif
- 
-     rc = ber_encode_OCTET_STRING(FALSE, &enc_ecpoint, &enc_ecpoint_len,
-                                  ecpoint, ecpoint_len);
-@@ -4564,12 +4618,30 @@ CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata,
-         goto out;
-     }
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     d_len = EC_KEY_priv2buf(ec_key, &d);
-     if (d_len == 0) {
-         TRACE_ERROR("Failed to get the EC private key.\n");
-         rc = CKR_FUNCTION_FAILED;
-         goto out;
-     }
-+#else
-+    if (!EVP_PKEY_get_bn_param(ec_pkey, OSSL_PKEY_PARAM_PRIV_KEY, &bn_d)) {
-+        TRACE_ERROR("EVP_PKEY_get_bn_param failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    d_len = ec_prime_len_from_nid(nid);
-+    d = OPENSSL_zalloc(d_len);
-+    if (d == NULL) {
-+        TRACE_ERROR("OPENSSL_zalloc failed\n");
-+        rc = CKR_HOST_MEMORY;
-+        goto out;
-+    }
-+
-+    BN_bn2binpad(bn_d, d, d_len);
-+#endif
- 
-     rc = build_attribute(CKA_VALUE, d, d_len, &value_attr);
-     if (rc != CKR_OK) {
-@@ -4602,10 +4674,17 @@ CK_RV token_specific_ec_generate_keypair(STDLL_TokData_t *tokdata,
-     rc = CKR_OK;
- 
- out:
--    if (ctx)
--        BN_CTX_free(ctx);
--    if (ec_key != NULL)
--        EC_KEY_free(ec_key);
-+    if (ctx != NULL)
-+        EVP_PKEY_CTX_free(ctx);
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    if (bnctx != NULL)
-+        BN_CTX_free(bnctx);
-+#else
-+    if (bn_d != NULL)
-+        BN_free(bn_d);
-+#endif
-+    if (ec_pkey != NULL)
-+        EVP_PKEY_free(ec_pkey);
-     if (ecpoint != NULL)
-         OPENSSL_free(ecpoint);
-     if (enc_ecpoint != NULL)
-@@ -4621,11 +4700,15 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata,  SESSION *sess,
-                              CK_BYTE *out_data, CK_ULONG *out_data_len,
-                              OBJECT *key_obj)
- {
--    EC_KEY *ec_key;
--    ECDSA_SIG *sig;
-+    EVP_PKEY *ec_key;
-+    ECDSA_SIG *sig = NULL;
-     const BIGNUM *r, *s;
-     CK_ULONG privlen, n;
-     CK_RV rc = CKR_OK;
-+    EVP_PKEY_CTX *ctx = NULL;
-+    size_t siglen;
-+    CK_BYTE *sigbuf = NULL;
-+    const unsigned char *p;
- 
-     UNUSED(tokdata);
-     UNUSED(sess);
-@@ -4636,16 +4719,54 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata,  SESSION *sess,
-     if (rc != CKR_OK)
-         return rc;
- 
--    sig = ECDSA_do_sign(in_data, in_data_len, ec_key);
-+    ctx = EVP_PKEY_CTX_new(ec_key, NULL);
-+    if (ctx == NULL) {
-+        TRACE_ERROR("EVP_PKEY_CTX_new failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (EVP_PKEY_sign_init(ctx) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_sign_init failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (EVP_PKEY_sign(ctx, NULL, &siglen, in_data, in_data_len) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_sign failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    sigbuf = malloc(siglen);
-+    if (sigbuf == NULL) {
-+        TRACE_ERROR("malloc failed\n");
-+        rc = CKR_HOST_MEMORY;
-+        goto out;
-+    }
-+
-+    if (EVP_PKEY_sign(ctx, sigbuf, &siglen, in_data, in_data_len) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_sign failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    p = sigbuf;
-+    sig = d2i_ECDSA_SIG(NULL, &p, siglen);
-     if (sig == NULL) {
--        TRACE_ERROR("ECDSA_do_sign failed\n");
-+        TRACE_ERROR("d2i_ECDSA_SIG failed\n");
-         rc = CKR_FUNCTION_FAILED;
-         goto out;
-     }
- 
-     ECDSA_SIG_get0(sig, &r, &s);
- 
--    privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8;
-+    privlen = ec_prime_len_from_pkey(ec_key);
-+    if (privlen <= 0) {
-+        TRACE_ERROR("ec_prime_len_from_pkey failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
- 
-     /* Insert leading 0x00's if r or s shorter than privlen */
-     n = privlen - BN_num_bytes(r);
-@@ -4662,7 +4783,11 @@ out:
-     if (sig != NULL)
-         ECDSA_SIG_free(sig);
-     if (ec_key != NULL)
--        EC_KEY_free(ec_key);
-+        EVP_PKEY_free(ec_key);
-+    if (sigbuf != NULL)
-+        free(sigbuf);
-+    if (ctx != NULL)
-+        EVP_PKEY_CTX_free(ctx);
- 
-     return rc;
- }
-@@ -4674,11 +4799,14 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata,
-                                CK_BYTE *signature,
-                                CK_ULONG signature_len, OBJECT *key_obj)
- {
--    EC_KEY *ec_key;
-+    EVP_PKEY *ec_key;
-     CK_ULONG privlen;
-     ECDSA_SIG *sig = NULL;
-     BIGNUM *r = NULL, *s = NULL;
-     CK_RV rc = CKR_OK;
-+    size_t siglen;
-+    CK_BYTE *sigbuf = NULL;
-+    EVP_PKEY_CTX *ctx = NULL;
- 
-     UNUSED(tokdata);
-     UNUSED(sess);
-@@ -4687,7 +4815,12 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata,
-     if (rc != CKR_OK)
-         return rc;
- 
--    privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_key)) + 7) / 8;
-+    privlen = ec_prime_len_from_pkey(ec_key);
-+    if (privlen <= 0) {
-+        TRACE_ERROR("ec_prime_len_from_pkey failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
- 
-     if (signature_len < 2 * privlen) {
-         TRACE_ERROR("Signature is too short\n");
-@@ -4715,7 +4848,27 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata,
-         goto out;
-     }
- 
--    rc = ECDSA_do_verify(in_data, in_data_len, sig, ec_key);
-+    siglen = i2d_ECDSA_SIG(sig, &sigbuf);
-+    if (siglen <= 0) {
-+        TRACE_ERROR("i2d_ECDSA_SIG failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    ctx = EVP_PKEY_CTX_new(ec_key, NULL);
-+    if (ctx == NULL) {
-+        TRACE_ERROR("EVP_PKEY_CTX_new failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    if (EVP_PKEY_verify_init(ctx) <= 0) {
-+        TRACE_ERROR("EVP_PKEY_verify_init failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+
-+    rc = EVP_PKEY_verify(ctx, sigbuf, siglen, in_data, in_data_len);
-     switch (rc) {
-     case 0:
-         rc = CKR_SIGNATURE_INVALID;
-@@ -4732,7 +4885,11 @@ out:
-     if (sig != NULL)
-         ECDSA_SIG_free(sig);
-     if (ec_key != NULL)
--        EC_KEY_free(ec_key);
-+        EVP_PKEY_free(ec_key);
-+    if (sigbuf != NULL)
-+        OPENSSL_free(sigbuf);
-+    if (ctx != NULL)
-+        EVP_PKEY_CTX_free(ctx);
- 
-     return rc;
- }
-@@ -4746,43 +4903,118 @@ CK_RV token_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata,
-                                       CK_ULONG *secret_value_len,
-                                       CK_BYTE *oid, CK_ULONG oid_length)
- {
--    EC_KEY *ec_pub = NULL, *ec_priv = NULL;
--    CK_ULONG privlen;
--    int secret_len;
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    EC_KEY *pub = NULL, *priv = NULL;
-+#else
-+    OSSL_PARAM_BLD *tmpl = NULL;
-+#endif
-+    EVP_PKEY *ec_pub = NULL, *ec_priv = NULL;
-+    EVP_PKEY_CTX *ctx = NULL;
-+    size_t secret_len;
-+    int nid;
-     CK_RV rc;
- 
-     UNUSED(tokdata);
- 
--    rc = make_ec_key_from_params(oid, oid_length, &ec_priv);
-+    nid = curve_nid_from_params(oid, oid_length);
-+    if (nid == NID_undef) {
-+        TRACE_ERROR("curve not supported by OpenSSL.\n");
-+        rc = CKR_CURVE_NOT_SUPPORTED;
-+        goto out;
-+    }
-+
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    rc = make_ec_key_from_params(oid, oid_length, &priv);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("make_ec_key_from_params failed\n");
-         goto out;
-     }
-+#else
-+    tmpl = OSSL_PARAM_BLD_new();
-+    if (tmpl == NULL) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_new failed\n");
-+        rc = CKR_HOST_MEMORY;
-+        goto out;
-+    }
-+
-+    if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME,
-+                                         OBJ_nid2sn(nid), 0)) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_push_utf8_string failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+#endif
- 
--    rc = fill_ec_key_from_privkey(ec_priv, priv_bytes, priv_length);
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    rc = fill_ec_key_from_privkey(priv, priv_bytes, priv_length, &ec_priv);
-+#else
-+    rc = fill_ec_key_from_privkey(tmpl, priv_bytes, priv_length, nid, &ec_priv);
-+#endif
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("fill_ec_key_from_privkey failed\n");
-         goto out;
-     }
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    priv = NULL;
-+#else
-+    OSSL_PARAM_BLD_free(tmpl);
-+    tmpl = NULL;
-+#endif
- 
--    rc = make_ec_key_from_params(oid, oid_length, &ec_pub);
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    rc = make_ec_key_from_params(oid, oid_length, &pub);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("make_ec_key_from_params failed\n");
-         goto out;
-     }
-+#else
-+    tmpl = OSSL_PARAM_BLD_new();
-+    if (tmpl == NULL) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_new failed\n");
-+        rc = CKR_HOST_MEMORY;
-+        goto out;
-+    }
-+
-+    if (!OSSL_PARAM_BLD_push_utf8_string(tmpl, OSSL_PKEY_PARAM_GROUP_NAME,
-+                                         OBJ_nid2sn(nid), 0)) {
-+        TRACE_ERROR("OSSL_PARAM_BLD_push_utf8_string failed\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto out;
-+    }
-+#endif
- 
--    rc = fill_ec_key_from_pubkey(ec_pub, pub_bytes, pub_length, TRUE);
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    rc = fill_ec_key_from_pubkey(pub, pub_bytes, pub_length, TRUE, nid,
-+                                 &ec_pub);
-+#else
-+    rc = fill_ec_key_from_pubkey(tmpl, pub_bytes, pub_length, TRUE, nid,
-+                                 &ec_pub);
-+#endif
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("fill_ec_key_from_pubkey failed\n");
-         goto out;
-     }
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    pub = NULL;
-+#else
-+    OSSL_PARAM_BLD_free(tmpl);
-+    tmpl = NULL;
-+#endif
- 
--    privlen = (EC_GROUP_order_bits(EC_KEY_get0_group(ec_priv)) + 7) / 8;
-+    ctx = EVP_PKEY_CTX_new(ec_priv, NULL);
-+    if (ctx == NULL) {
-+        TRACE_DEVEL("EVP_PKEY_CTX_new failed\n");
-+        goto out;
-+    }
- 
--    secret_len = ECDH_compute_key(secret_value, privlen,
--                                  EC_KEY_get0_public_key(ec_pub), ec_priv,
--                                  NULL);
--    if (secret_len <= 0) {
-+    if (EVP_PKEY_derive_init(ctx) <= 0 ||
-+        EVP_PKEY_derive_set_peer(ctx, ec_pub) <= 0) {
-+        TRACE_DEVEL("EVP_PKEY_derive_init/EVP_PKEY_derive_set_peer failed\n");
-+        goto out;
-+    }
-+
-+    secret_len = ec_prime_len_from_nid(nid);
-+    if (EVP_PKEY_derive(ctx, secret_value, &secret_len) <= 0) {
-         TRACE_DEVEL("ECDH_compute_key failed\n");
-         rc = CKR_FUNCTION_FAILED;
-         *secret_value_len = 0;
-@@ -4792,10 +5024,21 @@ CK_RV token_specific_ecdh_pkcs_derive(STDLL_TokData_t *tokdata,
-     *secret_value_len = secret_len;
- 
- out:
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    if (priv != NULL)
-+        EC_KEY_free(priv);
-+    if (pub != NULL)
-+        EC_KEY_free(pub);
-+#else
-+    if (tmpl != NULL)
-+        OSSL_PARAM_BLD_free(tmpl);
-+#endif
-     if (ec_priv != NULL)
--        EC_KEY_free(ec_priv);
-+        EVP_PKEY_free(ec_priv);
-     if (ec_pub != NULL)
--        EC_KEY_free(ec_pub);
-+        EVP_PKEY_free(ec_pub);
-+    if (ctx != NULL)
-+        EVP_PKEY_CTX_free(ctx);
- 
-     return rc;
- }
-@@ -4807,7 +5050,7 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
- {
-     CK_KEY_TYPE keytype;
- #ifndef NO_EC
--    EC_KEY *ec_key = NULL;
-+    EVP_PKEY *ec_key = NULL;
- #endif
-     CK_RV rc;
- 
-@@ -4824,7 +5067,7 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
-         /* Check if OpenSSL supports the curve */
-         rc = make_ec_key_from_template(obj->template, &ec_key);
-         if (ec_key != NULL)
--                EC_KEY_free(ec_key);
-+                EVP_PKEY_free(ec_key);
-         return rc;
- #endif
- 
diff --git a/SOURCES/opencryptoki-openssl3-533cdea6897d1bc0af13490f1c89248c52e7a73b.patch b/SOURCES/opencryptoki-openssl3-533cdea6897d1bc0af13490f1c89248c52e7a73b.patch
deleted file mode 100644
index af4395d..0000000
--- a/SOURCES/opencryptoki-openssl3-533cdea6897d1bc0af13490f1c89248c52e7a73b.patch
+++ /dev/null
@@ -1,147 +0,0 @@
-commit 533cdea6897d1bc0af13490f1c89248c52e7a73b
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 11:30:00 2021 +0200
-
-    COMMON: utilities.c: Remove deprecated OpenSSL functions
-    
-    Rework functions compute_sha(), compute_sha1(), and compute_md5() to
-    no longer use the mech_sha and mech_md5 routines, but to use the
-    OpenSSL EVP interface directly.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/utility.c b/usr/lib/common/utility.c
-index bcdc15bf..5fc68938 100644
---- a/usr/lib/common/utility.c
-+++ b/usr/lib/common/utility.c
-@@ -849,66 +849,89 @@ CK_RV get_hmac_digest(CK_ULONG mech, CK_ULONG *digest_mech, CK_BBOOL *general)
-     return CKR_OK;
- }
- 
--/* Compute specified SHA using either software or token implementation */
-+/* Compute specified SHA or MD5 using software */
- CK_RV compute_sha(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len,
-                   CK_BYTE *hash, CK_ULONG mech)
- {
--    DIGEST_CONTEXT ctx;
--    CK_ULONG hash_len;
--    CK_RV rv;
-+    const EVP_MD *md;
-+    unsigned int hash_len;
- 
--    memset(&ctx, 0x0, sizeof(ctx));
--    ctx.mech.mechanism = mech;
-+    UNUSED(tokdata);
- 
--    rv = get_sha_size(mech, &hash_len);
--    if (rv != CKR_OK)
--        return rv;
-+    switch (mech) {
-+    case CKM_MD5:
-+        hash_len = MD5_HASH_SIZE;
-+        md = EVP_md5();
-+        break;
-+    case CKM_SHA_1:
-+        hash_len = SHA1_HASH_SIZE;
-+        md = EVP_sha1();
-+        break;
-+    case CKM_SHA224:
-+    case CKM_SHA512_224:
-+        hash_len = SHA224_HASH_SIZE;
-+        md = EVP_sha224();
-+        break;
-+    case CKM_SHA256:
-+    case CKM_SHA512_256:
-+        hash_len = SHA256_HASH_SIZE;
-+        md = EVP_sha256();
-+        break;
-+    case CKM_SHA384:
-+        hash_len = SHA384_HASH_SIZE;
-+        md = EVP_sha384();
-+        break;
-+    case CKM_SHA512:
-+        hash_len = SHA512_HASH_SIZE;
-+        md = EVP_sha512();
-+        break;
-+#ifdef NID_sha3_224
-+    case CKM_IBM_SHA3_224:
-+        hash_len = SHA3_224_HASH_SIZE;
-+        md = EVP_sha3_224();
-+        break;
-+#endif
-+#ifdef NID_sha3_256
-+    case CKM_IBM_SHA3_256:
-+        hash_len = SHA3_256_HASH_SIZE;
-+        md = EVP_sha3_256();
-+        break;
-+#endif
-+#ifdef NID_sha3_384
-+    case CKM_IBM_SHA3_384:
-+        hash_len = SHA3_384_HASH_SIZE;
-+        md = EVP_sha3_384();
-+        break;
-+#endif
-+#ifdef NID_sha3_512
-+    case CKM_IBM_SHA3_512:
-+        hash_len = SHA3_512_HASH_SIZE;
-+        md = EVP_sha3_512();
-+        break;
-+#endif
-+    default:
-+        return CKR_MECHANISM_INVALID;
-+    }
- 
--    rv = sha_init(tokdata, NULL, &ctx, &ctx.mech);
--    if (rv != CKR_OK) {
--        TRACE_DEBUG("failed to create digest.\n");
--        return rv;
-+    if (EVP_Digest(data, len, hash, &hash_len, md, NULL) != 1) {
-+        TRACE_ERROR("%s EVP_Digest failed\n", __func__);
-+        return CKR_FUNCTION_FAILED;
-     }
--    rv = sha_hash(tokdata, NULL, FALSE, &ctx, data, len, hash, &hash_len);
- 
--    digest_mgr_cleanup(&ctx);
--    return rv;
-+    return CKR_OK;
- }
- 
- /* Compute SHA1 using software implementation */
- CK_RV compute_sha1(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len,
-                    CK_BYTE *hash)
- {
--    // XXX KEY
--    DIGEST_CONTEXT ctx;
--    CK_ULONG hash_len = SHA1_HASH_SIZE;
--
--    UNUSED(tokdata);
--
--    memset(&ctx, 0x0, sizeof(ctx));
--
--    sw_sha1_init(&ctx);
--    if (ctx.context == NULL)
--        return CKR_HOST_MEMORY;
--
--    return sw_sha1_hash(&ctx, data, len, hash, &hash_len);
-+    return compute_sha(tokdata, data, len, hash, CKM_SHA_1);
- }
- 
- CK_RV compute_md5(STDLL_TokData_t *tokdata, CK_BYTE *data, CK_ULONG len,
-                   CK_BYTE *hash)
- {
--    DIGEST_CONTEXT ctx;
--    CK_ULONG hash_len = MD5_HASH_SIZE;
--
--    UNUSED(tokdata);
--
--    memset(&ctx, 0x0, sizeof(ctx));
--
--    sw_md5_init(&ctx);
--    if (ctx.context == NULL)
--        return CKR_HOST_MEMORY;
--
--    return sw_md5_hash(&ctx, data, len, hash, &hash_len);
-+    return compute_sha(tokdata, data, len, hash, CKM_MD5);
- }
- 
- CK_RV get_keytype(STDLL_TokData_t *tokdata, CK_OBJECT_HANDLE hkey,
diff --git a/SOURCES/opencryptoki-openssl3-5377d25a6cbe3d07afcd08276ad7e90f62cad0c9.patch b/SOURCES/opencryptoki-openssl3-5377d25a6cbe3d07afcd08276ad7e90f62cad0c9.patch
deleted file mode 100644
index 165a69b..0000000
--- a/SOURCES/opencryptoki-openssl3-5377d25a6cbe3d07afcd08276ad7e90f62cad0c9.patch
+++ /dev/null
@@ -1,174 +0,0 @@
-commit 5377d25a6cbe3d07afcd08276ad7e90f62cad0c9
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 13:51:02 2021 +0200
-
-    COMMON: mech_sha: Remove deprecated OpenSSL functions
-    
-    All low level SHA functions are deprecated in OpenSSL 3.0.
-    Update the code to not use any of those.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
-index 314613a5..b3b965bf 100644
---- a/usr/lib/common/h_extern.h
-+++ b/usr/lib/common/h_extern.h
-@@ -1543,7 +1543,7 @@ CK_RV aes_cfb_decrypt_final(STDLL_TokData_t *tokdata, SESSION *sess,
- // SHA mechanisms
- //
- 
--void sw_sha1_init(DIGEST_CONTEXT *ctx);
-+CK_RV sw_sha1_init(DIGEST_CONTEXT *ctx);
- 
- CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-                    CK_ULONG in_data_len, CK_BYTE *out_data,
-diff --git a/usr/lib/common/mech_sha.c b/usr/lib/common/mech_sha.c
-index 0b9b7b28..1c81abe2 100644
---- a/usr/lib/common/mech_sha.c
-+++ b/usr/lib/common/mech_sha.c
-@@ -38,30 +38,49 @@
- #include "tok_spec_struct.h"
- #include "trace.h"
- 
--#include <openssl/sha.h>
-+#include <openssl/evp.h>
- #include <openssl/crypto.h>
- 
- //
- // Software SHA-1 implementation (OpenSSL based)
- //
- 
--void sw_sha1_init(DIGEST_CONTEXT *ctx)
-+static void sw_sha1_free(STDLL_TokData_t *tokdata, SESSION *sess,
-+                         CK_BYTE *context, CK_ULONG context_len)
- {
--    ctx->context_len = sizeof(SHA_CTX);
--    ctx->context = (CK_BYTE *) malloc(sizeof(SHA_CTX));
-+    UNUSED(tokdata);
-+    UNUSED(sess);
-+    UNUSED(context_len);
-+
-+    EVP_MD_CTX_free((EVP_MD_CTX *)context);
-+}
-+
-+CK_RV sw_sha1_init(DIGEST_CONTEXT *ctx)
-+{
-+    ctx->context_len = 1;
-+    ctx->context = (CK_BYTE *)EVP_MD_CTX_new();
-     if (ctx->context == NULL) {
-         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        // TODO: propagate error up?
--        return;
-+        return CKR_HOST_MEMORY;
-+    }
-+
-+    if (!EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, EVP_sha1(), NULL)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-+        return CKR_FUNCTION_FAILED;
-     }
- 
--    SHA1_Init((SHA_CTX *)ctx->context);
-+    ctx->state_unsaveable = CK_TRUE;
-+    ctx->context_free_func = sw_sha1_free;
-+
-+    return CKR_OK;
- }
- 
- CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-                    CK_ULONG in_data_len, CK_BYTE *out_data,
-                    CK_ULONG *out_data_len)
- {
-+    unsigned int len;
- 
-     if (!ctx || !out_data_len) {
-         TRACE_ERROR("%s received bad argument(s)\n", __func__);
-@@ -76,43 +95,60 @@ CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-     if (ctx->context == NULL)
-         return CKR_OPERATION_NOT_INITIALIZED;
- 
--    SHA1_Update((SHA_CTX *)ctx->context, in_data, in_data_len);
--    SHA1_Final(out_data, (SHA_CTX *)ctx->context);
--    *out_data_len = SHA1_HASH_SIZE;
-+    len = *out_data_len;
-+    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) ||
-+        !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-+    *out_data_len = len;
- 
--    if (ctx->context_free_func != NULL)
--        ctx->context_free_func(ctx->context, ctx->context_len);
--    else
--        free(ctx->context);
-+    EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-     ctx->context = NULL;
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
- 
--CK_RV sw_sha1_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
--                     CK_ULONG in_data_len)
-+static CK_RV sw_sha1_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-+                            CK_ULONG in_data_len)
- {
-     if (ctx->context == NULL)
-         return CKR_OPERATION_NOT_INITIALIZED;
- 
--    SHA1_Update((SHA_CTX *)ctx->context, in_data, in_data_len);
-+    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-     return CKR_OK;
- }
- 
--CK_RV sw_sha1_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data,
--                    CK_ULONG *out_data_len)
-+static CK_RV sw_sha1_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data,
-+                           CK_ULONG *out_data_len)
- {
-+    unsigned int len;
-+
-     if (ctx->context == NULL)
-         return CKR_OPERATION_NOT_INITIALIZED;
- 
--    SHA1_Final(out_data, (SHA_CTX *)ctx->context);
--    *out_data_len = SHA1_HASH_SIZE;
-+    if (*out_data_len < SHA1_HASH_SIZE) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
-+        return CKR_BUFFER_TOO_SMALL;
-+    }
-+
-+    len = *out_data_len;
-+    if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-+    *out_data_len = len;
- 
--    if (ctx->context_free_func != NULL)
--        ctx->context_free_func(ctx->context, ctx->context_len);
--    else
--        free(ctx->context);
-+    EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-     ctx->context = NULL;
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-@@ -134,8 +170,7 @@ CK_RV sha_init(STDLL_TokData_t *tokdata, SESSION *sess, DIGEST_CONTEXT *ctx,
-          *  supported. JML
-          */
-         if (mech->mechanism == CKM_SHA_1) {
--            sw_sha1_init(ctx);
--            return CKR_OK;
-+            return sw_sha1_init(ctx);
-         } else {
-             return CKR_MECHANISM_INVALID;
-         }
diff --git a/SOURCES/opencryptoki-openssl3-5cceead028ec8e0c244b01d38c9096c96d98f96b.patch b/SOURCES/opencryptoki-openssl3-5cceead028ec8e0c244b01d38c9096c96d98f96b.patch
deleted file mode 100644
index 0cfe159..0000000
--- a/SOURCES/opencryptoki-openssl3-5cceead028ec8e0c244b01d38c9096c96d98f96b.patch
+++ /dev/null
@@ -1,84 +0,0 @@
-commit 5cceead028ec8e0c244b01d38c9096c96d98f96b
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Jul 5 10:46:52 2021 +0200
-
-    ICSF: Remove support for OpenSSL < v1.1.1
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/icsf_stdll/pbkdf.c b/usr/lib/icsf_stdll/pbkdf.c
-index 4ddd0fd7..6ec4128a 100644
---- a/usr/lib/icsf_stdll/pbkdf.c
-+++ b/usr/lib/icsf_stdll/pbkdf.c
-@@ -82,7 +82,6 @@ CK_RV encrypt_aes(CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey,
-     const EVP_CIPHER *cipher = EVP_aes_256_cbc();
-     int tmplen;
- 
--#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
- 
-     EVP_EncryptInit_ex(ctx, cipher, NULL, dkey, iv);
-@@ -98,24 +97,6 @@ CK_RV encrypt_aes(CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey,
-     *outbuflen = (*outbuflen) + tmplen;
-     EVP_CIPHER_CTX_free(ctx);
- 
--#else
--    EVP_CIPHER_CTX ctx;
--    EVP_CIPHER_CTX_init(&ctx);
--
--    EVP_EncryptInit_ex(&ctx, cipher, NULL, dkey, iv);
--    if (!EVP_EncryptUpdate(&ctx, outbuf, outbuflen, inbuf, inbuflen)) {
--        TRACE_ERROR("EVP_EncryptUpdate failed.\n");
--        return CKR_FUNCTION_FAILED;
--    }
--    if (!EVP_EncryptFinal_ex(&ctx, outbuf + (*outbuflen), &tmplen)) {
--        TRACE_ERROR("EVP_EncryptFinal failed.\n");
--        return CKR_FUNCTION_FAILED;
--    }
--
--    *outbuflen = (*outbuflen) + tmplen;
--    EVP_CIPHER_CTX_cleanup(&ctx);
--#endif
--
-     return CKR_OK;
- }
- 
-@@ -125,7 +106,6 @@ CK_RV decrypt_aes(CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey,
-     int size;
-     const EVP_CIPHER *cipher = EVP_aes_256_cbc();
- 
--#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
- 
-     EVP_DecryptInit_ex(ctx, cipher, NULL, dkey, iv);
-@@ -147,30 +127,6 @@ CK_RV decrypt_aes(CK_BYTE * inbuf, int inbuflen, CK_BYTE * dkey,
- 
-     EVP_CIPHER_CTX_free(ctx);
- 
--#else
--    EVP_CIPHER_CTX ctx;
--    EVP_CIPHER_CTX_init(&ctx);
--
--    EVP_DecryptInit_ex(&ctx, cipher, NULL, dkey, iv);
--    if (!EVP_DecryptUpdate(&ctx, outbuf, outbuflen, inbuf, inbuflen)) {
--        TRACE_ERROR("EVP_DecryptUpdate failed.\n");
--        return CKR_FUNCTION_FAILED;
--    }
--    if (!EVP_DecryptFinal_ex(&ctx, outbuf + (*outbuflen), &size)) {
--        TRACE_ERROR("EVP_DecryptFinal failed.\n");
--        return CKR_FUNCTION_FAILED;
--    }
--
--    /* total length of the decrypted data */
--    *outbuflen = (*outbuflen) + size;
--
--    /* EVP_DecryptFinal removes any padding. The final length
--     * is the length of the decrypted data without padding.
--     */
--
--    EVP_CIPHER_CTX_cleanup(&ctx);
--#endif
--
-     return CKR_OK;
- }
- 
diff --git a/SOURCES/opencryptoki-openssl3-62fc2bcd98672c5d0ff8a2c926f3103110e91ed7.patch b/SOURCES/opencryptoki-openssl3-62fc2bcd98672c5d0ff8a2c926f3103110e91ed7.patch
deleted file mode 100644
index 5721c2f..0000000
--- a/SOURCES/opencryptoki-openssl3-62fc2bcd98672c5d0ff8a2c926f3103110e91ed7.patch
+++ /dev/null
@@ -1,226 +0,0 @@
-commit 62fc2bcd98672c5d0ff8a2c926f3103110e91ed7
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Thu Jul 1 13:37:04 2021 +0200
-
-    COMMON: Perform proper context cleanup for 3DES/AES CMAC mechanisms
-    
-    The handling of 3DES/AES CMAC mechanisms use a complex context structure,
-    that contains pointers. Such state can not be saved, and needs a custom
-    context free routine to properly clean up the context.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/mech_aes.c b/usr/lib/common/mech_aes.c
-index ad6af16b..59f82482 100644
---- a/usr/lib/common/mech_aes.c
-+++ b/usr/lib/common/mech_aes.c
-@@ -2691,6 +2691,24 @@ CK_RV aes_mac_verify_final(STDLL_TokData_t *tokdata,
-     return CKR_SIGNATURE_INVALID;
- }
- 
-+static void aes_cmac_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                             CK_BYTE *context, CK_ULONG context_len)
-+{
-+    UNUSED(tokdata);
-+    UNUSED(sess);
-+    UNUSED(context_len);
-+
-+    if (((AES_CMAC_CONTEXT *)context)->ctx != NULL) {
-+        token_specific.t_aes_cmac(tokdata, (CK_BYTE *)"", 0, NULL,
-+                                  ((AES_CMAC_CONTEXT *)context)->iv,
-+                                  CK_FALSE, CK_TRUE,
-+                                  ((AES_CMAC_CONTEXT *)context)->ctx);
-+        ((AES_CMAC_CONTEXT *)context)->ctx = NULL;
-+    }
-+
-+    free(context);
-+}
-+
- CK_RV aes_cmac_sign(STDLL_TokData_t *tokdata,
-                     SESSION *sess,
-                     CK_BBOOL length_only,
-@@ -2743,6 +2761,8 @@ CK_RV aes_cmac_sign(STDLL_TokData_t *tokdata,
-     if (((AES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = aes_cmac_cleanup;
-+
-     memcpy(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv, mac_len);
-     *out_data_len = mac_len;
- 
-@@ -2816,6 +2836,8 @@ CK_RV aes_cmac_sign_update(STDLL_TokData_t *tokdata,
- 
-             if (context->ctx != NULL)
-                 ctx->state_unsaveable = CK_TRUE;
-+
-+            ctx->context_free_func = aes_cmac_cleanup;
-         } else {
-             TRACE_DEVEL("Token specific aes cmac failed.\n");
-         }
-@@ -2882,6 +2904,8 @@ CK_RV aes_cmac_sign_final(STDLL_TokData_t *tokdata,
-     if (context->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = aes_cmac_cleanup;
-+
-     memcpy(out_data, context->iv, mac_len);
-     *out_data_len = mac_len;
- 
-@@ -2941,6 +2965,8 @@ CK_RV aes_cmac_verify(STDLL_TokData_t *tokdata,
-     if (((AES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = aes_cmac_cleanup;
-+
-     if (CRYPTO_memcmp(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv,
-                       out_data_len) == 0) {
-         return CKR_OK;
-@@ -3012,6 +3038,8 @@ CK_RV aes_cmac_verify_update(STDLL_TokData_t *tokdata,
- 
-             if (context->ctx != NULL)
-                 ctx->state_unsaveable = CK_TRUE;
-+
-+            ctx->context_free_func = aes_cmac_cleanup;
-         } else {
-             TRACE_DEVEL("Token specific aes cmac failed.\n");
-         }
-@@ -3070,6 +3098,8 @@ CK_RV aes_cmac_verify_final(STDLL_TokData_t *tokdata,
-     if (context->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = aes_cmac_cleanup;
-+
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Token specific aes mac failed.\n");
-         return rc;
-diff --git a/usr/lib/common/mech_des3.c b/usr/lib/common/mech_des3.c
-index be8d6075..591ad3fa 100644
---- a/usr/lib/common/mech_des3.c
-+++ b/usr/lib/common/mech_des3.c
-@@ -2334,6 +2334,24 @@ CK_RV des3_mac_verify_final(STDLL_TokData_t *tokdata,
-     return CKR_SIGNATURE_INVALID;
- }
- 
-+static void des3_cmac_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                              CK_BYTE *context, CK_ULONG context_len)
-+{
-+    UNUSED(tokdata);
-+    UNUSED(sess);
-+    UNUSED(context_len);
-+
-+    if (((DES_CMAC_CONTEXT *)context)->ctx != NULL) {
-+        token_specific.t_tdes_cmac(tokdata, (CK_BYTE *)"", 0, NULL,
-+                                   ((DES_CMAC_CONTEXT *)context)->iv,
-+                                   CK_FALSE, CK_TRUE,
-+                                   ((DES_CMAC_CONTEXT *)context)->ctx);
-+        ((DES_CMAC_CONTEXT *)context)->ctx = NULL;
-+    }
-+
-+    free(context);
-+}
-+
- CK_RV des3_cmac_sign(STDLL_TokData_t *tokdata,
-                      SESSION *sess,
-                      CK_BBOOL length_only,
-@@ -2383,6 +2401,8 @@ CK_RV des3_cmac_sign(STDLL_TokData_t *tokdata,
-     if (((DES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = des3_cmac_cleanup;
-+
-     memcpy(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv, mac_len);
- 
-     *out_data_len = mac_len;
-@@ -2456,6 +2476,8 @@ CK_RV des3_cmac_sign_update(STDLL_TokData_t *tokdata,
- 
-             if (context->ctx != NULL)
-                 ctx->state_unsaveable = CK_TRUE;
-+
-+            ctx->context_free_func = des3_cmac_cleanup;
-         } else {
-             TRACE_DEVEL("Token specific des3 cmac failed.\n");
-         }
-@@ -2521,6 +2543,8 @@ CK_RV des3_cmac_sign_final(STDLL_TokData_t *tokdata,
-     if (context->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = des3_cmac_cleanup;
-+
-     memcpy(out_data, context->iv, mac_len);
- 
-     *out_data_len = mac_len;
-@@ -2577,6 +2601,8 @@ CK_RV des3_cmac_verify(STDLL_TokData_t *tokdata,
-     if (((DES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = des3_cmac_cleanup;
-+
-     if (CRYPTO_memcmp(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv,
-                       out_data_len) == 0) {
-         return CKR_OK;
-@@ -2646,6 +2672,8 @@ CK_RV des3_cmac_verify_update(STDLL_TokData_t *tokdata,
- 
-             if (context->ctx != NULL)
-                 ctx->state_unsaveable = CK_TRUE;
-+
-+            ctx->context_free_func = des3_cmac_cleanup;
-         } else {
-             TRACE_DEVEL("Token specific des3 cmac failed.\n");
-         }
-@@ -2709,6 +2737,8 @@ CK_RV des3_cmac_verify_final(STDLL_TokData_t *tokdata,
-     if (context->ctx != NULL)
-         ctx->state_unsaveable = CK_TRUE;
- 
-+    ctx->context_free_func = des3_cmac_cleanup;
-+
-     if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0)
-         return CKR_OK;
- 
-diff --git a/usr/lib/ica_s390_stdll/ica_specific.c b/usr/lib/ica_s390_stdll/ica_specific.c
-index 77876467..881a430c 100644
---- a/usr/lib/ica_s390_stdll/ica_specific.c
-+++ b/usr/lib/ica_s390_stdll/ica_specific.c
-@@ -713,6 +713,9 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     UNUSED(tokdata);
-     UNUSED(ctx);
- 
-+    if (key == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+
-     // get the key type
-     rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
-     if (rc != CKR_OK) {
-@@ -3621,6 +3624,9 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     UNUSED(tokdata);
-     UNUSED(ctx);
- 
-+    if (key == NULL)
-+        return CKR_ARGUMENTS_BAD;
-+
-     rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
-     if (rc != CKR_OK) {
-         TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
-diff --git a/usr/lib/soft_stdll/soft_specific.c b/usr/lib/soft_stdll/soft_specific.c
-index aeff39a9..5ca22693 100644
---- a/usr/lib/soft_stdll/soft_specific.c
-+++ b/usr/lib/soft_stdll/soft_specific.c
-@@ -3994,6 +3994,9 @@ CK_RV token_specific_tdes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     UNUSED(tokdata);
- 
-     if (first) {
-+        if (key == NULL)
-+            return CKR_ARGUMENTS_BAD;
-+
-         // get the key type
-         rv = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
-         if (rv != CKR_OK) {
-@@ -4194,6 +4197,9 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata, CK_BYTE *message,
-     UNUSED(tokdata);
- 
-     if (first) {
-+        if (key == NULL)
-+            return CKR_ARGUMENTS_BAD;
-+
-         // get the key value
-         rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
-         if (rc != CKR_OK) {
diff --git a/SOURCES/opencryptoki-openssl3-6fee37f08391415cdf8d8610c501516c3d3ed29c.patch b/SOURCES/opencryptoki-openssl3-6fee37f08391415cdf8d8610c501516c3d3ed29c.patch
deleted file mode 100644
index 516b513..0000000
--- a/SOURCES/opencryptoki-openssl3-6fee37f08391415cdf8d8610c501516c3d3ed29c.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-commit 6fee37f08391415cdf8d8610c501516c3d3ed29c
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 13:41:57 2021 +0200
-
-    COMMON: mech_md5: Remove deprecated OpenSSL functions
-    
-    All low level MD5 functions are deprecated in OpenSSL 3.0.
-    Update the code to not use any of those.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
-index 47b96ba0..314613a5 100644
---- a/usr/lib/common/h_extern.h
-+++ b/usr/lib/common/h_extern.h
-@@ -1667,7 +1667,7 @@ CK_RV md5_hmac_verify(STDLL_TokData_t *tokdata,
-                       CK_ULONG in_data_len,
-                       CK_BYTE *signature, CK_ULONG sig_len);
- 
--void sw_md5_init(DIGEST_CONTEXT *ctx);
-+CK_RV sw_md5_init(DIGEST_CONTEXT *ctx);
- 
- CK_RV sw_md5_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-                   CK_ULONG in_data_len, CK_BYTE *out_data,
-diff --git a/usr/lib/common/mech_md5.c b/usr/lib/common/mech_md5.c
-index 320e2549..65c11def 100644
---- a/usr/lib/common/mech_md5.c
-+++ b/usr/lib/common/mech_md5.c
-@@ -20,30 +20,50 @@
- #include "tok_spec_struct.h"
- #include "trace.h"
- 
--#include <openssl/md5.h>
-+#include <openssl/evp.h>
- #include <openssl/crypto.h>
- 
- //
- // Software MD5 implementation (OpenSSL based)
- //
- 
--void sw_md5_init(DIGEST_CONTEXT *ctx)
-+static void sw_md5_free(STDLL_TokData_t *tokdata, SESSION *sess,
-+                        CK_BYTE *context, CK_ULONG context_len)
- {
--    ctx->context_len = sizeof(MD5_CTX);
--    ctx->context = (CK_BYTE *) malloc(sizeof(MD5_CTX));
-+    UNUSED(tokdata);
-+    UNUSED(sess);
-+    UNUSED(context_len);
-+
-+    EVP_MD_CTX_free((EVP_MD_CTX *)context);
-+}
-+
-+CK_RV sw_md5_init(DIGEST_CONTEXT *ctx)
-+{
-+    ctx->context_len = 1;
-+    ctx->context = (CK_BYTE *)EVP_MD_CTX_new();
-     if (ctx->context == NULL) {
-         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
--        // TODO: propagate error up?
--        return;
-+        return CKR_HOST_MEMORY;
-+    }
-+
-+    if (!EVP_DigestInit_ex((EVP_MD_CTX *)ctx->context, EVP_md5(), NULL)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-+        return CKR_FUNCTION_FAILED;
-     }
- 
--    MD5_Init((MD5_CTX *)ctx->context);
-+    ctx->state_unsaveable = CK_TRUE;
-+    ctx->context_free_func = sw_md5_free;
-+
-+    return CKR_OK;
- }
- 
- CK_RV sw_md5_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-                   CK_ULONG in_data_len, CK_BYTE *out_data,
-                   CK_ULONG *out_data_len)
- {
-+    unsigned int len;
-+
-     if (!ctx || !out_data_len) {
-         TRACE_ERROR("%s received bad argument(s)\n", __func__);
-         return CKR_FUNCTION_FAILED;
-@@ -57,43 +77,60 @@ CK_RV sw_md5_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-     if (ctx->context == NULL)
-         return CKR_OPERATION_NOT_INITIALIZED;
- 
--    MD5_Update((MD5_CTX *)ctx->context, in_data, in_data_len);
--    MD5_Final(out_data, (MD5_CTX *)ctx->context);
--    *out_data_len = MD5_HASH_SIZE;
-+    len = *out_data_len;
-+    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len) ||
-+        !EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
- 
--    if (ctx->context_free_func != NULL)
--        ctx->context_free_func(ctx->context, ctx->context_len);
--    else
--        free(ctx->context);
-+    *out_data_len = len;
-+
-+    EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-     ctx->context = NULL;
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
- 
--CK_RV sw_MD5_Update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
--                     CK_ULONG in_data_len)
-+static CK_RV sw_md5_update(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-+                           CK_ULONG in_data_len)
- {
-     if (ctx->context == NULL)
-         return CKR_OPERATION_NOT_INITIALIZED;
- 
--    MD5_Update((MD5_CTX *)ctx->context, in_data, in_data_len);
-+    if (!EVP_DigestUpdate((EVP_MD_CTX *)ctx->context, in_data, in_data_len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-     return CKR_OK;
- }
- 
--CK_RV sw_MD5_Final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data,
--                    CK_ULONG *out_data_len)
-+static CK_RV sw_md5_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data,
-+                          CK_ULONG *out_data_len)
- {
-+    unsigned int len;
-+
-     if (ctx->context == NULL)
-         return CKR_OPERATION_NOT_INITIALIZED;
- 
--    MD5_Final(out_data, (MD5_CTX *)ctx->context);
--    *out_data_len = MD5_HASH_SIZE;
-+    if (*out_data_len < MD5_HASH_SIZE) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_BUFFER_TOO_SMALL));
-+        return CKR_BUFFER_TOO_SMALL;
-+    }
- 
--    if (ctx->context_free_func != NULL)
--        ctx->context_free_func(ctx->context, ctx->context_len);
--    else
--        free(ctx->context);
-+    len = *out_data_len;
-+    if (!EVP_DigestFinal((EVP_MD_CTX *)ctx->context, out_data, &len)) {
-+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
-+        return CKR_FUNCTION_FAILED;
-+    }
-+
-+    *out_data_len = len;
-+
-+    EVP_MD_CTX_free((EVP_MD_CTX *)ctx->context);
-     ctx->context = NULL;
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-@@ -105,8 +142,7 @@ CK_RV md5_init(STDLL_TokData_t *tokdata, SESSION *sess, DIGEST_CONTEXT *ctx,
-     UNUSED(sess);
- 
-     if (mech->mechanism == CKM_MD5) {
--        sw_md5_init(ctx);
--        return CKR_OK;
-+        return sw_md5_init(ctx);
-     } else {
-         return CKR_MECHANISM_INVALID;
-     }
-@@ -159,7 +195,7 @@ CK_RV md5_hash_update(STDLL_TokData_t *tokdata, SESSION *sess,
-         return CKR_OK;
- 
-     if (ctx->mech.mechanism == CKM_MD5)
--        return sw_MD5_Update(ctx, in_data, in_data_len);
-+        return sw_md5_update(ctx, in_data, in_data_len);
-     else
-         return CKR_MECHANISM_INVALID;
- }
-@@ -188,7 +224,7 @@ CK_RV md5_hash_final(STDLL_TokData_t *tokdata, SESSION *sess,
-     }
- 
-     if (ctx->mech.mechanism == CKM_MD5)
--        return sw_MD5_Final(ctx, out_data, out_data_len);
-+        return sw_md5_final(ctx, out_data, out_data_len);
-     else
-         return CKR_MECHANISM_INVALID;
- }
diff --git a/SOURCES/opencryptoki-openssl3-7a23c12214688b287b9591133445e593da633caa.patch b/SOURCES/opencryptoki-openssl3-7a23c12214688b287b9591133445e593da633caa.patch
deleted file mode 100644
index b3c2339..0000000
--- a/SOURCES/opencryptoki-openssl3-7a23c12214688b287b9591133445e593da633caa.patch
+++ /dev/null
@@ -1,1085 +0,0 @@
-commit 7a23c12214688b287b9591133445e593da633caa
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Jul 5 12:58:42 2021 +0200
-
-    API: Use own OpenSSL library context for Opencryptoki's use of OpenSSL
-    
-    Create a separate library context for Opencryptoki's use of OpenSSL services
-    and explicitly load the 'default' provider for this context.
-    
-    This prevents call-loops when the calling application has configured a PKCS#11
-    provider that uses Opencryptoki under the covers. This could produce a loop
-    with the following calling tree:
-      Application -> Openssl -> PKCS11-provider -> Opencryptoki -> OpenSSL
-      -> PKCS11-provider -> Opencryptoki -> ...
-    Explicitly using the 'default' provider only for Opencrypoki's OpenSSL usage
-    breaks this loop.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/include/apictl.h b/usr/include/apictl.h
-index 81c65dad..0f3973b5 100644
---- a/usr/include/apictl.h
-+++ b/usr/include/apictl.h
-@@ -13,12 +13,16 @@
- #include <local_types.h>
- #include <stdll.h>
- #include <slotmgr.h>
--
--#include "local_types.h"
-+#include <defs.h>
- 
- #ifndef _APILOCAL_H
- #define _APILOCAL_H
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    #include <openssl/crypto.h>
-+    #include <openssl/provider.h>
-+#endif
-+
- // SAB Add a linked list of STDLL's loaded to
- // only load and get list once, but let multiple slots us it.
- 
-@@ -59,6 +63,10 @@ typedef struct {
-                                             // per slot
-     int socketfd;
-     pthread_t event_thread;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_LIB_CTX *openssl_libctx;
-+    OSSL_PROVIDER *openssl_default_provider;
-+#endif
- } API_Proc_Struct_t;
- 
- #endif
-diff --git a/usr/lib/api/api.mk b/usr/lib/api/api.mk
-index 630a43b7..282f0017 100644
---- a/usr/lib/api/api.mk
-+++ b/usr/lib/api/api.mk
-@@ -12,7 +12,7 @@ opencryptoki_libopencryptoki_la_CFLAGS =				\
- 	-DSTDLL_NAME=\"api\"
- 
- opencryptoki_libopencryptoki_la_LDFLAGS =				\
--	-shared	-Wl,-z,defs,-Bsymbolic -lc -ldl -lpthread		\
-+	-shared	-Wl,-z,defs,-Bsymbolic -lc -ldl -lpthread -lcrypto	\
- 	-version-info $(SO_CURRENT):$(SO_REVISION):$(SO_AGE)		\
- 	-Wl,--version-script=${srcdir}/opencryptoki.map
- 
-diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c
-index 6517ca6c..ca6aff06 100644
---- a/usr/lib/api/api_interface.c
-+++ b/usr/lib/api/api_interface.c
-@@ -37,6 +37,28 @@
- 
- void api_init();
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+#define BEGIN_OPENSSL_LIBCTX(ossl_ctx, rc)                                  \
-+        do {                                                                \
-+            OSSL_LIB_CTX  *prev_ctx = OSSL_LIB_CTX_set0_default((ossl_ctx));\
-+            if (prev_ctx == NULL) {                                         \
-+                (rc) = CKR_FUNCTION_FAILED;                                 \
-+                TRACE_ERROR("OSSL_LIB_CTX_set0_default failed\n");          \
-+                break;                                                      \
-+            }
-+
-+#define END_OPENSSL_LIBCTX(rc)                                              \
-+            if (OSSL_LIB_CTX_set0_default(prev_ctx) == NULL) {              \
-+                if ((rc) == CKR_OK)                                         \
-+                    (rc) = CKR_FUNCTION_FAILED;                             \
-+                TRACE_ERROR("OSSL_LIB_CTX_set0_default failed\n");          \
-+            }                                                               \
-+        } while (0);
-+#else
-+#define BEGIN_OPENSSL_LIBCTX(ossl_ctx, rc)  do {
-+#define END_OPENSSL_LIBCTX(rc)              } while (0);
-+#endif
-+
- // NOTES:
- // In many cases the specificaiton does not allow returns
- // of CKR_ARGUMENTSB_BAD.  We break the spec, since validation of parameters
-@@ -347,6 +369,7 @@ CK_RV C_CancelFunction(CK_SESSION_HANDLE hSession)
- 
- CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
- {
-+    CK_RV rc = CKR_OK;
-     // Although why does modutil do a close all sessions.  It is a single
-     // application it can only close its sessions...
-     // And all sessions should be closed anyhow.
-@@ -365,9 +388,11 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
-     /* for every node in the API-level session tree, if the session's slot
-      * matches slotID, close it
-      */
-+    BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc)
-     CloseAllSessions(slotID, FALSE);
-+    END_OPENSSL_LIBCTX(rc)
- 
--    return CKR_OK;
-+    return rc;
- }                               // end of C_CloseAllSessions
- 
- //------------------------------------------------------------------------
-@@ -408,9 +433,12 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_CloseSession) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_CloseSession(sltp->TokData, &rSession, FALSE);
-         TRACE_DEVEL("Called STDLL rv = 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-+
-         //  If the STDLL successfully closed the session
-         //  we can free it.. Otherwise we will have to leave it
-         //  lying arround.
-@@ -488,9 +516,12 @@ CK_RV C_CopyObject(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_CopyObject) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_CopyObject(sltp->TokData, &rSession, hObject,
-                                 pTemplate, ulCount, phNewObject);
-+        TRACE_DEVEL("fcn->ST_CopyObject returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -558,10 +589,12 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_CreateObject) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_CreateObject(sltp->TokData, &rSession, pTemplate,
-                                   ulCount, phObject);
-         TRACE_DEVEL("fcn->ST_CreateObject returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -611,10 +644,12 @@ CK_RV C_Decrypt(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Decrypt) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Decrypt(sltp->TokData, &rSession, pEncryptedData,
-                              ulEncryptedDataLen, pData, pulDataLen);
-         TRACE_DEVEL("fcn->ST_Decrypt returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -661,11 +696,13 @@ CK_RV C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DecryptDigestUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DecryptDigestUpdate(sltp->TokData, &rSession,
-                                          pEncryptedPart,
-                                          ulEncryptedPartLen, pPart, pulPartLen);
-         TRACE_DEVEL("fcn->ST_DecryptDigestUpdate returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -714,10 +751,12 @@ CK_RV C_DecryptFinal(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DecryptFinal) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DecryptFinal(sltp->TokData, &rSession, pLastPart,
-                                   pulLastPartLen);
-         TRACE_DEVEL("fcn->ST_DecryptFinal returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -771,9 +810,11 @@ CK_RV C_DecryptInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DecryptInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DecryptInit(sltp->TokData, &rSession, pMechanism, hKey);
-         TRACE_DEVEL("fcn->ST_DecryptInit returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -823,11 +864,13 @@ CK_RV C_DecryptUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DecryptUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DecryptUpdate(sltp->TokData, &rSession,
-                                    pEncryptedPart, ulEncryptedPartLen,
-                                    pPart, pulPartLen);
-         TRACE_DEVEL("fcn->ST_DecryptUpdate:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -873,11 +916,13 @@ CK_RV C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DecryptVerifyUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DecryptVerifyUpdate(sltp->TokData, &rSession,
-                                          pEncryptedPart, ulEncryptedPartLen,
-                                          pPart, pulPartLen);
-         TRACE_DEVEL("fcn->ST_DecryptVerifyUpdate returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -941,10 +986,12 @@ CK_RV C_DeriveKey(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DeriveKey) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DeriveKey(sltp->TokData, &rSession, pMechanism,
-                                hBaseKey, pTemplate, ulAttributeCount, phKey);
-         TRACE_DEVEL("fcn->ST_DeriveKey returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -992,9 +1039,11 @@ CK_RV C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DestroyObject) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DestroyObject(sltp->TokData, &rSession, hObject);
-         TRACE_DEVEL("fcn->ST_DestroyObject returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1040,10 +1089,12 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Digest) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Digest(sltp->TokData, &rSession, pData, ulDataLen,
-                             pDigest, pulDigestLen);
-         TRACE_DEVEL("fcn->ST_Digest:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1091,11 +1142,13 @@ CK_RV C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DigestEncryptUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DigestEncryptUpdate(sltp->TokData, &rSession,
-                                          pPart, ulPartLen,
-                                          pEncryptedPart, pulEncryptedPartLen);
-         TRACE_DEVEL("fcn->ST_DigestEncryptUpdate returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1139,10 +1192,12 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DigestFinal) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DigestFinal(sltp->TokData, &rSession, pDigest,
-                                  pulDigestLen);
-         TRACE_DEVEL("fcn->ST_DigestFinal returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1189,9 +1244,11 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DigestInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DigestInit(sltp->TokData, &rSession, pMechanism);
-         TRACE_DEVEL("fcn->ST_DigestInit returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1234,9 +1291,11 @@ CK_RV C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DigestKey) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DigestKey(sltp->TokData, &rSession, hKey);
-         TRACE_DEBUG("fcn->ST_DigestKey returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1280,9 +1339,11 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_DigestUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_DigestUpdate(sltp->TokData, &rSession, pPart, ulPartLen);
-         TRACE_DEVEL("fcn->ST_DigestUpdate returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1328,10 +1389,12 @@ CK_RV C_Encrypt(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Encrypt) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Encrypt(sltp->TokData, &rSession, pData,
-                              ulDataLen, pEncryptedData, pulEncryptedDataLen);
-         TRACE_DEVEL("fcn->ST_Encrypt returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1376,10 +1439,12 @@ CK_RV C_EncryptFinal(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_EncryptFinal) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_EncryptFinal(sltp->TokData, &rSession,
-                                   pLastEncryptedPart, pulLastEncryptedPartLen);
-         TRACE_DEVEL("fcn->ST_EncryptFinal: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1427,9 +1492,11 @@ CK_RV C_EncryptInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_EncryptInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_EncryptInit(sltp->TokData, &rSession, pMechanism, hKey);
-         TRACE_INFO("fcn->ST_EncryptInit returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1476,11 +1543,13 @@ CK_RV C_EncryptUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_EncryptUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_EncryptUpdate(sltp->TokData, &rSession, pPart,
-                                    ulPartLen, pEncryptedPart,
-                                    pulEncryptedPartLen);
-         TRACE_DEVEL("fcn->ST_EncryptUpdate returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1543,6 +1612,7 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
-     // unload all the STDLL's from the application
-     // This is in case the APP decides to do the re-initialize and
-     // continue on
-+    BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc)
-     for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
-         sltp = &(Anchor->SltList[slotID]);
-         if (slot_loaded[slotID]) {
-@@ -1565,12 +1635,20 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
-         if (!in_child_fork_initializer)
-             DL_UnLoad(sltp, slotID);
-     }
-+    END_OPENSSL_LIBCTX(rc)
- 
-     // Un register from Slot D
-     API_UnRegister();
- 
-     bt_destroy(&Anchor->sess_btree);
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    if (Anchor->openssl_default_provider != NULL)
-+        OSSL_PROVIDER_unload(Anchor->openssl_default_provider);
-+    if (Anchor->openssl_libctx != NULL)
-+        OSSL_LIB_CTX_free(Anchor->openssl_libctx);
-+#endif
-+
-     detach_shared_memory(Anchor->SharedMemP);
-     free(Anchor);               // Free API Proc Struct
-     Anchor = NULL;
-@@ -1632,10 +1710,12 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_FindObjects) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_FindObjects(sltp->TokData, &rSession, phObject,
-                                  ulMaxObjectCount, pulObjectCount);
-         TRACE_DEVEL("fcn->ST_FindObjects returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1683,9 +1763,11 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_FindObjectsFinal) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_FindObjectsFinal(sltp->TokData, &rSession);
-         TRACE_DEVEL("fcn->ST_FindObjectsFinal returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1736,10 +1818,12 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_FindObjectsInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_FindObjectsInit(sltp->TokData, &rSession,
-                                      pTemplate, ulCount);
-         TRACE_DEVEL("fcn->ST_FindObjectsInit returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1794,10 +1878,12 @@ CK_RV C_GenerateKey(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GenerateKey) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GenerateKey(sltp->TokData, &rSession, pMechanism,
-                                  pTemplate, ulCount, phKey);
-         TRACE_DEVEL("fcn->ST_GenerateKey returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1861,6 +1947,7 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GenerateKeyPair) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GenerateKeyPair(sltp->TokData, &rSession,
-                                      pMechanism,
-@@ -1870,6 +1957,7 @@ CK_RV C_GenerateKeyPair(CK_SESSION_HANDLE hSession,
-                                      ulPrivateKeyAttributeCount,
-                                      phPublicKey, phPrivateKey);
-         TRACE_DEVEL("fcn->ST_GenerateKeyPair returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1917,10 +2005,12 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GenerateRandom) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GenerateRandom(sltp->TokData, &rSession,
-                                     RandomData, ulRandomLen);
-         TRACE_DEVEL("fcn->ST_GenerateRandom returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -1977,10 +2067,12 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetAttributeValue) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GetAttributeValue(sltp->TokData, &rSession,
-                                        hObject, pTemplate, ulCount);
-         TRACE_DEVEL("fcn->ST_GetAttributeValue returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -2098,8 +2190,10 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetMechanismInfo) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         rv = fcn->ST_GetMechanismInfo(sltp->TokData, slotID, type, pInfo);
-         TRACE_DEVEL("fcn->ST_GetMechanismInfo returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -2156,9 +2250,11 @@ CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetMechanismList) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         rv = fcn->ST_GetMechanismList(sltp->TokData, slotID,
-                                       pMechanismList, pulCount);
-         TRACE_DEVEL("fcn->ST_GetMechanismList returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -2220,9 +2316,11 @@ CK_RV C_GetObjectSize(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetObjectSize) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GetObjectSize(sltp->TokData, &rSession, hObject, pulSize);
-         TRACE_DEVEL("fcn->ST_GetObjectSize retuned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -2272,10 +2370,12 @@ CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetOperationState) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GetOperationState(sltp->TokData, &rSession,
-                                        pOperationState, pulOperationStateLen);
-         TRACE_DEVEL("fcn->ST_GetOperationState returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -2328,6 +2428,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetSessionInfo) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_GetSessionInfo(sltp->TokData, &rSession, pInfo);
- 
-@@ -2335,6 +2436,7 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
-         TRACE_DEVEL("Slot %lu  State %lx  Flags %lx DevErr %lx\n",
-                     pInfo->slotID, pInfo->state, pInfo->flags,
-                     pInfo->ulDeviceError);
-+        END_OPENSSL_LIBCTX(rv)
- 
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-@@ -2650,11 +2752,13 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_GetTokenInfo) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         rv = fcn->ST_GetTokenInfo(sltp->TokData, slotID, pInfo);
-         if (rv == CKR_OK) {
-             get_sess_count(slotID, &(pInfo->ulSessionCount));
-         }
-         TRACE_DEVEL("rv %lu CK_TOKEN_INFO Flags %lx\n", rv, pInfo->flags);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -2814,6 +2918,35 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     bt_init(&Anchor->sess_btree, free);
-     Anchor->Pid = getpid();
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    /*
-+     * OpenSSL >= 3.0:
-+     * Create a separate library context for Opencryptoki's use of OpenSSL
-+     * services and explicitly load the 'default' provider for this context.
-+     * This prevents call loops when the calling application has configured a
-+     * PKCS#11 provider that uses Opencryptoki under the covers. This could
-+     * produce a loop with the following calling tree:
-+     *   Application -> Openssl -> PKCS11-provider -> Opencryptoki -> OpenSSL
-+     *   -> PKCS11-provider -> Opencryptoki -> ...
-+     * Explicitly using the 'default' provider only for Opencrypoki's OpenSSL
-+     * usage breaks this loop.
-+     */
-+    Anchor->openssl_libctx = OSSL_LIB_CTX_new();
-+    if (Anchor->openssl_libctx == NULL) {
-+        TRACE_ERROR("OSSL_LIB_CTX_new failed.\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto error;
-+    }
-+
-+    Anchor->openssl_default_provider =
-+                    OSSL_PROVIDER_load(Anchor->openssl_libctx, "default");
-+    if (Anchor->openssl_default_provider == NULL) {
-+        TRACE_ERROR("OSSL_PROVIDER_load for 'default' failed.\n");
-+        rc = CKR_FUNCTION_FAILED;
-+        goto error;
-+    }
-+#endif
-+
-     // Get shared memory
-     if ((Anchor->SharedMemP = attach_shared_memory()) == NULL) {
-         OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to attach to "
-@@ -2870,10 +3003,14 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-     }
-     //
-     // load all the slot DLL's here
-+    BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc)
-     for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
-         sltp = &(Anchor->SltList[slotID]);
-         slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID);
-     }
-+    END_OPENSSL_LIBCTX(rc)
-+    if (rc != CKR_OK)
-+        goto error_shm;
- 
-     /* Start event receiver thread */
-     if ((Anchor->SocketDataP.flags & FLAG_EVENT_SUPPORT_DISABLED) == 0 &&
-@@ -2883,6 +3020,7 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-         // unload all the STDLL's from the application
-         // This is in case the APP decides to do the re-initialize and
-         // continue on
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rc)
-         for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
-             sltp = &(Anchor->SltList[slotID]);
-             if (slot_loaded[slotID]) {
-@@ -2895,6 +3033,7 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
-             }
-             DL_UnLoad(sltp, slotID);
-         }
-+        END_OPENSSL_LIBCTX(rc)
- 
-         API_UnRegister();
- 
-@@ -2913,6 +3052,13 @@ error:
-     if (Anchor->socketfd >= 0)
-         close(Anchor->socketfd);
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    if (Anchor->openssl_default_provider != NULL)
-+        OSSL_PROVIDER_unload(Anchor->openssl_default_provider);
-+    if (Anchor->openssl_libctx != NULL)
-+        OSSL_LIB_CTX_free(Anchor->openssl_libctx);
-+#endif
-+
-     free((void *) Anchor);
-     Anchor = NULL;
- 
-@@ -2974,9 +3120,11 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_InitPIN) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_InitPIN(sltp->TokData, &rSession, pPin, ulPinLen);
-         TRACE_DEVEL("fcn->ST_InitPIN returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3042,8 +3190,10 @@ CK_RV C_InitToken(CK_SLOT_ID slotID,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_InitToken) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         rv = fcn->ST_InitToken(sltp->TokData, slotID, pPin, ulPinLen, pLabel);
-         TRACE_DEVEL("fcn->ST_InitToken returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3097,9 +3247,11 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Login) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Login(sltp->TokData, &rSession, userType, pPin, ulPinLen);
-         TRACE_DEVEL("fcn->ST_Login returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3147,9 +3299,11 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession)
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Logout) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Logout(sltp->TokData, &rSession);
-         TRACE_DEVEL("fcn->ST_Logout returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3223,9 +3377,11 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID,
-     }
- 
-     if (fcn->ST_OpenSession) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         rv = fcn->ST_OpenSession(sltp->TokData, slotID, flags,
-                                  &(apiSessp->sessionh));
-         TRACE_DEVEL("fcn->ST_OpenSession returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
- 
-         // If the session allocation is successful, then we need to
-         // complete the API session block and  return.  Otherwise
-@@ -3237,10 +3393,12 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID,
-              */
-             *phSession = AddToSessionList(apiSessp);
-             if (*phSession == 0) {
-+                BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-                 /* failed to add the object to the API-level tree, close the
-                  * STDLL-level session and return failure
-                  */
-                 fcn->ST_CloseSession(sltp->TokData, apiSessp, FALSE);
-+                END_OPENSSL_LIBCTX(rv)
-                 free(apiSessp);
-                 rv = CKR_HOST_MEMORY;
-                 goto done;
-@@ -3310,9 +3468,11 @@ CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SeedRandom) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SeedRandom(sltp->TokData, &rSession, pSeed, ulSeedLen);
-         TRACE_DEVEL("fcn->ST_SeedRandom returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3371,10 +3531,12 @@ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SetAttributeValue) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SetAttributeValue(sltp->TokData, &rSession,
-                                        hObject, pTemplate, ulCount);
-         TRACE_DEVEL("fcn->ST_SetAttributeValue returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3426,12 +3588,14 @@ CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SetOperationState) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SetOperationState(sltp->TokData, &rSession,
-                                        pOperationState,
-                                        ulOperationStateLen,
-                                        hEncryptionKey, hAuthenticationKey);
-         TRACE_DEVEL("fcn->ST_SetOperationState returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3486,10 +3650,12 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SetPIN) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SetPIN(sltp->TokData, &rSession, pOldPin,
-                             ulOldLen, pNewPin, ulNewLen);
-         TRACE_DEVEL("fcn->ST_SetPIN returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3540,10 +3706,12 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Sign) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Sign(sltp->TokData, &rSession, pData, ulDataLen,
-                           pSignature, pulSignatureLen);
-         TRACE_DEVEL("fcn->ST_Sign returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3590,11 +3758,13 @@ CK_RV C_SignEncryptUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SignEncryptUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SignEncryptUpdate(sltp->TokData, &rSession, pPart,
-                                        ulPartLen, pEncryptedPart,
-                                        pulEncryptedPartLen);
-         TRACE_DEVEL("fcn->ST_SignEncryptUpdate return: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3642,10 +3812,12 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SignFinal) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SignFinal(sltp->TokData, &rSession, pSignature,
-                                pulSignatureLen);
-         TRACE_DEVEL("fcn->ST_SignFinal returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3697,9 +3869,11 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SignInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SignInit(sltp->TokData, &rSession, pMechanism, hKey);
-         TRACE_DEVEL("fcn->ST_SignInit returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3745,10 +3919,12 @@ CK_RV C_SignRecover(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SignRecover) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SignRecover(sltp->TokData, &rSession, pData,
-                                  ulDataLen, pSignature, pulSignatureLen);
-         TRACE_DEVEL("fcn->ST_SignRecover returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3796,10 +3972,12 @@ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SignRecoverInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SignRecoverInit(sltp->TokData, &rSession,
-                                      pMechanism, hKey);
-         TRACE_DEVEL("fcn->ST_SignRecoverInit returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3847,9 +4025,11 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_SignUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_SignUpdate(sltp->TokData, &rSession, pPart, ulPartLen);
-         TRACE_DEVEL("fcn->ST_SignUpdate returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3910,12 +4090,14 @@ CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_UnwrapKey) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_UnwrapKey(sltp->TokData, &rSession, pMechanism,
-                                hUnwrappingKey, pWrappedKey,
-                                ulWrappedKeyLen, pTemplate,
-                                ulAttributeCount, phKey);
-         TRACE_DEVEL("fcn->ST_UnwrapKey returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -3962,10 +4144,12 @@ CK_RV C_Verify(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_Verify) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_Verify(sltp->TokData, &rSession, pData, ulDataLen,
-                             pSignature, ulSignatureLen);
-         TRACE_DEVEL("fcn->ST_Verify returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -4009,10 +4193,12 @@ CK_RV C_VerifyFinal(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_VerifyFinal) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_VerifyFinal(sltp->TokData, &rSession, pSignature,
-                                  ulSignatureLen);
-         TRACE_DEVEL("fcn->ST_VerifyFinal returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -4060,9 +4246,11 @@ CK_RV C_VerifyInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_VerifyInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_VerifyInit(sltp->TokData, &rSession, pMechanism, hKey);
-         TRACE_DEVEL("fcn->ST_VerifyInit returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -4109,10 +4297,12 @@ CK_RV C_VerifyRecover(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_VerifyRecover) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_VerifyRecover(sltp->TokData, &rSession, pSignature,
-                                    ulSignatureLen, pData, pulDataLen);
-         TRACE_DEVEL("fcn->ST_VerifyRecover returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -4160,10 +4350,12 @@ CK_RV C_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_VerifyRecoverInit) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_VerifyRecoverInit(sltp->TokData, &rSession,
-                                        pMechanism, hKey);
-         TRACE_DEVEL("fcn->ST_VerifyRecoverInit returned:0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -4207,9 +4399,11 @@ CK_RV C_VerifyUpdate(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_VerifyUpdate) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_VerifyUpdate(sltp->TokData, &rSession, pPart, ulPartLen);
-         TRACE_DEVEL("fcn->ST_VerifyUpdate returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -4407,10 +4601,12 @@ CK_RV C_WrapKey(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_WrapKey) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_WrapKey(sltp->TokData, &rSession, pMechanism,
-                              hWrappingKey, hKey, pWrappedKey, pulWrappedKeyLen);
-         TRACE_DEVEL("fcn->ST_WrapKey returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-@@ -5110,6 +5306,7 @@ CK_RV C_IBM_ReencryptSingle(CK_SESSION_HANDLE hSession,
-         return CKR_TOKEN_NOT_PRESENT;
-     }
-     if (fcn->ST_IBM_ReencryptSingle) {
-+        BEGIN_OPENSSL_LIBCTX(Anchor->openssl_libctx, rv)
-         // Map the Session to the slot session
-         rv = fcn->ST_IBM_ReencryptSingle(sltp->TokData, &rSession, pDecrMech,
-                                          hDecrKey, pEncrMech, hEncrKey,
-@@ -5117,6 +5314,7 @@ CK_RV C_IBM_ReencryptSingle(CK_SESSION_HANDLE hSession,
-                                          pReencryptedData,
-                                          pulReencryptedDataLen);
-         TRACE_DEVEL("fcn->ST_IBM_ReencryptSingle returned: 0x%lx\n", rv);
-+        END_OPENSSL_LIBCTX(rv)
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_NOT_SUPPORTED));
-         rv = CKR_FUNCTION_NOT_SUPPORTED;
-diff --git a/usr/lib/api/socket_client.c b/usr/lib/api/socket_client.c
-index e344ddbf..423972a1 100644
---- a/usr/lib/api/socket_client.c
-+++ b/usr/lib/api/socket_client.c
-@@ -245,11 +245,22 @@ static int handle_event(API_Proc_Struct_t *anchor, event_msg_t *event,
-     return 0;
- }
- 
-+struct cleanup_data {
-+    API_Proc_Struct_t *anchor;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_LIB_CTX *prev_libctx;
-+#endif
-+};
-+
- static void event_thread_cleanup(void *arg)
- {
--    API_Proc_Struct_t *anchor = arg;
-+    struct cleanup_data *cleanup = arg;
- 
--    UNUSED(anchor);
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_LIB_CTX_set0_default(cleanup->prev_libctx);
-+#else
-+    UNUSED(cleanup);
-+#endif
- 
-     TRACE_DEVEL("Event thread %lu terminating\n", pthread_self());
- }
-@@ -257,6 +268,10 @@ static void event_thread_cleanup(void *arg)
- static void *event_thread(void *arg)
- {
-     API_Proc_Struct_t *anchor = arg;
-+    struct cleanup_data cleanup;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_LIB_CTX *prev_libctx;
-+#endif
-     int oldstate, oldtype;
-     struct pollfd pollfd;
-     event_msg_t event;
-@@ -275,10 +290,24 @@ static void *event_thread(void *arg)
-         return NULL;
-     }
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    /* Ensure that the event thread uses Opencryptoki's own library context */
-+    prev_libctx = OSSL_LIB_CTX_set0_default(Anchor->openssl_libctx);
-+    if (prev_libctx == NULL) {
-+        TRACE_ERROR("OSSL_LIB_CTX_set0_default failed\n");
-+        TRACE_DEVEL("Event thread %lu terminating\n", pthread_self());
-+        return NULL;
-+    }
-+#endif
-+
-     /* Enable cancellation */
-     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
-     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
--    pthread_cleanup_push(event_thread_cleanup, anchor);
-+    cleanup.anchor = anchor;
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    cleanup.prev_libctx = prev_libctx;
-+#endif
-+    pthread_cleanup_push(event_thread_cleanup, &cleanup);
- 
-     pollfd.fd = anchor->socketfd;
-     pollfd.events = POLLIN | POLLHUP | POLLERR;
-@@ -395,6 +424,10 @@ static void *event_thread(void *arg)
-     close(anchor->socketfd);
-     anchor->socketfd = -1;
- 
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+    OSSL_LIB_CTX_set0_default(prev_libctx);
-+#endif
-+
-     pthread_cleanup_pop(1);
-     return NULL;
- }
diff --git a/SOURCES/opencryptoki-openssl3-7b4177e8557887d196ce77a129d457e817f8cc59.patch b/SOURCES/opencryptoki-openssl3-7b4177e8557887d196ce77a129d457e817f8cc59.patch
deleted file mode 100644
index 104a5f4..0000000
--- a/SOURCES/opencryptoki-openssl3-7b4177e8557887d196ce77a129d457e817f8cc59.patch
+++ /dev/null
@@ -1,870 +0,0 @@
-commit 7b4177e8557887d196ce77a129d457e817f8cc59
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 10:47:28 2021 +0200
-
-    TPM: Remove deprecated OpenSSL functions
-    
-    All low level RSA functions are deprecated in OpenSSL 3.0.
-    Update the code to not use any of those, and only use the EVP
-    interface.
-    
-    Also remove support for OpenSSL < v1.1.1. This code used even more
-    low level RSA, DES, and AES functions.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/tpm_stdll/tpm_openssl.c b/usr/lib/tpm_stdll/tpm_openssl.c
-index 94ef9a62..0ccc543d 100644
---- a/usr/lib/tpm_stdll/tpm_openssl.c
-+++ b/usr/lib/tpm_stdll/tpm_openssl.c
-@@ -39,50 +39,33 @@
- 
- #include "tpm_specific.h"
- 
--/*
-- * In order to make opencryptoki compatible with
-- * OpenSSL 1.1 API Changes and backward compatible
-- * we need to check for its version
-- */
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--#define OLDER_OPENSSL
-+#if OPENSSL_VERSION_PREREQ(3, 0)
-+#include <openssl/core_names.h>
- #endif
- 
- #ifdef DEBUG
- void openssl_print_errors()
- {
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     ERR_load_ERR_strings();
-+#endif
-     ERR_load_crypto_strings();
-     ERR_print_errors_fp(stderr);
- }
- #endif
- 
--RSA *openssl_gen_key(STDLL_TokData_t *tokdata)
-+EVP_PKEY *openssl_gen_key(STDLL_TokData_t *tokdata)
- {
--    RSA *rsa = NULL;
-     int rc = 0, counter = 0;
-     char buf[32];
--#ifndef OLDER_OPENSSL
-     EVP_PKEY *pkey = NULL;
-     EVP_PKEY_CTX *ctx = NULL;
-     BIGNUM *bne = NULL;
--#endif
- 
-     token_specific_rng(tokdata, (CK_BYTE *) buf, 32);
-     RAND_seed(buf, 32);
- 
- regen_rsa_key:
--#ifdef OLDER_OPENSSL
--    rsa = RSA_generate_key(2048, 65537, NULL, NULL);
--    if (rsa == NULL) {
--        fprintf(stderr, "Error generating user's RSA key\n");
--        ERR_load_crypto_strings();
--        ERR_print_errors_fp(stderr);
--        goto err;
--    }
--
--    rc = RSA_check_key(rsa);
--#else
-     bne = BN_new();
-     rc = BN_set_word(bne, 65537);
-     if (!rc) {
-@@ -98,35 +81,36 @@ regen_rsa_key:
- 
-     if (EVP_PKEY_keygen_init(ctx) <= 0
-         || EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 2048) <= 0
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-         || EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, bne) <= 0) {
-+#else
-+        || EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, bne) <= 0) {
-+#endif
-         fprintf(stderr, "Error generating user's RSA key\n");
-         ERR_load_crypto_strings();
-         ERR_print_errors_fp(stderr);
-         goto err;
-     }
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     bne = NULL; // will be freed as part of the context
--    if (EVP_PKEY_keygen(ctx, &pkey) <= 0
--        || (rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
-+#else
-+    BN_free(bne);
-+    bne = NULL;
-+#endif
-+    if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
-         fprintf(stderr, "Error generating user's RSA key\n");
-         ERR_load_crypto_strings();
-         ERR_print_errors_fp(stderr);
-         goto err;
-     }
--#if OPENSSL_VERSION_NUMBER < 0x10101000L
--    rc = RSA_check_key(rsa);
--#else
-     EVP_PKEY_CTX_free(ctx);
-     ctx = EVP_PKEY_CTX_new(pkey, NULL);
-     if (ctx == NULL)
-         goto err;
-     rc = (EVP_PKEY_check(ctx) == 1 ? 1 : 0);
--#endif
--#endif
-     switch (rc) {
-     case 0:
-         /* rsa is not a valid RSA key */
--        RSA_free(rsa);
--        rsa = NULL;
-         counter++;
-         if (counter == KEYGEN_RETRY) {
-             TRACE_DEVEL("Tried %d times to generate a "
-@@ -145,30 +129,23 @@ regen_rsa_key:
-         break;
-     }
- 
--#ifndef OLDER_OPENSSL
--    if (pkey != NULL)
--        EVP_PKEY_free(pkey);
-     if (ctx != NULL)
-         EVP_PKEY_CTX_free(ctx);
-     if (bne != NULL)
-         BN_free(bne);
--#endif
--    return rsa;
-+    return pkey;
- err:
--    if (rsa != NULL)
--        RSA_free(rsa);
--#ifndef OLDER_OPENSSL
-     if (pkey != NULL)
-         EVP_PKEY_free(pkey);
-     if (ctx != NULL)
-         EVP_PKEY_CTX_free(ctx);
-     if (bne != NULL)
-         BN_free(bne);
--#endif
-+
-     return NULL;
- }
- 
--int openssl_write_key(STDLL_TokData_t * tokdata, RSA * rsa, char *filename,
-+int openssl_write_key(STDLL_TokData_t * tokdata, EVP_PKEY *pkey, char *filename,
-                       CK_BYTE * pPin)
- {
-     BIO *b = NULL;
-@@ -193,8 +170,8 @@ int openssl_write_key(STDLL_TokData_t * tokdata, RSA * rsa, char *filename,
-         return -1;
-     }
- 
--    if (!PEM_write_bio_RSAPrivateKey(b, rsa,
--                                     EVP_aes_256_cbc(), NULL, 0, 0, pPin)) {
-+    if (!PEM_write_bio_PrivateKey(b, pkey,
-+                                  EVP_aes_256_cbc(), NULL, 0, 0, pPin)) {
-         BIO_free(b);
-         TRACE_ERROR("Writing key %s to disk failed.\n", loc);
-         DEBUG_openssl_print_errors();
-@@ -211,10 +188,10 @@ int openssl_write_key(STDLL_TokData_t * tokdata, RSA * rsa, char *filename,
- }
- 
- CK_RV openssl_read_key(STDLL_TokData_t * tokdata, char *filename,
--                       CK_BYTE * pPin, RSA ** ret)
-+                       CK_BYTE * pPin, EVP_PKEY **ret)
- {
-     BIO *b = NULL;
--    RSA *rsa = NULL;
-+    EVP_PKEY *pkey = NULL;
-     char loc[PATH_MAX];
-     struct passwd *pw = NULL;
-     CK_RV rc = CKR_FUNCTION_FAILED;
-@@ -242,7 +219,7 @@ CK_RV openssl_read_key(STDLL_TokData_t * tokdata, char *filename,
-         return CKR_FILE_NOT_FOUND;
-     }
- 
--    if ((rsa = PEM_read_bio_RSAPrivateKey(b, NULL, 0, pPin)) == NULL) {
-+    if ((pkey = PEM_read_bio_PrivateKey(b, NULL, 0, pPin)) == NULL) {
-         TRACE_ERROR("Reading key %s from disk failed.\n", loc);
-         DEBUG_openssl_print_errors();
-         if (ERR_GET_REASON(ERR_get_error()) == PEM_R_BAD_DECRYPT) {
-@@ -253,40 +230,54 @@ CK_RV openssl_read_key(STDLL_TokData_t * tokdata, char *filename,
-     }
- 
-     BIO_free(b);
--    *ret = rsa;
-+    *ret = pkey;
- 
-     return CKR_OK;
- }
- 
--int openssl_get_modulus_and_prime(RSA * rsa, unsigned int *size_n,
-+int openssl_get_modulus_and_prime(EVP_PKEY *pkey, unsigned int *size_n,
-                                   unsigned char *n, unsigned int *size_p,
-                                   unsigned char *p)
- {
--#ifndef OLDER_OPENSSL
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-     const BIGNUM *n_tmp, *p_tmp;
-+    RSA *rsa;
-+#else
-+    BIGNUM *n_tmp, *p_tmp;
- #endif
- 
-+#if !OPENSSL_VERSION_PREREQ(3, 0)
-+    rsa = EVP_PKEY_get0_RSA(pkey);
-     /* get the modulus from the RSA object */
--#ifdef OLDER_OPENSSL
--    if ((*size_n = BN_bn2bin(rsa->n, n)) <= 0) {
--#else
-     RSA_get0_key(rsa, &n_tmp, NULL, NULL);
-     if ((*size_n = BN_bn2bin(n_tmp, n)) <= 0) {
--#endif
-         DEBUG_openssl_print_errors();
-         return -1;
-     }
- 
-     /* get one of the primes from the RSA object */
--#ifdef OLDER_OPENSSL
--    if ((*size_p = BN_bn2bin(rsa->p, p)) <= 0) {
--#else
-     RSA_get0_factors(rsa, &p_tmp, NULL);
-     if ((*size_p = BN_bn2bin(p_tmp, p)) <= 0) {
--#endif
-         DEBUG_openssl_print_errors();
-         return -1;
-     }
-+#else
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_N, &n_tmp) ||
-+        (*size_n = BN_bn2bin(n_tmp, n)) <= 0) {
-+        DEBUG_openssl_print_errors();
-+        BN_free(n_tmp);
-+        return -1;
-+    }
-+    BN_free(n_tmp);
-+
-+    if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, &p_tmp) ||
-+        (*size_p = BN_bn2bin(p_tmp, p)) <= 0) {
-+        DEBUG_openssl_print_errors();
-+        BN_free(p_tmp);
-+        return -1;
-+    }
-+    BN_free(p_tmp);
-+#endif
- 
-     return 0;
- }
-diff --git a/usr/lib/tpm_stdll/tpm_specific.c b/usr/lib/tpm_stdll/tpm_specific.c
-index 4ebb4a88..45bc4b78 100644
---- a/usr/lib/tpm_stdll/tpm_specific.c
-+++ b/usr/lib/tpm_stdll/tpm_specific.c
-@@ -1451,15 +1451,15 @@ CK_RV token_create_private_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash,
-     tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data;
-     CK_RV rc;
-     TSS_RESULT result;
--    RSA *rsa;
-+    EVP_PKEY *pkey;
-     unsigned int size_n, size_p;
-     unsigned char n[256], p[256];
- 
-     /* all sw generated keys are 2048 bits */
--    if ((rsa = openssl_gen_key(tokdata)) == NULL)
-+    if ((pkey = openssl_gen_key(tokdata)) == NULL)
-         return CKR_HOST_MEMORY;
- 
--    if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) {
-+    if (openssl_get_modulus_and_prime(pkey, &size_n, n, &size_p, p) != 0) {
-         TRACE_DEVEL("openssl_get_modulus_and_prime failed\n");
-         return CKR_FUNCTION_FAILED;
-     }
-@@ -1473,13 +1473,13 @@ CK_RV token_create_private_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash,
-         return rc;
-     }
- 
--    if (openssl_write_key(tokdata, rsa, TPMTOK_PRIV_ROOT_KEY_FILE, pPin)) {
-+    if (openssl_write_key(tokdata, pkey, TPMTOK_PRIV_ROOT_KEY_FILE, pPin)) {
-         TRACE_DEVEL("openssl_write_key failed.\n");
--        RSA_free(rsa);
-+        EVP_PKEY_free(pkey);
-         return CKR_FUNCTION_FAILED;
-     }
- 
--    RSA_free(rsa);
-+    EVP_PKEY_free(pkey);
- 
-     /* store the user base key in a PKCS#11 object internally */
-     rc = token_store_tss_key(tokdata, tpm_data->hPrivateRootKey,
-@@ -1529,15 +1529,15 @@ CK_RV token_create_public_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash,
-     tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data;
-     CK_RV rc;
-     TSS_RESULT result;
--    RSA *rsa;
-+    EVP_PKEY *pkey;
-     unsigned int size_n, size_p;
-     unsigned char n[256], p[256];
- 
-     /* all sw generated keys are 2048 bits */
--    if ((rsa = openssl_gen_key(tokdata)) == NULL)
-+    if ((pkey = openssl_gen_key(tokdata)) == NULL)
-         return CKR_HOST_MEMORY;
- 
--    if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) {
-+    if (openssl_get_modulus_and_prime(pkey, &size_n, n, &size_p, p) != 0) {
-         TRACE_DEVEL("openssl_get_modulus_and_prime failed\n");
-         return CKR_FUNCTION_FAILED;
-     }
-@@ -1551,13 +1551,13 @@ CK_RV token_create_public_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash,
-         return rc;
-     }
- 
--    if (openssl_write_key(tokdata, rsa, TPMTOK_PUB_ROOT_KEY_FILE, pPin)) {
-+    if (openssl_write_key(tokdata, pkey, TPMTOK_PUB_ROOT_KEY_FILE, pPin)) {
-         TRACE_DEVEL("openssl_write_key\n");
--        RSA_free(rsa);
-+        EVP_PKEY_free(pkey);
-         return CKR_FUNCTION_FAILED;
-     }
- 
--    RSA_free(rsa);
-+    EVP_PKEY_free(pkey);
- 
-     result = Tspi_Key_LoadKey(tpm_data->hPublicRootKey, tpm_data->hSRK);
-     if (result) {
-@@ -1602,7 +1602,7 @@ CK_RV token_create_public_tree(STDLL_TokData_t * tokdata, CK_BYTE * pinHash,
- CK_RV token_migrate(STDLL_TokData_t * tokdata, int key_type, CK_BYTE * pin)
- {
-     tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data;
--    RSA *rsa;
-+    EVP_PKEY *pkey;
-     char *backup_loc;
-     unsigned int size_n, size_p;
-     unsigned char n[256], p[256];
-@@ -1630,7 +1630,7 @@ CK_RV token_migrate(STDLL_TokData_t * tokdata, int key_type, CK_BYTE * pin)
-     }
- 
-     /* read the backup key with the old pin */
--    if ((rc = openssl_read_key(tokdata, backup_loc, pin, &rsa))) {
-+    if ((rc = openssl_read_key(tokdata, backup_loc, pin, &pkey))) {
-         if (rc == CKR_FILE_NOT_FOUND)
-             rc = CKR_FUNCTION_FAILED;
-         TRACE_DEVEL("openssl_read_key failed\n");
-@@ -1640,8 +1640,9 @@ CK_RV token_migrate(STDLL_TokData_t * tokdata, int key_type, CK_BYTE * pin)
-     /* So, reading the backup openssl key off disk succeeded with the SOs PIN.
-      * We will now try to re-wrap that key with the current SRK
-      */
--    if (openssl_get_modulus_and_prime(rsa, &size_n, n, &size_p, p) != 0) {
-+    if (openssl_get_modulus_and_prime(pkey, &size_n, n, &size_p, p) != 0) {
-         TRACE_DEVEL("openssl_get_modulus_and_prime failed\n");
-+        EVP_PKEY_free(pkey);
-         return CKR_FUNCTION_FAILED;
-     }
- 
-@@ -1650,10 +1651,10 @@ CK_RV token_migrate(STDLL_TokData_t * tokdata, int key_type, CK_BYTE * pin)
-                            phKey);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("token_wrap_sw_key failed. rc=0x%lx\n", rc);
--        RSA_free(rsa);
-+        EVP_PKEY_free(pkey);
-         return rc;
-     }
--    RSA_free(rsa);
-+    EVP_PKEY_free(pkey);
- 
-     result = Tspi_Key_LoadKey(*phKey, tpm_data->hSRK);
-     if (result) {
-@@ -1998,7 +1999,7 @@ CK_RV token_specific_set_pin(STDLL_TokData_t * tokdata, SESSION * sess,
-     tpm_private_data_t *tpm_data = (tpm_private_data_t *)tokdata->private_data;
-     CK_BYTE oldpin_hash[SHA1_HASH_SIZE], newpin_hash[SHA1_HASH_SIZE];
-     CK_RV rc;
--    RSA *rsa_root;
-+    EVP_PKEY *pkey_root;
-     TSS_RESULT result;
- 
-     if (!sess) {
-@@ -2094,7 +2095,7 @@ CK_RV token_specific_set_pin(STDLL_TokData_t * tokdata, SESSION * sess,
- 
-         /* read the backup key with the old pin */
-         rc = openssl_read_key(tokdata, TPMTOK_PRIV_ROOT_KEY_FILE, pOldPin,
--                              &rsa_root);
-+                              &pkey_root);
-         if (rc != CKR_OK) {
-             if (rc == CKR_FILE_NOT_FOUND) {
-                 /* If the user has moved his backup PEM file off site, allow a
-@@ -2107,14 +2108,14 @@ CK_RV token_specific_set_pin(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* write it out using the new pin */
--        rc = openssl_write_key(tokdata, rsa_root, TPMTOK_PRIV_ROOT_KEY_FILE,
-+        rc = openssl_write_key(tokdata, pkey_root, TPMTOK_PRIV_ROOT_KEY_FILE,
-                                pNewPin);
-         if (rc != CKR_OK) {
--            RSA_free(rsa_root);
-+            EVP_PKEY_free(pkey_root);
-             TRACE_DEVEL("openssl_write_key failed\n");
-             return CKR_FUNCTION_FAILED;
-         }
--        RSA_free(rsa_root);
-+        EVP_PKEY_free(pkey_root);
-     } else if (sess->session_info.state == CKS_RW_SO_FUNCTIONS) {
-         if (tpm_data->not_initialized) {
-             if (memcmp(default_so_pin_sha, oldpin_hash, SHA1_HASH_SIZE)) {
-@@ -2166,7 +2167,7 @@ CK_RV token_specific_set_pin(STDLL_TokData_t * tokdata, SESSION * sess,
- 
-         /* change auth on the public root key's openssl backup */
-         rc = openssl_read_key(tokdata, TPMTOK_PUB_ROOT_KEY_FILE, pOldPin,
--                              &rsa_root);
-+                              &pkey_root);
-         if (rc != CKR_OK) {
-             if (rc == CKR_FILE_NOT_FOUND) {
-                 /* If the user has moved his backup PEM file off site, allow a
-@@ -2179,14 +2180,14 @@ CK_RV token_specific_set_pin(STDLL_TokData_t * tokdata, SESSION * sess,
-         }
- 
-         /* write it out using the new pin */
--        rc = openssl_write_key(tokdata, rsa_root, TPMTOK_PUB_ROOT_KEY_FILE,
-+        rc = openssl_write_key(tokdata, pkey_root, TPMTOK_PUB_ROOT_KEY_FILE,
-                                pNewPin);
-         if (rc != CKR_OK) {
--            RSA_free(rsa_root);
-+            EVP_PKEY_free(pkey_root);
-             TRACE_DEVEL("openssl_write_key failed\n");
-             return CKR_FUNCTION_FAILED;
-         }
--        RSA_free(rsa_root);
-+        EVP_PKEY_free(pkey_root);
-     } else {
-         TRACE_ERROR("%s\n", ock_err(ERR_SESSION_READ_ONLY));
-         rc = CKR_SESSION_READ_ONLY;
-@@ -2401,60 +2402,6 @@ CK_RV token_specific_des_ecb(STDLL_TokData_t * tokdata,
-                              CK_ULONG * out_data_len,
-                              OBJECT * key, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc;
--    CK_ATTRIBUTE *attr = NULL;
--
--    DES_key_schedule des_key2;
--    const_DES_cblock key_val_SSL, in_key_data;
--    DES_cblock out_key_data;
--    unsigned int i, j;
--
--    UNUSED(tokdata);
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
--        return rc;
--    }
--
--    // Create the key schedule
--    memcpy(&key_val_SSL, attr->pValue, 8);
--    DES_set_key_unchecked(&key_val_SSL, &des_key2);
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // Both the encrypt and the decrypt are done 8 bytes at a time
--    if (encrypt) {
--        for (i = 0; i < in_data_len; i = i + 8) {
--            memcpy(in_key_data, in_data + i, 8);
--            DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2,
--                            DES_ENCRYPT);
--            memcpy(out_data + i, out_key_data, 8);
--        }
--
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--
--        for (j = 0; j < in_data_len; j = j + 8) {
--            memcpy(in_key_data, in_data + j, 8);
--            DES_ecb_encrypt(&in_key_data, &out_key_data, &des_key2,
--                            DES_DECRYPT);
--            memcpy(out_data + j, out_key_data, 8);
--        }
--
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_ecb();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -2501,7 +2448,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_des_cbc(STDLL_TokData_t * tokdata,
-@@ -2511,50 +2457,6 @@ CK_RV token_specific_des_cbc(STDLL_TokData_t * tokdata,
-                              CK_ULONG * out_data_len,
-                              OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc;
--    CK_ATTRIBUTE *attr = NULL;
--
--    DES_cblock ivec;
--
--    DES_key_schedule des_key2;
--    const_DES_cblock key_val_SSL;
--
--    UNUSED(tokdata);
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
--        return rc;
--    }
--
--    // Create the key schedule
--    memcpy(&key_val_SSL, attr->pValue, 8);
--    DES_set_key_unchecked(&key_val_SSL, &des_key2);
--
--    memcpy(&ivec, init_v, 8);
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--
--
--    if (encrypt) {
--        DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec,
--                         DES_ENCRYPT);
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--        DES_ncbc_encrypt(in_data, out_data, in_data_len, &des_key2, &ivec,
--                         DES_DECRYPT);
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_cbc();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -2601,7 +2503,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata,
-@@ -2611,83 +2512,6 @@ CK_RV token_specific_tdes_ecb(STDLL_TokData_t * tokdata,
-                               CK_ULONG * out_data_len,
-                               OBJECT * key, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc;
--    CK_ATTRIBUTE *attr = NULL;
--    CK_KEY_TYPE keytype;
--    CK_BYTE key_value[3 * DES_KEY_SIZE];
--
--    unsigned int k, j;
--    DES_key_schedule des_key1;
--    DES_key_schedule des_key2;
--    DES_key_schedule des_key3;
--
--    const_DES_cblock key_SSL1, key_SSL2, key_SSL3, in_key_data;
--    DES_cblock out_key_data;
--
--    UNUSED(tokdata);
--
--    // get the key type
--    rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n");
--        return rc;
--    }
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--
--    if (keytype == CKK_DES2) {
--        memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE);
--        memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE);
--    } else {
--        memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE);
--    }
--
--    // The key as passed is a 24 byte long string containing three des keys
--    // pick them apart and create the 3 corresponding key schedules
--    memcpy(&key_SSL1, key_value, 8);
--    memcpy(&key_SSL2, key_value + 8, 8);
--    memcpy(&key_SSL3, key_value + 16, 8);
--    DES_set_key_unchecked(&key_SSL1, &des_key1);
--    DES_set_key_unchecked(&key_SSL2, &des_key2);
--    DES_set_key_unchecked(&key_SSL3, &des_key3);
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // the encrypt and decrypt are done 8 bytes at a time
--    if (encrypt) {
--        for (k = 0; k < in_data_len; k = k + 8) {
--            memcpy(in_key_data, in_data + k, 8);
--            DES_ecb3_encrypt((const_DES_cblock *) & in_key_data,
--                             (DES_cblock *) & out_key_data,
--                             &des_key1, &des_key2, &des_key3, DES_ENCRYPT);
--            memcpy(out_data + k, out_key_data, 8);
--        }
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--        for (j = 0; j < in_data_len; j = j + 8) {
--            memcpy(in_key_data, in_data + j, 8);
--            DES_ecb3_encrypt((const_DES_cblock *) & in_key_data,
--                             (DES_cblock *) & out_key_data,
--                             &des_key1, &des_key2, &des_key3, DES_DECRYPT);
--            memcpy(out_data + j, out_key_data, 8);
--        }
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_ede3_ecb();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -2747,7 +2571,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata,
-@@ -2757,81 +2580,6 @@ CK_RV token_specific_tdes_cbc(STDLL_TokData_t * tokdata,
-                               CK_ULONG * out_data_len,
-                               OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_RV rc = CKR_OK;
--    CK_ATTRIBUTE *attr = NULL;
--    CK_KEY_TYPE keytype;
--    CK_BYTE key_value[3 * DES_KEY_SIZE];
--
--    DES_key_schedule des_key1;
--    DES_key_schedule des_key2;
--    DES_key_schedule des_key3;
--
--    const_DES_cblock key_SSL1, key_SSL2, key_SSL3;
--    DES_cblock ivec;
--
--    UNUSED(tokdata);
--
--    // get the key type
--    rc = template_attribute_get_ulong(key->template, CKA_KEY_TYPE, &keytype);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_KEY_TYPE for the key\n");
--        return rc;
--    }
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key\n");
--        return rc;
--    }
--
--    if (keytype == CKK_DES2) {
--        memcpy(key_value, attr->pValue, 2 * DES_KEY_SIZE);
--        memcpy(key_value + (2 * DES_KEY_SIZE), attr->pValue, DES_KEY_SIZE);
--    } else {
--        memcpy(key_value, attr->pValue, 3 * DES_KEY_SIZE);
--    }
--
--    // The key as passed in is a 24 byte string containing 3 keys
--    // pick it apart and create the key schedules
--    memcpy(&key_SSL1, key_value, 8);
--    memcpy(&key_SSL2, key_value + 8, 8);
--    memcpy(&key_SSL3, key_value + 16, 8);
--    DES_set_key_unchecked(&key_SSL1, &des_key1);
--    DES_set_key_unchecked(&key_SSL2, &des_key2);
--    DES_set_key_unchecked(&key_SSL3, &des_key3);
--
--    memcpy(ivec, init_v, sizeof(ivec));
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by 8
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // Encrypt or decrypt the data
--    if (encrypt) {
--        DES_ede3_cbc_encrypt(in_data,
--                             out_data,
--                             in_data_len,
--                             &des_key1,
--                             &des_key2, &des_key3, &ivec, DES_ENCRYPT);
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    } else {
--        DES_ede3_cbc_encrypt(in_data,
--                             out_data,
--                             in_data_len,
--                             &des_key1,
--                             &des_key2, &des_key3, &ivec, DES_DECRYPT);
--
--        *out_data_len = in_data_len;
--        rc = CKR_OK;
--    }
--
--    return rc;
--#else
-     const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
-     EVP_CIPHER_CTX *ctx = NULL;
-     CK_ATTRIBUTE *attr = NULL;
-@@ -2891,7 +2639,6 @@ done:
-     OPENSSL_cleanse(dkey, sizeof(dkey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- /* wrap the 20 bytes of auth data @authData and store in an attribute of the two
-@@ -3626,49 +3373,6 @@ CK_RV token_specific_aes_ecb(STDLL_TokData_t * tokdata,
-                              CK_ULONG * out_data_len,
-                              OBJECT * key, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    CK_ATTRIBUTE *attr = NULL;
--    AES_KEY ssl_aes_key;
--    unsigned int i;
--    /* There's a previous check that in_data_len % AES_BLOCK_SIZE == 0,
--     * so this is fine */
--    CK_ULONG loops = (CK_ULONG) (in_data_len / AES_BLOCK_SIZE);
--    CK_RV rc;
--
--    UNUSED(tokdata);
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
--        return rc;
--    }
--
--    memset(&ssl_aes_key, 0, sizeof(AES_KEY));
--
--    // AES_ecb_encrypt encrypts only a single block, so we have to break up the
--    // input data here
--    if (encrypt) {
--        AES_set_encrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        for (i = 0; i < loops; i++) {
--            AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE),
--                            (unsigned char *) out_data + (i * AES_BLOCK_SIZE),
--                            &ssl_aes_key, AES_ENCRYPT);
--        }
--    } else {
--        AES_set_decrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        for (i = 0; i < loops; i++) {
--            AES_ecb_encrypt((unsigned char *) in_data + (i * AES_BLOCK_SIZE),
--                            (unsigned char *) out_data + (i * AES_BLOCK_SIZE),
--                            &ssl_aes_key, AES_DECRYPT);
--        }
--    }
--    *out_data_len = in_data_len;
--
--    return CKR_OK;
--#else
-     CK_RV rc;
-     int outlen;
-     unsigned char akey[AES_KEY_SIZE_256];
-@@ -3729,7 +3433,6 @@ done:
-     OPENSSL_cleanse(akey, sizeof(akey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_aes_cbc(STDLL_TokData_t * tokdata,
-@@ -3739,39 +3442,6 @@ CK_RV token_specific_aes_cbc(STDLL_TokData_t * tokdata,
-                              CK_ULONG * out_data_len,
-                              OBJECT * key, CK_BYTE * init_v, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    AES_KEY ssl_aes_key;
--    CK_ATTRIBUTE *attr = NULL;
--    CK_RV rc;
--
--    UNUSED(tokdata);
--
--    // get the key value
--    rc = template_attribute_get_non_empty(key->template, CKA_VALUE, &attr);
--    if (rc != CKR_OK) {
--        TRACE_ERROR("Could not find CKA_VALUE for the key.\n");
--        return rc;
--    }
--
--    memset(&ssl_aes_key, 0, sizeof(AES_KEY));
--
--    // AES_cbc_encrypt chunks the data into AES_BLOCK_SIZE blocks, unlike
--    // AES_ecb_encrypt, so no looping required.
--    if (encrypt) {
--        AES_set_encrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data,
--                        in_data_len, &ssl_aes_key, init_v, AES_ENCRYPT);
--    } else {
--        AES_set_decrypt_key((unsigned char *) attr->pValue,
--                            (attr->ulValueLen * 8), &ssl_aes_key);
--        AES_cbc_encrypt((unsigned char *) in_data, (unsigned char *) out_data,
--                        in_data_len, &ssl_aes_key, init_v, AES_DECRYPT);
--    }
--    *out_data_len = in_data_len;
--
--    return CKR_OK;
--#else
-     CK_RV rc;
-     int outlen;
-     unsigned char akey[AES_KEY_SIZE_256];
-@@ -3832,7 +3502,6 @@ done:
-     OPENSSL_cleanse(akey, sizeof(akey));
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV token_specific_get_mechanism_list(STDLL_TokData_t * tokdata,
-diff --git a/usr/lib/tpm_stdll/tpm_specific.h b/usr/lib/tpm_stdll/tpm_specific.h
-index 81af2744..2ffd0afc 100644
---- a/usr/lib/tpm_stdll/tpm_specific.h
-+++ b/usr/lib/tpm_stdll/tpm_specific.h
-@@ -56,10 +56,10 @@
- /* retry count for generating software RSA keys */
- #define KEYGEN_RETRY    5
- 
--RSA *openssl_gen_key(STDLL_TokData_t *);
--int openssl_write_key(STDLL_TokData_t *, RSA *, char *, CK_BYTE *);
--CK_RV openssl_read_key(STDLL_TokData_t *, char *, CK_BYTE *, RSA **);
--int openssl_get_modulus_and_prime(RSA *, unsigned int *, unsigned char *,
-+EVP_PKEY *openssl_gen_key(STDLL_TokData_t *);
-+int openssl_write_key(STDLL_TokData_t *, EVP_PKEY *, char *, CK_BYTE *);
-+CK_RV openssl_read_key(STDLL_TokData_t *, char *, CK_BYTE *, EVP_PKEY **);
-+int openssl_get_modulus_and_prime(EVP_PKEY *, unsigned int *, unsigned char *,
-                                   unsigned int *, unsigned char *);
- int util_set_file_mode(char *, mode_t);
- CK_BYTE *util_create_id(int);
diff --git a/SOURCES/opencryptoki-openssl3-93588f53d918fe6c7452da076b95081fb6aa9aef.patch b/SOURCES/opencryptoki-openssl3-93588f53d918fe6c7452da076b95081fb6aa9aef.patch
deleted file mode 100644
index a9d436e..0000000
--- a/SOURCES/opencryptoki-openssl3-93588f53d918fe6c7452da076b95081fb6aa9aef.patch
+++ /dev/null
@@ -1,1847 +0,0 @@
-commit 93588f53d918fe6c7452da076b95081fb6aa9aef
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jun 30 13:18:39 2021 +0200
-
-    COMMON: Prevent unsavable operation state to be exported
-    
-    Tokens using OpenSSL 3.0 to implement digest operations (SHA, MD5) are no
-    longer able to store its digest state in the session context in a way
-    that it could be exported via C_GetOperationState(). OpenSSL 3.0 does not
-    provide support to get the digest state. A token must therefore place
-    pointers to OpenSSL digest contexts into the session state structure.
-    Such a state can not be externalized through C_GetOperationState().
-    
-    Also see the discussion in OpenSSL issue "Digest State Serialization":
-    https://github.com/openssl/openssl/issues/14222
-    
-    Allow a token to mark an operation context as 'not saveable', which will
-    cause C_GetOperationState() to return CKR_STATE_UNSAVEABLE if it is tried
-    to save such a state.
-    
-    Also, such operation contexts can not simply be freed that way the common
-    code performs that. Allow a token to use a custom context free function,
-    to cleanup such complex context structures.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/decr_mgr.c b/usr/lib/common/decr_mgr.c
-index 9842302b..fea6c99e 100644
---- a/usr/lib/common/decr_mgr.c
-+++ b/usr/lib/common/decr_mgr.c
-@@ -620,7 +620,8 @@ done:
- 
- //
- //
--CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx)
-+CK_RV decr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                       ENCR_DECR_CONTEXT *ctx)
- {
-     if (!ctx) {
-         TRACE_ERROR("Invalid function argument.\n");
-@@ -635,6 +636,7 @@ CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx)
-     ctx->init_pending = FALSE;
-     ctx->context_len = 0;
-     ctx->pkey_active = FALSE;
-+    ctx->state_unsaveable = FALSE;
- 
-     if (ctx->mech.pParameter) {
-         free(ctx->mech.pParameter);
-@@ -642,9 +644,14 @@ CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx)
-     }
- 
-     if (ctx->context) {
--        free(ctx->context);
-+        if (ctx->context_free_func != NULL)
-+            ctx->context_free_func(tokdata, sess, ctx->context,
-+                                   ctx->context_len);
-+        else
-+            free(ctx->context);
-         ctx->context = NULL;
-     }
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-diff --git a/usr/lib/common/dig_mgr.c b/usr/lib/common/dig_mgr.c
-index 77cb60a1..222eee75 100644
---- a/usr/lib/common/dig_mgr.c
-+++ b/usr/lib/common/dig_mgr.c
-@@ -63,7 +63,7 @@ CK_RV digest_mgr_init(STDLL_TokData_t *tokdata,
-         ctx->context = NULL;
-         rc = sha_init(tokdata, sess, ctx, mech);
-         if (rc != CKR_OK) {
--            digest_mgr_cleanup(ctx);    // to de-initialize context above
-+            digest_mgr_cleanup(tokdata, sess, ctx);    // to de-initialize context above
-             TRACE_ERROR("Failed to init sha context.\n");
-             return rc;
-         }
-@@ -76,7 +76,7 @@ CK_RV digest_mgr_init(STDLL_TokData_t *tokdata,
-         ctx->context_len = sizeof(MD2_CONTEXT);
-         ctx->context = (CK_BYTE *) malloc(sizeof(MD2_CONTEXT));
-         if (!ctx->context) {
--            digest_mgr_cleanup(ctx);    // to de-initialize context above
-+            digest_mgr_cleanup(tokdata, sess, ctx);    // to de-initialize context above
-             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-             return CKR_HOST_MEMORY;
-         }
-@@ -90,7 +90,7 @@ CK_RV digest_mgr_init(STDLL_TokData_t *tokdata,
-           ctx->context = NULL;
-           rc = md5_init(tokdata, sess, ctx, mech);
-           if (rc != CKR_OK) {
--              digest_mgr_cleanup(ctx);    // to de-initialize context above
-+              digest_mgr_cleanup(tokdata, sess, ctx);    // to de-initialize context above
-               TRACE_ERROR("Failed to init md5 context.\n");
-               return rc;
-           }
-@@ -103,7 +103,7 @@ CK_RV digest_mgr_init(STDLL_TokData_t *tokdata,
-     if (mech->ulParameterLen > 0 && mech->pParameter != NULL) {
-         ptr = (CK_BYTE *) malloc(mech->ulParameterLen);
-         if (!ptr) {
--            digest_mgr_cleanup(ctx);    // to de-initialize context above
-+            digest_mgr_cleanup(tokdata, sess, ctx);    // to de-initialize context above
-             TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
-             return CKR_HOST_MEMORY;
-         }
-@@ -122,7 +122,8 @@ CK_RV digest_mgr_init(STDLL_TokData_t *tokdata,
- 
- //
- //
--CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx)
-+CK_RV digest_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                         DIGEST_CONTEXT *ctx)
- {
-     if (!ctx) {
-         TRACE_ERROR("Invalid function argument.\n");
-@@ -134,6 +135,7 @@ CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx)
-     ctx->multi = FALSE;
-     ctx->active = FALSE;
-     ctx->context_len = 0;
-+    ctx->state_unsaveable = FALSE;
- 
-     if (ctx->mech.pParameter) {
-         free(ctx->mech.pParameter);
-@@ -141,9 +143,14 @@ CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx)
-     }
- 
-     if (ctx->context != NULL) {
--        free(ctx->context);
-+        if (ctx->context_free_func != NULL)
-+            ctx->context_free_func(tokdata, sess, ctx->context,
-+                                   ctx->context_len);
-+        else
-+            free(ctx->context);
-         ctx->context = NULL;
-     }
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-@@ -232,7 +239,7 @@ out:
-         // unless it returns CKR_BUFFER_TOO_SMALL or is a successful call (i.e.,
-         // one which returns CKR_OK) to determine the length of the buffer
-         // needed to hold the message digest."
--        digest_mgr_cleanup(ctx);
-+        digest_mgr_cleanup(tokdata, sess, ctx);
-     }
- 
-     return rc;
-@@ -301,7 +308,7 @@ CK_RV digest_mgr_digest_update(STDLL_TokData_t *tokdata,
- 
- out:
-     if (rc != CKR_OK) {
--        digest_mgr_cleanup(ctx);
-+        digest_mgr_cleanup(tokdata, sess, ctx);
-         // "A call to C_DigestUpdate which results in an error
-         // terminates the current digest operation."
-     }
-@@ -373,7 +380,7 @@ CK_RV digest_mgr_digest_key(STDLL_TokData_t *tokdata,
- 
- out:
-     if (rc != CKR_OK) {
--        digest_mgr_cleanup(ctx);
-+        digest_mgr_cleanup(tokdata, sess, ctx);
-     }
- 
-     object_put(tokdata, key_obj, TRUE);
-@@ -451,7 +458,7 @@ out:
-         // operation unless it returns CKR_BUFFER_TOO_SMALL or is a successful
-         // call (i.e., one which returns CKR_OK) to determine the length of the
-         // buffer needed to hold the message digest."
--        digest_mgr_cleanup(ctx);
-+        digest_mgr_cleanup(tokdata, sess, ctx);
-     }
- 
-     return rc;
-diff --git a/usr/lib/common/encr_mgr.c b/usr/lib/common/encr_mgr.c
-index 3e85ceab..7f7dfbae 100644
---- a/usr/lib/common/encr_mgr.c
-+++ b/usr/lib/common/encr_mgr.c
-@@ -617,7 +617,8 @@ done:
- 
- //
- //
--CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx)
-+CK_RV encr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                       ENCR_DECR_CONTEXT *ctx)
- {
-     if (!ctx) {
-         TRACE_ERROR("Invalid function argument.\n");
-@@ -632,6 +633,7 @@ CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx)
-     ctx->init_pending = FALSE;
-     ctx->context_len = 0;
-     ctx->pkey_active = FALSE;
-+    ctx->state_unsaveable = FALSE;
- 
-     if (ctx->mech.pParameter) {
-         free(ctx->mech.pParameter);
-@@ -639,9 +641,14 @@ CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx)
-     }
- 
-     if (ctx->context) {
--        free(ctx->context);
-+        if (ctx->context_free_func != NULL)
-+            ctx->context_free_func(tokdata, sess, ctx->context,
-+                                   ctx->context_len);
-+        else
-+            free(ctx->context);
-         ctx->context = NULL;
-     }
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-@@ -1204,8 +1211,8 @@ done:
-         free(decr_data);
-     }
- 
--    decr_mgr_cleanup(decr_ctx);
--    encr_mgr_cleanup(encr_ctx);
-+    decr_mgr_cleanup(tokdata, sess, decr_ctx);
-+    encr_mgr_cleanup(tokdata, sess, encr_ctx);
- 
-     return rc;
- }
-diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
-index 5e251d95..47b96ba0 100644
---- a/usr/lib/common/h_extern.h
-+++ b/usr/lib/common/h_extern.h
-@@ -1790,7 +1790,8 @@ CK_RV encr_mgr_init(STDLL_TokData_t *tokdata,
-                     CK_ULONG operation,
-                     CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle);
- 
--CK_RV encr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx);
-+CK_RV encr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                       ENCR_DECR_CONTEXT *ctx);
- 
- CK_RV encr_mgr_encrypt(STDLL_TokData_t *tokdata,
-                        SESSION *sess, CK_BBOOL length_only,
-@@ -1825,7 +1826,8 @@ CK_RV decr_mgr_init(STDLL_TokData_t *tokdata,
-                     CK_ULONG operation,
-                     CK_MECHANISM *mech, CK_OBJECT_HANDLE key_handle);
- 
--CK_RV decr_mgr_cleanup(ENCR_DECR_CONTEXT *ctx);
-+CK_RV decr_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                       ENCR_DECR_CONTEXT *ctx);
- 
- CK_RV decr_mgr_decrypt(STDLL_TokData_t *tokdata,
-                        SESSION *sess, CK_BBOOL length_only,
-@@ -1866,7 +1868,8 @@ CK_RV decr_mgr_update_des3_cbc(STDLL_TokData_t *tokdata, SESSION *sess,
- 
- // digest manager routines
- //
--CK_RV digest_mgr_cleanup(DIGEST_CONTEXT *ctx);
-+CK_RV digest_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                         DIGEST_CONTEXT *ctx);
- 
- CK_RV digest_mgr_init(STDLL_TokData_t *tokdata,
-                       SESSION *sess,
-@@ -1955,7 +1958,8 @@ CK_RV sign_mgr_init(STDLL_TokData_t *tokdata,
-                     CK_MECHANISM *mech,
-                     CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle);
- 
--CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx);
-+CK_RV sign_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                       SIGN_VERIFY_CONTEXT *ctx);
- 
- CK_RV sign_mgr_sign(STDLL_TokData_t *tokdata,
-                     SESSION *sess,
-@@ -1992,7 +1996,8 @@ CK_RV verify_mgr_init(STDLL_TokData_t *tokdata,
-                       CK_MECHANISM *mech,
-                       CK_BBOOL recover_mode, CK_OBJECT_HANDLE key_handle);
- 
--CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx);
-+CK_RV verify_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                         SIGN_VERIFY_CONTEXT *ctx);
- 
- CK_RV verify_mgr_verify(STDLL_TokData_t *tokdata,
-                         SESSION *sess,
-@@ -2036,10 +2041,11 @@ CK_BBOOL session_mgr_so_session_exists(STDLL_TokData_t *tokdata);
- CK_BBOOL session_mgr_user_session_exists(STDLL_TokData_t *tokdata);
- CK_BBOOL session_mgr_public_session_exists(STDLL_TokData_t *tokdata);
- 
--CK_RV session_mgr_get_op_state(SESSION *sess, CK_BBOOL length_only,
-+CK_RV session_mgr_get_op_state(SESSION *sess,
-+                               CK_BBOOL length_only,
-                                CK_BYTE *data, CK_ULONG *data_len);
- 
--CK_RV session_mgr_set_op_state(SESSION *sess,
-+CK_RV session_mgr_set_op_state(STDLL_TokData_t *tokdata, SESSION *sess,
-                                CK_OBJECT_HANDLE encr_key,
-                                CK_OBJECT_HANDLE auth_key, CK_BYTE *data,
-                                CK_ULONG data_len);
-diff --git a/usr/lib/common/host_defs.h b/usr/lib/common/host_defs.h
-index c0b5c83d..41fdb657 100644
---- a/usr/lib/common/host_defs.h
-+++ b/usr/lib/common/host_defs.h
-@@ -21,27 +21,36 @@
- 
- #include "local_types.h"
- 
-+struct _SESSION;
-+
-+typedef void (*context_free_func_t)(STDLL_TokData_t *tokdata, struct _SESSION *sess,
-+                                    CK_BYTE *context, CK_ULONG context_len);
-+
- typedef struct _ENCR_DECR_CONTEXT {
-     CK_OBJECT_HANDLE key;
-     CK_MECHANISM mech;
-     CK_BYTE *context;
-     CK_ULONG context_len;
-+    context_free_func_t context_free_func;
-     CK_BBOOL multi;
-     CK_BBOOL active;
-     CK_BBOOL init_pending;      // indicate init request pending
-     CK_BBOOL multi_init;        // multi field is initialized
-                                 // on first call *after* init
-     CK_BBOOL pkey_active;
-+    CK_BBOOL state_unsaveable;
- } ENCR_DECR_CONTEXT;
- 
- typedef struct _DIGEST_CONTEXT {
-     CK_MECHANISM mech;
-     CK_BYTE *context;
-     CK_ULONG context_len;
-+    context_free_func_t context_free_func;
-     CK_BBOOL multi;
-     CK_BBOOL active;
-     CK_BBOOL multi_init;        // multi field is initialized
-                                 // on first call *after* init
-+    CK_BBOOL state_unsaveable;
- } DIGEST_CONTEXT;
- 
- typedef struct _SIGN_VERIFY_CONTEXT {
-@@ -49,6 +58,7 @@ typedef struct _SIGN_VERIFY_CONTEXT {
-     CK_MECHANISM mech;          // current sign mechanism
-     CK_BYTE *context;           // temporary work area
-     CK_ULONG context_len;
-+    context_free_func_t context_free_func;
-     CK_BBOOL multi;             // is this a multi-part operation?
-     CK_BBOOL recover;           // are we in recover mode?
-     CK_BBOOL active;
-@@ -56,6 +66,7 @@ typedef struct _SIGN_VERIFY_CONTEXT {
-     CK_BBOOL multi_init;        // multi field is initialized
-                                 // on first call *after* init
-     CK_BBOOL pkey_active;
-+    CK_BBOOL state_unsaveable;
- } SIGN_VERIFY_CONTEXT;
- 
- 
-diff --git a/usr/lib/common/key_mgr.c b/usr/lib/common/key_mgr.c
-index d9cd1f2f..aea74b7c 100644
---- a/usr/lib/common/key_mgr.c
-+++ b/usr/lib/common/key_mgr.c
-@@ -1011,7 +1011,7 @@ CK_RV key_mgr_wrap_key(STDLL_TokData_t *tokdata,
-         OPENSSL_cleanse(data, data_len);
-         free(data);
-     }
--    encr_mgr_cleanup(ctx);
-+    encr_mgr_cleanup(tokdata, sess, ctx);
-     free(ctx);
- 
- done:
-@@ -1259,7 +1259,7 @@ CK_RV key_mgr_unwrap_key(STDLL_TokData_t *tokdata,
-                           FALSE,
-                           ctx, wrapped_key, wrapped_key_len, data, &data_len);
- 
--    decr_mgr_cleanup(ctx);
-+    decr_mgr_cleanup(tokdata, sess, ctx);
-     free(ctx);
-     ctx = NULL;
- 
-@@ -1345,7 +1345,7 @@ done:
-         free(data);
-     }
-     if (ctx != NULL) {
--        decr_mgr_cleanup(ctx);
-+        decr_mgr_cleanup(tokdata, sess, ctx);
-         free(ctx);
-     }
- 
-diff --git a/usr/lib/common/lock_sess_mgr.c b/usr/lib/common/lock_sess_mgr.c
-index 0c7dbedf..0609a6c9 100644
---- a/usr/lib/common/lock_sess_mgr.c
-+++ b/usr/lib/common/lock_sess_mgr.c
-@@ -276,32 +276,62 @@ CK_RV session_mgr_close_session(STDLL_TokData_t *tokdata,
-     if (sess->find_list)
-         free(sess->find_list);
- 
--    if (sess->encr_ctx.context)
--        free(sess->encr_ctx.context);
-+    if (sess->encr_ctx.context) {
-+        if (sess->encr_ctx.context_free_func != NULL)
-+            sess->encr_ctx.context_free_func(tokdata, sess,
-+                                             sess->encr_ctx.context,
-+                                             sess->encr_ctx.context_len);
-+        else
-+            free(sess->encr_ctx.context);
-+    }
- 
-     if (sess->encr_ctx.mech.pParameter)
-         free(sess->encr_ctx.mech.pParameter);
- 
--    if (sess->decr_ctx.context)
--        free(sess->decr_ctx.context);
-+    if (sess->decr_ctx.context) {
-+        if (sess->decr_ctx.context_free_func != NULL)
-+            sess->decr_ctx.context_free_func(tokdata, sess,
-+                                             sess->decr_ctx.context,
-+                                             sess->decr_ctx.context_len);
-+        else
-+            free(sess->decr_ctx.context);
-+    }
- 
-     if (sess->decr_ctx.mech.pParameter)
-         free(sess->decr_ctx.mech.pParameter);
- 
--    if (sess->digest_ctx.context)
--        free(sess->digest_ctx.context);
-+    if (sess->digest_ctx.context) {
-+        if (sess->digest_ctx.context_free_func != NULL)
-+            sess->digest_ctx.context_free_func(tokdata, sess,
-+                                               sess->digest_ctx.context,
-+                                               sess->digest_ctx.context_len);
-+        else
-+            free(sess->digest_ctx.context);
-+    }
- 
-     if (sess->digest_ctx.mech.pParameter)
-         free(sess->digest_ctx.mech.pParameter);
- 
--    if (sess->sign_ctx.context)
--        free(sess->sign_ctx.context);
-+    if (sess->sign_ctx.context) {
-+        if (sess->sign_ctx.context_free_func != NULL)
-+            sess->sign_ctx.context_free_func(tokdata, sess,
-+                                             sess->sign_ctx.context,
-+                                             sess->sign_ctx.context_len);
-+        else
-+            free(sess->sign_ctx.context);
-+    }
- 
-     if (sess->sign_ctx.mech.pParameter)
-         free(sess->sign_ctx.mech.pParameter);
- 
--    if (sess->verify_ctx.context)
--        free(sess->verify_ctx.context);
-+    if (sess->verify_ctx.context) {
-+        if (sess->verify_ctx.context_free_func != NULL)
-+            sess->verify_ctx.context_free_func(tokdata, sess,
-+                                               sess->verify_ctx.context,
-+                                               sess->verify_ctx.context_len);
-+        else
-+            free(sess->verify_ctx.context);
-+    }
- 
-     if (sess->verify_ctx.mech.pParameter)
-         free(sess->verify_ctx.mech.pParameter);
-@@ -354,32 +384,62 @@ void session_free(STDLL_TokData_t *tokdata, void *node_value,
-     if (sess->find_list)
-         free(sess->find_list);
- 
--    if (sess->encr_ctx.context)
--        free(sess->encr_ctx.context);
-+    if (sess->encr_ctx.context) {
-+        if (sess->encr_ctx.context_free_func != NULL)
-+            sess->encr_ctx.context_free_func(tokdata, sess,
-+                                             sess->encr_ctx.context,
-+                                             sess->encr_ctx.context_len);
-+        else
-+            free(sess->encr_ctx.context);
-+    }
- 
-     if (sess->encr_ctx.mech.pParameter)
-         free(sess->encr_ctx.mech.pParameter);
- 
--    if (sess->decr_ctx.context)
--        free(sess->decr_ctx.context);
-+    if (sess->decr_ctx.context) {
-+        if (sess->decr_ctx.context_free_func != NULL)
-+            sess->decr_ctx.context_free_func(tokdata, sess,
-+                                             sess->decr_ctx.context,
-+                                             sess->decr_ctx.context_len);
-+        else
-+            free(sess->decr_ctx.context);
-+    }
- 
-     if (sess->decr_ctx.mech.pParameter)
-         free(sess->decr_ctx.mech.pParameter);
- 
--    if (sess->digest_ctx.context)
--        free(sess->digest_ctx.context);
-+    if (sess->digest_ctx.context) {
-+        if (sess->digest_ctx.context_free_func != NULL)
-+            sess->digest_ctx.context_free_func(tokdata, sess,
-+                                               sess->digest_ctx.context,
-+                                               sess->digest_ctx.context_len);
-+        else
-+            free(sess->digest_ctx.context);
-+    }
- 
-     if (sess->digest_ctx.mech.pParameter)
-         free(sess->digest_ctx.mech.pParameter);
- 
--    if (sess->sign_ctx.context)
--        free(sess->sign_ctx.context);
-+    if (sess->sign_ctx.context) {
-+        if (sess->sign_ctx.context_free_func != NULL)
-+            sess->sign_ctx.context_free_func(tokdata, sess,
-+                                             sess->sign_ctx.context,
-+                                             sess->sign_ctx.context_len);
-+        else
-+            free(sess->sign_ctx.context);
-+    }
- 
-     if (sess->sign_ctx.mech.pParameter)
-         free(sess->sign_ctx.mech.pParameter);
- 
--    if (sess->verify_ctx.context)
--        free(sess->verify_ctx.context);
-+    if (sess->verify_ctx.context) {
-+        if (sess->verify_ctx.context_free_func != NULL)
-+            sess->verify_ctx.context_free_func(tokdata, sess,
-+                                               sess->verify_ctx.context,
-+                                               sess->verify_ctx.context_len);
-+        else
-+            free(sess->verify_ctx.context);
-+    }
- 
-     if (sess->verify_ctx.mech.pParameter)
-         free(sess->verify_ctx.mech.pParameter);
-@@ -528,6 +588,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     active_ops = 0;
- 
-     if (sess->encr_ctx.active == TRUE) {
-+        if (sess->encr_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -572,6 +636,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->decr_ctx.active == TRUE) {
-+        if (sess->decr_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -616,6 +684,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->digest_ctx.active == TRUE) {
-+        if (sess->digest_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -660,6 +732,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->sign_ctx.active == TRUE) {
-+        if (sess->sign_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -704,6 +780,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->verify_ctx.active == TRUE) {
-+        if (sess->verify_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -759,7 +839,7 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
- 
- //
- //
--CK_RV session_mgr_set_op_state(SESSION *sess,
-+CK_RV session_mgr_set_op_state(STDLL_TokData_t *tokdata, SESSION *sess,
-                                CK_OBJECT_HANDLE encr_key,
-                                CK_OBJECT_HANDLE auth_key,
-                                CK_BYTE *data, CK_ULONG data_len)
-@@ -939,19 +1019,19 @@ CK_RV session_mgr_set_op_state(SESSION *sess,
-     // state information looks okay.  cleanup the current session state, first
-     //
-     if (sess->encr_ctx.active)
--        encr_mgr_cleanup(&sess->encr_ctx);
-+        encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
- 
-     if (sess->decr_ctx.active)
--        decr_mgr_cleanup(&sess->decr_ctx);
-+        decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
- 
-     if (sess->digest_ctx.active)
--        digest_mgr_cleanup(&sess->digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &sess->digest_ctx);
- 
-     if (sess->sign_ctx.active)
--        sign_mgr_cleanup(&sess->sign_ctx);
-+        sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
- 
-     if (sess->verify_ctx.active)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
- 
-     // copy the new state information
-diff --git a/usr/lib/common/mech_aes.c b/usr/lib/common/mech_aes.c
-index a117487d..ad6af16b 100644
---- a/usr/lib/common/mech_aes.c
-+++ b/usr/lib/common/mech_aes.c
-@@ -2740,6 +2740,9 @@ CK_RV aes_cmac_sign(STDLL_TokData_t *tokdata,
-         goto done;
-     }
- 
-+    if (((AES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     memcpy(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv, mac_len);
-     *out_data_len = mac_len;
- 
-@@ -2810,6 +2813,9 @@ CK_RV aes_cmac_sign_update(STDLL_TokData_t *tokdata,
-             context->len = remain;
- 
-             context->initialized = CK_TRUE;
-+
-+            if (context->ctx != NULL)
-+                ctx->state_unsaveable = CK_TRUE;
-         } else {
-             TRACE_DEVEL("Token specific aes cmac failed.\n");
-         }
-@@ -2873,6 +2879,9 @@ CK_RV aes_cmac_sign_final(STDLL_TokData_t *tokdata,
-         goto done;
-     }
- 
-+    if (context->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     memcpy(out_data, context->iv, mac_len);
-     *out_data_len = mac_len;
- 
-@@ -2929,6 +2938,9 @@ CK_RV aes_cmac_verify(STDLL_TokData_t *tokdata,
-         return rc;
-     }
- 
-+    if (((AES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     if (CRYPTO_memcmp(out_data, ((AES_CMAC_CONTEXT *) ctx->context)->iv,
-                       out_data_len) == 0) {
-         return CKR_OK;
-@@ -2997,6 +3009,9 @@ CK_RV aes_cmac_verify_update(STDLL_TokData_t *tokdata,
-             context->len = remain;
- 
-             context->initialized = CK_TRUE;
-+
-+            if (context->ctx != NULL)
-+                ctx->state_unsaveable = CK_TRUE;
-         } else {
-             TRACE_DEVEL("Token specific aes cmac failed.\n");
-         }
-@@ -3052,6 +3067,9 @@ CK_RV aes_cmac_verify_final(STDLL_TokData_t *tokdata,
-     object_put(tokdata, key_obj, TRUE);
-     key_obj = NULL;
- 
-+    if (context->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Token specific aes mac failed.\n");
-         return rc;
-diff --git a/usr/lib/common/mech_des3.c b/usr/lib/common/mech_des3.c
-index 786f9a4a..be8d6075 100644
---- a/usr/lib/common/mech_des3.c
-+++ b/usr/lib/common/mech_des3.c
-@@ -2380,6 +2380,9 @@ CK_RV des3_cmac_sign(STDLL_TokData_t *tokdata,
-     if (rc != CKR_OK)
-         TRACE_DEVEL("Token specific des3 cmac failed.\n");
- 
-+    if (((DES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     memcpy(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv, mac_len);
- 
-     *out_data_len = mac_len;
-@@ -2450,6 +2453,9 @@ CK_RV des3_cmac_sign_update(STDLL_TokData_t *tokdata,
-             context->len = remain;
- 
-             context->initialized = CK_TRUE;
-+
-+            if (context->ctx != NULL)
-+                ctx->state_unsaveable = CK_TRUE;
-         } else {
-             TRACE_DEVEL("Token specific des3 cmac failed.\n");
-         }
-@@ -2512,6 +2518,9 @@ CK_RV des3_cmac_sign_final(STDLL_TokData_t *tokdata,
-         goto done;
-     }
- 
-+    if (context->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     memcpy(out_data, context->iv, mac_len);
- 
-     *out_data_len = mac_len;
-@@ -2565,6 +2574,9 @@ CK_RV des3_cmac_verify(STDLL_TokData_t *tokdata,
-     object_put(tokdata, key_obj, TRUE);
-     key_obj = NULL;
- 
-+    if (((DES_CMAC_CONTEXT *)ctx->context)->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     if (CRYPTO_memcmp(out_data, ((DES_CMAC_CONTEXT *) ctx->context)->iv,
-                       out_data_len) == 0) {
-         return CKR_OK;
-@@ -2631,6 +2643,9 @@ CK_RV des3_cmac_verify_update(STDLL_TokData_t *tokdata,
-             context->len = remain;
- 
-             context->initialized = CK_TRUE;
-+
-+            if (context->ctx != NULL)
-+                ctx->state_unsaveable = CK_TRUE;
-         } else {
-             TRACE_DEVEL("Token specific des3 cmac failed.\n");
-         }
-@@ -2691,6 +2706,9 @@ CK_RV des3_cmac_verify_final(STDLL_TokData_t *tokdata,
-         return rc;
-     }
- 
-+    if (context->ctx != NULL)
-+        ctx->state_unsaveable = CK_TRUE;
-+
-     if (CRYPTO_memcmp(signature, context->iv, signature_len) == 0)
-         return CKR_OK;
- 
-diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c
-index a0a06302..c338d063 100644
---- a/usr/lib/common/mech_ec.c
-+++ b/usr/lib/common/mech_ec.c
-@@ -414,7 +414,7 @@ CK_RV ec_hash_sign(STDLL_TokData_t *tokdata,
-                            in_data_len, hash, &hash_len);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Digest Mgr Digest failed.\n");
--        digest_mgr_cleanup(&digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-         return rc;
-     }
- 
-@@ -434,7 +434,7 @@ CK_RV ec_hash_sign(STDLL_TokData_t *tokdata,
-         TRACE_DEVEL("Sign Mgr Sign failed.\n");
- 
- error:
--    sign_mgr_cleanup(&sign_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &sign_ctx);
- 
-     return rc;
- }
-@@ -485,6 +485,7 @@ CK_RV ec_hash_sign_update(STDLL_TokData_t *tokdata,
-             return rc;
-         }
-         context->flag = TRUE;
-+        ctx->state_unsaveable |= context->hash_context.state_unsaveable;
-     }
- 
-     rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
-@@ -556,12 +557,12 @@ CK_RV ec_hash_sign_final(STDLL_TokData_t *tokdata,
-         TRACE_DEVEL("Sign Mgr Sign failed.\n");
- 
-     if (length_only == TRUE || rc == CKR_BUFFER_TOO_SMALL) {
--        sign_mgr_cleanup(&sign_ctx);
-+        sign_mgr_cleanup(tokdata, sess, &sign_ctx);
-         return rc;
-     }
- 
- done:
--    sign_mgr_cleanup(&sign_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &sign_ctx);
- 
-     return rc;
- }
-@@ -627,7 +628,7 @@ CK_RV ec_hash_verify(STDLL_TokData_t *tokdata,
-                            in_data_len, hash, &hash_len);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Digest Mgr Digest failed.\n");
--        digest_mgr_cleanup(&digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-         return rc;
-     }
-     // Verify the Signed BER-encoded Data block
-@@ -649,7 +650,7 @@ CK_RV ec_hash_verify(STDLL_TokData_t *tokdata,
-     if (rc != CKR_OK)
-         TRACE_DEVEL("Verify Mgr Verify failed.\n");
- done:
--    sign_mgr_cleanup(&verify_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &verify_ctx);
- 
-     return rc;
- }
-@@ -701,6 +702,7 @@ CK_RV ec_hash_verify_update(STDLL_TokData_t *tokdata,
-             return rc;
-         }
-         context->flag = TRUE;
-+        ctx->state_unsaveable |= context->hash_context.state_unsaveable;
-     }
- 
-     rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
-@@ -768,7 +770,7 @@ CK_RV ec_hash_verify_final(STDLL_TokData_t *tokdata,
-     if (rc != CKR_OK)
-         TRACE_DEVEL("Verify Mgr Verify failed.\n");
- done:
--    verify_mgr_cleanup(&verify_ctx);
-+    verify_mgr_cleanup(tokdata, sess, &verify_ctx);
- 
-     return rc;
- }
-@@ -823,7 +825,7 @@ CK_RV ckm_kdf(STDLL_TokData_t *tokdata, SESSION *sess, CK_ULONG kdf,
-                            h_len);
-     if (rc != CKR_OK) {
-         TRACE_ERROR("digest_mgr_digest failed with rc = %s\n", ock_err(rc));
--        digest_mgr_cleanup(&ctx);
-+        digest_mgr_cleanup(tokdata, sess, &ctx);
-         return rc;
-     }
- 
-diff --git a/usr/lib/common/mech_md2.c b/usr/lib/common/mech_md2.c
-index beb84365..91da6259 100644
---- a/usr/lib/common/mech_md2.c
-+++ b/usr/lib/common/mech_md2.c
-@@ -245,7 +245,7 @@ CK_RV md2_hmac_sign(STDLL_TokData_t *tokdata,
-                                attr->pValue, attr->ulValueLen, hash, &hash_len);
-         if (rc != CKR_OK) {
-             TRACE_DEVEL("Digest Mgr Digest failed.\n");
--            digest_mgr_cleanup(&digest_ctx);
-+            digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-             goto done;
-         }
-         memset(&digest_ctx, 0x0, sizeof(DIGEST_CONTEXT));
-diff --git a/usr/lib/common/mech_md5.c b/usr/lib/common/mech_md5.c
-index 6b1281de..320e2549 100644
---- a/usr/lib/common/mech_md5.c
-+++ b/usr/lib/common/mech_md5.c
-@@ -61,7 +61,10 @@ CK_RV sw_md5_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-     MD5_Final(out_data, (MD5_CTX *)ctx->context);
-     *out_data_len = MD5_HASH_SIZE;
- 
--    free(ctx->context);
-+    if (ctx->context_free_func != NULL)
-+        ctx->context_free_func(ctx->context, ctx->context_len);
-+    else
-+        free(ctx->context);
-     ctx->context = NULL;
- 
-     return CKR_OK;
-@@ -86,7 +89,10 @@ CK_RV sw_MD5_Final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data,
-     MD5_Final(out_data, (MD5_CTX *)ctx->context);
-     *out_data_len = MD5_HASH_SIZE;
- 
--    free(ctx->context);
-+    if (ctx->context_free_func != NULL)
-+        ctx->context_free_func(ctx->context, ctx->context_len);
-+    else
-+        free(ctx->context);
-     ctx->context = NULL;
- 
-     return CKR_OK;
-@@ -267,7 +273,7 @@ CK_RV md5_hmac_sign(STDLL_TokData_t *tokdata,
-                                attr->pValue, attr->ulValueLen, hash, &hash_len);
-         if (rc != CKR_OK) {
-             TRACE_DEVEL("Digest Mgr Digest failed.\n");
--            digest_mgr_cleanup(&digest_ctx);
-+            digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-             goto done;
-         }
- 
-@@ -413,6 +419,6 @@ CK_RV md5_hmac_verify(STDLL_TokData_t *tokdata, SESSION *sess,
-     }
- 
- done:
--    sign_mgr_cleanup(&hmac_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &hmac_ctx);
-     return rc;
- }
-diff --git a/usr/lib/common/mech_rsa.c b/usr/lib/common/mech_rsa.c
-index e35b383c..0a690e78 100644
---- a/usr/lib/common/mech_rsa.c
-+++ b/usr/lib/common/mech_rsa.c
-@@ -1476,7 +1476,7 @@ CK_RV rsa_hash_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess,
-                            in_data, in_data_len, hash, &hlen);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Digest Mgr Digest failed.\n");
--        digest_mgr_cleanup(&digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-         return rc;
-     }
- 
-@@ -1497,7 +1497,7 @@ CK_RV rsa_hash_pss_sign(STDLL_TokData_t *tokdata, SESSION *sess,
-         TRACE_DEVEL("Sign Mgr Sign failed.\n");
- 
- done:
--    sign_mgr_cleanup(&sign_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &sign_ctx);
- 
-     return rc;
- }
-@@ -1546,6 +1546,7 @@ CK_RV rsa_hash_pss_update(STDLL_TokData_t *tokdata, SESSION *sess,
-             TRACE_DEVEL("Digest Mgr Init failed.\n");
-             return rc;
-         }
-+        ctx->state_unsaveable |= digest_ctx->state_unsaveable;
-     }
- 
-     rc = digest_mgr_digest_update(tokdata, sess, digest_ctx, in_data,
-@@ -1613,7 +1614,7 @@ CK_RV rsa_hash_pss_sign_final(STDLL_TokData_t *tokdata, SESSION *sess,
-         TRACE_DEVEL("Sign Mgr Sign failed.\n");
- 
- done:
--    sign_mgr_cleanup(&sign_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &sign_ctx);
- 
-     return rc;
- }
-@@ -1676,7 +1677,7 @@ CK_RV rsa_hash_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess,
-                            in_data_len, hash, &hlen);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Digest Mgr Digest failed.\n");
--        digest_mgr_cleanup(&digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-         return rc;
-     }
- 
-@@ -1698,7 +1699,7 @@ CK_RV rsa_hash_pss_verify(STDLL_TokData_t *tokdata, SESSION *sess,
-         TRACE_DEVEL("Verify Mgr Verify failed.\n");
- 
- done:
--    verify_mgr_cleanup(&verify_ctx);
-+    verify_mgr_cleanup(tokdata, sess, &verify_ctx);
- 
-     return rc;
- }
-@@ -1760,7 +1761,7 @@ CK_RV rsa_hash_pss_verify_final(STDLL_TokData_t *tokdata, SESSION *sess,
-         TRACE_DEVEL("Verify Mgr Verify failed.\n");
- 
- done:
--    verify_mgr_cleanup(&verify_ctx);
-+    verify_mgr_cleanup(tokdata, sess, &verify_ctx);
- 
-     return rc;
- }
-@@ -1842,7 +1843,7 @@ CK_RV rsa_hash_pkcs_sign(STDLL_TokData_t *tokdata,
-                            in_data_len, hash, &hash_len);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Digest Mgr Digest failed.\n");
--        digest_mgr_cleanup(&digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-         return rc;
-     }
-     // build the BER-encodings
-@@ -1885,7 +1886,7 @@ error:
-         free(octet_str);
-     if (ber_data)
-         free(ber_data);
--    sign_mgr_cleanup(&sign_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &sign_ctx);
- 
-     return rc;
- }
-@@ -1934,6 +1935,7 @@ CK_RV rsa_hash_pkcs_sign_update(STDLL_TokData_t *tokdata,
-             return rc;
-         }
-         context->flag = TRUE;
-+        ctx->state_unsaveable |= context->hash_context.state_unsaveable;
-     }
- 
-     rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
-@@ -2021,7 +2023,7 @@ CK_RV rsa_hash_pkcs_verify(STDLL_TokData_t *tokdata,
-                            in_data_len, hash, &hash_len);
-     if (rc != CKR_OK) {
-         TRACE_DEVEL("Digest Mgr Digest failed.\n");
--        digest_mgr_cleanup(&digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-         return rc;
-     }
-     // Build the BER encoding
-@@ -2063,7 +2065,7 @@ done:
-         free(octet_str);
-     if (ber_data)
-         free(ber_data);
--    sign_mgr_cleanup(&verify_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &verify_ctx);
- 
-     return rc;
- }
-@@ -2111,6 +2113,7 @@ CK_RV rsa_hash_pkcs_verify_update(STDLL_TokData_t *tokdata,
-             return rc;
-         }
-         context->flag = TRUE;
-+        ctx->state_unsaveable |= context->hash_context.state_unsaveable;
-     }
- 
-     rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
-@@ -2236,7 +2239,7 @@ done:
-         free(octet_str);
-     if (ber_data)
-         free(ber_data);
--    sign_mgr_cleanup(&sign_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &sign_ctx);
- 
-     return rc;
- }
-@@ -2347,7 +2350,7 @@ done:
-         free(octet_str);
-     if (ber_data)
-         free(ber_data);
--    verify_mgr_cleanup(&verify_ctx);
-+    verify_mgr_cleanup(tokdata, sess, &verify_ctx);
- 
-     return rc;
- }
-diff --git a/usr/lib/common/mech_sha.c b/usr/lib/common/mech_sha.c
-index 4037b8f1..0b9b7b28 100644
---- a/usr/lib/common/mech_sha.c
-+++ b/usr/lib/common/mech_sha.c
-@@ -80,7 +80,10 @@ CK_RV sw_sha1_hash(DIGEST_CONTEXT *ctx, CK_BYTE *in_data,
-     SHA1_Final(out_data, (SHA_CTX *)ctx->context);
-     *out_data_len = SHA1_HASH_SIZE;
- 
--    free(ctx->context);
-+    if (ctx->context_free_func != NULL)
-+        ctx->context_free_func(ctx->context, ctx->context_len);
-+    else
-+        free(ctx->context);
-     ctx->context = NULL;
- 
-     return CKR_OK;
-@@ -105,7 +108,10 @@ CK_RV sw_sha1_final(DIGEST_CONTEXT *ctx, CK_BYTE *out_data,
-     SHA1_Final(out_data, (SHA_CTX *)ctx->context);
-     *out_data_len = SHA1_HASH_SIZE;
- 
--    free(ctx->context);
-+    if (ctx->context_free_func != NULL)
-+        ctx->context_free_func(ctx->context, ctx->context_len);
-+    else
-+        free(ctx->context);
-     ctx->context = NULL;
- 
-     return CKR_OK;
-@@ -421,7 +427,7 @@ CK_RV sha_hmac_sign(STDLL_TokData_t *tokdata,
-                                attr->pValue, attr->ulValueLen, hash, &hash_len);
-         if (rc != CKR_OK) {
-             TRACE_DEVEL("Digest Mgr Digest failed.\n");
--            digest_mgr_cleanup(&digest_ctx);
-+            digest_mgr_cleanup(tokdata, sess, &digest_ctx);
-             goto done;
-         }
- 
-@@ -607,7 +613,7 @@ CK_RV sha_hmac_verify(STDLL_TokData_t *tokdata, SESSION *sess,
-     }
- 
- done:
--    sign_mgr_cleanup(&hmac_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &hmac_ctx);
-     return rc;
- }
- 
-diff --git a/usr/lib/common/mech_ssl3.c b/usr/lib/common/mech_ssl3.c
-index 66bdb8f4..566aeee2 100644
---- a/usr/lib/common/mech_ssl3.c
-+++ b/usr/lib/common/mech_ssl3.c
-@@ -289,6 +289,7 @@ CK_RV ssl3_mac_sign_update(STDLL_TokData_t *tokdata,
-             goto done;
-         }
-         context->flag = TRUE;
-+        ctx->state_unsaveable |= context->hash_context.state_unsaveable;
-     }
- 
- 
-@@ -485,7 +486,7 @@ CK_RV ssl3_mac_verify(STDLL_TokData_t *tokdata,
-         rc = CKR_SIGNATURE_INVALID;
-     }
- error:
--    sign_mgr_cleanup(&mac_ctx);
-+    sign_mgr_cleanup(tokdata, sess, &mac_ctx);
- 
-     return rc;
- }
-@@ -573,6 +574,7 @@ CK_RV ssl3_mac_verify_update(STDLL_TokData_t *tokdata,
-             goto done;
-         }
-         context->flag = TRUE;
-+        ctx->state_unsaveable |= context->hash_context.state_unsaveable;
-     }
- 
-     rc = digest_mgr_digest_update(tokdata, sess, &context->hash_context,
-diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c
-index a3749d26..d01091f9 100644
---- a/usr/lib/common/new_host.c
-+++ b/usr/lib/common/new_host.c
-@@ -1215,8 +1215,9 @@ CK_RV SC_SetOperationState(STDLL_TokData_t *tokdata,
-         goto done;
-     }
- 
--    rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey,
--                                  pOperationState, ulOperationStateLen);
-+    rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey,
-+                                  hAuthenticationKey, pOperationState,
-+                                  ulOperationStateLen);
- 
-     if (rc != CKR_OK)
-         TRACE_DEVEL("session_mgr_set_op_state() failed.\n");
-@@ -2128,7 +2129,7 @@ CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2187,7 +2188,7 @@ CK_RV SC_EncryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2244,7 +2245,7 @@ CK_RV SC_EncryptFinal(STDLL_TokData_t * tokdata, ST_SESSION_HANDLE * sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n",
-@@ -2361,7 +2362,7 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2420,7 +2421,7 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2477,7 +2478,7 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2825,7 +2826,7 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-@@ -2875,7 +2876,7 @@ CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (rc != CKR_OK && sess != NULL)
--        sign_mgr_cleanup(&sess->sign_ctx);
-+        sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
- 
-     TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
-@@ -2930,7 +2931,7 @@ CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n",
-@@ -3045,7 +3046,7 @@ CK_RV SC_SignRecover(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_SignRecover: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-@@ -3155,7 +3156,7 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
-@@ -3205,7 +3206,7 @@ CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (rc != CKR_OK && sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
-@@ -3255,7 +3256,7 @@ CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
-@@ -3372,7 +3373,7 @@ CK_RV SC_VerifyRecover(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess != NULL)
--            verify_mgr_cleanup(&sess->verify_ctx);
-+            verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
-     }
- 
-     TRACE_INFO("C_VerifyRecover: rc = 0x%08lx, sess = %ld, recover len = %lu, "
-diff --git a/usr/lib/common/sess_mgr.c b/usr/lib/common/sess_mgr.c
-index e2da6df5..69c3be3b 100644
---- a/usr/lib/common/sess_mgr.c
-+++ b/usr/lib/common/sess_mgr.c
-@@ -243,32 +243,62 @@ CK_RV session_mgr_close_session(STDLL_TokData_t *tokdata,
-     if (sess->find_list)
-         free(sess->find_list);
- 
--    if (sess->encr_ctx.context)
--        free(sess->encr_ctx.context);
-+    if (sess->encr_ctx.context) {
-+        if (sess->encr_ctx.context_free_func != NULL)
-+            sess->encr_ctx.context_free_func(tokdata, sess,
-+                                             sess->encr_ctx.context,
-+                                             sess->encr_ctx.context_len);
-+        else
-+            free(sess->encr_ctx.context);
-+    }
- 
-     if (sess->encr_ctx.mech.pParameter)
-         free(sess->encr_ctx.mech.pParameter);
- 
--    if (sess->decr_ctx.context)
--        free(sess->decr_ctx.context);
-+    if (sess->decr_ctx.context) {
-+        if (sess->decr_ctx.context_free_func != NULL)
-+            sess->decr_ctx.context_free_func(tokdata, sess,
-+                                             sess->decr_ctx.context,
-+                                             sess->decr_ctx.context_len);
-+        else
-+            free(sess->decr_ctx.context);
-+    }
- 
-     if (sess->decr_ctx.mech.pParameter)
-         free(sess->decr_ctx.mech.pParameter);
- 
--    if (sess->digest_ctx.context)
--        free(sess->digest_ctx.context);
-+    if (sess->digest_ctx.context) {
-+        if (sess->digest_ctx.context_free_func != NULL)
-+            sess->digest_ctx.context_free_func(tokdata, sess,
-+                                               sess->digest_ctx.context,
-+                                               sess->digest_ctx.context_len);
-+        else
-+            free(sess->digest_ctx.context);
-+    }
- 
-     if (sess->digest_ctx.mech.pParameter)
-         free(sess->digest_ctx.mech.pParameter);
- 
--    if (sess->sign_ctx.context)
--        free(sess->sign_ctx.context);
-+    if (sess->sign_ctx.context) {
-+        if (sess->sign_ctx.context_free_func != NULL)
-+            sess->sign_ctx.context_free_func(tokdata, sess,
-+                                             sess->sign_ctx.context,
-+                                             sess->sign_ctx.context_len);
-+        else
-+            free(sess->sign_ctx.context);
-+    }
- 
-     if (sess->sign_ctx.mech.pParameter)
-         free(sess->sign_ctx.mech.pParameter);
- 
--    if (sess->verify_ctx.context)
--        free(sess->verify_ctx.context);
-+    if (sess->verify_ctx.context) {
-+        if (sess->verify_ctx.context_free_func != NULL)
-+            sess->verify_ctx.context_free_func(tokdata, sess,
-+                                               sess->verify_ctx.context,
-+                                               sess->verify_ctx.context_len);
-+        else
-+            free(sess->verify_ctx.context);
-+    }
- 
-     if (sess->verify_ctx.mech.pParameter)
-         free(sess->verify_ctx.mech.pParameter);
-@@ -323,32 +353,62 @@ void session_free(STDLL_TokData_t *tokdata, void *node_value,
-     if (sess->find_list)
-         free(sess->find_list);
- 
--    if (sess->encr_ctx.context)
--        free(sess->encr_ctx.context);
-+    if (sess->encr_ctx.context) {
-+        if (sess->encr_ctx.context_free_func != NULL)
-+            sess->encr_ctx.context_free_func(tokdata, sess,
-+                                             sess->encr_ctx.context,
-+                                             sess->encr_ctx.context_len);
-+        else
-+            free(sess->encr_ctx.context);
-+    }
- 
-     if (sess->encr_ctx.mech.pParameter)
-         free(sess->encr_ctx.mech.pParameter);
- 
--    if (sess->decr_ctx.context)
--        free(sess->decr_ctx.context);
-+    if (sess->decr_ctx.context) {
-+        if (sess->decr_ctx.context_free_func != NULL)
-+            sess->decr_ctx.context_free_func(tokdata, sess,
-+                                             sess->decr_ctx.context,
-+                                             sess->decr_ctx.context_len);
-+        else
-+            free(sess->decr_ctx.context);
-+    }
- 
-     if (sess->decr_ctx.mech.pParameter)
-         free(sess->decr_ctx.mech.pParameter);
- 
--    if (sess->digest_ctx.context)
--        free(sess->digest_ctx.context);
-+    if (sess->digest_ctx.context) {
-+        if (sess->digest_ctx.context_free_func != NULL)
-+            sess->digest_ctx.context_free_func(tokdata, sess,
-+                                               sess->digest_ctx.context,
-+                                               sess->digest_ctx.context_len);
-+        else
-+            free(sess->digest_ctx.context);
-+    }
- 
-     if (sess->digest_ctx.mech.pParameter)
-         free(sess->digest_ctx.mech.pParameter);
- 
--    if (sess->sign_ctx.context)
--        free(sess->sign_ctx.context);
-+    if (sess->sign_ctx.context) {
-+        if (sess->sign_ctx.context_free_func != NULL)
-+            sess->sign_ctx.context_free_func(tokdata, sess,
-+                                             sess->sign_ctx.context,
-+                                             sess->sign_ctx.context_len);
-+        else
-+            free(sess->sign_ctx.context);
-+    }
- 
-     if (sess->sign_ctx.mech.pParameter)
-         free(sess->sign_ctx.mech.pParameter);
- 
--    if (sess->verify_ctx.context)
--        free(sess->verify_ctx.context);
-+    if (sess->verify_ctx.context) {
-+        if (sess->verify_ctx.context_free_func != NULL)
-+            sess->verify_ctx.context_free_func(tokdata, sess,
-+                                               sess->verify_ctx.context,
-+                                               sess->verify_ctx.context_len);
-+        else
-+            free(sess->verify_ctx.context);
-+    }
- 
-     if (sess->verify_ctx.mech.pParameter)
-         free(sess->verify_ctx.mech.pParameter);
-@@ -480,6 +540,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     active_ops = 0;
- 
-     if (sess->encr_ctx.active == TRUE) {
-+        if (sess->encr_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -524,6 +588,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->decr_ctx.active == TRUE) {
-+        if (sess->decr_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -568,6 +636,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->digest_ctx.active == TRUE) {
-+        if (sess->digest_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -612,6 +684,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->sign_ctx.active == TRUE) {
-+        if (sess->sign_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -656,6 +732,10 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
-     }
- 
-     if (sess->verify_ctx.active == TRUE) {
-+        if (sess->verify_ctx.state_unsaveable) {
-+            TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-+            return CKR_STATE_UNSAVEABLE;
-+        }
-         active_ops++;
-         if (op_data != NULL) {
-             TRACE_ERROR("%s\n", ock_err(ERR_STATE_UNSAVEABLE));
-@@ -711,7 +791,7 @@ CK_RV session_mgr_get_op_state(SESSION *sess,
- 
- //
- //
--CK_RV session_mgr_set_op_state(SESSION *sess,
-+CK_RV session_mgr_set_op_state(STDLL_TokData_t *tokdata, SESSION *sess,
-                                CK_OBJECT_HANDLE encr_key,
-                                CK_OBJECT_HANDLE auth_key,
-                                CK_BYTE *data, CK_ULONG data_len)
-@@ -891,19 +971,19 @@ CK_RV session_mgr_set_op_state(SESSION *sess,
-     // state information looks okay.  cleanup the current session state, first
-     //
-     if (sess->encr_ctx.active)
--        encr_mgr_cleanup(&sess->encr_ctx);
-+        encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
- 
-     if (sess->decr_ctx.active)
--        decr_mgr_cleanup(&sess->decr_ctx);
-+        decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
- 
-     if (sess->digest_ctx.active)
--        digest_mgr_cleanup(&sess->digest_ctx);
-+        digest_mgr_cleanup(tokdata, sess, &sess->digest_ctx);
- 
-     if (sess->sign_ctx.active)
--        sign_mgr_cleanup(&sess->sign_ctx);
-+        sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
- 
-     if (sess->verify_ctx.active)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
- 
-     // copy the new state information
-diff --git a/usr/lib/common/sign_mgr.c b/usr/lib/common/sign_mgr.c
-index c7268e01..74e3a9e0 100644
---- a/usr/lib/common/sign_mgr.c
-+++ b/usr/lib/common/sign_mgr.c
-@@ -805,7 +805,8 @@ done:
- 
- //
- //
--CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
-+CK_RV sign_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                       SIGN_VERIFY_CONTEXT *ctx)
- {
-     if (!ctx) {
-         TRACE_ERROR("Invalid function argument.\n");
-@@ -821,6 +822,7 @@ CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
-     ctx->recover = FALSE;
-     ctx->context_len = 0;
-     ctx->pkey_active = FALSE;
-+    ctx->state_unsaveable = FALSE;
- 
-     if (ctx->mech.pParameter) {
-         free(ctx->mech.pParameter);
-@@ -828,9 +830,14 @@ CK_RV sign_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
-     }
- 
-     if (ctx->context) {
--        free(ctx->context);
-+        if (ctx->context_free_func != NULL)
-+            ctx->context_free_func(tokdata, sess, ctx->context,
-+                                   ctx->context_len);
-+        else
-+            free(ctx->context);
-         ctx->context = NULL;
-     }
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-diff --git a/usr/lib/common/verify_mgr.c b/usr/lib/common/verify_mgr.c
-index c46a9803..b49fbb49 100644
---- a/usr/lib/common/verify_mgr.c
-+++ b/usr/lib/common/verify_mgr.c
-@@ -798,7 +798,8 @@ done:
- 
- //
- //
--CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
-+CK_RV verify_mgr_cleanup(STDLL_TokData_t *tokdata, SESSION *sess,
-+                         SIGN_VERIFY_CONTEXT *ctx)
- {
-     if (!ctx) {
-         TRACE_ERROR("Invalid function argument.\n");
-@@ -814,6 +815,7 @@ CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
-     ctx->recover = FALSE;
-     ctx->context_len = 0;
-     ctx->pkey_active = FALSE;
-+    ctx->state_unsaveable = FALSE;
- 
-     if (ctx->mech.pParameter) {
-         free(ctx->mech.pParameter);
-@@ -821,9 +823,14 @@ CK_RV verify_mgr_cleanup(SIGN_VERIFY_CONTEXT *ctx)
-     }
- 
-     if (ctx->context) {
--        free(ctx->context);
-+        if (ctx->context_free_func != NULL)
-+            ctx->context_free_func(tokdata, sess, ctx->context,
-+                                   ctx->context_len);
-+        else
-+            free(ctx->context);
-         ctx->context = NULL;
-     }
-+    ctx->context_free_func = NULL;
- 
-     return CKR_OK;
- }
-diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
-index fb6055e9..49775d0a 100644
---- a/usr/lib/ep11_stdll/ep11_specific.c
-+++ b/usr/lib/ep11_stdll/ep11_specific.c
-@@ -8091,7 +8091,7 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
-         ctx->context_len = ep11_state_l;
-         ctx->pkey_active = FALSE;
-         if (rc != CKR_OK) {
--            decr_mgr_cleanup(ctx);
-+            decr_mgr_cleanup(tokdata, session, ctx);
-             rc = ep11_error_to_pkcs11_error(rc, session);
-             TRACE_ERROR("%s m_DecryptInit rc=0x%lx blob_len=0x%zx "
-                         "mech=0x%lx\n", __func__, rc, blob_len,
-@@ -8124,7 +8124,7 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
-         ctx->context_len = ep11_state_l;
-         ctx->pkey_active = FALSE;
-         if (rc != CKR_OK) {
--            encr_mgr_cleanup(ctx);
-+            encr_mgr_cleanup(tokdata, session, ctx);
-             rc = ep11_error_to_pkcs11_error(rc, session);
-             TRACE_ERROR("%s m_EncryptInit rc=0x%lx blob_len=0x%zx "
-                         "mech=0x%lx\n", __func__, rc, blob_len,
-diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
-index cd12604e..a0e7517c 100644
---- a/usr/lib/ep11_stdll/new_host.c
-+++ b/usr/lib/ep11_stdll/new_host.c
-@@ -1223,8 +1223,9 @@ CK_RV SC_SetOperationState(STDLL_TokData_t *tokdata,
-         goto done;
-     }
- 
--    rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey,
--                                  pOperationState, ulOperationStateLen);
-+    rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey,
-+                                  hAuthenticationKey, pOperationState,
-+                                  ulOperationStateLen);
- 
-     if (rc != CKR_OK)
-         TRACE_DEVEL("session_mgr_set_op_state() failed.\n");
-@@ -2160,7 +2161,7 @@ CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2236,7 +2237,7 @@ CK_RV SC_EncryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2310,7 +2311,7 @@ CK_RV SC_EncryptFinal(STDLL_TokData_t * tokdata, ST_SESSION_HANDLE * sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n",
-@@ -2478,7 +2479,7 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2554,7 +2555,7 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2626,7 +2627,7 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -3022,7 +3023,7 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-@@ -3104,7 +3105,7 @@ CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (rc != CKR_OK && sess != NULL)
--        sign_mgr_cleanup(&sess->sign_ctx);
-+        sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
- 
-     TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
-@@ -3185,7 +3186,7 @@ CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n",
-@@ -3406,7 +3407,7 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
-@@ -3487,7 +3488,7 @@ CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (rc != CKR_OK && sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
-@@ -3562,7 +3563,7 @@ CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
-diff --git a/usr/lib/ica_s390_stdll/ica_specific.c b/usr/lib/ica_s390_stdll/ica_specific.c
-index 7a81145d..77876467 100644
---- a/usr/lib/ica_s390_stdll/ica_specific.c
-+++ b/usr/lib/ica_s390_stdll/ica_specific.c
-@@ -810,8 +810,10 @@ CK_RV token_specific_sha_init(STDLL_TokData_t *tokdata, DIGEST_CONTEXT *ctx,
-     }
- 
-     /* (re)alloc ctx in one memory area */
--    if (ctx->context)
-+    if (ctx->context) {
-         free(ctx->context);
-+        ctx->context_free_func = NULL;
-+    }
-     ctx->context_len = 0;
-     ctx->context = malloc(ctxsize + devctxsize);
-     if (ctx->context == NULL) {
-diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c
-index cfef7425..09e9d27a 100644
---- a/usr/lib/icsf_stdll/new_host.c
-+++ b/usr/lib/icsf_stdll/new_host.c
-@@ -773,8 +773,9 @@ CK_RV SC_SetOperationState(STDLL_TokData_t *tokdata,
-     //set the handle into the session.
-     sess->handle = sSession->sessionh;
- 
--    rc = session_mgr_set_op_state(sess, hEncryptionKey, hAuthenticationKey,
--                                  pOperationState, ulOperationStateLen);
-+    rc = session_mgr_set_op_state(tokdata, sess, hEncryptionKey,
-+                                  hAuthenticationKey, pOperationState,
-+                                  ulOperationStateLen);
- 
-     if (rc != CKR_OK)
-         TRACE_DEVEL("session_mgr_set_op_state() failed.\n");
-@@ -1556,7 +1557,7 @@ CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_Encrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -1612,7 +1613,7 @@ CK_RV SC_EncryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_EncryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -1671,7 +1672,7 @@ CK_RV SC_EncryptFinal(STDLL_TokData_t * tokdata, ST_SESSION_HANDLE * sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            encr_mgr_cleanup(&sess->encr_ctx);
-+            encr_mgr_cleanup(tokdata, sess, &sess->encr_ctx);
-     }
- 
-     TRACE_INFO("C_EncryptFinal: rc = 0x%08lx, sess = %ld\n",
-@@ -1790,7 +1791,7 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_Decrypt: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -1846,7 +1847,7 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_OK && rc != CKR_BUFFER_TOO_SMALL && sess != NULL) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_DecryptUpdate: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -1903,7 +1904,7 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || length_only != TRUE)) {
-         if (sess)
--            decr_mgr_cleanup(&sess->decr_ctx);
-+            decr_mgr_cleanup(tokdata, sess, &sess->decr_ctx);
-     }
- 
-     TRACE_INFO("C_DecryptFinal: rc = 0x%08lx, sess = %ld, amount = %lu\n",
-@@ -2261,7 +2262,7 @@ CK_RV SC_Sign(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_Sign: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-@@ -2312,7 +2313,7 @@ CK_RV SC_SignUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
-         TRACE_DEVEL("icsftok_sign_update() failed.\n");
- done:
-     if (rc != CKR_OK && sess != NULL)
--        sign_mgr_cleanup(&sess->sign_ctx);
-+        sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
- 
-     TRACE_INFO("C_SignUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
-@@ -2364,7 +2365,7 @@ CK_RV SC_SignFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- done:
-     if (rc != CKR_BUFFER_TOO_SMALL && (rc != CKR_OK || pSignature)) {
-         if (sess != NULL)
--            sign_mgr_cleanup(&sess->sign_ctx);
-+            sign_mgr_cleanup(tokdata, sess, &sess->sign_ctx);
-     }
- 
-     TRACE_INFO("C_SignFinal: rc = 0x%08lx, sess = %ld\n",
-@@ -2517,7 +2518,7 @@ CK_RV SC_Verify(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_Verify: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulDataLen);
-@@ -2568,7 +2569,7 @@ CK_RV SC_VerifyUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (rc != CKR_OK && sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_VerifyUpdate: rc = 0x%08lx, sess = %ld, datalen = %lu\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle, ulPartLen);
-@@ -2619,7 +2620,7 @@ CK_RV SC_VerifyFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
- 
- done:
-     if (sess != NULL)
--        verify_mgr_cleanup(&sess->verify_ctx);
-+        verify_mgr_cleanup(tokdata, sess, &sess->verify_ctx);
- 
-     TRACE_INFO("C_VerifyFinal: rc = 0x%08lx, sess = %ld\n",
-                rc, (sess == NULL) ? -1 : (CK_LONG) sess->handle);
diff --git a/SOURCES/opencryptoki-openssl3-ab3fceae6194e8213e9d3ffb7447ccd04d469b9d.patch b/SOURCES/opencryptoki-openssl3-ab3fceae6194e8213e9d3ffb7447ccd04d469b9d.patch
deleted file mode 100644
index 091bc8e..0000000
--- a/SOURCES/opencryptoki-openssl3-ab3fceae6194e8213e9d3ffb7447ccd04d469b9d.patch
+++ /dev/null
@@ -1,115 +0,0 @@
-commit ab3fceae6194e8213e9d3ffb7447ccd04d469b9d
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Mon Jul 5 10:45:04 2021 +0200
-
-    COMMON: sw_crypt.c: Remove support for OpenSSL < v1.1.1
-    
-    Remove support for OpenSSL < v1.1.1. This code used low level
-    DES/AES functions.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/sw_crypt.c b/usr/lib/common/sw_crypt.c
-index 906a41ab..253b3c26 100644
---- a/usr/lib/common/sw_crypt.c
-+++ b/usr/lib/common/sw_crypt.c
-@@ -32,51 +32,6 @@ CK_RV sw_des3_cbc(CK_BYTE *in_data,
-                   CK_ULONG *out_data_len,
-                   CK_BYTE *init_v, CK_BYTE *key_value, CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    DES_key_schedule des_key1;
--    DES_key_schedule des_key2;
--    DES_key_schedule des_key3;
--
--    const_DES_cblock key_SSL1, key_SSL2, key_SSL3;
--    DES_cblock ivec;
--
--    // the des decrypt will only fail if the data length is not evenly divisible
--    // by DES_BLOCK_SIZE
--    if (in_data_len % DES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--    // The key as passed in is a 24 byte string containing 3 keys
--    // pick it apart and create the key schedules
--    memcpy(&key_SSL1, key_value, (size_t) 8);
--    memcpy(&key_SSL2, key_value + 8, (size_t) 8);
--    memcpy(&key_SSL3, key_value + 16, (size_t) 8);
--    DES_set_key_unchecked(&key_SSL1, &des_key1);
--    DES_set_key_unchecked(&key_SSL2, &des_key2);
--    DES_set_key_unchecked(&key_SSL3, &des_key3);
--
--    memcpy(ivec, init_v, sizeof(ivec));
--
--    // Encrypt or decrypt the data
--    if (encrypt) {
--        DES_ede3_cbc_encrypt(in_data,
--                             out_data,
--                             in_data_len,
--                             &des_key1,
--                             &des_key2, &des_key3, &ivec, DES_ENCRYPT);
--        *out_data_len = in_data_len;
--    } else {
--        DES_ede3_cbc_encrypt(in_data,
--                             out_data,
--                             in_data_len,
--                             &des_key1,
--                             &des_key2, &des_key3, &ivec, DES_DECRYPT);
--
--        *out_data_len = in_data_len;
--    }
--
--    return CKR_OK;
--#else
-     CK_RV rc;
-     int outlen;
-     const EVP_CIPHER *cipher = EVP_des_ede3_cbc();
-@@ -109,7 +64,6 @@ CK_RV sw_des3_cbc(CK_BYTE *in_data,
- done:
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
- 
- CK_RV sw_aes_cbc(CK_BYTE *in_data,
-@@ -119,33 +73,6 @@ CK_RV sw_aes_cbc(CK_BYTE *in_data,
-                  CK_BYTE *init_v, CK_BYTE *key_value, CK_ULONG keylen,
-                  CK_BYTE encrypt)
- {
--#if OPENSSL_VERSION_NUMBER < 0x10100000L
--    AES_KEY aes_key;
--
--    UNUSED(out_data_len); //XXX can this parameter be removed ?
--
--    memset(&aes_key, 0, sizeof(aes_key));
--
--    // the aes decrypt will only fail if the data length is not evenly divisible
--    // by AES_BLOCK_SIZE
--    if (in_data_len % AES_BLOCK_SIZE) {
--        TRACE_ERROR("%s\n", ock_err(ERR_DATA_LEN_RANGE));
--        return CKR_DATA_LEN_RANGE;
--    }
--
--    // Encrypt or decrypt the data
--    if (encrypt) {
--        AES_set_encrypt_key(key_value, keylen * 8, &aes_key);
--        AES_cbc_encrypt(in_data, out_data, in_data_len, &aes_key,
--                        init_v, AES_ENCRYPT);
--    } else {
--        AES_set_decrypt_key(key_value, keylen * 8, &aes_key);
--        AES_cbc_encrypt(in_data,  out_data, in_data_len, &aes_key,
--                        init_v, AES_DECRYPT);
--    }
--
--    return CKR_OK;
--#else
-     CK_RV rc;
-     int outlen;
-     const EVP_CIPHER *cipher = NULL;
-@@ -187,5 +114,4 @@ CK_RV sw_aes_cbc(CK_BYTE *in_data,
- done:
-     EVP_CIPHER_CTX_free(ctx);
-     return rc;
--#endif
- }
diff --git a/SOURCES/opencryptoki-openssl3-c4683eb904238d20cb34a4c7661ffac04901283c.patch b/SOURCES/opencryptoki-openssl3-c4683eb904238d20cb34a4c7661ffac04901283c.patch
deleted file mode 100644
index 8a88c26..0000000
--- a/SOURCES/opencryptoki-openssl3-c4683eb904238d20cb34a4c7661ffac04901283c.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-commit c4683eb904238d20cb34a4c7661ffac04901283c
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Tue Jun 29 17:35:30 2021 +0200
-
-    COMMON: Add OPENSSL_VERSION_PREREQ macro to check for OpenSSL version
-    
-    Make the OPENSSL_VERSION_PREREQ macro available independent of the
-    used OpenSSL version, so that the code can easily check for the OpenSSL
-    version it is compiled with.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/usr/lib/common/defs.h b/usr/lib/common/defs.h
-index 22d75d2d..8ab50517 100644
---- a/usr/lib/common/defs.h
-+++ b/usr/lib/common/defs.h
-@@ -17,6 +17,20 @@
- #ifndef _DEFS_H
- #define _DEFS_H
- 
-+#include <openssl/opensslv.h>
-+
-+#ifndef OPENSSL_VERSION_PREREQ
-+    #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR)
-+        #define OPENSSL_VERSION_PREREQ(maj, min)        \
-+            ((OPENSSL_VERSION_MAJOR << 16) +        \
-+            OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))
-+    #else
-+        #define OPENSSL_VERSION_PREREQ(maj, min)        \
-+            (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | \
-+            ((min) << 20)))
-+    #endif
-+#endif
-+
- #define MAX_SESSION_COUNT     64
- #define MAX_PIN_LEN           8
- #define MIN_PIN_LEN           4
diff --git a/SOURCES/opencryptoki-openssl3-dd9cfe2ef89dad185397df46227f9392a6317d35.patch b/SOURCES/opencryptoki-openssl3-dd9cfe2ef89dad185397df46227f9392a6317d35.patch
deleted file mode 100644
index dccf2e8..0000000
--- a/SOURCES/opencryptoki-openssl3-dd9cfe2ef89dad185397df46227f9392a6317d35.patch
+++ /dev/null
@@ -1,49 +0,0 @@
-commit dd9cfe2ef89dad185397df46227f9392a6317d35
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Wed Jul 21 13:54:59 2021 +0200
-
-    CONFIGURE: Check that OpenSSL 1.1.1 or later is available
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/configure.ac b/configure.ac
-index 286b7408..f47060d9 100644
---- a/configure.ac
-+++ b/configure.ac
-@@ -277,21 +277,14 @@ if test "x$with_openssl" != "xno"; then
- 	old_libs="$LIBS"
- 	CFLAGS="$CFLAGS $OPENSSL_CFLAGS"
- 	LIBS="$LIBS $OPENSSL_LIBS"
--	AC_CHECK_HEADER([openssl/ssl.h], [], [
--		if test "x$with_openssl" != "xcheck"; then
--			AC_MSG_ERROR([Build with OpenSSL requested but OpenSSL headers couldn't be found])
--		fi
--		with_openssl=no
-+	AC_CHECK_HEADER([openssl/evp.h], [], [
-+		AC_MSG_ERROR([OpenSSL 1.1.1 or later is required but OpenSSL headers couldn't be found])
- 	])
- 	if test "x$with_openssl" != "xno"; then
--		AC_CHECK_LIB([crypto], [RSA_generate_key], [
-+		AC_CHECK_LIB([crypto], [EVP_sha3_256], [
- 			OPENSSL_LIBS="$OPENSSL_LIBS -lcrypto"
--			with_openssl=yes
--			], [
--				if test "x$with_openssl" != "xcheck"; then
--					AC_MSG_ERROR([Build with OpenSSL requested but OpenSSL libraries couldn't be found])
--				fi
--				with_openssl=no
-+			with_openssl=yes], [
-+			AC_MSG_ERROR([OpenSSL 1.1.1 or later is required but OpenSSL libraries version 1.1.1 or later couldn't be found])
- 		])
- 	fi
- 	if test "x$with_openssl" = "xno"; then
-@@ -299,6 +292,9 @@ if test "x$with_openssl" != "xno"; then
- 		LIBS="$old_libs"
- 	fi
- fi
-+if test "x$with_openssl" != "xyes"; then
-+	AC_MSG_ERROR([OpenSSL 1.1.1 or later is required but build without OpenSSL was requested])
-+fi
- AC_SUBST([OPENSSL_CFLAGS])
- AC_SUBST([OPENSSL_LIBS])
- 
diff --git a/SOURCES/opencryptoki-openssl3-ecf71404e84ae35931cd6c7398c825378ee052b6.patch b/SOURCES/opencryptoki-openssl3-ecf71404e84ae35931cd6c7398c825378ee052b6.patch
deleted file mode 100644
index 722c1d6..0000000
--- a/SOURCES/opencryptoki-openssl3-ecf71404e84ae35931cd6c7398c825378ee052b6.patch
+++ /dev/null
@@ -1,853 +0,0 @@
-commit ecf71404e84ae35931cd6c7398c825378ee052b6
-Author: Ingo Franzki <ifranzki@linux.ibm.com>
-Date:   Fri Jul 2 11:20:22 2021 +0200
-
-    TESTCASES: Soft: Skip tests with RSA publ.exp. not supported by OpenSSL
-    
-    OpenSSL 3.0 only accepts public exponents of 3 and 65537 for RSA keys.
-    Skip the testcase if another public exponent is used.
-    
-    Also fixed some ugly line breaks within messages.
-    
-    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
-
-diff --git a/testcases/common/common.c b/testcases/common/common.c
-index bfd486cb..0a64ecf2 100644
---- a/testcases/common/common.c
-+++ b/testcases/common/common.c
-@@ -876,6 +876,16 @@ int is_valid_cca_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len)
-         || (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3)));
- }
- 
-+/** Returns true if pubexp is valid for Soft Tokens **/
-+int is_valid_soft_pubexp(CK_BYTE pubexp[], CK_ULONG pubexp_len)
-+{
-+    CK_BYTE exp3[] = { 0x03 };  // 3
-+    CK_BYTE exp65537[] = { 0x01, 0x00, 0x01 };  // 65537
-+
-+    return (pubexp_len == 1 && (!memcmp(pubexp, exp3, 1)))
-+        || (pubexp_len == 3 && (!memcmp(pubexp, exp65537, 3)));
-+}
-+
- /** Returns true if slot_id is an ICSF token
-  ** ICSF token info is not necessarily hard-coded like the other tokens
-  ** so there is no single identifying attribute. So, instead just
-diff --git a/testcases/crypto/rsa_func.c b/testcases/crypto/rsa_func.c
-index 62aa7a76..8739ed37 100644
---- a/testcases/crypto/rsa_func.c
-+++ b/testcases/crypto/rsa_func.c
-@@ -102,8 +102,8 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].modbits);
-             free(s);
-             continue;
-         }
-@@ -111,8 +111,7 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -124,8 +123,7 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp,
-                                      tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -148,6 +146,16 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-                  continue;
-              }
-         }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp,
-+                                      tsuite->tv[i].publ_exp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp.='%s'",
-+                              s);
-+                free(s);
-+                continue;
-+            }
-+        }
-         // tpm special cases:
-         // tpm token can only use public exponent 0x010001 (65537)
-         // so skip test if invalid public exponent is used
-@@ -155,8 +163,7 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len))
-                 || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) {
--                testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'",
--                              s);
-+                testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -166,8 +173,7 @@ CK_RV do_EncryptDecryptRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-             if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len) ||
-                 (tsuite->tv[i].modbits < 1024)) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -376,8 +382,8 @@ CK_RV do_EncryptDecryptImportRSA(struct PUBLISHED_TEST_SUITE_INFO *tsuite)
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].mod_len * 8)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].mod_len * 8);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].mod_len * 8);
-             free(s);
-             continue;
-         }
-@@ -385,16 +391,14 @@ CK_RV do_EncryptDecryptImportRSA(struct PUBLISHED_TEST_SUITE_INFO *tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-             // modulus length must be multiple of 128 byte
-             // skip test if modulus length has unsuported size
-             if ((tsuite->tv[i].mod_len % 128) != 0) {
--                testcase_skip("EP11 Token cannot be used with "
--                              "this test vector.");
-+                testcase_skip("EP11 Token cannot be used with this test vector.");
-                 free(s);
-                 continue;
-             }
-@@ -416,8 +420,7 @@ CK_RV do_EncryptDecryptImportRSA(struct PUBLISHED_TEST_SUITE_INFO *tsuite)
-                 (tsuite->tv[i].exp2_len >
-                  (tsuite->tv[i].mod_len / 2)) ||
-                 (tsuite->tv[i].coef_len > (tsuite->tv[i].mod_len / 2))) {
--                testcase_skip("ICA Token cannot be used with "
--                              "this test vector.");
-+                testcase_skip("ICA Token cannot be used with this test vector.");
-                 free(s);
-                 continue;
-             }
-@@ -431,12 +434,21 @@ CK_RV do_EncryptDecryptImportRSA(struct PUBLISHED_TEST_SUITE_INFO *tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp,
-                                      tsuite->tv[i].pubexp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp.='%s'", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp,
-+                                      tsuite->tv[i].pubexp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-         }
-+
-         // tpm special cases:
-         // tpm token can only use public exponent 0x010001 (65537)
-         // so skip test if invalid public exponent is used
-@@ -444,8 +456,7 @@ CK_RV do_EncryptDecryptImportRSA(struct PUBLISHED_TEST_SUITE_INFO *tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len))
-                 || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len * 8))) {
--                testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'",
--                              s);
-+                testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -455,8 +466,7 @@ CK_RV do_EncryptDecryptImportRSA(struct PUBLISHED_TEST_SUITE_INFO *tsuite)
-             if (!is_valid_icsf_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len) ||
-                 (tsuite->tv[i].mod_len * 8 < 1024)) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -691,8 +701,8 @@ CK_RV do_SignVerifyRSA(struct GENERATED_TEST_SUITE_INFO * tsuite,
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].modbits);
-             free(s);
-             continue;
-         }
-@@ -700,8 +710,7 @@ CK_RV do_SignVerifyRSA(struct GENERATED_TEST_SUITE_INFO * tsuite,
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -710,8 +719,16 @@ CK_RV do_SignVerifyRSA(struct GENERATED_TEST_SUITE_INFO * tsuite,
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp,
-                                      tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp,
-+                                      tsuite->tv[i].publ_exp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -721,8 +738,7 @@ CK_RV do_SignVerifyRSA(struct GENERATED_TEST_SUITE_INFO * tsuite,
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len))
-                 || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) {
--                testcase_skip("TPM Token cannot " "be used with publ_exp='%s'.",
--                              s);
-+                testcase_skip("TPM Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -732,8 +748,7 @@ CK_RV do_SignVerifyRSA(struct GENERATED_TEST_SUITE_INFO * tsuite,
-             if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len) ||
-                 (tsuite->tv[i].modbits < 1024)) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -944,16 +959,23 @@ CK_RV do_SignVerify_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite)
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].modbits);
-             free(s);
-             continue;
-         }
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp,
-                                      tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp,
-+                                      tsuite->tv[i].publ_exp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -1154,8 +1176,8 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite)
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].modbits);
-             continue;
-         }
-         // get public exponent from test vector
-@@ -1169,8 +1191,7 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -1179,8 +1200,7 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite)
-             if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len) ||
-                 (tsuite->tv[i].modbits < 1024)) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -1189,8 +1209,7 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len)) ||
-                 (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) {
--                testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'",
--                              s);
-+                testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-            }
-@@ -1198,8 +1217,7 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp,
-                                      tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -1228,6 +1246,14 @@ CK_RV do_WrapUnwrapRSA(struct GENERATED_TEST_SUITE_INFO * tsuite)
-                  continue;
-              }
-         }
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp,
-+                                      tsuite->tv[i].publ_exp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
- 
-         // begin test
-         testcase_begin("%s Wrap Unwrap with test vector %d, "
-@@ -1554,8 +1580,7 @@ CK_RV do_SignRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-                 (tsuite->tv[i].exp2_len >
-                  (tsuite->tv[i].mod_len / 2)) ||
-                 (tsuite->tv[i].coef_len > (tsuite->tv[i].mod_len / 2))) {
--                testcase_skip("ICA Token cannot be used with "
--                              "this test vector.");
-+                testcase_skip("ICA Token cannot be used with this test vector.");
-                 continue;
-             }
- 
-@@ -1565,8 +1590,7 @@ CK_RV do_SignRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         // skip test if modulus length has unsuported size
-         if (is_ep11_token(slot_id)) {
-             if ((tsuite->tv[i].mod_len % 128) != 0) {
--                testcase_skip("EP11 Token cannot be used with "
--                              "this test vector.");
-+                testcase_skip("EP11 Token cannot be used with this test vector.");
-                 continue;
-             }
-         }
-@@ -1575,8 +1599,7 @@ CK_RV do_SignRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len))
-                 || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) {
--                testcase_skip("TPM Token cannot "
--                              "be used with this test vector.");
-+                testcase_skip("TPM Token cannot be used with this test vector.");
-                 continue;
-             }
-         }
-@@ -1584,8 +1607,15 @@ CK_RV do_SignRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp,
-                                      tsuite->tv[i].pubexp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with this test vector.");
-+                testcase_skip("CCA Token cannot be used with this test vector.");
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp,
-+                                      tsuite->tv[i].pubexp_len)) {
-+                testcase_skip("Soft Token cannot be used with this test vector.");
-                 continue;
-             }
-         }
-@@ -1735,8 +1765,7 @@ CK_RV do_VerifyRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         // skip test if modulus length has unsuported size
-         if (is_ep11_token(slot_id)) {
-             if ((tsuite->tv[i].mod_len % 128) != 0) {
--                testcase_skip("EP11 Token cannot be used with "
--                              "this test vector.");
-+                testcase_skip("EP11 Token cannot be used with this test vector.");
-                 continue;
-             }
-         }
-@@ -1745,8 +1774,7 @@ CK_RV do_VerifyRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len))
-                 || (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) {
--                testcase_skip("TPM Token cannot "
--                              "be used with this test vector.");
-+                testcase_skip("TPM Token cannot be used with this test vector.");
-                 continue;
-             }
-         }
-@@ -1754,8 +1782,15 @@ CK_RV do_VerifyRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp,
-                                      tsuite->tv[i].pubexp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with this test vector.");
-+                testcase_skip("CCA Token cannot be used with this test vector.");
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp,
-+                                      tsuite->tv[i].pubexp_len)) {
-+                testcase_skip("Soft Token cannot be used with this test vector.");
-                 continue;
-             }
-         }
-diff --git a/testcases/crypto/rsaupdate_func.c b/testcases/crypto/rsaupdate_func.c
-index 20611b85..22f8d7e4 100644
---- a/testcases/crypto/rsaupdate_func.c
-+++ b/testcases/crypto/rsaupdate_func.c
-@@ -96,8 +96,8 @@ CK_RV do_SignVerifyUpdateRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].modbits);
-             free(s);
-             continue;
-         }
-@@ -105,8 +105,7 @@ CK_RV do_SignVerifyUpdateRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -115,19 +114,27 @@ CK_RV do_SignVerifyUpdateRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp,
-                                      tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-         }
- 
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp,
-+                                      tsuite->tv[i].publ_exp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+
-+
-         if (is_tpm_token(slot_id)) {
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len))
-                 || (!is_valid_tpm_modbits(tsuite->tv[i].modbits))) {
--                testcase_skip("TPM Token cannot " "be used with publ_exp='%s'.",
--                              s);
-+                testcase_skip("TPM Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -137,8 +144,7 @@ CK_RV do_SignVerifyUpdateRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-             if (!is_valid_icsf_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len) ||
-                 (tsuite->tv[i].modbits < 1024)) {
--                testcase_skip("ICSF Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -162,8 +168,7 @@ CK_RV do_SignVerifyUpdateRSA(struct GENERATED_TEST_SUITE_INFO *tsuite)
-                                        tsuite->tv[i].publ_exp_len,
-                                        &publ_key, &priv_key);
-         if (rc != CKR_OK) {
--            testcase_error("generate_RSA_PKCS_KeyPair(), "
--                           "rc=%s", p11_get_ckr(rc));
-+            testcase_error("generate_RSA_PKCS_KeyPair(), rc=%s", p11_get_ckr(rc));
-             goto testcase_cleanup;
-         }
- 
-@@ -367,8 +372,8 @@ CK_RV do_SignVerifyUpdate_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite)
- 
-         if (!keysize_supported(slot_id, tsuite->mech.mechanism,
-                                tsuite->tv[i].modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", SLOT_ID, tsuite->tv[i].modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          SLOT_ID, tsuite->tv[i].modbits);
-             free(s);
-             continue;
-         }
-@@ -376,8 +381,7 @@ CK_RV do_SignVerifyUpdate_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].publ_exp,
-                                       tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -386,8 +390,16 @@ CK_RV do_SignVerifyUpdate_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].publ_exp,
-                                      tsuite->tv[i].publ_exp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].publ_exp,
-+                                      tsuite->tv[i].publ_exp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -412,8 +424,7 @@ CK_RV do_SignVerifyUpdate_RSAPSS(struct GENERATED_TEST_SUITE_INFO * tsuite)
-                                        tsuite->tv[i].publ_exp_len,
-                                        &publ_key, &priv_key);
-         if (rc != CKR_OK) {
--            testcase_error("generate_RSA_PKCS_KeyPair(), "
--                           "rc=%s", p11_get_ckr(rc));
-+            testcase_error("generate_RSA_PKCS_KeyPair(), rc=%s", p11_get_ckr(rc));
-             goto error;
-         }
-         // generate message
-@@ -639,8 +650,7 @@ CK_RV do_VerifyUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with pub_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with pub_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -650,8 +660,7 @@ CK_RV do_VerifyUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len)) ||
-                 (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) {
--                testcase_skip("TPM Token cannot "
--                              "be used with pub_exp='%s'.", s);
-+                testcase_skip("TPM Token cannot be used with pub_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -660,8 +669,16 @@ CK_RV do_VerifyUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp,
-                                      tsuite->tv[i].pubexp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp,
-+                                      tsuite->tv[i].pubexp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -826,8 +843,7 @@ CK_RV do_SignUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-                 (tsuite->tv[i].exp2_len >
-                  (tsuite->tv[i].mod_len / 2)) ||
-                 (tsuite->tv[i].coef_len > (tsuite->tv[i].mod_len / 2))) {
--                testcase_skip("ICA Token cannot be used with "
--                              "this test vector.");
-+                testcase_skip("ICA Token cannot be used with this test vector.");
-                 free(s);
-                 continue;
-             }
-@@ -848,8 +864,7 @@ CK_RV do_SignUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len)) {
--                testcase_skip("EP11 Token cannot "
--                              "be used with publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token cannot be used with publ_exp.='%s'", s);
-                 free(s);
-                 continue;
-             }
-@@ -859,8 +874,7 @@ CK_RV do_SignUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-             if ((!is_valid_tpm_pubexp(tsuite->tv[i].pub_exp,
-                                       tsuite->tv[i].pubexp_len)) ||
-                 (!is_valid_tpm_modbits(tsuite->tv[i].mod_len))) {
--                testcase_skip("TPM Token cannot "
--                              "be used with pub_exp='%s'.", s);
-+                testcase_skip("TPM Token cannot be used with pub_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-@@ -869,8 +883,16 @@ CK_RV do_SignUpdateRSA(struct PUBLISHED_TEST_SUITE_INFO * tsuite)
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(tsuite->tv[i].pub_exp,
-                                      tsuite->tv[i].pubexp_len)) {
--                testcase_skip("CCA Token cannot "
--                              "be used with publ_exp='%s'.", s);
-+                testcase_skip("CCA Token cannot be used with publ_exp='%s'.", s);
-+                free(s);
-+                continue;
-+            }
-+        }
-+
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(tsuite->tv[i].pub_exp,
-+                                      tsuite->tv[i].pubexp_len)) {
-+                testcase_skip("Soft Token cannot be used with publ_exp='%s'.", s);
-                 free(s);
-                 continue;
-             }
-diff --git a/testcases/misc_tests/reencrypt.c b/testcases/misc_tests/reencrypt.c
-index a78e1f5a..93fa31bd 100644
---- a/testcases/misc_tests/reencrypt.c
-+++ b/testcases/misc_tests/reencrypt.c
-@@ -361,24 +361,29 @@ CK_RV do_reencrypt(struct mech_info *mech1, struct mech_info *mech2)
- 
-         if (!keysize_supported(slot_id, mech2->key_gen_mech.mechanism,
-                                mech2->rsa_modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", slot_id, mech2->rsa_modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          slot_id, mech2->rsa_modbits);
-             goto testcase_cleanup;
-         }
- 
-         if (is_ep11_token(slot_id)) {
-             if (!is_valid_ep11_pubexp(mech2->rsa_publ_exp,
-                                       mech2->rsa_publ_exp_len)) {
--                testcase_skip("EP11 Token in cannot be used with "
--                             "publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token in cannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-         if (is_cca_token(slot_id)) {
-             if (!is_valid_cca_pubexp(mech2->rsa_publ_exp,
-                                      mech2->rsa_publ_exp_len)) {
--                testcase_skip("CCA Token in cannot be used with "
--                        "     publ_exp.='%s'", s);
-+                testcase_skip("CCA Token in cannot be used with publ_exp.='%s'", s);
-+                goto testcase_cleanup;
-+            }
-+        }
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(mech2->rsa_publ_exp,
-+                                      mech2->rsa_publ_exp_len)) {
-+                testcase_skip("Soft Token in cannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -386,8 +391,7 @@ CK_RV do_reencrypt(struct mech_info *mech1, struct mech_info *mech2)
-             if (!is_valid_tpm_pubexp(mech2->rsa_publ_exp,
-                                      mech2->rsa_publ_exp_len) ||
-                 !is_valid_tpm_modbits(mech2->rsa_modbits)) {
--                testcase_skip("TPM Token cannot be used with "
--                              "publ_exp.='%s'", s);
-+                testcase_skip("TPM Token cannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -395,8 +399,7 @@ CK_RV do_reencrypt(struct mech_info *mech1, struct mech_info *mech2)
-             if (!is_valid_icsf_pubexp(mech2->rsa_publ_exp,
-                                       mech2->rsa_publ_exp_len) ||
-                 mech2->rsa_modbits < 1024) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -619,6 +622,14 @@ CK_RV do_encrypt_reencrypt(struct mech_info *mech1)
-                 goto testcase_cleanup;
-             }
-         }
-+        if (is_soft_token(slot_id)) {
-+            if (!is_valid_soft_pubexp(mech1->rsa_publ_exp,
-+                                      mech1->rsa_publ_exp_len)) {
-+                testsuite_skip(NUM_REENCRYPT_TESTS, "Soft Token cannot be "
-+                               "used with publ_exp.='%s'", s);
-+                goto testcase_cleanup;
-+            }
-+        }
-         if (is_tpm_token(slot_id) ) {
-             if (!is_valid_tpm_pubexp(mech1->rsa_publ_exp,
-                                      mech1->rsa_publ_exp_len) ||
-diff --git a/testcases/misc_tests/tok2tok_transport.c b/testcases/misc_tests/tok2tok_transport.c
-index 9c1dee8f..ebb44760 100644
---- a/testcases/misc_tests/tok2tok_transport.c
-+++ b/testcases/misc_tests/tok2tok_transport.c
-@@ -581,30 +581,35 @@ CK_RV do_wrap_key_test(struct wrapped_mech_info *tsuite,
- 
-         if (!keysize_supported(slot_id1, tsuite->wrapped_key_gen_mech.mechanism,
-                                tsuite->rsa_modbits)) {
--            testcase_skip("Token in slot %lu cannot be used with "
--                          "modbits.='%ld'", slot_id1, tsuite->rsa_modbits);
-+            testcase_skip("Token in slot %lu cannot be used with modbits.='%ld'",
-+                          slot_id1, tsuite->rsa_modbits);
-             goto testcase_cleanup;
-         }
-         if (!keysize_supported(slot_id2, tsuite->wrapped_key_gen_mech.mechanism,
-                                tsuite->rsa_modbits)) {
--            testcase_skip("Token in slot %lu cannot be used with "
--                          "modbits.='%ld'", slot_id2, tsuite->rsa_modbits);
-+            testcase_skip("Token in slot %lu cannot be used with modbits.='%ld'",
-+                          slot_id2, tsuite->rsa_modbits);
-             goto testcase_cleanup;
-         }
- 
-         if (is_ep11_token(slot_id1) || is_ep11_token(slot_id2)) {
-             if (!is_valid_ep11_pubexp(tsuite->rsa_publ_exp,
-                                       tsuite->rsa_publ_exp_len)) {
--                testcase_skip("EP11 Token in cannot be used with "
--                             "publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token in cannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-         if (is_cca_token(slot_id1) || is_cca_token(slot_id2)) {
-             if (!is_valid_cca_pubexp(tsuite->rsa_publ_exp,
-                                      tsuite->rsa_publ_exp_len)) {
--                testcase_skip("CCA Token in scannot be used with "
--                              "publ_exp.='%s'", s);
-+                testcase_skip("CCA Token in scannot be used with publ_exp.='%s'", s);
-+                goto testcase_cleanup;
-+            }
-+        }
-+        if (is_soft_token(slot_id1) || is_cca_token(slot_id2)) {
-+            if (!is_valid_soft_pubexp(tsuite->rsa_publ_exp,
-+                                      tsuite->rsa_publ_exp_len)) {
-+                testcase_skip("Soft Token in scannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -612,8 +617,7 @@ CK_RV do_wrap_key_test(struct wrapped_mech_info *tsuite,
-             if (!is_valid_tpm_pubexp(tsuite->rsa_publ_exp,
-                                      tsuite->rsa_publ_exp_len) ||
-                 !is_valid_tpm_modbits(tsuite->rsa_modbits)) {
--                testcase_skip("TPM Token cannot " "be used with "
--                              "publ_exp.='%s'", s);
-+                testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -621,8 +625,7 @@ CK_RV do_wrap_key_test(struct wrapped_mech_info *tsuite,
-             if (!is_valid_icsf_pubexp(tsuite->rsa_publ_exp,
-                                       tsuite->rsa_publ_exp_len) ||
-                 tsuite->rsa_modbits < 1024) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -967,31 +970,36 @@ CK_RV do_wrapping_test(struct wrapping_mech_info *tsuite)
-         if (!keysize_supported(slot_id1,
-                                tsuite->wrapping_key_gen_mech.mechanism,
-                                tsuite->rsa_modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", slot_id1, tsuite->rsa_modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          slot_id1, tsuite->rsa_modbits);
-             goto testcase_cleanup;
-         }
-         if (!keysize_supported(slot_id2,
-                                tsuite->wrapping_key_gen_mech.mechanism,
-                                tsuite->rsa_modbits)) {
--            testcase_skip("Token in slot %ld cannot be used with "
--                          "modbits.='%ld'", slot_id2, tsuite->rsa_modbits);
-+            testcase_skip("Token in slot %ld cannot be used with modbits.='%ld'",
-+                          slot_id2, tsuite->rsa_modbits);
-             goto testcase_cleanup;
-         }
- 
-         if (is_ep11_token(slot_id1) || is_ep11_token(slot_id2)) {
-             if (!is_valid_ep11_pubexp(tsuite->rsa_publ_exp,
-                                       tsuite->rsa_publ_exp_len)) {
--                testcase_skip("EP11 Token in cannot be used with "
--                             "publ_exp.='%s'", s);
-+                testcase_skip("EP11 Token in cannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-         if (is_cca_token(slot_id1) || is_cca_token(slot_id2)) {
-             if (!is_valid_cca_pubexp(tsuite->rsa_publ_exp,
-                                      tsuite->rsa_publ_exp_len)) {
--                testcase_skip("CCA Token in scannot be used with "
--                              "publ_exp.='%s'", s);
-+                testcase_skip("CCA Token in scannot be used with publ_exp.='%s'", s);
-+                goto testcase_cleanup;
-+            }
-+        }
-+        if (is_soft_token(slot_id1) || is_soft_token(slot_id2)) {
-+            if (!is_valid_soft_pubexp(tsuite->rsa_publ_exp,
-+                                      tsuite->rsa_publ_exp_len)) {
-+                testcase_skip("Soft Token in scannot be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -999,8 +1007,7 @@ CK_RV do_wrapping_test(struct wrapping_mech_info *tsuite)
-             if (!is_valid_tpm_pubexp(tsuite->rsa_publ_exp,
-                                      tsuite->rsa_publ_exp_len) ||
-                 !is_valid_tpm_modbits(tsuite->rsa_modbits)) {
--                testcase_skip("TPM Token cannot " "be used with "
--                              "publ_exp.='%s'", s);
-+                testcase_skip("TPM Token cannot " "be used with publ_exp.='%s'", s);
-                 goto testcase_cleanup;
-             }
-         }
-@@ -1008,8 +1015,7 @@ CK_RV do_wrapping_test(struct wrapping_mech_info *tsuite)
-             if (!is_valid_icsf_pubexp(tsuite->rsa_publ_exp,
-                                       tsuite->rsa_publ_exp_len) ||
-                 tsuite->rsa_modbits < 1024) {
--                testcase_skip("ICSF Token cannot be used with "
--                              "publ_exp='%s'.", s);
-+                testcase_skip("ICSF Token cannot be used with publ_exp='%s'.", s);
-                 goto testcase_cleanup;
-             }
-         }
diff --git a/SOURCES/opencryptoki-pkcsslotd-pidfile.patch b/SOURCES/opencryptoki-pkcsslotd-pidfile.patch
index 8af4d96..92f7e3c 100644
--- a/SOURCES/opencryptoki-pkcsslotd-pidfile.patch
+++ b/SOURCES/opencryptoki-pkcsslotd-pidfile.patch
@@ -10,3 +10,20 @@ diff -up opencryptoki-3.16.0/misc/pkcsslotd.service.in.me opencryptoki-3.16.0/mi
  ExecStart=@sbindir@/pkcsslotd
  
  [Install]
+diff -up opencryptoki-3.16.0/usr/include/slotmgr.h.me opencryptoki-3.16.0/usr/include/slotmgr.h
+--- opencryptoki-3.16.0/usr/include/slotmgr.h.me	2021-06-30 17:28:18.000594834 +0200
++++ opencryptoki-3.16.0/usr/include/slotmgr.h	2021-06-30 17:28:38.920890278 +0200
+@@ -30,10 +30,10 @@
+ #define TOK_PATH  SBIN_PATH "/pkcsslotd"
+ #define OCK_API_LOCK_FILE LOCKDIR_PATH "/LCK..APIlock"
+ 
+-#define PROC_SOCKET_FILE_PATH "/var/run/pkcsslotd.socket"
+-#define ADMIN_SOCKET_FILE_PATH "/var/run/pkcsslotd.admin.socket"
++#define PROC_SOCKET_FILE_PATH "/run/pkcsslotd.socket"
++#define ADMIN_SOCKET_FILE_PATH "/run/pkcsslotd.admin.socket"
+ 
+-#define PID_FILE_PATH "/var/run/pkcsslotd.pid"
++#define PID_FILE_PATH "/run/pkcsslotd.pid"
+ #define OCK_CONFIG OCK_CONFDIR "/opencryptoki.conf"
+ 
+ #ifndef CK_BOOL
diff --git a/SOURCES/opencryptoki.module b/SOURCES/opencryptoki.module
deleted file mode 100644
index 4720c04..0000000
--- a/SOURCES/opencryptoki.module
+++ /dev/null
@@ -1,8 +0,0 @@
-# This file describes how to load the opensc module
-# See: http://p11-glue.freedesktop.org/doc/p11-kit/config.html
-
-# This is a relative path, which means it will be loaded from
-# the p11-kit default path which is usually $(libdir)/pkcs11.
-# Doing it this way allows for packagers to package opensc for
-# 32-bit and 64-bit and make them parallel installable
-module: libopencryptoki.so
diff --git a/SPECS/opencryptoki.spec b/SPECS/opencryptoki.spec
index 6235217..0c064ad 100644
--- a/SPECS/opencryptoki.spec
+++ b/SPECS/opencryptoki.spec
@@ -1,66 +1,25 @@
 Name:			opencryptoki
-Summary:		Implementation of the PKCS#11 (Cryptoki) specification v2.11
-Version:		3.16.0
-Release:		12%{?dist}
+Summary:		Implementation of the PKCS#11 (Cryptoki) specification v3.0
+Version:		3.17.0
+Release:		3%{?dist}
 License:		CPL
 URL:			https://github.com/opencryptoki/opencryptoki
 Source0:		https://github.com/opencryptoki/%{name}/archive/v%{version}/%{name}-%{version}.tar.gz
-Source1:		opencryptoki.module
 # https://bugzilla.redhat.com/show_bug.cgi?id=732756
 Patch0:			opencryptoki-3.11.0-group.patch
-
 # bz#1373833, change tmpfiles snippets from /var/lock/* to /run/lock/*
 Patch1:			opencryptoki-3.11.0-lockdir.patch
-# PIDfile below legacy directory /var/run/
-Patch2:			opencryptoki-pkcsslotd-pidfile.patch
-# Use --no-undefined to debug missing symbols
-#Patch100:			%%{name}-3.2-no-undefined.patch
-
+# add missing p11sak_defined_attrs.conf
+Patch2:			opencryptoki-3.17.0-p11sak.patch
 # upstream patches
-Patch200:	opencryptoki-3.16.0-4e3b43c3d8844402c04a66b55c6c940f965109f0.patch
-Patch201:	opencryptoki-3.16.0-c79e899d77a5724635a9d4451a34a240e2c7e891.patch
-Patch202:	opencryptoki-3.16.0-69244a5e0d9dfec3ef534b19b89a541576bb17dc.patch
-Patch203:	opencryptoki-3.16.0-b07505993dd8b2f367cf3b630f6da186e4e8550d.patch
-Patch204:	opencryptoki-3.16.0-b048be548508dd1958bb7271568f388d0f6cbcf8.patch
-Patch205:	opencryptoki-3.16.0-e9548127edae313da7840bcb87fd0afd04549c2e.patch
-Patch206:	opencryptoki-3.16.0-d929fe8470e99f4dcbbd889e7aa87e147d0d5b48.patch
-Patch207:	opencryptoki-3.16.0-19f56d12b302b87e1dacf613cc61a063ad209d15.patch
-Patch208:	opencryptoki-3.16.0-342dfbeb8275f5ea6ed52dd3f30126614ec1d037.patch
-Patch209:	opencryptoki-3.16.0-fa94a16116d8382a987ddf9e8cdd88027dd1f647.patch
-Patch210:	opencryptoki-3.16.0-d7de5092247a0efc2c397f12977a7c9925420143.patch
-Patch211:	opencryptoki-3.16.0-1fdd0e4497b0078e73e0004e3492db647c7c458b.patch
-Patch212:	opencryptoki-3.16.0-bf812c652c49d7e248b115d121a4f7f6568941a2.patch
-Patch213:	opencryptoki-3.16.0-7b7d83c571ceb3050969359817d4145600f14ae8.patch
-Patch214:	opencryptoki-3.16.0-pkcstok_migrate-detection_if_pkcsslotd_is_still_running.patch
-Patch215:	opencryptoki-3.16.0-5824364d995e5d2418f885ee57e377e11d1b3302.patch
-Patch216:	opencryptoki-3.16.0-e88a9de3128df1c4b89bd4c7312c15bb3eb34593.patch
-Patch217:	opencryptoki-3.16.0-d2f137cce5e6efb123842509352c7c49f889c67f.patch
-Patch218:	opencryptoki-openssl3-dd9cfe2ef89dad185397df46227f9392a6317d35.patch
-Patch219:	opencryptoki-openssl3-93588f53d918fe6c7452da076b95081fb6aa9aef.patch
-Patch220:	opencryptoki-openssl3-62fc2bcd98672c5d0ff8a2c926f3103110e91ed7.patch
-Patch221:	opencryptoki-openssl3-50408fc3ae0f25b256dda2033d538f88c9b4f903.patch
-Patch222:	opencryptoki-openssl3-145a696d478a1694ef314659a3d374f03f75c1b1.patch
-Patch223:	opencryptoki-openssl3-7a23c12214688b287b9591133445e593da633caa.patch
-Patch224:	opencryptoki-openssl3-ecf71404e84ae35931cd6c7398c825378ee052b6.patch
-Patch225:	opencryptoki-openssl3-50e3f06823696c74eea90a77e16b28da1f79cd47.patch
-Patch226:	opencryptoki-openssl3-ab3fceae6194e8213e9d3ffb7447ccd04d469b9d.patch
-Patch227:	opencryptoki-openssl3-5377d25a6cbe3d07afcd08276ad7e90f62cad0c9.patch
-Patch228:	opencryptoki-openssl3-6fee37f08391415cdf8d8610c501516c3d3ed29c.patch
-Patch230:	opencryptoki-openssl3-2c116d49359a5eb91ad7f1483c64650c7874a513.patch
-Patch231:	opencryptoki-openssl3-533cdea6897d1bc0af13490f1c89248c52e7a73b.patch
-Patch232:	opencryptoki-openssl3-5cceead028ec8e0c244b01d38c9096c96d98f96b.patch
-Patch233:	opencryptoki-openssl3-7b4177e8557887d196ce77a129d457e817f8cc59.patch
-Patch234:	opencryptoki-openssl3-11a53055b22d590bd3c197908b0ff63f6fd3c520.patch
-Patch235:	opencryptoki-openssl3-c4683eb904238d20cb34a4c7661ffac04901283c.patch
-Patch236:	opencryptoki-openssl3-11196c4d7e221d29f0d385bd48ae4d6023a6e874.patch
-Patch237:	opencryptoki-openssl3-4dd8a952fc00dd54cce090e4c053de408ba3884b.patch
-Patch238:	opencryptoki-openssl3-376e664f082b66de970b62a81588b034fd560d27.patch
+# PIDfile below legacy directory /var/run/
+Patch300: opencryptoki-pkcsslotd-pidfile.patch
 
 Requires(pre):		coreutils
 Requires: 		(selinux-policy >= 34.1.8-1 if selinux-policy-targeted)
 BuildRequires:		gcc
 BuildRequires:		gcc-c++
-BuildRequires:		openssl-devel
+BuildRequires:		openssl-devel >= 1.1.1
 %if 0%{?tmptok}
 BuildRequires:		trousers-devel
 %endif
@@ -72,7 +31,7 @@ BuildRequires:		libitm-devel
 BuildRequires:		expect
 BuildRequires:		make
 %ifarch s390 s390x
-BuildRequires:		libica-devel >= 2.3
+BuildRequires:		libica-devel >= 3.3
 %endif
 Requires(pre):		%{name}-libs%{?_isa} = %{version}-%{release}
 Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
@@ -83,7 +42,7 @@ Requires(postun):	systemd
 
 
 %description
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -96,7 +55,7 @@ Summary:		The run-time libraries for opencryptoki package
 Requires(pre):	shadow-utils
 
 %description libs
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -122,7 +81,7 @@ Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
 Provides:		%{name}(token)
 
 %description swtok
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -138,7 +97,7 @@ Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
 Provides:		%{name}(token)
 
 %description tpmtok
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -154,7 +113,7 @@ Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
 Provides:		%{name}(token)
 
 %description icsftok
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -171,7 +130,7 @@ Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
 Provides:		%{name}(token)
 
 %description icatok
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -188,7 +147,7 @@ Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
 Provides:		%{name}(token)
 
 %description ccatok
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -205,7 +164,7 @@ Requires:		%{name}-libs%{?_isa} = %{version}-%{release}
 Provides:		%{name}(token)
 
 %description ep11tok
-Opencryptoki implements the PKCS#11 specification v2.11 for a set of
+Opencryptoki implements the PKCS#11 specification v2.20 for a set of
 cryptographic hardware, such as IBM 4764 and 4765 crypto cards, and the
 Trusted Platform Module (TPM) chip. Opencryptoki also brings a software
 token implementation that can be used without any cryptographic
@@ -266,6 +225,7 @@ fi
 %doc doc/README.token_data
 %dir %{_sysconfdir}/%{name}
 %config(noreplace) %{_sysconfdir}/%{name}/%{name}.conf
+%attr(0640, root, pkcs11) %config(noreplace) %{_sysconfdir}/%{name}/p11sak_defined_attrs.conf
 %{_tmpfilesdir}/%{name}.conf
 %{_unitdir}/pkcsslotd.service
 %{_sbindir}/p11sak
@@ -276,6 +236,7 @@ fi
 %{_mandir}/man1/pkcstok_migrate.1*
 %{_mandir}/man1/pkcsconf.1*
 %{_mandir}/man5/%{name}.conf.5*
+%{_mandir}/man5/p11sak_defined_attrs.conf.5*
 %{_mandir}/man7/%{name}.7*
 %{_mandir}/man8/pkcsslotd.8*
 %{_libdir}/opencryptoki/methods
@@ -357,6 +318,16 @@ fi
 
 
 %changelog
+* Sat Dec 04 2021 Than Ngo <than@redhat.com> - 3.17.0-3
+- Related: #2015888, added missing patch pkcsslotd-pidfile
+
+* Wed Nov 24 2021 Than Ngo <than@redhat.com> - 3.17.0-2
+- Related: #2015888, add missing p11sak_defined_attrs.conf
+
+* Wed Nov 03 2021 Than Ngo <than@redhat.com> - 3.17.0-1
+- Resolves: #2015888, rebase to 3.17.0
+- Resolves: #2017720, openCryptoki key management tool 
+
 * Thu Aug 26 2021 Than Ngo <than@redhat.com> - 3.16.0-12
 - Related: #1989138, Support for OpenSSL 3.0