]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added a modified pakchois library (to open arbitrary pkcs11 modules).
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Mon, 24 May 2010 14:58:31 +0000 (16:58 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 3 Jun 2010 17:54:54 +0000 (19:54 +0200)
Current gnutls works only with this one.

lib/Makefile.am
lib/configure.ac
lib/m4/hooks.m4
lib/pakchois/errors.c [new file with mode: 0644]
lib/pakchois/pakchois.c [new file with mode: 0644]
lib/pakchois/pakchois.h [new file with mode: 0644]
lib/pakchois/pakchois11.h [new file with mode: 0644]

index 12b686bb03335f52b46fdaf8a8542955b246c71d..d795fa7a29db47af932faa62caee080cee1de8dd 100644 (file)
@@ -88,6 +88,7 @@ if ENABLE_PKCS11
 COBJECTS += pkcs11.c pkcs11_privkey.c
 endif
 
+
 if ENABLE_NETTLE
 SUBDIRS += nettle
 else
@@ -125,6 +126,11 @@ HFILES = debug.h gnutls_compress.h gnutls_cipher.h gnutls_buffers.h        \
        ext_session_ticket.h ext_signature.h gnutls_cryptodev.h         \
        ext_safe_renegotiation.h
 
+if ENABLE_LOCAL_PAKCHOIS
+COBJECTS+=pakchois/pakchois.c pakchois/errors.c
+HFILES+=pakchois/pakchois.h pakchois/pakchois11.h
+endif
+
 # Separate so we can create the documentation
 
 libgnutls_la_SOURCES = $(HFILES) $(COBJECTS) $(SRP_COBJECTS)   \
@@ -154,9 +160,7 @@ else
 libgnutls_la_LDFLAGS += $(LTLIBTASN1)
 endif
 
-if ENABLE_PAKCHOIS
 libgnutls_la_LDFLAGS += $(LTLIBPAKCHOIS)
-endif
 
 if ENABLE_NETTLE
 libgnutls_la_LDFLAGS += $(LTLIBNETTLE) -lgmp -lpthread -lhogweed
index 0918742d52196dd1614b5cad7b1aede9d46cab29..35fa0d4ee418d995eab6714da697ffe3e941fb78 100644 (file)
@@ -79,19 +79,6 @@ else
  AC_MSG_RESULT(no)
 fi
 
-AC_ARG_WITH(pakchois, AS_HELP_STRING([--without-pakchois],
-                                 [disable pakchois PKCS11 support]),
-            ac_pakchois=$withval, ac_pakchois=yes)
-AC_MSG_CHECKING([whether to include pakchois PKCS11 support])
-if test x$ac_pakchois != xno; then
- AC_MSG_RESULT(yes)
- AC_LIB_HAVE_LINKFLAGS(pakchois,, [#include <pakchois/pakchois.h>], [pakchois_module_load(0,0);])
- if test "$ac_cv_libpakchois" != yes; then
-   AC_MSG_ERROR(
-*** 
-*** Pakchois was not found. This is required for PKCS11 support.)
-AM_CONDITIONAL(ENABLE_PAKCHOIS, test "$ac_cv_libpakchois" = "yes")
-
 lgl_INIT
 
 LIBGNUTLS_LIBS="-L${libdir} -lgnutls $LIBS"
index 316bf8229e2a2ccdbb1f5e9ba6ad00e10bc7569b..aaf95c6b8d61ef982278c6b05713d0c80f5d3f54 100644 (file)
@@ -92,6 +92,35 @@ AC_DEFUN([LIBGNUTLS_HOOKS],
   AC_MSG_RESULT($included_libtasn1)
   AM_CONDITIONAL(ENABLE_MINITASN1, test "$included_libtasn1" = "yes")
 
+  AC_ARG_WITH(included-pakchois,
+    AS_HELP_STRING([--with-included-pakchois], [use the included pakchois]),
+      included_pakchois=$withval,
+      included_pakchois=no)
+  if test "$included_pakchois" = "no"; then
+    AC_LIB_HAVE_LINKFLAGS(pakchois,, [#include <pakchois/pakchois.h>],
+                          [pakchois_module_load(0,0);])
+    if test "$ac_cv_pakchois" != yes; then
+      included_pakchois=yes
+      AC_MSG_WARN([[
+  *** 
+  *** Pakchois was not found. Will use the included one.
+  ]])
+    fi
+  fi
+  AC_MSG_CHECKING([whether to use the included pakchois])
+  AC_MSG_RESULT($included_pakchois)
+  AM_CONDITIONAL(ENABLE_LOCAL_PAKCHOIS, test "$included_pakchois" = "yes")
+  if test "$included_pakchois" = "yes";then
+       AC_CHECK_LIB(pthread, pthread_mutex_lock,,
+          [AC_MSG_ERROR([could not find pthread_mutex_lock])])
+       AC_CHECK_LIB(dl, dlopen,,
+          [AC_MSG_ERROR([could not find dlopen])])
+
+       module_path="${libdir}:${libdir}/pkcs11"
+
+       CPPFLAGS="$CPPFLAGS -DPAKCHOIS_MODPATH=\\\"${module_path}\\\""
+  fi
+
   AC_ARG_WITH(lzo,
     AS_HELP_STRING([--with-lzo], [use experimental LZO compression]),
                    use_lzo=$withval, use_lzo=no)
diff --git a/lib/pakchois/errors.c b/lib/pakchois/errors.c
new file mode 100644 (file)
index 0000000..de09b92
--- /dev/null
@@ -0,0 +1,146 @@
+/* 
+   pakchois PKCS#11 interface -- error mapping
+   Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA
+*/
+
+/*
+  This code is directly derived from the scute.org PKCS#11 cryptoki
+  interface, which is:
+
+   Copyright 2006, 2007 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+   PURPOSE.
+*/
+
+#include "config.h"
+
+#include "pakchois.h"
+
+#ifdef ENABLE_NLS
+#include <libintl.h>
+#define _(x) dgettext(PACKAGE_NAME, x)
+#else
+#define _(x) x
+#endif
+
+const char *pakchois_error(ck_rv_t rv)
+{
+    if (rv >= CKR_VENDOR_DEFINED) {
+        return _("Vendor defined error");
+    }
+
+    switch (rv) {
+    case CKR_OK: return _("OK");
+    case CKR_CANCEL: return _("Cancel");
+    case CKR_HOST_MEMORY: return _("Host memory");
+    case CKR_SLOT_ID_INVALID: return _("Slot id invalid");
+    case CKR_GENERAL_ERROR: return _("General error");
+    case CKR_FUNCTION_FAILED: return _("Function failed");
+    case CKR_ARGUMENTS_BAD: return _("Arguments bad");
+    case CKR_NO_EVENT: return _("No event");
+    case CKR_NEED_TO_CREATE_THREADS: return _("Need to create threads");
+    case CKR_CANT_LOCK: return _("Can't lock");
+    case CKR_ATTRIBUTE_READ_ONLY: return _("Attribute read only");
+    case CKR_ATTRIBUTE_SENSITIVE: return _("Attribute sensitive");
+    case CKR_ATTRIBUTE_TYPE_INVALID: return _("Attribute type invalid");
+    case CKR_ATTRIBUTE_VALUE_INVALID: return _("Attribute value invalid");
+    case CKR_DATA_INVALID: return _("Data invalid");
+    case CKR_DATA_LEN_RANGE: return _("Data len range");
+    case CKR_DEVICE_ERROR: return _("Device error");
+    case CKR_DEVICE_MEMORY: return _("Device memory");
+    case CKR_DEVICE_REMOVED: return _("Device removed");
+    case CKR_ENCRYPTED_DATA_INVALID: return _("Encrypted data invalid");
+    case CKR_ENCRYPTED_DATA_LEN_RANGE: return _("Encrypted data len range");
+    case CKR_FUNCTION_CANCELED: return _("Function canceled");
+    case CKR_FUNCTION_NOT_PARALLEL: return _("Function not parallel");
+    case CKR_FUNCTION_NOT_SUPPORTED: return _("Function not supported");
+    case CKR_KEY_HANDLE_INVALID: return _("Key handle invalid");
+    case CKR_KEY_SIZE_RANGE: return _("Key size range");
+    case CKR_KEY_TYPE_INCONSISTENT: return _("Key type inconsistent");
+    case CKR_KEY_NOT_NEEDED: return _("Key not needed");
+    case CKR_KEY_CHANGED: return _("Key changed");
+    case CKR_KEY_NEEDED: return _("Key needed");
+    case CKR_KEY_INDIGESTIBLE: return _("Key indigestible");
+    case CKR_KEY_FUNCTION_NOT_PERMITTED: return _("Key function not permitted");
+    case CKR_KEY_NOT_WRAPPABLE: return _("Key not wrappable");
+    case CKR_KEY_UNEXTRACTABLE: return _("Key unextractable");
+    case CKR_MECHANISM_INVALID: return _("Mechanism invalid");
+    case CKR_MECHANISM_PARAM_INVALID: return _("Mechanism param invalid");
+    case CKR_OBJECT_HANDLE_INVALID: return _("Object handle invalid");
+    case CKR_OPERATION_ACTIVE: return _("Operation active");
+    case CKR_OPERATION_NOT_INITIALIZED: return _("Operation not initialized");
+    case CKR_PIN_INCORRECT: return _("PIN incorrect");
+    case CKR_PIN_INVALID: return _("PIN invalid");
+    case CKR_PIN_LEN_RANGE: return _("PIN len range");
+    case CKR_PIN_EXPIRED: return _("PIN expired");
+    case CKR_PIN_LOCKED: return _("PIN locked");
+    case CKR_SESSION_CLOSED: return _("Session closed");
+    case CKR_SESSION_COUNT: return _("Session count");
+    case CKR_SESSION_HANDLE_INVALID: return _("Session handle invalid");
+    case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return _("Session parallel not supported");
+    case CKR_SESSION_READ_ONLY: return _("Session read only");
+    case CKR_SESSION_EXISTS: return _("Session exists");
+    case CKR_SESSION_READ_ONLY_EXISTS: return _("Session read only exists");
+    case CKR_SESSION_READ_WRITE_SO_EXISTS: return _("Session read write so exists");
+    case CKR_SIGNATURE_INVALID: return _("Signature invalid");
+    case CKR_SIGNATURE_LEN_RANGE: return _("Signature length range");
+    case CKR_TEMPLATE_INCOMPLETE: return _("Template incomplete");
+    case CKR_TEMPLATE_INCONSISTENT: return _("Template inconsistent");
+    case CKR_TOKEN_NOT_PRESENT: return _("Token not present");
+    case CKR_TOKEN_NOT_RECOGNIZED: return _("Token not recognized");
+    case CKR_TOKEN_WRITE_PROTECTED: return _("Token write protected");
+    case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return _("Unwrapping key handle invalid");
+    case CKR_UNWRAPPING_KEY_SIZE_RANGE: return _("Unwrapping key size range");
+    case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return _("Unwrapping key type inconsistent");
+    case CKR_USER_ALREADY_LOGGED_IN: return _("User already logged in");
+    case CKR_USER_NOT_LOGGED_IN: return _("User not logged in");
+    case CKR_USER_PIN_NOT_INITIALIZED: return _("User PIN not initialized");
+    case CKR_USER_TYPE_INVALID: return _("User type invalid");
+    case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return _("Another user already logged in");
+    case CKR_USER_TOO_MANY_TYPES: return _("User too many types");
+    case CKR_WRAPPED_KEY_INVALID: return _("Wrapped key invalid");
+    case CKR_WRAPPED_KEY_LEN_RANGE: return _("Wrapped key length range");
+    case CKR_WRAPPING_KEY_HANDLE_INVALID: return _("Wrapping key handle invalid");
+    case CKR_WRAPPING_KEY_SIZE_RANGE: return _("Wrapping key size range");
+    case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return _("Wrapping key type inconsistent");
+    case CKR_RANDOM_SEED_NOT_SUPPORTED: return _("Random seed not supported");
+    case CKR_RANDOM_NO_RNG: return _("Random no rng");
+    case CKR_DOMAIN_PARAMS_INVALID: return _("Domain params invalid");
+    case CKR_BUFFER_TOO_SMALL: return _("Buffer too small");
+    case CKR_SAVED_STATE_INVALID: return _("Saved state invalid");
+    case CKR_INFORMATION_SENSITIVE: return _("Information sensitive");
+    case CKR_STATE_UNSAVEABLE: return _("State unsaveable");
+    case CKR_CRYPTOKI_NOT_INITIALIZED: return _("Cryptoki not initialized");
+    case CKR_CRYPTOKI_ALREADY_INITIALIZED: return _("Cryptoki already initialized");
+    case CKR_MUTEX_BAD: return _("Mutex bad");
+    case CKR_MUTEX_NOT_LOCKED: return _("Mutex not locked");
+    case CKR_FUNCTION_REJECTED: return _("Function rejected");
+    default:
+        break;
+    }
+
+    return _("Unknown error");
+}
diff --git a/lib/pakchois/pakchois.c b/lib/pakchois/pakchois.c
new file mode 100644 (file)
index 0000000..a69dfb0
--- /dev/null
@@ -0,0 +1,982 @@
+/* 
+   pakchois PKCS#11 interface
+   Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA
+*/
+
+/*
+  The interface is directly derived from the scute.org PKCS#11
+  cryptoki interface, which is:
+
+   Copyright 2006, 2007 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+   PURPOSE.
+*/
+
+#include "config.h"
+
+#include <dlfcn.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <assert.h>
+#include "pakchois.h"
+
+struct provider {
+    char *name;
+    void *handle;
+    pthread_mutex_t mutex;
+    const struct ck_function_list *fns;
+    unsigned int refcount;
+    struct provider *next, **prevref;
+};
+
+struct pakchois_module_s {
+    struct slot *slots;
+    struct provider *provider;
+};
+
+static pthread_mutex_t provider_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* List of loaded providers; any modification to the list or any
+ * individual module must performed whilst holding this mutex. */
+static struct provider *provider_list;
+
+struct pakchois_session_s {
+    pakchois_module_t *module;
+    ck_session_handle_t id;
+    pakchois_notify_t notify;
+    void *notify_data;
+    /* Doubly-linked list.  Either prevref = &previous->next or else
+     * prevref = &slot->sessions for the list head. */
+    pakchois_session_t **prevref;
+    pakchois_session_t *next;
+};
+
+struct slot {
+    ck_slot_id_t id;
+    pakchois_session_t *sessions;
+    struct slot *next;
+};
+
+#define DIR_DELIMITER '/'
+
+char* pkcs11ize(const char* name)
+{
+    int len;
+    char* oname;
+    char *base;
+    char *suffix;
+    
+    oname = strdup(name);
+    if (oname == NULL) {
+        return NULL;
+    }
+    
+    /* basename has too many ifs to use */
+    base = strrchr(oname, DIR_DELIMITER);
+    if (base == NULL) {
+        base = oname;
+    } else {
+        base++;
+    }
+
+    suffix = strchr(base, '.');
+    if (suffix != NULL) {
+               if (strncmp(suffix, ".so", 3)==0) {
+                       suffix[0] = 0; /* null terminate before . */
+               }
+    }
+
+    /* check and remove for -p11 or -pkcs11 */
+       suffix = base;
+    while((suffix=strchr(suffix, '-')) != NULL) {
+               if (strncasecmp(suffix, "-p11", 4)==0 || 
+                       strncasecmp(suffix, "-pkcs11", 7)==0) {
+                       suffix[0] = 0;
+                       break;
+               }
+               suffix++;
+       }
+    
+    len = strlen(base);
+
+    memmove(oname, base, len);
+    oname[len] = 0;
+
+    return oname;
+}
+
+static const char *suffix_prefixes[][2] = {
+    { "lib", "pk11.so" },
+    { "", "-pkcs11.so" },
+    { "", ".so" },
+    { "lib", ".so" },
+    { NULL, NULL }
+};
+
+#define CALL(name, args) (mod->provider->fns->C_ ## name) args
+#define CALLS(name, args) (sess->module->provider->fns->C_ ## name) args
+#define CALLS1(n, a) CALLS(n, (sess->id, a))
+#define CALLS2(n, a, b) CALLS(n, (sess->id, a, b))
+#define CALLS3(n, a, b, c) CALLS(n, (sess->id, a, b, c))
+#define CALLS4(n, a, b, c, d) CALLS(n, (sess->id, a, b, c, d))
+#define CALLS5(n, a, b, c, d, e) CALLS(n, (sess->id, a, b, c, d, e))
+#define CALLS7(n, a, b, c, d, e, f, g) CALLS(n, (sess->id, a, b, c, d, e, f, g))
+
+static void *find_pkcs11_module(const char *name, CK_C_GetFunctionList *gfl)
+{
+    char module_path[] = PAKCHOIS_MODPATH;
+    char *next = module_path;
+    void *h;
+
+    /* try the plain name first */
+    h = dlopen(name, RTLD_LOCAL|RTLD_NOW);
+    if (h != NULL) {
+         *gfl = dlsym(h, "C_GetFunctionList");
+         if (*gfl) {
+              return h;
+         }
+         dlclose(h);
+    }
+    
+    while (next) {
+        char *dir = next, *sep = strchr(next, ':');
+        unsigned i;
+
+        if (sep) { 
+            *sep++ = '\0';
+            next = sep;
+        }
+        else {
+            next = NULL;
+        }
+
+        
+        for (i = 0; suffix_prefixes[i][0]; i++) {
+            char path[PATH_MAX];
+            
+            snprintf(path, sizeof path, "%s/%s%s%s", dir,
+                     suffix_prefixes[i][0], name, suffix_prefixes[i][1]);
+
+            h = dlopen(path, RTLD_LOCAL|RTLD_NOW);
+            if (h != NULL) {
+                *gfl = dlsym(h, "C_GetFunctionList");
+                if (*gfl) {
+                    return h;
+                }
+                dlclose(h);
+            }
+        }
+    }
+
+    return NULL;
+}            
+
+static struct provider *find_provider(const char *name)
+{
+    struct provider *p;
+
+    for (p = provider_list; p; p = p->next) {
+        if (strcmp(name, p->name) == 0) {
+            return p;
+        }
+    }
+
+    return NULL;    
+}
+
+static ck_rv_t load_provider(struct provider **provider, const char *name, 
+                             void *reserved)
+{
+    CK_C_GetFunctionList gfl;
+    struct provider *prov;
+    struct ck_function_list *fns;
+    struct ck_c_initialize_args args;
+    void *h;
+    ck_rv_t rv;
+    char *cname = NULL;
+
+    if (pthread_mutex_lock(&provider_mutex) != 0) {
+        return CKR_CANT_LOCK;
+    }
+
+    cname = pkcs11ize(name);
+    if (cname == NULL) {
+        rv = CKR_HOST_MEMORY;
+        goto fail_locked;
+    }
+
+fprintf(stderr, "found name: %s\n", cname);
+
+    prov = find_provider(cname);
+    if (prov) {
+        prov->refcount++;
+        *provider = prov;
+        free(cname);
+        pthread_mutex_unlock(&provider_mutex);
+        return CKR_OK;
+    }
+
+    h = find_pkcs11_module(name, &gfl);
+    if (!h) {
+        rv = CKR_GENERAL_ERROR;
+        goto fail_ndup;
+    }
+    
+    rv = gfl(&fns);
+    if (rv != CKR_OK) {
+        goto fail_dso;
+    }
+    
+    *provider = prov = malloc(sizeof *prov);
+    if (prov == NULL) {
+        rv = CKR_HOST_MEMORY;
+        goto fail_dso;
+    }
+    
+    if (pthread_mutex_init(&prov->mutex, NULL)) {
+        rv = CKR_GENERAL_ERROR;
+        goto fail_ctx;
+    }
+
+    prov->name = cname;
+    prov->handle = h;
+    prov->fns = fns;
+    prov->refcount = 1;
+
+    /* Require OS locking, the only sane option. */
+    memset(&args, 0, sizeof args);
+    args.flags = CKF_OS_LOCKING_OK;          
+    args.reserved = reserved;
+
+    rv = fns->C_Initialize(&args);
+    if (rv != CKR_OK) {
+        goto fail_ctx;
+    }
+
+    prov->next = provider_list;
+    prov->prevref = &provider_list;
+    if (prov->next) {
+        prov->next->prevref = &prov->next;
+    }
+    provider_list = prov;
+
+    pthread_mutex_unlock(&provider_mutex);
+    
+    return CKR_OK;
+fail_ctx:        
+    free(prov);
+fail_dso:
+    dlclose(h);
+fail_ndup:
+    free(cname);
+fail_locked:
+    pthread_mutex_unlock(&provider_mutex);
+    *provider = NULL;
+    return rv;
+}    
+
+static ck_rv_t load_module(pakchois_module_t **module, const char *name, 
+                           void *reserved)
+{
+    ck_rv_t rv;
+    pakchois_module_t *pm = malloc(sizeof *pm);
+
+    if (!pm) {
+        return CKR_HOST_MEMORY;
+    }
+
+    rv = load_provider(&pm->provider, name, reserved);
+    if (rv) {
+        return rv;
+    }
+    
+    *module = pm;    
+    pm->slots = NULL;
+
+    return CKR_OK;
+}    
+
+ck_rv_t pakchois_module_load(pakchois_module_t **module, const char *name)
+{
+    return load_module(module, name, NULL);
+}
+
+ck_rv_t pakchois_module_nssload(pakchois_module_t **module, 
+                                const char *name,
+                                const char *directory,
+                                const char *cert_prefix,
+                                const char *key_prefix,
+                                const char *secmod_db)
+{
+    char buf[256];
+
+    snprintf(buf, sizeof buf, 
+             "configdir='%s' certPrefix='%s' keyPrefix='%s' secmod='%s'",
+             directory, cert_prefix ? cert_prefix : "",
+             key_prefix ? key_prefix : "", 
+             secmod_db ? secmod_db : "secmod.db");
+
+    return load_module(module, name, buf);
+}
+
+/* Unreference a provider structure and destoy if, if necessary.  Must
+ * be called WIHTOUT the provider mutex held.  */
+static void provider_unref(struct provider *prov)
+{
+    assert(pthread_mutex_lock(&provider_mutex) == 0);
+
+    if (--prov->refcount == 0) {
+        prov->fns->C_Finalize(NULL);
+        dlclose(prov->handle);
+        *prov->prevref = prov->next;
+        if (prov->next) {
+            prov->next->prevref = prov->prevref;
+        }
+        free(prov->name);
+        free(prov);
+    }
+    pthread_mutex_unlock(&provider_mutex);
+}
+
+void pakchois_module_destroy(pakchois_module_t *mod)
+{
+    provider_unref(mod->provider);
+
+    while (mod->slots) {
+        struct slot *slot = mod->slots;
+        pakchois_close_all_sessions(mod, slot->id);
+        mod->slots = slot->next;
+        free(slot);
+    }
+
+    free(mod);
+}
+
+#ifdef __GNUC__
+static void pakchois_destructor(void)
+    __attribute__((destructor));
+
+static void pakchois_destructor(void)
+{
+    pthread_mutex_destroy(&provider_mutex);
+}
+#else
+#warning need destructor support
+#endif
+
+ck_rv_t pakchois_get_info(pakchois_module_t *mod, struct ck_info *info)
+{
+    return CALL(GetInfo, (info));
+}
+
+ck_rv_t pakchois_get_slot_list(pakchois_module_t *mod,
+                              unsigned char token_present,
+                              ck_slot_id_t *slot_list,
+                              unsigned long *count)
+{
+    return CALL(GetSlotList, (token_present, slot_list, count));
+}
+
+ck_rv_t pakchois_get_slot_info(pakchois_module_t *mod,
+                              ck_slot_id_t slot_id,
+                              struct ck_slot_info *info)
+{
+    return CALL(GetSlotInfo, (slot_id, info));
+}
+
+ck_rv_t pakchois_get_token_info(pakchois_module_t *mod,
+                               ck_slot_id_t slot_id,
+                               struct ck_token_info *info)
+{
+    return CALL(GetTokenInfo, (slot_id, info));
+}
+
+ck_rv_t pakchois_wait_for_slot_event(pakchois_module_t *mod,
+                                    ck_flags_t flags, ck_slot_id_t *slot,
+                                    void *reserved)
+{
+    ck_rv_t rv;
+
+    if (pthread_mutex_lock(&mod->provider->mutex)) {
+        return CKR_CANT_LOCK;
+    }
+        
+    rv = CALL(WaitForSlotEvent, (flags, slot, reserved));
+    pthread_mutex_unlock(&mod->provider->mutex);
+    return rv;
+}
+
+ck_rv_t pakchois_get_mechanism_list(pakchois_module_t *mod,
+                                   ck_slot_id_t slot_id,
+                                   ck_mechanism_type_t *mechanism_list,
+                                   unsigned long *count)
+{
+    return CALL(GetMechanismList, (slot_id, mechanism_list, count));
+}
+
+ck_rv_t pakchois_get_mechanism_info(pakchois_module_t *mod,
+                                   ck_slot_id_t slot_id,
+                                   ck_mechanism_type_t type,
+                                   struct ck_mechanism_info *info)
+{
+    return CALL(GetMechanismInfo, (slot_id, type, info));
+}
+
+ck_rv_t pakchois_init_token(pakchois_module_t *mod,
+                           ck_slot_id_t slot_id, unsigned char *pin,
+                           unsigned long pin_len, unsigned char *label)
+{
+    return CALL(InitToken, (slot_id, pin, pin_len, label));
+}
+
+ck_rv_t pakchois_init_pin(pakchois_session_t *sess, unsigned char *pin,
+                         unsigned long pin_len)
+{
+    return CALLS2(InitPIN, pin, pin_len);
+}
+
+ck_rv_t pakchois_set_pin(pakchois_session_t *sess, unsigned char *old_pin,
+                        unsigned long old_len, unsigned char *new_pin,
+                        unsigned long new_len)
+{
+    return CALLS4(SetPIN, old_pin, old_len, new_pin, new_len);
+}
+
+static ck_rv_t notify_thunk(ck_session_handle_t session,
+                            ck_notification_t event, void *application)
+{
+    pakchois_session_t *sess = application;
+
+    return sess->notify(sess, event, sess->notify_data);
+}
+
+static struct slot *find_slot(pakchois_module_t *mod, ck_slot_id_t id)
+{
+    struct slot *slot;
+
+    for (slot = mod->slots; slot; slot = slot->next)
+        if (slot->id == id)
+            return slot;
+
+    return NULL;
+}
+
+static struct slot *find_or_create_slot(pakchois_module_t *mod,
+                                        ck_slot_id_t id)
+{
+    struct slot *slot = find_slot(mod, id);
+
+    if (slot) {
+        return slot;
+    }
+
+    slot = malloc(sizeof *slot);
+    if (!slot) {
+        return NULL;
+    }
+    
+    slot->id = id;
+    slot->sessions = NULL;
+    slot->next = mod->slots;
+    mod->slots = slot;
+
+    return slot;
+}
+
+static ck_rv_t insert_session(pakchois_module_t *mod,
+                              pakchois_session_t *session,
+                              ck_slot_id_t id)
+{
+    struct slot *slot = find_or_create_slot(mod, id);
+    
+    if (!slot) {
+        return CKR_HOST_MEMORY;
+    }
+
+    session->prevref = &slot->sessions;
+    session->next = slot->sessions;
+    if (session->next) {
+        session->next->prevref = session->prevref;
+    }
+    slot->sessions = session;
+
+    return CKR_OK;
+}
+
+ck_rv_t pakchois_open_session(pakchois_module_t *mod,
+                             ck_slot_id_t slot_id, ck_flags_t flags,
+                             void *application, pakchois_notify_t notify,
+                             pakchois_session_t **session)
+{
+    ck_session_handle_t sh;
+    pakchois_session_t *sess;
+    ck_rv_t rv;
+
+    sess = calloc(1, sizeof *sess);
+    if (sess == NULL) {
+        return CKR_HOST_MEMORY;
+    }    
+
+    rv = CALL(OpenSession, (slot_id, flags, sess, notify_thunk, &sh));
+    if (rv != CKR_OK) {
+        free(sess);
+        return rv;
+    }
+    
+    *session = sess;
+    sess->module = mod;
+    sess->id = sh;
+
+    return insert_session(mod, sess, slot_id);
+}
+
+ck_rv_t pakchois_close_session(pakchois_session_t *sess)
+{
+    /* PKCS#11 says that all bets are off on failure, so destroy the
+     * session object and just return the error code. */
+    ck_rv_t rv = CALLS(CloseSession, (sess->id));
+    *sess->prevref = sess->next;
+    if (sess->next) {
+        sess->next->prevref = sess->prevref;
+    }
+    free(sess);
+    return rv;
+}
+
+ck_rv_t pakchois_close_all_sessions(pakchois_module_t *mod,
+                                   ck_slot_id_t slot_id)
+{
+    struct slot *slot;
+    ck_rv_t rv, frv = CKR_OK;
+
+    slot = find_slot(mod, slot_id);
+
+    if (!slot) {
+        return CKR_SLOT_ID_INVALID;
+    }
+
+    while (slot->sessions) {
+        rv = pakchois_close_session(slot->sessions);
+        if (rv != CKR_OK) {
+            frv = rv;
+        }
+    }
+
+    return frv;
+}
+
+ck_rv_t pakchois_get_session_info(pakchois_session_t *sess,
+                                 struct ck_session_info *info)
+{
+    return CALLS1(GetSessionInfo, info);
+}
+
+ck_rv_t pakchois_get_operation_state(pakchois_session_t *sess,
+                                    unsigned char *operation_state,
+                                    unsigned long *operation_state_len)
+{
+    return CALLS2(GetOperationState, operation_state, 
+                  operation_state_len);
+}
+
+ck_rv_t pakchois_set_operation_state(pakchois_session_t *sess,
+                                    unsigned char *operation_state,
+                                    unsigned long operation_state_len,
+                                    ck_object_handle_t encryption_key,
+                                    ck_object_handle_t authentiation_key)
+{
+    return CALLS4(SetOperationState, operation_state, operation_state_len,
+                  encryption_key, authentiation_key);
+}
+
+ck_rv_t pakchois_login(pakchois_session_t *sess, ck_user_type_t user_type,
+                      unsigned char *pin, unsigned long pin_len)
+{
+    return CALLS3(Login, user_type, pin, pin_len);
+}
+
+ck_rv_t pakchois_logout(pakchois_session_t *sess)
+{
+    return CALLS(Logout, (sess->id));
+}
+
+ck_rv_t pakchois_create_object(pakchois_session_t *sess,
+                              struct ck_attribute *templ,
+                              unsigned long count,
+                              ck_object_handle_t *object)
+{
+    return CALLS3(CreateObject, templ, count, object);
+}
+
+ck_rv_t pakchois_copy_object(pakchois_session_t *sess,
+                            ck_object_handle_t object,
+                            struct ck_attribute *templ, unsigned long count,
+                            ck_object_handle_t *new_object)
+{
+    return CALLS4(CopyObject, object, templ, count, new_object);
+}
+
+ck_rv_t pakchois_destroy_object(pakchois_session_t *sess,
+                               ck_object_handle_t object)
+{
+    return CALLS1(DestroyObject, object);
+}    
+
+ck_rv_t pakchois_get_object_size(pakchois_session_t *sess,
+                                ck_object_handle_t object,
+                                unsigned long *size)
+{
+    return CALLS2(GetObjectSize, object, size);
+}
+
+ck_rv_t pakchois_get_attribute_value(pakchois_session_t *sess,
+                                    ck_object_handle_t object,
+                                    struct ck_attribute *templ,
+                                    unsigned long count)
+{
+    return CALLS3(GetAttributeValue, object, templ, count);
+}
+
+ck_rv_t pakchois_set_attribute_value(pakchois_session_t *sess,
+                                    ck_object_handle_t object,
+                                    struct ck_attribute *templ,
+                                    unsigned long count)
+{
+    return CALLS3(SetAttributeValue, object, templ, count);
+}
+
+ck_rv_t pakchois_find_objects_init(pakchois_session_t *sess,
+                                  struct ck_attribute *templ,
+                                  unsigned long count)
+{
+    return CALLS2(FindObjectsInit, templ, count);
+}
+
+ck_rv_t pakchois_find_objects(pakchois_session_t *sess,
+                             ck_object_handle_t *object,
+                             unsigned long max_object_count,
+                             unsigned long *object_count)
+{
+    return CALLS3(FindObjects, object, max_object_count, object_count);
+}
+
+ck_rv_t pakchois_find_objects_final(pakchois_session_t *sess)
+{
+    return CALLS(FindObjectsFinal, (sess->id));
+}
+
+ck_rv_t pakchois_encrypt_init(pakchois_session_t *sess,
+                             struct ck_mechanism *mechanism,
+                             ck_object_handle_t key)
+{
+    return CALLS2(EncryptInit, mechanism, key);
+}
+
+ck_rv_t pakchois_encrypt(pakchois_session_t *sess,
+                        unsigned char *data, unsigned long data_len,
+                        unsigned char *encrypted_data,
+                        unsigned long *encrypted_data_len)
+{
+    return CALLS4(Encrypt, data, data_len, 
+                  encrypted_data, encrypted_data_len);
+}
+
+ck_rv_t pakchois_encrypt_update(pakchois_session_t *sess,
+                               unsigned char *part, unsigned long part_len,
+                               unsigned char *encrypted_part,
+                               unsigned long *encrypted_part_len)
+{
+    return CALLS4(EncryptUpdate, part, part_len, 
+                  encrypted_part, encrypted_part_len);
+}
+
+ck_rv_t pakchois_encrypt_final(pakchois_session_t *sess,
+                              unsigned char *last_encrypted_part,
+                              unsigned long *last_encrypted_part_len)
+{
+    return CALLS2(EncryptFinal, last_encrypted_part, last_encrypted_part_len);
+}
+
+ck_rv_t pakchois_decrypt_init(pakchois_session_t *sess,
+                             struct ck_mechanism *mechanism,
+                             ck_object_handle_t key)
+{
+    return CALLS2(DecryptInit, mechanism, key);
+}
+
+ck_rv_t pakchois_decrypt(pakchois_session_t *sess,
+                        unsigned char *encrypted_data,
+                        unsigned long encrypted_data_len,
+                        unsigned char *data, unsigned long *data_len)
+{
+    return CALLS4(Decrypt, encrypted_data, encrypted_data_len, data, data_len);
+}
+
+ck_rv_t pakchois_decrypt_update(pakchois_session_t *sess,
+                               unsigned char *encrypted_part,
+                               unsigned long encrypted_part_len,
+                               unsigned char *part, unsigned long *part_len)
+{
+    return CALLS4(DecryptUpdate, encrypted_part, encrypted_part_len,
+                  part, part_len);
+}
+
+ck_rv_t pakchois_decrypt_final(pakchois_session_t *sess,
+                              unsigned char *last_part,
+                              unsigned long *last_part_len)
+{
+    return CALLS2(DecryptFinal, last_part, last_part_len);
+}
+
+ck_rv_t pakchois_digest_init(pakchois_session_t *sess,
+                            struct ck_mechanism *mechanism)
+{
+    return CALLS1(DigestInit, mechanism);
+}
+
+ck_rv_t pakchois_digest(pakchois_session_t *sess, unsigned char *data,
+                       unsigned long data_len, unsigned char *digest,
+                       unsigned long *digest_len)
+{
+    return CALLS4(Digest, data, data_len, digest, digest_len);
+}
+
+ck_rv_t pakchois_digest_update(pakchois_session_t *sess,
+                              unsigned char *part, unsigned long part_len)
+{
+    return CALLS2(DigestUpdate, part, part_len);
+}
+
+ck_rv_t pakchois_digest_key(pakchois_session_t *sess,
+                           ck_object_handle_t key)
+{
+    return CALLS1(DigestKey, key);
+}
+
+ck_rv_t pakchois_digest_final(pakchois_session_t *sess,
+                             unsigned char *digest,
+                             unsigned long *digest_len)
+{
+    return CALLS2(DigestFinal, digest, digest_len);
+}
+
+ck_rv_t pakchois_sign_init(pakchois_session_t *sess,
+                          struct ck_mechanism *mechanism,
+                          ck_object_handle_t key)
+{
+    return CALLS2(SignInit, mechanism, key);
+}
+
+ck_rv_t pakchois_sign(pakchois_session_t *sess, unsigned char *data,
+                     unsigned long data_len, unsigned char *signature,
+                     unsigned long *signature_len)
+{
+    return CALLS4(Sign, data, data_len, signature, signature_len);
+}
+
+ck_rv_t pakchois_sign_update(pakchois_session_t *sess,
+                            unsigned char *part, unsigned long part_len)
+{
+    return CALLS2(SignUpdate, part, part_len);
+}
+
+ck_rv_t pakchois_sign_final(pakchois_session_t *sess,
+                           unsigned char *signature,
+                           unsigned long *signature_len)
+{
+    return CALLS2(SignFinal, signature, signature_len);
+}
+
+ck_rv_t pakchois_sign_recover_init(pakchois_session_t *sess,
+                                  struct ck_mechanism *mechanism,
+                                  ck_object_handle_t key)
+{
+    return CALLS2(SignRecoverInit, mechanism, key);
+}
+
+ck_rv_t pakchois_sign_recover(pakchois_session_t *sess,
+                             unsigned char *data, unsigned long data_len,
+                             unsigned char *signature,
+                             unsigned long *signature_len)
+{
+    return CALLS4(SignRecover, data, data_len, signature, signature_len);
+}
+
+ck_rv_t pakchois_verify_init(pakchois_session_t *sess,
+                            struct ck_mechanism *mechanism,
+                            ck_object_handle_t key)
+{
+    return CALLS2(VerifyInit, mechanism, key);
+}
+
+ck_rv_t pakchois_verify(pakchois_session_t *sess, unsigned char *data,
+                       unsigned long data_len, unsigned char *signature,
+                       unsigned long signature_len)
+{
+    return CALLS4(Verify, data, data_len, signature, signature_len);
+}
+
+ck_rv_t pakchois_verify_update(pakchois_session_t *sess,
+                              unsigned char *part, unsigned long part_len)
+{
+    return CALLS2(VerifyUpdate, part, part_len);
+}
+
+ck_rv_t pakchois_verify_final(pakchois_session_t *sess,
+                             unsigned char *signature,
+                             unsigned long signature_len)
+{
+    return CALLS2(VerifyFinal, signature, signature_len);
+}
+
+ck_rv_t pakchois_verify_recover_init(pakchois_session_t *sess,
+                                    struct ck_mechanism *mechanism,
+                                    ck_object_handle_t key)
+{
+    return CALLS2(VerifyRecoverInit, mechanism, key);
+}
+
+ck_rv_t pakchois_verify_recover(pakchois_session_t *sess,
+                               unsigned char *signature,
+                               unsigned long signature_len,
+                               unsigned char *data, unsigned long *data_len)
+{
+    return CALLS4(VerifyRecover, signature, signature_len, data, data_len);
+}
+
+ck_rv_t pakchois_digest_encrypt_update(pakchois_session_t *sess,
+                                      unsigned char *part,
+                                      unsigned long part_len,
+                                      unsigned char *encrypted_part,
+                                      unsigned long *encrypted_part_len)
+{
+    return CALLS4(DigestEncryptUpdate, part, part_len,
+                  encrypted_part, encrypted_part_len);
+}
+
+ck_rv_t pakchois_decrypt_digest_update(pakchois_session_t *sess,
+                                      unsigned char *encrypted_part,
+                                      unsigned long encrypted_part_len,
+                                      unsigned char *part,
+                                      unsigned long *part_len)
+{
+    return CALLS4(DecryptDigestUpdate, encrypted_part, encrypted_part_len,
+                  part, part_len);
+}
+
+ck_rv_t pakchois_sign_encrypt_update(pakchois_session_t *sess,
+                                    unsigned char *part,
+                                    unsigned long part_len,
+                                    unsigned char *encrypted_part,
+                                    unsigned long *encrypted_part_len)
+{
+    return CALLS4(SignEncryptUpdate, part, part_len,
+                  encrypted_part, encrypted_part_len);
+}
+
+ck_rv_t pakchois_decrypt_verify_update(pakchois_session_t *sess,
+                                      unsigned char *encrypted_part,
+                                      unsigned long encrypted_part_len,
+                                      unsigned char *part,
+                                      unsigned long *part_len)
+{
+    return CALLS4(DecryptVerifyUpdate, encrypted_part, encrypted_part_len,
+                  part, part_len);
+}
+
+ck_rv_t pakchois_generate_key(pakchois_session_t *sess,
+                             struct ck_mechanism *mechanism,
+                             struct ck_attribute *templ,
+                             unsigned long count, ck_object_handle_t *key)
+{
+    return CALLS4(GenerateKey, mechanism, templ, count, key);
+}
+
+ck_rv_t pakchois_generate_key_pair(pakchois_session_t *sess,
+                                  struct ck_mechanism *mechanism,
+                                  struct ck_attribute *public_key_template,
+                                  unsigned long public_key_attribute_count,
+                                  struct ck_attribute *private_key_template,
+                                  unsigned long private_key_attribute_count,
+                                  ck_object_handle_t *public_key,
+                                  ck_object_handle_t *private_key)
+{
+    return CALLS7(GenerateKeyPair, mechanism,
+                  public_key_template, public_key_attribute_count,
+                  private_key_template, private_key_attribute_count,
+                  public_key, private_key);
+}
+
+ck_rv_t pakchois_wrap_key(pakchois_session_t *sess,
+                         struct ck_mechanism *mechanism,
+                         ck_object_handle_t wrapping_key,
+                         ck_object_handle_t key, unsigned char *wrapped_key,
+                         unsigned long *wrapped_key_len)
+{
+    return CALLS5(WrapKey, mechanism, wrapping_key,
+                  key, wrapped_key, wrapped_key_len);
+}    
+
+ck_rv_t pakchois_unwrap_key(pakchois_session_t *sess,
+                           struct ck_mechanism *mechanism,
+                           ck_object_handle_t unwrapping_key,
+                           unsigned char *wrapped_key,
+                           unsigned long wrapped_key_len,
+                           struct ck_attribute *templ,
+                           unsigned long attribute_count,
+                           ck_object_handle_t *key)
+{
+    return CALLS7(UnwrapKey, mechanism, unwrapping_key, 
+                  wrapped_key, wrapped_key_len, templ, attribute_count,
+                  key);
+}
+
+ck_rv_t pakchois_derive_key(pakchois_session_t *sess,
+                           struct ck_mechanism *mechanism,
+                           ck_object_handle_t base_key,
+                           struct ck_attribute *templ,
+                           unsigned long attribute_count,
+                           ck_object_handle_t *key)
+{
+    return CALLS5(DeriveKey, mechanism, base_key, templ, attribute_count, key);
+}
+
+
+ck_rv_t pakchois_seed_random(pakchois_session_t *sess,
+                            unsigned char *seed, unsigned long seed_len)
+{
+    return CALLS2(SeedRandom, seed, seed_len);
+}
+
+ck_rv_t pakchois_generate_random(pakchois_session_t *sess,
+                                unsigned char *random_data,
+                                unsigned long random_len)
+{
+    return CALLS2(GenerateRandom, random_data, random_len);
+}
diff --git a/lib/pakchois/pakchois.h b/lib/pakchois/pakchois.h
new file mode 100644 (file)
index 0000000..76999ef
--- /dev/null
@@ -0,0 +1,361 @@
+/* 
+   pakchois PKCS#11 interface
+   Copyright (C) 2008, Joe Orton <joe@manyfish.co.uk>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with this library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA
+
+*/
+
+/*
+  This interface is directly derived from the scute.org PKCS#11
+  cryptoki interface, which is:
+
+   Copyright 2006, 2007 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+   PURPOSE.
+*/
+
+#ifndef PAKCHOIS_H
+#define PAKCHOIS_H
+
+#define CRYPTOKI_GNU
+
+#include "pakchois11.h"
+
+/* API version: major is bumped for any backwards-incompatible
+ * changes. minor is bumped for any new interfaces.  Note that the API
+ * is versioned independent of the project release version.  */
+#define PAKCHOIS_API_MAJOR (0)
+#define PAKCHOIS_API_MINOR (2)
+
+/* API version history (note that API versions do not map directly to
+   the project version!):
+
+   0.1: Initial release
+   0.2: Addition of pakchois_error()
+        Concurrent access guarantee added for pakchois_module_load()
+        Thread-safety guarantee added for pakchois_wait_for_slot_event()
+*/
+
+typedef struct pakchois_module_s pakchois_module_t;
+typedef struct pakchois_session_s pakchois_session_t;
+
+/* Load a PKCS#11 module by name (for example "opensc" or
+ * "gnome-keyring").  Returns CKR_OK on success.  Any module of given
+ * name may be safely loaded multiple times within an application; the
+ * underlying PKCS#11 provider will be loaded only once. */
+ck_rv_t pakchois_module_load(pakchois_module_t **module, const char *name);
+
+/* Load an NSS "softokn" which violates the PKCS#11 standard in
+ * initialization, with given name (e.g. "softokn3").  The directory
+ * in which the NSS database resides must be specified; the other
+ * arguments may be NULL to use defaults. Returns CKR_OK on
+ * success. */
+ck_rv_t pakchois_module_nssload(pakchois_module_t **module, 
+                                const char *name,
+                                const char *directory,
+                                const char *cert_prefix,
+                                const char *key_prefix,
+                                const char *secmod_db);
+
+/* Destroy a PKCS#11 module. */
+void pakchois_module_destroy(pakchois_module_t *module);
+
+/* Return the error string corresponding to the given return value.
+ * Never returns NULL.  */
+const char *pakchois_error(ck_rv_t rv);
+
+/* All following interfaces model the PKCS#11 equivalents, without the
+   camel-cased naming convention.  The PKCS#11 specification has
+   detailed interface descriptions:
+   
+      http://www.rsa.com/rsalabs/node.asp?id=2133
+
+   The differences between this interface and PKCS#11 are:
+   
+   1. some interfaces take a module pointer as first argument
+
+   2. session handlers are represented as opaque objects
+
+   3. the notify callback type has changed accordingly
+
+   4. the C_Initialize, C_Finalize, and C_GetFunctionList interfaces
+   are not exposed (these are called internally by
+   pakchois_module_load and pakchois_module_destroy)
+
+   5. pakchois_wait_for_slot_event() is thread-safe against other
+   callers of pakchois_wait_for_slot_event(); the call to the
+   underlying provider's WaitForSlotEvent function is protected by a
+   mutex.
+
+   6. pakchois_close_all_sessions() only closes sessions associated
+   with the given module instance; any sessions opened by other users
+   of the underlying provider are unaffected.
+
+   If a module object is used concurrently from separate threads,
+   undefined behaviour results.  If a session object is used
+   concurrently from separate threads, undefined behavioure results.
+
+*/
+ck_rv_t pakchois_get_info(pakchois_module_t *module, struct ck_info *info);
+
+ck_rv_t pakchois_get_slot_list(pakchois_module_t *module,
+                              unsigned char token_present,
+                              ck_slot_id_t *slot_list,
+                              unsigned long *count);
+
+ck_rv_t pakchois_get_slot_info(pakchois_module_t *module,
+                              ck_slot_id_t slot_id,
+                              struct ck_slot_info *info);
+
+ck_rv_t pakchois_get_token_info(pakchois_module_t *module,
+                               ck_slot_id_t slot_id,
+                               struct ck_token_info *info);
+
+ck_rv_t pakchois_wait_for_slot_event(pakchois_module_t *module,
+                                    ck_flags_t flags, ck_slot_id_t *slot,
+                                    void *reserved);
+
+ck_rv_t pakchois_get_mechanism_list(pakchois_module_t *module,
+                                   ck_slot_id_t slot_id,
+                                   ck_mechanism_type_t *mechanism_list,
+                                   unsigned long *count);
+
+ck_rv_t pakchois_get_mechanism_info(pakchois_module_t *module,
+                                   ck_slot_id_t slot_id,
+                                   ck_mechanism_type_t type,
+                                   struct ck_mechanism_info *info);
+
+ck_rv_t pakchois_init_token(pakchois_module_t *module,
+                           ck_slot_id_t slot_id, unsigned char *pin,
+                           unsigned long pin_len, unsigned char *label);
+
+ck_rv_t pakchois_init_pin(pakchois_session_t *session, unsigned char *pin,
+                         unsigned long pin_len);
+
+ck_rv_t pakchois_set_pin(pakchois_session_t *session, unsigned char *old_pin,
+                        unsigned long old_len, unsigned char *new_pin,
+                        unsigned long new_len);
+
+typedef ck_rv_t (*pakchois_notify_t) (pakchois_session_t *sess,
+                                      ck_notification_t event,
+                                      void *application);
+
+ck_rv_t pakchois_open_session(pakchois_module_t *module,
+                             ck_slot_id_t slot_id, ck_flags_t flags,
+                             void *application, pakchois_notify_t notify,
+                             pakchois_session_t **session);
+
+ck_rv_t pakchois_close_session(pakchois_session_t *session);
+
+ck_rv_t pakchois_close_all_sessions(pakchois_module_t *module,
+                                   ck_slot_id_t slot_id);
+
+ck_rv_t pakchois_get_session_info(pakchois_session_t *session,
+                                 struct ck_session_info *info);
+ck_rv_t pakchois_get_operation_state(pakchois_session_t *session,
+                                    unsigned char *operation_state,
+                                    unsigned long *operation_state_len);
+ck_rv_t pakchois_set_operation_state(pakchois_session_t *session,
+                                    unsigned char *operation_state,
+                                    unsigned long operation_state_len,
+                                    ck_object_handle_t encryption_key,
+                                    ck_object_handle_t authentiation_key);
+
+ck_rv_t pakchois_login(pakchois_session_t *session, ck_user_type_t user_type,
+                      unsigned char *pin, unsigned long pin_len);
+ck_rv_t pakchois_logout(pakchois_session_t *session);
+
+ck_rv_t pakchois_create_object(pakchois_session_t *session,
+                              struct ck_attribute *templ,
+                              unsigned long count,
+                              ck_object_handle_t *object);
+ck_rv_t pakchois_copy_object(pakchois_session_t *session,
+                            ck_object_handle_t object,
+                            struct ck_attribute *templ, unsigned long count,
+                            ck_object_handle_t *new_object);
+ck_rv_t pakchois_destroy_object(pakchois_session_t *session,
+                               ck_object_handle_t object);
+ck_rv_t pakchois_get_object_size(pakchois_session_t *session,
+                                ck_object_handle_t object,
+                                unsigned long *size);
+
+ck_rv_t pakchois_get_attribute_value(pakchois_session_t *session,
+                                    ck_object_handle_t object,
+                                    struct ck_attribute *templ,
+                                    unsigned long count);
+ck_rv_t pakchois_set_attribute_value(pakchois_session_t *session,
+                                    ck_object_handle_t object,
+                                    struct ck_attribute *templ,
+                                    unsigned long count);
+ck_rv_t pakchois_find_objects_init(pakchois_session_t *session,
+                                  struct ck_attribute *templ,
+                                  unsigned long count);
+ck_rv_t pakchois_find_objects(pakchois_session_t *session,
+                             ck_object_handle_t *object,
+                             unsigned long max_object_count,
+                             unsigned long *object_count);
+ck_rv_t pakchois_find_objects_final(pakchois_session_t *session);
+
+ck_rv_t pakchois_encrypt_init(pakchois_session_t *session,
+                             struct ck_mechanism *mechanism,
+                             ck_object_handle_t key);
+ck_rv_t pakchois_encrypt(pakchois_session_t *session,
+                        unsigned char *data, unsigned long data_len,
+                        unsigned char *encrypted_data,
+                        unsigned long *encrypted_data_len);
+ck_rv_t pakchois_encrypt_update(pakchois_session_t *session,
+                               unsigned char *part, unsigned long part_len,
+                               unsigned char *encrypted_part,
+                               unsigned long *encrypted_part_len);
+ck_rv_t pakchois_encrypt_final(pakchois_session_t *session,
+                              unsigned char *last_encrypted_part,
+                              unsigned long *last_encrypted_part_len);
+
+ck_rv_t pakchois_decrypt_init(pakchois_session_t *session,
+                             struct ck_mechanism *mechanism,
+                             ck_object_handle_t key);
+ck_rv_t pakchois_decrypt(pakchois_session_t *session,
+                        unsigned char *encrypted_data,
+                        unsigned long encrypted_data_len,
+                        unsigned char *data, unsigned long *data_len);
+ck_rv_t pakchois_decrypt_update(pakchois_session_t *session,
+                               unsigned char *encrypted_part,
+                               unsigned long encrypted_part_len,
+                               unsigned char *part, unsigned long *part_len);
+ck_rv_t pakchois_decrypt_final(pakchois_session_t *session,
+                              unsigned char *last_part,
+                              unsigned long *last_part_len);
+ck_rv_t pakchois_digest_init(pakchois_session_t *session,
+                            struct ck_mechanism *mechanism);
+ck_rv_t pakchois_digest(pakchois_session_t *session, unsigned char *data,
+                       unsigned long data_len, unsigned char *digest,
+                       unsigned long *digest_len);
+ck_rv_t pakchois_digest_update(pakchois_session_t *session,
+                              unsigned char *part, unsigned long part_len);
+ck_rv_t pakchois_digest_key(pakchois_session_t *session,
+                           ck_object_handle_t key);
+ck_rv_t pakchois_digest_final(pakchois_session_t *session,
+                             unsigned char *digest,
+                             unsigned long *digest_len);
+
+ck_rv_t pakchois_sign_init(pakchois_session_t *session,
+                          struct ck_mechanism *mechanism,
+                          ck_object_handle_t key);
+ck_rv_t pakchois_sign(pakchois_session_t *session, unsigned char *data,
+                     unsigned long data_len, unsigned char *signature,
+                     unsigned long *signature_len);
+ck_rv_t pakchois_sign_update(pakchois_session_t *session,
+                            unsigned char *part, unsigned long part_len);
+ck_rv_t pakchois_sign_final(pakchois_session_t *session,
+                           unsigned char *signature,
+                           unsigned long *signature_len);
+ck_rv_t pakchois_sign_recover_init(pakchois_session_t *session,
+                                  struct ck_mechanism *mechanism,
+                                  ck_object_handle_t key);
+ck_rv_t pakchois_sign_recover(pakchois_session_t *session,
+                             unsigned char *data, unsigned long data_len,
+                             unsigned char *signature,
+                             unsigned long *signature_len);
+
+ck_rv_t pakchois_verify_init(pakchois_session_t *session,
+                            struct ck_mechanism *mechanism,
+                            ck_object_handle_t key);
+ck_rv_t pakchois_verify(pakchois_session_t *session, unsigned char *data,
+                       unsigned long data_len, unsigned char *signature,
+                       unsigned long signature_len);
+ck_rv_t pakchois_verify_update(pakchois_session_t *session,
+                              unsigned char *part, unsigned long part_len);
+ck_rv_t pakchois_verify_final(pakchois_session_t *session,
+                             unsigned char *signature,
+                             unsigned long signature_len);
+ck_rv_t pakchois_verify_recover_init(pakchois_session_t *session,
+                                    struct ck_mechanism *mechanism,
+                                    ck_object_handle_t key);
+ck_rv_t pakchois_verify_recover(pakchois_session_t *session,
+                               unsigned char *signature,
+                               unsigned long signature_len,
+                               unsigned char *data, unsigned long *data_len);
+
+ck_rv_t pakchois_digest_encrypt_update(pakchois_session_t *session,
+                                      unsigned char *part,
+                                      unsigned long part_len,
+                                      unsigned char *encrypted_part,
+                                      unsigned long *encrypted_part_len);
+ck_rv_t pakchois_decrypt_digest_update(pakchois_session_t *session,
+                                      unsigned char *encrypted_part,
+                                      unsigned long encrypted_part_len,
+                                      unsigned char *part,
+                                      unsigned long *part_len);
+ck_rv_t pakchois_sign_encrypt_update(pakchois_session_t *session,
+                                    unsigned char *part,
+                                    unsigned long part_len,
+                                    unsigned char *encrypted_part,
+                                    unsigned long *encrypted_part_len);
+ck_rv_t pakchois_decrypt_verify_update(pakchois_session_t *session,
+                                      unsigned char *encrypted_part,
+                                      unsigned long encrypted_part_len,
+                                      unsigned char *part,
+                                      unsigned long *part_len);
+
+ck_rv_t pakchois_generate_key(pakchois_session_t *session,
+                             struct ck_mechanism *mechanism,
+                             struct ck_attribute *templ,
+                             unsigned long count, ck_object_handle_t *key);
+ck_rv_t pakchois_generate_key_pair(pakchois_session_t *session,
+                                  struct ck_mechanism *mechanism,
+                                  struct ck_attribute *public_key_template,
+                                  unsigned long public_key_attribute_count,
+                                  struct ck_attribute *private_key_template,
+                                  unsigned long private_key_attribute_count,
+                                  ck_object_handle_t *public_key,
+                                  ck_object_handle_t *private_key);
+
+ck_rv_t pakchois_wrap_key(pakchois_session_t *session,
+                         struct ck_mechanism *mechanism,
+                         ck_object_handle_t wrapping_key,
+                         ck_object_handle_t key, unsigned char *wrapped_key,
+                         unsigned long *wrapped_key_len);
+ck_rv_t pakchois_unwrap_key(pakchois_session_t *session,
+                           struct ck_mechanism *mechanism,
+                           ck_object_handle_t unwrapping_key,
+                           unsigned char *wrapped_key,
+                           unsigned long wrapped_key_len,
+                           struct ck_attribute *templ,
+                           unsigned long attribute_count,
+                           ck_object_handle_t *key);
+ck_rv_t pakchois_derive_key(pakchois_session_t *session,
+                           struct ck_mechanism *mechanism,
+                           ck_object_handle_t base_key,
+                           struct ck_attribute *templ,
+                           unsigned long attribute_count,
+                           ck_object_handle_t *key);
+
+ck_rv_t pakchois_seed_random(pakchois_session_t *session,
+                            unsigned char *seed, unsigned long seed_len);
+ck_rv_t pakchois_generate_random(pakchois_session_t *session,
+                                unsigned char *random_data,
+                                unsigned long random_len);
+
+#endif /* PAKCHOIS_H */
diff --git a/lib/pakchois/pakchois11.h b/lib/pakchois/pakchois11.h
new file mode 100644 (file)
index 0000000..2e6a1e3
--- /dev/null
@@ -0,0 +1,1357 @@
+/* pkcs11.h
+   Copyright 2006, 2007 g10 Code GmbH
+   Copyright 2006 Andreas Jellinghaus
+
+   This file is free software; as a special exception the author gives
+   unlimited permission to copy and/or distribute it, with or without
+   modifications, as long as this notice is preserved.
+
+   This file is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY, to the extent permitted by law; without even
+   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+   PURPOSE.  */
+
+/* Please submit changes back to the Scute project at
+   http://www.scute.org/ (or send them to marcus@g10code.com), so that
+   they can be picked up by other projects from there as well.  */
+
+/* This file is a modified implementation of the PKCS #11 standard by
+   RSA Security Inc.  It is mostly a drop-in replacement, with the
+   following change:
+
+   This header file does not require any macro definitions by the user
+   (like CK_DEFINE_FUNCTION etc).  In fact, it defines those macros
+   for you (if useful, some are missing, let me know if you need
+   more).
+
+   There is an additional API available that does comply better to the
+   GNU coding standard.  It can be switched on by defining
+   CRYPTOKI_GNU before including this header file.  For this, the
+   following changes are made to the specification:
+
+   All structure types are changed to a "struct ck_foo" where CK_FOO
+   is the type name in PKCS #11.
+
+   All non-structure types are changed to ck_foo_t where CK_FOO is the
+   lowercase version of the type name in PKCS #11.  The basic types
+   (CK_ULONG et al.) are removed without substitute.
+
+   All members of structures are modified in the following way: Type
+   indication prefixes are removed, and underscore characters are
+   inserted before words.  Then the result is lowercased.
+
+   Note that function names are still in the original case, as they
+   need for ABI compatibility.
+
+   CK_FALSE, CK_TRUE and NULL_PTR are removed without substitute.  Use
+   <stdbool.h>.
+
+   If CRYPTOKI_COMPAT is defined before including this header file,
+   then none of the API changes above take place, and the API is the
+   one defined by the PKCS #11 standard.  */
+
+#ifndef PKCS11_H
+#define PKCS11_H 1
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The version of cryptoki we implement.  The revision is changed with
+   each modification of this file.  If you do not use the "official"
+   version of this file, please consider deleting the revision macro
+   (you may use a macro with a different name to keep track of your
+   versions).  */
+#define CRYPTOKI_VERSION_MAJOR         2
+#define CRYPTOKI_VERSION_MINOR         20
+#define CRYPTOKI_VERSION_REVISION      6
+
+
+/* Compatibility interface is default, unless CRYPTOKI_GNU is
+   given.  */
+#ifndef CRYPTOKI_GNU
+#ifndef CRYPTOKI_COMPAT
+#define CRYPTOKI_COMPAT 1
+#endif
+#endif
+
+/* System dependencies.  */
+
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+
+/* There is a matching pop below.  */
+#pragma pack(push, cryptoki, 1)
+
+#ifdef CRYPTOKI_EXPORTS
+#define CK_SPEC __declspec(dllexport)
+#else
+#define CK_SPEC __declspec(dllimport)
+#endif
+
+#else
+
+#define CK_SPEC
+
+#endif
+
+\f
+#ifdef CRYPTOKI_COMPAT
+  /* If we are in compatibility mode, switch all exposed names to the
+     PKCS #11 variant.  There are corresponding #undefs below.  */
+
+#define ck_flags_t CK_FLAGS
+#define ck_version _CK_VERSION
+
+#define ck_info _CK_INFO
+#define cryptoki_version cryptokiVersion
+#define manufacturer_id manufacturerID
+#define library_description libraryDescription
+#define library_version libraryVersion
+
+#define ck_notification_t CK_NOTIFICATION
+#define ck_slot_id_t CK_SLOT_ID
+
+#define ck_slot_info _CK_SLOT_INFO
+#define slot_description slotDescription
+#define hardware_version hardwareVersion
+#define firmware_version firmwareVersion
+
+#define ck_token_info _CK_TOKEN_INFO
+#define serial_number serialNumber
+#define max_session_count ulMaxSessionCount
+#define session_count ulSessionCount
+#define max_rw_session_count ulMaxRwSessionCount
+#define rw_session_count ulRwSessionCount
+#define max_pin_len ulMaxPinLen
+#define min_pin_len ulMinPinLen
+#define total_public_memory ulTotalPublicMemory
+#define free_public_memory ulFreePublicMemory
+#define total_private_memory ulTotalPrivateMemory
+#define free_private_memory ulFreePrivateMemory
+#define utc_time utcTime
+
+#define ck_session_handle_t CK_SESSION_HANDLE
+#define ck_user_type_t CK_USER_TYPE
+#define ck_state_t CK_STATE
+
+#define ck_session_info _CK_SESSION_INFO
+#define slot_id slotID
+#define device_error ulDeviceError
+
+#define ck_object_handle_t CK_OBJECT_HANDLE
+#define ck_object_class_t CK_OBJECT_CLASS
+#define ck_hw_feature_type_t CK_HW_FEATURE_TYPE
+#define ck_key_type_t CK_KEY_TYPE
+#define ck_certificate_type_t CK_CERTIFICATE_TYPE
+#define ck_attribute_type_t CK_ATTRIBUTE_TYPE
+
+#define ck_attribute _CK_ATTRIBUTE
+#define value pValue
+#define value_len ulValueLen
+
+#define ck_date _CK_DATE
+
+#define ck_mechanism_type_t CK_MECHANISM_TYPE
+
+#define ck_mechanism _CK_MECHANISM
+#define parameter pParameter
+#define parameter_len ulParameterLen
+
+#define ck_mechanism_info _CK_MECHANISM_INFO
+#define min_key_size ulMinKeySize
+#define max_key_size ulMaxKeySize
+
+#define ck_rv_t CK_RV
+#define ck_notify_t CK_NOTIFY
+
+#define ck_function_list _CK_FUNCTION_LIST
+
+#define ck_createmutex_t CK_CREATEMUTEX
+#define ck_destroymutex_t CK_DESTROYMUTEX
+#define ck_lockmutex_t CK_LOCKMUTEX
+#define ck_unlockmutex_t CK_UNLOCKMUTEX
+
+#define ck_c_initialize_args _CK_C_INITIALIZE_ARGS
+#define create_mutex CreateMutex
+#define destroy_mutex DestroyMutex
+#define lock_mutex LockMutex
+#define unlock_mutex UnlockMutex
+#define reserved pReserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+\f
+
+typedef unsigned long ck_flags_t;
+
+struct ck_version
+{
+  unsigned char major;
+  unsigned char minor;
+};
+
+
+struct ck_info
+{
+  struct ck_version cryptoki_version;
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  unsigned char library_description[32];
+  struct ck_version library_version;
+};
+
+
+typedef unsigned long ck_notification_t;
+
+#define CKN_SURRENDER  (0)
+
+
+typedef unsigned long ck_slot_id_t;
+
+
+struct ck_slot_info
+{
+  unsigned char slot_description[64];
+  unsigned char manufacturer_id[32];
+  ck_flags_t flags;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+};
+
+
+#define CKF_TOKEN_PRESENT      (1 << 0)
+#define CKF_REMOVABLE_DEVICE   (1 << 1)
+#define CKF_HW_SLOT            (1 << 2)
+#define CKF_ARRAY_ATTRIBUTE    (1 << 30)
+
+
+struct ck_token_info
+{
+  unsigned char label[32];
+  unsigned char manufacturer_id[32];
+  unsigned char model[16];
+  unsigned char serial_number[16];
+  ck_flags_t flags;
+  unsigned long max_session_count;
+  unsigned long session_count;
+  unsigned long max_rw_session_count;
+  unsigned long rw_session_count;
+  unsigned long max_pin_len;
+  unsigned long min_pin_len;
+  unsigned long total_public_memory;
+  unsigned long free_public_memory;
+  unsigned long total_private_memory;
+  unsigned long free_private_memory;
+  struct ck_version hardware_version;
+  struct ck_version firmware_version;
+  unsigned char utc_time[16];
+};
+
+
+#define CKF_RNG                                        (1 << 0)
+#define CKF_WRITE_PROTECTED                    (1 << 1)
+#define CKF_LOGIN_REQUIRED                     (1 << 2)
+#define CKF_USER_PIN_INITIALIZED               (1 << 3)
+#define CKF_RESTORE_KEY_NOT_NEEDED             (1 << 5)
+#define CKF_CLOCK_ON_TOKEN                     (1 << 6)
+#define CKF_PROTECTED_AUTHENTICATION_PATH      (1 << 8)
+#define CKF_DUAL_CRYPTO_OPERATIONS             (1 << 9)
+#define CKF_TOKEN_INITIALIZED                  (1 << 10)
+#define CKF_SECONDARY_AUTHENTICATION           (1 << 11)
+#define CKF_USER_PIN_COUNT_LOW                 (1 << 16)
+#define CKF_USER_PIN_FINAL_TRY                 (1 << 17)
+#define CKF_USER_PIN_LOCKED                    (1 << 18)
+#define CKF_USER_PIN_TO_BE_CHANGED             (1 << 19)
+#define CKF_SO_PIN_COUNT_LOW                   (1 << 20)
+#define CKF_SO_PIN_FINAL_TRY                   (1 << 21)
+#define CKF_SO_PIN_LOCKED                      (1 << 22)
+#define CKF_SO_PIN_TO_BE_CHANGED               (1 << 23)
+
+#define CK_UNAVAILABLE_INFORMATION     ((unsigned long) -1)
+#define CK_EFFECTIVELY_INFINITE                (0)
+
+
+typedef unsigned long ck_session_handle_t;
+
+#define CK_INVALID_HANDLE      (0)
+
+
+typedef unsigned long ck_user_type_t;
+
+#define CKU_SO                 (0)
+#define CKU_USER               (1)
+#define CKU_CONTEXT_SPECIFIC   (2)
+
+
+typedef unsigned long ck_state_t;
+
+#define CKS_RO_PUBLIC_SESSION  (0)
+#define CKS_RO_USER_FUNCTIONS  (1)
+#define CKS_RW_PUBLIC_SESSION  (2)
+#define CKS_RW_USER_FUNCTIONS  (3)
+#define CKS_RW_SO_FUNCTIONS    (4)
+
+
+struct ck_session_info
+{
+  ck_slot_id_t slot_id;
+  ck_state_t state;
+  ck_flags_t flags;
+  unsigned long device_error;
+};
+
+#define CKF_RW_SESSION         (1 << 1)
+#define CKF_SERIAL_SESSION     (1 << 2)
+
+
+typedef unsigned long ck_object_handle_t;
+
+
+typedef unsigned long ck_object_class_t;
+
+#define CKO_DATA               (0)
+#define CKO_CERTIFICATE                (1)
+#define CKO_PUBLIC_KEY         (2)
+#define CKO_PRIVATE_KEY                (3)
+#define CKO_SECRET_KEY         (4)
+#define CKO_HW_FEATURE         (5)
+#define CKO_DOMAIN_PARAMETERS  (6)
+#define CKO_MECHANISM          (7)
+#define CKO_VENDOR_DEFINED     ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_hw_feature_type_t;
+
+#define CKH_MONOTONIC_COUNTER  (1)
+#define CKH_CLOCK              (2)
+#define CKH_USER_INTERFACE     (3)
+#define CKH_VENDOR_DEFINED     ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_key_type_t;
+
+#define CKK_RSA                        (0)
+#define CKK_DSA                        (1)
+#define CKK_DH                 (2)
+#define CKK_ECDSA              (3)
+#define CKK_EC                 (3)
+#define CKK_X9_42_DH           (4)
+#define CKK_KEA                        (5)
+#define CKK_GENERIC_SECRET     (0x10)
+#define CKK_RC2                        (0x11)
+#define CKK_RC4                        (0x12)
+#define CKK_DES                        (0x13)
+#define CKK_DES2               (0x14)
+#define CKK_DES3               (0x15)
+#define CKK_CAST               (0x16)
+#define CKK_CAST3              (0x17)
+#define CKK_CAST128            (0x18)
+#define CKK_RC5                        (0x19)
+#define CKK_IDEA               (0x1a)
+#define CKK_SKIPJACK           (0x1b)
+#define CKK_BATON              (0x1c)
+#define CKK_JUNIPER            (0x1d)
+#define CKK_CDMF               (0x1e)
+#define CKK_AES                        (0x1f)
+#define CKK_BLOWFISH           (0x20)
+#define CKK_TWOFISH            (0x21)
+#define CKK_VENDOR_DEFINED     ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_certificate_type_t;
+
+#define CKC_X_509              (0)
+#define CKC_X_509_ATTR_CERT    (1)
+#define CKC_WTLS               (2)
+#define CKC_VENDOR_DEFINED     ((unsigned long) (1 << 31))
+
+
+typedef unsigned long ck_attribute_type_t;
+
+#define CKA_CLASS                      (0)
+#define CKA_TOKEN                      (1)
+#define CKA_PRIVATE                    (2)
+#define CKA_LABEL                      (3)
+#define CKA_APPLICATION                        (0x10)
+#define CKA_VALUE                      (0x11)
+#define CKA_OBJECT_ID                  (0x12)
+#define CKA_CERTIFICATE_TYPE           (0x80)
+#define CKA_ISSUER                     (0x81)
+#define CKA_SERIAL_NUMBER              (0x82)
+#define CKA_AC_ISSUER                  (0x83)
+#define CKA_OWNER                      (0x84)
+#define CKA_ATTR_TYPES                 (0x85)
+#define CKA_TRUSTED                    (0x86)
+#define CKA_CERTIFICATE_CATEGORY       (0x87)
+#define CKA_JAVA_MIDP_SECURITY_DOMAIN  (0x88)
+#define CKA_URL                                (0x89)
+#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY (0x8a)
+#define CKA_HASH_OF_ISSUER_PUBLIC_KEY  (0x8b)
+#define CKA_CHECK_VALUE                        (0x90)
+#define CKA_KEY_TYPE                   (0x100)
+#define CKA_SUBJECT                    (0x101)
+#define CKA_ID                         (0x102)
+#define CKA_SENSITIVE                  (0x103)
+#define CKA_ENCRYPT                    (0x104)
+#define CKA_DECRYPT                    (0x105)
+#define CKA_WRAP                       (0x106)
+#define CKA_UNWRAP                     (0x107)
+#define CKA_SIGN                       (0x108)
+#define CKA_SIGN_RECOVER               (0x109)
+#define CKA_VERIFY                     (0x10a)
+#define CKA_VERIFY_RECOVER             (0x10b)
+#define CKA_DERIVE                     (0x10c)
+#define CKA_START_DATE                 (0x110)
+#define CKA_END_DATE                   (0x111)
+#define CKA_MODULUS                    (0x120)
+#define CKA_MODULUS_BITS               (0x121)
+#define CKA_PUBLIC_EXPONENT            (0x122)
+#define CKA_PRIVATE_EXPONENT           (0x123)
+#define CKA_PRIME_1                    (0x124)
+#define CKA_PRIME_2                    (0x125)
+#define CKA_EXPONENT_1                 (0x126)
+#define CKA_EXPONENT_2                 (0x127)
+#define CKA_COEFFICIENT                        (0x128)
+#define CKA_PRIME                      (0x130)
+#define CKA_SUBPRIME                   (0x131)
+#define CKA_BASE                       (0x132)
+#define CKA_PRIME_BITS                 (0x133)
+#define CKA_SUB_PRIME_BITS             (0x134)
+#define CKA_VALUE_BITS                 (0x160)
+#define CKA_VALUE_LEN                  (0x161)
+#define CKA_EXTRACTABLE                        (0x162)
+#define CKA_LOCAL                      (0x163)
+#define CKA_NEVER_EXTRACTABLE          (0x164)
+#define CKA_ALWAYS_SENSITIVE           (0x165)
+#define CKA_KEY_GEN_MECHANISM          (0x166)
+#define CKA_MODIFIABLE                 (0x170)
+#define CKA_ECDSA_PARAMS               (0x180)
+#define CKA_EC_PARAMS                  (0x180)
+#define CKA_EC_POINT                   (0x181)
+#define CKA_SECONDARY_AUTH             (0x200)
+#define CKA_AUTH_PIN_FLAGS             (0x201)
+#define CKA_ALWAYS_AUTHENTICATE                (0x202)
+#define CKA_WRAP_WITH_TRUSTED          (0x210)
+#define CKA_HW_FEATURE_TYPE            (0x300)
+#define CKA_RESET_ON_INIT              (0x301)
+#define CKA_HAS_RESET                  (0x302)
+#define CKA_PIXEL_X                    (0x400)
+#define CKA_PIXEL_Y                    (0x401)
+#define CKA_RESOLUTION                 (0x402)
+#define CKA_CHAR_ROWS                  (0x403)
+#define CKA_CHAR_COLUMNS               (0x404)
+#define CKA_COLOR                      (0x405)
+#define CKA_BITS_PER_PIXEL             (0x406)
+#define CKA_CHAR_SETS                  (0x480)
+#define CKA_ENCODING_METHODS           (0x481)
+#define CKA_MIME_TYPES                 (0x482)
+#define CKA_MECHANISM_TYPE             (0x500)
+#define CKA_REQUIRED_CMS_ATTRIBUTES    (0x501)
+#define CKA_DEFAULT_CMS_ATTRIBUTES     (0x502)
+#define CKA_SUPPORTED_CMS_ATTRIBUTES   (0x503)
+#define CKA_WRAP_TEMPLATE              (CKF_ARRAY_ATTRIBUTE | 0x211)
+#define CKA_UNWRAP_TEMPLATE            (CKF_ARRAY_ATTRIBUTE | 0x212)
+#define CKA_ALLOWED_MECHANISMS         (CKF_ARRAY_ATTRIBUTE | 0x600)
+#define CKA_VENDOR_DEFINED             ((unsigned long) (1 << 31))
+
+
+struct ck_attribute
+{
+  ck_attribute_type_t type;
+  void *value;
+  unsigned long value_len;
+};
+
+
+struct ck_date
+{
+  unsigned char year[4];
+  unsigned char month[2];
+  unsigned char day[2];
+};
+
+
+typedef unsigned long ck_mechanism_type_t;
+
+#define CKM_RSA_PKCS_KEY_PAIR_GEN      (0)
+#define CKM_RSA_PKCS                   (1)
+#define CKM_RSA_9796                   (2)
+#define CKM_RSA_X_509                  (3)
+#define CKM_MD2_RSA_PKCS               (4)
+#define CKM_MD5_RSA_PKCS               (5)
+#define CKM_SHA1_RSA_PKCS              (6)
+#define CKM_RIPEMD128_RSA_PKCS         (7)
+#define CKM_RIPEMD160_RSA_PKCS         (8)
+#define CKM_RSA_PKCS_OAEP              (9)
+#define CKM_RSA_X9_31_KEY_PAIR_GEN     (0xa)
+#define CKM_RSA_X9_31                  (0xb)
+#define CKM_SHA1_RSA_X9_31             (0xc)
+#define CKM_RSA_PKCS_PSS               (0xd)
+#define CKM_SHA1_RSA_PKCS_PSS          (0xe)
+#define CKM_DSA_KEY_PAIR_GEN           (0x10)
+#define        CKM_DSA                         (0x11)
+#define CKM_DSA_SHA1                   (0x12)
+#define CKM_DH_PKCS_KEY_PAIR_GEN       (0x20)
+#define CKM_DH_PKCS_DERIVE             (0x21)
+#define        CKM_X9_42_DH_KEY_PAIR_GEN       (0x30)
+#define CKM_X9_42_DH_DERIVE            (0x31)
+#define CKM_X9_42_DH_HYBRID_DERIVE     (0x32)
+#define CKM_X9_42_MQV_DERIVE           (0x33)
+#define CKM_SHA256_RSA_PKCS            (0x40)
+#define CKM_SHA384_RSA_PKCS            (0x41)
+#define CKM_SHA512_RSA_PKCS            (0x42)
+#define CKM_SHA256_RSA_PKCS_PSS                (0x43)
+#define CKM_SHA384_RSA_PKCS_PSS                (0x44)
+#define CKM_SHA512_RSA_PKCS_PSS                (0x45)
+#define CKM_RC2_KEY_GEN                        (0x100)
+#define CKM_RC2_ECB                    (0x101)
+#define        CKM_RC2_CBC                     (0x102)
+#define        CKM_RC2_MAC                     (0x103)
+#define CKM_RC2_MAC_GENERAL            (0x104)
+#define CKM_RC2_CBC_PAD                        (0x105)
+#define CKM_RC4_KEY_GEN                        (0x110)
+#define CKM_RC4                                (0x111)
+#define CKM_DES_KEY_GEN                        (0x120)
+#define CKM_DES_ECB                    (0x121)
+#define CKM_DES_CBC                    (0x122)
+#define CKM_DES_MAC                    (0x123)
+#define CKM_DES_MAC_GENERAL            (0x124)
+#define CKM_DES_CBC_PAD                        (0x125)
+#define CKM_DES2_KEY_GEN               (0x130)
+#define CKM_DES3_KEY_GEN               (0x131)
+#define CKM_DES3_ECB                   (0x132)
+#define CKM_DES3_CBC                   (0x133)
+#define CKM_DES3_MAC                   (0x134)
+#define CKM_DES3_MAC_GENERAL           (0x135)
+#define CKM_DES3_CBC_PAD               (0x136)
+#define CKM_CDMF_KEY_GEN               (0x140)
+#define CKM_CDMF_ECB                   (0x141)
+#define CKM_CDMF_CBC                   (0x142)
+#define CKM_CDMF_MAC                   (0x143)
+#define CKM_CDMF_MAC_GENERAL           (0x144)
+#define CKM_CDMF_CBC_PAD               (0x145)
+#define CKM_MD2                                (0x200)
+#define CKM_MD2_HMAC                   (0x201)
+#define CKM_MD2_HMAC_GENERAL           (0x202)
+#define CKM_MD5                                (0x210)
+#define CKM_MD5_HMAC                   (0x211)
+#define CKM_MD5_HMAC_GENERAL           (0x212)
+#define CKM_SHA_1                      (0x220)
+#define CKM_SHA_1_HMAC                 (0x221)
+#define CKM_SHA_1_HMAC_GENERAL         (0x222)
+#define CKM_RIPEMD128                  (0x230)
+#define CKM_RIPEMD128_HMAC             (0x231)
+#define CKM_RIPEMD128_HMAC_GENERAL     (0x232)
+#define CKM_RIPEMD160                  (0x240)
+#define CKM_RIPEMD160_HMAC             (0x241)
+#define CKM_RIPEMD160_HMAC_GENERAL     (0x242)
+#define CKM_SHA256                     (0x250)
+#define CKM_SHA256_HMAC                        (0x251)
+#define CKM_SHA256_HMAC_GENERAL                (0x252)
+#define CKM_SHA384                     (0x260)
+#define CKM_SHA384_HMAC                        (0x261)
+#define CKM_SHA384_HMAC_GENERAL                (0x262)
+#define CKM_SHA512                     (0x270)
+#define CKM_SHA512_HMAC                        (0x271)
+#define CKM_SHA512_HMAC_GENERAL                (0x272)
+#define CKM_CAST_KEY_GEN               (0x300)
+#define CKM_CAST_ECB                   (0x301)
+#define CKM_CAST_CBC                   (0x302)
+#define CKM_CAST_MAC                   (0x303)
+#define CKM_CAST_MAC_GENERAL           (0x304)
+#define CKM_CAST_CBC_PAD               (0x305)
+#define CKM_CAST3_KEY_GEN              (0x310)
+#define CKM_CAST3_ECB                  (0x311)
+#define CKM_CAST3_CBC                  (0x312)
+#define CKM_CAST3_MAC                  (0x313)
+#define CKM_CAST3_MAC_GENERAL          (0x314)
+#define CKM_CAST3_CBC_PAD              (0x315)
+#define CKM_CAST5_KEY_GEN              (0x320)
+#define CKM_CAST128_KEY_GEN            (0x320)
+#define CKM_CAST5_ECB                  (0x321)
+#define CKM_CAST128_ECB                        (0x321)
+#define CKM_CAST5_CBC                  (0x322)
+#define CKM_CAST128_CBC                        (0x322)
+#define CKM_CAST5_MAC                  (0x323)
+#define        CKM_CAST128_MAC                 (0x323)
+#define CKM_CAST5_MAC_GENERAL          (0x324)
+#define CKM_CAST128_MAC_GENERAL                (0x324)
+#define CKM_CAST5_CBC_PAD              (0x325)
+#define CKM_CAST128_CBC_PAD            (0x325)
+#define CKM_RC5_KEY_GEN                        (0x330)
+#define CKM_RC5_ECB                    (0x331)
+#define CKM_RC5_CBC                    (0x332)
+#define CKM_RC5_MAC                    (0x333)
+#define CKM_RC5_MAC_GENERAL            (0x334)
+#define CKM_RC5_CBC_PAD                        (0x335)
+#define CKM_IDEA_KEY_GEN               (0x340)
+#define CKM_IDEA_ECB                   (0x341)
+#define        CKM_IDEA_CBC                    (0x342)
+#define CKM_IDEA_MAC                   (0x343)
+#define CKM_IDEA_MAC_GENERAL           (0x344)
+#define CKM_IDEA_CBC_PAD               (0x345)
+#define CKM_GENERIC_SECRET_KEY_GEN     (0x350)
+#define CKM_CONCATENATE_BASE_AND_KEY   (0x360)
+#define CKM_CONCATENATE_BASE_AND_DATA  (0x362)
+#define CKM_CONCATENATE_DATA_AND_BASE  (0x363)
+#define CKM_XOR_BASE_AND_DATA          (0x364)
+#define CKM_EXTRACT_KEY_FROM_KEY       (0x365)
+#define CKM_SSL3_PRE_MASTER_KEY_GEN    (0x370)
+#define CKM_SSL3_MASTER_KEY_DERIVE     (0x371)
+#define CKM_SSL3_KEY_AND_MAC_DERIVE    (0x372)
+#define CKM_SSL3_MASTER_KEY_DERIVE_DH  (0x373)
+#define CKM_TLS_PRE_MASTER_KEY_GEN     (0x374)
+#define CKM_TLS_MASTER_KEY_DERIVE      (0x375)
+#define CKM_TLS_KEY_AND_MAC_DERIVE     (0x376)
+#define CKM_TLS_MASTER_KEY_DERIVE_DH   (0x377)
+#define CKM_SSL3_MD5_MAC               (0x380)
+#define CKM_SSL3_SHA1_MAC              (0x381)
+#define CKM_MD5_KEY_DERIVATION         (0x390)
+#define CKM_MD2_KEY_DERIVATION         (0x391)
+#define CKM_SHA1_KEY_DERIVATION                (0x392)
+#define CKM_PBE_MD2_DES_CBC            (0x3a0)
+#define CKM_PBE_MD5_DES_CBC            (0x3a1)
+#define CKM_PBE_MD5_CAST_CBC           (0x3a2)
+#define CKM_PBE_MD5_CAST3_CBC          (0x3a3)
+#define CKM_PBE_MD5_CAST5_CBC          (0x3a4)
+#define CKM_PBE_MD5_CAST128_CBC                (0x3a4)
+#define CKM_PBE_SHA1_CAST5_CBC         (0x3a5)
+#define CKM_PBE_SHA1_CAST128_CBC       (0x3a5)
+#define CKM_PBE_SHA1_RC4_128           (0x3a6)
+#define CKM_PBE_SHA1_RC4_40            (0x3a7)
+#define CKM_PBE_SHA1_DES3_EDE_CBC      (0x3a8)
+#define CKM_PBE_SHA1_DES2_EDE_CBC      (0x3a9)
+#define CKM_PBE_SHA1_RC2_128_CBC       (0x3aa)
+#define CKM_PBE_SHA1_RC2_40_CBC                (0x3ab)
+#define CKM_PKCS5_PBKD2                        (0x3b0)
+#define CKM_PBA_SHA1_WITH_SHA1_HMAC    (0x3c0)
+#define CKM_KEY_WRAP_LYNKS             (0x400)
+#define CKM_KEY_WRAP_SET_OAEP          (0x401)
+#define CKM_SKIPJACK_KEY_GEN           (0x1000)
+#define CKM_SKIPJACK_ECB64             (0x1001)
+#define CKM_SKIPJACK_CBC64             (0x1002)
+#define CKM_SKIPJACK_OFB64             (0x1003)
+#define CKM_SKIPJACK_CFB64             (0x1004)
+#define CKM_SKIPJACK_CFB32             (0x1005)
+#define CKM_SKIPJACK_CFB16             (0x1006)
+#define CKM_SKIPJACK_CFB8              (0x1007)
+#define CKM_SKIPJACK_WRAP              (0x1008)
+#define CKM_SKIPJACK_PRIVATE_WRAP      (0x1009)
+#define CKM_SKIPJACK_RELAYX            (0x100a)
+#define CKM_KEA_KEY_PAIR_GEN           (0x1010)
+#define CKM_KEA_KEY_DERIVE             (0x1011)
+#define CKM_FORTEZZA_TIMESTAMP         (0x1020)
+#define CKM_BATON_KEY_GEN              (0x1030)
+#define CKM_BATON_ECB128               (0x1031)
+#define CKM_BATON_ECB96                        (0x1032)
+#define CKM_BATON_CBC128               (0x1033)
+#define CKM_BATON_COUNTER              (0x1034)
+#define CKM_BATON_SHUFFLE              (0x1035)
+#define CKM_BATON_WRAP                 (0x1036)
+#define CKM_ECDSA_KEY_PAIR_GEN         (0x1040)
+#define CKM_EC_KEY_PAIR_GEN            (0x1040)
+#define CKM_ECDSA                      (0x1041)
+#define CKM_ECDSA_SHA1                 (0x1042)
+#define CKM_ECDH1_DERIVE               (0x1050)
+#define CKM_ECDH1_COFACTOR_DERIVE      (0x1051)
+#define CKM_ECMQV_DERIVE               (0x1052)
+#define CKM_JUNIPER_KEY_GEN            (0x1060)
+#define CKM_JUNIPER_ECB128             (0x1061)
+#define CKM_JUNIPER_CBC128             (0x1062)
+#define CKM_JUNIPER_COUNTER            (0x1063)
+#define CKM_JUNIPER_SHUFFLE            (0x1064)
+#define CKM_JUNIPER_WRAP               (0x1065)
+#define CKM_FASTHASH                   (0x1070)
+#define CKM_AES_KEY_GEN                        (0x1080)
+#define CKM_AES_ECB                    (0x1081)
+#define CKM_AES_CBC                    (0x1082)
+#define CKM_AES_MAC                    (0x1083)
+#define CKM_AES_MAC_GENERAL            (0x1084)
+#define CKM_AES_CBC_PAD                        (0x1085)
+#define CKM_DSA_PARAMETER_GEN          (0x2000)
+#define CKM_DH_PKCS_PARAMETER_GEN      (0x2001)
+#define CKM_X9_42_DH_PARAMETER_GEN     (0x2002)
+#define CKM_VENDOR_DEFINED             ((unsigned long) (1 << 31))
+
+
+struct ck_mechanism
+{
+  ck_mechanism_type_t mechanism;
+  void *parameter;
+  unsigned long parameter_len;
+};
+
+
+struct ck_mechanism_info
+{
+  unsigned long min_key_size;
+  unsigned long max_key_size;
+  ck_flags_t flags;
+};
+
+#define CKF_HW                 (1 << 0)
+#define CKF_ENCRYPT            (1 << 8)
+#define CKF_DECRYPT            (1 << 9)
+#define CKF_DIGEST             (1 << 10)
+#define CKF_SIGN               (1 << 11)
+#define CKF_SIGN_RECOVER       (1 << 12)
+#define CKF_VERIFY             (1 << 13)
+#define CKF_VERIFY_RECOVER     (1 << 14)
+#define CKF_GENERATE           (1 << 15)
+#define CKF_GENERATE_KEY_PAIR  (1 << 16)
+#define CKF_WRAP               (1 << 17)
+#define CKF_UNWRAP             (1 << 18)
+#define CKF_DERIVE             (1 << 19)
+#define CKF_EXTENSION          ((unsigned long) (1 << 31))
+
+
+/* Flags for C_WaitForSlotEvent.  */
+#define CKF_DONT_BLOCK                         (1)
+
+
+typedef unsigned long ck_rv_t;
+
+
+typedef ck_rv_t (*ck_notify_t) (ck_session_handle_t session,
+                               ck_notification_t event, void *application);
+
+/* Forward reference.  */
+struct ck_function_list;
+
+#define _CK_DECLARE_FUNCTION(name, args)       \
+typedef ck_rv_t (*CK_ ## name) args;           \
+ck_rv_t CK_SPEC name args
+
+_CK_DECLARE_FUNCTION (C_Initialize, (void *init_args));
+_CK_DECLARE_FUNCTION (C_Finalize, (void *reserved));
+_CK_DECLARE_FUNCTION (C_GetInfo, (struct ck_info *info));
+_CK_DECLARE_FUNCTION (C_GetFunctionList,
+                     (struct ck_function_list **function_list));
+
+_CK_DECLARE_FUNCTION (C_GetSlotList,
+                     (unsigned char token_present, ck_slot_id_t *slot_list,
+                      unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetSlotInfo,
+                     (ck_slot_id_t slot_id, struct ck_slot_info *info));
+_CK_DECLARE_FUNCTION (C_GetTokenInfo,
+                     (ck_slot_id_t slot_id, struct ck_token_info *info));
+_CK_DECLARE_FUNCTION (C_WaitForSlotEvent,
+                     (ck_flags_t flags, ck_slot_id_t *slot, void *reserved));
+_CK_DECLARE_FUNCTION (C_GetMechanismList,
+                     (ck_slot_id_t slot_id,
+                      ck_mechanism_type_t *mechanism_list,
+                      unsigned long *count));
+_CK_DECLARE_FUNCTION (C_GetMechanismInfo,
+                     (ck_slot_id_t slot_id, ck_mechanism_type_t type,
+                      struct ck_mechanism_info *info));
+_CK_DECLARE_FUNCTION (C_InitToken,
+                     (ck_slot_id_t slot_id, unsigned char *pin,
+                      unsigned long pin_len, unsigned char *label));
+_CK_DECLARE_FUNCTION (C_InitPIN,
+                     (ck_session_handle_t session, unsigned char *pin,
+                      unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_SetPIN,
+                     (ck_session_handle_t session, unsigned char *old_pin,
+                      unsigned long old_len, unsigned char *new_pin,
+                      unsigned long new_len));
+
+_CK_DECLARE_FUNCTION (C_OpenSession,
+                     (ck_slot_id_t slot_id, ck_flags_t flags,
+                      void *application, ck_notify_t notify,
+                      ck_session_handle_t *session));
+_CK_DECLARE_FUNCTION (C_CloseSession, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CloseAllSessions, (ck_slot_id_t slot_id));
+_CK_DECLARE_FUNCTION (C_GetSessionInfo,
+                     (ck_session_handle_t session,
+                      struct ck_session_info *info));
+_CK_DECLARE_FUNCTION (C_GetOperationState,
+                     (ck_session_handle_t session,
+                      unsigned char *operation_state,
+                      unsigned long *operation_state_len));
+_CK_DECLARE_FUNCTION (C_SetOperationState,
+                     (ck_session_handle_t session,
+                      unsigned char *operation_state,
+                      unsigned long operation_state_len,
+                      ck_object_handle_t encryption_key,
+                      ck_object_handle_t authentiation_key));
+_CK_DECLARE_FUNCTION (C_Login,
+                     (ck_session_handle_t session, ck_user_type_t user_type,
+                      unsigned char *pin, unsigned long pin_len));
+_CK_DECLARE_FUNCTION (C_Logout, (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_CreateObject,
+                     (ck_session_handle_t session,
+                      struct ck_attribute *templ,
+                      unsigned long count, ck_object_handle_t *object));
+_CK_DECLARE_FUNCTION (C_CopyObject,
+                     (ck_session_handle_t session, ck_object_handle_t object,
+                      struct ck_attribute *templ, unsigned long count,
+                      ck_object_handle_t *new_object));
+_CK_DECLARE_FUNCTION (C_DestroyObject,
+                     (ck_session_handle_t session,
+                      ck_object_handle_t object));
+_CK_DECLARE_FUNCTION (C_GetObjectSize,
+                     (ck_session_handle_t session,
+                      ck_object_handle_t object,
+                      unsigned long *size));
+_CK_DECLARE_FUNCTION (C_GetAttributeValue,
+                     (ck_session_handle_t session,
+                      ck_object_handle_t object,
+                      struct ck_attribute *templ,
+                      unsigned long count));
+_CK_DECLARE_FUNCTION (C_SetAttributeValue,
+                     (ck_session_handle_t session,
+                      ck_object_handle_t object,
+                      struct ck_attribute *templ,
+                      unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjectsInit,
+                     (ck_session_handle_t session,
+                      struct ck_attribute *templ,
+                      unsigned long count));
+_CK_DECLARE_FUNCTION (C_FindObjects,
+                     (ck_session_handle_t session,
+                      ck_object_handle_t *object,
+                      unsigned long max_object_count,
+                      unsigned long *object_count));
+_CK_DECLARE_FUNCTION (C_FindObjectsFinal,
+                     (ck_session_handle_t session));
+
+_CK_DECLARE_FUNCTION (C_EncryptInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Encrypt,
+                     (ck_session_handle_t session,
+                      unsigned char *data, unsigned long data_len,
+                      unsigned char *encrypted_data,
+                      unsigned long *encrypted_data_len));
+_CK_DECLARE_FUNCTION (C_EncryptUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *part, unsigned long part_len,
+                      unsigned char *encrypted_part,
+                      unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_EncryptFinal,
+                     (ck_session_handle_t session,
+                      unsigned char *last_encrypted_part,
+                      unsigned long *last_encrypted_part_len));
+
+_CK_DECLARE_FUNCTION (C_DecryptInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Decrypt,
+                     (ck_session_handle_t session,
+                      unsigned char *encrypted_data,
+                      unsigned long encrypted_data_len,
+                      unsigned char *data, unsigned long *data_len));
+_CK_DECLARE_FUNCTION (C_DecryptUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *encrypted_part,
+                      unsigned long encrypted_part_len,
+                      unsigned char *part, unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_DecryptFinal,
+                     (ck_session_handle_t session,
+                      unsigned char *last_part,
+                      unsigned long *last_part_len));
+
+_CK_DECLARE_FUNCTION (C_DigestInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism));
+_CK_DECLARE_FUNCTION (C_Digest,
+                     (ck_session_handle_t session,
+                      unsigned char *data, unsigned long data_len,
+                      unsigned char *digest,
+                      unsigned long *digest_len));
+_CK_DECLARE_FUNCTION (C_DigestUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_DigestKey,
+                     (ck_session_handle_t session, ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_DigestFinal,
+                     (ck_session_handle_t session,
+                      unsigned char *digest,
+                      unsigned long *digest_len));
+
+_CK_DECLARE_FUNCTION (C_SignInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Sign,
+                     (ck_session_handle_t session,
+                      unsigned char *data, unsigned long data_len,
+                      unsigned char *signature,
+                      unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_SignFinal,
+                     (ck_session_handle_t session,
+                      unsigned char *signature,
+                      unsigned long *signature_len));
+_CK_DECLARE_FUNCTION (C_SignRecoverInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_SignRecover,
+                     (ck_session_handle_t session,
+                      unsigned char *data, unsigned long data_len,
+                      unsigned char *signature,
+                      unsigned long *signature_len));
+
+_CK_DECLARE_FUNCTION (C_VerifyInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_Verify,
+                     (ck_session_handle_t session,
+                      unsigned char *data, unsigned long data_len,
+                      unsigned char *signature,
+                      unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *part, unsigned long part_len));
+_CK_DECLARE_FUNCTION (C_VerifyFinal,
+                     (ck_session_handle_t session,
+                      unsigned char *signature,
+                      unsigned long signature_len));
+_CK_DECLARE_FUNCTION (C_VerifyRecoverInit,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t key));
+_CK_DECLARE_FUNCTION (C_VerifyRecover,
+                     (ck_session_handle_t session,
+                      unsigned char *signature,
+                      unsigned long signature_len,
+                      unsigned char *data,
+                      unsigned long *data_len));
+
+_CK_DECLARE_FUNCTION (C_DigestEncryptUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *part, unsigned long part_len,
+                      unsigned char *encrypted_part,
+                      unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptDigestUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *encrypted_part,
+                      unsigned long encrypted_part_len,
+                      unsigned char *part,
+                      unsigned long *part_len));
+_CK_DECLARE_FUNCTION (C_SignEncryptUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *part, unsigned long part_len,
+                      unsigned char *encrypted_part,
+                      unsigned long *encrypted_part_len));
+_CK_DECLARE_FUNCTION (C_DecryptVerifyUpdate,
+                     (ck_session_handle_t session,
+                      unsigned char *encrypted_part,
+                      unsigned long encrypted_part_len,
+                      unsigned char *part,
+                      unsigned long *part_len));
+
+_CK_DECLARE_FUNCTION (C_GenerateKey,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      struct ck_attribute *templ,
+                      unsigned long count,
+                      ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_GenerateKeyPair,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      struct ck_attribute *public_key_template,
+                      unsigned long public_key_attribute_count,
+                      struct ck_attribute *private_key_template,
+                      unsigned long private_key_attribute_count,
+                      ck_object_handle_t *public_key,
+                      ck_object_handle_t *private_key));
+_CK_DECLARE_FUNCTION (C_WrapKey,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t wrapping_key,
+                      ck_object_handle_t key,
+                      unsigned char *wrapped_key,
+                      unsigned long *wrapped_key_len));
+_CK_DECLARE_FUNCTION (C_UnwrapKey,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t unwrapping_key,
+                      unsigned char *wrapped_key,
+                      unsigned long wrapped_key_len,
+                      struct ck_attribute *templ,
+                      unsigned long attribute_count,
+                      ck_object_handle_t *key));
+_CK_DECLARE_FUNCTION (C_DeriveKey,
+                     (ck_session_handle_t session,
+                      struct ck_mechanism *mechanism,
+                      ck_object_handle_t base_key,
+                      struct ck_attribute *templ,
+                      unsigned long attribute_count,
+                      ck_object_handle_t *key));
+
+_CK_DECLARE_FUNCTION (C_SeedRandom,
+                     (ck_session_handle_t session, unsigned char *seed,
+                      unsigned long seed_len));
+_CK_DECLARE_FUNCTION (C_GenerateRandom,
+                     (ck_session_handle_t session,
+                      unsigned char *random_data,
+                      unsigned long random_len));
+
+_CK_DECLARE_FUNCTION (C_GetFunctionStatus, (ck_session_handle_t session));
+_CK_DECLARE_FUNCTION (C_CancelFunction, (ck_session_handle_t session));
+
+
+struct ck_function_list
+{
+  struct ck_version version;
+  CK_C_Initialize C_Initialize;
+  CK_C_Finalize C_Finalize;
+  CK_C_GetInfo C_GetInfo;
+  CK_C_GetFunctionList C_GetFunctionList;
+  CK_C_GetSlotList C_GetSlotList;
+  CK_C_GetSlotInfo C_GetSlotInfo;
+  CK_C_GetTokenInfo C_GetTokenInfo;
+  CK_C_GetMechanismList C_GetMechanismList;
+  CK_C_GetMechanismInfo C_GetMechanismInfo;
+  CK_C_InitToken C_InitToken;
+  CK_C_InitPIN C_InitPIN;
+  CK_C_SetPIN C_SetPIN;
+  CK_C_OpenSession C_OpenSession;
+  CK_C_CloseSession C_CloseSession;
+  CK_C_CloseAllSessions C_CloseAllSessions;
+  CK_C_GetSessionInfo C_GetSessionInfo;
+  CK_C_GetOperationState C_GetOperationState;
+  CK_C_SetOperationState C_SetOperationState;
+  CK_C_Login C_Login;
+  CK_C_Logout C_Logout;
+  CK_C_CreateObject C_CreateObject;
+  CK_C_CopyObject C_CopyObject;
+  CK_C_DestroyObject C_DestroyObject;
+  CK_C_GetObjectSize C_GetObjectSize;
+  CK_C_GetAttributeValue C_GetAttributeValue;
+  CK_C_SetAttributeValue C_SetAttributeValue;
+  CK_C_FindObjectsInit C_FindObjectsInit;
+  CK_C_FindObjects C_FindObjects;
+  CK_C_FindObjectsFinal C_FindObjectsFinal;
+  CK_C_EncryptInit C_EncryptInit;
+  CK_C_Encrypt C_Encrypt;
+  CK_C_EncryptUpdate C_EncryptUpdate;
+  CK_C_EncryptFinal C_EncryptFinal;
+  CK_C_DecryptInit C_DecryptInit;
+  CK_C_Decrypt C_Decrypt;
+  CK_C_DecryptUpdate C_DecryptUpdate;
+  CK_C_DecryptFinal C_DecryptFinal;
+  CK_C_DigestInit C_DigestInit;
+  CK_C_Digest C_Digest;
+  CK_C_DigestUpdate C_DigestUpdate;
+  CK_C_DigestKey C_DigestKey;
+  CK_C_DigestFinal C_DigestFinal;
+  CK_C_SignInit C_SignInit;
+  CK_C_Sign C_Sign;
+  CK_C_SignUpdate C_SignUpdate;
+  CK_C_SignFinal C_SignFinal;
+  CK_C_SignRecoverInit C_SignRecoverInit;
+  CK_C_SignRecover C_SignRecover;
+  CK_C_VerifyInit C_VerifyInit;
+  CK_C_Verify C_Verify;
+  CK_C_VerifyUpdate C_VerifyUpdate;
+  CK_C_VerifyFinal C_VerifyFinal;
+  CK_C_VerifyRecoverInit C_VerifyRecoverInit;
+  CK_C_VerifyRecover C_VerifyRecover;
+  CK_C_DigestEncryptUpdate C_DigestEncryptUpdate;
+  CK_C_DecryptDigestUpdate C_DecryptDigestUpdate;
+  CK_C_SignEncryptUpdate C_SignEncryptUpdate;
+  CK_C_DecryptVerifyUpdate C_DecryptVerifyUpdate;
+  CK_C_GenerateKey C_GenerateKey;
+  CK_C_GenerateKeyPair C_GenerateKeyPair;
+  CK_C_WrapKey C_WrapKey;
+  CK_C_UnwrapKey C_UnwrapKey;
+  CK_C_DeriveKey C_DeriveKey;
+  CK_C_SeedRandom C_SeedRandom;
+  CK_C_GenerateRandom C_GenerateRandom;
+  CK_C_GetFunctionStatus C_GetFunctionStatus;
+  CK_C_CancelFunction C_CancelFunction;
+  CK_C_WaitForSlotEvent C_WaitForSlotEvent;
+};
+
+
+typedef ck_rv_t (*ck_createmutex_t) (void **mutex);
+typedef ck_rv_t (*ck_destroymutex_t) (void *mutex);
+typedef ck_rv_t (*ck_lockmutex_t) (void *mutex);
+typedef ck_rv_t (*ck_unlockmutex_t) (void *mutex);
+
+
+struct ck_c_initialize_args
+{
+  ck_createmutex_t create_mutex;
+  ck_destroymutex_t destroy_mutex;
+  ck_lockmutex_t lock_mutex;
+  ck_unlockmutex_t unlock_mutex;
+  ck_flags_t flags;
+  void *reserved;
+};
+
+
+#define CKF_LIBRARY_CANT_CREATE_OS_THREADS     (1 << 0)
+#define CKF_OS_LOCKING_OK                      (1 << 1)
+
+#define CKR_OK                                 (0)
+#define CKR_CANCEL                             (1)
+#define CKR_HOST_MEMORY                                (2)
+#define CKR_SLOT_ID_INVALID                    (3)
+#define CKR_GENERAL_ERROR                      (5)
+#define CKR_FUNCTION_FAILED                    (6)
+#define CKR_ARGUMENTS_BAD                      (7)
+#define CKR_NO_EVENT                           (8)
+#define CKR_NEED_TO_CREATE_THREADS             (9)
+#define CKR_CANT_LOCK                          (0xa)
+#define CKR_ATTRIBUTE_READ_ONLY                        (0x10)
+#define CKR_ATTRIBUTE_SENSITIVE                        (0x11)
+#define CKR_ATTRIBUTE_TYPE_INVALID             (0x12)
+#define CKR_ATTRIBUTE_VALUE_INVALID            (0x13)
+#define CKR_DATA_INVALID                       (0x20)
+#define CKR_DATA_LEN_RANGE                     (0x21)
+#define CKR_DEVICE_ERROR                       (0x30)
+#define CKR_DEVICE_MEMORY                      (0x31)
+#define CKR_DEVICE_REMOVED                     (0x32)
+#define CKR_ENCRYPTED_DATA_INVALID             (0x40)
+#define CKR_ENCRYPTED_DATA_LEN_RANGE           (0x41)
+#define CKR_FUNCTION_CANCELED                  (0x50)
+#define CKR_FUNCTION_NOT_PARALLEL              (0x51)
+#define CKR_FUNCTION_NOT_SUPPORTED             (0x54)
+#define CKR_KEY_HANDLE_INVALID                 (0x60)
+#define CKR_KEY_SIZE_RANGE                     (0x62)
+#define CKR_KEY_TYPE_INCONSISTENT              (0x63)
+#define CKR_KEY_NOT_NEEDED                     (0x64)
+#define CKR_KEY_CHANGED                                (0x65)
+#define CKR_KEY_NEEDED                         (0x66)
+#define CKR_KEY_INDIGESTIBLE                   (0x67)
+#define CKR_KEY_FUNCTION_NOT_PERMITTED         (0x68)
+#define CKR_KEY_NOT_WRAPPABLE                  (0x69)
+#define CKR_KEY_UNEXTRACTABLE                  (0x6a)
+#define CKR_MECHANISM_INVALID                  (0x70)
+#define CKR_MECHANISM_PARAM_INVALID            (0x71)
+#define CKR_OBJECT_HANDLE_INVALID              (0x82)
+#define CKR_OPERATION_ACTIVE                   (0x90)
+#define CKR_OPERATION_NOT_INITIALIZED          (0x91)
+#define CKR_PIN_INCORRECT                      (0xa0)
+#define CKR_PIN_INVALID                                (0xa1)
+#define CKR_PIN_LEN_RANGE                      (0xa2)
+#define CKR_PIN_EXPIRED                                (0xa3)
+#define CKR_PIN_LOCKED                         (0xa4)
+#define CKR_SESSION_CLOSED                     (0xb0)
+#define CKR_SESSION_COUNT                      (0xb1)
+#define CKR_SESSION_HANDLE_INVALID             (0xb3)
+#define CKR_SESSION_PARALLEL_NOT_SUPPORTED     (0xb4)
+#define CKR_SESSION_READ_ONLY                  (0xb5)
+#define CKR_SESSION_EXISTS                     (0xb6)
+#define CKR_SESSION_READ_ONLY_EXISTS           (0xb7)
+#define CKR_SESSION_READ_WRITE_SO_EXISTS       (0xb8)
+#define CKR_SIGNATURE_INVALID                  (0xc0)
+#define CKR_SIGNATURE_LEN_RANGE                        (0xc1)
+#define CKR_TEMPLATE_INCOMPLETE                        (0xd0)
+#define CKR_TEMPLATE_INCONSISTENT              (0xd1)
+#define CKR_TOKEN_NOT_PRESENT                  (0xe0)
+#define CKR_TOKEN_NOT_RECOGNIZED               (0xe1)
+#define CKR_TOKEN_WRITE_PROTECTED              (0xe2)
+#define        CKR_UNWRAPPING_KEY_HANDLE_INVALID       (0xf0)
+#define CKR_UNWRAPPING_KEY_SIZE_RANGE          (0xf1)
+#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT   (0xf2)
+#define CKR_USER_ALREADY_LOGGED_IN             (0x100)
+#define CKR_USER_NOT_LOGGED_IN                 (0x101)
+#define CKR_USER_PIN_NOT_INITIALIZED           (0x102)
+#define CKR_USER_TYPE_INVALID                  (0x103)
+#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN     (0x104)
+#define CKR_USER_TOO_MANY_TYPES                        (0x105)
+#define CKR_WRAPPED_KEY_INVALID                        (0x110)
+#define CKR_WRAPPED_KEY_LEN_RANGE              (0x112)
+#define CKR_WRAPPING_KEY_HANDLE_INVALID                (0x113)
+#define CKR_WRAPPING_KEY_SIZE_RANGE            (0x114)
+#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT     (0x115)
+#define CKR_RANDOM_SEED_NOT_SUPPORTED          (0x120)
+#define CKR_RANDOM_NO_RNG                      (0x121)
+#define CKR_DOMAIN_PARAMS_INVALID              (0x130)
+#define CKR_BUFFER_TOO_SMALL                   (0x150)
+#define CKR_SAVED_STATE_INVALID                        (0x160)
+#define CKR_INFORMATION_SENSITIVE              (0x170)
+#define CKR_STATE_UNSAVEABLE                   (0x180)
+#define CKR_CRYPTOKI_NOT_INITIALIZED           (0x190)
+#define CKR_CRYPTOKI_ALREADY_INITIALIZED       (0x191)
+#define CKR_MUTEX_BAD                          (0x1a0)
+#define CKR_MUTEX_NOT_LOCKED                   (0x1a1)
+#define CKR_FUNCTION_REJECTED                  (0x200)
+#define CKR_VENDOR_DEFINED                     ((unsigned long) (1 << 31))
+
+
+\f
+/* Compatibility layer.  */
+
+#ifdef CRYPTOKI_COMPAT
+
+#undef CK_DEFINE_FUNCTION
+#define CK_DEFINE_FUNCTION(retval, name) retval CK_SPEC name
+
+/* For NULL.  */
+#include <stddef.h>
+
+typedef unsigned char CK_BYTE;
+typedef unsigned char CK_CHAR;
+typedef unsigned char CK_UTF8CHAR;
+typedef unsigned char CK_BBOOL;
+typedef unsigned long int CK_ULONG;
+typedef long int CK_LONG;
+typedef CK_BYTE *CK_BYTE_PTR;
+typedef CK_CHAR *CK_CHAR_PTR;
+typedef CK_UTF8CHAR *CK_UTF8CHAR_PTR;
+typedef CK_ULONG *CK_ULONG_PTR;
+typedef void *CK_VOID_PTR;
+typedef void **CK_VOID_PTR_PTR;
+#define CK_FALSE 0
+#define CK_TRUE 1
+#ifndef CK_DISABLE_TRUE_FALSE
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#endif
+
+typedef struct ck_version CK_VERSION;
+typedef struct ck_version *CK_VERSION_PTR;
+
+typedef struct ck_info CK_INFO;
+typedef struct ck_info *CK_INFO_PTR;
+
+typedef ck_slot_id_t *CK_SLOT_ID_PTR;
+
+typedef struct ck_slot_info CK_SLOT_INFO;
+typedef struct ck_slot_info *CK_SLOT_INFO_PTR;
+
+typedef struct ck_token_info CK_TOKEN_INFO;
+typedef struct ck_token_info *CK_TOKEN_INFO_PTR;
+
+typedef ck_session_handle_t *CK_SESSION_HANDLE_PTR;
+
+typedef struct ck_session_info CK_SESSION_INFO;
+typedef struct ck_session_info *CK_SESSION_INFO_PTR;
+
+typedef ck_object_handle_t *CK_OBJECT_HANDLE_PTR;
+
+typedef ck_object_class_t *CK_OBJECT_CLASS_PTR;
+
+typedef struct ck_attribute CK_ATTRIBUTE;
+typedef struct ck_attribute *CK_ATTRIBUTE_PTR;
+
+typedef struct ck_date CK_DATE;
+typedef struct ck_date *CK_DATE_PTR;
+
+typedef ck_mechanism_type_t *CK_MECHANISM_TYPE_PTR;
+
+typedef struct ck_mechanism CK_MECHANISM;
+typedef struct ck_mechanism *CK_MECHANISM_PTR;
+
+typedef struct ck_mechanism_info CK_MECHANISM_INFO;
+typedef struct ck_mechanism_info *CK_MECHANISM_INFO_PTR;
+
+typedef struct ck_function_list CK_FUNCTION_LIST;
+typedef struct ck_function_list *CK_FUNCTION_LIST_PTR;
+typedef struct ck_function_list **CK_FUNCTION_LIST_PTR_PTR;
+
+typedef struct ck_c_initialize_args CK_C_INITIALIZE_ARGS;
+typedef struct ck_c_initialize_args *CK_C_INITIALIZE_ARGS_PTR;
+
+#define NULL_PTR NULL
+
+/* Delete the helper macros defined at the top of the file.  */
+#undef ck_flags_t
+#undef ck_version
+
+#undef ck_info
+#undef cryptoki_version
+#undef manufacturer_id
+#undef library_description
+#undef library_version
+
+#undef ck_notification_t
+#undef ck_slot_id_t
+
+#undef ck_slot_info
+#undef slot_description
+#undef hardware_version
+#undef firmware_version
+
+#undef ck_token_info
+#undef serial_number
+#undef max_session_count
+#undef session_count
+#undef max_rw_session_count
+#undef rw_session_count
+#undef max_pin_len
+#undef min_pin_len
+#undef total_public_memory
+#undef free_public_memory
+#undef total_private_memory
+#undef free_private_memory
+#undef utc_time
+
+#undef ck_session_handle_t
+#undef ck_user_type_t
+#undef ck_state_t
+
+#undef ck_session_info
+#undef slot_id
+#undef device_error
+
+#undef ck_object_handle_t
+#undef ck_object_class_t
+#undef ck_hw_feature_type_t
+#undef ck_key_type_t
+#undef ck_certificate_type_t
+#undef ck_attribute_type_t
+
+#undef ck_attribute
+#undef value
+#undef value_len
+
+#undef ck_date
+
+#undef ck_mechanism_type_t
+
+#undef ck_mechanism
+#undef parameter
+#undef parameter_len
+
+#undef ck_mechanism_info
+#undef min_key_size
+#undef max_key_size
+
+#undef ck_rv_t
+#undef ck_notify_t
+
+#undef ck_function_list
+
+#undef ck_createmutex_t
+#undef ck_destroymutex_t
+#undef ck_lockmutex_t
+#undef ck_unlockmutex_t
+
+#undef ck_c_initialize_args
+#undef create_mutex
+#undef destroy_mutex
+#undef lock_mutex
+#undef unlock_mutex
+#undef reserved
+
+#endif /* CRYPTOKI_COMPAT */
+
+\f
+/* System dependencies.  */
+#if defined(_WIN32) || defined(CRYPTOKI_FORCE_WIN32)
+#pragma pack(pop, cryptoki)
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* PKCS11_H */