Blame SOURCES/opencryptoki-3.16.0-b048be548508dd1958bb7271568f388d0f6cbcf8.patch

8520e9
commit b048be548508dd1958bb7271568f388d0f6cbcf8
8520e9
Author: Ingo Franzki <ifranzki@linux.ibm.com>
8520e9
Date:   Mon Feb 8 16:50:00 2021 +0100
8520e9
8520e9
    Event support: API and token level changes
8520e9
    
8520e9
    Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
8520e9
8520e9
diff --git a/usr/include/apictl.h b/usr/include/apictl.h
8520e9
index 8898cae3..81c65dad 100644
8520e9
--- a/usr/include/apictl.h
8520e9
+++ b/usr/include/apictl.h
8520e9
@@ -57,6 +57,8 @@ typedef struct {
8520e9
     API_Slot_t SltList[NUMBER_SLOTS_MANAGED];
8520e9
     DLL_Load_t DLLs[NUMBER_SLOTS_MANAGED];  // worst case we have a separate DLL
8520e9
                                             // per slot
8520e9
+    int socketfd;
8520e9
+    pthread_t event_thread;
8520e9
 } API_Proc_Struct_t;
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/include/events.h b/usr/include/events.h
8520e9
new file mode 100644
8520e9
index 00000000..dac6ad52
8520e9
--- /dev/null
8520e9
+++ b/usr/include/events.h
8520e9
@@ -0,0 +1,83 @@
8520e9
+/*
8520e9
+ * COPYRIGHT (c) International Business Machines Corp. 2021
8520e9
+ *
8520e9
+ * This program is provided under the terms of the Common Public License,
8520e9
+ * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
8520e9
+ * software constitutes recipient's acceptance of CPL-1.0 terms which can be
8520e9
+ * found in the file LICENSE file or at
8520e9
+ * https://opensource.org/licenses/cpl1.0.php
8520e9
+ */
8520e9
+
8520e9
+#include <stdint.h>
8520e9
+#include <pkcs11types.h>
8520e9
+#include <limits.h>
8520e9
+#include <stdio.h>
8520e9
+
8520e9
+#include "local_types.h"
8520e9
+#include "pkcs32.h"
8520e9
+
8520e9
+#ifndef _EVENTS_H
8520e9
+#define _EVENTS_H
8520e9
+
8520e9
+typedef struct {
8520e9
+    unsigned int version;       /* EVENT_VERSION_xxx */
8520e9
+    unsigned int type;          /* EVENT_TYPE_xxx */
8520e9
+    unsigned int flags;         /* EVENT_FLAGS_xxx */
8520e9
+    unsigned int token_type;    /* Destination token type: EVENT_TOK_TYPE_xxx */
8520e9
+    char token_label[member_size(CK_TOKEN_INFO_32, label)];
8520e9
+                                /* Label of destination token (or blanks) */
8520e9
+    pid_t process_id;           /* Process ID of destination process (or 0) */
8520e9
+    unsigned int payload_len;   /* Length of payload in bytes */
8520e9
+    /* Followed by payload_len bytes of payload (event specific) */
8520e9
+} __attribute__ ((__packed__)) event_msg_t;
8520e9
+
8520e9
+typedef struct {
8520e9
+    unsigned int version;               /* EVENT_VERSION_xxx */
8520e9
+    unsigned int positive_replies;      /* Number of tokens that replied a */
8520e9
+    unsigned int negative_replies;      /* positive, or negative feedback, */
8520e9
+    unsigned int nothandled_replies;    /* or that did not handle the event. */
8520e9
+                                        /* Note: Only tokens matching the event
8520e9
+                                         * destination fields (pid, label,
8520e9
+                                         * token-type) are counted. */
8520e9
+} __attribute__ ((__packed__)) event_reply_t;
8520e9
+
8520e9
+/* Event and reply versions */
8520e9
+#define EVENT_VERSION_1         1
8520e9
+
8520e9
+/* Event classes (encoded into event type) */
8520e9
+#define EVENT_CLASS_MASK        0xffff0000
8520e9
+#define EVENT_CLASS_UDEV        0x00010000
8520e9
+#define EVENT_CLASS_ADMIN       0x00020000
8520e9
+
8520e9
+/* Event types */
8520e9
+#define EVENT_TYPE_APQN_ADD     EVENT_CLASS_UDEV + 0x00000001
8520e9
+#define EVENT_TYPE_APQN_REMOVE  EVENT_CLASS_UDEV + 0x00000002
8520e9
+
8520e9
+/* Event flags */
8520e9
+#define EVENT_FLAGS_NONE        0x00000000
8520e9
+#define EVENT_FLAGS_REPLY_REQ   0x00000001
8520e9
+
8520e9
+/* Event token destination types */
8520e9
+#define EVENT_TOK_TYPE_ALL      0x00000000
8520e9
+#define EVENT_TOK_TYPE_CCA      0x00000001
8520e9
+#define EVENT_TOK_TYPE_EP11     0x00000002
8520e9
+
8520e9
+/* Maximum event payload length 128k */
8520e9
+#define EVENT_MAX_PAYLOAD_LENGTH    (128 * 1024)
8520e9
+
8520e9
+/* Event payload for EVENT_TYPE_APQN_ADD and EVENT_TYPE_APQN_REMOVE */
8520e9
+typedef struct {
8520e9
+    unsigned short card;
8520e9
+    unsigned short domain;
8520e9
+    unsigned int device_type;            /* from uevent DEV_TYPE property */
8520e9
+} __attribute__ ((__packed__)) event_udev_apqn_data_t;
8520e9
+
8520e9
+/* AP device types */
8520e9
+#define AP_DEVICE_TYPE_CEX3A        8
8520e9
+#define AP_DEVICE_TYPE_CEX3C        9
8520e9
+#define AP_DEVICE_TYPE_CEX4         10
8520e9
+#define AP_DEVICE_TYPE_CEX5         11
8520e9
+#define AP_DEVICE_TYPE_CEX6         12
8520e9
+#define AP_DEVICE_TYPE_CEX7         13
8520e9
+
8520e9
+#endif
8520e9
diff --git a/usr/include/include.mk b/usr/include/include.mk
8520e9
index a36afb25..79e593d7 100644
8520e9
--- a/usr/include/include.mk
8520e9
+++ b/usr/include/include.mk
8520e9
@@ -7,4 +7,5 @@ opencryptokiinclude_HEADERS =						\
8520e9
 
8520e9
 noinst_HEADERS +=							\
8520e9
 	usr/include/apictl.h usr/include/local_types.h			\
8520e9
-	usr/include/pkcs32.h usr/include/slotmgr.h usr/include/stdll.h
8520e9
+	usr/include/pkcs32.h usr/include/slotmgr.h usr/include/stdll.h	\
8520e9
+	usr/include/events.h
8520e9
diff --git a/usr/include/local_types.h b/usr/include/local_types.h
8520e9
index f03c6629..c7c7f5ec 100644
8520e9
--- a/usr/include/local_types.h
8520e9
+++ b/usr/include/local_types.h
8520e9
@@ -11,6 +11,8 @@
8520e9
 #ifndef __LOCAL_TYPES
8520e9
 #define __LOCAL_TYPES
8520e9
 
8520e9
+#define member_size(type, member) sizeof(((type *)0)->member)
8520e9
+
8520e9
 typedef unsigned char uint8;
8520e9
 
8520e9
 typedef unsigned short uint16;
8520e9
diff --git a/usr/include/stdll.h b/usr/include/stdll.h
8520e9
index 57f6c6e8..9a3b760c 100644
8520e9
--- a/usr/include/stdll.h
8520e9
+++ b/usr/include/stdll.h
8520e9
@@ -350,6 +350,11 @@ typedef CK_RV (CK_PTR ST_C_IBM_ReencryptSingle)(STDLL_TokData_t *tokdata,
8520e9
                                                 CK_BYTE_PTR pReencryptedData,
8520e9
                                             CK_ULONG_PTR pulReencryptedDataLen);
8520e9
 
8520e9
+typedef CK_RV (CK_PTR ST_C_HandleEvent)(STDLL_TokData_t *tokdata,
8520e9
+                                        unsigned int event_type,
8520e9
+                                        unsigned int event_flags,
8520e9
+                                        const char *payload,
8520e9
+                                        unsigned int payload_len);
8520e9
 
8520e9
 struct ST_FCN_LIST {
8520e9
 
8520e9
@@ -424,6 +429,9 @@ struct ST_FCN_LIST {
8520e9
     ST_C_CancelFunction ST_CancelFunction;
8520e9
 
8520e9
     ST_C_IBM_ReencryptSingle ST_IBM_ReencryptSingle;
8520e9
+
8520e9
+    /* The functions defined below are not part of the external API */
8520e9
+    ST_C_HandleEvent ST_HandleEvent;
8520e9
 };
8520e9
 
8520e9
 typedef struct ST_FCN_LIST STDLL_FcnList_t;
8520e9
diff --git a/usr/lib/api/api_interface.c b/usr/lib/api/api_interface.c
8520e9
index f1ee9132..b74b763f 100644
8520e9
--- a/usr/lib/api/api_interface.c
8520e9
+++ b/usr/lib/api/api_interface.c
8520e9
@@ -286,7 +286,31 @@ void child_fork_initializer()
8520e9
     if (Anchor != NULL)
8520e9
         C_Finalize(NULL);
8520e9
     in_child_fork_initializer = FALSE;
8520e9
- }
8520e9
+}
8520e9
+
8520e9
+void parent_fork_prepare()
8520e9
+{
8520e9
+    if (Anchor == NULL)
8520e9
+        return;
8520e9
+
8520e9
+    /*
8520e9
+     * Stop the event thread in the fork parent, since having the event thread
8520e9
+     * active when a fork is performed causes various problems (e.g. deadlocks
8520e9
+     * in glibc).
8520e9
+     */
8520e9
+    if (Anchor->event_thread > 0)
8520e9
+        stop_event_thread();
8520e9
+}
8520e9
+
8520e9
+void parent_fork_after()
8520e9
+{
8520e9
+    if (Anchor == NULL)
8520e9
+        return;
8520e9
+
8520e9
+    /* Restart the event thread in the parent when fork is complete */
8520e9
+    if (Anchor->event_thread == 0)
8520e9
+        start_event_thread();
8520e9
+}
8520e9
 
8520e9
 //------------------------------------------------------------------------
8520e9
 // API function C_CancelFunction
8520e9
@@ -1501,6 +1525,20 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
8520e9
 
8520e9
     shData = &(Anchor->SocketDataP);
8520e9
 
8520e9
+    /*
8520e9
+     * Stop the event thread and close the socket.
8520e9
+     * If C_Finalize is called as part of the fork initializer, don't stop
8520e9
+     * the thread, since a forked process does not have any threads, and don't
8520e9
+     * close the socket, as this would close the connection of the parent
8520e9
+     * process to the pkcsslotd as well.
8520e9
+     * */
8520e9
+    if (!in_child_fork_initializer) {
8520e9
+        if (Anchor->event_thread > 0)
8520e9
+            stop_event_thread();
8520e9
+        if (Anchor->socketfd >= 0)
8520e9
+            close(Anchor->socketfd);
8520e9
+    }
8520e9
+
8520e9
     // unload all the STDLL's from the application
8520e9
     // This is in case the APP decides to do the re-initialize and
8520e9
     // continue on
8520e9
@@ -2642,6 +2680,8 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
8520e9
     CK_C_INITIALIZE_ARGS *pArg;
8520e9
     char fcnmap = 0;
8520e9
     CK_RV rc = CKR_OK;
8520e9
+    CK_SLOT_ID slotID;
8520e9
+    API_Slot_t *sltp;
8520e9
 
8520e9
     /*
8520e9
      * Lock so that only one thread can run C_Initialize or C_Finalize at
8520e9
@@ -2674,6 +2714,7 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
8520e9
     // This must be done prior to all goto error calls, else bt_destroy()
8520e9
     // will fail because it accesses uninitialized memory when t->size > 0.
8520e9
     memset(Anchor, 0, sizeof(API_Proc_Struct_t));
8520e9
+    Anchor->socketfd = -1;
8520e9
 
8520e9
     TRACE_DEBUG("Anchor allocated at %s\n", (char *) Anchor);
8520e9
 
8520e9
@@ -2789,11 +2830,21 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
8520e9
     }
8520e9
     TRACE_DEBUG("Shared memory %p \n", Anchor->SharedMemP);
8520e9
 
8520e9
-    if (!init_socket_data()) {
8520e9
+    /* Connect to slot daemon and retrieve slot infos */
8520e9
+    Anchor->socketfd = connect_socket(SOCKET_FILE_PATH);
8520e9
+    if (Anchor->socketfd < 0) {
8520e9
         OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to create a "
8520e9
                    "socket. Verify that the slot management daemon is "
8520e9
                    "running.\n");
8520e9
-        TRACE_ERROR("Cannot attach to socket.\n");
8520e9
+        TRACE_ERROR("Failed to connect to slot daemon\n");
8520e9
+        rc = CKR_FUNCTION_FAILED;
8520e9
+        goto error_shm;
8520e9
+    }
8520e9
+
8520e9
+    if (!init_socket_data(Anchor->socketfd)) {
8520e9
+        OCK_SYSLOG(LOG_ERR, "C_Initialize: Module failed to retrieve slot "
8520e9
+                   "infos from slot deamon.\n");
8520e9
+        TRACE_ERROR("Failed to receive slot infos from socket.\n");
8520e9
         rc = CKR_FUNCTION_FAILED;
8520e9
         goto error_shm;
8520e9
     }
8520e9
@@ -2810,15 +2861,35 @@ CK_RV C_Initialize(CK_VOID_PTR pVoid)
8520e9
     }
8520e9
     //
8520e9
     // load all the slot DLL's here
8520e9
-    {
8520e9
-        CK_SLOT_ID slotID;
8520e9
-        API_Slot_t *sltp;
8520e9
+    for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
8520e9
+        sltp = &(Anchor->SltList[slotID]);
8520e9
+        slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID);
8520e9
+    }
8520e9
 
8520e9
+    /* Start event receiver thread */
8520e9
+    if (start_event_thread() != 0) {
8520e9
+        TRACE_ERROR("Failed to start event thread\n");
8520e9
+
8520e9
+        // unload all the STDLL's from the application
8520e9
+        // This is in case the APP decides to do the re-initialize and
8520e9
+        // continue on
8520e9
         for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
8520e9
             sltp = &(Anchor->SltList[slotID]);
8520e9
-            slot_loaded[slotID] = DL_Load_and_Init(sltp, slotID);
8520e9
+            if (slot_loaded[slotID]) {
8520e9
+                if (sltp->pSTfini) {
8520e9
+                    // call the terminate function..
8520e9
+                    sltp->pSTfini(sltp->TokData, slotID,
8520e9
+                                  &Anchor->SocketDataP.slot_info[slotID],
8520e9
+                                  &trace, 0);
8520e9
+                }
8520e9
+            }
8520e9
+            DL_UnLoad(sltp, slotID);
8520e9
         }
8520e9
 
8520e9
+        API_UnRegister();
8520e9
+
8520e9
+        rc = CKR_FUNCTION_FAILED;
8520e9
+        goto error_shm;
8520e9
     }
8520e9
 
8520e9
     pthread_mutex_unlock(&GlobMutex);
8520e9
@@ -2829,6 +2900,8 @@ error_shm:
8520e9
 
8520e9
 error:
8520e9
     bt_destroy(&Anchor->sess_btree);
8520e9
+    if (Anchor->socketfd >= 0)
8520e9
+        close(Anchor->socketfd);
8520e9
 
8520e9
     free((void *) Anchor);
8520e9
     Anchor = NULL;
8520e9
@@ -5052,7 +5125,8 @@ void api_init(void)
8520e9
 {
8520e9
     // Should only have to do the atfork stuff at load time...
8520e9
     if (!Initialized) {
8520e9
-        pthread_atfork(NULL, NULL, (void (*)()) child_fork_initializer);
8520e9
+        pthread_atfork(parent_fork_prepare, parent_fork_after,
8520e9
+                       child_fork_initializer);
8520e9
         Initialized = 1;
8520e9
     }
8520e9
 }
8520e9
diff --git a/usr/lib/api/apiproto.h b/usr/lib/api/apiproto.h
8520e9
index 871f3778..8523fb8e 100644
8520e9
--- a/usr/lib/api/apiproto.h
8520e9
+++ b/usr/lib/api/apiproto.h
8520e9
@@ -50,6 +50,9 @@ void CK_Info_From_Internal(CK_INFO_PTR dest, CK_INFO_PTR_64 src);
8520e9
 int sessions_exist(CK_SLOT_ID);
8520e9
 
8520e9
 void CloseAllSessions(CK_SLOT_ID slot_id, CK_BBOOL in_fork_initializer);
8520e9
-int init_socket_data();
8520e9
+int connect_socket(const char *file_path);
8520e9
+int init_socket_data(int socketfd);
8520e9
+int start_event_thread();
8520e9
+int stop_event_thread();
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/lib/api/socket_client.c b/usr/lib/api/socket_client.c
8520e9
index 6bacf151..e344ddbf 100644
8520e9
--- a/usr/lib/api/socket_client.c
8520e9
+++ b/usr/lib/api/socket_client.c
8520e9
@@ -23,114 +23,421 @@
8520e9
 #include <grp.h>
8520e9
 #include <errno.h>
8520e9
 #include <stdlib.h>
8520e9
+#include <stdbool.h>
8520e9
+#include <poll.h>
8520e9
 
8520e9
 #include "apiproto.h"
8520e9
 #include "slotmgr.h"
8520e9
 #include "apictl.h"
8520e9
+#include "trace.h"
8520e9
 #include "ock_syslog.h"
8520e9
+#include "events.h"
8520e9
 
8520e9
 extern API_Proc_Struct_t *Anchor;
8520e9
-//
8520e9
-// Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data
8520e9
-// structure with the values passed by the pkcsslotd via a socket RPC.
8520e9
-int init_socket_data()
8520e9
+
8520e9
+int connect_socket(const char *file_path)
8520e9
 {
8520e9
     int socketfd;
8520e9
     struct sockaddr_un daemon_address;
8520e9
     struct stat file_info;
8520e9
     struct group *grp;
8520e9
-    int n;
8520e9
-    unsigned int bytes_received = 0;
8520e9
-    Slot_Mgr_Socket_t *daemon_socket_data = NULL;
8520e9
-    int ret = FALSE;
8520e9
 
8520e9
-    if (stat(SOCKET_FILE_PATH, &file_info)) {
8520e9
+    if (stat(file_path, &file_info)) {
8520e9
         OCK_SYSLOG(LOG_ERR,
8520e9
-                   "init_socket_data: failed to find socket file, errno=%d",
8520e9
+                   "connect_socket: failed to find socket file, errno=%d",
8520e9
                    errno);
8520e9
-        return FALSE;
8520e9
+        return -1;
8520e9
     }
8520e9
 
8520e9
     grp = getgrnam("pkcs11");
8520e9
     if (!grp) {
8520e9
         OCK_SYSLOG(LOG_ERR,
8520e9
-                   "init_socket_data: pkcs11 group does not exist, errno=%d",
8520e9
+                   "connect_socket: pkcs11 group does not exist, errno=%d",
8520e9
                    errno);
8520e9
-        return FALSE;
8520e9
+        return -1;
8520e9
     }
8520e9
 
8520e9
     if (file_info.st_uid != 0 || file_info.st_gid != grp->gr_gid) {
8520e9
         OCK_SYSLOG(LOG_ERR,
8520e9
-                   "init_socket_data: incorrect permissions on socket file");
8520e9
-        return FALSE;
8520e9
+                   "connect_socket: incorrect permissions on socket file");
8520e9
+        return -1;
8520e9
     }
8520e9
 
8520e9
     if ((socketfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
8520e9
         OCK_SYSLOG(LOG_ERR,
8520e9
-                   "init_socket_data: failed to create socket, errno=%d",
8520e9
+                   "connect_socket: failed to create socket, errno=%d",
8520e9
                    errno);
8520e9
-        return FALSE;
8520e9
+        return -1;
8520e9
     }
8520e9
 
8520e9
     memset(&daemon_address, 0, sizeof(struct sockaddr_un));
8520e9
     daemon_address.sun_family = AF_UNIX;
8520e9
-    strcpy(daemon_address.sun_path, SOCKET_FILE_PATH);
8520e9
+    strcpy(daemon_address.sun_path, file_path);
8520e9
 
8520e9
     if (connect(socketfd, (struct sockaddr *) &daemon_address,
8520e9
                 sizeof(struct sockaddr_un)) != 0) {
8520e9
         OCK_SYSLOG(LOG_ERR,
8520e9
-                   "init_socket_data: failed to connect to slotmanager daemon, "
8520e9
+                   "connect_socket: failed to connect to slotmanager daemon, "
8520e9
                    "errno=%d",
8520e9
                    errno);
8520e9
-        goto exit;
8520e9
-    }
8520e9
-    // allocate data buffer
8520e9
-    daemon_socket_data =
8520e9
-        (Slot_Mgr_Socket_t *) malloc(sizeof(*daemon_socket_data));
8520e9
-    if (!daemon_socket_data) {
8520e9
-        OCK_SYSLOG(LOG_ERR, "init_socket_data: failed to \
8520e9
-                   allocate %lu bytes \
8520e9
-                   for daemon data, errno=%d",
8520e9
-                   sizeof(*daemon_socket_data), errno);
8520e9
-        goto exit;
8520e9
+        goto error;
8520e9
     }
8520e9
 
8520e9
-    while (bytes_received < sizeof(*daemon_socket_data)) {
8520e9
-        n = read(socketfd, ((char *) daemon_socket_data) + bytes_received,
8520e9
-                 sizeof(*daemon_socket_data) - bytes_received);
8520e9
+    return socketfd;
8520e9
+
8520e9
+error:
8520e9
+    close(socketfd);
8520e9
+    return -1;
8520e9
+}
8520e9
+
8520e9
+static ssize_t read_all(int socketfd, char *buffer, size_t size)
8520e9
+{
8520e9
+    size_t bytes_received = 0;
8520e9
+    ssize_t n;
8520e9
+
8520e9
+    while (bytes_received < size) {
8520e9
+        n = read(socketfd, buffer + bytes_received, size - bytes_received);
8520e9
         if (n < 0) {
8520e9
             // read error
8520e9
             if (errno == EINTR)
8520e9
                 continue;
8520e9
-            OCK_SYSLOG(LOG_ERR, "init_socket_data: read error \
8520e9
-                       on daemon socket, errno=%d", errno);
8520e9
-            goto exit;
8520e9
-        } else if (n == 0) {
8520e9
-            // eof but we still expect some bytes
8520e9
-            OCK_SYSLOG(LOG_ERR, "init_socket_data: read returned \
8520e9
-                       with eof but we still \
8520e9
-                       expect %lu bytes from daemon",
8520e9
-                       sizeof(*daemon_socket_data) - bytes_received);
8520e9
-            goto exit;
8520e9
-        } else {
8520e9
-            // n > 0, we got some bytes
8520e9
-            bytes_received += n;
8520e9
+            return -errno;
8520e9
         }
8520e9
+        if (n == 0)
8520e9
+            break;
8520e9
+
8520e9
+        bytes_received += n;
8520e9
     }
8520e9
 
8520e9
-    ret = TRUE;
8520e9
+    return bytes_received;
8520e9
+}
8520e9
+
8520e9
+static ssize_t send_all(int socketfd, char *buffer, size_t size)
8520e9
+{
8520e9
+    size_t bytes_sent = 0;
8520e9
+    ssize_t n;
8520e9
 
8520e9
-    // copy the Slot_Mgr_Socket_t struct into global
8520e9
-    // Anchor SocketDataPdata buffer
8520e9
-    memcpy(&(Anchor->SocketDataP), daemon_socket_data,
8520e9
-           sizeof(*daemon_socket_data));
8520e9
+    while (bytes_sent < size) {
8520e9
+        n = send(socketfd, buffer + bytes_sent, size - bytes_sent, 0);
8520e9
+        if (n < 0) {
8520e9
+            // send error
8520e9
+            if (errno == EINTR)
8520e9
+                continue;
8520e9
+            return -errno;
8520e9
+        }
8520e9
+        if (n == 0)
8520e9
+            break;
8520e9
 
8520e9
-exit:
8520e9
-    //free the data buffer after copy
8520e9
-    if (daemon_socket_data)
8520e9
-        free(daemon_socket_data);
8520e9
+        bytes_sent += n;
8520e9
+    }
8520e9
 
8520e9
-    close(socketfd);
8520e9
+    return bytes_sent;
8520e9
+}
8520e9
+
8520e9
+//
8520e9
+// Will fill out the Slot_Mgr_Socket_t structure in the Anchor global data
8520e9
+// structure with the values passed by the pkcsslotd via a socket RPC.
8520e9
+int init_socket_data(int socketfd)
8520e9
+{
8520e9
+    ssize_t n;
8520e9
+    int ret = TRUE;
8520e9
+
8520e9
+    n = read_all(socketfd, (char *)&Anchor->SocketDataP,
8520e9
+                 sizeof(Anchor->SocketDataP));
8520e9
+    if (n < 0) {
8520e9
+        // read error
8520e9
+        OCK_SYSLOG(LOG_ERR, "init_socket_data: read error \
8520e9
+                   on daemon socket, errno=%d", -n);
8520e9
+        ret = FALSE;
8520e9
+    }
8520e9
+    if (n != sizeof(Anchor->SocketDataP)) {
8520e9
+        // eof but we still expect some bytes
8520e9
+        OCK_SYSLOG(LOG_ERR, "init_socket_data: read returned \
8520e9
+                   with eof but we still \
8520e9
+                   expect %lu bytes from daemon",
8520e9
+                   sizeof(Anchor->SocketDataP) - n);
8520e9
+        ret = FALSE;
8520e9
+    }
8520e9
 
8520e9
     return ret;
8520e9
 }
8520e9
+
8520e9
+static bool match_token_label_filter(event_msg_t *event, API_Slot_t *sltp)
8520e9
+{
8520e9
+    if (event->token_label[0] == ' ' || event->token_label[0] == '\0')
8520e9
+        return true;
8520e9
+
8520e9
+    return memcmp(event->token_label,
8520e9
+                  sltp->TokData->nv_token_data->token_info.label,
8520e9
+                  sizeof(event->token_label)) == 0;
8520e9
+}
8520e9
+
8520e9
+struct type_model {
8520e9
+    unsigned int type;
8520e9
+    char model[member_size(CK_TOKEN_INFO_32, model)];
8520e9
+};
8520e9
+
8520e9
+static const struct type_model type_model_flt[] = {
8520e9
+        { .type = EVENT_TOK_TYPE_CCA,  .model = "CCA             " },
8520e9
+        { .type = EVENT_TOK_TYPE_EP11, .model = "EP11            " },
8520e9
+};
8520e9
+
8520e9
+static bool match_token_type_filter(event_msg_t *event, API_Slot_t *sltp)
8520e9
+{
8520e9
+    size_t i;
8520e9
+
8520e9
+    if (event->token_type == EVENT_TOK_TYPE_ALL)
8520e9
+        return true;
8520e9
+
8520e9
+    for (i = 0; i < sizeof(type_model_flt) / sizeof(struct type_model); i++) {
8520e9
+        if (memcmp(sltp->TokData->nv_token_data->token_info.model,
8520e9
+                   type_model_flt[i].model,
8520e9
+                   sizeof(type_model_flt[i].model)) == 0 &&
8520e9
+            (event->token_type & type_model_flt[i].type) != 0)
8520e9
+            return true;
8520e9
+    }
8520e9
+
8520e9
+    return false;
8520e9
+}
8520e9
+
8520e9
+static int handle_event(API_Proc_Struct_t *anchor, event_msg_t *event,
8520e9
+                        char *payload, event_reply_t *reply)
8520e9
+{
8520e9
+    CK_SLOT_ID slotID;
8520e9
+    API_Slot_t *sltp;
8520e9
+    CK_RV rc;
8520e9
+
8520e9
+    /* If its not for our process, ignore it, don't increment reply counters */
8520e9
+    if (event->process_id != 0 && event->process_id != anchor->Pid)
8520e9
+        return 0;
8520e9
+
8520e9
+    for (slotID = 0; slotID < NUMBER_SLOTS_MANAGED; slotID++) {
8520e9
+        sltp = &anchor->SltList[slotID];
8520e9
+        if (sltp->DLLoaded == FALSE || sltp->FcnList == NULL)
8520e9
+            continue;
8520e9
+
8520e9
+        if (!match_token_label_filter(event, sltp))
8520e9
+            continue;
8520e9
+        if (!match_token_type_filter(event, sltp))
8520e9
+            continue;
8520e9
+
8520e9
+        if (sltp->FcnList->ST_HandleEvent != NULL)
8520e9
+            rc = sltp->FcnList->ST_HandleEvent(sltp->TokData, event->type,
8520e9
+                                               event->flags, payload,
8520e9
+                                               event->payload_len);
8520e9
+        else
8520e9
+            rc = CKR_FUNCTION_NOT_SUPPORTED;
8520e9
+
8520e9
+        TRACE_DEVEL("Slot %lu ST_HandleEvent rc: 0x%lx\n", slotID, rc);
8520e9
+        switch (rc) {
8520e9
+        case CKR_OK:
8520e9
+            reply->positive_replies++;
8520e9
+            break;
8520e9
+        case CKR_FUNCTION_NOT_SUPPORTED:
8520e9
+            reply->nothandled_replies++;
8520e9
+            break;
8520e9
+        default:
8520e9
+            reply->negative_replies++;
8520e9
+            break;
8520e9
+        }
8520e9
+    }
8520e9
+
8520e9
+    return 0;
8520e9
+}
8520e9
+
8520e9
+static void event_thread_cleanup(void *arg)
8520e9
+{
8520e9
+    API_Proc_Struct_t *anchor = arg;
8520e9
+
8520e9
+    UNUSED(anchor);
8520e9
+
8520e9
+    TRACE_DEVEL("Event thread %lu terminating\n", pthread_self());
8520e9
+}
8520e9
+
8520e9
+static void *event_thread(void *arg)
8520e9
+{
8520e9
+    API_Proc_Struct_t *anchor = arg;
8520e9
+    int oldstate, oldtype;
8520e9
+    struct pollfd pollfd;
8520e9
+    event_msg_t event;
8520e9
+    char *payload;
8520e9
+    event_reply_t reply;
8520e9
+    ssize_t num;
8520e9
+    int rc;
8520e9
+
8520e9
+    UNUSED(arg);
8520e9
+
8520e9
+    TRACE_DEVEL("Event thread %lu running\n", pthread_self());
8520e9
+
8520e9
+    if (anchor->socketfd < 0) {
8520e9
+        TRACE_ERROR("socket is already closed.\n");
8520e9
+        TRACE_DEVEL("Event thread %lu terminating\n", pthread_self());
8520e9
+        return NULL;
8520e9
+    }
8520e9
+
8520e9
+    /* Enable cancellation */
8520e9
+    pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
8520e9
+    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
8520e9
+    pthread_cleanup_push(event_thread_cleanup, anchor);
8520e9
+
8520e9
+    pollfd.fd = anchor->socketfd;
8520e9
+    pollfd.events = POLLIN | POLLHUP | POLLERR;
8520e9
+
8520e9
+    while (1) {
8520e9
+        pollfd.revents = 0;
8520e9
+        rc = poll(&pollfd, 1, -1);
8520e9
+        if (rc < 0) {
8520e9
+            if (errno == EINTR)
8520e9
+                continue;
8520e9
+            TRACE_ERROR("poll failed: %d\n", errno);
8520e9
+            break;
8520e9
+        }
8520e9
+
8520e9
+        if (rc == 0)
8520e9
+            continue;
8520e9
+
8520e9
+        if (pollfd.revents & (POLLHUP | POLLERR)) {
8520e9
+            TRACE_ERROR("Error on socket, possibly closed by slot daemon\n");
8520e9
+            break;
8520e9
+        }
8520e9
+        if ((pollfd.revents & POLLIN) == 0)
8520e9
+            continue;
8520e9
+
8520e9
+        /* Disable for cancellation while we are working on an event */
8520e9
+        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate);
8520e9
+
8520e9
+        TRACE_DEVEL("Receive new event ....\n");
8520e9
+
8520e9
+        num = read_all(anchor->socketfd, (char *)&event, sizeof(event));
8520e9
+        if (num != sizeof(event)) {
8520e9
+            TRACE_ERROR("Error receiving the event, rc: %ld\n", num);
8520e9
+            break;
8520e9
+        }
8520e9
+
8520e9
+        TRACE_DEBUG("Event version:      %u\n", event.version);
8520e9
+        TRACE_DEBUG("Event type:         0x%08x\n", event.type);
8520e9
+        TRACE_DEBUG("Event flags:        0x%08x\n", event.flags);
8520e9
+        TRACE_DEBUG("Event token_type:   0x%08x\n", event.token_type);
8520e9
+        TRACE_DEBUG("Event token_name:   '%.32s'\n", event.token_label);
8520e9
+        TRACE_DEBUG("Event process_id:   %u\n", event.process_id);
8520e9
+        TRACE_DEBUG("Event payload_len:  %u\n", event.payload_len);
8520e9
+
8520e9
+        if (event.version != EVENT_VERSION_1) {
8520e9
+            TRACE_ERROR("Event version invalid: %u\n", event.version);
8520e9
+            break;
8520e9
+        }
8520e9
+
8520e9
+        payload = NULL;
8520e9
+        if (event.payload_len > 0) {
8520e9
+            payload = malloc(event.payload_len);
8520e9
+            if (payload == NULL) {
8520e9
+                TRACE_ERROR("Failed to allocate buffer for event payload\n");
8520e9
+                break;
8520e9
+            }
8520e9
+
8520e9
+            num = read_all(anchor->socketfd, payload, event.payload_len);
8520e9
+            if (num != event.payload_len) {
8520e9
+                TRACE_ERROR("Error receiving the event payload, rc: %ld\n", num);
8520e9
+                if (payload != NULL)
8520e9
+                    free(payload);
8520e9
+                break;
8520e9
+            }
8520e9
+
8520e9
+            TRACE_DEBUG("Event payload:\n");
8520e9
+            TRACE_DEBUG_DUMP("  ", payload, event.payload_len);
8520e9
+        }
8520e9
+
8520e9
+        memset(&reply, 0, sizeof(reply));
8520e9
+        reply.version = EVENT_VERSION_1;
8520e9
+        rc = handle_event(anchor, &event, payload, &reply);
8520e9
+        if (rc != 0) {
8520e9
+            TRACE_ERROR("Error handling the event, rc: %d\n", rc);
8520e9
+            if (payload != NULL)
8520e9
+                free(payload);
8520e9
+            break;
8520e9
+        }
8520e9
+
8520e9
+        TRACE_DEBUG("Reply version:      %u\n", reply.version);
8520e9
+        TRACE_DEBUG("Reply positive:     %u\n", reply.positive_replies);
8520e9
+        TRACE_DEBUG("Reply negative:     %u\n", reply.negative_replies);
8520e9
+        TRACE_DEBUG("Reply not-handled:  %u\n", reply.nothandled_replies);
8520e9
+
8520e9
+        if (event.flags & EVENT_FLAGS_REPLY_REQ) {
8520e9
+            num = send_all(anchor->socketfd, (char *)&reply, sizeof(reply));
8520e9
+            if (num != sizeof(reply)) {
8520e9
+                TRACE_ERROR("Error sending the event reply, rc: %ld\n", num);
8520e9
+                if (payload != NULL)
8520e9
+                    free(payload);
8520e9
+                break;
8520e9
+            }
8520e9
+        }
8520e9
+
8520e9
+        if (payload != NULL)
8520e9
+            free(payload);
8520e9
+
8520e9
+        /* Re-enable for  and test if we got canceled in the meantime */
8520e9
+        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
8520e9
+        pthread_testcancel();
8520e9
+    }
8520e9
+
8520e9
+    /*
8520e9
+     * Close the socket if we encounter an unrecoverable error (e.g. received
8520e9
+     * invalid event) and stop the thread because of that.
8520e9
+     * If the thread is stopped via stop_event_thread(), then it gets canceled
8520e9
+     * via pthread_cancel(), and will not reach this place, thus the socket is
8520e9
+     * not closed. This is intended, and the socket will then be closed by
8520e9
+     * C_Finalize(). The atfork 'prepare' handler in the parent process also
8520e9
+     * stops the thread (via stop_event_thread()), and the socket must not be
8520e9
+     * closed in this case, because the thread is restarted in the atfork
8520e9
+     * 'parent' handler, and should continue to receive events from the
8520e9
+     * socket.
8520e9
+     */
8520e9
+    close(anchor->socketfd);
8520e9
+    anchor->socketfd = -1;
8520e9
+
8520e9
+    pthread_cleanup_pop(1);
8520e9
+    return NULL;
8520e9
+}
8520e9
+
8520e9
+int start_event_thread()
8520e9
+{
8520e9
+    int rc;
8520e9
+
8520e9
+    rc =  pthread_create(&Anchor->event_thread, NULL, event_thread, Anchor);
8520e9
+    if (rc != 0) {
8520e9
+        OCK_SYSLOG(LOG_ERR, "start_event_thread: pthread_create failed, "
8520e9
+                   "errno=%d", rc);
8520e9
+        TRACE_ERROR("Failed to start event thread, errno=%d\n", rc);
8520e9
+        return rc;
8520e9
+    }
8520e9
+
8520e9
+    TRACE_DEVEL("Event thread %lu has been started\n", Anchor->event_thread);
8520e9
+    return 0;
8520e9
+}
8520e9
+
8520e9
+int stop_event_thread()
8520e9
+{
8520e9
+    int rc;
8520e9
+    void *status;
8520e9
+
8520e9
+    TRACE_DEVEL("Canceling event thread %lu\n", Anchor->event_thread);
8520e9
+    rc = pthread_cancel(Anchor->event_thread);
8520e9
+    if (rc != 0 && rc != ESRCH)
8520e9
+        return rc;
8520e9
+
8520e9
+    TRACE_DEVEL("Waiting for event thread %lu to terminate\n",
8520e9
+                Anchor->event_thread);
8520e9
+    rc = pthread_join(Anchor->event_thread, &status);
8520e9
+    if (rc != 0)
8520e9
+        return rc;
8520e9
+
8520e9
+    if (status != PTHREAD_CANCELED) {
8520e9
+        TRACE_ERROR("Event thread was stopped, but did not return the "
8520e9
+                   "expected status\n");
8520e9
+    }
8520e9
+
8520e9
+    TRACE_DEVEL("Event thread %lu has terminated\n", Anchor->event_thread);
8520e9
+
8520e9
+    Anchor->event_thread = 0;
8520e9
+    return 0;
8520e9
+}
8520e9
diff --git a/usr/lib/cca_stdll/tok_struct.h b/usr/lib/cca_stdll/tok_struct.h
8520e9
index 2b43fa8e..182e2ac2 100644
8520e9
--- a/usr/lib/cca_stdll/tok_struct.h
8520e9
+++ b/usr/lib/cca_stdll/tok_struct.h
8520e9
@@ -134,6 +134,7 @@ token_spec_t token_specific = {
8520e9
     &token_specific_reencrypt_single,
8520e9
     NULL,                       // set_attribute_values
8520e9
     NULL,                       // set_attrs_for_new_object
8520e9
+    NULL,                       // handle_event
8520e9
 };
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/lib/common/new_host.c b/usr/lib/common/new_host.c
8520e9
index aae00984..a3749d26 100644
8520e9
--- a/usr/lib/common/new_host.c
8520e9
+++ b/usr/lib/common/new_host.c
8520e9
@@ -4039,6 +4039,24 @@ done:
8520e9
     return rc;
8520e9
 }
8520e9
 
8520e9
+CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
8520e9
+                     unsigned int event_flags, const char *payload,
8520e9
+                     unsigned int payload_len)
8520e9
+{
8520e9
+    CK_RV rc;
8520e9
+
8520e9
+    if (token_specific.t_handle_event == NULL)
8520e9
+        return CKR_FUNCTION_NOT_SUPPORTED;
8520e9
+
8520e9
+    rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
8520e9
+                                       payload, payload_len);
8520e9
+
8520e9
+    TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
8520e9
+               "event_flags = 0x%08x\n", rc, event_type, event_flags);
8520e9
+
8520e9
+    return rc;
8520e9
+}
8520e9
+
8520e9
 void SC_SetFunctionList(void)
8520e9
 {
8520e9
     function_list.ST_Initialize = ST_Initialize;
8520e9
@@ -4104,4 +4122,6 @@ void SC_SetFunctionList(void)
8520e9
     function_list.ST_CancelFunction = NULL;     // SC_CancelFunction;
8520e9
 
8520e9
     function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
8520e9
+
8520e9
+    function_list.ST_HandleEvent = SC_HandleEvent;
8520e9
 }
8520e9
diff --git a/usr/lib/common/tok_spec_struct.h b/usr/lib/common/tok_spec_struct.h
8520e9
index 30ffcf02..0e90d411 100644
8520e9
--- a/usr/lib/common/tok_spec_struct.h
8520e9
+++ b/usr/lib/common/tok_spec_struct.h
8520e9
@@ -278,6 +278,10 @@ struct token_specific_struct {
8520e9
 
8520e9
     CK_RV(*t_set_attrs_for_new_object) (STDLL_TokData_t *, CK_OBJECT_CLASS,
8520e9
                                         CK_ULONG, TEMPLATE *);
8520e9
+
8520e9
+    CK_RV(*t_handle_event) (STDLL_TokData_t *tokdata, unsigned int event_type,
8520e9
+                            unsigned int event_flags, const char *payload,
8520e9
+                            unsigned int payload_len);
8520e9
 };
8520e9
 
8520e9
 typedef struct token_specific_struct token_spec_t;
8520e9
diff --git a/usr/lib/common/tok_specific.h b/usr/lib/common/tok_specific.h
8520e9
index ffb72909..997fa7e1 100644
8520e9
--- a/usr/lib/common/tok_specific.h
8520e9
+++ b/usr/lib/common/tok_specific.h
8520e9
@@ -326,4 +326,10 @@ CK_RV token_specific_set_attrs_for_new_object(STDLL_TokData_t *,
8520e9
                                               CK_OBJECT_CLASS, CK_ULONG,
8520e9
                                               TEMPLATE *);
8520e9
 
8520e9
+CK_RV token_specific_handle_event(STDLL_TokData_t *tokdata,
8520e9
+                                  unsigned int event_type,
8520e9
+                                  unsigned int event_flags,
8520e9
+                                  const char *payload,
8520e9
+                                  unsigned int payload_len);
8520e9
+
8520e9
 #endif
8520e9
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
8520e9
index 6fcef68a..4e592363 100644
8520e9
--- a/usr/lib/ep11_stdll/new_host.c
8520e9
+++ b/usr/lib/ep11_stdll/new_host.c
8520e9
@@ -4262,6 +4262,24 @@ done:
8520e9
     return rc;
8520e9
 }
8520e9
 
8520e9
+CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
8520e9
+                     unsigned int event_flags, const char *payload,
8520e9
+                     unsigned int payload_len)
8520e9
+{
8520e9
+    CK_RV rc;
8520e9
+
8520e9
+    if (token_specific.t_handle_event == NULL)
8520e9
+        return CKR_FUNCTION_NOT_SUPPORTED;
8520e9
+
8520e9
+    rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
8520e9
+                                       payload, payload_len);
8520e9
+
8520e9
+    TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
8520e9
+               "event_flags = 0x%08x\n", rc, event_type, event_flags);
8520e9
+
8520e9
+    return rc;
8520e9
+}
8520e9
+
8520e9
 void SC_SetFunctionList(void)
8520e9
 {
8520e9
     function_list.ST_Initialize = ST_Initialize;
8520e9
@@ -4327,4 +4345,6 @@ void SC_SetFunctionList(void)
8520e9
     function_list.ST_CancelFunction = NULL;     // SC_CancelFunction;
8520e9
 
8520e9
     function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
8520e9
+
8520e9
+    function_list.ST_HandleEvent = SC_HandleEvent;
8520e9
 }
8520e9
diff --git a/usr/lib/ep11_stdll/tok_struct.h b/usr/lib/ep11_stdll/tok_struct.h
8520e9
index 51aae6fb..2c0af9cf 100644
8520e9
--- a/usr/lib/ep11_stdll/tok_struct.h
8520e9
+++ b/usr/lib/ep11_stdll/tok_struct.h
8520e9
@@ -137,6 +137,7 @@ token_spec_t token_specific = {
8520e9
     &token_specific_reencrypt_single,
8520e9
     &token_specific_set_attribute_values,
8520e9
     &token_specific_set_attrs_for_new_object,
8520e9
+    NULL,                       // handle_event
8520e9
 };
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/lib/ica_s390_stdll/tok_struct.h b/usr/lib/ica_s390_stdll/tok_struct.h
8520e9
index 13ee72c9..a260a276 100644
8520e9
--- a/usr/lib/ica_s390_stdll/tok_struct.h
8520e9
+++ b/usr/lib/ica_s390_stdll/tok_struct.h
8520e9
@@ -147,6 +147,7 @@ token_spec_t token_specific = {
8520e9
     NULL,                       // reencrypt_single
8520e9
     NULL,                       // set_attribute_values
8520e9
     NULL,                       // set_attrs_for_new_object
8520e9
+    NULL,                       // handle_event
8520e9
 };
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/lib/icsf_stdll/new_host.c b/usr/lib/icsf_stdll/new_host.c
8520e9
index 0f93ce5c..cfef7425 100644
8520e9
--- a/usr/lib/icsf_stdll/new_host.c
8520e9
+++ b/usr/lib/icsf_stdll/new_host.c
8520e9
@@ -3332,6 +3332,24 @@ done:
8520e9
     return rc;
8520e9
 }
8520e9
 
8520e9
+CK_RV SC_HandleEvent(STDLL_TokData_t *tokdata, unsigned int event_type,
8520e9
+                     unsigned int event_flags, const char *payload,
8520e9
+                     unsigned int payload_len)
8520e9
+{
8520e9
+    CK_RV rc;
8520e9
+
8520e9
+    if (token_specific.t_handle_event == NULL)
8520e9
+        return CKR_FUNCTION_NOT_SUPPORTED;
8520e9
+
8520e9
+    rc = token_specific.t_handle_event(tokdata, event_type, event_flags,
8520e9
+                                       payload, payload_len);
8520e9
+
8520e9
+    TRACE_INFO("SC_HandleEvent: rc = 0x%08lx, event_type = 0x%08x, "
8520e9
+               "event_flags = 0x%08x\n", rc, event_type, event_flags);
8520e9
+
8520e9
+    return rc;
8520e9
+}
8520e9
+
8520e9
 void SC_SetFunctionList(void)
8520e9
 {
8520e9
     function_list.ST_Initialize = ST_Initialize;
8520e9
@@ -3397,4 +3415,6 @@ void SC_SetFunctionList(void)
8520e9
     function_list.ST_CancelFunction = NULL;     // SC_CancelFunction;
8520e9
 
8520e9
     function_list.ST_IBM_ReencryptSingle = SC_IBM_ReencryptSingle;
8520e9
+
8520e9
+    function_list.ST_HandleEvent = SC_HandleEvent;
8520e9
 }
8520e9
diff --git a/usr/lib/icsf_stdll/tok_struct.h b/usr/lib/icsf_stdll/tok_struct.h
8520e9
index fb1619ee..0f930a29 100644
8520e9
--- a/usr/lib/icsf_stdll/tok_struct.h
8520e9
+++ b/usr/lib/icsf_stdll/tok_struct.h
8520e9
@@ -129,6 +129,7 @@ token_spec_t token_specific = {
8520e9
     NULL,                       // reencrypt_single
8520e9
     NULL,                       // set_attribute_values
8520e9
     NULL,                       // set_attrs_for_new_object
8520e9
+    NULL,                       // handle_event
8520e9
 };
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/lib/soft_stdll/tok_struct.h b/usr/lib/soft_stdll/tok_struct.h
8520e9
index acf7c5d7..e43df038 100644
8520e9
--- a/usr/lib/soft_stdll/tok_struct.h
8520e9
+++ b/usr/lib/soft_stdll/tok_struct.h
8520e9
@@ -172,6 +172,7 @@ token_spec_t token_specific = {
8520e9
     NULL,                       // reencrypt_single
8520e9
     NULL,                       // set_attribute_values
8520e9
     NULL,                       // set_attrs_for_new_object
8520e9
+    NULL,                       // handle_event
8520e9
 };
8520e9
 
8520e9
 #endif
8520e9
diff --git a/usr/lib/tpm_stdll/tok_struct.h b/usr/lib/tpm_stdll/tok_struct.h
8520e9
index d48b93e5..8903f123 100644
8520e9
--- a/usr/lib/tpm_stdll/tok_struct.h
8520e9
+++ b/usr/lib/tpm_stdll/tok_struct.h
8520e9
@@ -120,4 +120,5 @@ struct token_specific_struct token_specific = {
8520e9
     NULL,                       // reencrypt_single
8520e9
     NULL,                       // set_attribute_values
8520e9
     NULL,                       // set_attrs_for_new_object
8520e9
+    NULL,                       // handle_event
8520e9
 };