Blame SOURCES/opencryptoki-3.16.0-1fdd0e4497b0078e73e0004e3492db647c7c458b.patch

9c2944
commit 1fdd0e4497b0078e73e0004e3492db647c7c458b
9c2944
Author: Ingo Franzki <ifranzki@linux.ibm.com>
9c2944
Date:   Wed Feb 24 15:47:05 2021 +0100
9c2944
9c2944
    EP11: Handle APQN events to update APQN version, CP infos and target
9c2944
    
9c2944
    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
9c2944
9c2944
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
9c2944
index 52f95d7a..728fedd5 100644
9c2944
--- a/usr/lib/ep11_stdll/ep11_specific.c
9c2944
+++ b/usr/lib/ep11_stdll/ep11_specific.c
9c2944
@@ -38,6 +38,7 @@
9c2944
 #include "ock_syslog.h"
9c2944
 #include "ec_defs.h"
9c2944
 #include "p11util.h"
9c2944
+#include "events.h"
9c2944
 
9c2944
 #include <sys/types.h>
9c2944
 #include <sys/stat.h>
9c2944
@@ -197,19 +198,27 @@ typedef struct {
9c2944
 
9c2944
 #define MAX_RETRY_COUNT 100
9c2944
 
9c2944
-#define RETRY_START             do {                                     \
9c2944
+#define RETRY_START(rc, tokdata)                                         \
9c2944
+                                do {                                     \
9c2944
                                     int retry_count;                     \
9c2944
+                                    ep11_target_info_t* target_info =    \
9c2944
+                                             get_target_info((tokdata)); \
9c2944
+                                    if (target_info == NULL)             \
9c2944
+                                        (rc) = CKR_FUNCTION_FAILED;      \
9c2944
                                     for(retry_count = 0;                 \
9c2944
+                                        target_info != NULL &&           \
9c2944
                                         retry_count < MAX_RETRY_COUNT;   \
9c2944
                                         retry_count ++) {
9c2944
 
9c2944
 #define RETRY_END(rc, tokdata, session)  if ((rc) != CKR_SESSION_CLOSED) \
9c2944
                                              break;                      \
9c2944
                                          (rc) = ep11tok_relogin_session( \
9c2944
-                                                      tokdata, session); \
9c2944
+                                                  (tokdata), (session)); \
9c2944
                                          if ((rc) != CKR_OK)             \
9c2944
                                              break;                      \
9c2944
                                     }                                    \
9c2944
+                                    put_target_info((tokdata),           \
9c2944
+                                                    target_info);        \
9c2944
                                 } while (0);
9c2944
 
9c2944
 #define CKF_EP11_HELPER_SESSION      0x80000000
9c2944
@@ -248,7 +257,6 @@ typedef struct ep11_card_version {
9c2944
 } ep11_card_version_t;
9c2944
 
9c2944
 static CK_RV ep11tok_get_ep11_library_version(CK_VERSION *lib_version);
9c2944
-static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata);
9c2944
 static void free_card_versions(ep11_card_version_t *card_version);
9c2944
 static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
9c2944
                               const CK_VERSION *ep11_lib_version,
9c2944
@@ -476,16 +484,23 @@ static CK_RV handle_all_ep11_cards(ep11_target_t * ep11_targets,
9c2944
 #define PKEY_MODE_ENABLE4NONEXTR    2
9c2944
 
9c2944
 typedef struct {
9c2944
+    volatile unsigned long ref_count;
9c2944
     target_t target;
9c2944
+    ep11_card_version_t *card_versions;
9c2944
+    CK_ULONG used_firmware_API_version;
9c2944
+    unsigned char control_points[XCP_CP_BYTES];
9c2944
+    size_t control_points_len;
9c2944
+    size_t max_control_point_index;
9c2944
+    CK_CHAR serialNumber[16];
9c2944
+} ep11_target_info_t;
9c2944
+
9c2944
+typedef struct {
9c2944
     ep11_target_t target_list;
9c2944
     CK_BYTE raw2key_wrap_blob[MAX_BLOBSIZE];
9c2944
     size_t raw2key_wrap_blob_l;
9c2944
     int cka_sensitive_default_true;
9c2944
     char cp_filter_config_filename[PATH_MAX];
9c2944
     cp_config_t *cp_config;
9c2944
-    unsigned char control_points[XCP_CP_BYTES];
9c2944
-    size_t control_points_len;
9c2944
-    size_t max_control_point_index;
9c2944
     int strict_mode;
9c2944
     int vhsm_mode;
9c2944
     int optimize_single_ops;
9c2944
@@ -497,12 +512,14 @@ typedef struct {
9c2944
     char digest_libica_path[PATH_MAX];
9c2944
     libica_t libica;
9c2944
     CK_VERSION ep11_lib_version;
9c2944
-    ep11_card_version_t *card_versions;
9c2944
-    CK_ULONG used_firmware_API_version;
9c2944
-    CK_CHAR serialNumber[16];
9c2944
+    volatile ep11_target_info_t *target_info;
9c2944
+    pthread_rwlock_t target_rwlock;
9c2944
 } ep11_private_data_t;
9c2944
 
9c2944
-static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata);
9c2944
+static ep11_target_info_t *get_target_info(STDLL_TokData_t *tokdata);
9c2944
+static void put_target_info(STDLL_TokData_t *tokdata,
9c2944
+                            ep11_target_info_t *target_info);
9c2944
+static CK_RV refresh_target_info(STDLL_TokData_t *tokdata);
9c2944
 
9c2944
 static CK_RV get_ep11_target_for_apqn(uint_32 adapter, uint_32 domain,
9c2944
                                       target_t *target, uint64_t flags);
9c2944
@@ -704,8 +721,13 @@ static CK_RV ep11tok_pkey_get_firmware_mk_vp(STDLL_TokData_t *tokdata)
9c2944
     CK_BYTE blob[MAX_BLOBSIZE];
9c2944
     size_t blobsize = sizeof(blob);
9c2944
     CK_ATTRIBUTE *pkey_attr = NULL, *blob_attr=NULL;
9c2944
+    ep11_target_info_t* target_info;
9c2944
     CK_RV ret;
9c2944
 
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
     /* Check if CPACF_WRAP mech supported */
9c2944
     if (ep11tok_is_mechanism_supported(tokdata, CKM_IBM_CPACF_WRAP) != CKR_OK) {
9c2944
         TRACE_INFO("CKM_IBM_CPACF_WRAP not supported on this system.\n");
9c2944
@@ -717,7 +739,7 @@ static CK_RV ep11tok_pkey_get_firmware_mk_vp(STDLL_TokData_t *tokdata)
9c2944
 
9c2944
     /* Create an AES testkey with CKA_IBM_PROTKEY_EXTRACTABLE */
9c2944
     ret = dll_m_GenerateKey(&mech, tmpl, tmpl_len, NULL, 0,
9c2944
-                            blob, &blobsize, csum, &csum_l, ep11_data->target);
9c2944
+                            blob, &blobsize, csum, &csum_l, target_info->target);
9c2944
     if (ret != CKR_OK) {
9c2944
         TRACE_ERROR("dll_m_GenerateKey failed with rc=0x%lx\n",ret);
9c2944
         goto done;
9c2944
@@ -749,6 +771,8 @@ done:
9c2944
     if (blob_attr)
9c2944
         free(blob_attr);
9c2944
 
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+
9c2944
     return ret;
9c2944
 }
9c2944
 
9c2944
@@ -1337,7 +1361,7 @@ static CK_RV ab_unwrap_update_template(STDLL_TokData_t * tokdata,
9c2944
                                        OBJECT *obj,
9c2944
                                        CK_KEY_TYPE keytype)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    ep11_target_info_t* target_info;
9c2944
     CK_RV rc;
9c2944
     CK_BBOOL trusted, encrypt, decrypt, wrap, unwrap, sign, sign_recover,
9c2944
              verify, verify_recover, derive, extractable, local,
9c2944
@@ -1367,9 +1391,16 @@ static CK_RV ab_unwrap_update_template(STDLL_TokData_t * tokdata,
9c2944
     CK_ATTRIBUTE *attr;
9c2944
     CK_BBOOL cktrue = TRUE;
9c2944
 
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
     rc = dll_m_GetAttributeValue(blob, blob_len, attrs,
9c2944
                                  sizeof(attrs) / sizeof(CK_ATTRIBUTE),
9c2944
-                                 ep11_data->target);
9c2944
+                                 target_info->target);
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+
9c2944
     if (rc != CKR_OK) {
9c2944
         TRACE_ERROR("Retrieving attributes from AB unwrapped key failed, rc=0x%lx\n",
9c2944
                     rc);
9c2944
@@ -2117,10 +2148,10 @@ static CK_RV rawkey_2_blob(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
      * calls the ep11 lib (which in turns sends the request to the card),
9c2944
      * all m_ function are ep11 functions
9c2944
      */
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
9c2944
                                  ep11_data->raw2key_wrap_blob_l, &mech, key,
9c2944
-                                 ksize, cipher, &clen, ep11_data->target);
9c2944
+                                 ksize, cipher, &clen, target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -2146,12 +2177,12 @@ static CK_RV rawkey_2_blob(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
     /* the encrypted key is decrypted and a blob is build,
9c2944
      * card accepts only blobs as keys
9c2944
      */
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_UnwrapKey(cipher, clen, ep11_data->raw2key_wrap_blob,
9c2944
                              ep11_data->raw2key_wrap_blob_l, NULL, ~0,
9c2944
                              ep11_pin_blob, ep11_pin_blob_len, &mech,
9c2944
                              new_p_attrs, new_attrs_len, blob, blen, csum,
9c2944
-                             &cslen, ep11_data->target);
9c2944
+                             &cslen, target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -2194,14 +2225,20 @@ rawkey_2_blob_end:
9c2944
 CK_RV token_specific_rng(STDLL_TokData_t * tokdata, CK_BYTE * output,
9c2944
                          CK_ULONG bytes)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
-    CK_RV rc = dll_m_GenerateRandom(output, bytes, ep11_data->target);
9c2944
+    CK_RV rc = dll_m_GenerateRandom(output, bytes, target_info->target);
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
         TRACE_ERROR("%s output=%p bytes=%lu rc=0x%lx\n",
9c2944
                     __func__, (void *)output, bytes, rc);
9c2944
     }
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
@@ -2215,6 +2252,7 @@ static CK_RV make_wrapblob(STDLL_TokData_t * tokdata, CK_ATTRIBUTE * tmpl_in,
9c2944
 {
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_MECHANISM mech = { CKM_AES_KEY_GEN, NULL_PTR, 0 };
9c2944
+    ep11_target_info_t* target_info;
9c2944
     CK_BYTE csum[MAX_CSUMSIZE];
9c2944
     size_t csum_l = sizeof(csum);
9c2944
     CK_RV rc;
9c2944
@@ -2225,11 +2263,15 @@ static CK_RV make_wrapblob(STDLL_TokData_t * tokdata, CK_ATTRIBUTE * tmpl_in,
9c2944
         return CKR_OK;
9c2944
     }
9c2944
 
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
     ep11_data->raw2key_wrap_blob_l = sizeof(ep11_data->raw2key_wrap_blob);
9c2944
     rc = dll_m_GenerateKey(&mech, tmpl_in, tmpl_len, NULL, 0,
9c2944
                            ep11_data->raw2key_wrap_blob,
9c2944
                            &ep11_data->raw2key_wrap_blob_l, csum, &csum_l,
9c2944
-                           ep11_data->target);
9c2944
+                           target_info->target);
9c2944
 
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -2240,6 +2282,7 @@ static CK_RV make_wrapblob(STDLL_TokData_t * tokdata, CK_ATTRIBUTE * tmpl_in,
9c2944
                    __func__, ep11_data->raw2key_wrap_blob_l, rc);
9c2944
     }
9c2944
 
9c2944
+    put_target_info(tokdata, target_info);
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
@@ -2479,6 +2522,14 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
9c2944
     if (ep11_data == NULL)
9c2944
         return CKR_HOST_MEMORY;
9c2944
 
9c2944
+    if (pthread_rwlock_init(&ep11_data->target_rwlock, NULL) != 0) {
9c2944
+        TRACE_DEVEL("Target Lock init failed.\n");
9c2944
+        OCK_SYSLOG(LOG_ERR, "%s: Failed to initialize the target lock\n",
9c2944
+                   __func__);
9c2944
+        rc = CKR_CANT_LOCK;
9c2944
+        goto error;
9c2944
+    }
9c2944
+
9c2944
     tokdata->private_data = ep11_data;
9c2944
 
9c2944
     /* read ep11 specific config file with user specified
9c2944
@@ -2513,13 +2564,28 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
9c2944
     }
9c2944
 #endif
9c2944
 
9c2944
-    rc = ep11tok_get_ep11_version(tokdata);
9c2944
-    if (rc != CKR_OK)
9c2944
+    rc = ep11tok_get_ep11_library_version(&ep11_data->ep11_lib_version);
9c2944
+    if (rc != CKR_OK) {
9c2944
+        TRACE_ERROR("%s Failed to get the Ep11 library version "
9c2944
+                    "(ep11tok_get_ep11_library_version rc=0x%lx)\n", __func__,
9c2944
+                    rc);
9c2944
+        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the EP11 library version "
9c2944
+                   "rc=0x%lx\n", __func__, rc);
9c2944
         goto error;
9c2944
+    }
9c2944
 
9c2944
-    rc = ep11tok_setup_target(tokdata);
9c2944
-    if (rc != CKR_OK)
9c2944
+    TRACE_INFO("%s Host library version: %d.%d\n", __func__,
9c2944
+               ep11_data->ep11_lib_version.major,
9c2944
+               ep11_data->ep11_lib_version.minor);
9c2944
+
9c2944
+    rc = refresh_target_info(tokdata);
9c2944
+    if (rc != CKR_OK) {
9c2944
+        TRACE_ERROR("%s Failed to get the target info (refresh_target_info "
9c2944
+                    "rc=0x%lx)\n", __func__, rc);
9c2944
+        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the target info rc=0x%lx\n",
9c2944
+                   __func__, rc);
9c2944
         goto error;
9c2944
+    }
9c2944
 
9c2944
     if (ep11_data->digest_libica) {
9c2944
         rc = ep11tok_load_libica(tokdata);
9c2944
@@ -2530,18 +2596,6 @@ CK_RV ep11tok_init(STDLL_TokData_t * tokdata, CK_SLOT_ID SlotNumber,
9c2944
     ep11_data->msa_level = get_msa_level();
9c2944
     TRACE_INFO("MSA level = %i\n", ep11_data->msa_level);
9c2944
 
9c2944
-    ep11_data->control_points_len = sizeof(ep11_data->control_points);
9c2944
-    rc = get_control_points(tokdata, ep11_data->control_points,
9c2944
-                            &ep11_data->control_points_len,
9c2944
-                            &ep11_data->max_control_point_index);
9c2944
-    if (rc != CKR_OK) {
9c2944
-        TRACE_ERROR("%s Failed to get the control points (get_control_points "
9c2944
-                    "rc=0x%lx)\n", __func__, rc);
9c2944
-        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the control points rc=0x%lx\n",
9c2944
-                   __func__, rc);
9c2944
-        goto error;
9c2944
-    }
9c2944
-
9c2944
     /* create an AES key needed for importing keys
9c2944
      * (encrypt by wrap_key and m_UnwrapKey by wrap key)
9c2944
      */
9c2944
@@ -2600,10 +2654,14 @@ CK_RV ep11tok_final(STDLL_TokData_t * tokdata)
9c2944
     TRACE_INFO("ep11 %s running\n", __func__);
9c2944
 
9c2944
     if (ep11_data != NULL) {
9c2944
-        if (dll_m_rm_module != NULL)
9c2944
-            dll_m_rm_module(NULL, ep11_data->target);
9c2944
+        if (ep11_data->target_info != NULL) {
9c2944
+            if (dll_m_rm_module != NULL)
9c2944
+                dll_m_rm_module(NULL, ep11_data->target_info->target);
9c2944
+            free_card_versions(ep11_data->target_info->card_versions);
9c2944
+            free((void* )ep11_data->target_info);
9c2944
+        }
9c2944
+        pthread_rwlock_destroy(&ep11_data->target_rwlock);
9c2944
         free_cp_config(ep11_data->cp_config);
9c2944
-        free_card_versions(ep11_data->card_versions);
9c2944
         free(ep11_data);
9c2944
         tokdata->private_data = NULL;
9c2944
     }
9c2944
@@ -2619,7 +2677,6 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION * sess,
9c2944
                              CK_BYTE *spki, CK_ULONG spki_len,
9c2944
                              CK_BYTE *maced_spki, CK_ULONG *maced_spki_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     unsigned char *ep11_pin_blob = NULL;
9c2944
     CK_ULONG ep11_pin_blob_len = 0;
9c2944
     ep11_session_t *ep11_session = (ep11_session_t *) sess->private_data;
9c2944
@@ -2712,11 +2769,11 @@ static CK_RV make_maced_spki(STDLL_TokData_t *tokdata, SESSION * sess,
9c2944
     ep11_get_pin_blob(ep11_session, object_is_session_object(pub_key_obj),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_UnwrapKey(spki, spki_len, NULL, 0, NULL, 0,
9c2944
                              ep11_pin_blob, ep11_pin_blob_len, &mech,
9c2944
                              p_attrs, attrs_len, maced_spki, maced_spki_len,
9c2944
-                             csum, &cslen, ep11_data->target);
9c2944
+                             csum, &cslen, target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -2870,11 +2927,11 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         }
9c2944
 
9c2944
         /* encrypt */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
9c2944
                                      ep11_data->raw2key_wrap_blob_l, &mech_w,
9c2944
                                      data, data_len, cipher, &cipher_l,
9c2944
-                                     ep11_data->target);
9c2944
+                                     target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
9c2944
@@ -2901,12 +2958,12 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         /* calls the card, it decrypts the private RSA key,
9c2944
          * reads its BER format and builds a blob.
9c2944
          */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_UnwrapKey(cipher, cipher_l, ep11_data->raw2key_wrap_blob,
9c2944
                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
9c2944
                                  ep11_pin_blob, ep11_pin_blob_len, &mech_w,
9c2944
                                  new_p_attrs, new_attrs_len, blob, blob_size,
9c2944
-                                 csum, &cslen, ep11_data->target);
9c2944
+                                 csum, &cslen, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         if (rc != CKR_OK) {
9c2944
@@ -3101,11 +3158,11 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         }
9c2944
 
9c2944
         /* encrypt */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
9c2944
                                      ep11_data->raw2key_wrap_blob_l,
9c2944
                                      &mech_w, data, data_len,
9c2944
-                                     cipher, &cipher_l, ep11_data->target);
9c2944
+                                     cipher, &cipher_l, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
9c2944
@@ -3133,14 +3190,14 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         /* calls the card, it decrypts the private EC key,
9c2944
          * reads its BER format and builds a blob.
9c2944
          */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_UnwrapKey(cipher, cipher_l,
9c2944
                                  ep11_data->raw2key_wrap_blob,
9c2944
                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
9c2944
                                  ep11_pin_blob,
9c2944
                                  ep11_pin_blob_len, &mech_w,
9c2944
                                  new_p_attrs, new_attrs_len, blob,
9c2944
-                                 blob_size, csum, &cslen, ep11_data->target);
9c2944
+                                 blob_size, csum, &cslen, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         if (rc != CKR_OK) {
9c2944
@@ -3295,11 +3352,11 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         }
9c2944
 
9c2944
         /* encrypt */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
9c2944
                                      ep11_data->raw2key_wrap_blob_l,
9c2944
                                      &mech_w, data, data_len,
9c2944
-                                     cipher, &cipher_l, ep11_data->target);
9c2944
+                                     cipher, &cipher_l, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
 
9c2944
@@ -3327,14 +3384,14 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         /* calls the card, it decrypts the private EC key,
9c2944
          * reads its BER format and builds a blob.
9c2944
          */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_UnwrapKey(cipher, cipher_l,
9c2944
                                  ep11_data->raw2key_wrap_blob,
9c2944
                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
9c2944
                                  ep11_pin_blob,
9c2944
                                  ep11_pin_blob_len, &mech_w,
9c2944
                                  new_p_attrs, new_attrs_len, blob,
9c2944
-                                 blob_size, csum, &cslen, ep11_data->target);
9c2944
+                                 blob_size, csum, &cslen, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         if (rc != CKR_OK) {
9c2944
@@ -3478,11 +3535,11 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         }
9c2944
 
9c2944
         /* encrypt */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
9c2944
                                      ep11_data->raw2key_wrap_blob_l,
9c2944
                                      &mech_w, data, data_len,
9c2944
-                                     cipher, &cipher_l, ep11_data->target);
9c2944
+                                     cipher, &cipher_l, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
9c2944
@@ -3509,14 +3566,14 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         /* calls the card, it decrypts the private EC key,
9c2944
          * reads its BER format and builds a blob.
9c2944
          */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_UnwrapKey(cipher, cipher_l,
9c2944
                                  ep11_data->raw2key_wrap_blob,
9c2944
                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
9c2944
                                  ep11_pin_blob,
9c2944
                                  ep11_pin_blob_len, &mech_w,
9c2944
                                  new_p_attrs, new_attrs_len, blob,
9c2944
-                                 blob_size, csum, &cslen, ep11_data->target);
9c2944
+                                 blob_size, csum, &cslen, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         if (rc != CKR_OK) {
9c2944
@@ -3666,11 +3723,11 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         }
9c2944
 
9c2944
         /* encrypt */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
9c2944
                                      ep11_data->raw2key_wrap_blob_l,
9c2944
                                      &mech_w, data, data_len,
9c2944
-                                     cipher, &cipher_l, ep11_data->target);
9c2944
+                                     cipher, &cipher_l, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
9c2944
@@ -3699,14 +3756,14 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
9c2944
         /* calls the card, it decrypts the private Dilithium key,
9c2944
          * reads its BER format and builds a blob.
9c2944
          */
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_UnwrapKey(cipher, cipher_l,
9c2944
                                  ep11_data->raw2key_wrap_blob,
9c2944
                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
9c2944
                                  ep11_pin_blob,
9c2944
                                  ep11_pin_blob_len, &mech_w,
9c2944
                                  new_p_attrs, new_attrs_len, blob,
9c2944
-                                 blob_size, csum, &cslen, ep11_data->target);
9c2944
+                                 blob_size, csum, &cslen, target_info->target);
9c2944
         RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
         if (rc != CKR_OK) {
9c2944
@@ -3884,7 +3941,6 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                            CK_MECHANISM_PTR mech, CK_ATTRIBUTE_PTR attrs,
9c2944
                            CK_ULONG attrs_len, CK_OBJECT_HANDLE_PTR handle)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_BYTE blob[MAX_BLOBSIZE];
9c2944
     size_t blobsize = sizeof(blob);
9c2944
     CK_BYTE csum[MAX_CSUMSIZE];
9c2944
@@ -3936,10 +3992,10 @@ CK_RV ep11tok_generate_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
     ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_GenerateKey(mech, new_attrs2, new_attrs2_len, ep11_pin_blob,
9c2944
                                ep11_pin_blob_len, blob, &blobsize,
9c2944
-                               csum, &csum_len, ep11_data->target);
9c2944
+                               csum, &csum_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4354,6 +4410,7 @@ CK_RV token_specific_sha_init(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
     size_t state_len = MAX(MAX_DIGEST_STATE_BYTES, sizeof(libica_sha_context_t));
9c2944
     CK_BYTE *state;
9c2944
     libica_sha_context_t *libica_ctx;
9c2944
+    ep11_target_info_t* target_info;
9c2944
 
9c2944
     state = calloc(state_len, 1); /* freed by dig_mgr.c */
9c2944
     if (!state) {
9c2944
@@ -4361,15 +4418,21 @@ CK_RV token_specific_sha_init(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
         return CKR_HOST_MEMORY;
9c2944
     }
9c2944
 
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
     if (ep11tok_libica_digest_available(ep11_data, mech->mechanism)) {
9c2944
         libica_ctx = (libica_sha_context_t *)state;
9c2944
         state_len = sizeof(libica_sha_context_t);
9c2944
         libica_ctx->first = CK_TRUE;
9c2944
         rc = get_sha_block_size(mech->mechanism, &libica_ctx->block_size);
9c2944
     } else {
9c2944
-        rc = dll_m_DigestInit(state, &state_len, mech, ep11_data->target);
9c2944
+        rc = dll_m_DigestInit(state, &state_len, mech, target_info->target);
9c2944
     }
9c2944
 
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
         TRACE_ERROR("%s rc=0x%lx\n", __func__, rc);
9c2944
@@ -4399,6 +4462,11 @@ CK_RV token_specific_sha(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
 {
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
     if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) {
9c2944
         rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism,
9c2944
@@ -4408,7 +4476,7 @@ CK_RV token_specific_sha(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
                                    SHA_MSG_PART_ONLY);
9c2944
     } else {
9c2944
         rc = dll_m_Digest(c->context, c->context_len, in_data, in_data_len,
9c2944
-                          out_data, out_data_len, ep11_data->target);
9c2944
+                          out_data, out_data_len, target_info->target);
9c2944
     }
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -4417,6 +4485,8 @@ CK_RV token_specific_sha(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
     } else {
9c2944
         TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
9c2944
     }
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
@@ -4430,6 +4500,11 @@ CK_RV token_specific_sha_update(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
     CK_ULONG out_len = sizeof(temp_out);
9c2944
     CK_ULONG len;
9c2944
     CK_RV rc = CKR_OK;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
     if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) {
9c2944
         if (libica_ctx->offset > 0 || in_data_len < libica_ctx->block_size) {
9c2944
@@ -4479,7 +4554,7 @@ CK_RV token_specific_sha_update(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
         }
9c2944
     } else {
9c2944
         rc = dll_m_DigestUpdate(c->context, c->context_len,
9c2944
-                                in_data, in_data_len, ep11_data->target);
9c2944
+                                in_data, in_data_len, target_info->target);
9c2944
     }
9c2944
 
9c2944
 out:
9c2944
@@ -4489,6 +4564,8 @@ out:
9c2944
     } else {
9c2944
         TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
9c2944
     }
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
@@ -4499,6 +4576,11 @@ CK_RV token_specific_sha_final(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     libica_sha_context_t *libica_ctx = (libica_sha_context_t *)c->context;
9c2944
     CK_RV rc;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
     if (ep11tok_libica_digest_available(ep11_data, c->mech.mechanism)) {
9c2944
         rc = ep11tok_libica_digest(ep11_data, c->mech.mechanism,
9c2944
@@ -4510,7 +4592,7 @@ CK_RV token_specific_sha_final(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
                                         SHA_MSG_PART_FINAL);
9c2944
     } else {
9c2944
         rc = dll_m_DigestFinal(c->context, c->context_len,
9c2944
-                               out_data, out_data_len, ep11_data->target);
9c2944
+                               out_data, out_data_len, target_info->target);
9c2944
     }
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -4520,6 +4602,7 @@ CK_RV token_specific_sha_final(STDLL_TokData_t * tokdata, DIGEST_CONTEXT * c,
9c2944
         TRACE_INFO("%s rc=0x%lx\n", __func__, rc);
9c2944
     }
9c2944
 
9c2944
+    put_target_info(tokdata, target_info);
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
@@ -4528,7 +4611,6 @@ CK_RV token_specific_rsa_sign(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
                               CK_BYTE *out_data, CK_ULONG *out_data_len,
9c2944
                               OBJECT *key_obj)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     size_t keyblobsize = 0;
9c2944
     CK_BYTE *keyblob;
9c2944
@@ -4544,9 +4626,9 @@ CK_RV token_specific_rsa_sign(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     mech.pParameter = NULL;
9c2944
     mech.ulParameterLen = 0;
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len,
9c2944
-                          out_data, out_data_len, ep11_data->target);
9c2944
+                          out_data, out_data_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4563,7 +4645,6 @@ CK_RV token_specific_rsa_verify(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
                                 CK_BYTE *signature, CK_ULONG sig_len,
9c2944
                                 OBJECT *key_obj)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *spki;
9c2944
     size_t spki_len = 0;
9c2944
@@ -4579,9 +4660,9 @@ CK_RV token_specific_rsa_verify(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     mech.pParameter = NULL;
9c2944
     mech.ulParameterLen = 0;
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len,
9c2944
-                            signature, sig_len, ep11_data->target);
9c2944
+                            signature, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4598,7 +4679,6 @@ CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
                                   CK_BYTE *in_data, CK_ULONG in_data_len,
9c2944
                                   CK_BYTE *sig, CK_ULONG *sig_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     size_t keyblobsize = 0;
9c2944
     CK_BYTE *keyblob;
9c2944
@@ -4616,9 +4696,9 @@ CK_RV token_specific_rsa_pss_sign(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     mech.ulParameterLen = ctx->mech.ulParameterLen;
9c2944
     mech.pParameter = ctx->mech.pParameter;
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len,
9c2944
-                          sig, sig_len, ep11_data->target);
9c2944
+                          sig, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4638,7 +4718,6 @@ CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
                                     CK_BYTE *in_data, CK_ULONG in_data_len,
9c2944
                                     CK_BYTE *signature, CK_ULONG sig_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *spki;
9c2944
     size_t spki_len = 0;
9c2944
@@ -4656,9 +4735,9 @@ CK_RV token_specific_rsa_pss_verify(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     mech.ulParameterLen = ctx->mech.ulParameterLen;
9c2944
     mech.pParameter = ctx->mech.pParameter;
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len,
9c2944
-                            signature, sig_len, ep11_data->target);
9c2944
+                            signature, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4678,7 +4757,6 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION  *session,
9c2944
                              CK_BYTE *out_data, CK_ULONG *out_data_len,
9c2944
                              OBJECT *key_obj )
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &(session->sign_ctx);
9c2944
     CK_RV rc;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -4707,9 +4785,9 @@ CK_RV token_specific_ec_sign(STDLL_TokData_t *tokdata, SESSION  *session,
9c2944
     mech.pParameter = NULL;
9c2944
     mech.ulParameterLen = 0;
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_SignSingle(keyblob, keyblobsize, &mech, in_data, in_data_len,
9c2944
-                          out_data, out_data_len, ep11_data->target);
9c2944
+                          out_data, out_data_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4728,7 +4806,6 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION  *session,
9c2944
                                CK_BYTE *out_data, CK_ULONG out_data_len,
9c2944
                                OBJECT *key_obj )
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &(session->verify_ctx);
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *spki;
9c2944
@@ -4757,9 +4834,9 @@ CK_RV token_specific_ec_verify(STDLL_TokData_t *tokdata, SESSION  *session,
9c2944
     mech.pParameter = NULL;
9c2944
     mech.ulParameterLen = 0;
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_VerifySingle(spki, spki_len, &mech, in_data, in_data_len,
9c2944
-                            out_data, out_data_len, ep11_data->target);
9c2944
+                            out_data, out_data_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4784,7 +4861,6 @@ CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata,
9c2944
                                       CK_BYTE *in_data, CK_ULONG in_data_len,
9c2944
                                       CK_BYTE *out_data, CK_ULONG *out_data_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *decr_key, *encr_key;
9c2944
     size_t decr_key_len = 0, encr_key_len = 0;
9c2944
@@ -4813,10 +4889,10 @@ CK_RV token_specific_reencrypt_single(STDLL_TokData_t *tokdata,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_ReencryptSingle(decr_key, decr_key_len, encr_key, encr_key_len,
9c2944
                                decr_mech, encr_mech, in_data, in_data_len,
9c2944
-                               out_data, out_data_len, ep11_data->target);
9c2944
+                               out_data, out_data_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -4892,7 +4968,6 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                          CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs,
9c2944
                          CK_ULONG attrs_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *keyblob;
9c2944
     size_t keyblobsize;
9c2944
@@ -4920,6 +4995,8 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
     CK_ULONG privlen;
9c2944
     int curve_type;
9c2944
     CK_BBOOL allocated = FALSE;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+    CK_ULONG used_firmware_API_version;
9c2944
 
9c2944
     memset(newblob, 0, sizeof(newblob));
9c2944
 
9c2944
@@ -5009,7 +5086,15 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
          * then we can pass the mechanism parameters as-is, otherwise we still
9c2944
          * need to use the old way.
9c2944
          */
9c2944
-        if (ep11_data->used_firmware_API_version <= 2) {
9c2944
+        target_info = get_target_info(tokdata);
9c2944
+        if (target_info == NULL)
9c2944
+            return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
+        used_firmware_API_version = target_info->used_firmware_API_version;
9c2944
+
9c2944
+        put_target_info(tokdata, target_info);
9c2944
+
9c2944
+        if (used_firmware_API_version <= 2) {
9c2944
             if (ecdh1_parms->kdf != CKD_NULL) {
9c2944
                 TRACE_ERROR("%s KDF for CKM_ECDH1_DERIVE not supported: %lu\n",
9c2944
                             __func__, ecdh1_parms->kdf);
9c2944
@@ -5133,11 +5218,11 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
     ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc =
9c2944
         dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len, keyblob, keyblobsize,
9c2944
                         NULL, 0, ep11_pin_blob, ep11_pin_blob_len, newblob,
9c2944
-                        &newblobsize, csum, &cslen, ep11_data->target);
9c2944
+                        &newblobsize, csum, &cslen, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -5231,7 +5316,6 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                  CK_ULONG ulPrivateKeyAttributeCount,
9c2944
                                  CK_SESSION_HANDLE h)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE publblob[MAX_BLOBSIZE];
9c2944
     size_t publblobsize = sizeof(publblob);
9c2944
@@ -5418,13 +5502,13 @@ static CK_RV dh_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                                  ulPrivateKeyAttributeCount)),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_GenerateKeyPair(pMechanism,
9c2944
                                    new_publ_attrs, new_publ_attrs_len,
9c2944
                                    new_priv_attrs, new_priv_attrs_len,
9c2944
                                    ep11_pin_blob, ep11_pin_blob_len,
9c2944
                                    privblob, &privblobsize,
9c2944
-                                   publblob, &publblobsize, ep11_data->target);
9c2944
+                                   publblob, &publblobsize, target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -5543,7 +5627,6 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                   CK_ULONG ulPrivateKeyAttributeCount,
9c2944
                                   CK_SESSION_HANDLE h)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE publblob[MAX_BLOBSIZE];
9c2944
     size_t publblobsize = sizeof(publblob);
9c2944
@@ -5752,13 +5835,13 @@ static CK_RV dsa_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                                  ulPrivateKeyAttributeCount)),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_GenerateKeyPair(pMechanism,
9c2944
                                    new_publ_attrs2, new_publ_attrs2_len,
9c2944
                                    new_priv_attrs2, new_priv_attrs2_len,
9c2944
                                    ep11_pin_blob, ep11_pin_blob_len, privblob,
9c2944
                                    &privblobsize, publblob, &publblobsize,
9c2944
-                                   ep11_data->target);
9c2944
+                                   target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -5866,7 +5949,6 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                      CK_ULONG ulPrivateKeyAttributeCount,
9c2944
                                      CK_SESSION_HANDLE h)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_ATTRIBUTE *attr = NULL;
9c2944
     CK_ATTRIBUTE *n_attr = NULL;
9c2944
@@ -5967,13 +6049,13 @@ static CK_RV rsa_ec_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                                  ulPrivateKeyAttributeCount)),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_GenerateKeyPair(pMechanism,
9c2944
                                    new_publ_attrs2, new_publ_attrs2_len,
9c2944
                                    new_priv_attrs2, new_priv_attrs2_len,
9c2944
                                    ep11_pin_blob, ep11_pin_blob_len,
9c2944
                                    privkey_blob, &privkey_blob_len, spki,
9c2944
-                                   &spki_len, ep11_data->target);
9c2944
+                                   &spki_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, sess);
9c2944
@@ -6225,7 +6307,6 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                      CK_ULONG ulPrivateKeyAttributeCount,
9c2944
                                      CK_SESSION_HANDLE h)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_ATTRIBUTE *attr = NULL;
9c2944
     CK_BYTE privkey_blob[MAX_BLOBSIZE];
9c2944
@@ -6308,13 +6389,13 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t * tokdata,
9c2944
                                                  ulPrivateKeyAttributeCount)),
9c2944
                       &ep11_pin_blob, &ep11_pin_blob_len);
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_GenerateKeyPair(pMechanism,
9c2944
                                    new_publ_attrs2, new_publ_attrs2_len,
9c2944
                                    new_priv_attrs2, new_priv_attrs2_len,
9c2944
                                    ep11_pin_blob, ep11_pin_blob_len,
9c2944
                                    privkey_blob, &privkey_blob_len, spki,
9c2944
-                                   &spki_len, ep11_data->target);
9c2944
+                                   &spki_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, sess)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, sess);
9c2944
@@ -6914,7 +6995,6 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                         CK_MECHANISM * mech, CK_BBOOL recover_mode,
9c2944
                         CK_OBJECT_HANDLE key)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     size_t keyblobsize = 0;
9c2944
     CK_BYTE *keyblob;
9c2944
@@ -6980,9 +7060,9 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         goto done;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_SignInit(ep11_sign_state, &ep11_sign_state_l,
9c2944
-                            mech, keyblob, keyblobsize, ep11_data->target);
9c2944
+                            mech, keyblob, keyblobsize, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7017,7 +7097,6 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                    CK_ULONG in_data_len, CK_BYTE * signature,
9c2944
                    CK_ULONG * sig_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -7049,9 +7128,9 @@ CK_RV ep11tok_sign(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         goto done; /* no ep11 fallback possible */
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_Sign(ctx->context, ctx->context_len, in_data, in_data_len,
9c2944
-                        signature, sig_len, ep11_data->target);
9c2944
+                        signature, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7073,7 +7152,6 @@ done:
9c2944
 CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                           CK_BYTE * in_data, CK_ULONG in_data_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -7095,9 +7173,9 @@ CK_RV ep11tok_sign_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_SignUpdate(ctx->context, ctx->context_len, in_data,
9c2944
-                              in_data_len, ep11_data->target);
9c2944
+                              in_data_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7120,7 +7198,6 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                          CK_BBOOL length_only, CK_BYTE * signature,
9c2944
                          CK_ULONG * sig_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &session->sign_ctx;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -7139,9 +7216,9 @@ CK_RV ep11tok_sign_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_SignFinal(ctx->context, ctx->context_len, signature, sig_len,
9c2944
-                             ep11_data->target);
9c2944
+                             target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7169,7 +7246,6 @@ CK_RV ep11tok_sign_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     size_t keyblobsize = 0;
9c2944
     CK_BYTE *keyblob;
9c2944
     OBJECT *key_obj = NULL;
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
 
9c2944
     UNUSED(length_only);
9c2944
 
9c2944
@@ -7186,9 +7262,9 @@ CK_RV ep11tok_sign_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
         goto done;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_SignSingle(keyblob, keyblobsize, mech, in_data, in_data_len,
9c2944
-                          signature, sig_len, ep11_data->target);
9c2944
+                          signature, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -7209,7 +7285,6 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                           CK_MECHANISM * mech, CK_BBOOL recover_mode,
9c2944
                           CK_OBJECT_HANDLE key)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *spki;
9c2944
     size_t spki_len = 0;
9c2944
@@ -7285,9 +7360,9 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         goto done;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_VerifyInit(ep11_sign_state, &ep11_sign_state_l, mech,
9c2944
-                              spki, spki_len, ep11_data->target);
9c2944
+                              spki, spki_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7320,7 +7395,6 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                      CK_BYTE * in_data, CK_ULONG in_data_len,
9c2944
                      CK_BYTE * signature, CK_ULONG sig_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -7353,9 +7427,9 @@ CK_RV ep11tok_verify(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         goto done; /* no ep11 fallback possible */
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_Verify(ctx->context, ctx->context_len, in_data, in_data_len,
9c2944
-                          signature, sig_len, ep11_data->target);
9c2944
+                          signature, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7377,7 +7451,6 @@ done:
9c2944
 CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                             CK_BYTE * in_data, CK_ULONG in_data_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -7399,9 +7472,9 @@ CK_RV ep11tok_verify_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_VerifyUpdate(ctx->context, ctx->context_len, in_data,
9c2944
-                                in_data_len, ep11_data->target);
9c2944
+                                in_data_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7423,7 +7496,6 @@ done:
9c2944
 CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                            CK_BYTE * signature, CK_ULONG sig_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     SIGN_VERIFY_CONTEXT *ctx = &session->verify_ctx;
9c2944
     size_t keyblobsize = 0;
9c2944
@@ -7442,9 +7514,9 @@ CK_RV ep11tok_verify_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_VerifyFinal(ctx->context, ctx->context_len, signature,
9c2944
-                               sig_len, ep11_data->target);
9c2944
+                               sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7471,7 +7543,6 @@ CK_RV ep11tok_verify_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     CK_BYTE *spki;
9c2944
     size_t spki_len = 0;
9c2944
     OBJECT *key_obj = NULL;
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
 
9c2944
     rc = h_opaque_2_blob(tokdata, key, &spki, &spki_len, &key_obj, READ_LOCK);
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7495,9 +7566,9 @@ CK_RV ep11tok_verify_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
         goto done;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_VerifySingle(spki, spki_len, mech, in_data, in_data_len,
9c2944
-                            signature, sig_len, ep11_data->target);
9c2944
+                            signature, sig_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -7517,7 +7588,6 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                             CK_BYTE_PTR output_part,
9c2944
                             CK_ULONG_PTR p_output_part_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
9c2944
     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
9c2944
@@ -7538,10 +7608,10 @@ CK_RV ep11tok_decrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_DecryptFinal(ctx->context, ctx->context_len,
9c2944
                                 output_part, p_output_part_len,
9c2944
-                                ep11_data->target);
9c2944
+                                target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7564,7 +7634,6 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                       CK_BYTE_PTR input_data, CK_ULONG input_data_len,
9c2944
                       CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
9c2944
     CK_BBOOL length_only = (output_data == NULL ? CK_TRUE : CK_FALSE);
9c2944
@@ -7586,10 +7655,10 @@ CK_RV ep11tok_decrypt(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_Decrypt(ctx->context, ctx->context_len, input_data,
9c2944
                            input_data_len, output_data, p_output_data_len,
9c2944
-                           ep11_data->target);
9c2944
+                           target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7613,7 +7682,6 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                              CK_BYTE_PTR output_part,
9c2944
                              CK_ULONG_PTR p_output_part_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
9c2944
     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
9c2944
@@ -7640,10 +7708,10 @@ CK_RV ep11tok_decrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_DecryptUpdate(ctx->context, ctx->context_len,
9c2944
                                  input_part, input_part_len, output_part,
9c2944
-                                 p_output_part_len, ep11_data->target);
9c2944
+                                 p_output_part_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7671,7 +7739,6 @@ CK_RV ep11tok_decrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     size_t keyblobsize = 0;
9c2944
     CK_BYTE *keyblob;
9c2944
     OBJECT *key_obj = NULL;
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
 
9c2944
     UNUSED(length_only);
9c2944
 
9c2944
@@ -7688,10 +7755,10 @@ CK_RV ep11tok_decrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
         goto done;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data,
9c2944
                              input_data_len, output_data, p_output_data_len,
9c2944
-                             ep11_data->target);
9c2944
+                             target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -7711,7 +7778,6 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                             CK_BYTE_PTR output_part,
9c2944
                             CK_ULONG_PTR p_output_part_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     ENCR_DECR_CONTEXT *ctx = &session->encr_ctx;
9c2944
     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
9c2944
@@ -7732,10 +7798,10 @@ CK_RV ep11tok_encrypt_final(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_EncryptFinal(ctx->context, ctx->context_len,
9c2944
                                 output_part, p_output_part_len,
9c2944
-                                ep11_data->target);
9c2944
+                                target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7758,7 +7824,6 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                       CK_BYTE_PTR input_data, CK_ULONG input_data_len,
9c2944
                       CK_BYTE_PTR output_data, CK_ULONG_PTR p_output_data_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     ENCR_DECR_CONTEXT *ctx = &session->encr_ctx;
9c2944
     CK_BBOOL length_only = (output_data == NULL ? CK_TRUE : CK_FALSE);
9c2944
@@ -7780,10 +7845,10 @@ CK_RV ep11tok_encrypt(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_Encrypt(ctx->context, ctx->context_len, input_data,
9c2944
                            input_data_len, output_data, p_output_data_len,
9c2944
-                           ep11_data->target);
9c2944
+                           target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7807,7 +7872,6 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                              CK_BYTE_PTR output_part,
9c2944
                              CK_ULONG_PTR p_output_part_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     ENCR_DECR_CONTEXT *ctx = &session->encr_ctx;
9c2944
     CK_BBOOL length_only = (output_part == NULL ? CK_TRUE : CK_FALSE);
9c2944
@@ -7834,10 +7898,10 @@ CK_RV ep11tok_encrypt_update(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_EncryptUpdate(ctx->context, ctx->context_len,
9c2944
                                  input_part, input_part_len, output_part,
9c2944
-                                 p_output_part_len, ep11_data->target);
9c2944
+                                 p_output_part_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -7865,7 +7929,6 @@ CK_RV ep11tok_encrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
     size_t keyblobsize = 0;
9c2944
     CK_BYTE *keyblob;
9c2944
     OBJECT *key_obj = NULL;
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
 
9c2944
     UNUSED(length_only);
9c2944
 
9c2944
@@ -7893,10 +7956,10 @@ CK_RV ep11tok_encrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
         goto done;
9c2944
     }
9c2944
 
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
     rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data,
9c2944
                              input_data_len, output_data, p_output_data_len,
9c2944
-                             ep11_data->target);
9c2944
+                             target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -7916,7 +7979,6 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                                   CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE key,
9c2944
                                   int op)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = CKR_OK;
9c2944
     CK_BYTE *blob;
9c2944
     size_t blob_len = 0;
9c2944
@@ -7979,9 +8041,9 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
 
9c2944
     if (op == DECRYPT) {
9c2944
         ENCR_DECR_CONTEXT *ctx = &session->decr_ctx;
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_DecryptInit(ep11_state, &ep11_state_l, mech, blob,
9c2944
-                                   blob_len, ep11_data->target);
9c2944
+                                   blob_len, target_info->target);
9c2944
         RETRY_END(rc, tokdata, session)
9c2944
         ctx->key = key;
9c2944
         ctx->active = TRUE;
9c2944
@@ -8012,9 +8074,9 @@ static CK_RV ep11_ende_crypt_init(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
             goto error;
9c2944
         }
9c2944
 
9c2944
-        RETRY_START
9c2944
+        RETRY_START(rc, tokdata)
9c2944
             rc = dll_m_EncryptInit(ep11_state, &ep11_state_l, mech, blob,
9c2944
-                                   blob_len, ep11_data->target);
9c2944
+                                   blob_len, target_info->target);
9c2944
         RETRY_END(rc, tokdata, session)
9c2944
         ctx->key = key;
9c2944
         ctx->active = TRUE;
9c2944
@@ -8092,7 +8154,6 @@ CK_RV ep11tok_wrap_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                        CK_OBJECT_HANDLE key, CK_BYTE_PTR wrapped_key,
9c2944
                        CK_ULONG_PTR p_wrapped_key_len)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *wrapping_blob;
9c2944
     size_t wrapping_blob_len;
9c2944
@@ -8192,11 +8253,11 @@ CK_RV ep11tok_wrap_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
      * (wrapping blob). The wrapped key can be processed by any PKCS11
9c2944
      * implementation.
9c2944
      */
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc =
9c2944
         dll_m_WrapKey(wrap_target_blob, wrap_target_blob_len, wrapping_blob,
9c2944
                       wrapping_blob_len, sign_blob, sign_blob_len, mech,
9c2944
-                      wrapped_key, p_wrapped_key_len, ep11_data->target);
9c2944
+                      wrapped_key, p_wrapped_key_len, target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -8228,7 +8289,6 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
                          CK_OBJECT_HANDLE wrapping_key,
9c2944
                          CK_OBJECT_HANDLE_PTR p_key)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     CK_BYTE *wrapping_blob, *temp;
9c2944
     size_t wrapping_blob_len;
9c2944
@@ -8388,13 +8448,13 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
9c2944
     /* we need a blob for the new key created by unwrapping,
9c2944
      * the wrapped key comes in BER
9c2944
      */
9c2944
-    RETRY_START
9c2944
+    RETRY_START(rc, tokdata)
9c2944
         rc = dll_m_UnwrapKey(wrapped_key, wrapped_key_len, wrapping_blob,
9c2944
                              wrapping_blob_len, verifyblob, verifyblobsize,
9c2944
                              ep11_pin_blob,
9c2944
                              ep11_pin_blob_len, mech, new_attrs2, new_attrs2_len,
9c2944
                              keyblob, &keyblobsize, csum, &cslen,
9c2944
-                             ep11_data->target);
9c2944
+                             target_info->target);
9c2944
     RETRY_END(rc, tokdata, session)
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -8657,21 +8717,25 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
9c2944
                                  CK_MECHANISM_TYPE_PTR pMechanismList,
9c2944
                                  CK_ULONG_PTR pulCount)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc = 0;
9c2944
     CK_ULONG counter = 0, size = 0;
9c2944
     CK_MECHANISM_TYPE_PTR mlist = NULL;
9c2944
     CK_ULONG i;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
     /* size querry */
9c2944
     if (pMechanismList == NULL) {
9c2944
         rc = dll_m_GetMechanismList(0, pMechanismList, pulCount,
9c2944
-                                    ep11_data->target);
9c2944
+                                    target_info->target);
9c2944
         if (rc != CKR_OK) {
9c2944
             rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
             TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #1\n",
9c2944
                         __func__, rc);
9c2944
-            return rc;
9c2944
+            goto out;
9c2944
         }
9c2944
 
9c2944
         /* adjust the size according to the ban list,
9c2944
@@ -8693,16 +8757,16 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
9c2944
                                     sizeof(CK_MECHANISM_TYPE) * counter);
9c2944
             if (!mlist) {
9c2944
                 TRACE_ERROR("%s Memory allocation failed\n", __func__);
9c2944
-                return CKR_HOST_MEMORY;
9c2944
+                rc = CKR_HOST_MEMORY;
9c2944
+                goto out;
9c2944
             }
9c2944
-            rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target);
9c2944
+            rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target);
9c2944
             if (rc != CKR_OK) {
9c2944
                 rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
                 TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #2\n",
9c2944
                             __func__, rc);
9c2944
-                free(mlist);
9c2944
                 if (rc != CKR_BUFFER_TOO_SMALL)
9c2944
-                    return rc;
9c2944
+                    goto out;
9c2944
             }
9c2944
         } while (rc == CKR_BUFFER_TOO_SMALL);
9c2944
 
9c2944
@@ -8722,12 +8786,12 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
9c2944
          * that comes as parameter, this is a 'reduced size',
9c2944
          * ep11 would complain about insufficient list size
9c2944
          */
9c2944
-        rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target);
9c2944
+        rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target);
9c2944
         if (rc != CKR_OK) {
9c2944
             rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
             TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #3\n",
9c2944
                         __func__, rc);
9c2944
-            return rc;
9c2944
+            goto out;
9c2944
         }
9c2944
 
9c2944
         /*
9c2944
@@ -8744,17 +8808,17 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
9c2944
                                     sizeof(CK_MECHANISM_TYPE) * counter);
9c2944
             if (!mlist) {
9c2944
                 TRACE_ERROR("%s Memory allocation failed\n", __func__);
9c2944
-                return CKR_HOST_MEMORY;
9c2944
+                rc = CKR_HOST_MEMORY;
9c2944
+                goto out;
9c2944
             }
9c2944
             /* all the card has */
9c2944
-            rc = dll_m_GetMechanismList(0, mlist, &counter, ep11_data->target);
9c2944
+            rc = dll_m_GetMechanismList(0, mlist, &counter, target_info->target);
9c2944
             if (rc != CKR_OK) {
9c2944
                 rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
                 TRACE_ERROR("%s bad rc=0x%lx from m_GetMechanismList() #4\n",
9c2944
                             __func__, rc);
9c2944
-                free(mlist);
9c2944
                 if (rc != CKR_BUFFER_TOO_SMALL)
9c2944
-                    return rc;
9c2944
+                    goto out;
9c2944
             }
9c2944
         } while (rc == CKR_BUFFER_TOO_SMALL);
9c2944
 
9c2944
@@ -8775,8 +8839,10 @@ CK_RV ep11tok_get_mechanism_list(STDLL_TokData_t * tokdata,
9c2944
             rc = CKR_BUFFER_TOO_SMALL;
9c2944
     }
9c2944
 
9c2944
+out:
9c2944
     if (mlist)
9c2944
         free(mlist);
9c2944
+    put_target_info(tokdata, target_info);
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
@@ -8790,6 +8856,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
     CK_BBOOL found = FALSE;
9c2944
     CK_ULONG i;
9c2944
     int status;
9c2944
+    CK_RV rc = CKR_OK;
9c2944
+    ep11_target_info_t* target_info;
9c2944
 
9c2944
     for (i = 0; i < supported_mech_list_len; i++) {
9c2944
         if (type == ep11_supported_mech_list[i]) {
9c2944
@@ -8804,13 +8872,18 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         return CKR_MECHANISM_INVALID;
9c2944
     }
9c2944
 
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
     if (check_cps_for_mechanism(ep11_data->cp_config,
9c2944
-                                type, ep11_data->control_points,
9c2944
-                                ep11_data->control_points_len,
9c2944
-                                ep11_data->max_control_point_index) != CKR_OK) {
9c2944
+                                type, target_info->control_points,
9c2944
+                                target_info->control_points_len,
9c2944
+                                target_info->max_control_point_index) != CKR_OK) {
9c2944
         TRACE_INFO("%s Mech '%s' banned due to control point\n",
9c2944
                                    __func__, ep11_get_ckm(type));
9c2944
-        return CKR_MECHANISM_INVALID;
9c2944
+        rc = CKR_MECHANISM_INVALID;
9c2944
+        goto out;
9c2944
     }
9c2944
 
9c2944
     switch(type) {
9c2944
@@ -8840,14 +8913,17 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         if (status == -1) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
9c2944
                         __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         break;
9c2944
 
9c2944
     case CKM_RSA_PKCS_OAEP:
9c2944
         /* CKM_RSA_PKCS_OAEP is not supported with EP11 host library <= 1.3 */
9c2944
-        if (compare_ck_version(&ep11_data->ep11_lib_version, &ver1_3) <= 0)
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+        if (compare_ck_version(&ep11_data->ep11_lib_version, &ver1_3) <= 0) {
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
+        }
9c2944
         break;
9c2944
 
9c2944
     case CKM_IBM_SHA3_224:
9c2944
@@ -8863,7 +8939,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         if (status != 1) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
9c2944
                                     __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         break;
9c2944
 
9c2944
@@ -8876,7 +8953,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         if (status != 1) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
9c2944
                                     __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         break;
9c2944
 
9c2944
@@ -8887,7 +8965,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) < 0) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to host library version\n",
9c2944
                                     __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
 
9c2944
         status = check_required_versions(tokdata, edwards_req_versions,
9c2944
@@ -8895,7 +8974,8 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         if (status != 1) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
9c2944
                                     __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         break;
9c2944
 
9c2944
@@ -8903,14 +8983,16 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
         if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) <= 0) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to host library version\n",
9c2944
                                      __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         status = check_required_versions(tokdata, ibm_dilithium_req_versions,
9c2944
                                          NUM_DILITHIUM_REQ);
9c2944
         if (status != 1) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
9c2944
                                     __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         break;
9c2944
 
9c2944
@@ -8919,19 +9001,23 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
9c2944
             TRACE_INFO("%s Mech '%s' banned due to host library version\n",
9c2944
                                      __func__, ep11_get_ckm(type));
9c2944
 
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         status = check_required_versions(tokdata, ibm_cpacf_wrap_req_versions,
9c2944
                                          NUM_CPACF_WRAP_REQ);
9c2944
         if (status != 1) {
9c2944
             TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
9c2944
                                     __func__, ep11_get_ckm(type));
9c2944
-            return CKR_MECHANISM_INVALID;
9c2944
+            rc = CKR_MECHANISM_INVALID;
9c2944
+            goto out;
9c2944
         }
9c2944
         break;
9c2944
     }
9c2944
 
9c2944
-    return CKR_OK;
9c2944
+out:
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+    return rc;
9c2944
 }
9c2944
 
9c2944
 CK_RV ep11tok_is_mechanism_supported_ex(STDLL_TokData_t *tokdata,
9c2944
@@ -8976,9 +9062,9 @@ CK_RV ep11tok_get_mechanism_info(STDLL_TokData_t * tokdata,
9c2944
                                  CK_MECHANISM_TYPE type,
9c2944
                                  CK_MECHANISM_INFO_PTR pInfo)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_RV rc;
9c2944
     int status;
9c2944
+    ep11_target_info_t* target_info;
9c2944
 
9c2944
     rc = ep11tok_is_mechanism_supported(tokdata, type);
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -8987,7 +9073,14 @@ CK_RV ep11tok_get_mechanism_info(STDLL_TokData_t * tokdata,
9c2944
         return rc;
9c2944
     }
9c2944
 
9c2944
-    rc = dll_m_GetMechanismInfo(0, type, pInfo, ep11_data->target);
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
+    rc = dll_m_GetMechanismInfo(0, type, pInfo, target_info->target);
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
         TRACE_ERROR("%s m_GetMechanismInfo(0x%lx) failed with rc=0x%lx\n",
9c2944
@@ -10265,6 +10358,11 @@ static CK_RV generate_ep11_session_id(STDLL_TokData_t * tokdata,
9c2944
     CK_MECHANISM mech;
9c2944
     CK_ULONG len;
9c2944
     libica_sha_context_t ctx;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
     session_id_data.handle = session->handle;
9c2944
     gettimeofday(&session_id_data.timeofday, NULL);
9c2944
@@ -10286,7 +10384,9 @@ static CK_RV generate_ep11_session_id(STDLL_TokData_t * tokdata,
9c2944
         rc = dll_m_DigestSingle(&mech, (CK_BYTE_PTR)&session_id_data,
9c2944
                                 sizeof(session_id_data),
9c2944
                                 ep11_session->session_id, &len,
9c2944
-                                ep11_data->target);
9c2944
+                                target_info->target);
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
 
9c2944
     if (rc != CKR_OK) {
9c2944
         rc = ep11_error_to_pkcs11_error(rc, session);
9c2944
@@ -10964,7 +11064,7 @@ static CK_RV get_card_type(uint_32 adapter, CK_ULONG *type)
9c2944
 
9c2944
 typedef struct query_version
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data;
9c2944
+    ep11_target_info_t *target_info;
9c2944
     CK_CHAR serialNumber[16];
9c2944
     CK_BBOOL first;
9c2944
     CK_BBOOL error;
9c2944
@@ -11005,7 +11105,7 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
9c2944
     }
9c2944
 
9c2944
     /* Try to find existing version info for this card type */
9c2944
-    card_version = qv->ep11_data->card_versions;
9c2944
+    card_version = qv->target_info->card_versions;
9c2944
     while (card_version != NULL) {
9c2944
         if (card_version->card_type == card_type)
9c2944
            break;
9c2944
@@ -11050,8 +11150,8 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
9c2944
         card_version->firmware_version = xcp_info.firmwareVersion;
9c2944
 #endif
9c2944
 
9c2944
-        card_version->next = qv->ep11_data->card_versions;
9c2944
-        qv->ep11_data->card_versions = card_version;
9c2944
+        card_version->next = qv->target_info->card_versions;
9c2944
+        qv->target_info->card_versions = card_version;
9c2944
     } else {
9c2944
         /*
9c2944
          * Version info for this card type is already available, so check this
9c2944
@@ -11134,23 +11234,16 @@ static CK_RV ep11tok_get_ep11_library_version(CK_VERSION *lib_version)
9c2944
     return CKR_OK;
9c2944
 }
9c2944
 
9c2944
-static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata)
9c2944
+static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata,
9c2944
+                                      ep11_target_info_t *target_info)
9c2944
 {
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     ep11_card_version_t *card_version;
9c2944
     query_version_t qv;
9c2944
     CK_RV rc;
9c2944
 
9c2944
-    rc = ep11tok_get_ep11_library_version(&ep11_data->ep11_lib_version);
9c2944
-    if (rc != CKR_OK)
9c2944
-        return rc;
9c2944
-
9c2944
-    TRACE_INFO("%s Host library version: %d.%d\n", __func__,
9c2944
-               ep11_data->ep11_lib_version.major,
9c2944
-               ep11_data->ep11_lib_version.minor);
9c2944
-
9c2944
     memset(&qv, 0, sizeof(qv));
9c2944
-    qv.ep11_data = ep11_data;
9c2944
+    qv.target_info = target_info;
9c2944
     qv.first = TRUE;
9c2944
 
9c2944
     rc = handle_all_ep11_cards(&ep11_data->target_list, version_query_handler,
9c2944
@@ -11169,18 +11262,18 @@ static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata)
9c2944
         return CKR_DEVICE_ERROR;
9c2944
     }
9c2944
 
9c2944
-    memcpy(ep11_data->serialNumber, qv.serialNumber,
9c2944
-           sizeof(ep11_data->serialNumber));
9c2944
+    memcpy(target_info->serialNumber, qv.serialNumber,
9c2944
+           sizeof(target_info->serialNumber));
9c2944
 
9c2944
-    TRACE_INFO("%s Serial number: %.16s\n", __func__, ep11_data->serialNumber);
9c2944
+    TRACE_INFO("%s Serial number: %.16s\n", __func__, target_info->serialNumber);
9c2944
 
9c2944
     /* EP11 host lib version <= 2 only support API version 2 */
9c2944
     if (ep11_data->ep11_lib_version.major <= 2)
9c2944
-        ep11_data->used_firmware_API_version = 2;
9c2944
+        target_info->used_firmware_API_version = 2;
9c2944
     else
9c2944
-        ep11_data->used_firmware_API_version = 0;
9c2944
+        target_info->used_firmware_API_version = 0;
9c2944
 
9c2944
-    card_version = ep11_data->card_versions;
9c2944
+    card_version = target_info->card_versions;
9c2944
     while (card_version != NULL) {
9c2944
         TRACE_INFO("%s Card type: CEX%luP\n", __func__,
9c2944
                    card_version->card_type);
9c2944
@@ -11190,19 +11283,19 @@ static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata)
9c2944
                 card_version->firmware_version.major,
9c2944
                 card_version->firmware_version.minor);
9c2944
 
9c2944
-        if (ep11_data->used_firmware_API_version == 0)
9c2944
-            ep11_data->used_firmware_API_version =
9c2944
+        if (target_info->used_firmware_API_version == 0)
9c2944
+            target_info->used_firmware_API_version =
9c2944
                                 card_version->firmware_API_version;
9c2944
         else
9c2944
-            ep11_data->used_firmware_API_version =
9c2944
-                                MIN(ep11_data->used_firmware_API_version,
9c2944
+            target_info->used_firmware_API_version =
9c2944
+                                MIN(target_info->used_firmware_API_version,
9c2944
                                     card_version->firmware_API_version);
9c2944
 
9c2944
         card_version = card_version->next;
9c2944
     }
9c2944
 
9c2944
     TRACE_INFO("%s Used Firmware API: %lu\n", __func__,
9c2944
-               ep11_data->used_firmware_API_version);
9c2944
+               target_info->used_firmware_API_version);
9c2944
 
9c2944
     return CKR_OK;
9c2944
 }
9c2944
@@ -11220,20 +11313,29 @@ static void free_card_versions(ep11_card_version_t *card_version)
9c2944
     }
9c2944
 }
9c2944
 
9c2944
-void ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
9c2944
+CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
9c2944
                                  CK_TOKEN_INFO_PTR pInfo)
9c2944
 {
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
 
9c2944
     /*
9c2944
      * report the EP11 firmware version as hardware version, and
9c2944
      * the EP11 host library version as firmware version
9c2944
      */
9c2944
-    if (ep11_data->card_versions != NULL)
9c2944
-        pInfo->hardwareVersion = ep11_data->card_versions->firmware_version;
9c2944
+    if (target_info->card_versions != NULL)
9c2944
+        pInfo->hardwareVersion = target_info->card_versions->firmware_version;
9c2944
     pInfo->firmwareVersion = ep11_data->ep11_lib_version;
9c2944
-    memcpy(pInfo->serialNumber, ep11_data->serialNumber,
9c2944
+    memcpy(pInfo->serialNumber, target_info->serialNumber,
9c2944
            sizeof(pInfo->serialNumber));
9c2944
+
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+
9c2944
+    return CKR_OK;
9c2944
 }
9c2944
 
9c2944
 /**
9c2944
@@ -11247,13 +11349,17 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
9c2944
                                    const version_req_t req[],
9c2944
                                    CK_ULONG num_req)
9c2944
 {
9c2944
-    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     CK_ULONG i, max_card_type = 0, min_card_type = 0xFFFFFFFF;
9c2944
     CK_BBOOL req_not_fullfilled = CK_FALSE;
9c2944
     CK_BBOOL req_fullfilled = CK_FALSE;
9c2944
     ep11_card_version_t *card_version;
9c2944
+    ep11_target_info_t* target_info;
9c2944
     int status;
9c2944
 
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return CKR_FUNCTION_FAILED;
9c2944
+
9c2944
     for (i = 0; i < num_req; i++) {
9c2944
         status = check_card_version(tokdata, req[i].card_type,
9c2944
                                            req[i].min_lib_version,
9c2944
@@ -11268,7 +11374,7 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
9c2944
     }
9c2944
 
9c2944
     /* Are card types < min_card_type present? */
9c2944
-    card_version = ep11_data->card_versions;
9c2944
+    card_version = target_info->card_versions;
9c2944
     while (card_version != NULL) {
9c2944
          if (card_version->card_type < min_card_type)
9c2944
              req_not_fullfilled = CK_TRUE;
9c2944
@@ -11276,7 +11382,7 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
9c2944
      }
9c2944
 
9c2944
     /* Are card types > max_card_type present? */
9c2944
-    card_version = ep11_data->card_versions;
9c2944
+    card_version = target_info->card_versions;
9c2944
     while (card_version != NULL) {
9c2944
         if (card_version->card_type > max_card_type) {
9c2944
             /*
9c2944
@@ -11285,9 +11391,10 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
9c2944
               * So all others must also meet the version requirements or be
9c2944
               * not present.
9c2944
               */
9c2944
+            status = 1;
9c2944
              if (req_not_fullfilled == CK_TRUE)
9c2944
-                 return -1;
9c2944
-             return 1;
9c2944
+                 status = -1;
9c2944
+             goto out;
9c2944
         }
9c2944
         card_version = card_version->next;
9c2944
     }
9c2944
@@ -11298,13 +11405,19 @@ static int check_required_versions(STDLL_TokData_t *tokdata,
9c2944
          * At least one don't meet the requirements, so all other must not
9c2944
          * fulfill the requirements, too, or are not present.
9c2944
          */
9c2944
+        status = 0;
9c2944
         if (req_fullfilled == CK_TRUE)
9c2944
-                return -1;
9c2944
-        return 0;
9c2944
+            status = -1;
9c2944
+        goto out;
9c2944
     } else {
9c2944
         /* All of the cards that are present fulfill the requirements */
9c2944
-        return 1;
9c2944
+        status = 1;
9c2944
+        goto out;
9c2944
     }
9c2944
+
9c2944
+out:
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+    return status;
9c2944
 }
9c2944
 
9c2944
 /**
9c2944
@@ -11320,6 +11433,8 @@ static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
9c2944
 {
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     ep11_card_version_t *card_version;
9c2944
+    ep11_target_info_t* target_info;
9c2944
+    int status = 1;
9c2944
 
9c2944
     TRACE_DEBUG("%s checking versions for CEX%luP cards.\n", __func__, card_type);
9c2944
 
9c2944
@@ -11331,21 +11446,28 @@ static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
9c2944
         }
9c2944
     }
9c2944
 
9c2944
-    card_version = ep11_data->card_versions;
9c2944
+    target_info = get_target_info(tokdata);
9c2944
+    if (target_info == NULL)
9c2944
+        return -1;
9c2944
+
9c2944
+    card_version = target_info->card_versions;
9c2944
     while (card_version != NULL) {
9c2944
         if (card_version->card_type == card_type)
9c2944
             break;
9c2944
         card_version = card_version->next;
9c2944
     }
9c2944
 
9c2944
-    if (card_version == NULL)
9c2944
-        return -1;
9c2944
+    if (card_version == NULL) {
9c2944
+        status = -1;
9c2944
+        goto out;
9c2944
+    }
9c2944
 
9c2944
     if (firmware_version != NULL) {
9c2944
         if (compare_ck_version(&card_version->firmware_version,
9c2944
                                firmware_version) < 0) {
9c2944
             TRACE_DEBUG("%s firmware_version is less than required\n", __func__);
9c2944
-            return 0;
9c2944
+            status = 0;
9c2944
+            goto out;
9c2944
         }
9c2944
     }
9c2944
 
9c2944
@@ -11353,53 +11475,57 @@ static int check_card_version(STDLL_TokData_t *tokdata, CK_ULONG card_type,
9c2944
         if (card_version->firmware_API_version < *firmware_API_version) {
9c2944
             TRACE_DEBUG("%s firmware_API_version is less than required\n",
9c2944
                        __func__);
9c2944
-            return 0;
9c2944
+            status = 0;
9c2944
+            goto out;
9c2944
         }
9c2944
     }
9c2944
 
9c2944
-    return 1;
9c2944
+ out:
9c2944
+    put_target_info(tokdata, target_info);
9c2944
+    return status;
9c2944
 }
9c2944
 
9c2944
-static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata)
9c2944
+static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata,
9c2944
+                                  ep11_target_info_t *target_info)
9c2944
 {
9c2944
     ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
     struct XCP_Module module;
9c2944
-    CK_RV rc;
9c2944
+    CK_RV rc = CKR_OK;
9c2944
     short i;
9c2944
 
9c2944
     if (dll_m_add_module == NULL) {
9c2944
         TRACE_WARNING("%s Function dll_m_add_module is not available, falling "
9c2944
                       "back to old target handling\n", __func__);
9c2944
 
9c2944
-        if (ep11_data->used_firmware_API_version > 2) {
9c2944
+        if (target_info->used_firmware_API_version > 2) {
9c2944
             TRACE_ERROR("%s selecting an API version is not possible with old "
9c2944
                         "target handling\n", __func__);
9c2944
             return CKR_FUNCTION_FAILED;
9c2944
         }
9c2944
 
9c2944
-        ep11_data->target = (target_t)&ep11_data->target_list;
9c2944
+        target_info->target = (target_t)&ep11_data->target_list;
9c2944
         return CKR_OK;
9c2944
     }
9c2944
 
9c2944
-    if (ep11_data->used_firmware_API_version > 2 &&
9c2944
+    if (target_info->used_firmware_API_version > 2 &&
9c2944
         ep11_data->ep11_lib_version.major < 3) {
9c2944
         TRACE_ERROR("%s selecting an API version is not possible with an EP11"
9c2944
                     " host library version < 3.0\n", __func__);
9c2944
         return CKR_FUNCTION_FAILED;
9c2944
     }
9c2944
 
9c2944
-    ep11_data->target = XCP_TGT_INIT;
9c2944
+    target_info->target = XCP_TGT_INIT;
9c2944
     memset(&module, 0, sizeof(module));
9c2944
     module.version = ep11_data->ep11_lib_version.major >= 3 ? XCP_MOD_VERSION_2
9c2944
                                                             : XCP_MOD_VERSION_1;
9c2944
     module.flags = XCP_MFL_VIRTUAL | XCP_MFL_MODULE;
9c2944
-    module.api = ep11_data->used_firmware_API_version;
9c2944
+    module.api = target_info->used_firmware_API_version;
9c2944
 
9c2944
     TRACE_DEVEL("%s XCP_MOD_VERSION: %u\n", __func__, module.version);
9c2944
 
9c2944
     if (ep11_data->target_list.length == 0) {
9c2944
         /* APQN_ANY: Create an empty module group */
9c2944
-        rc = dll_m_add_module(&module, &ep11_data->target);
9c2944
+        rc = dll_m_add_module(&module, &target_info->target);
9c2944
         if (rc != CKR_OK) {
9c2944
             TRACE_ERROR("%s dll_m_add_module (ANY) failed: rc=%ld\n",
9c2944
                         __func__, rc);
9c2944
@@ -11414,11 +11540,12 @@ static CK_RV ep11tok_setup_target(STDLL_TokData_t *tokdata)
9c2944
         XCPTGTMASK_SET_DOM(module.domainmask,
9c2944
                            ep11_data->target_list.apqns[2 * i + 1]);
9c2944
 
9c2944
-        rc = dll_m_add_module(&module, &ep11_data->target);
9c2944
+        rc = dll_m_add_module(&module, &target_info->target);
9c2944
         if (rc != CKR_OK) {
9c2944
             TRACE_ERROR("%s dll_m_add_module (%02x.%04x) failed: rc=%ld\n",
9c2944
                     __func__, ep11_data->target_list.apqns[2 * i],
9c2944
                     ep11_data->target_list.apqns[2 * i + 1], rc);
9c2944
+            dll_m_rm_module(NULL, target_info->target);
9c2944
             return CKR_FUNCTION_FAILED;
9c2944
         }
9c2944
     }
9c2944
@@ -11494,6 +11621,7 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata, OBJECT *obj,
9c2944
     CK_ULONG num_attributes = 0;
9c2944
     CK_ATTRIBUTE *attr;
9c2944
     CK_RV rc;
9c2944
+    ep11_target_info_t* target_info;
9c2944
 
9c2944
     rc = template_attribute_get_ulong(obj->template, CKA_CLASS, &class);
9c2944
     if (rc != CKR_OK) {
9c2944
@@ -11575,9 +11703,18 @@ CK_RV token_specific_set_attribute_values(STDLL_TokData_t *tokdata, OBJECT *obj,
9c2944
             goto out;
9c2944
         }
9c2944
 
9c2944
+        target_info = get_target_info(tokdata);
9c2944
+        if (target_info == NULL) {
9c2944
+            rc = CKR_FUNCTION_FAILED;
9c2944
+            goto out;
9c2944
+        }
9c2944
+
9c2944
         rc = dll_m_SetAttributeValue(ibm_opaque_attr->pValue,
9c2944
                                      ibm_opaque_attr->ulValueLen, attributes,
9c2944
-                                     num_attributes, ep11_data->target);
9c2944
+                                     num_attributes, target_info->target);
9c2944
+
9c2944
+        put_target_info(tokdata, target_info);
9c2944
+
9c2944
         if (rc != CKR_OK) {
9c2944
             rc = ep11_error_to_pkcs11_error(rc, NULL);
9c2944
             TRACE_ERROR("%s m_SetAttributeValue failed rc=0x%lx\n",
9c2944
@@ -11601,3 +11738,233 @@ out:
9c2944
     return rc;
9c2944
 }
9c2944
 
9c2944
+/*
9c2944
+ * ATTENTION: This function is called in a separate thread. All actions
9c2944
+ * performed by this function must be thread save and use locks to lock
9c2944
+ * against concurrent access by other threads.
9c2944
+ */
9c2944
+static CK_RV ep11tok_handle_apqn_event(STDLL_TokData_t *tokdata,
9c2944
+                                       unsigned int event_type,
9c2944
+                                       event_udev_apqn_data_t *apqn_data)
9c2944
+{
9c2944
+    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    CK_BBOOL found = FALSE;
9c2944
+    CK_RV rc = CKR_OK;
9c2944
+    char name[20];
9c2944
+    int i;
9c2944
+
9c2944
+    /* Is it one of the configured APQNs ?*/
9c2944
+    if (ep11_data->target_list.length > 0) {
9c2944
+        /* APQN_WHITELIST is specified */
9c2944
+        for (i = 0; i < ep11_data->target_list.length; i++) {
9c2944
+            if (ep11_data->target_list.apqns[2 * i] == apqn_data->card &&
9c2944
+                ep11_data->target_list.apqns[2 * i + 1] == apqn_data->domain) {
9c2944
+                found = TRUE;
9c2944
+                break;
9c2944
+            }
9c2944
+        }
9c2944
+    } else {
9c2944
+        /* APQN_ANY is specified */
9c2944
+        found = TRUE;
9c2944
+        if (event_type == EVENT_TYPE_APQN_ADD) {
9c2944
+            snprintf(name, sizeof(name), "card%02x", apqn_data->card);
9c2944
+            if (is_card_ep11_and_online(name) != CKR_OK)
9c2944
+                found = FALSE; /* Not an EP11 APQN */
9c2944
+        }
9c2944
+    }
9c2944
+    if (!found)
9c2944
+        return CKR_OK;
9c2944
+
9c2944
+    TRACE_DEVEL("%s Refreshing target infos due to event for APQN %02x.%04x\n",
9c2944
+                __func__, apqn_data->card, apqn_data->domain);
9c2944
+
9c2944
+    rc = refresh_target_info(tokdata);
9c2944
+    if (rc != CKR_OK) {
9c2944
+        TRACE_ERROR("%s Failed to get the target infos (refresh_target_info "
9c2944
+                    "rc=0x%lx)\n", __func__, rc);
9c2944
+        OCK_SYSLOG(LOG_ERR, "%s: Failed to get the target info rc=0x%lx\n",
9c2944
+                   __func__, rc);
9c2944
+        return rc;
9c2944
+    }
9c2944
+
9c2944
+    return CKR_OK;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Called by the event thread, on receipt of an event.
9c2944
+ *
9c2944
+ * ATTENTION: This function is called in a separate thread. All actions
9c2944
+ * performed by this function must be thread save and use locks to lock
9c2944
+ * against concurrent access by other threads.
9c2944
+ */
9c2944
+CK_RV token_specific_handle_event(STDLL_TokData_t *tokdata,
9c2944
+                                  unsigned int event_type,
9c2944
+                                  unsigned int event_flags,
9c2944
+                                  const char *payload,
9c2944
+                                  unsigned int payload_len)
9c2944
+{
9c2944
+    UNUSED(event_flags);
9c2944
+
9c2944
+    switch (event_type) {
9c2944
+    case EVENT_TYPE_APQN_ADD:
9c2944
+    case EVENT_TYPE_APQN_REMOVE:
9c2944
+        if (payload_len != sizeof(event_udev_apqn_data_t))
9c2944
+            return CKR_FUNCTION_FAILED;
9c2944
+        return ep11tok_handle_apqn_event(tokdata, event_type,
9c2944
+                                         (event_udev_apqn_data_t *)payload);
9c2944
+
9c2944
+    default:
9c2944
+        return CKR_FUNCTION_NOT_SUPPORTED;
9c2944
+    }
9c2944
+
9c2944
+    return CKR_OK;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Refreshes the target info using the currently configured and available
9c2944
+ * APQNs. Registers the newly allocated target info as the current one in a
9c2944
+ * thread save way and gives back the previous one so that it is release when
9c2944
+ * no longer used (i.e. by a concurrently running thread).
9c2944
+ */
9c2944
+static CK_RV refresh_target_info(STDLL_TokData_t *tokdata)
9c2944
+{
9c2944
+    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    volatile ep11_target_info_t *prev_info;
9c2944
+    ep11_target_info_t *target_info;
9c2944
+    CK_RV rc;
9c2944
+
9c2944
+    target_info = calloc(1, sizeof(ep11_target_info_t));
9c2944
+    if (target_info == NULL) {
9c2944
+        TRACE_ERROR("%s Memory allocation failed\n", __func__);
9c2944
+        return CKR_HOST_MEMORY;
9c2944
+    }
9c2944
+
9c2944
+    target_info->ref_count = 1;
9c2944
+
9c2944
+    /* Get the version info freshly with the current set of APQNs */
9c2944
+    rc = ep11tok_get_ep11_version(tokdata, target_info);
9c2944
+    if (rc != 0)
9c2944
+        goto error;
9c2944
+
9c2944
+    /* Get the control points freshly with the current set of APQNs */
9c2944
+    target_info->control_points_len = sizeof(target_info->control_points);
9c2944
+    rc = get_control_points(tokdata, target_info->control_points,
9c2944
+                            &target_info->control_points_len,
9c2944
+                            &target_info->max_control_point_index);
9c2944
+    if (rc != 0)
9c2944
+        goto error;
9c2944
+
9c2944
+    /* Setup the group target freshly with the current set of APQNs */
9c2944
+    rc = ep11tok_setup_target(tokdata, target_info);
9c2944
+    if (rc != CKR_OK)
9c2944
+        goto error;
9c2944
+
9c2944
+    /* Set the new one as the current one (locked against concurrent get's) */
9c2944
+    if (pthread_rwlock_wrlock(&ep11_data->target_rwlock) != 0) {
9c2944
+        TRACE_DEVEL("Target Write-Lock failed.\n");
9c2944
+        rc = CKR_CANT_LOCK;
9c2944
+        goto error;
9c2944
+    }
9c2944
+
9c2944
+    prev_info = ep11_data->target_info;
9c2944
+    ep11_data->target_info = target_info;
9c2944
+
9c2944
+    if (pthread_rwlock_unlock(&ep11_data->target_rwlock) != 0) {
9c2944
+        TRACE_DEVEL("Target Unlock failed.\n");
9c2944
+        return CKR_CANT_LOCK;
9c2944
+    }
9c2944
+
9c2944
+    /* Release the previous one */
9c2944
+    if (prev_info != NULL)
9c2944
+        put_target_info(tokdata, (ep11_target_info_t *)prev_info);
9c2944
+
9c2944
+    return CKR_OK;
9c2944
+
9c2944
+error:
9c2944
+    free_card_versions(target_info->card_versions);
9c2944
+    free((void *)target_info);
9c2944
+    return rc;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Get the current EP11 target info.
9c2944
+ * Do NOT use the ep11_data->target_info directly, always get a copy using
9c2944
+ * this function. This will increment the reference count of the target info,
9c2944
+ * and return the current target info in a thread save way.
9c2944
+ * When no longer needed, put it back using put_target_info().
9c2944
+ */
9c2944
+static ep11_target_info_t *get_target_info(STDLL_TokData_t *tokdata)
9c2944
+{
9c2944
+    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    volatile ep11_target_info_t *target_info;
9c2944
+#ifdef DEBUG
9c2944
+    unsigned long ref_count;
9c2944
+#endif
9c2944
+
9c2944
+    /*
9c2944
+     * Lock until we have obtained the current target info and have
9c2944
+     * increased the reference counter
9c2944
+     */
9c2944
+    if (pthread_rwlock_rdlock(&ep11_data->target_rwlock) != 0) {
9c2944
+        TRACE_DEVEL("Target Read-Lock failed.\n");
9c2944
+        return NULL;
9c2944
+    }
9c2944
+
9c2944
+    target_info = *((void * volatile *)&ep11_data->target_info);
9c2944
+    if (target_info == NULL) {
9c2944
+        TRACE_ERROR("%s: target_info is NULL\n", __func__);
9c2944
+        return NULL;
9c2944
+    }
9c2944
+
9c2944
+#ifdef DEBUG
9c2944
+    ref_count = __sync_add_and_fetch(&target_info->ref_count, 1);
9c2944
+
9c2944
+    TRACE_DEBUG("%s: target_info: %p ref_count: %lu\n", __func__,
9c2944
+                (void *)target_info, ref_count);
9c2944
+#else
9c2944
+    __sync_add_and_fetch(&target_info->ref_count, 1);
9c2944
+#endif
9c2944
+
9c2944
+    if (pthread_rwlock_unlock(&ep11_data->target_rwlock) != 0) {
9c2944
+        TRACE_DEVEL("Target Unlock failed.\n");
9c2944
+        return NULL;
9c2944
+    }
9c2944
+
9c2944
+    return (ep11_target_info_t *)target_info;
9c2944
+}
9c2944
+
9c2944
+/*
9c2944
+ * Give back an EP11 target info. This will decrement the reference count,
9c2944
+ * and will free it if the reference count reaches zero.
9c2944
+ */
9c2944
+static void put_target_info(STDLL_TokData_t *tokdata,
9c2944
+                            ep11_target_info_t *target_info)
9c2944
+{
9c2944
+    ep11_private_data_t *ep11_data = tokdata->private_data;
9c2944
+    unsigned long ref_count;
9c2944
+
9c2944
+    if (target_info == NULL)
9c2944
+        return;
9c2944
+
9c2944
+    if (target_info->ref_count > 0) {
9c2944
+        ref_count = __sync_sub_and_fetch(&target_info->ref_count, 1);
9c2944
+
9c2944
+        TRACE_DEBUG("%s: target_info: %p ref_count: %lu\n", __func__,
9c2944
+                    (void *)target_info, ref_count);
9c2944
+    } else {
9c2944
+        TRACE_WARNING("%s: target_info: %p ref_count already 0.\n", __func__,
9c2944
+                      (void *)target_info);
9c2944
+        ref_count = 0;
9c2944
+    }
9c2944
+
9c2944
+    if (ref_count == 0 && target_info != ep11_data->target_info) {
9c2944
+        TRACE_DEBUG("%s: target_info: %p is freed\n", __func__,
9c2944
+                    (void *)target_info);
9c2944
+
9c2944
+        if (dll_m_rm_module != NULL)
9c2944
+            dll_m_rm_module(NULL, target_info->target);
9c2944
+        free_card_versions(target_info->card_versions);
9c2944
+        free(target_info);
9c2944
+    }
9c2944
+}
9c2944
+
9c2944
diff --git a/usr/lib/ep11_stdll/ep11_specific.h b/usr/lib/ep11_stdll/ep11_specific.h
9c2944
index 55fc023c..343f4b3d 100644
9c2944
--- a/usr/lib/ep11_stdll/ep11_specific.h
9c2944
+++ b/usr/lib/ep11_stdll/ep11_specific.h
9c2944
@@ -161,7 +161,7 @@ CK_BBOOL ep11tok_libica_mech_available(STDLL_TokData_t *tokdata,
9c2944
                                        CK_MECHANISM_TYPE mech,
9c2944
                                        CK_OBJECT_HANDLE hKey);
9c2944
 
9c2944
-void ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
9c2944
+CK_RV ep11tok_copy_firmware_info(STDLL_TokData_t *tokdata,
9c2944
                                  CK_TOKEN_INFO_PTR pInfo);
9c2944
 
9c2944
 CK_BBOOL ep11tok_pkey_usage_ok(STDLL_TokData_t *tokdata, SESSION *session,
9c2944
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
9c2944
index 4e592363..cd12604e 100644
9c2944
--- a/usr/lib/ep11_stdll/new_host.c
9c2944
+++ b/usr/lib/ep11_stdll/new_host.c
9c2944
@@ -298,7 +298,7 @@ CK_RV SC_GetTokenInfo(STDLL_TokData_t *tokdata, CK_SLOT_ID sid,
9c2944
         goto done;
9c2944
     }
9c2944
     copy_token_contents_sensibly(pInfo, tokdata->nv_token_data);
9c2944
-    ep11tok_copy_firmware_info(tokdata, pInfo);
9c2944
+    rc = ep11tok_copy_firmware_info(tokdata, pInfo);
9c2944
 
9c2944
     /* Set the time */
9c2944
     now = time((time_t *) NULL);
9c2944
diff --git a/usr/lib/ep11_stdll/tok_struct.h b/usr/lib/ep11_stdll/tok_struct.h
9c2944
index 2c0af9cf..01268c67 100644
9c2944
--- a/usr/lib/ep11_stdll/tok_struct.h
9c2944
+++ b/usr/lib/ep11_stdll/tok_struct.h
9c2944
@@ -137,7 +137,7 @@ token_spec_t token_specific = {
9c2944
     &token_specific_reencrypt_single,
9c2944
     &token_specific_set_attribute_values,
9c2944
     &token_specific_set_attrs_for_new_object,
9c2944
-    NULL,                       // handle_event
9c2944
+    &token_specific_handle_event,
9c2944
 };
9c2944
 
9c2944
 #endif