4577391 [rkeene@sledge /home/rkeene/archive/openssh]$ cat -n openssh-4.4p1pkcs11-0.17.patch
    1 diff -urNp openssh-4.4p1/authfd.c openssh-4.4p1+pkcs11-0.17/authfd.c
    2 --- openssh-4.4p1/authfd.c  2006-09-01 08:38:36.000000000 +0300
    3 +++ openssh-4.4p1+pkcs11-0.17/authfd.c  2006-10-12 13:59:59.000000000 +0200
    4 @@ -669,3 +669,79 @@ decode_reply(int type)
    5     /* NOTREACHED */
    6     return 0;
    7  }
    8 +
    9 +#ifndef SSH_PKCS11_DISABLED
   10 +
   11 +int
   12 +ssh_pkcs11_add_provider (AuthenticationConnection *auth, const char *provider,
   13 +   int protected_authentication, const char *sign_mode, int cert_private)
   14 +{
   15 +   Buffer msg;
   16 +   int type;
   17 +   int code;
   18 +
   19 +   code = SSH_AGENTC_PKCS11_ADD_PROVIDER;
   20 +
   21 +   buffer_init(&msg);
   22 +   buffer_put_char(&msg, code);
   23 +   buffer_put_cstring(&msg, provider);
   24 +   buffer_put_int(&msg, protected_authentication);
   25 +   buffer_put_cstring(&msg, sign_mode == NULL ? "auto" : sign_mode);
   26 +   buffer_put_int(&msg, cert_private);
   27 +
   28 +   if (ssh_request_reply(auth, &msg, &msg) == 0) {
   29 +       buffer_free(&msg);
   30 +       return 0;
   31 +   }
   32 +   type = buffer_get_char(&msg);
   33 +   buffer_free(&msg);
   34 +   return decode_reply(type);
   35 +}
   36 +
   37 +int
   38 +ssh_pkcs11_id (AuthenticationConnection *auth, const pkcs11_identity *id, int remove)
   39 +{
   40 +   Buffer msg;
   41 +   int type;
   42 +   int code;
   43 +
   44 +   code = remove ? SSH_AGENTC_PKCS11_REMOVE_ID : SSH_AGENTC_PKCS11_ADD_ID;
   45 +
   46 +   buffer_init(&msg);
   47 +   buffer_put_char(&msg, code);
   48 +   buffer_put_cstring(&msg, id->id);
   49 +   buffer_put_int(&msg, id->pin_cache_period);
   50 +   buffer_put_cstring(&msg, id->cert_file == NULL ? "" : id->cert_file);
   51 +
   52 +   if (ssh_request_reply(auth, &msg, &msg) == 0) {
   53 +       buffer_free(&msg);
   54 +       return 0;
   55 +   }
   56 +   type = buffer_get_char(&msg);
   57 +   buffer_free(&msg);
   58 +   return decode_reply(type);
   59 +}
   60 +
   61 +int
   62 +ssh_pkcs11_set_ask_pin (AuthenticationConnection *auth, const char *pin_prog)
   63 +{
   64 +   Buffer msg;
   65 +   int type;
   66 +   int code;
   67 +
   68 +   code = SSH_AGENTC_PKCS11_SET_ASK_PIN;
   69 +
   70 +   buffer_init(&msg);
   71 +   buffer_put_char(&msg, code);
   72 +   buffer_put_cstring(&msg, pin_prog);
   73 +
   74 +   if (ssh_request_reply(auth, &msg, &msg) == 0) {
   75 +       buffer_free(&msg);
   76 +       return 0;
   77 +   }
   78 +   type = buffer_get_char(&msg);
   79 +   buffer_free(&msg);
   80 +   return decode_reply(type);
   81 +}
   82 +
   83 +#endif /* SSH_PKCS11_DISABLED */
   84 diff -urNp openssh-4.4p1/authfd.h openssh-4.4p1+pkcs11-0.17/authfd.h
   85 --- openssh-4.4p1/authfd.h  2006-08-05 05:39:39.000000000 +0300
   86 +++ openssh-4.4p1+pkcs11-0.17/authfd.h  2006-10-12 13:57:49.000000000 +0200
   87 @@ -16,6 +16,8 @@
   88  #ifndef AUTHFD_H
   89  #define AUTHFD_H
   90  
   91 +#include "pkcs11.h"
   92 +
   93  /* Messages for the authentication agent connection. */
   94  #define SSH_AGENTC_REQUEST_RSA_IDENTITIES  1
   95  #define SSH_AGENT_RSA_IDENTITIES_ANSWER        2
   96 @@ -49,6 +51,11 @@
   97  #define SSH2_AGENTC_ADD_ID_CONSTRAINED     25
   98  #define SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED 26
   99  
  100 +#define SSH_AGENTC_PKCS11_ADD_PROVIDER     27
  101 +#define SSH_AGENTC_PKCS11_ADD_ID       28
  102 +#define SSH_AGENTC_PKCS11_REMOVE_ID        29
  103 +#define SSH_AGENTC_PKCS11_SET_ASK_PIN      30
  104 +
  105  #define    SSH_AGENT_CONSTRAIN_LIFETIME        1
  106  #define    SSH_AGENT_CONSTRAIN_CONFIRM     2
  107  
  108 @@ -92,4 +99,11 @@ int
  109  ssh_agent_sign(AuthenticationConnection *, Key *, u_char **, u_int *, u_char *,
  110      u_int);
  111  
  112 +#ifndef SSH_PKCS11_DISABLED
  113 +int    ssh_pkcs11_add_provider (AuthenticationConnection *, const char *,
  114 +    int, const char *, int);
  115 +int    ssh_pkcs11_id (AuthenticationConnection *, const pkcs11_identity *, int remove);
  116 +int    ssh_pkcs11_set_ask_pin (AuthenticationConnection *, const char *);
  117 +#endif /* SSH_PKCS11_DISABLED */
  118 +
  119  #endif             /* AUTHFD_H */
  120 diff -urNp openssh-4.4p1/ChangeLog.pkcs11 openssh-4.4p1+pkcs11-0.17/ChangeLog.pkcs11
  121 --- openssh-4.4p1/ChangeLog.pkcs11  1970-01-01 02:00:00.000000000 +0200
  122 +++ openssh-4.4p1+pkcs11-0.17/ChangeLog.pkcs11  2006-10-23 17:36:52.000000000 +0200
  123 @@ -0,0 +1,49 @@
  124 +20061023
  125 + - (alonbl) Removed logit from ssh-agent, thanks to Denniston, Todd.
  126 + - (alonbl) Release 0.17
  127 +
  128 +20061020
  129 + - (alonbl) Major modification of ssh-add command-line parameters.
  130 +   Now, a complete serialized certificate needs to be specified, this
  131 +   in order to allow people to add id without forcing card to be available.
  132 +   But to allow complete silent addition a certificate file also needed.
  133 +   --pkcs11-show-ids is used in order to get a list of resources.
  134 +   --pkcs11-add-id --pkcs11-id <serialized id> \
  135 +      [--pkcs11-cert-file <cert_file>]
  136 + - (alonbl) PKCS#11 release 0.16
  137 +
  138 +20061012
  139 + - (alonbl) OpenSC bug workaround.
  140 + - (alonbl) PKCS#11 release 0.15
  141 +
  142 +20060930
  143 + - (alonbl) Some pkcs11-helper updates.
  144 + - (alonbl) Rebase against 4.4p1.
  145 + - (alonbl) PKCS#11 release 0.14
  146 +
  147 +20060709
  148 + - (alonbl) PKCS#11 fixed handling multiproviders.
  149 + - (alonbl) PKCS#11 release 0.13
  150 +
  151 +20060608
  152 + - (alonbl) PKCS#11 modifed to match X.509-5.5 patch, works OK with focing
  153 +   ssh-rsa id.
  154 + - (alonbl) PKCS#11 removed --pkcs11-x509-force-ssh argument.
  155 + - (alonbl) PKCS#11 release 0.12
  156 +
  157 +20060527
  158 + - (alonbl) PKCS#11 fix issues with gcc-2
  159 + - (alonbl) PKCS#11 fix issues with openssl-0.9.6 (first) version.
  160 + - (alonbl) PKCS#11 modified to match X.509-5.4 patch.
  161 + - (alonbl) PKCS#11 add --pkcs11-x509-force-ssh argument to force ssh id out
  162 +   of X.509 certificate.
  163 + - (alonbl) PKCS#11 release 0.11
  164 +
  165 +20060419
  166 + - (alonbl) PKCS#11 fix handling empty attributes.
  167 + - (alonbl) PKCS#11 release 0.10
  168 +
  169 +20060404
  170 + - (alonbl) PKCS#11 code sync.
  171 + - (alonbl) PKCS#11 release 0.09
  172 +
  173 diff -urNp openssh-4.4p1/config.h.in openssh-4.4p1+pkcs11-0.17/config.h.in
  174 --- openssh-4.4p1/config.h.in   2006-09-26 14:03:33.000000000 +0300
  175 +++ openssh-4.4p1+pkcs11-0.17/config.h.in   2006-09-28 16:31:03.000000000 +0300
  176 @@ -1217,6 +1217,12 @@
  177  /* Use audit debugging module */
  178  #undef SSH_AUDIT_EVENTS
  179  
  180 +/* Define if you don't want use PKCS#11 */
  181 +#undef SSH_PKCS11_DISABLED
  182 +
  183 +/* Define if you don't want use X509 with PKCS#11 */
  184 +#undef SSH_PKCS11_X509_DISABLED
  185 +
  186  /* non-privileged user for privilege separation */
  187  #undef SSH_PRIVSEP_USER
  188  
  189 diff -urNp openssh-4.4p1/configure openssh-4.4p1+pkcs11-0.17/configure
  190 --- openssh-4.4p1/configure 2006-09-26 14:03:41.000000000 +0300
  191 +++ openssh-4.4p1+pkcs11-0.17/configure 2006-09-28 16:33:53.000000000 +0300
  192 @@ -1307,6 +1307,7 @@ Optional Features:
  193    --disable-libutil       disable use of libutil (login() etc.) no
  194    --disable-pututline     disable use of pututline() etc. (uwtmp) no
  195    --disable-pututxline    disable use of pututxline() etc. (uwtmpx) no
  196 +  --disable-pkcs11        Disable PKCS#11 support
  197  
  198  Optional Packages:
  199    --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
  200 @@ -32163,6 +32164,33 @@ if test ! -z "$blibpath" ; then
  201  echo "$as_me: WARNING: Please check and edit blibpath in LDFLAGS in Makefile" >&2;}
  202  fi
  203  
  204 +ssh_pkcs11="yes"
  205 +ssh_pkcs11_x509="yes"
  206 +# Check whether --enable-pkcs11 was given.
  207 +if test "${enable_pkcs11+set}" = set; then
  208 +  enableval=$enable_pkcs11;
  209 +   if test "x$enableval" = "xno"; then
  210 +       ssh_pkcs11="no"
  211 +   fi
  212 +
  213 +
  214 +fi
  215 +
  216 +if test "x$ssh_pkcs11" = "xno"; then
  217 +
  218 +cat >>confdefs.h <<_ACEOF
  219 +#define SSH_PKCS11_DISABLED 1
  220 +_ACEOF
  221 +
  222 +fi
  223 +if test "x$ssh_x509" = "x"; then
  224 +
  225 +cat >>confdefs.h <<_ACEOF
  226 +#define SSH_PKCS11_X509_DISABLED 1
  227 +_ACEOF
  228 +
  229 +fi
  230 +
  231  CFLAGS="$CFLAGS $werror_flags"
  232  
  233  
  234 @@ -33415,6 +33443,7 @@ echo "       IP address in \$DISPLAY hac
  235  echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
  236  echo "                  BSD Auth support: $BSD_AUTH_MSG"
  237  echo "              Random number source: $RAND_MSG"
  238 +echo "                   PKCS#11 support: $ssh_pkcs11"
  239  if test ! -z "$USE_RAND_HELPER" ; then
  240  echo "     ssh-rand-helper collects from: $RAND_HELPER_MSG"
  241  fi
  242 diff -urNp openssh-4.4p1/configure.ac openssh-4.4p1+pkcs11-0.17/configure.ac
  243 --- openssh-4.4p1/configure.ac  2006-09-24 22:08:59.000000000 +0300
  244 +++ openssh-4.4p1+pkcs11-0.17/configure.ac  2006-09-28 08:05:35.000000000 +0300
  245 @@ -3912,6 +3912,27 @@ if test ! -z "$blibpath" ; then
  246     AC_MSG_WARN([Please check and edit blibpath in LDFLAGS in Makefile])
  247  fi
  248  
  249 +ssh_pkcs11="yes"
  250 +ssh_pkcs11_x509="yes"
  251 +AC_ARG_ENABLE(pkcs11,
  252 +   [  --disable-pkcs11        Disable PKCS#11 support],
  253 +   [
  254 +   if test "x$enableval" = "xno"; then
  255 +       ssh_pkcs11="no"
  256 +   fi
  257 +   ]
  258 +)
  259 +if test "x$ssh_pkcs11" = "xno"; then
  260 +   AC_DEFINE_UNQUOTED(
  261 +       SSH_PKCS11_DISABLED, 1,
  262 +       [Define if you don't want use PKCS#11])
  263 +fi
  264 +if test "x$ssh_x509" = "x"; then
  265 +   AC_DEFINE_UNQUOTED(
  266 +       SSH_PKCS11_X509_DISABLED, 1,
  267 +       [Define if you don't want use X509 with PKCS#11])
  268 +fi
  269 +
  270  dnl Adding -Werror to CFLAGS early prevents configure tests from running.
  271  dnl Add now.
  272  CFLAGS="$CFLAGS $werror_flags"
  273 @@ -3973,6 +3994,7 @@ echo "       IP address in \$DISPLAY hac
  274  echo "           Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
  275  echo "                  BSD Auth support: $BSD_AUTH_MSG"
  276  echo "              Random number source: $RAND_MSG"
  277 +echo "                   PKCS#11 support: $ssh_pkcs11"
  278  if test ! -z "$USE_RAND_HELPER" ; then
  279  echo "     ssh-rand-helper collects from: $RAND_HELPER_MSG"
  280  fi
  281 diff -urNp openssh-4.4p1/cryptoki.h openssh-4.4p1+pkcs11-0.17/cryptoki.h
  282 --- openssh-4.4p1/cryptoki.h    1970-01-01 02:00:00.000000000 +0200
  283 +++ openssh-4.4p1+pkcs11-0.17/cryptoki.h    2006-09-28 08:05:35.000000000 +0300
  284 @@ -0,0 +1,35 @@
  285 +/* cryptoki.h include file for PKCS #11. */
  286 +/* $Revision: 1.4 $ */
  287 +
  288 +/* License to copy and use this software is granted provided that it is
  289 + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
  290 + * (Cryptoki)" in all material mentioning or referencing this software.
  291 +
  292 + * License is also granted to make and use derivative works provided that
  293 + * such works are identified as "derived from the RSA Security Inc. PKCS #11
  294 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or 
  295 + * referencing the derived work.
  296 +
  297 + * RSA Security Inc. makes no representations concerning either the 
  298 + * merchantability of this software or the suitability of this software for
  299 + * any particular purpose. It is provided "as is" without express or implied
  300 + * warranty of any kind.
  301 + */
  302 +
  303 +#ifndef ___CRYPTOKI_H_INC___
  304 +#define ___CRYPTOKI_H_INC___
  305 +
  306 +#define CK_PTR *
  307 +
  308 +#define CK_DEFINE_FUNCTION(returnType, name) returnType name
  309 +#define CK_DECLARE_FUNCTION(returnType, name) returnType name
  310 +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
  311 +#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
  312 +
  313 +#ifndef NULL_PTR
  314 +#define NULL_PTR 0
  315 +#endif
  316 +
  317 +#include "pkcs11-headers/pkcs11.h"
  318 +
  319 +#endif /* ___CRYPTOKI_H_INC___ */
  320 diff -urNp openssh-4.4p1/cryptoki-win32.h openssh-4.4p1+pkcs11-0.17/cryptoki-win32.h
  321 --- openssh-4.4p1/cryptoki-win32.h  1970-01-01 02:00:00.000000000 +0200
  322 +++ openssh-4.4p1+pkcs11-0.17/cryptoki-win32.h  2006-09-28 08:05:35.000000000 +0300
  323 @@ -0,0 +1,66 @@
  324 +/* cryptoki.h include file for PKCS #11. */
  325 +/* $Revision: 1.4 $ */
  326 +
  327 +/* License to copy and use this software is granted provided that it is
  328 + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
  329 + * (Cryptoki)" in all material mentioning or referencing this software.
  330 +
  331 + * License is also granted to make and use derivative works provided that
  332 + * such works are identified as "derived from the RSA Security Inc. PKCS #11
  333 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or 
  334 + * referencing the derived work.
  335 +
  336 + * RSA Security Inc. makes no representations concerning either the 
  337 + * merchantability of this software or the suitability of this software for
  338 + * any particular purpose. It is provided "as is" without express or implied
  339 + * warranty of any kind.
  340 + */
  341 +
  342 +/* This is a sample file containing the top level include directives
  343 + * for building Win32 Cryptoki libraries and applications.
  344 + */
  345 +
  346 +#ifndef ___CRYPTOKI_H_INC___
  347 +#define ___CRYPTOKI_H_INC___
  348 +
  349 +#pragma pack(push, cryptoki, 1)
  350 +
  351 +/* Specifies that the function is a DLL entry point. */
  352 +#define CK_IMPORT_SPEC __declspec(dllimport)
  353 +
  354 +/* Define CRYPTOKI_EXPORTS during the build of cryptoki libraries. Do
  355 + * not define it in applications.
  356 + */
  357 +#ifdef CRYPTOKI_EXPORTS
  358 +/* Specified that the function is an exported DLL entry point. */
  359 +#define CK_EXPORT_SPEC __declspec(dllexport) 
  360 +#else
  361 +#define CK_EXPORT_SPEC CK_IMPORT_SPEC 
  362 +#endif
  363 +
  364 +/* Ensures the calling convention for Win32 builds */
  365 +#define CK_CALL_SPEC __cdecl
  366 +
  367 +#define CK_PTR *
  368 +
  369 +#define CK_DEFINE_FUNCTION(returnType, name) \
  370 +  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
  371 +
  372 +#define CK_DECLARE_FUNCTION(returnType, name) \
  373 +  returnType CK_EXPORT_SPEC CK_CALL_SPEC name
  374 +
  375 +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
  376 +  returnType CK_IMPORT_SPEC (CK_CALL_SPEC CK_PTR name)
  377 +
  378 +#define CK_CALLBACK_FUNCTION(returnType, name) \
  379 +  returnType (CK_CALL_SPEC CK_PTR name)
  380 +
  381 +#ifndef NULL_PTR
  382 +#define NULL_PTR 0
  383 +#endif
  384 +
  385 +#include "pkcs11-headers/pkcs11.h"
  386 +
  387 +#pragma pack(pop, cryptoki)
  388 +
  389 +#endif /* ___CRYPTOKI_H_INC___ */
  390 diff -urNp openssh-4.4p1/LICENCE openssh-4.4p1+pkcs11-0.17/LICENCE
  391 --- openssh-4.4p1/LICENCE   2006-08-30 20:24:41.000000000 +0300
  392 +++ openssh-4.4p1+pkcs11-0.17/LICENCE   2006-09-28 08:05:35.000000000 +0300
  393 @@ -332,6 +332,9 @@ OpenSSH contains no GPL code.
  394     * authorization.                                                           *
  395     ****************************************************************************/
  396  
  397 +    d) PKCS #11: Cryptographic Token Interface Standard
  398 +
  399 +   This software uses RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
  400  
  401  ------
  402  $OpenBSD: LICENCE,v 1.19 2004/08/30 09:18:08 markus Exp $
  403 diff -urNp openssh-4.4p1/Makefile.in openssh-4.4p1+pkcs11-0.17/Makefile.in
  404 --- openssh-4.4p1/Makefile.in   2006-09-12 14:54:10.000000000 +0300
  405 +++ openssh-4.4p1+pkcs11-0.17/Makefile.in   2006-09-28 08:05:35.000000000 +0300
  406 @@ -66,6 +66,7 @@ TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-a
  407  
  408  LIBSSH_OBJS=acss.o authfd.o authfile.o bufaux.o bufbn.o buffer.o \
  409     canohost.o channels.o cipher.o cipher-acss.o cipher-aes.o \
  410 +   pkcs11.o pkcs11-helper.o \
  411     cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
  412     compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
  413     log.o match.o md-sha256.o moduli.o nchan.o packet.o \
  414 diff -urNp openssh-4.4p1/pkcs11.c openssh-4.4p1+pkcs11-0.17/pkcs11.c
  415 --- openssh-4.4p1/pkcs11.c  1970-01-01 02:00:00.000000000 +0200
  416 +++ openssh-4.4p1+pkcs11-0.17/pkcs11.c  2006-10-23 17:35:54.000000000 +0200
  417 @@ -0,0 +1,1139 @@
  418 +/*
  419 + * Copyright (c) 2005-2006 Alon Bar-Lev.  All rights reserved.
  420 + *
  421 + * Redistribution and use in source and binary forms, with or without
  422 + * modification, are permitted provided that the following conditions
  423 + * are met:
  424 + * 1. Redistributions of source code must retain the above copyright
  425 + *    notice, this list of conditions and the following disclaimer.
  426 + * 2. Redistributions in binary form must reproduce the above copyright
  427 + *    notice, this list of conditions and the following disclaimer in the
  428 + *    documentation and/or other materials provided with the distribution.
  429 + *
  430 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  431 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  432 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  433 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  434 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  435 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  436 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  437 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  438 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  439 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  440 + */
  441 +
  442 +/*
  443 + * The routines in this file deal with providing private key cryptography
  444 + * using RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
  445 + *
  446 + */
  447 +
  448 +#include "includes.h"
  449 +#include <sys/wait.h>
  450 +#include <errno.h>
  451 +
  452 +#if !defined(SSH_PKCS11_DISABLED)
  453 +
  454 +#include "pkcs11-helper.h"
  455 +#include "pkcs11.h"
  456 +#include "openssl/pem.h"
  457 +#include "misc.h"
  458 +
  459 +static
  460 +char *
  461 +ssh_from_x509 (X509 *x509);
  462 +
  463 +static char *s_szSetPINProg = NULL;
  464 +
  465 +static
  466 +unsigned
  467 +_pkcs11_msg_pkcs112openssh (
  468 +   IN const unsigned flags
  469 +) {
  470 +   unsigned openssh_flags;
  471 +
  472 +   switch (flags) {
  473 +       case PKCS11H_LOG_DEBUG2:
  474 +           openssh_flags = SYSLOG_LEVEL_DEBUG3;
  475 +       break;
  476 +       case PKCS11H_LOG_DEBUG1:
  477 +           openssh_flags = SYSLOG_LEVEL_DEBUG2;
  478 +       break;
  479 +       case PKCS11H_LOG_INFO:
  480 +           openssh_flags = SYSLOG_LEVEL_INFO;
  481 +       break;
  482 +       case PKCS11H_LOG_WARN:
  483 +           openssh_flags = SYSLOG_LEVEL_ERROR;
  484 +       break;
  485 +       case PKCS11H_LOG_ERROR:
  486 +           openssh_flags = SYSLOG_LEVEL_FATAL;
  487 +       break;
  488 +       default:
  489 +           openssh_flags = SYSLOG_LEVEL_FATAL;
  490 +       break;
  491 +   }
  492 +
  493 +   return openssh_flags;
  494 +}
  495 +
  496 +static
  497 +unsigned
  498 +_pkcs11_msg_openssh2pkcs11 (
  499 +   IN const unsigned flags
  500 +) {
  501 +   unsigned pkcs11_flags;
  502 +
  503 +   switch (flags) {
  504 +       case SYSLOG_LEVEL_DEBUG3:
  505 +           pkcs11_flags = PKCS11H_LOG_DEBUG2;
  506 +       break;
  507 +       case SYSLOG_LEVEL_DEBUG2:
  508 +           pkcs11_flags = PKCS11H_LOG_DEBUG1;
  509 +       break;
  510 +       case SYSLOG_LEVEL_INFO:
  511 +           pkcs11_flags = PKCS11H_LOG_INFO;
  512 +       break;
  513 +       case SYSLOG_LEVEL_ERROR:
  514 +           pkcs11_flags = PKCS11H_LOG_WARN;
  515 +       break;
  516 +       case SYSLOG_LEVEL_FATAL:
  517 +           pkcs11_flags = PKCS11H_LOG_ERROR;
  518 +       break;
  519 +       default:
  520 +           pkcs11_flags = PKCS11H_LOG_ERROR;
  521 +       break;
  522 +   }
  523 +
  524 +   return pkcs11_flags;
  525 +}
  526 +
  527 +static
  528 +void
  529 +_pkcs11_openssh_log (
  530 +   IN void * const pData,
  531 +   IN unsigned flags,
  532 +   IN const char * const szFormat,
  533 +   IN va_list args
  534 +) {
  535 +   do_log (_pkcs11_msg_pkcs112openssh (flags), szFormat, args);
  536 +}
  537 +
  538 +static
  539 +int
  540 +_pkcs11_ssh_prompt (
  541 +   IN const char * const szType,
  542 +   IN const char * const szPrompt,
  543 +   OUT char * const szInput,
  544 +   IN const int nMaxInput
  545 +) {
  546 +   pid_t pid = -1;
  547 +   int fds[2] = {-1, -1};
  548 +   int fOK = TRUE;
  549 +
  550 +   /*
  551 +    * Make sure we don't reuse PIN
  552 +    */
  553 +   if (fOK) {
  554 +       memset (szInput, 0, nMaxInput);
  555 +   }
  556 +
  557 +   if (fOK && s_szSetPINProg == NULL) {
  558 +       fOK = FALSE;
  559 +   }
  560 +
  561 +   if (fOK && pipe (fds) == -1) {
  562 +       fOK = FALSE;
  563 +   }
  564 +
  565 +   if (fOK && (pid = fork ()) == -1) {
  566 +       fOK = FALSE;
  567 +   }
  568 +
  569 +   if (fOK) {
  570 +       if (pid == 0) {
  571 +           close (fds[0]);
  572 +           fds[0] = -1;
  573 +
  574 +           if (fOK && dup2 (fds[1], 1) == -1) {
  575 +               fOK = FALSE;
  576 +           }
  577 +           if (fOK) {
  578 +               close (fds[1]);
  579 +               fds[1] = -1;
  580 +           }
  581 +
  582 +           if (fOK) {
  583 +               execl (
  584 +                   s_szSetPINProg,
  585 +                   s_szSetPINProg,
  586 +                   "-t",
  587 +                   szType,
  588 +                   szPrompt,
  589 +                   NULL
  590 +               );
  591 +           }
  592 +
  593 +           exit (1);
  594 +       }
  595 +       else {
  596 +           int status;
  597 +           int r = 0;
  598 +           
  599 +           close (fds[1]);
  600 +           fds[1] = -1;
  601 +
  602 +           if (fOK) {
  603 +               while (
  604 +                   (r=waitpid (pid, &status, 0)) == 0 ||
  605 +                   (r == -1 && errno == EINTR)
  606 +               );
  607 +
  608 +               if (r == -1) {
  609 +                   fOK = FALSE;
  610 +               }
  611 +           }
  612 +
  613 +           if (fOK && !WIFEXITED (status)) {
  614 +               fOK = FALSE;
  615 +           }
  616 +
  617 +           if (fOK && WEXITSTATUS (status) != 0) {
  618 +               fOK = FALSE;
  619 +           }
  620 +           
  621 +           if (fOK) {
  622 +               if (!strcmp (szType, "password")) {
  623 +                   if ((r = read (fds[0], szInput, nMaxInput)) == -1) {
  624 +                       fOK = FALSE;
  625 +                       r = 0;
  626 +                   }
  627 +               }
  628 +               else {
  629 +                   r = 0;
  630 +               }
  631 +               szInput[r] = '\0';
  632 +           }
  633 +
  634 +           if (fOK) {
  635 +               if (strlen (szInput) > 0 && szInput[strlen (szInput)-1] == '\n') {
  636 +                   szInput[strlen (szInput)-1] = '\0';
  637 +               }
  638 +               /*
  639 +                * for DOS compatability
  640 +                */
  641 +               if (strlen (szInput) > 0 && szInput[strlen (szInput)-1] == '\r') {
  642 +                   szInput[strlen (szInput)-1] = '\0';
  643 +               }
  644 +           }
  645 +       }
  646 +   }
  647 +
  648 +   if (fds[0] != -1) {
  649 +       close (fds[0]);
  650 +       fds[0] = -1;
  651 +   }
  652 +
  653 +   if (fds[1] != -1) {
  654 +       close (fds[1]);
  655 +       fds[1] = -1;
  656 +   }
  657 +
  658 +   return fOK;
  659 +}
  660 +
  661 +static
  662 +void
  663 +_pkcs11_ssh_print (
  664 +   IN void * const pData,
  665 +   IN const char * const szFormat,
  666 +   IN ...
  667 +) {
  668 +   va_list args;
  669 +
  670 +   va_start (args, szFormat);
  671 +   vprintf (szFormat, args);
  672 +   va_end (args);
  673 +}
  674 +
  675 +static
  676 +PKCS11H_BOOL
  677 +_pkcs11_ssh_token_prompt (
  678 +   IN void * const pData1,
  679 +   IN void * const pData2,
  680 +   IN const pkcs11h_token_id_t token,
  681 +   IN const unsigned retry
  682 +) {
  683 +   char szPrompt[1024];
  684 +   char szPIN[1024];
  685 +   
  686 +   snprintf (szPrompt, sizeof (szPrompt), "Please insert token '%s' or cancel", token->display);
  687 +   return _pkcs11_ssh_prompt ("okcancel", szPrompt, szPIN, sizeof (szPIN));
  688 +}
  689 +
  690 +static
  691 +PKCS11H_BOOL
  692 +_pkcs11_ssh_pin_prompt (
  693 +   IN void * const pData1,
  694 +   IN void * const pData2,
  695 +   IN const pkcs11h_token_id_t token,
  696 +   IN const unsigned retry,
  697 +   OUT char * const szPIN,
  698 +   IN const size_t nMaxPIN
  699 +) {
  700 +   char szPrompt[1024];
  701 +
  702 +   snprintf (szPrompt, sizeof (szPrompt), "Please enter PIN for token '%s'", token->display);
  703 +   return _pkcs11_ssh_prompt ("password", szPrompt, szPIN, nMaxPIN);
  704 +}
  705 +
  706 +static
  707 +PKCS11H_BOOL
  708 +_pkcs11_ssh_pin_prompt_cli (
  709 +   IN void * const pData1,
  710 +   IN void * const pData2,
  711 +   IN const pkcs11h_token_id_t token,
  712 +   IN const unsigned retry,
  713 +   OUT char * const szPIN,
  714 +   IN const size_t nMaxPIN
  715 +) {
  716 +   char szPrompt[1024];
  717 +   snprintf (szPrompt, sizeof (szPrompt), "Please enter '%s' PIN or 'cancel': ", token->display);
  718 +   char *p = getpass (szPrompt);
  719 +
  720 +   strncpy (szPIN, p, nMaxPIN);
  721 +   szPIN[nMaxPIN-1] = '\0';
  722 +
  723 +   return strcmp (szPIN, "cancel") != 0;
  724 +}
  725 +
  726 +void
  727 +_pkcs11_do_log (
  728 +   IN LogLevel l,
  729 +   IN const char *f,
  730 +   IN ...
  731 +) {
  732 +   va_list args;
  733 +   va_start (args, f);
  734 +   do_log (l, f, args);
  735 +   va_end (args);
  736 +}
  737 +
  738 +int
  739 +pkcs11_initialize (
  740 +   const int fProtectedAuthentication,
  741 +   const int nPINCachePeriod
  742 +) {
  743 +   CK_RV rv = CKR_OK;
  744 +
  745 +   debug3 (
  746 +       "PKCS#11: pkcs11_initialize - entered fProtectedAuthentication=%d, nPINCachePeriod=%d",
  747 +       fProtectedAuthentication,
  748 +       nPINCachePeriod
  749 +   );
  750 +
  751 +   if (
  752 +       rv == CKR_OK &&
  753 +       (rv = pkcs11h_initialize ()) != CKR_OK
  754 +   ) {
  755 +       error ("PKCS#11: Cannot initialize %ld-'%s'", rv, pkcs11h_getMessage (rv));
  756 +   }
  757 +
  758 +   if (
  759 +       rv == CKR_OK &&
  760 +       (rv = pkcs11h_setLogHook (_pkcs11_openssh_log, NULL)) != CKR_OK
  761 +   ) {
  762 +       error ("PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
  763 +   }
  764 +
  765 +   /*
  766 +    * WARNING!!!
  767 +    * There is no way to get log level,
  768 +    * so set to minimum.
  769 +    * After fix in log.c it can be fixed.
  770 +    */
  771 +   if (rv == CKR_OK) {
  772 +       pkcs11h_setLogLevel (_pkcs11_msg_openssh2pkcs11 (SYSLOG_LEVEL_DEBUG3));
  773 +   }
  774 +
  775 +   if (
  776 +       rv == CKR_OK &&
  777 +       (rv = pkcs11h_setTokenPromptHook (_pkcs11_ssh_token_prompt, NULL)) != CKR_OK
  778 +   ) {
  779 +       error ("PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
  780 +   }
  781 +
  782 +   if (
  783 +       rv == CKR_OK &&
  784 +       (rv = pkcs11h_setPINPromptHook (_pkcs11_ssh_pin_prompt, NULL)) != CKR_OK
  785 +   ) {
  786 +       error ("PKCS#11: Cannot set hooks %ld-'%s'", rv, pkcs11h_getMessage (rv));
  787 +   }
  788 +
  789 +   if (
  790 +       rv == CKR_OK &&
  791 +       (rv = pkcs11h_setProtectedAuthentication (fProtectedAuthentication)) != CKR_OK
  792 +   ) {
  793 +       error ("PKCS#11: Cannot set protected authentication mode %ld-'%s'", rv, pkcs11h_getMessage (rv));
  794 +   }
  795 +
  796 +   if (
  797 +       rv == CKR_OK &&
  798 +       (rv = pkcs11h_setPINCachePeriod (nPINCachePeriod)) != CKR_OK
  799 +   ) {
  800 +       error ("PKCS#11: Cannot set PIN cache period %ld-'%s'", rv, pkcs11h_getMessage (rv));
  801 +   }
  802 +
  803 +   debug3 (
  804 +       "PKCS#11: pkcs11_initialize - return rv=%ld-'%s'",
  805 +       rv,
  806 +       pkcs11h_getMessage (rv)
  807 +   );
  808 +
  809 +   return rv == CKR_OK;
  810 +}
  811 +
  812 +void
  813 +pkcs11_terminate () {
  814 +   debug3 ("PKCS#11: pkcs11_terminate - entered");
  815 +
  816 +   pkcs11h_terminate ();
  817 +
  818 +   debug3 ("PKCS#11: pkcs11_terminate - return");
  819 +}
  820 +
  821 +void
  822 +pkcs11_forkFix () {
  823 +   pkcs11h_forkFixup ();
  824 +}
  825 +
  826 +int
  827 +pkcs11_setAskPIN (
  828 +   const char * const pin_prog
  829 +) {
  830 +   if (pin_prog != NULL) {
  831 +       if (s_szSetPINProg != NULL) {
  832 +           xfree (s_szSetPINProg);
  833 +           s_szSetPINProg = NULL;
  834 +       }
  835 +
  836 +       s_szSetPINProg = xstrdup (pin_prog);
  837 +   }
  838 +
  839 +   return 1;
  840 +}
  841 +
  842 +int
  843 +pkcs11_addProvider (
  844 +   const char * const provider,
  845 +   const int fProtectedAuthentication,
  846 +   const char * const sign_mode,
  847 +   const int fCertIsPrivate
  848 +) {
  849 +   unsigned maskSignMode = 0;
  850 +   CK_RV rv = CKR_OK;
  851 +
  852 +   PKCS11H_ASSERT (provider != NULL);
  853 +   PKCS11H_ASSERT (sign_mode != NULL);
  854 +
  855 +   debug3 (
  856 +       "PKCS#11: pkcs11_addProvider - entered - provider='%s', fProtectedAuthentication=%d, sign_mode='%s',
	fCertIsPrivate=%d",
  857 +       provider,
  858 +       fProtectedAuthentication ? 1 : 0,
  859 +       sign_mode == NULL ? "default" : sign_mode,
  860 +       fCertIsPrivate ? 1 : 0
  861 +   );
  862 +
  863 +   debug (
  864 +       "PKCS#11: Adding PKCS#11 provider '%s'",
  865 +       provider
  866 +   );
  867 +
  868 +   if (rv == CKR_OK) {
  869 +       if (sign_mode == NULL || !strcmp (sign_mode, "auto")) {
  870 +           maskSignMode = 0;
  871 +       }
  872 +       else if (!strcmp (sign_mode, "sign")) {
  873 +           maskSignMode = PKCS11H_SIGNMODE_MASK_SIGN;
  874 +       }
  875 +       else if (!strcmp (sign_mode, "recover")) {
  876 +           maskSignMode = PKCS11H_SIGNMODE_MASK_RECOVER;
  877 +       }
  878 +       else if (!strcmp (sign_mode, "any")) {
  879 +           maskSignMode = (
  880 +               PKCS11H_SIGNMODE_MASK_SIGN |
  881 +               PKCS11H_SIGNMODE_MASK_RECOVER
  882 +           );
  883 +       }
  884 +       else {
  885 +           error ("PKCS#11: Invalid sign mode '%s'", sign_mode);
  886 +           rv = CKR_ARGUMENTS_BAD;
  887 +       }
  888 +   }
  889 +
  890 +   if (
  891 +       rv == CKR_OK &&
  892 +       (rv = pkcs11h_addProvider (
  893 +           provider,
  894 +           provider,
  895 +           fProtectedAuthentication,
  896 +           maskSignMode,
  897 +           PKCS11H_SLOTEVENT_METHOD_AUTO,
  898 +           0,
  899 +           fCertIsPrivate
  900 +       )) != CKR_OK
  901 +   ) {
  902 +       error ("PKCS#11: Cannot initialize provider '%s' %ld-'%s'", provider, rv, pkcs11h_getMessage (rv));
  903 +   }
  904 +
  905 +   debug3 (
  906 +       "PKCS#11: pkcs11_addProvider - return rv=%ld-'%s'",
  907 +       rv,
  908 +       pkcs11h_getMessage (rv)
  909 +   );
  910 +
  911 +   return rv == CKR_OK;
  912 +}
  913 +
  914 +pkcs11_identity *
  915 +pkcs11_identity_new () {
  916 +   pkcs11_identity *id = xmalloc (sizeof (struct pkcs11_identity_s));
  917 +   if (id != NULL) {
  918 +       memset (id, 0, sizeof (struct pkcs11_identity_s));
  919 +   }
  920 +   return id;
  921 +}
  922 +
  923 +void
  924 +pkcs11_identity_free (
  925 +   const pkcs11_identity * const id
  926 +) {
  927 +   if (id != NULL) {
  928 +       xfree ((void *)id);
  929 +   }
  930 +}
  931 +
  932 +void
  933 +pkcs11_getKey (
  934 +   IN const pkcs11_identity * const id,
  935 +   OUT Key ** const sshkey,
  936 +   OUT char * const szComment,
  937 +   IN const int nCommentMax
  938 +) {
  939 +   X509 *x509 = NULL;
  940 +   RSA *rsa = NULL;
  941 +   pkcs11h_certificate_id_t certificate_id = NULL;
  942 +   pkcs11h_certificate_t certificate = NULL;
  943 +   pkcs11h_openssl_session_t openssl_session = NULL;
  944 +   size_t temp;
  945 +   CK_RV rv = CKR_OK;
  946 +
  947 +   int fOK = TRUE;
  948 +
  949 +   debug3 (
  950 +       "PKCS#11: pkcs11_getKey - entered - id=%p, sshkey=%p, szComment=%p, nCommentMax=%d",
  951 +       (void *)id,
  952 +       (void *)sshkey,
  953 +       (void *)szComment,
  954 +       nCommentMax
  955 +   );
  956 +
  957 +   PKCS11H_ASSERT (id != NULL);
  958 +   PKCS11H_ASSERT (sshkey!=NULL);
  959 +   PKCS11H_ASSERT (szComment!=NULL);
  960 +
  961 +   debug3 (
  962 +       "PKCS#11: pkcs11_getKey - id - id=%s, pin_cache_period=%d, cert_file=%s",
  963 +       id->id,
  964 +       id->pin_cache_period,
  965 +       id->cert_file
  966 +   );
  967 +
  968 +   PKCS11H_ASSERT (id->id);
  969 +
  970 +   if (
  971 +       fOK &&
  972 +       pkcs11h_certificate_deserializeCertificateId (&certificate_id, id->id)
  973 +   ) {
  974 +       fOK = FALSE;
  975 +       error ("PKCS#11: Cannot deserialize id %ld-'%s'", rv, pkcs11h_getMessage (rv));
  976 +   }
  977 +
  978 +   if (
  979 +       fOK &&
  980 +       id->cert_file != NULL &&
  981 +       id->cert_file[0] != '\x0' 
  982 +   ) {
  983 +       X509 *x509 = NULL;
  984 +       unsigned char *p = NULL;
  985 +       unsigned char *certificate_blob = NULL;
  986 +       size_t certificate_blob_size = 0;
  987 +       FILE *fp = NULL;
  988 +
  989 +       if (
  990 +           fOK &&
  991 +           (fp = fopen (id->cert_file, "r")) == NULL
  992 +       ) {
  993 +           fOK = FALSE;
  994 +           error ("PKCS#11: Cannot open file '%s'", id->cert_file);
  995 +       }
  996 +
  997 +       if (
  998 +           fOK &&
  999 +           !PEM_read_X509 (
 1000 +               fp,
 1001 +               &x509,
 1002 +               NULL,
 1003 +               0
 1004 +           )
 1005 +       ) {
 1006 +           x509 = NULL;
 1007 +           fOK = FALSE;
 1008 +           error ("PKCS#11: Cannot read PEM from file '%s'", id->cert_file);
 1009 +       }
 1010 +
 1011 +       if (
 1012 +           fOK &&
 1013 +           (certificate_blob_size = i2d_X509 (x509, NULL)) < 0
 1014 +       ) {
 1015 +           fOK = FALSE;
 1016 +           error ("PKCS#11: Cannot read decode certificate");
 1017 +       }
 1018 +
 1019 +       if (
 1020 +           fOK &&
 1021 +           (certificate_blob = (unsigned char *)xmalloc (certificate_blob_size)) == NULL
 1022 +       ) {
 1023 +           fOK = FALSE;
 1024 +           error ("PKCS#11: Cannot allocate memory");
 1025 +       }
 1026 +
 1027 +       /*
 1028 +        * i2d_X509 increments p!!!
 1029 +        */
 1030 +       p = certificate_blob;
 1031 +
 1032 +       if (
 1033 +           fOK &&
 1034 +           (certificate_blob_size = i2d_X509 (x509, &p)) < 0
 1035 +       ) {
 1036 +           fOK = FALSE;
 1037 +           error ("PKCS#11: Cannot read decode certificate");
 1038 +       }
 1039 +
 1040 +       if (
 1041 +           fOK &&
 1042 +           pkcs11h_certificate_setCertificateIdCertificateBlob (
 1043 +               certificate_id,
 1044 +               certificate_blob,
 1045 +               certificate_blob_size
 1046 +           ) != CKR_OK
 1047 +       ) {
 1048 +           fOK = FALSE;
 1049 +           error ("PKCS#11: Cannot set certificate blob %ld-'%s'", rv, pkcs11h_getMessage (rv));
 1050 +       }
 1051 +
 1052 +       if (x509 != NULL) {
 1053 +           X509_free (x509);
 1054 +           x509 = NULL;
 1055 +       }
 1056 +
 1057 +       if (certificate_blob != NULL) {
 1058 +           xfree (certificate_blob);
 1059 +           certificate_blob = NULL;
 1060 +       }
 1061 +
 1062 +       if (fp != NULL) {
 1063 +           fclose (fp);
 1064 +           fp = NULL;
 1065 +       }
 1066 +   }
 1067 +
 1068 +   if (
 1069 +       fOK &&
 1070 +       (rv = pkcs11h_certificate_create (
 1071 +           certificate_id,
 1072 +           NULL,
 1073 +           PKCS11H_PROMPT_MASK_ALLOW_ALL,
 1074 +           id->pin_cache_period,
 1075 +           &certificate
 1076 +       )) != CKR_OK
 1077 +   ) {
 1078 +       fOK = FALSE;
 1079 +       error ("PKCS#11: Cannot get certificate %ld-'%s'", rv, pkcs11h_getMessage (rv));
 1080 +   }
 1081 +
 1082 +   if (certificate_id != NULL){
 1083 +       pkcs11h_certificate_freeCertificateId (certificate_id);
 1084 +       certificate_id = NULL;
 1085 +   }
 1086 +
 1087 +   /*
 1088 +    * Is called so next certificate_id will
 1089 +    * contain a proper description
 1090 +    */
 1091 +   if (
 1092 +       fOK &&
 1093 +       (rv = pkcs11h_certificate_getCertificateBlob (
 1094 +           certificate,
 1095 +           NULL,
 1096 +           &temp
 1097 +       )) != CKR_OK
 1098 +   ) {
 1099 +       fOK = FALSE;
 1100 +       error ("PKCS#11: Cannot get certificate blob %ld-'%s'", rv, pkcs11h_getMessage (rv));
 1101 +   }
 1102 +
 1103 +   if (
 1104 +       fOK &&
 1105 +       (rv = pkcs11h_certificate_getCertificateId (
 1106 +           certificate,
 1107 +           &certificate_id
 1108 +       )) != CKR_OK
 1109 +   ) {
 1110 +       fOK = FALSE;
 1111 +       error ("PKCS#11: Cannot get certificate_id %ld-'%s'", rv, pkcs11h_getMessage (rv));
 1112 +   }
 1113 +
 1114 +   if (fOK) {
 1115 +       strncpy (szComment, certificate_id->displayName, nCommentMax);
 1116 +       szComment[nCommentMax - 1] = '\0';
 1117 +   }
 1118 +
 1119 +   if (
 1120 +       fOK &&
 1121 +       (openssl_session = pkcs11h_openssl_createSession (certificate)) == NULL
 1122 +   ) {
 1123 +       fOK = FALSE;
 1124 +       error ("PKCS#11: Cannot initialize openssl session");
 1125 +   }
 1126 +
 1127 +   if (fOK) {
 1128 +       /*
 1129 +        * will be release by openssl_session
 1130 +        */
 1131 +       certificate = NULL;
 1132 +   }
 1133 +
 1134 +   if (
 1135 +       fOK &&
 1136 +       (rsa = pkcs11h_openssl_session_getRSA (openssl_session)) == NULL
 1137 +   ) {
 1138 +       fOK = FALSE;
 1139 +       error ("PKCS#11: Unable get rsa object");
 1140 +   }
 1141 +
 1142 +   if (
 1143 +       fOK &&
 1144 +       (x509 = pkcs11h_openssl_session_getX509 (openssl_session)) == NULL
 1145 +   ) {
 1146 +       fOK = FALSE;
 1147 +       error ("PKCS#11: Unable get certificate object");
 1148 +   }
 1149 +
 1150 +   if (fOK) {
 1151 +       *sshkey = key_new_private (KEY_UNSPEC);
 1152 +       (*sshkey)->rsa = rsa;
 1153 +       rsa = NULL;
 1154 +#if defined(SSH_PKCS11_X509_DISABLED)
 1155 +       (*sshkey)->type = KEY_RSA;
 1156 +#else
 1157 +       (*sshkey)->type = KEY_X509_RSA;
 1158 +       (*sshkey)->x509 = x509;
 1159 +       x509 = NULL;
 1160 +#endif
 1161 +   }
 1162 +
 1163 +   if (x509 != NULL) {
 1164 +       X509_free (x509);
 1165 +       x509 = NULL;
 1166 +   }
 1167 +
 1168 +   if (openssl_session != NULL) {
 1169 +       pkcs11h_openssl_freeSession (openssl_session);
 1170 +       openssl_session = NULL;
 1171 +   }
 1172 +
 1173 +   if (certificate != NULL) {
 1174 +       pkcs11h_certificate_freeCertificate (certificate);
 1175 +       certificate = NULL;
 1176 +   }
 1177 +
 1178 +   if (certificate_id != NULL) {
 1179 +       pkcs11h_certificate_freeCertificateId (certificate_id);
 1180 +       certificate_id = NULL;
 1181 +   }
 1182 +
 1183 +   debug3 (
 1184 +       "PKCS#11: pkcs11_getKey - return fOK=%d, rv=%ld",
 1185 +       fOK ? 1 : 0,
 1186 +       rv
 1187 +   );
 1188 +}
 1189 +
 1190 +void
 1191 +pkcs11_show_ids (
 1192 +   const char * const provider,
 1193 +   int allow_protected_auth,
 1194 +   int cert_is_private
 1195 +) {
 1196 +   pkcs11h_certificate_id_list_t user_certificates = NULL;
 1197 +   pkcs11h_certificate_id_list_t current = NULL;
 1198 +   CK_RV rv = CKR_OK;
 1199 +
 1200 +   if (rv == CKR_OK) {
 1201 +       rv = pkcs11h_initialize ();
 1202 +   }
 1203 +
 1204 +   if (rv == CKR_OK) {
 1205 +       rv = pkcs11h_setLogHook (_pkcs11_openssh_log, NULL);
 1206 +   }
 1207 +
 1208 +   if (rv == CKR_OK) {
 1209 +       pkcs11h_setLogLevel (_pkcs11_msg_openssh2pkcs11 (SYSLOG_LEVEL_DEBUG3));
 1210 +   }
 1211 +
 1212 +   if (rv == CKR_OK) {
 1213 +       rv = pkcs11h_setPINPromptHook (_pkcs11_ssh_pin_prompt_cli, NULL);
 1214 +   }
 1215 +
 1216 +   if (rv == CKR_OK) {
 1217 +       rv = pkcs11h_setProtectedAuthentication (TRUE);
 1218 +   }
 1219 +
 1220 +   if (rv == CKR_OK) {
 1221 +       rv = pkcs11h_addProvider (
 1222 +           provider,
 1223 +           provider,
 1224 +           allow_protected_auth ? TRUE : FALSE,
 1225 +           0,
 1226 +           FALSE,
 1227 +           0,
 1228 +           cert_is_private ? TRUE : FALSE
 1229 +       );
 1230 +   }
 1231 +
 1232 +   if (rv == CKR_OK) {
 1233 +       rv = pkcs11h_certificate_enumCertificateIds (
 1234 +           PKCS11H_ENUM_METHOD_CACHE_EXIST,
 1235 +           NULL,
 1236 +           PKCS11H_PROMPT_MASK_ALLOW_ALL,
 1237 +           NULL,
 1238 +           &user_certificates
 1239 +       );
 1240 +   }
 1241 +
 1242 +   for (current = user_certificates; rv == CKR_OK && current != NULL; current = current->next) {
 1243 +       pkcs11h_certificate_t certificate = NULL;
 1244 +       X509 *x509 = NULL;
 1245 +       char dn[1024] = {0};
 1246 +       char *ser = NULL;
 1247 +       char *ssh_key = NULL;
 1248 +       size_t ser_len = 0;
 1249 +
 1250 +       if (rv == CKR_OK) {
 1251 +           rv = pkcs11h_certificate_serializeCertificateId (NULL, &ser_len, current->certificate_id);
 1252 +       }
 1253 +
 1254 +       if (
 1255 +           rv == CKR_OK &&
 1256 +           (ser = (char *)xmalloc (ser_len)) == NULL
 1257 +       ) {
 1258 +           rv = CKR_HOST_MEMORY;
 1259 +       }
 1260 +
 1261 +       if (rv == CKR_OK) {
 1262 +           rv = pkcs11h_certificate_serializeCertificateId (ser, &ser_len, current->certificate_id);
 1263 +       }
 1264 +
 1265 +       if (rv == CKR_OK) {
 1266 +           rv = pkcs11h_certificate_create (
 1267 +               current->certificate_id,
 1268 +               NULL,
 1269 +               PKCS11H_PROMPT_MASK_ALLOW_ALL,
 1270 +               PKCS11H_PIN_CACHE_INFINITE,
 1271 +               &certificate
 1272 +           );
 1273 +       }
 1274 +
 1275 +       if (
 1276 +           rv == CKR_OK &&
 1277 +           (x509 = pkcs11h_openssl_getX509 (certificate)) == NULL
 1278 +       ) {
 1279 +           rv = CKR_FUNCTION_FAILED;
 1280 +       }
 1281 +
 1282 +       if (rv == CKR_OK) {
 1283 +           X509_NAME_oneline (
 1284 +               X509_get_subject_name (x509),
 1285 +               dn,
 1286 +               sizeof (dn)
 1287 +           );
 1288 +           printf (
 1289 +               (
 1290 +                   "\n"
 1291 +                   "********************************************\n"
 1292 +                   "IDENTITY:\n"
 1293 +                   "        DN:            %s\n"
 1294 +                   "        Serialized id: %s\n"
 1295 +                   "\n"
 1296 +                   "        Certificate:\n"
 1297 +               ),
 1298 +               dn,
 1299 +               ser
 1300 +           );
 1301 +           PEM_write_X509 (stdout, x509);
 1302 +       }
 1303 +
 1304 +       if (
 1305 +           rv == CKR_OK &&
 1306 +           (ssh_key = ssh_from_x509 (x509)) != NULL
 1307 +       ) {
 1308 +           printf (
 1309 +               (
 1310 +                   "\n"
 1311 +                   "        SSH:\n"
 1312 +                   "%s\n"
 1313 +               ),
 1314 +               ssh_key
 1315 +           );
 1316 +
 1317 +           xfree (ssh_key);
 1318 +       }
 1319 +
 1320 +       if (x509 != NULL) {
 1321 +           X509_free (x509);
 1322 +           x509 = NULL;
 1323 +       }
 1324 +
 1325 +       if (certificate != NULL) {
 1326 +           pkcs11h_certificate_freeCertificate (certificate);
 1327 +           certificate = NULL;
 1328 +       }
 1329 +
 1330 +       if (ser != NULL) {
 1331 +           xfree (ser);
 1332 +           ser = NULL;
 1333 +       }
 1334 +
 1335 +       /*
 1336 +        * Ignore error
 1337 +        */
 1338 +       if (rv != CKR_OK) {
 1339 +           error ("PKCS#11: Failed to get id %ld-'%s'", rv, pkcs11h_getMessage (rv));
 1340 +           rv = CKR_OK;
 1341 +       }
 1342 +   }
 1343 +
 1344 +   if (user_certificates != NULL) {
 1345 +       pkcs11h_certificate_freeCertificateIdList (user_certificates);
 1346 +       user_certificates = NULL;
 1347 +   }
 1348 +
 1349 +   pkcs11h_terminate ();
 1350 +}
 1351 +
 1352 +void
 1353 +pkcs11_dump_slots (
 1354 +   const char * const provider
 1355 +) {
 1356 +   pkcs11h_standalone_dump_slots (
 1357 +       _pkcs11_ssh_print,
 1358 +       NULL,
 1359 +       provider
 1360 +   );
 1361 +}
 1362 +
 1363 +void
 1364 +pkcs11_dump_objects (
 1365 +   const char * const provider,
 1366 +   const char * const slot,
 1367 +   const char * const pin
 1368 +) {
 1369 +   pkcs11h_standalone_dump_objects (
 1370 +       _pkcs11_ssh_print,
 1371 +       NULL,
 1372 +       provider,
 1373 +       slot,
 1374 +       pin
 1375 +   );
 1376 +}
 1377 +
 1378 +/*
 1379 + * The ssh_from_x509 is dirived of Tatu and Markus work.
 1380 + *
 1381 + * Copyright (c) 2006 Alon bar-Lev <alon.barlev@gmail.com>.  All rights reserved.
 1382 + * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
 1383 + * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 1384 + */
 1385 +
 1386 +#define PUT_32BIT(cp, value) ( \
 1387 +   (cp)[0] = (value) >> 24, \
 1388 +   (cp)[1] = (value) >> 16, \
 1389 +   (cp)[2] = (value) >> 8, \
 1390 +   (cp)[3] = (value) )
 1391 +
 1392 +static
 1393 +char *
 1394 +ssh_from_x509 (X509 *x509) {
 1395 +
 1396 +   EVP_PKEY *pubkey = NULL;
 1397 +   BIO *bio = NULL, *bio2 = NULL, *bio64 = NULL;
 1398 +   unsigned char *blob = NULL, *buffer = NULL;
 1399 +   char *ret = NULL;
 1400 +   int blobsize = 0, retsize = 0;
 1401 +   int bytes_name = 0, bytes_exponent = 0, bytes_modulus = 0;
 1402 +   unsigned char *bp;
 1403 +   char *p;
 1404 +   int n;
 1405 +   const char *keyname = NULL;
 1406 +   int ok = 1;
 1407 +
 1408 +   if (ok && (pubkey = X509_get_pubkey (x509)) == NULL) {
 1409 +       ok = 0;
 1410 +   }
 1411 +
 1412 +   if (ok && (bio64 = BIO_new (BIO_f_base64 ())) == NULL) {
 1413 +       ok = 0;
 1414 +   }
 1415 +
 1416 +   if (ok && (bio = BIO_new (BIO_s_mem ())) == NULL) {
 1417 +       ok = 0;
 1418 +   }
 1419 +
 1420 +   if (ok && (bio2 = BIO_push (bio64, bio)) == NULL) {
 1421 +       ok = 0;
 1422 +   }
 1423 +
 1424 +   if (ok && pubkey->type != EVP_PKEY_RSA) {
 1425 +       ok = 0;
 1426 +   }
 1427 +
 1428 +   if (ok) {
 1429 +       keyname = "ssh-rsa";
 1430 +   }
 1431 +
 1432 +   if (ok) {
 1433 +       bytes_name = strlen (keyname);
 1434 +       bytes_exponent = BN_num_bytes (pubkey->pkey.rsa->e);
 1435 +       bytes_modulus = BN_num_bytes (pubkey->pkey.rsa->n);
 1436 +       
 1437 +       blobsize = (
 1438 +           4 + bytes_name +
 1439 +           4 + (bytes_exponent + 1) +
 1440 +           4 + (bytes_modulus + 1) +
 1441 +           1
 1442 +       );
 1443 +   }
 1444 + 
 1445 +   if (ok && (blob = (unsigned char *)xmalloc (blobsize)) == NULL) {
 1446 +       ok = 0;
 1447 +   }
 1448 +
 1449 +   if (ok && (buffer = (unsigned char *)xmalloc (blobsize)) == NULL) {
 1450 +       ok = 0;
 1451 +   }
 1452 +
 1453 +   if (ok) {
 1454 +       bp = blob;
 1455 +       
 1456 +       PUT_32BIT (bp, bytes_name), bp += 4;
 1457 +       memcpy (bp, keyname, bytes_name), bp += bytes_name;
 1458 +
 1459 +       BN_bn2bin (pubkey->pkey.rsa->e, buffer);
 1460 +       if (buffer[0] & 0x80) {
 1461 +           // highest bit set would indicate a negative number.
 1462 +           // to avoid this, we have to spend an extra byte:
 1463 +           PUT_32BIT (bp, bytes_exponent+1), bp += 4;
 1464 +           *(bp++) = 0;
 1465 +       } else {
 1466 +           PUT_32BIT (bp, bytes_exponent), bp += 4;
 1467 +       }
 1468 +       memcpy (bp, buffer, bytes_exponent), bp += bytes_exponent;
 1469 +           
 1470 +       BN_bn2bin (pubkey->pkey.rsa->n, buffer);
 1471 +       if (buffer[0] & 0x80) {
 1472 +           PUT_32BIT (bp, bytes_modulus+1), bp += 4;
 1473 +           *(bp++) = 0;
 1474 +       } else {
 1475 +           PUT_32BIT( bp, bytes_modulus ), bp += 4;
 1476 +       }
 1477 +       memcpy (bp, buffer, bytes_modulus), bp += bytes_modulus;
 1478 +   }
 1479 +
 1480 +
 1481 +   if (ok && BIO_write (bio2, blob, bp-blob) == -1) {
 1482 +       ok = 0;
 1483 +   }
 1484 +
 1485 +   if (ok && BIO_flush (bio2) == -1) {
 1486 +       ok = 0;
 1487 +   }
 1488 +
 1489 +   /*
 1490 +    * Allocate the newline too... We will remove them later
 1491 +    * For MS, allocate return as well.
 1492 +    */
 1493 +   if (ok) {
 1494 +       retsize = strlen (keyname) + 1 + (blobsize * 4 / 3) + (blobsize * 2 / 50) + 10 + 1;
 1495 +   }
 1496 +
 1497 +   if (ok && (ret = xmalloc (retsize)) == NULL) {
 1498 +       ok = 0;
 1499 +   }
 1500 +   
 1501 +   if (ok) {
 1502 +       strcpy (ret, keyname);
 1503 +       strcat (ret, " ");
 1504 +   }
 1505 +
 1506 +   if (ok && (n = BIO_read (bio, ret + strlen (ret), retsize - strlen (ret) - 1)) == -1) {
 1507 +       ok = 0;
 1508 +   }
 1509 +
 1510 +   if (ok) {
 1511 +       ret[strlen (keyname) + 1 + n] = '\x0';
 1512 +   }
 1513 +
 1514 +   if (ok) {
 1515 +       while ((p = strchr (ret, '\n')) != NULL) {
 1516 +           memmove (p, p+1, strlen (p)+1);
 1517 +       }
 1518 +       while ((p = strchr (ret, '\r')) != NULL) {
 1519 +           memmove (p, p+1, strlen (p)+1);
 1520 +       }
 1521 +
 1522 +   }
 1523 +
 1524 +   if (bio != NULL) {
 1525 +       BIO_free_all (bio);
 1526 +       bio = NULL;
 1527 +   }
 1528 +
 1529 +   if (pubkey != NULL) {
 1530 +       EVP_PKEY_free (pubkey);
 1531 +       pubkey = NULL;
 1532 +   }
 1533 +
 1534 +   if (buffer != NULL) {
 1535 +       xfree (buffer);
 1536 +       buffer = NULL;
 1537 +   }
 1538 +
 1539 +   if (blob != NULL) {
 1540 +       xfree (blob);
 1541 +       blob = NULL;
 1542 +   }
 1543 +
 1544 +   if (!ok) {
 1545 +       if (ret != NULL) {
 1546 +           xfree (ret);
 1547 +           ret = NULL;
 1548 +       }
 1549 +   }
 1550 +   
 1551 +   return ret;
 1552 +}
 1553 +
 1554 +#else
 1555 +static void dummy (void) {}
 1556 +#endif /* SSH_PKCS11_DISABLED */
 1557 diff -urNp openssh-4.4p1/pkcs11.h openssh-4.4p1+pkcs11-0.17/pkcs11.h
 1558 --- openssh-4.4p1/pkcs11.h  1970-01-01 02:00:00.000000000 +0200
 1559 +++ openssh-4.4p1+pkcs11-0.17/pkcs11.h  2006-10-12 13:55:28.000000000 +0200
 1560 @@ -0,0 +1,100 @@
 1561 +/*
 1562 + * Copyright (c) 2005-2006 Alon Bar-Lev.  All rights reserved.
 1563 + *
 1564 + * Redistribution and use in source and binary forms, with or without
 1565 + * modification, are permitted provided that the following conditions
 1566 + * are met:
 1567 + * 1. Redistributions of source code must retain the above copyright
 1568 + *    notice, this list of conditions and the following disclaimer.
 1569 + * 2. Redistributions in binary form must reproduce the above copyright
 1570 + *    notice, this list of conditions and the following disclaimer in the
 1571 + *    documentation and/or other materials provided with the distribution.
 1572 + *
 1573 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1574 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1575 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 1576 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 1577 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 1578 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 1579 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 1580 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 1581 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 1582 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 1583 + */
 1584 +
 1585 +#ifndef SSH_PKCS11_H
 1586 +#define SSH_PKCS11_H
 1587 +
 1588 +#if !defined(SSH_PKCS11_DISABLED)
 1589 +
 1590 +#include "key.h"
 1591 +
 1592 +typedef struct pkcs11_identity_s {
 1593 +   char *id;
 1594 +   int pin_cache_period;
 1595 +   char *cert_file;
 1596 +} pkcs11_identity;
 1597 +
 1598 +int
 1599 +pkcs11_initialize (
 1600 +   const int fProtectedAuthentication,
 1601 +   const int nPINCachePeriod
 1602 +);
 1603 +
 1604 +void
 1605 +pkcs11_terminate ();
 1606 +
 1607 +void
 1608 +pkcs11_forkFix ();
 1609 +
 1610 +int
 1611 +pkcs11_setAskPIN (
 1612 +   const char * const pin_prog
 1613 +);
 1614 +
 1615 +int
 1616 +pkcs11_addProvider (
 1617 +   const char * const provider,
 1618 +   const int fProtectedAuthentication,
 1619 +   const char * const sign_mode,
 1620 +   const int fCertIsPrivate
 1621 +);
 1622 +
 1623 +pkcs11_identity *
 1624 +pkcs11_identity_new ();
 1625 +
 1626 +void
 1627 +pkcs11_identity_free (
 1628 +   const pkcs11_identity * const id
 1629 +);
 1630 +
 1631 +void
 1632 +pkcs11_getKey (
 1633 +   const pkcs11_identity * const id,
 1634 +   Key ** const sshkey,
 1635 +   char * const szComment,
 1636 +   const int nCommentMax
 1637 +);
 1638 +
 1639 +void
 1640 +pkcs11_show_ids (
 1641 +   const char * const provider,
 1642 +   int allow_protected_auth,
 1643 +   int cert_is_private
 1644 +);
 1645 +
 1646 +void
 1647 +pkcs11_dump_slots (
 1648 +   const char * const provider
 1649 +);
 1650 +
 1651 +void
 1652 +pkcs11_dump_objects (
 1653 +   const char * const provider,
 1654 +   const char * const slot,
 1655 +   const char * const pin
 1656 +);
 1657 +   
 1658 +#endif         /* SSH_PKCS11_DISABLED */
 1659 +
 1660 +#endif         /* OPENSSH_PKCS11_H */
 1661 diff -urNp openssh-4.4p1/pkcs11-headers/pkcs11f.h openssh-4.4p1+pkcs11-0.17/pkcs11-headers/pkcs11f.h
 1662 --- openssh-4.4p1/pkcs11-headers/pkcs11f.h  1970-01-01 02:00:00.000000000 +0200
 1663 +++ openssh-4.4p1+pkcs11-0.17/pkcs11-headers/pkcs11f.h  2006-09-28 08:05:35.000000000 +0300
 1664 @@ -0,0 +1,912 @@
 1665 +/* pkcs11f.h include file for PKCS #11. */
 1666 +/* $Revision: 1.4 $ */
 1667 +
 1668 +/* License to copy and use this software is granted provided that it is
 1669 + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
 1670 + * (Cryptoki)" in all material mentioning or referencing this software.
 1671 +
 1672 + * License is also granted to make and use derivative works provided that
 1673 + * such works are identified as "derived from the RSA Security Inc. PKCS #11
 1674 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or 
 1675 + * referencing the derived work.
 1676 +
 1677 + * RSA Security Inc. makes no representations concerning either the 
 1678 + * merchantability of this software or the suitability of this software for
 1679 + * any particular purpose. It is provided "as is" without express or implied
 1680 + * warranty of any kind.
 1681 + */
 1682 +
 1683 +/* This header file contains pretty much everything about all the */
 1684 +/* Cryptoki function prototypes.  Because this information is */
 1685 +/* used for more than just declaring function prototypes, the */
 1686 +/* order of the functions appearing herein is important, and */
 1687 +/* should not be altered. */
 1688 +
 1689 +/* General-purpose */
 1690 +
 1691 +/* C_Initialize initializes the Cryptoki library. */
 1692 +CK_PKCS11_FUNCTION_INFO(C_Initialize)
 1693 +#ifdef CK_NEED_ARG_LIST
 1694 +(
 1695 +  CK_VOID_PTR   pInitArgs  /* if this is not NULL_PTR, it gets
 1696 +                            * cast to CK_C_INITIALIZE_ARGS_PTR
 1697 +                            * and dereferenced */
 1698 +);
 1699 +#endif
 1700 +
 1701 +
 1702 +/* C_Finalize indicates that an application is done with the
 1703 + * Cryptoki library. */
 1704 +CK_PKCS11_FUNCTION_INFO(C_Finalize)
 1705 +#ifdef CK_NEED_ARG_LIST
 1706 +(
 1707 +  CK_VOID_PTR   pReserved  /* reserved.  Should be NULL_PTR */
 1708 +);
 1709 +#endif
 1710 +
 1711 +
 1712 +/* C_GetInfo returns general information about Cryptoki. */
 1713 +CK_PKCS11_FUNCTION_INFO(C_GetInfo)
 1714 +#ifdef CK_NEED_ARG_LIST
 1715 +(
 1716 +  CK_INFO_PTR   pInfo  /* location that receives information */
 1717 +);
 1718 +#endif
 1719 +
 1720 +
 1721 +/* C_GetFunctionList returns the function list. */
 1722 +CK_PKCS11_FUNCTION_INFO(C_GetFunctionList)
 1723 +#ifdef CK_NEED_ARG_LIST
 1724 +(
 1725 +  CK_FUNCTION_LIST_PTR_PTR ppFunctionList  /* receives pointer to
 1726 +                                            * function list */
 1727 +);
 1728 +#endif
 1729 +
 1730 +
 1731 +
 1732 +/* Slot and token management */
 1733 +
 1734 +/* C_GetSlotList obtains a list of slots in the system. */
 1735 +CK_PKCS11_FUNCTION_INFO(C_GetSlotList)
 1736 +#ifdef CK_NEED_ARG_LIST
 1737 +(
 1738 +  CK_BBOOL       tokenPresent,  /* only slots with tokens? */
 1739 +  CK_SLOT_ID_PTR pSlotList,     /* receives array of slot IDs */
 1740 +  CK_ULONG_PTR   pulCount       /* receives number of slots */
 1741 +);
 1742 +#endif
 1743 +
 1744 +
 1745 +/* C_GetSlotInfo obtains information about a particular slot in
 1746 + * the system. */
 1747 +CK_PKCS11_FUNCTION_INFO(C_GetSlotInfo)
 1748 +#ifdef CK_NEED_ARG_LIST
 1749 +(
 1750 +  CK_SLOT_ID       slotID,  /* the ID of the slot */
 1751 +  CK_SLOT_INFO_PTR pInfo    /* receives the slot information */
 1752 +);
 1753 +#endif
 1754 +
 1755 +
 1756 +/* C_GetTokenInfo obtains information about a particular token
 1757 + * in the system. */
 1758 +CK_PKCS11_FUNCTION_INFO(C_GetTokenInfo)
 1759 +#ifdef CK_NEED_ARG_LIST
 1760 +(
 1761 +  CK_SLOT_ID        slotID,  /* ID of the token's slot */
 1762 +  CK_TOKEN_INFO_PTR pInfo    /* receives the token information */
 1763 +);
 1764 +#endif
 1765 +
 1766 +
 1767 +/* C_GetMechanismList obtains a list of mechanism types
 1768 + * supported by a token. */
 1769 +CK_PKCS11_FUNCTION_INFO(C_GetMechanismList)
 1770 +#ifdef CK_NEED_ARG_LIST
 1771 +(
 1772 +  CK_SLOT_ID            slotID,          /* ID of token's slot */
 1773 +  CK_MECHANISM_TYPE_PTR pMechanismList,  /* gets mech. array */
 1774 +  CK_ULONG_PTR          pulCount         /* gets # of mechs. */
 1775 +);
 1776 +#endif
 1777 +
 1778 +
 1779 +/* C_GetMechanismInfo obtains information about a particular
 1780 + * mechanism possibly supported by a token. */
 1781 +CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo)
 1782 +#ifdef CK_NEED_ARG_LIST
 1783 +(
 1784 +  CK_SLOT_ID            slotID,  /* ID of the token's slot */
 1785 +  CK_MECHANISM_TYPE     type,    /* type of mechanism */
 1786 +  CK_MECHANISM_INFO_PTR pInfo    /* receives mechanism info */
 1787 +);
 1788 +#endif
 1789 +
 1790 +
 1791 +/* C_InitToken initializes a token. */
 1792 +CK_PKCS11_FUNCTION_INFO(C_InitToken)
 1793 +#ifdef CK_NEED_ARG_LIST
 1794 +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */
 1795 +(
 1796 +  CK_SLOT_ID      slotID,    /* ID of the token's slot */
 1797 +  CK_UTF8CHAR_PTR pPin,      /* the SO's initial PIN */
 1798 +  CK_ULONG        ulPinLen,  /* length in bytes of the PIN */
 1799 +  CK_UTF8CHAR_PTR pLabel     /* 32-byte token label (blank padded) */
 1800 +);
 1801 +#endif
 1802 +
 1803 +
 1804 +/* C_InitPIN initializes the normal user's PIN. */
 1805 +CK_PKCS11_FUNCTION_INFO(C_InitPIN)
 1806 +#ifdef CK_NEED_ARG_LIST
 1807 +(
 1808 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 1809 +  CK_UTF8CHAR_PTR   pPin,      /* the normal user's PIN */
 1810 +  CK_ULONG          ulPinLen   /* length in bytes of the PIN */
 1811 +);
 1812 +#endif
 1813 +
 1814 +
 1815 +/* C_SetPIN modifies the PIN of the user who is logged in. */
 1816 +CK_PKCS11_FUNCTION_INFO(C_SetPIN)
 1817 +#ifdef CK_NEED_ARG_LIST
 1818 +(
 1819 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 1820 +  CK_UTF8CHAR_PTR   pOldPin,   /* the old PIN */
 1821 +  CK_ULONG          ulOldLen,  /* length of the old PIN */
 1822 +  CK_UTF8CHAR_PTR   pNewPin,   /* the new PIN */
 1823 +  CK_ULONG          ulNewLen   /* length of the new PIN */
 1824 +);
 1825 +#endif
 1826 +
 1827 +
 1828 +
 1829 +/* Session management */
 1830 +
 1831 +/* C_OpenSession opens a session between an application and a
 1832 + * token. */
 1833 +CK_PKCS11_FUNCTION_INFO(C_OpenSession)
 1834 +#ifdef CK_NEED_ARG_LIST
 1835 +(
 1836 +  CK_SLOT_ID            slotID,        /* the slot's ID */
 1837 +  CK_FLAGS              flags,         /* from CK_SESSION_INFO */
 1838 +  CK_VOID_PTR           pApplication,  /* passed to callback */
 1839 +  CK_NOTIFY             Notify,        /* callback function */
 1840 +  CK_SESSION_HANDLE_PTR phSession      /* gets session handle */
 1841 +);
 1842 +#endif
 1843 +
 1844 +
 1845 +/* C_CloseSession closes a session between an application and a
 1846 + * token. */
 1847 +CK_PKCS11_FUNCTION_INFO(C_CloseSession)
 1848 +#ifdef CK_NEED_ARG_LIST
 1849 +(
 1850 +  CK_SESSION_HANDLE hSession  /* the session's handle */
 1851 +);
 1852 +#endif
 1853 +
 1854 +
 1855 +/* C_CloseAllSessions closes all sessions with a token. */
 1856 +CK_PKCS11_FUNCTION_INFO(C_CloseAllSessions)
 1857 +#ifdef CK_NEED_ARG_LIST
 1858 +(
 1859 +  CK_SLOT_ID     slotID  /* the token's slot */
 1860 +);
 1861 +#endif
 1862 +
 1863 +
 1864 +/* C_GetSessionInfo obtains information about the session. */
 1865 +CK_PKCS11_FUNCTION_INFO(C_GetSessionInfo)
 1866 +#ifdef CK_NEED_ARG_LIST
 1867 +(
 1868 +  CK_SESSION_HANDLE   hSession,  /* the session's handle */
 1869 +  CK_SESSION_INFO_PTR pInfo      /* receives session info */
 1870 +);
 1871 +#endif
 1872 +
 1873 +
 1874 +/* C_GetOperationState obtains the state of the cryptographic operation
 1875 + * in a session. */
 1876 +CK_PKCS11_FUNCTION_INFO(C_GetOperationState)
 1877 +#ifdef CK_NEED_ARG_LIST
 1878 +(
 1879 +  CK_SESSION_HANDLE hSession,             /* session's handle */
 1880 +  CK_BYTE_PTR       pOperationState,      /* gets state */
 1881 +  CK_ULONG_PTR      pulOperationStateLen  /* gets state length */
 1882 +);
 1883 +#endif
 1884 +
 1885 +
 1886 +/* C_SetOperationState restores the state of the cryptographic
 1887 + * operation in a session. */
 1888 +CK_PKCS11_FUNCTION_INFO(C_SetOperationState)
 1889 +#ifdef CK_NEED_ARG_LIST
 1890 +(
 1891 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 1892 +  CK_BYTE_PTR      pOperationState,      /* holds state */
 1893 +  CK_ULONG         ulOperationStateLen,  /* holds state length */
 1894 +  CK_OBJECT_HANDLE hEncryptionKey,       /* en/decryption key */
 1895 +  CK_OBJECT_HANDLE hAuthenticationKey    /* sign/verify key */
 1896 +);
 1897 +#endif
 1898 +
 1899 +
 1900 +/* C_Login logs a user into a token. */
 1901 +CK_PKCS11_FUNCTION_INFO(C_Login)
 1902 +#ifdef CK_NEED_ARG_LIST
 1903 +(
 1904 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 1905 +  CK_USER_TYPE      userType,  /* the user type */
 1906 +  CK_UTF8CHAR_PTR   pPin,      /* the user's PIN */
 1907 +  CK_ULONG          ulPinLen   /* the length of the PIN */
 1908 +);
 1909 +#endif
 1910 +
 1911 +
 1912 +/* C_Logout logs a user out from a token. */
 1913 +CK_PKCS11_FUNCTION_INFO(C_Logout)
 1914 +#ifdef CK_NEED_ARG_LIST
 1915 +(
 1916 +  CK_SESSION_HANDLE hSession  /* the session's handle */
 1917 +);
 1918 +#endif
 1919 +
 1920 +
 1921 +
 1922 +/* Object management */
 1923 +
 1924 +/* C_CreateObject creates a new object. */
 1925 +CK_PKCS11_FUNCTION_INFO(C_CreateObject)
 1926 +#ifdef CK_NEED_ARG_LIST
 1927 +(
 1928 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 1929 +  CK_ATTRIBUTE_PTR  pTemplate,   /* the object's template */
 1930 +  CK_ULONG          ulCount,     /* attributes in template */
 1931 +  CK_OBJECT_HANDLE_PTR phObject  /* gets new object's handle. */
 1932 +);
 1933 +#endif
 1934 +
 1935 +
 1936 +/* C_CopyObject copies an object, creating a new object for the
 1937 + * copy. */
 1938 +CK_PKCS11_FUNCTION_INFO(C_CopyObject)
 1939 +#ifdef CK_NEED_ARG_LIST
 1940 +(
 1941 +  CK_SESSION_HANDLE    hSession,    /* the session's handle */
 1942 +  CK_OBJECT_HANDLE     hObject,     /* the object's handle */
 1943 +  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new object */
 1944 +  CK_ULONG             ulCount,     /* attributes in template */
 1945 +  CK_OBJECT_HANDLE_PTR phNewObject  /* receives handle of copy */
 1946 +);
 1947 +#endif
 1948 +
 1949 +
 1950 +/* C_DestroyObject destroys an object. */
 1951 +CK_PKCS11_FUNCTION_INFO(C_DestroyObject)
 1952 +#ifdef CK_NEED_ARG_LIST
 1953 +(
 1954 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 1955 +  CK_OBJECT_HANDLE  hObject    /* the object's handle */
 1956 +);
 1957 +#endif
 1958 +
 1959 +
 1960 +/* C_GetObjectSize gets the size of an object in bytes. */
 1961 +CK_PKCS11_FUNCTION_INFO(C_GetObjectSize)
 1962 +#ifdef CK_NEED_ARG_LIST
 1963 +(
 1964 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 1965 +  CK_OBJECT_HANDLE  hObject,   /* the object's handle */
 1966 +  CK_ULONG_PTR      pulSize    /* receives size of object */
 1967 +);
 1968 +#endif
 1969 +
 1970 +
 1971 +/* C_GetAttributeValue obtains the value of one or more object
 1972 + * attributes. */
 1973 +CK_PKCS11_FUNCTION_INFO(C_GetAttributeValue)
 1974 +#ifdef CK_NEED_ARG_LIST
 1975 +(
 1976 +  CK_SESSION_HANDLE hSession,   /* the session's handle */
 1977 +  CK_OBJECT_HANDLE  hObject,    /* the object's handle */
 1978 +  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs; gets vals */
 1979 +  CK_ULONG          ulCount     /* attributes in template */
 1980 +);
 1981 +#endif
 1982 +
 1983 +
 1984 +/* C_SetAttributeValue modifies the value of one or more object
 1985 + * attributes */
 1986 +CK_PKCS11_FUNCTION_INFO(C_SetAttributeValue)
 1987 +#ifdef CK_NEED_ARG_LIST
 1988 +(
 1989 +  CK_SESSION_HANDLE hSession,   /* the session's handle */
 1990 +  CK_OBJECT_HANDLE  hObject,    /* the object's handle */
 1991 +  CK_ATTRIBUTE_PTR  pTemplate,  /* specifies attrs and values */
 1992 +  CK_ULONG          ulCount     /* attributes in template */
 1993 +);
 1994 +#endif
 1995 +
 1996 +
 1997 +/* C_FindObjectsInit initializes a search for token and session
 1998 + * objects that match a template. */
 1999 +CK_PKCS11_FUNCTION_INFO(C_FindObjectsInit)
 2000 +#ifdef CK_NEED_ARG_LIST
 2001 +(
 2002 +  CK_SESSION_HANDLE hSession,   /* the session's handle */
 2003 +  CK_ATTRIBUTE_PTR  pTemplate,  /* attribute values to match */
 2004 +  CK_ULONG          ulCount     /* attrs in search template */
 2005 +);
 2006 +#endif
 2007 +
 2008 +
 2009 +/* C_FindObjects continues a search for token and session
 2010 + * objects that match a template, obtaining additional object
 2011 + * handles. */
 2012 +CK_PKCS11_FUNCTION_INFO(C_FindObjects)
 2013 +#ifdef CK_NEED_ARG_LIST
 2014 +(
 2015 + CK_SESSION_HANDLE    hSession,          /* session's handle */
 2016 + CK_OBJECT_HANDLE_PTR phObject,          /* gets obj. handles */
 2017 + CK_ULONG             ulMaxObjectCount,  /* max handles to get */
 2018 + CK_ULONG_PTR         pulObjectCount     /* actual # returned */
 2019 +);
 2020 +#endif
 2021 +
 2022 +
 2023 +/* C_FindObjectsFinal finishes a search for token and session
 2024 + * objects. */
 2025 +CK_PKCS11_FUNCTION_INFO(C_FindObjectsFinal)
 2026 +#ifdef CK_NEED_ARG_LIST
 2027 +(
 2028 +  CK_SESSION_HANDLE hSession  /* the session's handle */
 2029 +);
 2030 +#endif
 2031 +
 2032 +
 2033 +
 2034 +/* Encryption and decryption */
 2035 +
 2036 +/* C_EncryptInit initializes an encryption operation. */
 2037 +CK_PKCS11_FUNCTION_INFO(C_EncryptInit)
 2038 +#ifdef CK_NEED_ARG_LIST
 2039 +(
 2040 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 2041 +  CK_MECHANISM_PTR  pMechanism,  /* the encryption mechanism */
 2042 +  CK_OBJECT_HANDLE  hKey         /* handle of encryption key */
 2043 +);
 2044 +#endif
 2045 +
 2046 +
 2047 +/* C_Encrypt encrypts single-part data. */
 2048 +CK_PKCS11_FUNCTION_INFO(C_Encrypt)
 2049 +#ifdef CK_NEED_ARG_LIST
 2050 +(
 2051 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 2052 +  CK_BYTE_PTR       pData,               /* the plaintext data */
 2053 +  CK_ULONG          ulDataLen,           /* bytes of plaintext */
 2054 +  CK_BYTE_PTR       pEncryptedData,      /* gets ciphertext */
 2055 +  CK_ULONG_PTR      pulEncryptedDataLen  /* gets c-text size */
 2056 +);
 2057 +#endif
 2058 +
 2059 +
 2060 +/* C_EncryptUpdate continues a multiple-part encryption
 2061 + * operation. */
 2062 +CK_PKCS11_FUNCTION_INFO(C_EncryptUpdate)
 2063 +#ifdef CK_NEED_ARG_LIST
 2064 +(
 2065 +  CK_SESSION_HANDLE hSession,           /* session's handle */
 2066 +  CK_BYTE_PTR       pPart,              /* the plaintext data */
 2067 +  CK_ULONG          ulPartLen,          /* plaintext data len */
 2068 +  CK_BYTE_PTR       pEncryptedPart,     /* gets ciphertext */
 2069 +  CK_ULONG_PTR      pulEncryptedPartLen /* gets c-text size */
 2070 +);
 2071 +#endif
 2072 +
 2073 +
 2074 +/* C_EncryptFinal finishes a multiple-part encryption
 2075 + * operation. */
 2076 +CK_PKCS11_FUNCTION_INFO(C_EncryptFinal)
 2077 +#ifdef CK_NEED_ARG_LIST
 2078 +(
 2079 +  CK_SESSION_HANDLE hSession,                /* session handle */
 2080 +  CK_BYTE_PTR       pLastEncryptedPart,      /* last c-text */
 2081 +  CK_ULONG_PTR      pulLastEncryptedPartLen  /* gets last size */
 2082 +);
 2083 +#endif
 2084 +
 2085 +
 2086 +/* C_DecryptInit initializes a decryption operation. */
 2087 +CK_PKCS11_FUNCTION_INFO(C_DecryptInit)
 2088 +#ifdef CK_NEED_ARG_LIST
 2089 +(
 2090 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 2091 +  CK_MECHANISM_PTR  pMechanism,  /* the decryption mechanism */
 2092 +  CK_OBJECT_HANDLE  hKey         /* handle of decryption key */
 2093 +);
 2094 +#endif
 2095 +
 2096 +
 2097 +/* C_Decrypt decrypts encrypted data in a single part. */
 2098 +CK_PKCS11_FUNCTION_INFO(C_Decrypt)
 2099 +#ifdef CK_NEED_ARG_LIST
 2100 +(
 2101 +  CK_SESSION_HANDLE hSession,           /* session's handle */
 2102 +  CK_BYTE_PTR       pEncryptedData,     /* ciphertext */
 2103 +  CK_ULONG          ulEncryptedDataLen, /* ciphertext length */
 2104 +  CK_BYTE_PTR       pData,              /* gets plaintext */
 2105 +  CK_ULONG_PTR      pulDataLen          /* gets p-text size */
 2106 +);
 2107 +#endif
 2108 +
 2109 +
 2110 +/* C_DecryptUpdate continues a multiple-part decryption
 2111 + * operation. */
 2112 +CK_PKCS11_FUNCTION_INFO(C_DecryptUpdate)
 2113 +#ifdef CK_NEED_ARG_LIST
 2114 +(
 2115 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 2116 +  CK_BYTE_PTR       pEncryptedPart,      /* encrypted data */
 2117 +  CK_ULONG          ulEncryptedPartLen,  /* input length */
 2118 +  CK_BYTE_PTR       pPart,               /* gets plaintext */
 2119 +  CK_ULONG_PTR      pulPartLen           /* p-text size */
 2120 +);
 2121 +#endif
 2122 +
 2123 +
 2124 +/* C_DecryptFinal finishes a multiple-part decryption
 2125 + * operation. */
 2126 +CK_PKCS11_FUNCTION_INFO(C_DecryptFinal)
 2127 +#ifdef CK_NEED_ARG_LIST
 2128 +(
 2129 +  CK_SESSION_HANDLE hSession,       /* the session's handle */
 2130 +  CK_BYTE_PTR       pLastPart,      /* gets plaintext */
 2131 +  CK_ULONG_PTR      pulLastPartLen  /* p-text size */
 2132 +);
 2133 +#endif
 2134 +
 2135 +
 2136 +
 2137 +/* Message digesting */
 2138 +
 2139 +/* C_DigestInit initializes a message-digesting operation. */
 2140 +CK_PKCS11_FUNCTION_INFO(C_DigestInit)
 2141 +#ifdef CK_NEED_ARG_LIST
 2142 +(
 2143 +  CK_SESSION_HANDLE hSession,   /* the session's handle */
 2144 +  CK_MECHANISM_PTR  pMechanism  /* the digesting mechanism */
 2145 +);
 2146 +#endif
 2147 +
 2148 +
 2149 +/* C_Digest digests data in a single part. */
 2150 +CK_PKCS11_FUNCTION_INFO(C_Digest)
 2151 +#ifdef CK_NEED_ARG_LIST
 2152 +(
 2153 +  CK_SESSION_HANDLE hSession,     /* the session's handle */
 2154 +  CK_BYTE_PTR       pData,        /* data to be digested */
 2155 +  CK_ULONG          ulDataLen,    /* bytes of data to digest */
 2156 +  CK_BYTE_PTR       pDigest,      /* gets the message digest */
 2157 +  CK_ULONG_PTR      pulDigestLen  /* gets digest length */
 2158 +);
 2159 +#endif
 2160 +
 2161 +
 2162 +/* C_DigestUpdate continues a multiple-part message-digesting
 2163 + * operation. */
 2164 +CK_PKCS11_FUNCTION_INFO(C_DigestUpdate)
 2165 +#ifdef CK_NEED_ARG_LIST
 2166 +(
 2167 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 2168 +  CK_BYTE_PTR       pPart,     /* data to be digested */
 2169 +  CK_ULONG          ulPartLen  /* bytes of data to be digested */
 2170 +);
 2171 +#endif
 2172 +
 2173 +
 2174 +/* C_DigestKey continues a multi-part message-digesting
 2175 + * operation, by digesting the value of a secret key as part of
 2176 + * the data already digested. */
 2177 +CK_PKCS11_FUNCTION_INFO(C_DigestKey)
 2178 +#ifdef CK_NEED_ARG_LIST
 2179 +(
 2180 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 2181 +  CK_OBJECT_HANDLE  hKey       /* secret key to digest */
 2182 +);
 2183 +#endif
 2184 +
 2185 +
 2186 +/* C_DigestFinal finishes a multiple-part message-digesting
 2187 + * operation. */
 2188 +CK_PKCS11_FUNCTION_INFO(C_DigestFinal)
 2189 +#ifdef CK_NEED_ARG_LIST
 2190 +(
 2191 +  CK_SESSION_HANDLE hSession,     /* the session's handle */
 2192 +  CK_BYTE_PTR       pDigest,      /* gets the message digest */
 2193 +  CK_ULONG_PTR      pulDigestLen  /* gets byte count of digest */
 2194 +);
 2195 +#endif
 2196 +
 2197 +
 2198 +
 2199 +/* Signing and MACing */
 2200 +
 2201 +/* C_SignInit initializes a signature (private key encryption)
 2202 + * operation, where the signature is (will be) an appendix to
 2203 + * the data, and plaintext cannot be recovered from the
 2204 + *signature. */
 2205 +CK_PKCS11_FUNCTION_INFO(C_SignInit)
 2206 +#ifdef CK_NEED_ARG_LIST
 2207 +(
 2208 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 2209 +  CK_MECHANISM_PTR  pMechanism,  /* the signature mechanism */
 2210 +  CK_OBJECT_HANDLE  hKey         /* handle of signature key */
 2211 +);
 2212 +#endif
 2213 +
 2214 +
 2215 +/* C_Sign signs (encrypts with private key) data in a single
 2216 + * part, where the signature is (will be) an appendix to the
 2217 + * data, and plaintext cannot be recovered from the signature. */
 2218 +CK_PKCS11_FUNCTION_INFO(C_Sign)
 2219 +#ifdef CK_NEED_ARG_LIST
 2220 +(
 2221 +  CK_SESSION_HANDLE hSession,        /* the session's handle */
 2222 +  CK_BYTE_PTR       pData,           /* the data to sign */
 2223 +  CK_ULONG          ulDataLen,       /* count of bytes to sign */
 2224 +  CK_BYTE_PTR       pSignature,      /* gets the signature */
 2225 +  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
 2226 +);
 2227 +#endif
 2228 +
 2229 +
 2230 +/* C_SignUpdate continues a multiple-part signature operation,
 2231 + * where the signature is (will be) an appendix to the data, 
 2232 + * and plaintext cannot be recovered from the signature. */
 2233 +CK_PKCS11_FUNCTION_INFO(C_SignUpdate)
 2234 +#ifdef CK_NEED_ARG_LIST
 2235 +(
 2236 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 2237 +  CK_BYTE_PTR       pPart,     /* the data to sign */
 2238 +  CK_ULONG          ulPartLen  /* count of bytes to sign */
 2239 +);
 2240 +#endif
 2241 +
 2242 +
 2243 +/* C_SignFinal finishes a multiple-part signature operation, 
 2244 + * returning the signature. */
 2245 +CK_PKCS11_FUNCTION_INFO(C_SignFinal)
 2246 +#ifdef CK_NEED_ARG_LIST
 2247 +(
 2248 +  CK_SESSION_HANDLE hSession,        /* the session's handle */
 2249 +  CK_BYTE_PTR       pSignature,      /* gets the signature */
 2250 +  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
 2251 +);
 2252 +#endif
 2253 +
 2254 +
 2255 +/* C_SignRecoverInit initializes a signature operation, where
 2256 + * the data can be recovered from the signature. */
 2257 +CK_PKCS11_FUNCTION_INFO(C_SignRecoverInit)
 2258 +#ifdef CK_NEED_ARG_LIST
 2259 +(
 2260 +  CK_SESSION_HANDLE hSession,   /* the session's handle */
 2261 +  CK_MECHANISM_PTR  pMechanism, /* the signature mechanism */
 2262 +  CK_OBJECT_HANDLE  hKey        /* handle of the signature key */
 2263 +);
 2264 +#endif
 2265 +
 2266 +
 2267 +/* C_SignRecover signs data in a single operation, where the
 2268 + * data can be recovered from the signature. */
 2269 +CK_PKCS11_FUNCTION_INFO(C_SignRecover)
 2270 +#ifdef CK_NEED_ARG_LIST
 2271 +(
 2272 +  CK_SESSION_HANDLE hSession,        /* the session's handle */
 2273 +  CK_BYTE_PTR       pData,           /* the data to sign */
 2274 +  CK_ULONG          ulDataLen,       /* count of bytes to sign */
 2275 +  CK_BYTE_PTR       pSignature,      /* gets the signature */
 2276 +  CK_ULONG_PTR      pulSignatureLen  /* gets signature length */
 2277 +);
 2278 +#endif
 2279 +
 2280 +
 2281 +
 2282 +/* Verifying signatures and MACs */
 2283 +
 2284 +/* C_VerifyInit initializes a verification operation, where the
 2285 + * signature is an appendix to the data, and plaintext cannot
 2286 + *  cannot be recovered from the signature (e.g. DSA). */
 2287 +CK_PKCS11_FUNCTION_INFO(C_VerifyInit)
 2288 +#ifdef CK_NEED_ARG_LIST
 2289 +(
 2290 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 2291 +  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */
 2292 +  CK_OBJECT_HANDLE  hKey         /* verification key */ 
 2293 +);
 2294 +#endif
 2295 +
 2296 +
 2297 +/* C_Verify verifies a signature in a single-part operation, 
 2298 + * where the signature is an appendix to the data, and plaintext
 2299 + * cannot be recovered from the signature. */
 2300 +CK_PKCS11_FUNCTION_INFO(C_Verify)
 2301 +#ifdef CK_NEED_ARG_LIST
 2302 +(
 2303 +  CK_SESSION_HANDLE hSession,       /* the session's handle */
 2304 +  CK_BYTE_PTR       pData,          /* signed data */
 2305 +  CK_ULONG          ulDataLen,      /* length of signed data */
 2306 +  CK_BYTE_PTR       pSignature,     /* signature */
 2307 +  CK_ULONG          ulSignatureLen  /* signature length*/
 2308 +);
 2309 +#endif
 2310 +
 2311 +
 2312 +/* C_VerifyUpdate continues a multiple-part verification
 2313 + * operation, where the signature is an appendix to the data, 
 2314 + * and plaintext cannot be recovered from the signature. */
 2315 +CK_PKCS11_FUNCTION_INFO(C_VerifyUpdate)
 2316 +#ifdef CK_NEED_ARG_LIST
 2317 +(
 2318 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 2319 +  CK_BYTE_PTR       pPart,     /* signed data */
 2320 +  CK_ULONG          ulPartLen  /* length of signed data */
 2321 +);
 2322 +#endif
 2323 +
 2324 +
 2325 +/* C_VerifyFinal finishes a multiple-part verification
 2326 + * operation, checking the signature. */
 2327 +CK_PKCS11_FUNCTION_INFO(C_VerifyFinal)
 2328 +#ifdef CK_NEED_ARG_LIST
 2329 +(
 2330 +  CK_SESSION_HANDLE hSession,       /* the session's handle */
 2331 +  CK_BYTE_PTR       pSignature,     /* signature to verify */
 2332 +  CK_ULONG          ulSignatureLen  /* signature length */
 2333 +);
 2334 +#endif
 2335 +
 2336 +
 2337 +/* C_VerifyRecoverInit initializes a signature verification
 2338 + * operation, where the data is recovered from the signature. */
 2339 +CK_PKCS11_FUNCTION_INFO(C_VerifyRecoverInit)
 2340 +#ifdef CK_NEED_ARG_LIST
 2341 +(
 2342 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 2343 +  CK_MECHANISM_PTR  pMechanism,  /* the verification mechanism */
 2344 +  CK_OBJECT_HANDLE  hKey         /* verification key */
 2345 +);
 2346 +#endif
 2347 +
 2348 +
 2349 +/* C_VerifyRecover verifies a signature in a single-part
 2350 + * operation, where the data is recovered from the signature. */
 2351 +CK_PKCS11_FUNCTION_INFO(C_VerifyRecover)
 2352 +#ifdef CK_NEED_ARG_LIST
 2353 +(
 2354 +  CK_SESSION_HANDLE hSession,        /* the session's handle */
 2355 +  CK_BYTE_PTR       pSignature,      /* signature to verify */
 2356 +  CK_ULONG          ulSignatureLen,  /* signature length */
 2357 +  CK_BYTE_PTR       pData,           /* gets signed data */
 2358 +  CK_ULONG_PTR      pulDataLen       /* gets signed data len */
 2359 +);
 2360 +#endif
 2361 +
 2362 +
 2363 +
 2364 +/* Dual-function cryptographic operations */
 2365 +
 2366 +/* C_DigestEncryptUpdate continues a multiple-part digesting
 2367 + * and encryption operation. */
 2368 +CK_PKCS11_FUNCTION_INFO(C_DigestEncryptUpdate)
 2369 +#ifdef CK_NEED_ARG_LIST
 2370 +(
 2371 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 2372 +  CK_BYTE_PTR       pPart,               /* the plaintext data */
 2373 +  CK_ULONG          ulPartLen,           /* plaintext length */
 2374 +  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */
 2375 +  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */
 2376 +);
 2377 +#endif
 2378 +
 2379 +
 2380 +/* C_DecryptDigestUpdate continues a multiple-part decryption and
 2381 + * digesting operation. */
 2382 +CK_PKCS11_FUNCTION_INFO(C_DecryptDigestUpdate)
 2383 +#ifdef CK_NEED_ARG_LIST
 2384 +(
 2385 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 2386 +  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */
 2387 +  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */
 2388 +  CK_BYTE_PTR       pPart,               /* gets plaintext */
 2389 +  CK_ULONG_PTR      pulPartLen           /* gets plaintext len */
 2390 +);
 2391 +#endif
 2392 +
 2393 +
 2394 +/* C_SignEncryptUpdate continues a multiple-part signing and
 2395 + * encryption operation. */
 2396 +CK_PKCS11_FUNCTION_INFO(C_SignEncryptUpdate)
 2397 +#ifdef CK_NEED_ARG_LIST
 2398 +(
 2399 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 2400 +  CK_BYTE_PTR       pPart,               /* the plaintext data */
 2401 +  CK_ULONG          ulPartLen,           /* plaintext length */
 2402 +  CK_BYTE_PTR       pEncryptedPart,      /* gets ciphertext */
 2403 +  CK_ULONG_PTR      pulEncryptedPartLen  /* gets c-text length */
 2404 +);
 2405 +#endif
 2406 +
 2407 +
 2408 +/* C_DecryptVerifyUpdate continues a multiple-part decryption and
 2409 + * verify operation. */
 2410 +CK_PKCS11_FUNCTION_INFO(C_DecryptVerifyUpdate)
 2411 +#ifdef CK_NEED_ARG_LIST
 2412 +(
 2413 +  CK_SESSION_HANDLE hSession,            /* session's handle */
 2414 +  CK_BYTE_PTR       pEncryptedPart,      /* ciphertext */
 2415 +  CK_ULONG          ulEncryptedPartLen,  /* ciphertext length */
 2416 +  CK_BYTE_PTR       pPart,               /* gets plaintext */
 2417 +  CK_ULONG_PTR      pulPartLen           /* gets p-text length */
 2418 +);
 2419 +#endif
 2420 +
 2421 +
 2422 +
 2423 +/* Key management */
 2424 +
 2425 +/* C_GenerateKey generates a secret key, creating a new key
 2426 + * object. */
 2427 +CK_PKCS11_FUNCTION_INFO(C_GenerateKey)
 2428 +#ifdef CK_NEED_ARG_LIST
 2429 +(
 2430 +  CK_SESSION_HANDLE    hSession,    /* the session's handle */
 2431 +  CK_MECHANISM_PTR     pMechanism,  /* key generation mech. */
 2432 +  CK_ATTRIBUTE_PTR     pTemplate,   /* template for new key */
 2433 +  CK_ULONG             ulCount,     /* # of attrs in template */
 2434 +  CK_OBJECT_HANDLE_PTR phKey        /* gets handle of new key */
 2435 +);
 2436 +#endif
 2437 +
 2438 +
 2439 +/* C_GenerateKeyPair generates a public-key/private-key pair, 
 2440 + * creating new key objects. */
 2441 +CK_PKCS11_FUNCTION_INFO(C_GenerateKeyPair)
 2442 +#ifdef CK_NEED_ARG_LIST
 2443 +(
 2444 +  CK_SESSION_HANDLE    hSession,                    /* session
 2445 +                                                     * handle */
 2446 +  CK_MECHANISM_PTR     pMechanism,                  /* key-gen
 2447 +                                                     * mech. */
 2448 +  CK_ATTRIBUTE_PTR     pPublicKeyTemplate,          /* template
 2449 +                                                     * for pub.
 2450 +                                                     * key */
 2451 +  CK_ULONG             ulPublicKeyAttributeCount,   /* # pub.
 2452 +                                                     * attrs. */
 2453 +  CK_ATTRIBUTE_PTR     pPrivateKeyTemplate,         /* template
 2454 +                                                     * for priv.
 2455 +                                                     * key */
 2456 +  CK_ULONG             ulPrivateKeyAttributeCount,  /* # priv.
 2457 +                                                     * attrs. */
 2458 +  CK_OBJECT_HANDLE_PTR phPublicKey,                 /* gets pub.
 2459 +                                                     * key
 2460 +                                                     * handle */
 2461 +  CK_OBJECT_HANDLE_PTR phPrivateKey                 /* gets
 2462 +                                                     * priv. key
 2463 +                                                     * handle */
 2464 +);
 2465 +#endif
 2466 +
 2467 +
 2468 +/* C_WrapKey wraps (i.e., encrypts) a key. */
 2469 +CK_PKCS11_FUNCTION_INFO(C_WrapKey)
 2470 +#ifdef CK_NEED_ARG_LIST
 2471 +(
 2472 +  CK_SESSION_HANDLE hSession,        /* the session's handle */
 2473 +  CK_MECHANISM_PTR  pMechanism,      /* the wrapping mechanism */
 2474 +  CK_OBJECT_HANDLE  hWrappingKey,    /* wrapping key */
 2475 +  CK_OBJECT_HANDLE  hKey,            /* key to be wrapped */
 2476 +  CK_BYTE_PTR       pWrappedKey,     /* gets wrapped key */
 2477 +  CK_ULONG_PTR      pulWrappedKeyLen /* gets wrapped key size */
 2478 +);
 2479 +#endif
 2480 +
 2481 +
 2482 +/* C_UnwrapKey unwraps (decrypts) a wrapped key, creating a new
 2483 + * key object. */
 2484 +CK_PKCS11_FUNCTION_INFO(C_UnwrapKey)
 2485 +#ifdef CK_NEED_ARG_LIST
 2486 +(
 2487 +  CK_SESSION_HANDLE    hSession,          /* session's handle */
 2488 +  CK_MECHANISM_PTR     pMechanism,        /* unwrapping mech. */
 2489 +  CK_OBJECT_HANDLE     hUnwrappingKey,    /* unwrapping key */
 2490 +  CK_BYTE_PTR          pWrappedKey,       /* the wrapped key */
 2491 +  CK_ULONG             ulWrappedKeyLen,   /* wrapped key len */
 2492 +  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */
 2493 +  CK_ULONG             ulAttributeCount,  /* template length */
 2494 +  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */
 2495 +);
 2496 +#endif
 2497 +
 2498 +
 2499 +/* C_DeriveKey derives a key from a base key, creating a new key
 2500 + * object. */
 2501 +CK_PKCS11_FUNCTION_INFO(C_DeriveKey)
 2502 +#ifdef CK_NEED_ARG_LIST
 2503 +(
 2504 +  CK_SESSION_HANDLE    hSession,          /* session's handle */
 2505 +  CK_MECHANISM_PTR     pMechanism,        /* key deriv. mech. */
 2506 +  CK_OBJECT_HANDLE     hBaseKey,          /* base key */
 2507 +  CK_ATTRIBUTE_PTR     pTemplate,         /* new key template */
 2508 +  CK_ULONG             ulAttributeCount,  /* template length */
 2509 +  CK_OBJECT_HANDLE_PTR phKey              /* gets new handle */
 2510 +);
 2511 +#endif
 2512 +
 2513 +
 2514 +
 2515 +/* Random number generation */
 2516 +
 2517 +/* C_SeedRandom mixes additional seed material into the token's
 2518 + * random number generator. */
 2519 +CK_PKCS11_FUNCTION_INFO(C_SeedRandom)
 2520 +#ifdef CK_NEED_ARG_LIST
 2521 +(
 2522 +  CK_SESSION_HANDLE hSession,  /* the session's handle */
 2523 +  CK_BYTE_PTR       pSeed,     /* the seed material */
 2524 +  CK_ULONG          ulSeedLen  /* length of seed material */
 2525 +);
 2526 +#endif
 2527 +
 2528 +
 2529 +/* C_GenerateRandom generates random data. */
 2530 +CK_PKCS11_FUNCTION_INFO(C_GenerateRandom)
 2531 +#ifdef CK_NEED_ARG_LIST
 2532 +(
 2533 +  CK_SESSION_HANDLE hSession,    /* the session's handle */
 2534 +  CK_BYTE_PTR       RandomData,  /* receives the random data */
 2535 +  CK_ULONG          ulRandomLen  /* # of bytes to generate */
 2536 +);
 2537 +#endif
 2538 +
 2539 +
 2540 +
 2541 +/* Parallel function management */
 2542 +
 2543 +/* C_GetFunctionStatus is a legacy function; it obtains an
 2544 + * updated status of a function running in parallel with an
 2545 + * application. */
 2546 +CK_PKCS11_FUNCTION_INFO(C_GetFunctionStatus)
 2547 +#ifdef CK_NEED_ARG_LIST
 2548 +(
 2549 +  CK_SESSION_HANDLE hSession  /* the session's handle */
 2550 +);
 2551 +#endif
 2552 +
 2553 +
 2554 +/* C_CancelFunction is a legacy function; it cancels a function
 2555 + * running in parallel. */
 2556 +CK_PKCS11_FUNCTION_INFO(C_CancelFunction)
 2557 +#ifdef CK_NEED_ARG_LIST
 2558 +(
 2559 +  CK_SESSION_HANDLE hSession  /* the session's handle */
 2560 +);
 2561 +#endif
 2562 +
 2563 +
 2564 +
 2565 +/* Functions added in for Cryptoki Version 2.01 or later */
 2566 +
 2567 +/* C_WaitForSlotEvent waits for a slot event (token insertion,
 2568 + * removal, etc.) to occur. */
 2569 +CK_PKCS11_FUNCTION_INFO(C_WaitForSlotEvent)
 2570 +#ifdef CK_NEED_ARG_LIST
 2571 +(
 2572 +  CK_FLAGS flags,        /* blocking/nonblocking flag */
 2573 +  CK_SLOT_ID_PTR pSlot,  /* location that receives the slot ID */
 2574 +  CK_VOID_PTR pRserved   /* reserved.  Should be NULL_PTR */
 2575 +);
 2576 +#endif
 2577 diff -urNp openssh-4.4p1/pkcs11-headers/pkcs11.h openssh-4.4p1+pkcs11-0.17/pkcs11-headers/pkcs11.h
 2578 --- openssh-4.4p1/pkcs11-headers/pkcs11.h   1970-01-01 02:00:00.000000000 +0200
 2579 +++ openssh-4.4p1+pkcs11-0.17/pkcs11-headers/pkcs11.h   2006-09-28 08:05:35.000000000 +0300
 2580 @@ -0,0 +1,299 @@
 2581 +/* pkcs11.h include file for PKCS #11. */
 2582 +/* $Revision: 1.4 $ */
 2583 +
 2584 +/* License to copy and use this software is granted provided that it is
 2585 + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
 2586 + * (Cryptoki)" in all material mentioning or referencing this software.
 2587 +
 2588 + * License is also granted to make and use derivative works provided that
 2589 + * such works are identified as "derived from the RSA Security Inc. PKCS #11
 2590 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or 
 2591 + * referencing the derived work.
 2592 +
 2593 + * RSA Security Inc. makes no representations concerning either the 
 2594 + * merchantability of this software or the suitability of this software for
 2595 + * any particular purpose. It is provided "as is" without express or implied
 2596 + * warranty of any kind.
 2597 + */
 2598 +
 2599 +#ifndef _PKCS11_H_
 2600 +#define _PKCS11_H_ 1
 2601 +
 2602 +#ifdef __cplusplus
 2603 +extern "C" {
 2604 +#endif
 2605 +
 2606 +/* Before including this file (pkcs11.h) (or pkcs11t.h by
 2607 + * itself), 6 platform-specific macros must be defined.  These
 2608 + * macros are described below, and typical definitions for them
 2609 + * are also given.  Be advised that these definitions can depend
 2610 + * on both the platform and the compiler used (and possibly also
 2611 + * on whether a Cryptoki library is linked statically or
 2612 + * dynamically).
 2613 + *
 2614 + * In addition to defining these 6 macros, the packing convention
 2615 + * for Cryptoki structures should be set.  The Cryptoki
 2616 + * convention on packing is that structures should be 1-byte
 2617 + * aligned.
 2618 + *
 2619 + * If you're using Microsoft Developer Studio 5.0 to produce
 2620 + * Win32 stuff, this might be done by using the following
 2621 + * preprocessor directive before including pkcs11.h or pkcs11t.h:
 2622 + *
 2623 + * #pragma pack(push, cryptoki, 1)
 2624 + *
 2625 + * and using the following preprocessor directive after including
 2626 + * pkcs11.h or pkcs11t.h:
 2627 + *
 2628 + * #pragma pack(pop, cryptoki)
 2629 + *
 2630 + * If you're using an earlier version of Microsoft Developer
 2631 + * Studio to produce Win16 stuff, this might be done by using
 2632 + * the following preprocessor directive before including
 2633 + * pkcs11.h or pkcs11t.h:
 2634 + *
 2635 + * #pragma pack(1)
 2636 + *
 2637 + * In a UNIX environment, you're on your own for this.  You might
 2638 + * not need to do (or be able to do!) anything.
 2639 + *
 2640 + *
 2641 + * Now for the macros:
 2642 + *
 2643 + *
 2644 + * 1. CK_PTR: The indirection string for making a pointer to an
 2645 + * object.  It can be used like this:
 2646 + *
 2647 + * typedef CK_BYTE CK_PTR CK_BYTE_PTR;
 2648 + *
 2649 + * If you're using Microsoft Developer Studio 5.0 to produce
 2650 + * Win32 stuff, it might be defined by:
 2651 + *
 2652 + * #define CK_PTR *
 2653 + *
 2654 + * If you're using an earlier version of Microsoft Developer
 2655 + * Studio to produce Win16 stuff, it might be defined by:
 2656 + *
 2657 + * #define CK_PTR far *
 2658 + *
 2659 + * In a typical UNIX environment, it might be defined by:
 2660 + *
 2661 + * #define CK_PTR *
 2662 + *
 2663 + *
 2664 + * 2. CK_DEFINE_FUNCTION(returnType, name): A macro which makes
 2665 + * an exportable Cryptoki library function definition out of a
 2666 + * return type and a function name.  It should be used in the
 2667 + * following fashion to define the exposed Cryptoki functions in
 2668 + * a Cryptoki library:
 2669 + *
 2670 + * CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(
 2671 + *   CK_VOID_PTR pReserved
 2672 + * )
 2673 + * {
 2674 + *   ...
 2675 + * }
 2676 + *
 2677 + * If you're using Microsoft Developer Studio 5.0 to define a
 2678 + * function in a Win32 Cryptoki .dll, it might be defined by:
 2679 + *
 2680 + * #define CK_DEFINE_FUNCTION(returnType, name) \
 2681 + *   returnType __declspec(dllexport) name
 2682 + *
 2683 + * If you're using an earlier version of Microsoft Developer
 2684 + * Studio to define a function in a Win16 Cryptoki .dll, it
 2685 + * might be defined by:
 2686 + *
 2687 + * #define CK_DEFINE_FUNCTION(returnType, name) \
 2688 + *   returnType __export _far _pascal name
 2689 + *
 2690 + * In a UNIX environment, it might be defined by:
 2691 + *
 2692 + * #define CK_DEFINE_FUNCTION(returnType, name) \
 2693 + *   returnType name
 2694 + *
 2695 + *
 2696 + * 3. CK_DECLARE_FUNCTION(returnType, name): A macro which makes
 2697 + * an importable Cryptoki library function declaration out of a
 2698 + * return type and a function name.  It should be used in the
 2699 + * following fashion:
 2700 + *
 2701 + * extern CK_DECLARE_FUNCTION(CK_RV, C_Initialize)(
 2702 + *   CK_VOID_PTR pReserved
 2703 + * );
 2704 + *
 2705 + * If you're using Microsoft Developer Studio 5.0 to declare a
 2706 + * function in a Win32 Cryptoki .dll, it might be defined by:
 2707 + *
 2708 + * #define CK_DECLARE_FUNCTION(returnType, name) \
 2709 + *   returnType __declspec(dllimport) name
 2710 + *
 2711 + * If you're using an earlier version of Microsoft Developer
 2712 + * Studio to declare a function in a Win16 Cryptoki .dll, it
 2713 + * might be defined by:
 2714 + *
 2715 + * #define CK_DECLARE_FUNCTION(returnType, name) \
 2716 + *   returnType __export _far _pascal name
 2717 + *
 2718 + * In a UNIX environment, it might be defined by:
 2719 + *
 2720 + * #define CK_DECLARE_FUNCTION(returnType, name) \
 2721 + *   returnType name
 2722 + *
 2723 + *
 2724 + * 4. CK_DECLARE_FUNCTION_POINTER(returnType, name): A macro
 2725 + * which makes a Cryptoki API function pointer declaration or
 2726 + * function pointer type declaration out of a return type and a
 2727 + * function name.  It should be used in the following fashion:
 2728 + *
 2729 + * // Define funcPtr to be a pointer to a Cryptoki API function
 2730 + * // taking arguments args and returning CK_RV.
 2731 + * CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtr)(args);
 2732 + *
 2733 + * or
 2734 + *
 2735 + * // Define funcPtrType to be the type of a pointer to a
 2736 + * // Cryptoki API function taking arguments args and returning
 2737 + * // CK_RV, and then define funcPtr to be a variable of type
 2738 + * // funcPtrType.
 2739 + * typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, funcPtrType)(args);
 2740 + * funcPtrType funcPtr;
 2741 + *
 2742 + * If you're using Microsoft Developer Studio 5.0 to access
 2743 + * functions in a Win32 Cryptoki .dll, in might be defined by:
 2744 + *
 2745 + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
 2746 + *   returnType __declspec(dllimport) (* name)
 2747 + *
 2748 + * If you're using an earlier version of Microsoft Developer
 2749 + * Studio to access functions in a Win16 Cryptoki .dll, it might
 2750 + * be defined by:
 2751 + *
 2752 + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
 2753 + *   returnType __export _far _pascal (* name)
 2754 + *
 2755 + * In a UNIX environment, it might be defined by:
 2756 + *
 2757 + * #define CK_DECLARE_FUNCTION_POINTER(returnType, name) \
 2758 + *   returnType (* name)
 2759 + *
 2760 + *
 2761 + * 5. CK_CALLBACK_FUNCTION(returnType, name): A macro which makes
 2762 + * a function pointer type for an application callback out of
 2763 + * a return type for the callback and a name for the callback.
 2764 + * It should be used in the following fashion:
 2765 + *
 2766 + * CK_CALLBACK_FUNCTION(CK_RV, myCallback)(args);
 2767 + *
 2768 + * to declare a function pointer, myCallback, to a callback
 2769 + * which takes arguments args and returns a CK_RV.  It can also
 2770 + * be used like this:
 2771 + *
 2772 + * typedef CK_CALLBACK_FUNCTION(CK_RV, myCallbackType)(args);
 2773 + * myCallbackType myCallback;
 2774 + *
 2775 + * If you're using Microsoft Developer Studio 5.0 to do Win32
 2776 + * Cryptoki development, it might be defined by:
 2777 + *
 2778 + * #define CK_CALLBACK_FUNCTION(returnType, name) \
 2779 + *   returnType (* name)
 2780 + *
 2781 + * If you're using an earlier version of Microsoft Developer
 2782 + * Studio to do Win16 development, it might be defined by:
 2783 + *
 2784 + * #define CK_CALLBACK_FUNCTION(returnType, name) \
 2785 + *   returnType _far _pascal (* name)
 2786 + *
 2787 + * In a UNIX environment, it might be defined by:
 2788 + *
 2789 + * #define CK_CALLBACK_FUNCTION(returnType, name) \
 2790 + *   returnType (* name)
 2791 + *
 2792 + *
 2793 + * 6. NULL_PTR: This macro is the value of a NULL pointer.
 2794 + *
 2795 + * In any ANSI/ISO C environment (and in many others as well),
 2796 + * this should best be defined by
 2797 + *
 2798 + * #ifndef NULL_PTR
 2799 + * #define NULL_PTR 0
 2800 + * #endif
 2801 + */
 2802 +
 2803 +
 2804 +/* All the various Cryptoki types and #define'd values are in the
 2805 + * file pkcs11t.h. */
 2806 +#include "pkcs11t.h"
 2807 +
 2808 +#define __PASTE(x,y)      x##y
 2809 +
 2810 +
 2811 +/* ==============================================================
 2812 + * Define the "extern" form of all the entry points.
 2813 + * ==============================================================
 2814 + */
 2815 +
 2816 +#define CK_NEED_ARG_LIST  1
 2817 +#define CK_PKCS11_FUNCTION_INFO(name) \
 2818 +  extern CK_DECLARE_FUNCTION(CK_RV, name)
 2819 +
 2820 +/* pkcs11f.h has all the information about the Cryptoki
 2821 + * function prototypes. */
 2822 +#include "pkcs11f.h"
 2823 +
 2824 +#undef CK_NEED_ARG_LIST
 2825 +#undef CK_PKCS11_FUNCTION_INFO
 2826 +
 2827 +
 2828 +/* ==============================================================
 2829 + * Define the typedef form of all the entry points.  That is, for
 2830 + * each Cryptoki function C_XXX, define a type CK_C_XXX which is
 2831 + * a pointer to that kind of function.
 2832 + * ==============================================================
 2833 + */
 2834 +
 2835 +#define CK_NEED_ARG_LIST  1
 2836 +#define CK_PKCS11_FUNCTION_INFO(name) \
 2837 +  typedef CK_DECLARE_FUNCTION_POINTER(CK_RV, __PASTE(CK_,name))
 2838 +
 2839 +/* pkcs11f.h has all the information about the Cryptoki
 2840 + * function prototypes. */
 2841 +#include "pkcs11f.h"
 2842 +
 2843 +#undef CK_NEED_ARG_LIST
 2844 +#undef CK_PKCS11_FUNCTION_INFO
 2845 +
 2846 +
 2847 +/* ==============================================================
 2848 + * Define structed vector of entry points.  A CK_FUNCTION_LIST
 2849 + * contains a CK_VERSION indicating a library's Cryptoki version
 2850 + * and then a whole slew of function pointers to the routines in
 2851 + * the library.  This type was declared, but not defined, in
 2852 + * pkcs11t.h.
 2853 + * ==============================================================
 2854 + */
 2855 +
 2856 +#define CK_PKCS11_FUNCTION_INFO(name) \
 2857 +  __PASTE(CK_,name) name;
 2858 +  
 2859 +struct CK_FUNCTION_LIST {
 2860 +
 2861 +  CK_VERSION    version;  /* Cryptoki version */
 2862 +
 2863 +/* Pile all the function pointers into the CK_FUNCTION_LIST. */
 2864 +/* pkcs11f.h has all the information about the Cryptoki
 2865 + * function prototypes. */
 2866 +#include "pkcs11f.h"
 2867 +
 2868 +};
 2869 +
 2870 +#undef CK_PKCS11_FUNCTION_INFO
 2871 +
 2872 +
 2873 +#undef __PASTE
 2874 +
 2875 +#ifdef __cplusplus
 2876 +}
 2877 +#endif
 2878 +
 2879 +#endif
 2880 diff -urNp openssh-4.4p1/pkcs11-headers/pkcs11t.h openssh-4.4p1+pkcs11-0.17/pkcs11-headers/pkcs11t.h
 2881 --- openssh-4.4p1/pkcs11-headers/pkcs11t.h  1970-01-01 02:00:00.000000000 +0200
 2882 +++ openssh-4.4p1+pkcs11-0.17/pkcs11-headers/pkcs11t.h  2006-09-28 08:05:35.000000000 +0300
 2883 @@ -0,0 +1,1685 @@
 2884 +/* pkcs11t.h include file for PKCS #11. */
 2885 +/* $Revision: 1.6 $ */
 2886 +
 2887 +/* License to copy and use this software is granted provided that it is
 2888 + * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface
 2889 + * (Cryptoki)" in all material mentioning or referencing this software.
 2890 +
 2891 + * License is also granted to make and use derivative works provided that
 2892 + * such works are identified as "derived from the RSA Security Inc. PKCS #11
 2893 + * Cryptographic Token Interface (Cryptoki)" in all material mentioning or
 2894 + * referencing the derived work.
 2895 +
 2896 + * RSA Security Inc. makes no representations concerning either the
 2897 + * merchantability of this software or the suitability of this software for
 2898 + * any particular purpose. It is provided "as is" without express or implied
 2899 + * warranty of any kind.
 2900 + */
 2901 +
 2902 +/* See top of pkcs11.h for information about the macros that
 2903 + * must be defined and the structure-packing conventions that
 2904 + * must be set before including this file. */
 2905 +
 2906 +#ifndef _PKCS11T_H_
 2907 +#define _PKCS11T_H_ 1
 2908 +
 2909 +#define CK_TRUE 1
 2910 +#define CK_FALSE 0
 2911 +
 2912 +#ifndef CK_DISABLE_TRUE_FALSE
 2913 +#ifndef FALSE
 2914 +#define FALSE CK_FALSE
 2915 +#endif
 2916 +
 2917 +#ifndef TRUE
 2918 +#define TRUE CK_TRUE
 2919 +#endif
 2920 +#endif
 2921 +
 2922 +/* an unsigned 8-bit value */
 2923 +typedef unsigned char     CK_BYTE;
 2924 +
 2925 +/* an unsigned 8-bit character */
 2926 +typedef CK_BYTE           CK_CHAR;
 2927 +
 2928 +/* an 8-bit UTF-8 character */
 2929 +typedef CK_BYTE           CK_UTF8CHAR;
 2930 +
 2931 +/* a BYTE-sized Boolean flag */
 2932 +typedef CK_BYTE           CK_BBOOL;
 2933 +
 2934 +/* an unsigned value, at least 32 bits long */
 2935 +typedef unsigned long int CK_ULONG;
 2936 +
 2937 +/* a signed value, the same size as a CK_ULONG */
 2938 +/* CK_LONG is new for v2.0 */
 2939 +typedef long int          CK_LONG;
 2940 +
 2941 +/* at least 32 bits; each bit is a Boolean flag */
 2942 +typedef CK_ULONG          CK_FLAGS;
 2943 +
 2944 +
 2945 +/* some special values for certain CK_ULONG variables */
 2946 +#define CK_UNAVAILABLE_INFORMATION (~0UL)
 2947 +#define CK_EFFECTIVELY_INFINITE    0
 2948 +
 2949 +
 2950 +typedef CK_BYTE     CK_PTR   CK_BYTE_PTR;
 2951 +typedef CK_CHAR     CK_PTR   CK_CHAR_PTR;
 2952 +typedef CK_UTF8CHAR CK_PTR   CK_UTF8CHAR_PTR;
 2953 +typedef CK_ULONG    CK_PTR   CK_ULONG_PTR;
 2954 +typedef void        CK_PTR   CK_VOID_PTR;
 2955 +
 2956 +/* Pointer to a CK_VOID_PTR-- i.e., pointer to pointer to void */
 2957 +typedef CK_VOID_PTR CK_PTR CK_VOID_PTR_PTR;
 2958 +
 2959 +
 2960 +/* The following value is always invalid if used as a session */
 2961 +/* handle or object handle */
 2962 +#define CK_INVALID_HANDLE 0
 2963 +
 2964 +
 2965 +typedef struct CK_VERSION {
 2966 +  CK_BYTE       major;  /* integer portion of version number */
 2967 +  CK_BYTE       minor;  /* 1/100ths portion of version number */
 2968 +} CK_VERSION;
 2969 +
 2970 +typedef CK_VERSION CK_PTR CK_VERSION_PTR;
 2971 +
 2972 +
 2973 +typedef struct CK_INFO {
 2974 +  /* manufacturerID and libraryDecription have been changed from
 2975 +   * CK_CHAR to CK_UTF8CHAR for v2.10 */
 2976 +  CK_VERSION    cryptokiVersion;     /* Cryptoki interface ver */
 2977 +  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */
 2978 +  CK_FLAGS      flags;               /* must be zero */
 2979 +
 2980 +  /* libraryDescription and libraryVersion are new for v2.0 */
 2981 +  CK_UTF8CHAR   libraryDescription[32];  /* blank padded */
 2982 +  CK_VERSION    libraryVersion;          /* version of library */
 2983 +} CK_INFO;
 2984 +
 2985 +typedef CK_INFO CK_PTR    CK_INFO_PTR;
 2986 +
 2987 +
 2988 +/* CK_NOTIFICATION enumerates the types of notifications that
 2989 + * Cryptoki provides to an application */
 2990 +/* CK_NOTIFICATION has been changed from an enum to a CK_ULONG
 2991 + * for v2.0 */
 2992 +typedef CK_ULONG CK_NOTIFICATION;
 2993 +#define CKN_SURRENDER       0
 2994 +
 2995 +
 2996 +typedef CK_ULONG          CK_SLOT_ID;
 2997 +
 2998 +typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR;
 2999 +
 3000 +
 3001 +/* CK_SLOT_INFO provides information about a slot */
 3002 +typedef struct CK_SLOT_INFO {
 3003 +  /* slotDescription and manufacturerID have been changed from
 3004 +   * CK_CHAR to CK_UTF8CHAR for v2.10 */
 3005 +  CK_UTF8CHAR   slotDescription[64];  /* blank padded */
 3006 +  CK_UTF8CHAR   manufacturerID[32];   /* blank padded */
 3007 +  CK_FLAGS      flags;
 3008 +
 3009 +  /* hardwareVersion and firmwareVersion are new for v2.0 */
 3010 +  CK_VERSION    hardwareVersion;  /* version of hardware */
 3011 +  CK_VERSION    firmwareVersion;  /* version of firmware */
 3012 +} CK_SLOT_INFO;
 3013 +
 3014 +/* flags: bit flags that provide capabilities of the slot
 3015 + *      Bit Flag              Mask        Meaning
 3016 + */
 3017 +#define CKF_TOKEN_PRESENT     0x00000001  /* a token is there */
 3018 +#define CKF_REMOVABLE_DEVICE  0x00000002  /* removable devices*/
 3019 +#define CKF_HW_SLOT           0x00000004  /* hardware slot */
 3020 +
 3021 +typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR;
 3022 +
 3023 +
 3024 +/* CK_TOKEN_INFO provides information about a token */
 3025 +typedef struct CK_TOKEN_INFO {
 3026 +  /* label, manufacturerID, and model have been changed from
 3027 +   * CK_CHAR to CK_UTF8CHAR for v2.10 */
 3028 +  CK_UTF8CHAR   label[32];           /* blank padded */
 3029 +  CK_UTF8CHAR   manufacturerID[32];  /* blank padded */
 3030 +  CK_UTF8CHAR   model[16];           /* blank padded */
 3031 +  CK_CHAR       serialNumber[16];    /* blank padded */
 3032 +  CK_FLAGS      flags;               /* see below */
 3033 +
 3034 +  /* ulMaxSessionCount, ulSessionCount, ulMaxRwSessionCount,
 3035 +   * ulRwSessionCount, ulMaxPinLen, and ulMinPinLen have all been
 3036 +   * changed from CK_USHORT to CK_ULONG for v2.0 */
 3037 +  CK_ULONG      ulMaxSessionCount;     /* max open sessions */
 3038 +  CK_ULONG      ulSessionCount;        /* sess. now open */
 3039 +  CK_ULONG      ulMaxRwSessionCount;   /* max R/W sessions */
 3040 +  CK_ULONG      ulRwSessionCount;      /* R/W sess. now open */
 3041 +  CK_ULONG      ulMaxPinLen;           /* in bytes */
 3042 +  CK_ULONG      ulMinPinLen;           /* in bytes */
 3043 +  CK_ULONG      ulTotalPublicMemory;   /* in bytes */
 3044 +  CK_ULONG      ulFreePublicMemory;    /* in bytes */
 3045 +  CK_ULONG      ulTotalPrivateMemory;  /* in bytes */
 3046 +  CK_ULONG      ulFreePrivateMemory;   /* in bytes */
 3047 +
 3048 +  /* hardwareVersion, firmwareVersion, and time are new for
 3049 +   * v2.0 */
 3050 +  CK_VERSION    hardwareVersion;       /* version of hardware */
 3051 +  CK_VERSION    firmwareVersion;       /* version of firmware */
 3052 +  CK_CHAR       utcTime[16];           /* time */
 3053 +} CK_TOKEN_INFO;
 3054 +
 3055 +/* The flags parameter is defined as follows:
 3056 + *      Bit Flag                    Mask        Meaning
 3057 + */
 3058 +#define CKF_RNG                     0x00000001  /* has random #
 3059 +                                                 * generator */
 3060 +#define CKF_WRITE_PROTECTED         0x00000002  /* token is
 3061 +                                                 * write-
 3062 +                                                 * protected */
 3063 +#define CKF_LOGIN_REQUIRED          0x00000004  /* user must
 3064 +                                                 * login */
 3065 +#define CKF_USER_PIN_INITIALIZED    0x00000008  /* normal user's
 3066 +                                                 * PIN is set */
 3067 +
 3068 +/* CKF_RESTORE_KEY_NOT_NEEDED is new for v2.0.  If it is set,
 3069 + * that means that *every* time the state of cryptographic
 3070 + * operations of a session is successfully saved, all keys
 3071 + * needed to continue those operations are stored in the state */
 3072 +#define CKF_RESTORE_KEY_NOT_NEEDED  0x00000020
 3073 +
 3074 +/* CKF_CLOCK_ON_TOKEN is new for v2.0.  If it is set, that means
 3075 + * that the token has some sort of clock.  The time on that
 3076 + * clock is returned in the token info structure */
 3077 +#define CKF_CLOCK_ON_TOKEN          0x00000040
 3078 +
 3079 +/* CKF_PROTECTED_AUTHENTICATION_PATH is new for v2.0.  If it is
 3080 + * set, that means that there is some way for the user to login
 3081 + * without sending a PIN through the Cryptoki library itself */
 3082 +#define CKF_PROTECTED_AUTHENTICATION_PATH 0x00000100
 3083 +
 3084 +/* CKF_DUAL_CRYPTO_OPERATIONS is new for v2.0.  If it is true,
 3085 + * that means that a single session with the token can perform
 3086 + * dual simultaneous cryptographic operations (digest and
 3087 + * encrypt; decrypt and digest; sign and encrypt; and decrypt
 3088 + * and sign) */
 3089 +#define CKF_DUAL_CRYPTO_OPERATIONS  0x00000200
 3090 +
 3091 +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the
 3092 + * token has been initialized using C_InitializeToken or an
 3093 + * equivalent mechanism outside the scope of PKCS #11.
 3094 + * Calling C_InitializeToken when this flag is set will cause
 3095 + * the token to be reinitialized. */
 3096 +#define CKF_TOKEN_INITIALIZED       0x00000400
 3097 +
 3098 +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is
 3099 + * true, the token supports secondary authentication for
 3100 + * private key objects. This flag is deprecated in v2.11 and
 3101 +   onwards. */
 3102 +#define CKF_SECONDARY_AUTHENTICATION  0x00000800
 3103 +
 3104 +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an
 3105 + * incorrect user login PIN has been entered at least once
 3106 + * since the last successful authentication. */
 3107 +#define CKF_USER_PIN_COUNT_LOW       0x00010000
 3108 +
 3109 +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true,
 3110 + * supplying an incorrect user PIN will it to become locked. */
 3111 +#define CKF_USER_PIN_FINAL_TRY       0x00020000
 3112 +
 3113 +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the
 3114 + * user PIN has been locked. User login to the token is not
 3115 + * possible. */
 3116 +#define CKF_USER_PIN_LOCKED          0x00040000
 3117 +
 3118 +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
 3119 + * the user PIN value is the default value set by token
 3120 + * initialization or manufacturing, or the PIN has been
 3121 + * expired by the card. */
 3122 +#define CKF_USER_PIN_TO_BE_CHANGED   0x00080000
 3123 +
 3124 +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an
 3125 + * incorrect SO login PIN has been entered at least once since
 3126 + * the last successful authentication. */
 3127 +#define CKF_SO_PIN_COUNT_LOW         0x00100000
 3128 +
 3129 +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true,
 3130 + * supplying an incorrect SO PIN will it to become locked. */
 3131 +#define CKF_SO_PIN_FINAL_TRY         0x00200000
 3132 +
 3133 +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO
 3134 + * PIN has been locked. SO login to the token is not possible.
 3135 + */
 3136 +#define CKF_SO_PIN_LOCKED            0x00400000
 3137 +
 3138 +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true,
 3139 + * the SO PIN value is the default value set by token
 3140 + * initialization or manufacturing, or the PIN has been
 3141 + * expired by the card. */
 3142 +#define CKF_SO_PIN_TO_BE_CHANGED     0x00800000
 3143 +
 3144 +typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR;
 3145 +
 3146 +
 3147 +/* CK_SESSION_HANDLE is a Cryptoki-assigned value that
 3148 + * identifies a session */
 3149 +typedef CK_ULONG          CK_SESSION_HANDLE;
 3150 +
 3151 +typedef CK_SESSION_HANDLE CK_PTR CK_SESSION_HANDLE_PTR;
 3152 +
 3153 +
 3154 +/* CK_USER_TYPE enumerates the types of Cryptoki users */
 3155 +/* CK_USER_TYPE has been changed from an enum to a CK_ULONG for
 3156 + * v2.0 */
 3157 +typedef CK_ULONG          CK_USER_TYPE;
 3158 +/* Security Officer */
 3159 +#define CKU_SO    0
 3160 +/* Normal user */
 3161 +#define CKU_USER  1
 3162 +/* Context specific (added in v2.20) */
 3163 +#define CKU_CONTEXT_SPECIFIC   2
 3164 +
 3165 +/* CK_STATE enumerates the session states */
 3166 +/* CK_STATE has been changed from an enum to a CK_ULONG for
 3167 + * v2.0 */
 3168 +typedef CK_ULONG          CK_STATE;
 3169 +#define CKS_RO_PUBLIC_SESSION  0
 3170 +#define CKS_RO_USER_FUNCTIONS  1
 3171 +#define CKS_RW_PUBLIC_SESSION  2
 3172 +#define CKS_RW_USER_FUNCTIONS  3
 3173 +#define CKS_RW_SO_FUNCTIONS    4
 3174 +
 3175 +
 3176 +/* CK_SESSION_INFO provides information about a session */
 3177 +typedef struct CK_SESSION_INFO {
 3178 +  CK_SLOT_ID    slotID;
 3179 +  CK_STATE      state;
 3180 +  CK_FLAGS      flags;          /* see below */
 3181 +
 3182 +  /* ulDeviceError was changed from CK_USHORT to CK_ULONG for
 3183 +   * v2.0 */
 3184 +  CK_ULONG      ulDeviceError;  /* device-dependent error code */
 3185 +} CK_SESSION_INFO;
 3186 +
 3187 +/* The flags are defined in the following table:
 3188 + *      Bit Flag                Mask        Meaning
 3189 + */
 3190 +#define CKF_RW_SESSION          0x00000002  /* session is r/w */
 3191 +#define CKF_SERIAL_SESSION      0x00000004  /* no parallel */
 3192 +
 3193 +typedef CK_SESSION_INFO CK_PTR CK_SESSION_INFO_PTR;
 3194 +
 3195 +
 3196 +/* CK_OBJECT_HANDLE is a token-specific identifier for an
 3197 + * object  */
 3198 +typedef CK_ULONG          CK_OBJECT_HANDLE;
 3199 +
 3200 +typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR;
 3201 +
 3202 +
 3203 +/* CK_OBJECT_CLASS is a value that identifies the classes (or
 3204 + * types) of objects that Cryptoki recognizes.  It is defined
 3205 + * as follows: */
 3206 +/* CK_OBJECT_CLASS was changed from CK_USHORT to CK_ULONG for
 3207 + * v2.0 */
 3208 +typedef CK_ULONG          CK_OBJECT_CLASS;
 3209 +
 3210 +/* The following classes of objects are defined: */
 3211 +/* CKO_HW_FEATURE is new for v2.10 */
 3212 +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */
 3213 +/* CKO_MECHANISM is new for v2.20 */
 3214 +#define CKO_DATA              0x00000000
 3215 +#define CKO_CERTIFICATE       0x00000001
 3216 +#define CKO_PUBLIC_KEY        0x00000002
 3217 +#define CKO_PRIVATE_KEY       0x00000003
 3218 +#define CKO_SECRET_KEY        0x00000004
 3219 +#define CKO_HW_FEATURE        0x00000005
 3220 +#define CKO_DOMAIN_PARAMETERS 0x00000006
 3221 +#define CKO_MECHANISM         0x00000007
 3222 +#define CKO_VENDOR_DEFINED    0x80000000
 3223 +
 3224 +typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR;
 3225 +
 3226 +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a
 3227 + * value that identifies the hardware feature type of an object
 3228 + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */
 3229 +typedef CK_ULONG          CK_HW_FEATURE_TYPE;
 3230 +
 3231 +/* The following hardware feature types are defined */
 3232 +/* CKH_USER_INTERFACE is new for v2.20 */
 3233 +#define CKH_MONOTONIC_COUNTER  0x00000001
 3234 +#define CKH_CLOCK           0x00000002
 3235 +#define CKH_USER_INTERFACE  0x00000003
 3236 +#define CKH_VENDOR_DEFINED  0x80000000
 3237 +
 3238 +/* CK_KEY_TYPE is a value that identifies a key type */
 3239 +/* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */
 3240 +typedef CK_ULONG          CK_KEY_TYPE;
 3241 +
 3242 +/* the following key types are defined: */
 3243 +#define CKK_RSA             0x00000000
 3244 +#define CKK_DSA             0x00000001
 3245 +#define CKK_DH              0x00000002
 3246 +
 3247 +/* CKK_ECDSA and CKK_KEA are new for v2.0 */
 3248 +/* CKK_ECDSA is deprecated in v2.11, CKK_EC is preferred. */
 3249 +#define CKK_ECDSA           0x00000003
 3250 +#define CKK_EC              0x00000003
 3251 +#define CKK_X9_42_DH        0x00000004
 3252 +#define CKK_KEA             0x00000005
 3253 +
 3254 +#define CKK_GENERIC_SECRET  0x00000010
 3255 +#define CKK_RC2             0x00000011
 3256 +#define CKK_RC4             0x00000012
 3257 +#define CKK_DES             0x00000013
 3258 +#define CKK_DES2            0x00000014
 3259 +#define CKK_DES3            0x00000015
 3260 +
 3261 +/* all these key types are new for v2.0 */
 3262 +#define CKK_CAST            0x00000016
 3263 +#define CKK_CAST3           0x00000017
 3264 +/* CKK_CAST5 is deprecated in v2.11, CKK_CAST128 is preferred. */
 3265 +#define CKK_CAST5           0x00000018
 3266 +#define CKK_CAST128         0x00000018
 3267 +#define CKK_RC5             0x00000019
 3268 +#define CKK_IDEA            0x0000001A
 3269 +#define CKK_SKIPJACK        0x0000001B
 3270 +#define CKK_BATON           0x0000001C
 3271 +#define CKK_JUNIPER         0x0000001D
 3272 +#define CKK_CDMF            0x0000001E
 3273 +#define CKK_AES             0x0000001F
 3274 +
 3275 +/* BlowFish and TwoFish are new for v2.20 */
 3276 +#define CKK_BLOWFISH        0x00000020
 3277 +#define CKK_TWOFISH         0x00000021
 3278 +
 3279 +#define CKK_VENDOR_DEFINED  0x80000000
 3280 +
 3281 +
 3282 +/* CK_CERTIFICATE_TYPE is a value that identifies a certificate
 3283 + * type */
 3284 +/* CK_CERTIFICATE_TYPE was changed from CK_USHORT to CK_ULONG
 3285 + * for v2.0 */
 3286 +typedef CK_ULONG          CK_CERTIFICATE_TYPE;
 3287 +
 3288 +/* The following certificate types are defined: */
 3289 +/* CKC_X_509_ATTR_CERT is new for v2.10 */
 3290 +/* CKC_WTLS is new for v2.20 */
 3291 +#define CKC_X_509           0x00000000
 3292 +#define CKC_X_509_ATTR_CERT 0x00000001
 3293 +#define CKC_WTLS            0x00000002
 3294 +#define CKC_VENDOR_DEFINED  0x80000000
 3295 +
 3296 +
 3297 +/* CK_ATTRIBUTE_TYPE is a value that identifies an attribute
 3298 + * type */
 3299 +/* CK_ATTRIBUTE_TYPE was changed from CK_USHORT to CK_ULONG for
 3300 + * v2.0 */
 3301 +typedef CK_ULONG          CK_ATTRIBUTE_TYPE;
 3302 +
 3303 +/* The CKF_ARRAY_ATTRIBUTE flag identifies an attribute which
 3304 +   consists of an array of values. */
 3305 +#define CKF_ARRAY_ATTRIBUTE    0x40000000
 3306 +
 3307 +/* The following attribute types are defined: */
 3308 +#define CKA_CLASS              0x00000000
 3309 +#define CKA_TOKEN              0x00000001
 3310 +#define CKA_PRIVATE            0x00000002
 3311 +#define CKA_LABEL              0x00000003
 3312 +#define CKA_APPLICATION        0x00000010
 3313 +#define CKA_VALUE              0x00000011
 3314 +
 3315 +/* CKA_OBJECT_ID is new for v2.10 */
 3316 +#define CKA_OBJECT_ID          0x00000012
 3317 +
 3318 +#define CKA_CERTIFICATE_TYPE   0x00000080
 3319 +#define CKA_ISSUER             0x00000081
 3320 +#define CKA_SERIAL_NUMBER      0x00000082
 3321 +
 3322 +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new
 3323 + * for v2.10 */
 3324 +#define CKA_AC_ISSUER          0x00000083
 3325 +#define CKA_OWNER              0x00000084
 3326 +#define CKA_ATTR_TYPES         0x00000085
 3327 +
 3328 +/* CKA_TRUSTED is new for v2.11 */
 3329 +#define CKA_TRUSTED            0x00000086
 3330 +
 3331 +/* CKA_CERTIFICATE_CATEGORY ...
 3332 + * CKA_CHECK_VALUE are new for v2.20 */
 3333 +#define CKA_CERTIFICATE_CATEGORY        0x00000087
 3334 +#define CKA_JAVA_MIDP_SECURITY_DOMAIN   0x00000088
 3335 +#define CKA_URL                         0x00000089
 3336 +#define CKA_HASH_OF_SUBJECT_PUBLIC_KEY  0x0000008A
 3337 +#define CKA_HASH_OF_ISSUER_PUBLIC_KEY   0x0000008B
 3338 +#define CKA_CHECK_VALUE                 0x00000090
 3339 +
 3340 +#define CKA_KEY_TYPE           0x00000100
 3341 +#define CKA_SUBJECT            0x00000101
 3342 +#define CKA_ID                 0x00000102
 3343 +#define CKA_SENSITIVE          0x00000103
 3344 +#define CKA_ENCRYPT            0x00000104
 3345 +#define CKA_DECRYPT            0x00000105
 3346 +#define CKA_WRAP               0x00000106
 3347 +#define CKA_UNWRAP             0x00000107
 3348 +#define CKA_SIGN               0x00000108
 3349 +#define CKA_SIGN_RECOVER       0x00000109
 3350 +#define CKA_VERIFY             0x0000010A
 3351 +#define CKA_VERIFY_RECOVER     0x0000010B
 3352 +#define CKA_DERIVE             0x0000010C
 3353 +#define CKA_START_DATE         0x00000110
 3354 +#define CKA_END_DATE           0x00000111
 3355 +#define CKA_MODULUS            0x00000120
 3356 +#define CKA_MODULUS_BITS       0x00000121
 3357 +#define CKA_PUBLIC_EXPONENT    0x00000122
 3358 +#define CKA_PRIVATE_EXPONENT   0x00000123
 3359 +#define CKA_PRIME_1            0x00000124
 3360 +#define CKA_PRIME_2            0x00000125
 3361 +#define CKA_EXPONENT_1         0x00000126
 3362 +#define CKA_EXPONENT_2         0x00000127
 3363 +#define CKA_COEFFICIENT        0x00000128
 3364 +#define CKA_PRIME              0x00000130
 3365 +#define CKA_SUBPRIME           0x00000131
 3366 +#define CKA_BASE               0x00000132
 3367 +
 3368 +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */
 3369 +#define CKA_PRIME_BITS         0x00000133
 3370 +#define CKA_SUBPRIME_BITS      0x00000134
 3371 +#define CKA_SUB_PRIME_BITS     CKA_SUBPRIME_BITS
 3372 +/* (To retain backwards-compatibility) */
 3373 +
 3374 +#define CKA_VALUE_BITS         0x00000160
 3375 +#define CKA_VALUE_LEN          0x00000161
 3376 +
 3377 +/* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE,
 3378 + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS,
 3379 + * and CKA_EC_POINT are new for v2.0 */
 3380 +#define CKA_EXTRACTABLE        0x00000162
 3381 +#define CKA_LOCAL              0x00000163
 3382 +#define CKA_NEVER_EXTRACTABLE  0x00000164
 3383 +#define CKA_ALWAYS_SENSITIVE   0x00000165
 3384 +
 3385 +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */
 3386 +#define CKA_KEY_GEN_MECHANISM  0x00000166
 3387 +
 3388 +#define CKA_MODIFIABLE         0x00000170
 3389 +
 3390 +/* CKA_ECDSA_PARAMS is deprecated in v2.11,
 3391 + * CKA_EC_PARAMS is preferred. */
 3392 +#define CKA_ECDSA_PARAMS       0x00000180
 3393 +#define CKA_EC_PARAMS          0x00000180
 3394 +
 3395 +#define CKA_EC_POINT           0x00000181
 3396 +
 3397 +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS,
 3398 + * are new for v2.10. Deprecated in v2.11 and onwards. */
 3399 +#define CKA_SECONDARY_AUTH     0x00000200
 3400 +#define CKA_AUTH_PIN_FLAGS     0x00000201
 3401 +
 3402 +/* CKA_ALWAYS_AUTHENTICATE ...
 3403 + * CKA_UNWRAP_TEMPLATE are new for v2.20 */
 3404 +#define CKA_ALWAYS_AUTHENTICATE  0x00000202
 3405 +
 3406 +#define CKA_WRAP_WITH_TRUSTED    0x00000210
 3407 +#define CKA_WRAP_TEMPLATE        (CKF_ARRAY_ATTRIBUTE|0x00000211)
 3408 +#define CKA_UNWRAP_TEMPLATE      (CKF_ARRAY_ATTRIBUTE|0x00000212)
 3409 +
 3410 +/* CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET
 3411 + * are new for v2.10 */
 3412 +#define CKA_HW_FEATURE_TYPE    0x00000300
 3413 +#define CKA_RESET_ON_INIT      0x00000301
 3414 +#define CKA_HAS_RESET          0x00000302
 3415 +
 3416 +/* The following attributes are new for v2.20 */
 3417 +#define CKA_PIXEL_X                     0x00000400
 3418 +#define CKA_PIXEL_Y                     0x00000401
 3419 +#define CKA_RESOLUTION                  0x00000402
 3420 +#define CKA_CHAR_ROWS                   0x00000403
 3421 +#define CKA_CHAR_COLUMNS                0x00000404
 3422 +#define CKA_COLOR                       0x00000405
 3423 +#define CKA_BITS_PER_PIXEL              0x00000406
 3424 +#define CKA_CHAR_SETS                   0x00000480
 3425 +#define CKA_ENCODING_METHODS            0x00000481
 3426 +#define CKA_MIME_TYPES                  0x00000482
 3427 +#define CKA_MECHANISM_TYPE              0x00000500
 3428 +#define CKA_REQUIRED_CMS_ATTRIBUTES     0x00000501
 3429 +#define CKA_DEFAULT_CMS_ATTRIBUTES      0x00000502
 3430 +#define CKA_SUPPORTED_CMS_ATTRIBUTES    0x00000503
 3431 +#define CKA_ALLOWED_MECHANISMS          (CKF_ARRAY_ATTRIBUTE|0x00000600)
 3432 +
 3433 +#define CKA_VENDOR_DEFINED     0x80000000
 3434 +
 3435 +
 3436 +/* CK_ATTRIBUTE is a structure that includes the type, length
 3437 + * and value of an attribute */
 3438 +typedef struct CK_ATTRIBUTE {
 3439 +  CK_ATTRIBUTE_TYPE type;
 3440 +  CK_VOID_PTR       pValue;
 3441 +
 3442 +  /* ulValueLen went from CK_USHORT to CK_ULONG for v2.0 */
 3443 +  CK_ULONG          ulValueLen;  /* in bytes */
 3444 +} CK_ATTRIBUTE;
 3445 +
 3446 +typedef CK_ATTRIBUTE CK_PTR CK_ATTRIBUTE_PTR;
 3447 +
 3448 +
 3449 +/* CK_DATE is a structure that defines a date */
 3450 +typedef struct CK_DATE{
 3451 +  CK_CHAR       year[4];   /* the year ("1900" - "9999") */
 3452 +  CK_CHAR       month[2];  /* the month ("01" - "12") */
 3453 +  CK_CHAR       day[2];    /* the day   ("01" - "31") */
 3454 +} CK_DATE;
 3455 +
 3456 +
 3457 +/* CK_MECHANISM_TYPE is a value that identifies a mechanism
 3458 + * type */
 3459 +/* CK_MECHANISM_TYPE was changed from CK_USHORT to CK_ULONG for
 3460 + * v2.0 */
 3461 +typedef CK_ULONG          CK_MECHANISM_TYPE;
 3462 +
 3463 +/* the following mechanism types are defined: */
 3464 +#define CKM_RSA_PKCS_KEY_PAIR_GEN      0x00000000
 3465 +#define CKM_RSA_PKCS                   0x00000001
 3466 +#define CKM_RSA_9796                   0x00000002
 3467 +#define CKM_RSA_X_509                  0x00000003
 3468 +
 3469 +/* CKM_MD2_RSA_PKCS, CKM_MD5_RSA_PKCS, and CKM_SHA1_RSA_PKCS
 3470 + * are new for v2.0.  They are mechanisms which hash and sign */
 3471 +#define CKM_MD2_RSA_PKCS               0x00000004
 3472 +#define CKM_MD5_RSA_PKCS               0x00000005
 3473 +#define CKM_SHA1_RSA_PKCS              0x00000006
 3474 +
 3475 +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS, and
 3476 + * CKM_RSA_PKCS_OAEP are new for v2.10 */
 3477 +#define CKM_RIPEMD128_RSA_PKCS         0x00000007
 3478 +#define CKM_RIPEMD160_RSA_PKCS         0x00000008
 3479 +#define CKM_RSA_PKCS_OAEP              0x00000009
 3480 +
 3481 +/* CKM_RSA_X9_31_KEY_PAIR_GEN, CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31,
 3482 + * CKM_RSA_PKCS_PSS, and CKM_SHA1_RSA_PKCS_PSS are new for v2.11 */
 3483 +#define CKM_RSA_X9_31_KEY_PAIR_GEN     0x0000000A
 3484 +#define CKM_RSA_X9_31                  0x0000000B
 3485 +#define CKM_SHA1_RSA_X9_31             0x0000000C
 3486 +#define CKM_RSA_PKCS_PSS               0x0000000D
 3487 +#define CKM_SHA1_RSA_PKCS_PSS          0x0000000E
 3488 +
 3489 +#define CKM_DSA_KEY_PAIR_GEN           0x00000010
 3490 +#define CKM_DSA                        0x00000011
 3491 +#define CKM_DSA_SHA1                   0x00000012
 3492 +#define CKM_DH_PKCS_KEY_PAIR_GEN       0x00000020
 3493 +#define CKM_DH_PKCS_DERIVE             0x00000021
 3494 +
 3495 +/* CKM_X9_42_DH_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE,
 3496 + * CKM_X9_42_DH_HYBRID_DERIVE, and CKM_X9_42_MQV_DERIVE are new for
 3497 + * v2.11 */
 3498 +#define CKM_X9_42_DH_KEY_PAIR_GEN      0x00000030
 3499 +#define CKM_X9_42_DH_DERIVE            0x00000031
 3500 +#define CKM_X9_42_DH_HYBRID_DERIVE     0x00000032
 3501 +#define CKM_X9_42_MQV_DERIVE           0x00000033
 3502 +
 3503 +/* CKM_SHA256/384/512 are new for v2.20 */
 3504 +#define CKM_SHA256_RSA_PKCS            0x00000040
 3505 +#define CKM_SHA384_RSA_PKCS            0x00000041
 3506 +#define CKM_SHA512_RSA_PKCS            0x00000042
 3507 +#define CKM_SHA256_RSA_PKCS_PSS        0x00000043
 3508 +#define CKM_SHA384_RSA_PKCS_PSS        0x00000044
 3509 +#define CKM_SHA512_RSA_PKCS_PSS        0x00000045
 3510 +
 3511 +#define CKM_RC2_KEY_GEN                0x00000100
 3512 +#define CKM_RC2_ECB                    0x00000101
 3513 +#define CKM_RC2_CBC                    0x00000102
 3514 +#define CKM_RC2_MAC                    0x00000103
 3515 +
 3516 +/* CKM_RC2_MAC_GENERAL and CKM_RC2_CBC_PAD are new for v2.0 */
 3517 +#define CKM_RC2_MAC_GENERAL            0x00000104
 3518 +#define CKM_RC2_CBC_PAD                0x00000105
 3519 +
 3520 +#define CKM_RC4_KEY_GEN                0x00000110
 3521 +#define CKM_RC4                        0x00000111
 3522 +#define CKM_DES_KEY_GEN                0x00000120
 3523 +#define CKM_DES_ECB                    0x00000121
 3524 +#define CKM_DES_CBC                    0x00000122
 3525 +#define CKM_DES_MAC                    0x00000123
 3526 +
 3527 +/* CKM_DES_MAC_GENERAL and CKM_DES_CBC_PAD are new for v2.0 */
 3528 +#define CKM_DES_MAC_GENERAL            0x00000124
 3529 +#define CKM_DES_CBC_PAD                0x00000125
 3530 +
 3531 +#define CKM_DES2_KEY_GEN               0x00000130
 3532 +#define CKM_DES3_KEY_GEN               0x00000131
 3533 +#define CKM_DES3_ECB                   0x00000132
 3534 +#define CKM_DES3_CBC                   0x00000133
 3535 +#define CKM_DES3_MAC                   0x00000134
 3536 +
 3537 +/* CKM_DES3_MAC_GENERAL, CKM_DES3_CBC_PAD, CKM_CDMF_KEY_GEN,
 3538 + * CKM_CDMF_ECB, CKM_CDMF_CBC, CKM_CDMF_MAC,
 3539 + * CKM_CDMF_MAC_GENERAL, and CKM_CDMF_CBC_PAD are new for v2.0 */
 3540 +#define CKM_DES3_MAC_GENERAL           0x00000135
 3541 +#define CKM_DES3_CBC_PAD               0x00000136
 3542 +#define CKM_CDMF_KEY_GEN               0x00000140
 3543 +#define CKM_CDMF_ECB                   0x00000141
 3544 +#define CKM_CDMF_CBC                   0x00000142
 3545 +#define CKM_CDMF_MAC                   0x00000143
 3546 +#define CKM_CDMF_MAC_GENERAL           0x00000144
 3547 +#define CKM_CDMF_CBC_PAD               0x00000145
 3548 +
 3549 +/* the following four DES mechanisms are new for v2.20 */
 3550 +#define CKM_DES_OFB64                  0x00000150
 3551 +#define CKM_DES_OFB8                   0x00000151
 3552 +#define CKM_DES_CFB64                  0x00000152
 3553 +#define CKM_DES_CFB8                   0x00000153
 3554 +
 3555 +#define CKM_MD2                        0x00000200
 3556 +
 3557 +/* CKM_MD2_HMAC and CKM_MD2_HMAC_GENERAL are new for v2.0 */
 3558 +#define CKM_MD2_HMAC                   0x00000201
 3559 +#define CKM_MD2_HMAC_GENERAL           0x00000202
 3560 +
 3561 +#define CKM_MD5                        0x00000210
 3562 +
 3563 +/* CKM_MD5_HMAC and CKM_MD5_HMAC_GENERAL are new for v2.0 */
 3564 +#define CKM_MD5_HMAC                   0x00000211
 3565 +#define CKM_MD5_HMAC_GENERAL           0x00000212
 3566 +
 3567 +#define CKM_SHA_1                      0x00000220
 3568 +
 3569 +/* CKM_SHA_1_HMAC and CKM_SHA_1_HMAC_GENERAL are new for v2.0 */
 3570 +#define CKM_SHA_1_HMAC                 0x00000221
 3571 +#define CKM_SHA_1_HMAC_GENERAL         0x00000222
 3572 +
 3573 +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC,
 3574 + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC,
 3575 + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */
 3576 +#define CKM_RIPEMD128                  0x00000230
 3577 +#define CKM_RIPEMD128_HMAC             0x00000231
 3578 +#define CKM_RIPEMD128_HMAC_GENERAL     0x00000232
 3579 +#define CKM_RIPEMD160                  0x00000240
 3580 +#define CKM_RIPEMD160_HMAC             0x00000241
 3581 +#define CKM_RIPEMD160_HMAC_GENERAL     0x00000242
 3582 +
 3583 +/* CKM_SHA256/384/512 are new for v2.20 */
 3584 +#define CKM_SHA256                     0x00000250
 3585 +#define CKM_SHA256_HMAC                0x00000251
 3586 +#define CKM_SHA256_HMAC_GENERAL        0x00000252
 3587 +#define CKM_SHA384                     0x00000260
 3588 +#define CKM_SHA384_HMAC                0x00000261
 3589 +#define CKM_SHA384_HMAC_GENERAL        0x00000262
 3590 +#define CKM_SHA512                     0x00000270
 3591 +#define CKM_SHA512_HMAC                0x00000271
 3592 +#define CKM_SHA512_HMAC_GENERAL        0x00000272
 3593 +
 3594 +/* All of the following mechanisms are new for v2.0 */
 3595 +/* Note that CAST128 and CAST5 are the same algorithm */
 3596 +#define CKM_CAST_KEY_GEN               0x00000300
 3597 +#define CKM_CAST_ECB                   0x00000301
 3598 +#define CKM_CAST_CBC                   0x00000302
 3599 +#define CKM_CAST_MAC                   0x00000303
 3600 +#define CKM_CAST_MAC_GENERAL           0x00000304
 3601 +#define CKM_CAST_CBC_PAD               0x00000305
 3602 +#define CKM_CAST3_KEY_GEN              0x00000310
 3603 +#define CKM_CAST3_ECB                  0x00000311
 3604 +#define CKM_CAST3_CBC                  0x00000312
 3605 +#define CKM_CAST3_MAC                  0x00000313
 3606 +#define CKM_CAST3_MAC_GENERAL          0x00000314
 3607 +#define CKM_CAST3_CBC_PAD              0x00000315
 3608 +#define CKM_CAST5_KEY_GEN              0x00000320
 3609 +#define CKM_CAST128_KEY_GEN            0x00000320
 3610 +#define CKM_CAST5_ECB                  0x00000321
 3611 +#define CKM_CAST128_ECB                0x00000321
 3612 +#define CKM_CAST5_CBC                  0x00000322
 3613 +#define CKM_CAST128_CBC                0x00000322
 3614 +#define CKM_CAST5_MAC                  0x00000323
 3615 +#define CKM_CAST128_MAC                0x00000323
 3616 +#define CKM_CAST5_MAC_GENERAL          0x00000324
 3617 +#define CKM_CAST128_MAC_GENERAL        0x00000324
 3618 +#define CKM_CAST5_CBC_PAD              0x00000325
 3619 +#define CKM_CAST128_CBC_PAD            0x00000325
 3620 +#define CKM_RC5_KEY_GEN                0x00000330
 3621 +#define CKM_RC5_ECB                    0x00000331
 3622 +#define CKM_RC5_CBC                    0x00000332
 3623 +#define CKM_RC5_MAC                    0x00000333
 3624 +#define CKM_RC5_MAC_GENERAL            0x00000334
 3625 +#define CKM_RC5_CBC_PAD                0x00000335
 3626 +#define CKM_IDEA_KEY_GEN               0x00000340
 3627 +#define CKM_IDEA_ECB                   0x00000341
 3628 +#define CKM_IDEA_CBC                   0x00000342
 3629 +#define CKM_IDEA_MAC                   0x00000343
 3630 +#define CKM_IDEA_MAC_GENERAL           0x00000344
 3631 +#define CKM_IDEA_CBC_PAD               0x00000345
 3632 +#define CKM_GENERIC_SECRET_KEY_GEN     0x00000350
 3633 +#define CKM_CONCATENATE_BASE_AND_KEY   0x00000360
 3634 +#define CKM_CONCATENATE_BASE_AND_DATA  0x00000362
 3635 +#define CKM_CONCATENATE_DATA_AND_BASE  0x00000363
 3636 +#define CKM_XOR_BASE_AND_DATA          0x00000364
 3637 +#define CKM_EXTRACT_KEY_FROM_KEY       0x00000365
 3638 +#define CKM_SSL3_PRE_MASTER_KEY_GEN    0x00000370
 3639 +#define CKM_SSL3_MASTER_KEY_DERIVE     0x00000371
 3640 +#define CKM_SSL3_KEY_AND_MAC_DERIVE    0x00000372
 3641 +
 3642 +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN,
 3643 + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, and
 3644 + * CKM_TLS_MASTER_KEY_DERIVE_DH are new for v2.11 */
 3645 +#define CKM_SSL3_MASTER_KEY_DERIVE_DH  0x00000373
 3646 +#define CKM_TLS_PRE_MASTER_KEY_GEN     0x00000374
 3647 +#define CKM_TLS_MASTER_KEY_DERIVE      0x00000375
 3648 +#define CKM_TLS_KEY_AND_MAC_DERIVE     0x00000376
 3649 +#define CKM_TLS_MASTER_KEY_DERIVE_DH   0x00000377
 3650 +
 3651 +/* CKM_TLS_PRF is new for v2.20 */
 3652 +#define CKM_TLS_PRF                    0x00000378
 3653 +
 3654 +#define CKM_SSL3_MD5_MAC               0x00000380
 3655 +#define CKM_SSL3_SHA1_MAC              0x00000381
 3656 +#define CKM_MD5_KEY_DERIVATION         0x00000390
 3657 +#define CKM_MD2_KEY_DERIVATION         0x00000391
 3658 +#define CKM_SHA1_KEY_DERIVATION        0x00000392
 3659 +
 3660 +/* CKM_SHA256/384/512 are new for v2.20 */
 3661 +#define CKM_SHA256_KEY_DERIVATION      0x00000393
 3662 +#define CKM_SHA384_KEY_DERIVATION      0x00000394
 3663 +#define CKM_SHA512_KEY_DERIVATION      0x00000395
 3664 +
 3665 +#define CKM_PBE_MD2_DES_CBC            0x000003A0
 3666 +#define CKM_PBE_MD5_DES_CBC            0x000003A1
 3667 +#define CKM_PBE_MD5_CAST_CBC           0x000003A2
 3668 +#define CKM_PBE_MD5_CAST3_CBC          0x000003A3
 3669 +#define CKM_PBE_MD5_CAST5_CBC          0x000003A4
 3670 +#define CKM_PBE_MD5_CAST128_CBC        0x000003A4
 3671 +#define CKM_PBE_SHA1_CAST5_CBC         0x000003A5
 3672 +#define CKM_PBE_SHA1_CAST128_CBC       0x000003A5
 3673 +#define CKM_PBE_SHA1_RC4_128           0x000003A6
 3674 +#define CKM_PBE_SHA1_RC4_40            0x000003A7
 3675 +#define CKM_PBE_SHA1_DES3_EDE_CBC      0x000003A8
 3676 +#define CKM_PBE_SHA1_DES2_EDE_CBC      0x000003A9
 3677 +#define CKM_PBE_SHA1_RC2_128_CBC       0x000003AA
 3678 +#define CKM_PBE_SHA1_RC2_40_CBC        0x000003AB
 3679 +
 3680 +/* CKM_PKCS5_PBKD2 is new for v2.10 */
 3681 +#define CKM_PKCS5_PBKD2                0x000003B0
 3682 +
 3683 +#define CKM_PBA_SHA1_WITH_SHA1_HMAC    0x000003C0
 3684 +
 3685 +/* WTLS mechanisms are new for v2.20 */
 3686 +#define CKM_WTLS_PRE_MASTER_KEY_GEN         0x000003D0
 3687 +#define CKM_WTLS_MASTER_KEY_DERIVE          0x000003D1
 3688 +#define CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC   0x000003D2
 3689 +#define CKM_WTLS_PRF                        0x000003D3
 3690 +#define CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE  0x000003D4
 3691 +#define CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE  0x000003D5
 3692 +
 3693 +#define CKM_KEY_WRAP_LYNKS             0x00000400
 3694 +#define CKM_KEY_WRAP_SET_OAEP          0x00000401
 3695 +
 3696 +/* CKM_CMS_SIG is new for v2.20 */
 3697 +#define CKM_CMS_SIG                    0x00000500
 3698 +
 3699 +/* Fortezza mechanisms */
 3700 +#define CKM_SKIPJACK_KEY_GEN           0x00001000
 3701 +#define CKM_SKIPJACK_ECB64             0x00001001
 3702 +#define CKM_SKIPJACK_CBC64             0x00001002
 3703 +#define CKM_SKIPJACK_OFB64             0x00001003
 3704 +#define CKM_SKIPJACK_CFB64             0x00001004
 3705 +#define CKM_SKIPJACK_CFB32             0x00001005
 3706 +#define CKM_SKIPJACK_CFB16             0x00001006
 3707 +#define CKM_SKIPJACK_CFB8              0x00001007
 3708 +#define CKM_SKIPJACK_WRAP              0x00001008
 3709 +#define CKM_SKIPJACK_PRIVATE_WRAP      0x00001009
 3710 +#define CKM_SKIPJACK_RELAYX            0x0000100a
 3711 +#define CKM_KEA_KEY_PAIR_GEN           0x00001010
 3712 +#define CKM_KEA_KEY_DERIVE             0x00001011
 3713 +#define CKM_FORTEZZA_TIMESTAMP         0x00001020
 3714 +#define CKM_BATON_KEY_GEN              0x00001030
 3715 +#define CKM_BATON_ECB128               0x00001031
 3716 +#define CKM_BATON_ECB96                0x00001032
 3717 +#define CKM_BATON_CBC128               0x00001033
 3718 +#define CKM_BATON_COUNTER              0x00001034
 3719 +#define CKM_BATON_SHUFFLE              0x00001035
 3720 +#define CKM_BATON_WRAP                 0x00001036
 3721 +
 3722 +/* CKM_ECDSA_KEY_PAIR_GEN is deprecated in v2.11,
 3723 + * CKM_EC_KEY_PAIR_GEN is preferred */
 3724 +#define CKM_ECDSA_KEY_PAIR_GEN         0x00001040
 3725 +#define CKM_EC_KEY_PAIR_GEN            0x00001040
 3726 +
 3727 +#define CKM_ECDSA                      0x00001041
 3728 +#define CKM_ECDSA_SHA1                 0x00001042
 3729 +
 3730 +/* CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE, and CKM_ECMQV_DERIVE
 3731 + * are new for v2.11 */
 3732 +#define CKM_ECDH1_DERIVE               0x00001050
 3733 +#define CKM_ECDH1_COFACTOR_DERIVE      0x00001051
 3734 +#define CKM_ECMQV_DERIVE               0x00001052
 3735 +
 3736 +#define CKM_JUNIPER_KEY_GEN            0x00001060
 3737 +#define CKM_JUNIPER_ECB128             0x00001061
 3738 +#define CKM_JUNIPER_CBC128             0x00001062
 3739 +#define CKM_JUNIPER_COUNTER            0x00001063
 3740 +#define CKM_JUNIPER_SHUFFLE            0x00001064
 3741 +#define CKM_JUNIPER_WRAP               0x00001065
 3742 +#define CKM_FASTHASH                   0x00001070
 3743 +
 3744 +/* CKM_AES_KEY_GEN, CKM_AES_ECB, CKM_AES_CBC, CKM_AES_MAC,
 3745 + * CKM_AES_MAC_GENERAL, CKM_AES_CBC_PAD, CKM_DSA_PARAMETER_GEN,
 3746 + * CKM_DH_PKCS_PARAMETER_GEN, and CKM_X9_42_DH_PARAMETER_GEN are
 3747 + * new for v2.11 */
 3748 +#define CKM_AES_KEY_GEN                0x00001080
 3749 +#define CKM_AES_ECB                    0x00001081
 3750 +#define CKM_AES_CBC                    0x00001082
 3751 +#define CKM_AES_MAC                    0x00001083
 3752 +#define CKM_AES_MAC_GENERAL            0x00001084
 3753 +#define CKM_AES_CBC_PAD                0x00001085
 3754 +
 3755 +/* BlowFish and TwoFish are new for v2.20 */
 3756 +#define CKM_BLOWFISH_KEY_GEN           0x00001090
 3757 +#define CKM_BLOWFISH_CBC               0x00001091
 3758 +#define CKM_TWOFISH_KEY_GEN            0x00001092
 3759 +#define CKM_TWOFISH_CBC                0x00001093
 3760 +
 3761 +
 3762 +/* CKM_xxx_ENCRYPT_DATA mechanisms are new for v2.20 */
 3763 +#define CKM_DES_ECB_ENCRYPT_DATA       0x00001100
 3764 +#define CKM_DES_CBC_ENCRYPT_DATA       0x00001101
 3765 +#define CKM_DES3_ECB_ENCRYPT_DATA      0x00001102
 3766 +#define CKM_DES3_CBC_ENCRYPT_DATA      0x00001103
 3767 +#define CKM_AES_ECB_ENCRYPT_DATA       0x00001104
 3768 +#define CKM_AES_CBC_ENCRYPT_DATA       0x00001105
 3769 +
 3770 +#define CKM_DSA_PARAMETER_GEN          0x00002000
 3771 +#define CKM_DH_PKCS_PARAMETER_GEN      0x00002001
 3772 +#define CKM_X9_42_DH_PARAMETER_GEN     0x00002002
 3773 +
 3774 +#define CKM_VENDOR_DEFINED             0x80000000
 3775 +
 3776 +typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR;
 3777 +
 3778 +
 3779 +/* CK_MECHANISM is a structure that specifies a particular
 3780 + * mechanism  */
 3781 +typedef struct CK_MECHANISM {
 3782 +  CK_MECHANISM_TYPE mechanism;
 3783 +  CK_VOID_PTR       pParameter;
 3784 +
 3785 +  /* ulParameterLen was changed from CK_USHORT to CK_ULONG for
 3786 +   * v2.0 */
 3787 +  CK_ULONG          ulParameterLen;  /* in bytes */
 3788 +} CK_MECHANISM;
 3789 +
 3790 +typedef CK_MECHANISM CK_PTR CK_MECHANISM_PTR;
 3791 +
 3792 +
 3793 +/* CK_MECHANISM_INFO provides information about a particular
 3794 + * mechanism */
 3795 +typedef struct CK_MECHANISM_INFO {
 3796 +    CK_ULONG    ulMinKeySize;
 3797 +    CK_ULONG    ulMaxKeySize;
 3798 +    CK_FLAGS    flags;
 3799 +} CK_MECHANISM_INFO;
 3800 +
 3801 +/* The flags are defined as follows:
 3802 + *      Bit Flag               Mask        Meaning */
 3803 +#define CKF_HW                 0x00000001  /* performed by HW */
 3804 +
 3805 +/* The flags CKF_ENCRYPT, CKF_DECRYPT, CKF_DIGEST, CKF_SIGN,
 3806 + * CKG_SIGN_RECOVER, CKF_VERIFY, CKF_VERIFY_RECOVER,
 3807 + * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP,
 3808 + * and CKF_DERIVE are new for v2.0.  They specify whether or not
 3809 + * a mechanism can be used for a particular task */
 3810 +#define CKF_ENCRYPT            0x00000100
 3811 +#define CKF_DECRYPT            0x00000200
 3812 +#define CKF_DIGEST             0x00000400
 3813 +#define CKF_SIGN               0x00000800
 3814 +#define CKF_SIGN_RECOVER       0x00001000
 3815 +#define CKF_VERIFY             0x00002000
 3816 +#define CKF_VERIFY_RECOVER     0x00004000
 3817 +#define CKF_GENERATE           0x00008000
 3818 +#define CKF_GENERATE_KEY_PAIR  0x00010000
 3819 +#define CKF_WRAP               0x00020000
 3820 +#define CKF_UNWRAP             0x00040000
 3821 +#define CKF_DERIVE             0x00080000
 3822 +
 3823 +/* CKF_EC_F_P, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE,
 3824 + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11. They
 3825 + * describe a token's EC capabilities not available in mechanism
 3826 + * information. */
 3827 +#define CKF_EC_F_P             0x00100000
 3828 +#define CKF_EC_F_2M            0x00200000
 3829 +#define CKF_EC_ECPARAMETERS    0x00400000
 3830 +#define CKF_EC_NAMEDCURVE      0x00800000
 3831 +#define CKF_EC_UNCOMPRESS      0x01000000
 3832 +#define CKF_EC_COMPRESS        0x02000000
 3833 +
 3834 +#define CKF_EXTENSION          0x80000000 /* FALSE for this version */
 3835 +
 3836 +typedef CK_MECHANISM_INFO CK_PTR CK_MECHANISM_INFO_PTR;
 3837 +
 3838 +
 3839 +/* CK_RV is a value that identifies the return value of a
 3840 + * Cryptoki function */
 3841 +/* CK_RV was changed from CK_USHORT to CK_ULONG for v2.0 */
 3842 +typedef CK_ULONG          CK_RV;
 3843 +
 3844 +#define CKR_OK                                0x00000000
 3845 +#define CKR_CANCEL                            0x00000001
 3846 +#define CKR_HOST_MEMORY                       0x00000002
 3847 +#define CKR_SLOT_ID_INVALID                   0x00000003
 3848 +
 3849 +/* CKR_FLAGS_INVALID was removed for v2.0 */
 3850 +
 3851 +/* CKR_GENERAL_ERROR and CKR_FUNCTION_FAILED are new for v2.0 */
 3852 +#define CKR_GENERAL_ERROR                     0x00000005
 3853 +#define CKR_FUNCTION_FAILED                   0x00000006
 3854 +
 3855 +/* CKR_ARGUMENTS_BAD, CKR_NO_EVENT, CKR_NEED_TO_CREATE_THREADS,
 3856 + * and CKR_CANT_LOCK are new for v2.01 */
 3857 +#define CKR_ARGUMENTS_BAD                     0x00000007
 3858 +#define CKR_NO_EVENT                          0x00000008
 3859 +#define CKR_NEED_TO_CREATE_THREADS            0x00000009
 3860 +#define CKR_CANT_LOCK                         0x0000000A
 3861 +
 3862 +#define CKR_ATTRIBUTE_READ_ONLY               0x00000010
 3863 +#define CKR_ATTRIBUTE_SENSITIVE               0x00000011
 3864 +#define CKR_ATTRIBUTE_TYPE_INVALID            0x00000012
 3865 +#define CKR_ATTRIBUTE_VALUE_INVALID           0x00000013
 3866 +#define CKR_DATA_INVALID                      0x00000020
 3867 +#define CKR_DATA_LEN_RANGE                    0x00000021
 3868 +#define CKR_DEVICE_ERROR                      0x00000030
 3869 +#define CKR_DEVICE_MEMORY                     0x00000031
 3870 +#define CKR_DEVICE_REMOVED                    0x00000032
 3871 +#define CKR_ENCRYPTED_DATA_INVALID            0x00000040
 3872 +#define CKR_ENCRYPTED_DATA_LEN_RANGE          0x00000041
 3873 +#define CKR_FUNCTION_CANCELED                 0x00000050
 3874 +#define CKR_FUNCTION_NOT_PARALLEL             0x00000051
 3875 +
 3876 +/* CKR_FUNCTION_NOT_SUPPORTED is new for v2.0 */
 3877 +#define CKR_FUNCTION_NOT_SUPPORTED            0x00000054
 3878 +
 3879 +#define CKR_KEY_HANDLE_INVALID                0x00000060
 3880 +
 3881 +/* CKR_KEY_SENSITIVE was removed for v2.0 */
 3882 +
 3883 +#define CKR_KEY_SIZE_RANGE                    0x00000062
 3884 +#define CKR_KEY_TYPE_INCONSISTENT             0x00000063
 3885 +
 3886 +/* CKR_KEY_NOT_NEEDED, CKR_KEY_CHANGED, CKR_KEY_NEEDED,
 3887 + * CKR_KEY_INDIGESTIBLE, CKR_KEY_FUNCTION_NOT_PERMITTED,
 3888 + * CKR_KEY_NOT_WRAPPABLE, and CKR_KEY_UNEXTRACTABLE are new for
 3889 + * v2.0 */
 3890 +#define CKR_KEY_NOT_NEEDED                    0x00000064
 3891 +#define CKR_KEY_CHANGED                       0x00000065
 3892 +#define CKR_KEY_NEEDED                        0x00000066
 3893 +#define CKR_KEY_INDIGESTIBLE                  0x00000067
 3894 +#define CKR_KEY_FUNCTION_NOT_PERMITTED        0x00000068
 3895 +#define CKR_KEY_NOT_WRAPPABLE                 0x00000069
 3896 +#define CKR_KEY_UNEXTRACTABLE                 0x0000006A
 3897 +
 3898 +#define CKR_MECHANISM_INVALID                 0x00000070
 3899 +#define CKR_MECHANISM_PARAM_INVALID           0x00000071
 3900 +
 3901 +/* CKR_OBJECT_CLASS_INCONSISTENT and CKR_OBJECT_CLASS_INVALID
 3902 + * were removed for v2.0 */
 3903 +#define CKR_OBJECT_HANDLE_INVALID             0x00000082
 3904 +#define CKR_OPERATION_ACTIVE                  0x00000090
 3905 +#define CKR_OPERATION_NOT_INITIALIZED         0x00000091
 3906 +#define CKR_PIN_INCORRECT                     0x000000A0
 3907 +#define CKR_PIN_INVALID                       0x000000A1
 3908 +#define CKR_PIN_LEN_RANGE                     0x000000A2
 3909 +
 3910 +/* CKR_PIN_EXPIRED and CKR_PIN_LOCKED are new for v2.0 */
 3911 +#define CKR_PIN_EXPIRED                       0x000000A3
 3912 +#define CKR_PIN_LOCKED                        0x000000A4
 3913 +
 3914 +#define CKR_SESSION_CLOSED                    0x000000B0
 3915 +#define CKR_SESSION_COUNT                     0x000000B1
 3916 +#define CKR_SESSION_HANDLE_INVALID            0x000000B3
 3917 +#define CKR_SESSION_PARALLEL_NOT_SUPPORTED    0x000000B4
 3918 +#define CKR_SESSION_READ_ONLY                 0x000000B5
 3919 +#define CKR_SESSION_EXISTS                    0x000000B6
 3920 +
 3921 +/* CKR_SESSION_READ_ONLY_EXISTS and
 3922 + * CKR_SESSION_READ_WRITE_SO_EXISTS are new for v2.0 */
 3923 +#define CKR_SESSION_READ_ONLY_EXISTS          0x000000B7
 3924 +#define CKR_SESSION_READ_WRITE_SO_EXISTS      0x000000B8
 3925 +
 3926 +#define CKR_SIGNATURE_INVALID                 0x000000C0
 3927 +#define CKR_SIGNATURE_LEN_RANGE               0x000000C1
 3928 +#define CKR_TEMPLATE_INCOMPLETE               0x000000D0
 3929 +#define CKR_TEMPLATE_INCONSISTENT             0x000000D1
 3930 +#define CKR_TOKEN_NOT_PRESENT                 0x000000E0
 3931 +#define CKR_TOKEN_NOT_RECOGNIZED              0x000000E1
 3932 +#define CKR_TOKEN_WRITE_PROTECTED             0x000000E2
 3933 +#define CKR_UNWRAPPING_KEY_HANDLE_INVALID     0x000000F0
 3934 +#define CKR_UNWRAPPING_KEY_SIZE_RANGE         0x000000F1
 3935 +#define CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT  0x000000F2
 3936 +#define CKR_USER_ALREADY_LOGGED_IN            0x00000100
 3937 +#define CKR_USER_NOT_LOGGED_IN                0x00000101
 3938 +#define CKR_USER_PIN_NOT_INITIALIZED          0x00000102
 3939 +#define CKR_USER_TYPE_INVALID                 0x00000103
 3940 +
 3941 +/* CKR_USER_ANOTHER_ALREADY_LOGGED_IN and CKR_USER_TOO_MANY_TYPES
 3942 + * are new to v2.01 */
 3943 +#define CKR_USER_ANOTHER_ALREADY_LOGGED_IN    0x00000104
 3944 +#define CKR_USER_TOO_MANY_TYPES               0x00000105
 3945 +
 3946 +#define CKR_WRAPPED_KEY_INVALID               0x00000110
 3947 +#define CKR_WRAPPED_KEY_LEN_RANGE             0x00000112
 3948 +#define CKR_WRAPPING_KEY_HANDLE_INVALID       0x00000113
 3949 +#define CKR_WRAPPING_KEY_SIZE_RANGE           0x00000114
 3950 +#define CKR_WRAPPING_KEY_TYPE_INCONSISTENT    0x00000115
 3951 +#define CKR_RANDOM_SEED_NOT_SUPPORTED         0x00000120
 3952 +
 3953 +/* These are new to v2.0 */
 3954 +#define CKR_RANDOM_NO_RNG                     0x00000121
 3955 +
 3956 +/* These are new to v2.11 */
 3957 +#define CKR_DOMAIN_PARAMS_INVALID             0x00000130
 3958 +
 3959 +/* These are new to v2.0 */
 3960 +#define CKR_BUFFER_TOO_SMALL                  0x00000150
 3961 +#define CKR_SAVED_STATE_INVALID               0x00000160
 3962 +#define CKR_INFORMATION_SENSITIVE             0x00000170
 3963 +#define CKR_STATE_UNSAVEABLE                  0x00000180
 3964 +
 3965 +/* These are new to v2.01 */
 3966 +#define CKR_CRYPTOKI_NOT_INITIALIZED          0x00000190
 3967 +#define CKR_CRYPTOKI_ALREADY_INITIALIZED      0x00000191
 3968 +#define CKR_MUTEX_BAD                         0x000001A0
 3969 +#define CKR_MUTEX_NOT_LOCKED                  0x000001A1
 3970 +
 3971 +/* This is new to v2.20 */
 3972 +#define CKR_FUNCTION_REJECTED                 0x00000200
 3973 +
 3974 +#define CKR_VENDOR_DEFINED                    0x80000000
 3975 +
 3976 +
 3977 +/* CK_NOTIFY is an application callback that processes events */
 3978 +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_NOTIFY)(
 3979 +  CK_SESSION_HANDLE hSession,     /* the session's handle */
 3980 +  CK_NOTIFICATION   event,
 3981 +  CK_VOID_PTR       pApplication  /* passed to C_OpenSession */
 3982 +);
 3983 +
 3984 +
 3985 +/* CK_FUNCTION_LIST is a structure holding a Cryptoki spec
 3986 + * version and pointers of appropriate types to all the
 3987 + * Cryptoki functions */
 3988 +/* CK_FUNCTION_LIST is new for v2.0 */
 3989 +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST;
 3990 +
 3991 +typedef CK_FUNCTION_LIST CK_PTR CK_FUNCTION_LIST_PTR;
 3992 +
 3993 +typedef CK_FUNCTION_LIST_PTR CK_PTR CK_FUNCTION_LIST_PTR_PTR;
 3994 +
 3995 +
 3996 +/* CK_CREATEMUTEX is an application callback for creating a
 3997 + * mutex object */
 3998 +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_CREATEMUTEX)(
 3999 +  CK_VOID_PTR_PTR ppMutex  /* location to receive ptr to mutex */
 4000 +);
 4001 +
 4002 +
 4003 +/* CK_DESTROYMUTEX is an application callback for destroying a
 4004 + * mutex object */
 4005 +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_DESTROYMUTEX)(
 4006 +  CK_VOID_PTR pMutex  /* pointer to mutex */
 4007 +);
 4008 +
 4009 +
 4010 +/* CK_LOCKMUTEX is an application callback for locking a mutex */
 4011 +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_LOCKMUTEX)(
 4012 +  CK_VOID_PTR pMutex  /* pointer to mutex */
 4013 +);
 4014 +
 4015 +
 4016 +/* CK_UNLOCKMUTEX is an application callback for unlocking a
 4017 + * mutex */
 4018 +typedef CK_CALLBACK_FUNCTION(CK_RV, CK_UNLOCKMUTEX)(
 4019 +  CK_VOID_PTR pMutex  /* pointer to mutex */
 4020 +);
 4021 +
 4022 +
 4023 +/* CK_C_INITIALIZE_ARGS provides the optional arguments to
 4024 + * C_Initialize */
 4025 +typedef struct CK_C_INITIALIZE_ARGS {
 4026 +  CK_CREATEMUTEX CreateMutex;
 4027 +  CK_DESTROYMUTEX DestroyMutex;
 4028 +  CK_LOCKMUTEX LockMutex;
 4029 +  CK_UNLOCKMUTEX UnlockMutex;
 4030 +  CK_FLAGS flags;
 4031 +  CK_VOID_PTR pReserved;
 4032 +} CK_C_INITIALIZE_ARGS;
 4033 +
 4034 +/* flags: bit flags that provide capabilities of the slot
 4035 + *      Bit Flag                           Mask       Meaning
 4036 + */
 4037 +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001
 4038 +#define CKF_OS_LOCKING_OK                  0x00000002
 4039 +
 4040 +typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR;
 4041 +
 4042 +
 4043 +/* additional flags for parameters to functions */
 4044 +
 4045 +/* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */
 4046 +#define CKF_DONT_BLOCK     1
 4047 +
 4048 +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10.
 4049 + * CK_RSA_PKCS_OAEP_MGF_TYPE  is used to indicate the Message
 4050 + * Generation Function (MGF) applied to a message block when
 4051 + * formatting a message block for the PKCS #1 OAEP encryption
 4052 + * scheme. */
 4053 +typedef CK_ULONG CK_RSA_PKCS_MGF_TYPE;
 4054 +
 4055 +typedef CK_RSA_PKCS_MGF_TYPE CK_PTR CK_RSA_PKCS_MGF_TYPE_PTR;
 4056 +
 4057 +/* The following MGFs are defined */
 4058 +/* CKG_MGF1_SHA256, CKG_MGF1_SHA384, and CKG_MGF1_SHA512
 4059 + * are new for v2.20 */
 4060 +#define CKG_MGF1_SHA1         0x00000001
 4061 +#define CKG_MGF1_SHA256       0x00000002
 4062 +#define CKG_MGF1_SHA384       0x00000003
 4063 +#define CKG_MGF1_SHA512       0x00000004
 4064 +
 4065 +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10.
 4066 + * CK_RSA_PKCS_OAEP_SOURCE_TYPE  is used to indicate the source
 4067 + * of the encoding parameter when formatting a message block
 4068 + * for the PKCS #1 OAEP encryption scheme. */
 4069 +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE;
 4070 +
 4071 +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR;
 4072 +
 4073 +/* The following encoding parameter sources are defined */
 4074 +#define CKZ_DATA_SPECIFIED    0x00000001
 4075 +
 4076 +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10.
 4077 + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the
 4078 + * CKM_RSA_PKCS_OAEP mechanism. */
 4079 +typedef struct CK_RSA_PKCS_OAEP_PARAMS {
 4080 +        CK_MECHANISM_TYPE hashAlg;
 4081 +        CK_RSA_PKCS_MGF_TYPE mgf;
 4082 +        CK_RSA_PKCS_OAEP_SOURCE_TYPE source;
 4083 +        CK_VOID_PTR pSourceData;
 4084 +        CK_ULONG ulSourceDataLen;
 4085 +} CK_RSA_PKCS_OAEP_PARAMS;
 4086 +
 4087 +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR;
 4088 +
 4089 +/* CK_RSA_PKCS_PSS_PARAMS is new for v2.11.
 4090 + * CK_RSA_PKCS_PSS_PARAMS provides the parameters to the
 4091 + * CKM_RSA_PKCS_PSS mechanism(s). */
 4092 +typedef struct CK_RSA_PKCS_PSS_PARAMS {
 4093 +        CK_MECHANISM_TYPE    hashAlg;
 4094 +        CK_RSA_PKCS_MGF_TYPE mgf;
 4095 +        CK_ULONG             sLen;
 4096 +} CK_RSA_PKCS_PSS_PARAMS;
 4097 +
 4098 +typedef CK_RSA_PKCS_PSS_PARAMS CK_PTR CK_RSA_PKCS_PSS_PARAMS_PTR;
 4099 +
 4100 +/* CK_EC_KDF_TYPE is new for v2.11. */
 4101 +typedef CK_ULONG CK_EC_KDF_TYPE;
 4102 +
 4103 +/* The following EC Key Derivation Functions are defined */
 4104 +#define CKD_NULL                 0x00000001
 4105 +#define CKD_SHA1_KDF             0x00000002
 4106 +
 4107 +/* CK_ECDH1_DERIVE_PARAMS is new for v2.11.
 4108 + * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
 4109 + * CKM_ECDH1_DERIVE and CKM_ECDH1_COFACTOR_DERIVE mechanisms,
 4110 + * where each party contributes one key pair.
 4111 + */
 4112 +typedef struct CK_ECDH1_DERIVE_PARAMS {
 4113 +  CK_EC_KDF_TYPE kdf;
 4114 +  CK_ULONG ulSharedDataLen;
 4115 +  CK_BYTE_PTR pSharedData;
 4116 +  CK_ULONG ulPublicDataLen;
 4117 +  CK_BYTE_PTR pPublicData;
 4118 +} CK_ECDH1_DERIVE_PARAMS;
 4119 +
 4120 +typedef CK_ECDH1_DERIVE_PARAMS CK_PTR CK_ECDH1_DERIVE_PARAMS_PTR;
 4121 +
 4122 +
 4123 +/* CK_ECDH2_DERIVE_PARAMS is new for v2.11.
 4124 + * CK_ECDH2_DERIVE_PARAMS provides the parameters to the
 4125 + * CKM_ECMQV_DERIVE mechanism, where each party contributes two key pairs. */
 4126 +typedef struct CK_ECDH2_DERIVE_PARAMS {
 4127 +  CK_EC_KDF_TYPE kdf;
 4128 +  CK_ULONG ulSharedDataLen;
 4129 +  CK_BYTE_PTR pSharedData;
 4130 +  CK_ULONG ulPublicDataLen;
 4131 +  CK_BYTE_PTR pPublicData;
 4132 +  CK_ULONG ulPrivateDataLen;
 4133 +  CK_OBJECT_HANDLE hPrivateData;
 4134 +  CK_ULONG ulPublicDataLen2;
 4135 +  CK_BYTE_PTR pPublicData2;
 4136 +} CK_ECDH2_DERIVE_PARAMS;
 4137 +
 4138 +typedef CK_ECDH2_DERIVE_PARAMS CK_PTR CK_ECDH2_DERIVE_PARAMS_PTR;
 4139 +
 4140 +typedef struct CK_ECMQV_DERIVE_PARAMS {
 4141 +  CK_EC_KDF_TYPE kdf;
 4142 +  CK_ULONG ulSharedDataLen;
 4143 +  CK_BYTE_PTR pSharedData;
 4144 +  CK_ULONG ulPublicDataLen;
 4145 +  CK_BYTE_PTR pPublicData;
 4146 +  CK_ULONG ulPrivateDataLen;
 4147 +  CK_OBJECT_HANDLE hPrivateData;
 4148 +  CK_ULONG ulPublicDataLen2;
 4149 +  CK_BYTE_PTR pPublicData2;
 4150 +  CK_OBJECT_HANDLE publicKey;
 4151 +} CK_ECMQV_DERIVE_PARAMS;
 4152 +
 4153 +typedef CK_ECMQV_DERIVE_PARAMS CK_PTR CK_ECMQV_DERIVE_PARAMS_PTR;
 4154 +
 4155 +/* Typedefs and defines for the CKM_X9_42_DH_KEY_PAIR_GEN and the
 4156 + * CKM_X9_42_DH_PARAMETER_GEN mechanisms (new for PKCS #11 v2.11) */
 4157 +typedef CK_ULONG CK_X9_42_DH_KDF_TYPE;
 4158 +typedef CK_X9_42_DH_KDF_TYPE CK_PTR CK_X9_42_DH_KDF_TYPE_PTR;
 4159 +
 4160 +/* The following X9.42 DH key derivation functions are defined
 4161 +   (besides CKD_NULL already defined : */
 4162 +#define CKD_SHA1_KDF_ASN1        0x00000003
 4163 +#define CKD_SHA1_KDF_CONCATENATE 0x00000004
 4164 +
 4165 +/* CK_X9_42_DH1_DERIVE_PARAMS is new for v2.11.
 4166 + * CK_X9_42_DH1_DERIVE_PARAMS provides the parameters to the
 4167 + * CKM_X9_42_DH_DERIVE key derivation mechanism, where each party
 4168 + * contributes one key pair */
 4169 +typedef struct CK_X9_42_DH1_DERIVE_PARAMS {
 4170 +  CK_X9_42_DH_KDF_TYPE kdf;
 4171 +  CK_ULONG ulOtherInfoLen;
 4172 +  CK_BYTE_PTR pOtherInfo;
 4173 +  CK_ULONG ulPublicDataLen;
 4174 +  CK_BYTE_PTR pPublicData;
 4175 +} CK_X9_42_DH1_DERIVE_PARAMS;
 4176 +
 4177 +typedef struct CK_X9_42_DH1_DERIVE_PARAMS CK_PTR CK_X9_42_DH1_DERIVE_PARAMS_PTR;
 4178 +
 4179 +/* CK_X9_42_DH2_DERIVE_PARAMS is new for v2.11.
 4180 + * CK_X9_42_DH2_DERIVE_PARAMS provides the parameters to the
 4181 + * CKM_X9_42_DH_HYBRID_DERIVE and CKM_X9_42_MQV_DERIVE key derivation
 4182 + * mechanisms, where each party contributes two key pairs */
 4183 +typedef struct CK_X9_42_DH2_DERIVE_PARAMS {
 4184 +  CK_X9_42_DH_KDF_TYPE kdf;
 4185 +  CK_ULONG ulOtherInfoLen;
 4186 +  CK_BYTE_PTR pOtherInfo;
 4187 +  CK_ULONG ulPublicDataLen;
 4188 +  CK_BYTE_PTR pPublicData;
 4189 +  CK_ULONG ulPrivateDataLen;
 4190 +  CK_OBJECT_HANDLE hPrivateData;
 4191 +  CK_ULONG ulPublicDataLen2;
 4192 +  CK_BYTE_PTR pPublicData2;
 4193 +} CK_X9_42_DH2_DERIVE_PARAMS;
 4194 +
 4195 +typedef CK_X9_42_DH2_DERIVE_PARAMS CK_PTR CK_X9_42_DH2_DERIVE_PARAMS_PTR;
 4196 +
 4197 +typedef struct CK_X9_42_MQV_DERIVE_PARAMS {
 4198 +  CK_X9_42_DH_KDF_TYPE kdf;
 4199 +  CK_ULONG ulOtherInfoLen;
 4200 +  CK_BYTE_PTR pOtherInfo;
 4201 +  CK_ULONG ulPublicDataLen;
 4202 +  CK_BYTE_PTR pPublicData;
 4203 +  CK_ULONG ulPrivateDataLen;
 4204 +  CK_OBJECT_HANDLE hPrivateData;
 4205 +  CK_ULONG ulPublicDataLen2;
 4206 +  CK_BYTE_PTR pPublicData2;
 4207 +  CK_OBJECT_HANDLE publicKey;
 4208 +} CK_X9_42_MQV_DERIVE_PARAMS;
 4209 +
 4210 +typedef CK_X9_42_MQV_DERIVE_PARAMS CK_PTR CK_X9_42_MQV_DERIVE_PARAMS_PTR;
 4211 +
 4212 +/* CK_KEA_DERIVE_PARAMS provides the parameters to the
 4213 + * CKM_KEA_DERIVE mechanism */
 4214 +/* CK_KEA_DERIVE_PARAMS is new for v2.0 */
 4215 +typedef struct CK_KEA_DERIVE_PARAMS {
 4216 +  CK_BBOOL      isSender;
 4217 +  CK_ULONG      ulRandomLen;
 4218 +  CK_BYTE_PTR   pRandomA;
 4219 +  CK_BYTE_PTR   pRandomB;
 4220 +  CK_ULONG      ulPublicDataLen;
 4221 +  CK_BYTE_PTR   pPublicData;
 4222 +} CK_KEA_DERIVE_PARAMS;
 4223 +
 4224 +typedef CK_KEA_DERIVE_PARAMS CK_PTR CK_KEA_DERIVE_PARAMS_PTR;
 4225 +
 4226 +
 4227 +/* CK_RC2_PARAMS provides the parameters to the CKM_RC2_ECB and
 4228 + * CKM_RC2_MAC mechanisms.  An instance of CK_RC2_PARAMS just
 4229 + * holds the effective keysize */
 4230 +typedef CK_ULONG          CK_RC2_PARAMS;
 4231 +
 4232 +typedef CK_RC2_PARAMS CK_PTR CK_RC2_PARAMS_PTR;
 4233 +
 4234 +
 4235 +/* CK_RC2_CBC_PARAMS provides the parameters to the CKM_RC2_CBC
 4236 + * mechanism */
 4237 +typedef struct CK_RC2_CBC_PARAMS {
 4238 +  /* ulEffectiveBits was changed from CK_USHORT to CK_ULONG for
 4239 +   * v2.0 */
 4240 +  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */
 4241 +
 4242 +  CK_BYTE       iv[8];            /* IV for CBC mode */
 4243 +} CK_RC2_CBC_PARAMS;
 4244 +
 4245 +typedef CK_RC2_CBC_PARAMS CK_PTR CK_RC2_CBC_PARAMS_PTR;
 4246 +
 4247 +
 4248 +/* CK_RC2_MAC_GENERAL_PARAMS provides the parameters for the
 4249 + * CKM_RC2_MAC_GENERAL mechanism */
 4250 +/* CK_RC2_MAC_GENERAL_PARAMS is new for v2.0 */
 4251 +typedef struct CK_RC2_MAC_GENERAL_PARAMS {
 4252 +  CK_ULONG      ulEffectiveBits;  /* effective bits (1-1024) */
 4253 +  CK_ULONG      ulMacLength;      /* Length of MAC in bytes */
 4254 +} CK_RC2_MAC_GENERAL_PARAMS;
 4255 +
 4256 +typedef CK_RC2_MAC_GENERAL_PARAMS CK_PTR \
 4257 +  CK_RC2_MAC_GENERAL_PARAMS_PTR;
 4258 +
 4259 +
 4260 +/* CK_RC5_PARAMS provides the parameters to the CKM_RC5_ECB and
 4261 + * CKM_RC5_MAC mechanisms */
 4262 +/* CK_RC5_PARAMS is new for v2.0 */
 4263 +typedef struct CK_RC5_PARAMS {
 4264 +  CK_ULONG      ulWordsize;  /* wordsize in bits */
 4265 +  CK_ULONG      ulRounds;    /* number of rounds */
 4266 +} CK_RC5_PARAMS;
 4267 +
 4268 +typedef CK_RC5_PARAMS CK_PTR CK_RC5_PARAMS_PTR;
 4269 +
 4270 +
 4271 +/* CK_RC5_CBC_PARAMS provides the parameters to the CKM_RC5_CBC
 4272 + * mechanism */
 4273 +/* CK_RC5_CBC_PARAMS is new for v2.0 */
 4274 +typedef struct CK_RC5_CBC_PARAMS {
 4275 +  CK_ULONG      ulWordsize;  /* wordsize in bits */
 4276 +  CK_ULONG      ulRounds;    /* number of rounds */
 4277 +  CK_BYTE_PTR   pIv;         /* pointer to IV */
 4278 +  CK_ULONG      ulIvLen;     /* length of IV in bytes */
 4279 +} CK_RC5_CBC_PARAMS;
 4280 +
 4281 +typedef CK_RC5_CBC_PARAMS CK_PTR CK_RC5_CBC_PARAMS_PTR;
 4282 +
 4283 +
 4284 +/* CK_RC5_MAC_GENERAL_PARAMS provides the parameters for the
 4285 + * CKM_RC5_MAC_GENERAL mechanism */
 4286 +/* CK_RC5_MAC_GENERAL_PARAMS is new for v2.0 */
 4287 +typedef struct CK_RC5_MAC_GENERAL_PARAMS {
 4288 +  CK_ULONG      ulWordsize;   /* wordsize in bits */
 4289 +  CK_ULONG      ulRounds;     /* number of rounds */
 4290 +  CK_ULONG      ulMacLength;  /* Length of MAC in bytes */
 4291 +} CK_RC5_MAC_GENERAL_PARAMS;
 4292 +
 4293 +typedef CK_RC5_MAC_GENERAL_PARAMS CK_PTR \
 4294 +  CK_RC5_MAC_GENERAL_PARAMS_PTR;
 4295 +
 4296 +
 4297 +/* CK_MAC_GENERAL_PARAMS provides the parameters to most block
 4298 + * ciphers' MAC_GENERAL mechanisms.  Its value is the length of
 4299 + * the MAC */
 4300 +/* CK_MAC_GENERAL_PARAMS is new for v2.0 */
 4301 +typedef CK_ULONG          CK_MAC_GENERAL_PARAMS;
 4302 +
 4303 +typedef CK_MAC_GENERAL_PARAMS CK_PTR CK_MAC_GENERAL_PARAMS_PTR;
 4304 +
 4305 +/* CK_DES/AES_ECB/CBC_ENCRYPT_DATA_PARAMS are new for v2.20 */
 4306 +typedef struct CK_DES_CBC_ENCRYPT_DATA_PARAMS {
 4307 +  CK_BYTE      iv[8];
 4308 +  CK_BYTE_PTR  pData;
 4309 +  CK_ULONG     length;
 4310 +} CK_DES_CBC_ENCRYPT_DATA_PARAMS;
 4311 +
 4312 +typedef CK_DES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR;
 4313 +
 4314 +typedef struct CK_AES_CBC_ENCRYPT_DATA_PARAMS {
 4315 +  CK_BYTE      iv[16];
 4316 +  CK_BYTE_PTR  pData;
 4317 +  CK_ULONG     length;
 4318 +} CK_AES_CBC_ENCRYPT_DATA_PARAMS;
 4319 +
 4320 +typedef CK_AES_CBC_ENCRYPT_DATA_PARAMS CK_PTR CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR;
 4321 +
 4322 +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS provides the parameters to the
 4323 + * CKM_SKIPJACK_PRIVATE_WRAP mechanism */
 4324 +/* CK_SKIPJACK_PRIVATE_WRAP_PARAMS is new for v2.0 */
 4325 +typedef struct CK_SKIPJACK_PRIVATE_WRAP_PARAMS {
 4326 +  CK_ULONG      ulPasswordLen;
 4327 +  CK_BYTE_PTR   pPassword;
 4328 +  CK_ULONG      ulPublicDataLen;
 4329 +  CK_BYTE_PTR   pPublicData;
 4330 +  CK_ULONG      ulPAndGLen;
 4331 +  CK_ULONG      ulQLen;
 4332 +  CK_ULONG      ulRandomLen;
 4333 +  CK_BYTE_PTR   pRandomA;
 4334 +  CK_BYTE_PTR   pPrimeP;
 4335 +  CK_BYTE_PTR   pBaseG;
 4336 +  CK_BYTE_PTR   pSubprimeQ;
 4337 +} CK_SKIPJACK_PRIVATE_WRAP_PARAMS;
 4338 +
 4339 +typedef CK_SKIPJACK_PRIVATE_WRAP_PARAMS CK_PTR \
 4340 +  CK_SKIPJACK_PRIVATE_WRAP_PTR;
 4341 +
 4342 +
 4343 +/* CK_SKIPJACK_RELAYX_PARAMS provides the parameters to the
 4344 + * CKM_SKIPJACK_RELAYX mechanism */
 4345 +/* CK_SKIPJACK_RELAYX_PARAMS is new for v2.0 */
 4346 +typedef struct CK_SKIPJACK_RELAYX_PARAMS {
 4347 +  CK_ULONG      ulOldWrappedXLen;
 4348 +  CK_BYTE_PTR   pOldWrappedX;
 4349 +  CK_ULONG      ulOldPasswordLen;
 4350 +  CK_BYTE_PTR   pOldPassword;
 4351 +  CK_ULONG      ulOldPublicDataLen;
 4352 +  CK_BYTE_PTR   pOldPublicData;
 4353 +  CK_ULONG      ulOldRandomLen;
 4354 +  CK_BYTE_PTR   pOldRandomA;
 4355 +  CK_ULONG      ulNewPasswordLen;
 4356 +  CK_BYTE_PTR   pNewPassword;
 4357 +  CK_ULONG      ulNewPublicDataLen;
 4358 +  CK_BYTE_PTR   pNewPublicData;
 4359 +  CK_ULONG      ulNewRandomLen;
 4360 +  CK_BYTE_PTR   pNewRandomA;
 4361 +} CK_SKIPJACK_RELAYX_PARAMS;
 4362 +
 4363 +typedef CK_SKIPJACK_RELAYX_PARAMS CK_PTR \
 4364 +  CK_SKIPJACK_RELAYX_PARAMS_PTR;
 4365 +
 4366 +
 4367 +typedef struct CK_PBE_PARAMS {
 4368 +  CK_BYTE_PTR      pInitVector;
 4369 +  CK_UTF8CHAR_PTR  pPassword;
 4370 +  CK_ULONG         ulPasswordLen;
 4371 +  CK_BYTE_PTR      pSalt;
 4372 +  CK_ULONG         ulSaltLen;
 4373 +  CK_ULONG         ulIteration;
 4374 +} CK_PBE_PARAMS;
 4375 +
 4376 +typedef CK_PBE_PARAMS CK_PTR CK_PBE_PARAMS_PTR;
 4377 +
 4378 +
 4379 +/* CK_KEY_WRAP_SET_OAEP_PARAMS provides the parameters to the
 4380 + * CKM_KEY_WRAP_SET_OAEP mechanism */
 4381 +/* CK_KEY_WRAP_SET_OAEP_PARAMS is new for v2.0 */
 4382 +typedef struct CK_KEY_WRAP_SET_OAEP_PARAMS {
 4383 +  CK_BYTE       bBC;     /* block contents byte */
 4384 +  CK_BYTE_PTR   pX;      /* extra data */
 4385 +  CK_ULONG      ulXLen;  /* length of extra data in bytes */
 4386 +} CK_KEY_WRAP_SET_OAEP_PARAMS;
 4387 +
 4388 +typedef CK_KEY_WRAP_SET_OAEP_PARAMS CK_PTR \
 4389 +  CK_KEY_WRAP_SET_OAEP_PARAMS_PTR;
 4390 +
 4391 +
 4392 +typedef struct CK_SSL3_RANDOM_DATA {
 4393 +  CK_BYTE_PTR  pClientRandom;
 4394 +  CK_ULONG     ulClientRandomLen;
 4395 +  CK_BYTE_PTR  pServerRandom;
 4396 +  CK_ULONG     ulServerRandomLen;
 4397 +} CK_SSL3_RANDOM_DATA;
 4398 +
 4399 +
 4400 +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS {
 4401 +  CK_SSL3_RANDOM_DATA RandomInfo;
 4402 +  CK_VERSION_PTR pVersion;
 4403 +} CK_SSL3_MASTER_KEY_DERIVE_PARAMS;
 4404 +
 4405 +typedef struct CK_SSL3_MASTER_KEY_DERIVE_PARAMS CK_PTR \
 4406 +  CK_SSL3_MASTER_KEY_DERIVE_PARAMS_PTR;
 4407 +
 4408 +
 4409 +typedef struct CK_SSL3_KEY_MAT_OUT {
 4410 +  CK_OBJECT_HANDLE hClientMacSecret;
 4411 +  CK_OBJECT_HANDLE hServerMacSecret;
 4412 +  CK_OBJECT_HANDLE hClientKey;
 4413 +  CK_OBJECT_HANDLE hServerKey;
 4414 +  CK_BYTE_PTR      pIVClient;
 4415 +  CK_BYTE_PTR      pIVServer;
 4416 +} CK_SSL3_KEY_MAT_OUT;
 4417 +
 4418 +typedef CK_SSL3_KEY_MAT_OUT CK_PTR CK_SSL3_KEY_MAT_OUT_PTR;
 4419 +
 4420 +
 4421 +typedef struct CK_SSL3_KEY_MAT_PARAMS {
 4422 +  CK_ULONG                ulMacSizeInBits;
 4423 +  CK_ULONG                ulKeySizeInBits;
 4424 +  CK_ULONG                ulIVSizeInBits;
 4425 +  CK_BBOOL                bIsExport;
 4426 +  CK_SSL3_RANDOM_DATA     RandomInfo;
 4427 +  CK_SSL3_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
 4428 +} CK_SSL3_KEY_MAT_PARAMS;
 4429 +
 4430 +typedef CK_SSL3_KEY_MAT_PARAMS CK_PTR CK_SSL3_KEY_MAT_PARAMS_PTR;
 4431 +
 4432 +/* CK_TLS_PRF_PARAMS is new for version 2.20 */
 4433 +typedef struct CK_TLS_PRF_PARAMS {
 4434 +  CK_BYTE_PTR  pSeed;
 4435 +  CK_ULONG     ulSeedLen;
 4436 +  CK_BYTE_PTR  pLabel;
 4437 +  CK_ULONG     ulLabelLen;
 4438 +  CK_BYTE_PTR  pOutput;
 4439 +  CK_ULONG_PTR pulOutputLen;
 4440 +} CK_TLS_PRF_PARAMS;
 4441 +
 4442 +typedef CK_TLS_PRF_PARAMS CK_PTR CK_TLS_PRF_PARAMS_PTR;
 4443 +
 4444 +/* WTLS is new for version 2.20 */
 4445 +typedef struct CK_WTLS_RANDOM_DATA {
 4446 +  CK_BYTE_PTR pClientRandom;
 4447 +  CK_ULONG    ulClientRandomLen;
 4448 +  CK_BYTE_PTR pServerRandom;
 4449 +  CK_ULONG    ulServerRandomLen;
 4450 +} CK_WTLS_RANDOM_DATA;
 4451 +
 4452 +typedef CK_WTLS_RANDOM_DATA CK_PTR CK_WTLS_RANDOM_DATA_PTR;
 4453 +
 4454 +typedef struct CK_WTLS_MASTER_KEY_DERIVE_PARAMS {
 4455 +  CK_MECHANISM_TYPE   DigestMechanism;
 4456 +  CK_WTLS_RANDOM_DATA RandomInfo;
 4457 +  CK_BYTE_PTR         pVersion;
 4458 +} CK_WTLS_MASTER_KEY_DERIVE_PARAMS;
 4459 +
 4460 +typedef CK_WTLS_MASTER_KEY_DERIVE_PARAMS CK_PTR \
 4461 +  CK_WTLS_MASTER_KEY_DERIVE_PARAMS_PTR;
 4462 +
 4463 +typedef struct CK_WTLS_PRF_PARAMS {
 4464 +  CK_MECHANISM_TYPE DigestMechanism;
 4465 +  CK_BYTE_PTR       pSeed;
 4466 +  CK_ULONG          ulSeedLen;
 4467 +  CK_BYTE_PTR       pLabel;
 4468 +  CK_ULONG          ulLabelLen;
 4469 +  CK_BYTE_PTR       pOutput;
 4470 +  CK_ULONG_PTR      pulOutputLen;
 4471 +} CK_WTLS_PRF_PARAMS;
 4472 +
 4473 +typedef CK_WTLS_PRF_PARAMS CK_PTR CK_WTLS_PRF_PARAMS_PTR;
 4474 +
 4475 +typedef struct CK_WTLS_KEY_MAT_OUT {
 4476 +  CK_OBJECT_HANDLE hMacSecret;
 4477 +  CK_OBJECT_HANDLE hKey;
 4478 +  CK_BYTE_PTR      pIV;
 4479 +} CK_WTLS_KEY_MAT_OUT;
 4480 +
 4481 +typedef CK_WTLS_KEY_MAT_OUT CK_PTR CK_WTLS_KEY_MAT_OUT_PTR;
 4482 +
 4483 +typedef struct CK_WTLS_KEY_MAT_PARAMS {
 4484 +  CK_MECHANISM_TYPE       DigestMechanism;
 4485 +  CK_ULONG                ulMacSizeInBits;
 4486 +  CK_ULONG                ulKeySizeInBits;
 4487 +  CK_ULONG                ulIVSizeInBits;
 4488 +  CK_ULONG                ulSequenceNumber;
 4489 +  CK_BBOOL                bIsExport;
 4490 +  CK_WTLS_RANDOM_DATA     RandomInfo;
 4491 +  CK_WTLS_KEY_MAT_OUT_PTR pReturnedKeyMaterial;
 4492 +} CK_WTLS_KEY_MAT_PARAMS;
 4493 +
 4494 +typedef CK_WTLS_KEY_MAT_PARAMS CK_PTR CK_WTLS_KEY_MAT_PARAMS_PTR;
 4495 +
 4496 +/* CMS is new for version 2.20 */
 4497 +typedef struct CK_CMS_SIG_PARAMS {
 4498 +  CK_OBJECT_HANDLE      certificateHandle;
 4499 +  CK_MECHANISM_PTR      pSigningMechanism;
 4500 +  CK_MECHANISM_PTR      pDigestMechanism;
 4501 +  CK_UTF8CHAR_PTR       pContentType;
 4502 +  CK_BYTE_PTR           pRequestedAttributes;
 4503 +  CK_ULONG              ulRequestedAttributesLen;
 4504 +  CK_BYTE_PTR           pRequiredAttributes;
 4505 +  CK_ULONG              ulRequiredAttributesLen;
 4506 +} CK_CMS_SIG_PARAMS;
 4507 +
 4508 +typedef CK_CMS_SIG_PARAMS CK_PTR CK_CMS_SIG_PARAMS_PTR;
 4509 +
 4510 +typedef struct CK_KEY_DERIVATION_STRING_DATA {
 4511 +  CK_BYTE_PTR pData;
 4512 +  CK_ULONG    ulLen;
 4513 +} CK_KEY_DERIVATION_STRING_DATA;
 4514 +
 4515 +typedef CK_KEY_DERIVATION_STRING_DATA CK_PTR \
 4516 +  CK_KEY_DERIVATION_STRING_DATA_PTR;
 4517 +
 4518 +
 4519 +/* The CK_EXTRACT_PARAMS is used for the
 4520 + * CKM_EXTRACT_KEY_FROM_KEY mechanism.  It specifies which bit
 4521 + * of the base key should be used as the first bit of the
 4522 + * derived key */
 4523 +/* CK_EXTRACT_PARAMS is new for v2.0 */
 4524 +typedef CK_ULONG CK_EXTRACT_PARAMS;
 4525 +
 4526 +typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
 4527 +
 4528 +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10.
 4529 + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to
 4530 + * indicate the Pseudo-Random Function (PRF) used to generate
 4531 + * key bits using PKCS #5 PBKDF2. */
 4532 +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE;
 4533 +
 4534 +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR;
 4535 +
 4536 +/* The following PRFs are defined in PKCS #5 v2.0. */
 4537 +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001
 4538 +
 4539 +
 4540 +/* CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is new for v2.10.
 4541 + * CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE is used to indicate the
 4542 + * source of the salt value when deriving a key using PKCS #5
 4543 + * PBKDF2. */
 4544 +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE;
 4545 +
 4546 +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR;
 4547 +
 4548 +/* The following salt value sources are defined in PKCS #5 v2.0. */
 4549 +#define CKZ_SALT_SPECIFIED        0x00000001
 4550 +
 4551 +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10.
 4552 + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the
 4553 + * parameters to the CKM_PKCS5_PBKD2 mechanism. */
 4554 +typedef struct CK_PKCS5_PBKD2_PARAMS {
 4555 +        CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE           saltSource;
 4556 +        CK_VOID_PTR                                pSaltSourceData;
 4557 +        CK_ULONG                                   ulSaltSourceDataLen;
 4558 +        CK_ULONG                                   iterations;
 4559 +        CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf;
 4560 +        CK_VOID_PTR                                pPrfData;
 4561 +        CK_ULONG                                   ulPrfDataLen;
 4562 +        CK_UTF8CHAR_PTR                            pPassword;
 4563 +        CK_ULONG_PTR                               ulPasswordLen;
 4564 +} CK_PKCS5_PBKD2_PARAMS;
 4565 +
 4566 +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR;
 4567 +
 4568 +#endif
 4569 diff -urNp openssh-4.4p1/pkcs11-helper.c openssh-4.4p1+pkcs11-0.17/pkcs11-helper.c
 4570 --- openssh-4.4p1/pkcs11-helper.c   1970-01-01 02:00:00.000000000 +0200
 4571 +++ openssh-4.4p1+pkcs11-0.17/pkcs11-helper.c   2006-10-22 17:11:50.000000000 +0200
 4572 @@ -0,0 +1,11337 @@
 4573 +/*
 4574 + * Copyright (c) 2005-2006 Alon Bar-Lev <alon.barlev@gmail.com>
 4575 + * All rights reserved.
 4576 + *
 4577 + * This software is available to you under a choice of one of two
 4578 + * licenses.  You may choose to be licensed under the terms of the GNU
 4579 + * General Public License (GPL) Version 2, or the OpenIB.org BSD license.
 4580 + *
 4581 + * GNU General Public License (GPL) Version 2
 4582 + * ===========================================
 4583 + *  This program is free software; you can redistribute it and/or modify
 4584 + *  it under the terms of the GNU General Public License version 2
 4585 + *  as published by the Free Software Foundation.
 4586 + *
 4587 + *  This program is distributed in the hope that it will be useful,
 4588 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 4589 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 4590 + *  GNU General Public License for more details.
 4591 + *
 4592 + *  You should have received a copy of the GNU General Public License
 4593 + *  along with this program (see the file COPYING[.GPL2] included with this
 4594 + *  distribution); if not, write to the Free Software Foundation, Inc.,
 4595 + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 4596 + *
 4597 + * OpenIB.org BSD license
 4598 + * =======================
 4599 + * Redistribution and use in source and binary forms, with or without modifi-
 4600 + * cation, are permitted provided that the following conditions are met:
 4601 + *
 4602 + *   o  Redistributions of source code must retain the above copyright notice,
 4603 + *      this list of conditions and the following disclaimer.
 4604 + *
 4605 + *   o  Redistributions in binary form must reproduce the above copyright no-
 4606 + *      tice, this list of conditions and the following disclaimer in the do-
 4607 + *      cumentation and/or other materials provided with the distribution.
 4608 + *
 4609 + *   o  The names of the contributors may not be used to endorse or promote
 4610 + *      products derived from this software without specific prior written
 4611 + *      permission.
 4612 + *
 4613 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 4614 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 4615 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 4616 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LI-
 4617 + * ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN-
 4618 + * TIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 4619 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEV-
 4620 + * ER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI-
 4621 + * LITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 4622 + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 4623 + */
 4624 +
 4625 +/*
 4626 + * The routines in this file deal with providing private key cryptography
 4627 + * using RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
 4628 + *
 4629 + */
 4630 +
 4631 +/*
 4632 + * Changelog
 4633 + *
 4634 + * 2006.09.24
 4635 + *     - (alonbl) Fix invalid certificate max size handling (Zeljko Vrba).
 4636 + *     - (alonbl) Added object serialization.
 4637 + *     - (alonbl) Added user data to hooks.
 4638 + *     - (alonbl) Added a force login method.
 4639 + *     - (alonbl) Added support for gnutls in addition to openssl.
 4640 + *     - (alonbl) Fixup threading lock issues.
 4641 + *     - (alonbl) Added support for duplicate serial tokens, based on label.
 4642 + *     - (alonbl) Added workaround for OpenSC cards, OpenSC bug#108, thanks to Kaupo Arulo.
 4643 + *     - (alonbl) Added a methods to lock session between two sign/decrypt operations.
 4644 + *     - (alonbl) Modified openssl interface.
 4645 + *     - (alonbl) Release 01.02.
 4646 + *
 4647 + * 2006.06.26
 4648 + *     - (alonbl) Fix handling mutiple providers.
 4649 + *     - (alonbl) Release 01.01.
 4650 + *
 4651 + * 2006.05.14
 4652 + *     - (alonbl) First stable release.
 4653 + *     - (alonbl) Release 01.00.
 4654 + *
 4655 + */
 4656 +
 4657 +#include "pkcs11-helper-config.h"
 4658 +
 4659 +#if defined(ENABLE_PKCS11H_HELPER)
 4660 +
 4661 +#include "pkcs11-helper.h"
 4662 +
 4663 +/*===========================================
 4664 + * Constants
 4665 + */
 4666 +
 4667 +#if defined(USE_PKCS11H_OPENSSL)
 4668 +
 4669 +#if OPENSSL_VERSION_NUMBER < 0x00907000L && defined(CRYPTO_LOCK_ENGINE)
 4670 +# define RSA_get_default_method RSA_get_default_openssl_method
 4671 +#else
 4672 +# ifdef HAVE_ENGINE_GET_DEFAULT_RSA
 4673 +#  include <openssl/engine.h>
 4674 +#  if OPENSSL_VERSION_NUMBER < 0x0090704fL
 4675 +#   define BROKEN_OPENSSL_ENGINE
 4676 +#  endif
 4677 +# endif
 4678 +#endif
 4679 +
 4680 +#if OPENSSL_VERSION_NUMBER < 0x00907000L
 4681 +#if !defined(RSA_PKCS1_PADDING_SIZE)
 4682 +#define RSA_PKCS1_PADDING_SIZE 11
 4683 +#endif
 4684 +#endif
 4685 +
 4686 +#endif
 4687 +
 4688 +#define PKCS11H_INVALID_SLOT_ID        ((CK_SLOT_ID)-1)
 4689 +#define PKCS11H_INVALID_SESSION_HANDLE ((CK_SESSION_HANDLE)-1)
 4690 +#define PKCS11H_INVALID_OBJECT_HANDLE  ((CK_OBJECT_HANDLE)-1)
 4691 +
 4692 +#define PKCS11H_DEFAULT_SLOTEVENT_POLL     5000
 4693 +#define PKCS11H_DEFAULT_MAX_LOGIN_RETRY        3
 4694 +#define PKCS11H_DEFAULT_PIN_CACHE_PERIOD   PKCS11H_PIN_CACHE_INFINITE
 4695 +
 4696 +#define PKCS11H_SERIALIZE_INVALID_CHARS    "\\/\"'%&#@!?$* <>{}[]()`|"
 4697 +
 4698 +enum _pkcs11h_private_op_e {
 4699 +   _pkcs11h_private_op_sign=0,
 4700 +   _pkcs11h_private_op_sign_recover,
 4701 +   _pkcs11h_private_op_decrypt
 4702 +};
 4703 +
 4704 +/*===========================================
 4705 + * Macros
 4706 + */
 4707 +
 4708 +#define PKCS11H_MSG_LEVEL_TEST(flags) (((unsigned int)flags) <= s_pkcs11h_loglevel)
 4709 +
 4710 +#if defined(HAVE_CPP_VARARG_MACRO_ISO) && !defined(__LCLINT__)
 4711 +# define PKCS11H_LOG(flags, ...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), __VA_ARGS__); } while
	(FALSE)
 4712 +# ifdef ENABLE_PKCS11H_DEBUG
 4713 +#  define PKCS11H_DEBUG(flags, ...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), __VA_ARGS__); } while
	(FALSE)
 4714 +# else
 4715 +#  define PKCS11H_DEBUG(flags, ...)
 4716 +# endif
 4717 +#elif defined(HAVE_CPP_VARARG_MACRO_GCC) && !defined(__LCLINT__)
 4718 +# define PKCS11H_LOG(flags, args...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), args); } while
	(FALSE)
 4719 +# ifdef ENABLE_PKCS11H_DEBUG
 4720 +#  define PKCS11H_DEBUG(flags, args...) do { if (PKCS11H_MSG_LEVEL_TEST(flags)) _pkcs11h_log((flags), args); } while
	(FALSE)
 4721 +# else
 4722 +#  define PKCS11H_DEBUG(flags, args...)
 4723 +# endif
 4724 +#else
 4725 +# define PKCS11H_LOG _pkcs11h_log
 4726 +# define PKCS11H_DEBUG _pkcs11h_log
 4727 +#endif
 4728 +
 4729 +/*===========================================
 4730 + * Types
 4731 + */
 4732 +
 4733 +struct pkcs11h_provider_s;
 4734 +struct pkcs11h_session_s;
 4735 +struct pkcs11h_data_s;
 4736 +typedef struct pkcs11h_provider_s *pkcs11h_provider_t;
 4737 +typedef struct pkcs11h_session_s *pkcs11h_session_t;
 4738 +typedef struct pkcs11h_data_s *pkcs11h_data_t;
 4739 +
 4740 +#if defined(USE_PKCS11H_OPENSSL)
 4741 +
 4742 +#if OPENSSL_VERSION_NUMBER < 0x00908000L
 4743 +typedef unsigned char *pkcs11_openssl_d2i_t;
 4744 +#else
 4745 +typedef const unsigned char *pkcs11_openssl_d2i_t;
 4746 +#endif
 4747 +
 4748 +#endif
 4749 +
 4750 +#if defined(ENABLE_PKCS11H_THREADING)
 4751 +
 4752 +#define PKCS11H_COND_INFINITE  0xffffffff
 4753 +
 4754 +#if defined(WIN32)
 4755 +#define PKCS11H_THREAD_NULL    NULL
 4756 +typedef HANDLE pkcs11h_cond_t;
 4757 +typedef HANDLE pkcs11h_mutex_t;
 4758 +typedef HANDLE pkcs11h_thread_t;
 4759 +#else
 4760 +#define PKCS11H_THREAD_NULL    0l
 4761 +typedef pthread_mutex_t pkcs11h_mutex_t;
 4762 +typedef pthread_t pkcs11h_thread_t;
 4763 +
 4764 +typedef struct {
 4765 +   pthread_cond_t cond;
 4766 +   pthread_mutex_t mut;
 4767 +} pkcs11h_cond_t;
 4768 +
 4769 +typedef struct __pkcs11h_threading_mutex_entry_s {
 4770 +   struct __pkcs11h_threading_mutex_entry_s *next;
 4771 +   pkcs11h_mutex_t *p_mutex;
 4772 +   PKCS11H_BOOL locked;
 4773 +} *__pkcs11h_threading_mutex_entry_t;
 4774 +#endif
 4775 +
 4776 +typedef void * (*pkcs11h_thread_start_t)(void *);
 4777 +
 4778 +typedef struct {
 4779 +   pkcs11h_thread_start_t start;
 4780 +   void *data;
 4781 +} __pkcs11h_thread_data_t;
 4782 +
 4783 +#endif             /* ENABLE_PKCS11H_THREADING */
 4784 +
 4785 +struct pkcs11h_provider_s {
 4786 +   pkcs11h_provider_t next;
 4787 +
 4788 +   PKCS11H_BOOL enabled;
 4789 +   char reference[1024];
 4790 +   char manufacturerID[sizeof (((CK_TOKEN_INFO *)NULL)->manufacturerID)+1];
 4791 +   
 4792 +#if defined(WIN32)
 4793 +   HANDLE handle;
 4794 +#else
 4795 +   void *handle;
 4796 +#endif
 4797 +
 4798 +   CK_FUNCTION_LIST_PTR f;
 4799 +   PKCS11H_BOOL should_finalize;
 4800 +   PKCS11H_BOOL allow_protected_auth;
 4801 +   PKCS11H_BOOL cert_is_private;
 4802 +   unsigned mask_sign_mode;
 4803 +   int slot_event_method;
 4804 +   int slot_poll_interval;
 4805 +
 4806 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 4807 +   pkcs11h_thread_t slotevent_thread;
 4808 +#endif
 4809 +};
 4810 +
 4811 +struct pkcs11h_session_s {
 4812 +   pkcs11h_session_t next;
 4813 +
 4814 +   int reference_count;
 4815 +   PKCS11H_BOOL valid;
 4816 +
 4817 +   pkcs11h_provider_t provider;
 4818 +
 4819 +   pkcs11h_token_id_t token_id;
 4820 +
 4821 +   CK_SESSION_HANDLE session_handle;
 4822 +
 4823 +   PKCS11H_BOOL allow_protected_auth_supported;
 4824 +   int pin_cache_period;
 4825 +   time_t pin_expire_time;
 4826 +
 4827 +#if defined(ENABLE_PKCS11H_ENUM)
 4828 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
 4829 +   pkcs11h_certificate_id_list_t cached_certs;
 4830 +   PKCS11H_BOOL touch;
 4831 +#endif
 4832 +#endif
 4833 +
 4834 +#if defined(ENABLE_PKCS11H_THREADING)
 4835 +   pkcs11h_mutex_t mutex;
 4836 +#endif
 4837 +};
 4838 +
 4839 +#if defined (ENABLE_PKCS11H_CERTIFICATE)
 4840 +
 4841 +struct pkcs11h_certificate_s {
 4842 +
 4843 +   pkcs11h_certificate_id_t id;
 4844 +   int pin_cache_period;
 4845 +   PKCS11H_BOOL pin_cache_populated_to_session;
 4846 +
 4847 +   unsigned mask_sign_mode;
 4848 +
 4849 +   pkcs11h_session_t session;
 4850 +   CK_OBJECT_HANDLE key_handle;
 4851 +
 4852 +   PKCS11H_BOOL operation_active;
 4853 +
 4854 +#if defined(ENABLE_PKCS11H_THREADING)
 4855 +   pkcs11h_mutex_t mutex;
 4856 +#endif
 4857 +
 4858 +   unsigned mask_prompt;
 4859 +   void * user_data;
 4860 +};
 4861 +
 4862 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
 4863 +
 4864 +struct pkcs11h_data_s {
 4865 +   PKCS11H_BOOL initialized;
 4866 +   int pin_cache_period;
 4867 +
 4868 +   pkcs11h_provider_t providers;
 4869 +   pkcs11h_session_t sessions;
 4870 +
 4871 +   struct {
 4872 +       void * log_data;
 4873 +       void * slotevent_data;
 4874 +       void * token_prompt_data;
 4875 +       void * pin_prompt_data;
 4876 +       pkcs11h_hook_log_t log;
 4877 +       pkcs11h_hook_slotevent_t slotevent;
 4878 +       pkcs11h_hook_token_prompt_t token_prompt;
 4879 +       pkcs11h_hook_pin_prompt_t pin_prompt;
 4880 +   } hooks;
 4881 +
 4882 +   PKCS11H_BOOL allow_protected_auth;
 4883 +   unsigned max_retries;
 4884 +
 4885 +#if defined(ENABLE_PKCS11H_THREADING)
 4886 +   struct {
 4887 +       pkcs11h_mutex_t global;
 4888 +       pkcs11h_mutex_t session;
 4889 +       pkcs11h_mutex_t cache;
 4890 +   } mutexes;
 4891 +#endif
 4892 +
 4893 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 4894 +   struct {
 4895 +       PKCS11H_BOOL initialized;
 4896 +       PKCS11H_BOOL should_terminate;
 4897 +       PKCS11H_BOOL skip_event;
 4898 +       pkcs11h_cond_t cond_event;
 4899 +       pkcs11h_thread_t thread;
 4900 +   } slotevent;
 4901 +#endif
 4902 +};
 4903 +
 4904 +#if defined(ENABLE_PKCS11H_OPENSSL)
 4905 +struct pkcs11h_openssl_session_s {
 4906 +   int reference_count;
 4907 +   PKCS11H_BOOL initialized;
 4908 +   X509 *x509;
 4909 +   RSA_METHOD smart_rsa;
 4910 +   int (*orig_finish)(RSA *rsa);
 4911 +   pkcs11h_certificate_t certificate;
 4912 +   pkcs11h_hook_openssl_cleanup_t cleanup_hook;
 4913 +};
 4914 +#endif
 4915 +
 4916 +/*======================================================================*
 4917 + * MEMORY INTERFACE
 4918 + *======================================================================*/
 4919 +
 4920 +static
 4921 +CK_RV
 4922 +_pkcs11h_mem_malloc (
 4923 +   OUT const void * * const p,
 4924 +   IN const size_t s
 4925 +);
 4926 +static
 4927 +CK_RV
 4928 +_pkcs11h_mem_free (
 4929 +   IN const void * * const p
 4930 +);
 4931 +static
 4932 +CK_RV
 4933 +_pkcs11h_mem_strdup (
 4934 +   OUT const char * * const dest,
 4935 +   IN const char * const src
 4936 +);
 4937 +static
 4938 +CK_RV
 4939 +_pkcs11h_mem_duplicate (
 4940 +   OUT const void * * const dest,
 4941 +   OUT size_t * const dest_size,
 4942 +   IN const void * const src,
 4943 +   IN const size_t mem_size
 4944 +);
 4945 +
 4946 +#if defined(ENABLE_PKCS11H_THREADING)
 4947 +/*======================================================================*
 4948 + * THREADING INTERFACE
 4949 + *======================================================================*/
 4950 +
 4951 +static
 4952 +void
 4953 +_pkcs11h_threading_sleep (
 4954 +   IN const unsigned milli
 4955 +);
 4956 +static
 4957 +CK_RV
 4958 +_pkcs11h_threading_mutexInit (
 4959 +   OUT pkcs11h_mutex_t * const mutex
 4960 +);
 4961 +static
 4962 +CK_RV
 4963 +_pkcs11h_threading_mutexLock (
 4964 +   IN OUT pkcs11h_mutex_t *const mutex
 4965 +);
 4966 +static
 4967 +CK_RV
 4968 +_pkcs11h_threading_mutexRelease (
 4969 +   IN OUT pkcs11h_mutex_t *const mutex
 4970 +);
 4971 +static
 4972 +CK_RV
 4973 +_pkcs11h_threading_mutexFree (
 4974 +   IN OUT pkcs11h_mutex_t *const mutex
 4975 +);
 4976 +#if !defined(WIN32)
 4977 +static
 4978 +void
 4979 +__pkcs1h_threading_mutexLockAll ();
 4980 +static
 4981 +void
 4982 +__pkcs1h_threading_mutexReleaseAll ();
 4983 +#endif
 4984 +static
 4985 +CK_RV
 4986 +_pkcs11h_threading_condSignal (
 4987 +   IN OUT pkcs11h_cond_t *const cond
 4988 +);
 4989 +static
 4990 +CK_RV
 4991 +_pkcs11h_threading_condInit (
 4992 +   OUT pkcs11h_cond_t * const cond
 4993 +);
 4994 +static
 4995 +CK_RV
 4996 +_pkcs11h_threading_condWait (
 4997 +   IN OUT pkcs11h_cond_t *const cond,
 4998 +   IN const unsigned milli
 4999 +);
 5000 +static
 5001 +CK_RV
 5002 +_pkcs11h_threading_condFree (
 5003 +   IN OUT pkcs11h_cond_t *const cond
 5004 +);
 5005 +static
 5006 +CK_RV
 5007 +_pkcs11h_threading_threadStart (
 5008 +   OUT pkcs11h_thread_t * const thread,
 5009 +   IN pkcs11h_thread_start_t const start,
 5010 +   IN void * data
 5011 +);
 5012 +static
 5013 +CK_RV
 5014 +_pkcs11h_threading_threadJoin (
 5015 +   IN pkcs11h_thread_t * const thread
 5016 +);
 5017 +#endif             /* ENABLE_PKCS11H_THREADING */
 5018 +
 5019 +/*======================================================================*
 5020 + * COMMON INTERNAL INTERFACE
 5021 + *======================================================================*/
 5022 +
 5023 +static
 5024 +void
 5025 +_pkcs11h_util_fixupFixedString (
 5026 +   OUT char * const target,            /* MUST BE >= length+1 */
 5027 +   IN const char * const source,
 5028 +   IN const size_t length              /* FIXED STRING LENGTH */
 5029 +);
 5030 +static
 5031 +CK_RV
 5032 +_pkcs11h_util_hexToBinary (
 5033 +   OUT unsigned char * const target,
 5034 +   IN const char * const source,
 5035 +   IN OUT size_t * const p_target_size
 5036 +);
 5037 +static
 5038 +CK_RV
 5039 +_pkcs11h_util_binaryToHex (
 5040 +   OUT char * const target,
 5041 +   IN const size_t target_size,
 5042 +   IN const unsigned char * const source,
 5043 +   IN const size_t source_size
 5044 +);
 5045 +CK_RV
 5046 +_pkcs11h_util_escapeString (
 5047 +   IN OUT char * const target,
 5048 +   IN const char * const source,
 5049 +   IN size_t * const max,
 5050 +   IN const char * const invalid_chars
 5051 +);
 5052 +static
 5053 +CK_RV
 5054 +_pkcs11h_util_unescapeString (
 5055 +   IN OUT char * const target,
 5056 +   IN const char * const source,
 5057 +   IN size_t * const max
 5058 +);
 5059 +static
 5060 +void
 5061 +_pkcs11h_log (
 5062 +   IN const unsigned flags,
 5063 +   IN const char * const format,
 5064 +   IN ...
 5065 +)
 5066 +#ifdef __GNUC__
 5067 +    __attribute__ ((format (printf, 2, 3)))
 5068 +#endif
 5069 +    ;
 5070 +
 5071 +static
 5072 +CK_RV
 5073 +_pkcs11h_session_getSlotList (
 5074 +   IN const pkcs11h_provider_t provider,
 5075 +   IN const CK_BBOOL token_present,
 5076 +   OUT CK_SLOT_ID_PTR * const pSlotList,
 5077 +   OUT CK_ULONG_PTR pulCount
 5078 +);
 5079 +static
 5080 +CK_RV
 5081 +_pkcs11h_session_getObjectAttributes (
 5082 +   IN const pkcs11h_session_t session,
 5083 +   IN const CK_OBJECT_HANDLE object,
 5084 +   IN OUT const CK_ATTRIBUTE_PTR attrs,
 5085 +   IN const unsigned count
 5086 +);
 5087 +static
 5088 +CK_RV
 5089 +_pkcs11h_session_freeObjectAttributes (
 5090 +   IN OUT const CK_ATTRIBUTE_PTR attrs,
 5091 +   IN const unsigned count
 5092 +);
 5093 +static
 5094 +CK_RV
 5095 +_pkcs11h_session_findObjects (
 5096 +   IN const pkcs11h_session_t session,
 5097 +   IN const CK_ATTRIBUTE * const filter,
 5098 +   IN const CK_ULONG filter_attrs,
 5099 +   OUT CK_OBJECT_HANDLE **const p_objects,
 5100 +   OUT CK_ULONG *p_objects_found
 5101 +);
 5102 +static
 5103 +CK_RV
 5104 +_pkcs11h_token_getTokenId (
 5105 +   IN const CK_TOKEN_INFO_PTR info,
 5106 +   OUT pkcs11h_token_id_t * const p_token_id
 5107 +);
 5108 +static
 5109 +CK_RV
 5110 +_pkcs11h_token_newTokenId (
 5111 +   OUT pkcs11h_token_id_t * const token_id
 5112 +);
 5113 +static
 5114 +CK_RV
 5115 +_pkcs11h_session_getSessionByTokenId (
 5116 +   IN const pkcs11h_token_id_t token_id,
 5117 +   OUT pkcs11h_session_t * const p_session
 5118 +);
 5119 +static
 5120 +CK_RV
 5121 +_pkcs11h_session_release (
 5122 +   IN const pkcs11h_session_t session
 5123 +);
 5124 +static
 5125 +CK_RV
 5126 +_pkcs11h_session_reset (
 5127 +   IN const pkcs11h_session_t session,
 5128 +   IN void * const user_data,
 5129 +   IN const unsigned mask_prompt,
 5130 +   OUT CK_SLOT_ID * const p_slot
 5131 +);
 5132 +static
 5133 +CK_RV
 5134 +_pkcs11h_session_getObjectById (
 5135 +   IN const pkcs11h_session_t session,
 5136 +   IN const CK_OBJECT_CLASS class,
 5137 +   IN const CK_BYTE_PTR id,
 5138 +   IN const size_t id_size,
 5139 +   OUT CK_OBJECT_HANDLE * const p_handle
 5140 +);
 5141 +static
 5142 +CK_RV
 5143 +_pkcs11h_session_validate (
 5144 +   IN const pkcs11h_session_t session
 5145 +);
 5146 +static
 5147 +CK_RV
 5148 +_pkcs11h_session_touch (
 5149 +   IN const pkcs11h_session_t session
 5150 +);
 5151 +static
 5152 +CK_RV
 5153 +_pkcs11h_session_login (
 5154 +   IN const pkcs11h_session_t session,
 5155 +   IN const PKCS11H_BOOL public_only,
 5156 +   IN const PKCS11H_BOOL readonly,
 5157 +   IN void * const user_data,
 5158 +   IN const unsigned mask_prompt
 5159 +);
 5160 +static
 5161 +CK_RV
 5162 +_pkcs11h_session_logout (
 5163 +   IN const pkcs11h_session_t session
 5164 +);
 5165 +
 5166 +static
 5167 +void
 5168 +_pkcs11h_hooks_default_log (
 5169 +   IN void * const global_data,
 5170 +   IN const unsigned flags,
 5171 +   IN const char * const format,
 5172 +   IN va_list args
 5173 +);
 5174 +
 5175 +static
 5176 +PKCS11H_BOOL
 5177 +_pkcs11h_hooks_default_token_prompt (
 5178 +   IN void * const global_data,
 5179 +   IN void * const user_data,
 5180 +   IN const pkcs11h_token_id_t token,
 5181 +   IN const unsigned retry
 5182 +);
 5183 +
 5184 +static
 5185 +PKCS11H_BOOL
 5186 +_pkcs11h_hooks_default_pin_prompt (
 5187 +   IN void * const global_data,
 5188 +   IN void * const user_data,
 5189 +   IN const pkcs11h_token_id_t token,
 5190 +   IN const unsigned retry,
 5191 +   OUT char * const pin,
 5192 +   IN const size_t pin_max
 5193 +);
 5194 +
 5195 +#if !defined(WIN32)
 5196 +#if defined(ENABLE_PKCS11H_THREADING)
 5197 +static
 5198 +void
 5199 +__pkcs11h_threading_atfork_prepare  ();
 5200 +static
 5201 +void
 5202 +__pkcs11h_threading_atfork_parent ();
 5203 +static
 5204 +void
 5205 +__pkcs11h_threading_atfork_child ();
 5206 +#endif
 5207 +static
 5208 +CK_RV
 5209 +_pkcs11h_forkFixup ();
 5210 +#endif
 5211 +
 5212 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
 5213 +/*======================================================================*
 5214 + * CERTIFICATE INTERFACE
 5215 + *======================================================================*/
 5216 +
 5217 +static
 5218 +time_t
 5219 +_pkcs11h_certificate_getExpiration (
 5220 +   IN const unsigned char * const certificate,
 5221 +   IN const size_t certificate_size
 5222 +);
 5223 +static
 5224 +PKCS11H_BOOL
 5225 +_pkcs11h_certificate_isBetterCertificate (
 5226 +   IN const unsigned char * const current,
 5227 +   IN const size_t current_size,
 5228 +   IN const unsigned char * const newone,
 5229 +   IN const size_t newone_size
 5230 +);
 5231 +static
 5232 +CK_RV
 5233 +_pkcs11h_certificate_newCertificateId (
 5234 +   OUT pkcs11h_certificate_id_t * const certificate_id
 5235 +);
 5236 +static
 5237 +CK_RV
 5238 +_pkcs11h_certificate_getDN (
 5239 +   IN const unsigned char * const blob,
 5240 +   IN const size_t blob_size,
 5241 +   OUT char * const dn,
 5242 +   IN const size_t dn_size
 5243 +);
 5244 +static
 5245 +CK_RV
 5246 +_pkcs11h_certificate_loadCertificate (
 5247 +   IN const pkcs11h_certificate_t certificate
 5248 +);
 5249 +static
 5250 +CK_RV
 5251 +_pkcs11h_certificate_updateCertificateIdDescription (
 5252 +   IN OUT pkcs11h_certificate_id_t certificate_id
 5253 +);
 5254 +static
 5255 +CK_RV
 5256 +_pkcs11h_certificate_getKeyAttributes (
 5257 +   IN const pkcs11h_certificate_t certificate
 5258 +);
 5259 +static
 5260 +CK_RV
 5261 +_pkcs11h_certificate_validateSession (
 5262 +   IN const pkcs11h_certificate_t certificate
 5263 +);
 5264 +static
 5265 +CK_RV
 5266 +_pkcs11h_certificate_resetSession (
 5267 +   IN const pkcs11h_certificate_t certificate,
 5268 +   IN const PKCS11H_BOOL public_only,
 5269 +   IN const PKCS11H_BOOL session_mutex_locked
 5270 +);
 5271 +static
 5272 +CK_RV
 5273 +_pkcs11h_certificate_doPrivateOperation (
 5274 +   IN const pkcs11h_certificate_t certificate,
 5275 +   IN const enum _pkcs11h_private_op_e op,
 5276 +   IN const CK_MECHANISM_TYPE mech_type,
 5277 +   IN const unsigned char * const source,
 5278 +   IN const size_t source_size,
 5279 +   OUT unsigned char * const target,
 5280 +   IN OUT size_t * const p_target_size
 5281 +);
 5282 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
 5283 +
 5284 +#if defined(ENABLE_PKCS11H_LOCATE)
 5285 +/*======================================================================*
 5286 + * LOCATE INTERFACE
 5287 + *======================================================================*/
 5288 +
 5289 +static
 5290 +CK_RV
 5291 +_pkcs11h_locate_getTokenIdBySlotId (
 5292 +   IN const char * const slot,
 5293 +   OUT pkcs11h_token_id_t * const p_token_id
 5294 +);
 5295 +static
 5296 +CK_RV
 5297 +_pkcs11h_locate_getTokenIdBySlotName (
 5298 +   IN const char * const name,
 5299 +   OUT pkcs11h_token_id_t * const p_token_id
 5300 +);
 5301 +static
 5302 +CK_RV
 5303 +_pkcs11h_locate_getTokenIdByLabel (
 5304 +   IN const char * const label,
 5305 +   OUT pkcs11h_token_id_t * const p_token_id
 5306 +);
 5307 +
 5308 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
 5309 +
 5310 +static
 5311 +CK_RV
 5312 +_pkcs11h_locate_getCertificateIdByLabel (
 5313 +   IN const pkcs11h_session_t session,
 5314 +   IN OUT const pkcs11h_certificate_id_t certificate_id,
 5315 +   IN const char * const label
 5316 +);
 5317 +static
 5318 +CK_RV
 5319 +_pkcs11h_locate_getCertificateIdBySubject (
 5320 +   IN const pkcs11h_session_t session,
 5321 +   IN OUT const pkcs11h_certificate_id_t certificate_id,
 5322 +   IN const char * const subject
 5323 +);
 5324 +
 5325 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
 5326 +#endif             /* ENABLE_PKCS11H_LOCATE */
 5327 +
 5328 +#if defined(ENABLE_PKCS11H_ENUM)
 5329 +/*======================================================================*
 5330 + * ENUM INTERFACE
 5331 + *======================================================================*/
 5332 +
 5333 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
 5334 +
 5335 +static
 5336 +CK_RV
 5337 +_pkcs11h_certificate_enumSessionCertificates (
 5338 +   IN const pkcs11h_session_t session,
 5339 +   IN void * const user_data,
 5340 +   IN const unsigned mask_prompt
 5341 +);
 5342 +static
 5343 +CK_RV
 5344 +_pkcs11h_certificate_splitCertificateIdList (
 5345 +   IN const pkcs11h_certificate_id_list_t cert_id_all,
 5346 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
 5347 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
 5348 +);
 5349 +
 5350 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
 5351 +
 5352 +#endif             /* ENABLE_PKCS11H_ENUM */
 5353 +
 5354 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 5355 +/*======================================================================*
 5356 + * SLOTEVENT INTERFACE
 5357 + *======================================================================*/
 5358 +
 5359 +static
 5360 +unsigned long
 5361 +_pkcs11h_slotevent_checksum (
 5362 +   IN const unsigned char * const p,
 5363 +   IN const size_t s
 5364 +);
 5365 +static
 5366 +void *
 5367 +_pkcs11h_slotevent_provider (
 5368 +   IN void *p
 5369 +);
 5370 +static
 5371 +void *
 5372 +_pkcs11h_slotevent_manager (
 5373 +   IN void *p
 5374 +);
 5375 +static
 5376 +CK_RV
 5377 +_pkcs11h_slotevent_init ();
 5378 +static
 5379 +CK_RV
 5380 +_pkcs11h_slotevent_notify ();
 5381 +static
 5382 +CK_RV
 5383 +_pkcs11h_slotevent_terminate ();
 5384 +
 5385 +#endif             /* ENABLE_PKCS11H_SLOTEVENT */
 5386 +
 5387 +#if defined(ENABLE_PKCS11H_OPENSSL)
 5388 +/*======================================================================*
 5389 + * OPENSSL INTERFACE
 5390 + *======================================================================*/
 5391 +
 5392 +static
 5393 +int
 5394 +_pkcs11h_openssl_finish (
 5395 +   IN OUT RSA *rsa
 5396 +);
 5397 +#if OPENSSL_VERSION_NUMBER < 0x00907000L
 5398 +static
 5399 +int
 5400 +_pkcs11h_openssl_dec (
 5401 +   IN int flen,
 5402 +   IN unsigned char *from,
 5403 +   OUT unsigned char *to,
 5404 +   IN OUT RSA *rsa,
 5405 +   IN int padding
 5406 +);
 5407 +static
 5408 +int
 5409 +_pkcs11h_openssl_sign (
 5410 +   IN int type,
 5411 +   IN unsigned char *m,
 5412 +   IN unsigned int m_len,
 5413 +   OUT unsigned char *sigret,
 5414 +   OUT unsigned int *siglen,
 5415 +   IN OUT RSA *rsa
 5416 +);
 5417 +#else
 5418 +static
 5419 +int
 5420 +_pkcs11h_openssl_dec (
 5421 +   IN int flen,
 5422 +   IN const unsigned char *from,
 5423 +   OUT unsigned char *to,
 5424 +   IN OUT RSA *rsa,
 5425 +   IN int padding
 5426 +);
 5427 +static
 5428 +int
 5429 +_pkcs11h_openssl_sign (
 5430 +   IN int type,
 5431 +   IN const unsigned char *m,
 5432 +   IN unsigned int m_len,
 5433 +   OUT unsigned char *sigret,
 5434 +   OUT unsigned int *siglen,
 5435 +   IN OUT const RSA *rsa
 5436 +);
 5437 +#endif
 5438 +static
 5439 +pkcs11h_openssl_session_t
 5440 +_pkcs11h_openssl_get_openssl_session (
 5441 +   IN OUT const RSA *rsa
 5442 +);  
 5443 +static
 5444 +pkcs11h_certificate_t
 5445 +_pkcs11h_openssl_get_pkcs11h_certificate (
 5446 +   IN OUT const RSA *rsa
 5447 +);  
 5448 +#endif             /* ENABLE_PKCS11H_OPENSSL */
 5449 +
 5450 +/*==========================================
 5451 + * Static data
 5452 + */
 5453 +
 5454 +#if defined(ENABLE_PKCS11H_THREADING)
 5455 +#if !defined(WIN32)
 5456 +static struct {
 5457 +   pkcs11h_mutex_t mutex;
 5458 +   __pkcs11h_threading_mutex_entry_t head;
 5459 +} __s_pkcs11h_threading_mutex_list = {
 5460 +   PTHREAD_MUTEX_INITIALIZER,
 5461 +   NULL
 5462 +};
 5463 +#endif
 5464 +#endif
 5465 +
 5466 +pkcs11h_data_t s_pkcs11h_data = NULL;
 5467 +unsigned int s_pkcs11h_loglevel = PKCS11H_LOG_INFO;
 5468 +
 5469 +/*======================================================================*
 5470 + * PUBLIC INTERFACE
 5471 + *======================================================================*/
 5472 +
 5473 +const char *
 5474 +pkcs11h_getMessage (
 5475 +   IN const CK_RV rv
 5476 +) {
 5477 +   switch (rv) {
 5478 +       case CKR_OK: return "CKR_OK";
 5479 +       case CKR_CANCEL: return "CKR_CANCEL";
 5480 +       case CKR_HOST_MEMORY: return "CKR_HOST_MEMORY";
 5481 +       case CKR_SLOT_ID_INVALID: return "CKR_SLOT_ID_INVALID";
 5482 +       case CKR_GENERAL_ERROR: return "CKR_GENERAL_ERROR";
 5483 +       case CKR_FUNCTION_FAILED: return "CKR_FUNCTION_FAILED";
 5484 +       case CKR_ARGUMENTS_BAD: return "CKR_ARGUMENTS_BAD";
 5485 +       case CKR_NO_EVENT: return "CKR_NO_EVENT";
 5486 +       case CKR_NEED_TO_CREATE_THREADS: return "CKR_NEED_TO_CREATE_THREADS";
 5487 +       case CKR_CANT_LOCK: return "CKR_CANT_LOCK";
 5488 +       case CKR_ATTRIBUTE_READ_ONLY: return "CKR_ATTRIBUTE_READ_ONLY";
 5489 +       case CKR_ATTRIBUTE_SENSITIVE: return "CKR_ATTRIBUTE_SENSITIVE";
 5490 +       case CKR_ATTRIBUTE_TYPE_INVALID: return "CKR_ATTRIBUTE_TYPE_INVALID";
 5491 +       case CKR_ATTRIBUTE_VALUE_INVALID: return "CKR_ATTRIBUTE_VALUE_INVALID";
 5492 +       case CKR_DATA_INVALID: return "CKR_DATA_INVALID";
 5493 +       case CKR_DATA_LEN_RANGE: return "CKR_DATA_LEN_RANGE";
 5494 +       case CKR_DEVICE_ERROR: return "CKR_DEVICE_ERROR";
 5495 +       case CKR_DEVICE_MEMORY: return "CKR_DEVICE_MEMORY";
 5496 +       case CKR_DEVICE_REMOVED: return "CKR_DEVICE_REMOVED";
 5497 +       case CKR_ENCRYPTED_DATA_INVALID: return "CKR_ENCRYPTED_DATA_INVALID";
 5498 +       case CKR_ENCRYPTED_DATA_LEN_RANGE: return "CKR_ENCRYPTED_DATA_LEN_RANGE";
 5499 +       case CKR_FUNCTION_CANCELED: return "CKR_FUNCTION_CANCELED";
 5500 +       case CKR_FUNCTION_NOT_PARALLEL: return "CKR_FUNCTION_NOT_PARALLEL";
 5501 +       case CKR_FUNCTION_NOT_SUPPORTED: return "CKR_FUNCTION_NOT_SUPPORTED";
 5502 +       case CKR_KEY_HANDLE_INVALID: return "CKR_KEY_HANDLE_INVALID";
 5503 +       case CKR_KEY_SIZE_RANGE: return "CKR_KEY_SIZE_RANGE";
 5504 +       case CKR_KEY_TYPE_INCONSISTENT: return "CKR_KEY_TYPE_INCONSISTENT";
 5505 +       case CKR_KEY_NOT_NEEDED: return "CKR_KEY_NOT_NEEDED";
 5506 +       case CKR_KEY_CHANGED: return "CKR_KEY_CHANGED";
 5507 +       case CKR_KEY_NEEDED: return "CKR_KEY_NEEDED";
 5508 +       case CKR_KEY_INDIGESTIBLE: return "CKR_KEY_INDIGESTIBLE";
 5509 +       case CKR_KEY_FUNCTION_NOT_PERMITTED: return "CKR_KEY_FUNCTION_NOT_PERMITTED";
 5510 +       case CKR_KEY_NOT_WRAPPABLE: return "CKR_KEY_NOT_WRAPPABLE";
 5511 +       case CKR_KEY_UNEXTRACTABLE: return "CKR_KEY_UNEXTRACTABLE";
 5512 +       case CKR_MECHANISM_INVALID: return "CKR_MECHANISM_INVALID";
 5513 +       case CKR_MECHANISM_PARAM_INVALID: return "CKR_MECHANISM_PARAM_INVALID";
 5514 +       case CKR_OBJECT_HANDLE_INVALID: return "CKR_OBJECT_HANDLE_INVALID";
 5515 +       case CKR_OPERATION_ACTIVE: return "CKR_OPERATION_ACTIVE";
 5516 +       case CKR_OPERATION_NOT_INITIALIZED: return "CKR_OPERATION_NOT_INITIALIZED";
 5517 +       case CKR_PIN_INCORRECT: return "CKR_PIN_INCORRECT";
 5518 +       case CKR_PIN_INVALID: return "CKR_PIN_INVALID";
 5519 +       case CKR_PIN_LEN_RANGE: return "CKR_PIN_LEN_RANGE";
 5520 +       case CKR_PIN_EXPIRED: return "CKR_PIN_EXPIRED";
 5521 +       case CKR_PIN_LOCKED: return "CKR_PIN_LOCKED";
 5522 +       case CKR_SESSION_CLOSED: return "CKR_SESSION_CLOSED";
 5523 +       case CKR_SESSION_COUNT: return "CKR_SESSION_COUNT";
 5524 +       case CKR_SESSION_HANDLE_INVALID: return "CKR_SESSION_HANDLE_INVALID";
 5525 +       case CKR_SESSION_PARALLEL_NOT_SUPPORTED: return "CKR_SESSION_PARALLEL_NOT_SUPPORTED";
 5526 +       case CKR_SESSION_READ_ONLY: return "CKR_SESSION_READ_ONLY";
 5527 +       case CKR_SESSION_EXISTS: return "CKR_SESSION_EXISTS";
 5528 +       case CKR_SESSION_READ_ONLY_EXISTS: return "CKR_SESSION_READ_ONLY_EXISTS";
 5529 +       case CKR_SESSION_READ_WRITE_SO_EXISTS: return "CKR_SESSION_READ_WRITE_SO_EXISTS";
 5530 +       case CKR_SIGNATURE_INVALID: return "CKR_SIGNATURE_INVALID";
 5531 +       case CKR_SIGNATURE_LEN_RANGE: return "CKR_SIGNATURE_LEN_RANGE";
 5532 +       case CKR_TEMPLATE_INCOMPLETE: return "CKR_TEMPLATE_INCOMPLETE";
 5533 +       case CKR_TEMPLATE_INCONSISTENT: return "CKR_TEMPLATE_INCONSISTENT";
 5534 +       case CKR_TOKEN_NOT_PRESENT: return "CKR_TOKEN_NOT_PRESENT";
 5535 +       case CKR_TOKEN_NOT_RECOGNIZED: return "CKR_TOKEN_NOT_RECOGNIZED";
 5536 +       case CKR_TOKEN_WRITE_PROTECTED: return "CKR_TOKEN_WRITE_PROTECTED";
 5537 +       case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return "CKR_UNWRAPPING_KEY_HANDLE_INVALID";
 5538 +       case CKR_UNWRAPPING_KEY_SIZE_RANGE: return "CKR_UNWRAPPING_KEY_SIZE_RANGE";
 5539 +       case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT";
 5540 +       case CKR_USER_ALREADY_LOGGED_IN: return "CKR_USER_ALREADY_LOGGED_IN";
 5541 +       case CKR_USER_NOT_LOGGED_IN: return "CKR_USER_NOT_LOGGED_IN";
 5542 +       case CKR_USER_PIN_NOT_INITIALIZED: return "CKR_USER_PIN_NOT_INITIALIZED";
 5543 +       case CKR_USER_TYPE_INVALID: return "CKR_USER_TYPE_INVALID";
 5544 +       case CKR_USER_ANOTHER_ALREADY_LOGGED_IN: return "CKR_USER_ANOTHER_ALREADY_LOGGED_IN";
 5545 +       case CKR_USER_TOO_MANY_TYPES: return "CKR_USER_TOO_MANY_TYPES";
 5546 +       case CKR_WRAPPED_KEY_INVALID: return "CKR_WRAPPED_KEY_INVALID";
 5547 +       case CKR_WRAPPED_KEY_LEN_RANGE: return "CKR_WRAPPED_KEY_LEN_RANGE";
 5548 +       case CKR_WRAPPING_KEY_HANDLE_INVALID: return "CKR_WRAPPING_KEY_HANDLE_INVALID";
 5549 +       case CKR_WRAPPING_KEY_SIZE_RANGE: return "CKR_WRAPPING_KEY_SIZE_RANGE";
 5550 +       case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT";
 5551 +       case CKR_RANDOM_SEED_NOT_SUPPORTED: return "CKR_RANDOM_SEED_NOT_SUPPORTED";
 5552 +       case CKR_RANDOM_NO_RNG: return "CKR_RANDOM_NO_RNG";
 5553 +       case CKR_DOMAIN_PARAMS_INVALID: return "CKR_DOMAIN_PARAMS_INVALID";
 5554 +       case CKR_BUFFER_TOO_SMALL: return "CKR_BUFFER_TOO_SMALL";
 5555 +       case CKR_SAVED_STATE_INVALID: return "CKR_SAVED_STATE_INVALID";
 5556 +       case CKR_INFORMATION_SENSITIVE: return "CKR_INFORMATION_SENSITIVE";
 5557 +       case CKR_STATE_UNSAVEABLE: return "CKR_STATE_UNSAVEABLE";
 5558 +       case CKR_CRYPTOKI_NOT_INITIALIZED: return "CKR_CRYPTOKI_NOT_INITIALIZED";
 5559 +       case CKR_CRYPTOKI_ALREADY_INITIALIZED: return "CKR_CRYPTOKI_ALREADY_INITIALIZED";
 5560 +       case CKR_MUTEX_BAD: return "CKR_MUTEX_BAD";
 5561 +       case CKR_MUTEX_NOT_LOCKED: return "CKR_MUTEX_NOT_LOCKED";
 5562 +       case CKR_FUNCTION_REJECTED: return "CKR_FUNCTION_REJECTED";
 5563 +       case CKR_VENDOR_DEFINED: return "CKR_VENDOR_DEFINED";
 5564 +       default: return "Unknown PKCS#11 error";
 5565 +   }
 5566 +}
 5567 +
 5568 +CK_RV
 5569 +pkcs11h_initialize () {
 5570 +
 5571 +#if defined(ENABLE_PKCS11H_THREADING)
 5572 +   PKCS11H_BOOL mutex_locked = FALSE;
 5573 +#endif
 5574 +   CK_RV rv = CKR_OK;
 5575 +
 5576 +   PKCS11H_DEBUG (
 5577 +       PKCS11H_LOG_DEBUG2,
 5578 +       "PKCS#11: pkcs11h_initialize entry"
 5579 +   );
 5580 +
 5581 +   pkcs11h_terminate ();
 5582 +
 5583 +   if (rv == CKR_OK) {
 5584 +       rv = _pkcs11h_mem_malloc ((void*)&s_pkcs11h_data, sizeof (struct pkcs11h_data_s));
 5585 +   }
 5586 +
 5587 +#if defined(USE_PKCS11H_OPENSSL) || defined(ENABLE_PKCS11H_OPENSSL)
 5588 +   OpenSSL_add_all_digests ();
 5589 +#endif
 5590 +#if defined(USE_PKCS11H_GNUTLS)
 5591 +   if (
 5592 +       rv == CKR_OK &&
 5593 +       gnutls_global_init () != GNUTLS_E_SUCCESS
 5594 +   ) {
 5595 +       rv = CKR_FUNCTION_FAILED;
 5596 +   }
 5597 +#endif
 5598 +
 5599 +#if defined(ENABLE_PKCS11H_THREADING)
 5600 +   if (rv == CKR_OK) {
 5601 +       rv = _pkcs11h_threading_mutexInit (&s_pkcs11h_data->mutexes.global); 
 5602 +   }
 5603 +   if (rv == CKR_OK) {
 5604 +       rv = _pkcs11h_threading_mutexInit (&s_pkcs11h_data->mutexes.session); 
 5605 +   }
 5606 +   if (rv == CKR_OK) {
 5607 +       rv = _pkcs11h_threading_mutexInit (&s_pkcs11h_data->mutexes.cache); 
 5608 +   }
 5609 +#if !defined(WIN32)
 5610 +   if (
 5611 +       rv == CKR_OK &&
 5612 +       pthread_atfork (
 5613 +           __pkcs11h_threading_atfork_prepare,
 5614 +           __pkcs11h_threading_atfork_parent,
 5615 +           __pkcs11h_threading_atfork_child
 5616 +       )
 5617 +   ) {
 5618 +       rv = CKR_FUNCTION_FAILED;
 5619 +   }
 5620 +#endif
 5621 +   if (
 5622 +       rv == CKR_OK &&
 5623 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global)) == CKR_OK
 5624 +   ) {
 5625 +       mutex_locked = TRUE;
 5626 +   }
 5627 +#endif
 5628 +
 5629 +   if (rv == CKR_OK) {
 5630 +       s_pkcs11h_data->max_retries = PKCS11H_DEFAULT_MAX_LOGIN_RETRY;
 5631 +       s_pkcs11h_data->allow_protected_auth = TRUE;
 5632 +       s_pkcs11h_data->pin_cache_period = PKCS11H_DEFAULT_PIN_CACHE_PERIOD;
 5633 +       s_pkcs11h_data->initialized = TRUE;
 5634 +   }
 5635 +
 5636 +   if (rv == CKR_OK) {
 5637 +       pkcs11h_setLogHook (_pkcs11h_hooks_default_log, NULL);
 5638 +       pkcs11h_setTokenPromptHook (_pkcs11h_hooks_default_token_prompt, NULL);
 5639 +       pkcs11h_setPINPromptHook (_pkcs11h_hooks_default_pin_prompt, NULL);
 5640 +   }
 5641 +   
 5642 +#if defined(ENABLE_PKCS11H_THREADING)
 5643 +   if (mutex_locked) {
 5644 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
 5645 +       mutex_locked = FALSE;
 5646 +   }
 5647 +#endif
 5648 +
 5649 +   PKCS11H_DEBUG (
 5650 +       PKCS11H_LOG_DEBUG2,
 5651 +       "PKCS#11: pkcs11h_initialize return rv=%ld-'%s'",
 5652 +       rv,
 5653 +       pkcs11h_getMessage (rv)
 5654 +   );
 5655 +
 5656 +   return rv;
 5657 +}
 5658 +
 5659 +CK_RV
 5660 +pkcs11h_terminate () {
 5661 +
 5662 +   PKCS11H_DEBUG (
 5663 +       PKCS11H_LOG_DEBUG2,
 5664 +       "PKCS#11: pkcs11h_terminate entry"
 5665 +   );
 5666 +
 5667 +   if (s_pkcs11h_data != NULL) {
 5668 +       pkcs11h_provider_t current_provider = NULL;
 5669 +
 5670 +       PKCS11H_DEBUG (
 5671 +           PKCS11H_LOG_DEBUG1,
 5672 +           "PKCS#11: Removing providers"
 5673 +       );
 5674 +
 5675 +       for (
 5676 +           current_provider = s_pkcs11h_data->providers;
 5677 +           current_provider != NULL;
 5678 +           current_provider = current_provider->next
 5679 +       ) {
 5680 +           pkcs11h_removeProvider (current_provider->reference);
 5681 +       }
 5682 +
 5683 +#if defined(ENABLE_PKCS11H_THREADING)
 5684 +       _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.cache);
 5685 +       _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.session);
 5686 +       _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global);
 5687 +#endif
 5688 +
 5689 +       PKCS11H_DEBUG (
 5690 +           PKCS11H_LOG_DEBUG1,
 5691 +           "PKCS#11: Releasing sessions"
 5692 +       );
 5693 +
 5694 +       while (s_pkcs11h_data->sessions != NULL) {
 5695 +           pkcs11h_session_t current = s_pkcs11h_data->sessions;
 5696 +           s_pkcs11h_data->sessions = s_pkcs11h_data->sessions->next;
 5697 +
 5698 +#if defined(ENABLE_PKCS11H_THREADING)
 5699 +           _pkcs11h_threading_mutexLock (&current->mutex);
 5700 +#endif
 5701 +
 5702 +           current->valid = FALSE;
 5703 +
 5704 +           if (current->reference_count != 0) {
 5705 +               PKCS11H_DEBUG (
 5706 +                   PKCS11H_LOG_DEBUG1,
 5707 +                   "PKCS#11: Warning: Found session with references"
 5708 +               );
 5709 +           }
 5710 +
 5711 +           if (current->token_id != NULL) {
 5712 +               pkcs11h_token_freeTokenId (current->token_id);
 5713 +               current->token_id = NULL;
 5714 +           }
 5715 +
 5716 +#if defined(ENABLE_PKCS11H_ENUM)
 5717 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
 5718 +           pkcs11h_certificate_freeCertificateIdList (current->cached_certs);
 5719 +#endif
 5720 +#endif
 5721 +
 5722 +           current->provider = NULL;
 5723 +
 5724 +#if defined(ENABLE_PKCS11H_THREADING)
 5725 +           _pkcs11h_threading_mutexFree (&current->mutex);
 5726 +#endif
 5727 +
 5728 +           _pkcs11h_mem_free ((void *)&current);
 5729 +       }
 5730 +
 5731 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 5732 +       PKCS11H_DEBUG (
 5733 +           PKCS11H_LOG_DEBUG1,
 5734 +           "PKCS#11: Terminating slotevent"
 5735 +       );
 5736 +
 5737 +       _pkcs11h_slotevent_terminate ();
 5738 +#endif
 5739 +       PKCS11H_DEBUG (
 5740 +           PKCS11H_LOG_DEBUG1,
 5741 +           "PKCS#11: Marking as uninitialized"
 5742 +       );
 5743 +       
 5744 +       s_pkcs11h_data->initialized = FALSE;
 5745 +
 5746 +       while (s_pkcs11h_data->providers != NULL) {
 5747 +           pkcs11h_provider_t current = s_pkcs11h_data->providers;
 5748 +           s_pkcs11h_data->providers = s_pkcs11h_data->providers->next;
 5749 +
 5750 +           _pkcs11h_mem_free ((void *)&current);
 5751 +       }
 5752 +
 5753 +#if defined(ENABLE_PKCS11H_THREADING)
 5754 +       _pkcs11h_threading_mutexFree (&s_pkcs11h_data->mutexes.cache);
 5755 +       _pkcs11h_threading_mutexFree (&s_pkcs11h_data->mutexes.global); 
 5756 +       _pkcs11h_threading_mutexFree (&s_pkcs11h_data->mutexes.session); 
 5757 +#endif
 5758 +
 5759 +#if defined(USE_PKCS11H_GNUTLS)
 5760 +       gnutls_global_deinit ();
 5761 +#endif
 5762 +
 5763 +       _pkcs11h_mem_free ((void *)&s_pkcs11h_data);
 5764 +   }
 5765 +
 5766 +   PKCS11H_DEBUG (
 5767 +       PKCS11H_LOG_DEBUG2,
 5768 +       "PKCS#11: pkcs11h_terminate return"
 5769 +   );
 5770 +
 5771 +   return CKR_OK;
 5772 +}
 5773 +
 5774 +void
 5775 +pkcs11h_setLogLevel (
 5776 +   IN const unsigned flags
 5777 +) {
 5778 +   s_pkcs11h_loglevel = flags;
 5779 +}
 5780 +
 5781 +unsigned
 5782 +pkcs11h_getLogLevel () {
 5783 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5784 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5785 +
 5786 +   return s_pkcs11h_loglevel;
 5787 +}
 5788 +
 5789 +CK_RV
 5790 +pkcs11h_setLogHook (
 5791 +   IN const pkcs11h_hook_log_t hook,
 5792 +   IN void * const global_data
 5793 +) {
 5794 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5795 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5796 +   PKCS11H_ASSERT (hook!=NULL);
 5797 +
 5798 +   s_pkcs11h_data->hooks.log = hook;
 5799 +   s_pkcs11h_data->hooks.log_data = global_data;
 5800 +
 5801 +   return CKR_OK;
 5802 +}
 5803 +
 5804 +CK_RV
 5805 +pkcs11h_setSlotEventHook (
 5806 +   IN const pkcs11h_hook_slotevent_t hook,
 5807 +   IN void * const global_data
 5808 +) {
 5809 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5810 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5811 +   PKCS11H_ASSERT (hook!=NULL);
 5812 +
 5813 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 5814 +   s_pkcs11h_data->hooks.slotevent = hook;
 5815 +   s_pkcs11h_data->hooks.slotevent_data = global_data;
 5816 +
 5817 +   return _pkcs11h_slotevent_init ();
 5818 +#else
 5819 +   (void)global_data;
 5820 +
 5821 +   return CKR_FUNCTION_NOT_SUPPORTED;
 5822 +#endif
 5823 +}
 5824 +
 5825 +CK_RV
 5826 +pkcs11h_setPINPromptHook (
 5827 +   IN const pkcs11h_hook_pin_prompt_t hook,
 5828 +   IN void * const global_data
 5829 +) {
 5830 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5831 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5832 +   PKCS11H_ASSERT (hook!=NULL);
 5833 +
 5834 +   s_pkcs11h_data->hooks.pin_prompt = hook;
 5835 +   s_pkcs11h_data->hooks.pin_prompt_data = global_data;
 5836 +
 5837 +   return CKR_OK;
 5838 +}
 5839 +
 5840 +CK_RV
 5841 +pkcs11h_setTokenPromptHook (
 5842 +   IN const pkcs11h_hook_token_prompt_t hook,
 5843 +   IN void * const global_data
 5844 +) {
 5845 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5846 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5847 +   PKCS11H_ASSERT (hook!=NULL);
 5848 +
 5849 +   s_pkcs11h_data->hooks.token_prompt = hook;
 5850 +   s_pkcs11h_data->hooks.token_prompt_data = global_data;
 5851 +
 5852 +   return CKR_OK;
 5853 +}
 5854 +
 5855 +CK_RV
 5856 +pkcs11h_setPINCachePeriod (
 5857 +   IN const int pin_cache_period
 5858 +) {
 5859 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5860 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5861 +
 5862 +   s_pkcs11h_data->pin_cache_period = pin_cache_period;
 5863 +
 5864 +   return CKR_OK;
 5865 +}
 5866 +
 5867 +CK_RV
 5868 +pkcs11h_setMaxLoginRetries (
 5869 +   IN const unsigned max_retries
 5870 +) {
 5871 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5872 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5873 +
 5874 +   s_pkcs11h_data->max_retries = max_retries;
 5875 +
 5876 +   return CKR_OK;
 5877 +}
 5878 +
 5879 +CK_RV
 5880 +pkcs11h_setProtectedAuthentication (
 5881 +   IN const PKCS11H_BOOL allow_protected_auth
 5882 +) {
 5883 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5884 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5885 +
 5886 +   s_pkcs11h_data->allow_protected_auth = allow_protected_auth;
 5887 +
 5888 +   return CKR_OK;
 5889 +}
 5890 +
 5891 +CK_RV
 5892 +pkcs11h_addProvider (
 5893 +   IN const char * const reference,
 5894 +   IN const char * const provider_location,
 5895 +   IN const PKCS11H_BOOL allow_protected_auth,
 5896 +   IN const unsigned mask_sign_mode,
 5897 +   IN const int slot_event_method,
 5898 +   IN const int slot_poll_interval,
 5899 +   IN const PKCS11H_BOOL cert_is_private
 5900 +) {
 5901 +#if defined(ENABLE_PKCS11H_THREADING)
 5902 +   PKCS11H_BOOL mutex_locked = FALSE;
 5903 +#endif
 5904 +#if defined(WIN32)
 5905 +   int mypid = 0;
 5906 +#else
 5907 +   pid_t mypid = getpid ();
 5908 +#endif
 5909 +   pkcs11h_provider_t provider = NULL;
 5910 +   CK_C_GetFunctionList gfl = NULL;
 5911 +   CK_INFO info;
 5912 +   CK_RV rv = CKR_OK;
 5913 +
 5914 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 5915 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 5916 +   PKCS11H_ASSERT (provider_location!=NULL);
 5917 +   /*PKCS11H_ASSERT (szSignMode!=NULL); NOT NEEDED*/
 5918 +
 5919 +   PKCS11H_DEBUG (
 5920 +       PKCS11H_LOG_DEBUG2,
 5921 +       "PKCS#11: pkcs11h_addProvider entry pid=%d, reference='%s', provider_location='%s', allow_protected_auth=%d,
	mask_sign_mode=%08x, cert_is_private=%d",
 5922 +       mypid,
 5923 +       reference,
 5924 +       provider_location,
 5925 +       allow_protected_auth ? 1 : 0,
 5926 +       mask_sign_mode,
 5927 +       cert_is_private ? 1 : 0
 5928 +   );
 5929 +
 5930 +   PKCS11H_DEBUG (
 5931 +       PKCS11H_LOG_DEBUG1,
 5932 +       "PKCS#11: Adding provider '%s'-'%s'",
 5933 +       reference,
 5934 +       provider_location
 5935 +   );
 5936 +
 5937 +#if defined(ENABLE_PKCS11H_THREADING)
 5938 +   if (
 5939 +       rv == CKR_OK &&
 5940 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global)) == CKR_OK
 5941 +   ) {
 5942 +       mutex_locked = TRUE;
 5943 +   }
 5944 +#endif
 5945 +
 5946 +   if (
 5947 +       rv == CKR_OK &&
 5948 +       (rv = _pkcs11h_mem_malloc ((void *)&provider, sizeof (struct pkcs11h_provider_s))) == CKR_OK
 5949 +   ) {
 5950 +       strncpy (
 5951 +           provider->reference,
 5952 +           reference,
 5953 +           sizeof (provider->reference)-1
 5954 +       );
 5955 +       provider->reference[sizeof (provider->reference)-1] = '\x0';
 5956 +       strncpy (
 5957 +           provider->manufacturerID,
 5958 +           (
 5959 +               strlen (provider_location) < sizeof (provider->manufacturerID) ?
 5960 +               provider_location :
 5961 +               provider_location+strlen (provider_location)-sizeof (provider->manufacturerID)+1
 5962 +           ),
 5963 +           sizeof (provider->manufacturerID)-1
 5964 +       );
 5965 +       provider->manufacturerID[sizeof (provider->manufacturerID)-1] = '\x0';
 5966 +       provider->allow_protected_auth = allow_protected_auth;
 5967 +       provider->mask_sign_mode = mask_sign_mode;
 5968 +       provider->slot_event_method = slot_event_method;
 5969 +       provider->slot_poll_interval = slot_poll_interval;
 5970 +       provider->cert_is_private = cert_is_private;
 5971 +   }
 5972 +       
 5973 +   if (rv == CKR_OK) {
 5974 +#if defined(WIN32)
 5975 +       provider->handle = LoadLibraryA (provider_location);
 5976 +#else
 5977 +       provider->handle = dlopen (provider_location, RTLD_NOW);
 5978 +#endif
 5979 +       if (provider->handle == NULL) {
 5980 +           rv = CKR_FUNCTION_FAILED;
 5981 +       }
 5982 +   }
 5983 +
 5984 +   if (rv == CKR_OK) {
 5985 +#if defined(WIN32)
 5986 +       gfl = (CK_C_GetFunctionList)GetProcAddress (
 5987 +           provider->handle,
 5988 +           "C_GetFunctionList"
 5989 +       );
 5990 +#else
 5991 +       /*
 5992 +        * Make compiler happy!
 5993 +        */
 5994 +       void *p = dlsym (
 5995 +           provider->handle,
 5996 +           "C_GetFunctionList"
 5997 +       );
 5998 +       memmove (
 5999 +           &gfl, 
 6000 +           &p,
 6001 +           sizeof (void *)
 6002 +       );
 6003 +#endif
 6004 +       if (gfl == NULL) {
 6005 +           rv = CKR_FUNCTION_FAILED;
 6006 +       }
 6007 +   }
 6008 +
 6009 +   if (rv == CKR_OK) {
 6010 +       rv = gfl (&provider->f);
 6011 +   }
 6012 +
 6013 +   if (rv == CKR_OK) {
 6014 +       if ((rv = provider->f->C_Initialize (NULL)) != CKR_OK) {
 6015 +           if (rv == CKR_CRYPTOKI_ALREADY_INITIALIZED) {
 6016 +               rv = CKR_OK;
 6017 +           }
 6018 +       }
 6019 +       else {
 6020 +           provider->should_finalize = TRUE;
 6021 +       }
 6022 +   }
 6023 +
 6024 +   if (
 6025 +       rv == CKR_OK &&
 6026 +       (rv = provider->f->C_GetInfo (&info)) == CKR_OK
 6027 +   ) {
 6028 +       _pkcs11h_util_fixupFixedString (
 6029 +           provider->manufacturerID,
 6030 +           (char *)info.manufacturerID,
 6031 +           sizeof (info.manufacturerID)
 6032 +       );
 6033 +   }
 6034 +
 6035 +   if (rv == CKR_OK) {
 6036 +       provider->enabled = TRUE;
 6037 +   }
 6038 +
 6039 +   if (provider != NULL) {
 6040 +       if (s_pkcs11h_data->providers == NULL) {
 6041 +           s_pkcs11h_data->providers = provider;
 6042 +       }
 6043 +       else {
 6044 +           pkcs11h_provider_t last = NULL;
 6045 +   
 6046 +           for (
 6047 +               last = s_pkcs11h_data->providers;
 6048 +               last->next != NULL;
 6049 +               last = last->next
 6050 +           );
 6051 +           last->next = provider;
 6052 +       }
 6053 +   }
 6054 +
 6055 +#if defined(ENABLE_PKCS11H_THREADING)
 6056 +   if (mutex_locked) {
 6057 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
 6058 +       mutex_locked = FALSE;
 6059 +   }
 6060 +#endif
 6061 +
 6062 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 6063 +   _pkcs11h_slotevent_notify ();
 6064 +#endif
 6065 +
 6066 +   PKCS11H_DEBUG (
 6067 +       PKCS11H_LOG_DEBUG1,
 6068 +       "PKCS#11: Provider '%s' added rv=%ld-'%s'",
 6069 +       reference,
 6070 +       rv,
 6071 +       pkcs11h_getMessage (rv)
 6072 +   );
 6073 +
 6074 +   PKCS11H_DEBUG (
 6075 +       PKCS11H_LOG_DEBUG2,
 6076 +       "PKCS#11: pkcs11h_addProvider return rv=%ld-'%s'",
 6077 +       rv,
 6078 +       pkcs11h_getMessage (rv)
 6079 +   );
 6080 +
 6081 +   return rv;
 6082 +}
 6083 +
 6084 +CK_RV
 6085 +pkcs11h_removeProvider (
 6086 +   IN const char * const reference
 6087 +) {
 6088 +#if defined(ENABLE_PKCS11H_THREADING)
 6089 +   pkcs11h_session_t current_session = NULL;
 6090 +#endif
 6091 +   pkcs11h_provider_t provider = NULL;
 6092 +   CK_RV rv = CKR_OK;
 6093 +
 6094 +   PKCS11H_ASSERT (reference!=NULL);
 6095 +
 6096 +   PKCS11H_DEBUG (
 6097 +       PKCS11H_LOG_DEBUG2,
 6098 +       "PKCS#11: pkcs11h_removeProvider entry reference='%s'",
 6099 +       reference
 6100 +   );
 6101 +
 6102 +   PKCS11H_DEBUG (
 6103 +       PKCS11H_LOG_DEBUG1,
 6104 +       "PKCS#11: Removing provider '%s'",
 6105 +       reference
 6106 +   );
 6107 +
 6108 +#if defined(ENABLE_PKCS11H_THREADING)
 6109 +   _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.cache);
 6110 +   _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.session);
 6111 +   _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global);
 6112 +
 6113 +   for (
 6114 +       current_session = s_pkcs11h_data->sessions;
 6115 +       current_session != NULL;
 6116 +       current_session = current_session->next
 6117 +   ) {
 6118 +       _pkcs11h_threading_mutexLock (&current_session->mutex);
 6119 +   }
 6120 +#endif
 6121 +
 6122 +   provider = s_pkcs11h_data->providers;
 6123 +   while (
 6124 +       rv == CKR_OK &&
 6125 +       provider != NULL &&
 6126 +       strcmp (reference, provider->reference)
 6127 +   ) {
 6128 +       provider = provider->next;
 6129 +   }
 6130 +
 6131 +   if (rv == CKR_OK && provider == NULL) {
 6132 +       rv = CKR_OBJECT_HANDLE_INVALID;
 6133 +   }
 6134 +
 6135 +   if (rv == CKR_OK) {
 6136 +       provider->enabled = FALSE;
 6137 +       provider->reference[0] = '\0';
 6138 +
 6139 +       if (provider->should_finalize) {
 6140 +           provider->f->C_Finalize (NULL);
 6141 +           provider->should_finalize = FALSE;
 6142 +       }
 6143 +
 6144 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 6145 +       _pkcs11h_slotevent_notify ();
 6146 +       
 6147 +       /*
 6148 +        * Wait until manager join this thread
 6149 +        * this happens saldom so I can poll
 6150 +        */
 6151 +       while (provider->slotevent_thread != PKCS11H_THREAD_NULL) {
 6152 +           _pkcs11h_threading_sleep (500);
 6153 +       }
 6154 +#endif
 6155 +
 6156 +       if (provider->f != NULL) {
 6157 +           provider->f = NULL;
 6158 +       }
 6159 +
 6160 +       if (provider->handle != NULL) {
 6161 +#if defined(WIN32)
 6162 +           FreeLibrary (provider->handle);
 6163 +#else
 6164 +           dlclose (provider->handle);
 6165 +#endif
 6166 +           provider->handle = NULL;
 6167 +       }
 6168 +   }
 6169 +
 6170 +#if defined(ENABLE_PKCS11H_THREADING)
 6171 +   for (
 6172 +       current_session = s_pkcs11h_data->sessions;
 6173 +       current_session != NULL;
 6174 +       current_session = current_session->next
 6175 +   ) {
 6176 +       _pkcs11h_threading_mutexRelease (&current_session->mutex);
 6177 +   }
 6178 +
 6179 +   _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.cache);
 6180 +   _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.session);
 6181 +   _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
 6182 +#endif
 6183 +   
 6184 +   PKCS11H_DEBUG (
 6185 +       PKCS11H_LOG_DEBUG2,
 6186 +       "PKCS#11: pkcs11h_removeProvider return rv=%ld-'%s'",
 6187 +       rv,
 6188 +       pkcs11h_getMessage (rv)
 6189 +   );
 6190 +
 6191 +   return rv;
 6192 +}
 6193 +
 6194 +CK_RV
 6195 +pkcs11h_forkFixup () {
 6196 +#if defined(WIN32)
 6197 +   return CKR_OK;
 6198 +#else
 6199 +#if defined(ENABLE_PKCS11H_THREADING)
 6200 +   return CKR_OK;
 6201 +#else
 6202 +   return _pkcs11h_forkFixup ();
 6203 +#endif
 6204 +#endif
 6205 +}
 6206 +
 6207 +CK_RV
 6208 +pkcs11h_plugAndPlay () {
 6209 +#if defined(WIN32)
 6210 +   int mypid = 0;
 6211 +#else
 6212 +   pid_t mypid = getpid ();
 6213 +#endif
 6214 +
 6215 +   PKCS11H_DEBUG (
 6216 +       PKCS11H_LOG_DEBUG2,
 6217 +       "PKCS#11: pkcs11h_forkFixup entry pid=%d",
 6218 +       mypid
 6219 +   );
 6220 +
 6221 +   if (s_pkcs11h_data != NULL && s_pkcs11h_data->initialized) {
 6222 +       pkcs11h_provider_t current;
 6223 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 6224 +       PKCS11H_BOOL slot_event_active = FALSE;
 6225 +#endif
 6226 +
 6227 +#if defined(ENABLE_PKCS11H_THREADING)
 6228 +       _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global);
 6229 +#endif
 6230 +       for (
 6231 +           current = s_pkcs11h_data->providers;
 6232 +           current != NULL;
 6233 +           current = current->next
 6234 +       ) {
 6235 +           if (current->enabled) {
 6236 +               current->f->C_Finalize (NULL);
 6237 +           }
 6238 +       }
 6239 +
 6240 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 6241 +       if (s_pkcs11h_data->slotevent.initialized) {
 6242 +           slot_event_active = TRUE;
 6243 +           _pkcs11h_slotevent_terminate ();
 6244 +       }
 6245 +#endif
 6246 +
 6247 +       for (
 6248 +           current = s_pkcs11h_data->providers;
 6249 +           current != NULL;
 6250 +           current = current->next
 6251 +       ) {
 6252 +           if (current->enabled) {
 6253 +               current->f->C_Initialize (NULL);
 6254 +           }
 6255 +       }
 6256 +
 6257 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 6258 +       if (slot_event_active) {
 6259 +           _pkcs11h_slotevent_init ();
 6260 +       }
 6261 +#endif
 6262 +
 6263 +#if defined(ENABLE_PKCS11H_THREADING)
 6264 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
 6265 +#endif
 6266 +   }
 6267 +
 6268 +   PKCS11H_DEBUG (
 6269 +       PKCS11H_LOG_DEBUG2,
 6270 +       "PKCS#11: pkcs11h_forkFixup return"
 6271 +   );
 6272 +
 6273 +   return CKR_OK;
 6274 +}
 6275 +
 6276 +CK_RV
 6277 +pkcs11h_token_freeTokenId (
 6278 +   IN pkcs11h_token_id_t token_id
 6279 +) {
 6280 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 6281 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 6282 +   PKCS11H_ASSERT (token_id!=NULL);
 6283 +
 6284 +   PKCS11H_DEBUG (
 6285 +       PKCS11H_LOG_DEBUG2,
 6286 +       "PKCS#11: pkcs11h_token_freeTokenId entry certificate_id=%p",
 6287 +       (void *)token_id
 6288 +   );
 6289 +
 6290 +   _pkcs11h_mem_free ((void *)&token_id);
 6291 +
 6292 +   PKCS11H_DEBUG (
 6293 +       PKCS11H_LOG_DEBUG2,
 6294 +       "PKCS#11: pkcs11h_token_freeTokenId return"
 6295 +   );
 6296 +
 6297 +   return CKR_OK;
 6298 +}
 6299 +
 6300 +CK_RV
 6301 +pkcs11h_token_duplicateTokenId (
 6302 +   OUT pkcs11h_token_id_t * const to,
 6303 +   IN const pkcs11h_token_id_t from
 6304 +) {
 6305 +   CK_RV rv = CKR_OK;
 6306 +
 6307 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 6308 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 6309 +   PKCS11H_ASSERT (to!=NULL);
 6310 +   PKCS11H_ASSERT (from!=NULL);
 6311 +
 6312 +   PKCS11H_DEBUG (
 6313 +       PKCS11H_LOG_DEBUG2,
 6314 +       "PKCS#11: pkcs11h_token_duplicateTokenId entry to=%p form=%p",
 6315 +       (void *)to,
 6316 +       (void *)from
 6317 +   );
 6318 +
 6319 +   *to = NULL;
 6320 +
 6321 +   if (rv == CKR_OK) {
 6322 +       rv = _pkcs11h_mem_duplicate (
 6323 +           (void*)to,
 6324 +           NULL,
 6325 +           from,
 6326 +           sizeof (struct pkcs11h_token_id_s)
 6327 +       );
 6328 +   }
 6329 +
 6330 +   PKCS11H_DEBUG (
 6331 +       PKCS11H_LOG_DEBUG2,
 6332 +       "PKCS#11: pkcs11h_token_duplicateTokenId return rv=%ld-'%s', *to=%p",
 6333 +       rv,
 6334 +       pkcs11h_getMessage (rv),
 6335 +       (void *)*to
 6336 +   );
 6337 +   
 6338 +   return rv;
 6339 +}
 6340 +
 6341 +PKCS11H_BOOL
 6342 +pkcs11h_token_sameTokenId (
 6343 +   IN const pkcs11h_token_id_t a,
 6344 +   IN const pkcs11h_token_id_t b
 6345 +) {
 6346 +   PKCS11H_ASSERT (a!=NULL);
 6347 +   PKCS11H_ASSERT (b!=NULL);
 6348 +
 6349 +   return (
 6350 +       !strcmp (a->manufacturerID, b->manufacturerID) &&
 6351 +       !strcmp (a->model, b->model) &&
 6352 +       !strcmp (a->serialNumber, b->serialNumber) &&
 6353 +       !strcmp (a->label, b->label)
 6354 +   );
 6355 +}
 6356 +
 6357 +#if defined(ENABLE_PKCS11H_SERIALIZATION)
 6358 +
 6359 +CK_RV
 6360 +pkcs11h_token_serializeTokenId (
 6361 +   OUT char * const sz,
 6362 +   IN OUT size_t *max,
 6363 +   IN const pkcs11h_token_id_t token_id
 6364 +) {
 6365 +   const char *sources[5];
 6366 +   CK_RV rv = CKR_OK;
 6367 +   size_t n;
 6368 +   int e;
 6369 +
 6370 +   /*PKCS11H_ASSERT (sz!=NULL); Not required*/
 6371 +   PKCS11H_ASSERT (max!=NULL);
 6372 +   PKCS11H_ASSERT (token_id!=NULL);
 6373 +
 6374 +   { /* Must be after assert */
 6375 +       sources[0] = token_id->manufacturerID;
 6376 +       sources[1] = token_id->model;
 6377 +       sources[2] = token_id->serialNumber;
 6378 +       sources[3] = token_id->label;
 6379 +       sources[4] = NULL;
 6380 +   }
 6381 +
 6382 +   PKCS11H_DEBUG (
 6383 +       PKCS11H_LOG_DEBUG2,
 6384 +       "PKCS#11: pkcs11h_token_serializeTokenId entry sz=%p, *max=%u, token_id=%p",
 6385 +       sz,
 6386 +       sz != NULL ? *max : 0,
 6387 +       (void *)token_id
 6388 +   );
 6389 +
 6390 +   n = 0;
 6391 +   for (e=0;rv == CKR_OK && sources[e] != NULL;e++) {
 6392 +       size_t t;
 6393 +       rv = _pkcs11h_util_escapeString (NULL, sources[e], &t, PKCS11H_SERIALIZE_INVALID_CHARS);
 6394 +       n+=t;
 6395 +   }
 6396 +
 6397 +   if (sz != NULL) {
 6398 +       if (*max < n) {
 6399 +           rv = CKR_ATTRIBUTE_VALUE_INVALID;
 6400 +       }
 6401 +       else {
 6402 +           n = 0;
 6403 +           for (e=0;sources[e] != NULL;e++) {
 6404 +               size_t t = *max-n;
 6405 +               _pkcs11h_util_escapeString (sz+n, sources[e], &t, PKCS11H_SERIALIZE_INVALID_CHARS);
 6406 +               n+=t;
 6407 +               sz[n-1] = '/';
 6408 +           }
 6409 +           sz[n-1] = '\x0';
 6410 +       }
 6411 +   }
 6412 +
 6413 +   *max = n;
 6414 +
 6415 +   PKCS11H_DEBUG (
 6416 +       PKCS11H_LOG_DEBUG2,
 6417 +       "PKCS#11: pkcs11h_token_serializeTokenId return rv=%ld-'%s', *max=%u, sz='%s'",
 6418 +       rv,
 6419 +       pkcs11h_getMessage (rv),
 6420 +       *max,
 6421 +       sz
 6422 +   );
 6423 +
 6424 +   return rv;
 6425 +}
 6426 +
 6427 +CK_RV
 6428 +pkcs11h_token_deserializeTokenId (
 6429 +   OUT pkcs11h_token_id_t *p_token_id,
 6430 +   IN const char * const sz
 6431 +) {
 6432 +#define __PKCS11H_TARGETS_NUMBER 4
 6433 +   struct {
 6434 +       char *p;
 6435 +       size_t s;
 6436 +   } targets[__PKCS11H_TARGETS_NUMBER];
 6437 +
 6438 +   pkcs11h_token_id_t token_id = NULL;
 6439 +   char *p1 = NULL;
 6440 +   char *_sz = NULL;
 6441 +   int e;
 6442 +   CK_RV rv = CKR_OK;
 6443 +
 6444 +   PKCS11H_ASSERT (p_token_id!=NULL);
 6445 +   PKCS11H_ASSERT (sz!=NULL);
 6446 +
 6447 +   PKCS11H_DEBUG (
 6448 +       PKCS11H_LOG_DEBUG2,
 6449 +       "PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'",
 6450 +       (void *)p_token_id,
 6451 +       sz
 6452 +   );
 6453 +
 6454 +   *p_token_id = NULL;
 6455 +
 6456 +   if (rv == CKR_OK) {
 6457 +       rv = _pkcs11h_mem_strdup (
 6458 +           (void *)&_sz,
 6459 +           sz
 6460 +       );
 6461 +   }
 6462 +
 6463 +   if (rv == CKR_OK) {
 6464 +       p1 = _sz;
 6465 +   }
 6466 +
 6467 +   if (
 6468 +       rv == CKR_OK &&
 6469 +       (rv = _pkcs11h_token_newTokenId (&token_id)) == CKR_OK
 6470 +   ) {
 6471 +       targets[0].p = token_id->manufacturerID;
 6472 +       targets[0].s = sizeof (token_id->manufacturerID);
 6473 +       targets[1].p = token_id->model;
 6474 +       targets[1].s = sizeof (token_id->model);
 6475 +       targets[2].p = token_id->serialNumber;
 6476 +       targets[2].s = sizeof (token_id->serialNumber);
 6477 +       targets[3].p = token_id->label;
 6478 +       targets[3].s = sizeof (token_id->label);
 6479 +   }
 6480 +
 6481 +   for (e=0;rv == CKR_OK && e < __PKCS11H_TARGETS_NUMBER;e++) {
 6482 +       size_t l;
 6483 +       char *p2 = NULL;
 6484 +
 6485 +       /*
 6486 +        * Don't search for last
 6487 +        * separator
 6488 +        */
 6489 +       if (rv == CKR_OK) {
 6490 +           if (e != __PKCS11H_TARGETS_NUMBER-1) {
 6491 +               p2 = strchr (p1, '/');
 6492 +               if (p2 == NULL) {
 6493 +                   rv = CKR_ATTRIBUTE_VALUE_INVALID;
 6494 +               }
 6495 +               else {
 6496 +                   *p2 = '\x0';
 6497 +               }
 6498 +           }
 6499 +       }
 6500 +
 6501 +       if (rv == CKR_OK) {
 6502 +           _pkcs11h_util_unescapeString (
 6503 +               NULL,
 6504 +               p1,
 6505 +               &l
 6506 +           );
 6507 +       }
 6508 +
 6509 +       if (rv == CKR_OK) {
 6510 +           if (l > targets[e].s) {
 6511 +               rv = CKR_ATTRIBUTE_VALUE_INVALID;
 6512 +           }
 6513 +       }
 6514 +
 6515 +       if (rv == CKR_OK) {
 6516 +           l = targets[e].s;
 6517 +           _pkcs11h_util_unescapeString (
 6518 +               targets[e].p,
 6519 +               p1,
 6520 +               &l
 6521 +           );
 6522 +       }
 6523 +
 6524 +       if (rv == CKR_OK) {
 6525 +           p1 = p2+1;
 6526 +       }
 6527 +   }
 6528 +
 6529 +   if (rv == CKR_OK) {
 6530 +       strncpy (
 6531 +           token_id->display,
 6532 +           token_id->label,
 6533 +           sizeof (token_id->display)
 6534 +       );
 6535 +   }
 6536 +
 6537 +   if (rv == CKR_OK) {
 6538 +       *p_token_id = token_id;
 6539 +       token_id = NULL;
 6540 +   }
 6541 +
 6542 +   if (_sz != NULL) {
 6543 +       _pkcs11h_mem_free ((void *)&_sz);
 6544 +   }
 6545 +
 6546 +   if (token_id != NULL) {
 6547 +       pkcs11h_token_freeTokenId (token_id);
 6548 +   }
 6549 +
 6550 +   return rv;
 6551 +#undef __PKCS11H_TARGETS_NUMBER
 6552 +}
 6553 +
 6554 +#endif             /* ENABLE_PKCS11H_SERIALIZATION */
 6555 +
 6556 +/*======================================================================*
 6557 + * MEMORY INTERFACE
 6558 + *======================================================================*/
 6559 +
 6560 +static
 6561 +CK_RV
 6562 +_pkcs11h_mem_malloc (
 6563 +   OUT const void * * const p,
 6564 +   IN const size_t s
 6565 +) {
 6566 +   CK_RV rv = CKR_OK;
 6567 +
 6568 +   PKCS11H_ASSERT (p!=NULL);
 6569 +   PKCS11H_ASSERT (s!=0);
 6570 +
 6571 +   *p = NULL;
 6572 +
 6573 +   if (s > 0) {
 6574 +       if (
 6575 +           (*p = (void *)PKCS11H_MALLOC (s)) == NULL
 6576 +       ) {
 6577 +           rv = CKR_HOST_MEMORY;
 6578 +       }
 6579 +       else {
 6580 +           memset ((void *)*p, 0, s);
 6581 +       }
 6582 +   }
 6583 +
 6584 +   return rv;
 6585 +}
 6586 +
 6587 +static
 6588 +CK_RV
 6589 +_pkcs11h_mem_free (
 6590 +   IN const void * * const  p
 6591 +) {
 6592 +   PKCS11H_ASSERT (p!=NULL);
 6593 +
 6594 +   PKCS11H_FREE ((void *)*p);
 6595 +   *p = NULL;
 6596 +
 6597 +   return CKR_OK;
 6598 +}
 6599 +
 6600 +static
 6601 +CK_RV
 6602 +_pkcs11h_mem_strdup (
 6603 +   OUT const char * * const dest,
 6604 +   IN const char * const src
 6605 +) {
 6606 +   return _pkcs11h_mem_duplicate (
 6607 +       (void *)dest,
 6608 +       NULL,
 6609 +       src,
 6610 +       strlen (src)+1
 6611 +   );
 6612 +}
 6613 +
 6614 +static
 6615 +CK_RV
 6616 +_pkcs11h_mem_duplicate (
 6617 +   OUT const void * * const dest,
 6618 +   OUT size_t * const p_dest_size,
 6619 +   IN const void * const src,
 6620 +   IN const size_t mem_size
 6621 +) {
 6622 +   CK_RV rv = CKR_OK;
 6623 +
 6624 +   PKCS11H_ASSERT (dest!=NULL);
 6625 +   /*PKCS11H_ASSERT (dest_size!=NULL); NOT NEEDED*/
 6626 +   PKCS11H_ASSERT (!(mem_size!=0&&src==NULL));
 6627 +
 6628 +   *dest = NULL;
 6629 +   if (p_dest_size != NULL) {
 6630 +       *p_dest_size = 0;
 6631 +   }
 6632 +
 6633 +   if (src != NULL) {
 6634 +       if (
 6635 +           rv == CKR_OK &&
 6636 +           (rv = _pkcs11h_mem_malloc (dest, mem_size)) == CKR_OK
 6637 +       ) {
 6638 +           if (p_dest_size != NULL) {
 6639 +               *p_dest_size = mem_size;
 6640 +           }
 6641 +           memmove ((void*)*dest, src, mem_size);
 6642 +       }
 6643 +   }
 6644 +
 6645 +   return rv;
 6646 +}
 6647 +
 6648 +#if defined(ENABLE_PKCS11H_THREADING)
 6649 +/*======================================================================*
 6650 + * THREADING INTERFACE
 6651 + *======================================================================*/
 6652 +
 6653 +static
 6654 +void
 6655 +_pkcs11h_threading_sleep (
 6656 +   IN const unsigned milli
 6657 +) {
 6658 +#if defined(WIN32)
 6659 +   Sleep (milli);
 6660 +#else
 6661 +   usleep (milli*1000);
 6662 +#endif
 6663 +}
 6664 +
 6665 +static
 6666 +CK_RV
 6667 +_pkcs11h_threading_mutexInit (
 6668 +   OUT pkcs11h_mutex_t * const mutex
 6669 +) {
 6670 +   CK_RV rv = CKR_OK;
 6671 +#if defined(WIN32)
 6672 +   if (
 6673 +       rv == CKR_OK &&
 6674 +       (*mutex = CreateMutex (NULL, FALSE, NULL)) == NULL
 6675 +   ) {
 6676 +       rv = CKR_FUNCTION_FAILED;
 6677 +   }
 6678 +#else
 6679 +   {
 6680 +       __pkcs11h_threading_mutex_entry_t entry = NULL;
 6681 +       PKCS11H_BOOL mutex_locked = FALSE;
 6682 +
 6683 +       if (
 6684 +           rv == CKR_OK &&
 6685 +           (rv = _pkcs11h_threading_mutexLock (&__s_pkcs11h_threading_mutex_list.mutex)) == CKR_OK
 6686 +       ) {
 6687 +           mutex_locked = TRUE;
 6688 +       }
 6689 +       
 6690 +       if (rv == CKR_OK) {
 6691 +           rv = _pkcs11h_mem_malloc (
 6692 +               (void *)&entry,
 6693 +               sizeof (struct __pkcs11h_threading_mutex_entry_s)
 6694 +           );
 6695 +       }
 6696 +
 6697 +       if (
 6698 +           rv == CKR_OK &&
 6699 +           pthread_mutex_init (mutex, NULL)
 6700 +       ) {
 6701 +           rv = CKR_FUNCTION_FAILED;
 6702 +       }
 6703 +
 6704 +       if (rv == CKR_OK) {
 6705 +           entry->p_mutex = mutex;
 6706 +           entry->next = __s_pkcs11h_threading_mutex_list.head;
 6707 +           __s_pkcs11h_threading_mutex_list.head = entry;
 6708 +           entry = NULL;
 6709 +       }
 6710 +
 6711 +       if (entry != NULL) {
 6712 +           _pkcs11h_mem_free ((void *)&entry);
 6713 +       }
 6714 +
 6715 +       if (mutex_locked) {
 6716 +           _pkcs11h_threading_mutexRelease (&__s_pkcs11h_threading_mutex_list.mutex);
 6717 +           mutex_locked = FALSE;
 6718 +       }
 6719 +   }
 6720 +#endif
 6721 +   return rv;
 6722 +}
 6723 +
 6724 +static
 6725 +CK_RV
 6726 +_pkcs11h_threading_mutexLock (
 6727 +   IN OUT pkcs11h_mutex_t *const mutex
 6728 +) {
 6729 +   CK_RV rv = CKR_OK;
 6730 +#if defined(WIN32)
 6731 +   if (
 6732 +       rv == CKR_OK &&
 6733 +       WaitForSingleObject (*mutex, INFINITE) == WAIT_FAILED
 6734 +   ) {
 6735 +       rv = CKR_FUNCTION_FAILED;
 6736 +   }
 6737 +#else
 6738 +   if (
 6739 +       rv == CKR_OK &&
 6740 +       pthread_mutex_lock (mutex)
 6741 +   ) {
 6742 +       rv = CKR_FUNCTION_FAILED;
 6743 +   }
 6744 +#endif
 6745 +   return rv;
 6746 +}
 6747 +
 6748 +static
 6749 +CK_RV
 6750 +_pkcs11h_threading_mutexRelease (
 6751 +   IN OUT pkcs11h_mutex_t *const mutex
 6752 +) {
 6753 +   CK_RV rv = CKR_OK;
 6754 +#if defined(WIN32)
 6755 +   if (
 6756 +       rv == CKR_OK &&
 6757 +       !ReleaseMutex (*mutex)
 6758 +   ) {
 6759 +       rv = CKR_FUNCTION_FAILED;
 6760 +   }
 6761 +#else
 6762 +   if (
 6763 +       rv == CKR_OK &&
 6764 +       pthread_mutex_unlock (mutex)
 6765 +   ) {
 6766 +       rv = CKR_FUNCTION_FAILED;
 6767 +   }
 6768 +#endif
 6769 +   return rv;
 6770 +}
 6771 +
 6772 +static
 6773 +CK_RV
 6774 +_pkcs11h_threading_mutexFree (
 6775 +   IN OUT pkcs11h_mutex_t *const mutex
 6776 +) {
 6777 +#if defined(WIN32)
 6778 +   if (*mutex != NULL) {
 6779 +       CloseHandle (*mutex);
 6780 +       *mutex = NULL;
 6781 +   }
 6782 +#else
 6783 +   {
 6784 +       __pkcs11h_threading_mutex_entry_t last = NULL;
 6785 +       __pkcs11h_threading_mutex_entry_t entry = NULL;
 6786 +       PKCS11H_BOOL mutex_locked = FALSE;
 6787 +
 6788 +       if (_pkcs11h_threading_mutexLock (&__s_pkcs11h_threading_mutex_list.mutex) == CKR_OK) {
 6789 +           mutex_locked = TRUE;
 6790 +       }
 6791 +
 6792 +       entry =  __s_pkcs11h_threading_mutex_list.head;
 6793 +       while (
 6794 +           entry != NULL &&
 6795 +           entry->p_mutex != mutex
 6796 +       ) {
 6797 +           last = entry;
 6798 +           entry = entry->next;
 6799 +       }
 6800 +
 6801 +       if (entry != NULL) {
 6802 +           if (last == NULL) {
 6803 +               __s_pkcs11h_threading_mutex_list.head = entry->next;
 6804 +           }
 6805 +           else {
 6806 +               last->next = entry->next;
 6807 +           }
 6808 +           _pkcs11h_mem_free ((void *)&entry);
 6809 +       }
 6810 +
 6811 +       pthread_mutex_destroy (mutex);
 6812 +
 6813 +       if (mutex_locked) {
 6814 +           _pkcs11h_threading_mutexRelease (&__s_pkcs11h_threading_mutex_list.mutex);
 6815 +           mutex_locked = FALSE;
 6816 +       }
 6817 +   }
 6818 +#endif
 6819 +   return CKR_OK;
 6820 +}
 6821 +
 6822 +#if !defined(WIN32)
 6823 +/*
 6824 + * This function is required in order
 6825 + * to lock all mutexes before fork is called,
 6826 + * and to avoid dedlocks.
 6827 + * The loop is required because there is no
 6828 + * way to lock all mutex in one system call...
 6829 + */
 6830 +static
 6831 +void
 6832 +__pkcs1h_threading_mutexLockAll () {
 6833 +   __pkcs11h_threading_mutex_entry_t entry = NULL;
 6834 +   PKCS11H_BOOL mutex_locked = FALSE;
 6835 +   PKCS11H_BOOL all_mutexes_locked = FALSE;
 6836 +
 6837 +   if (_pkcs11h_threading_mutexLock (&__s_pkcs11h_threading_mutex_list.mutex) == CKR_OK) {
 6838 +       mutex_locked = TRUE;
 6839 +   }
 6840 +
 6841 +   for (
 6842 +       entry = __s_pkcs11h_threading_mutex_list.head;
 6843 +       entry != NULL;
 6844 +       entry = entry->next
 6845 +   ) {
 6846 +       entry->locked = FALSE;
 6847 +   }
 6848 +
 6849 +   while (!all_mutexes_locked) {
 6850 +       PKCS11H_BOOL ok = TRUE;
 6851 +       
 6852 +       for (
 6853 +           entry = __s_pkcs11h_threading_mutex_list.head;
 6854 +           entry != NULL && ok;
 6855 +           entry = entry->next
 6856 +       ) {
 6857 +           if (!pthread_mutex_trylock (entry->p_mutex)) {
 6858 +               entry->locked = TRUE;
 6859 +           }
 6860 +           else {
 6861 +               ok = FALSE;
 6862 +           }
 6863 +       }
 6864 +
 6865 +       if (!ok) {
 6866 +           for (
 6867 +               entry = __s_pkcs11h_threading_mutex_list.head;
 6868 +               entry != NULL;
 6869 +               entry = entry->next
 6870 +           ) {
 6871 +               if (entry->locked == TRUE) {
 6872 +                   pthread_mutex_unlock (entry->p_mutex);
 6873 +                   entry->locked = FALSE;
 6874 +               }
 6875 +           }
 6876 +
 6877 +           _pkcs11h_threading_mutexRelease (&__s_pkcs11h_threading_mutex_list.mutex);
 6878 +           _pkcs11h_threading_sleep (1000);
 6879 +           _pkcs11h_threading_mutexLock (&__s_pkcs11h_threading_mutex_list.mutex);
 6880 +       }
 6881 +       else {
 6882 +           all_mutexes_locked  = TRUE;
 6883 +       }
 6884 +   }
 6885 +
 6886 +   if (mutex_locked) {
 6887 +       _pkcs11h_threading_mutexRelease (&__s_pkcs11h_threading_mutex_list.mutex);
 6888 +       mutex_locked = FALSE;
 6889 +   }
 6890 +}
 6891 +
 6892 +static
 6893 +void
 6894 +__pkcs1h_threading_mutexReleaseAll () {
 6895 +   __pkcs11h_threading_mutex_entry_t entry = NULL;
 6896 +   PKCS11H_BOOL mutex_locked = FALSE;
 6897 +
 6898 +   if (_pkcs11h_threading_mutexLock (&__s_pkcs11h_threading_mutex_list.mutex) == CKR_OK) {
 6899 +       mutex_locked = TRUE;
 6900 +   }
 6901 +
 6902 +   for (
 6903 +       entry = __s_pkcs11h_threading_mutex_list.head;
 6904 +       entry != NULL;
 6905 +       entry = entry->next
 6906 +   ) {
 6907 +       pthread_mutex_unlock (entry->p_mutex);
 6908 +       entry->locked = FALSE;
 6909 +   }
 6910 +
 6911 +   if (mutex_locked) {
 6912 +       _pkcs11h_threading_mutexRelease (&__s_pkcs11h_threading_mutex_list.mutex);
 6913 +       mutex_locked = FALSE;
 6914 +   }
 6915 +}
 6916 +#endif
 6917 +
 6918 +CK_RV
 6919 +_pkcs11h_threading_condSignal (
 6920 +   IN OUT pkcs11h_cond_t *const cond
 6921 +) {
 6922 +   CK_RV rv = CKR_OK;
 6923 +#if defined(WIN32)
 6924 +   if (
 6925 +       rv == CKR_OK &&
 6926 +       !SetEvent (*cond)
 6927 +   ) {
 6928 +       rv = CKR_FUNCTION_FAILED;
 6929 +   }
 6930 +#else
 6931 +   if (
 6932 +       rv == CKR_OK &&
 6933 +       (
 6934 +           pthread_mutex_lock (&cond->mut) ||
 6935 +           pthread_cond_signal (&cond->cond) ||
 6936 +           pthread_mutex_unlock (&cond->mut)
 6937 +       )
 6938 +   ) {
 6939 +       rv = CKR_FUNCTION_FAILED;
 6940 +   }
 6941 +#endif
 6942 +
 6943 +   return rv;
 6944 +}
 6945 +
 6946 +static
 6947 +CK_RV
 6948 +_pkcs11h_threading_condInit (
 6949 +   OUT pkcs11h_cond_t * const cond
 6950 +) {
 6951 +   CK_RV rv = CKR_OK;
 6952 +#if defined(WIN32)
 6953 +   if (
 6954 +       rv == CKR_OK &&
 6955 +       (*cond = CreateEvent (NULL, FALSE, FALSE, NULL)) == NULL
 6956 +   ) {
 6957 +       rv = CKR_FUNCTION_FAILED;
 6958 +   }
 6959 +#else
 6960 +   if (
 6961 +       rv == CKR_OK &&
 6962 +       (
 6963 +           pthread_mutex_init (&cond->mut, NULL) ||
 6964 +           pthread_cond_init (&cond->cond, NULL) ||
 6965 +           pthread_mutex_lock (&cond->mut)
 6966 +       )
 6967 +   ) {
 6968 +       rv = CKR_FUNCTION_FAILED;
 6969 +   }
 6970 +#endif
 6971 +   return rv;
 6972 +}
 6973 +
 6974 +static
 6975 +CK_RV
 6976 +_pkcs11h_threading_condWait (
 6977 +   IN OUT pkcs11h_cond_t *const cond,
 6978 +   IN const unsigned milli
 6979 +) {
 6980 +   CK_RV rv = CKR_OK;
 6981 +
 6982 +#if defined(WIN32)
 6983 +   DWORD dwMilli;
 6984 +
 6985 +   if (milli == PKCS11H_COND_INFINITE) {
 6986 +       dwMilli = INFINITE;
 6987 +   }
 6988 +   else {
 6989 +       dwMilli = milli;
 6990 +   }
 6991 +
 6992 +   if (
 6993 +       rv == CKR_OK &&
 6994 +       WaitForSingleObject (*cond, dwMilli) == WAIT_FAILED
 6995 +   ) {
 6996 +       rv = CKR_FUNCTION_FAILED;
 6997 +   }
 6998 +#else
 6999 +   if (milli == PKCS11H_COND_INFINITE) {
 7000 +       if (
 7001 +           rv == CKR_OK &&
 7002 +           pthread_cond_wait (&cond->cond, &cond->mut)
 7003 +       ) {
 7004 +           rv = CKR_FUNCTION_FAILED;
 7005 +       }
 7006 +   }
 7007 +   else {
 7008 +       struct timeval now;
 7009 +       struct timespec timeout;
 7010 +
 7011 +       if (
 7012 +           rv == CKR_OK &&
 7013 +           gettimeofday (&now, NULL)
 7014 +       ) {
 7015 +           rv = CKR_FUNCTION_FAILED;
 7016 +       }
 7017 +       
 7018 +       if (rv == CKR_OK) {
 7019 +           timeout.tv_sec = now.tv_sec + milli/1000;
 7020 +           timeout.tv_nsec = now.tv_usec*1000 + milli%1000;
 7021 +       }
 7022 +       
 7023 +       if (
 7024 +           rv == CKR_OK &&
 7025 +           pthread_cond_timedwait (&cond->cond, &cond->mut, &timeout)
 7026 +       ) {
 7027 +           rv = CKR_FUNCTION_FAILED;
 7028 +       }
 7029 +   }
 7030 +#endif
 7031 +   return rv;
 7032 +}
 7033 +
 7034 +static
 7035 +CK_RV
 7036 +_pkcs11h_threading_condFree (
 7037 +   IN OUT pkcs11h_cond_t *const cond
 7038 +) {
 7039 +#if defined(WIN32)
 7040 +   CloseHandle (*cond);
 7041 +   *cond = NULL;
 7042 +#else
 7043 +   pthread_mutex_unlock (&cond->mut);
 7044 +#endif
 7045 +   return CKR_OK;
 7046 +}
 7047 +
 7048 +#if defined(WIN32)
 7049 +static
 7050 +unsigned
 7051 +__stdcall
 7052 +__pkcs11h_thread_start (void *p) {
 7053 +   __pkcs11h_thread_data_t *_data = (__pkcs11h_thread_data_t *)p;
 7054 +   unsigned ret;
 7055 +
 7056 +   ret = (unsigned)_data->start (_data->data);
 7057 +
 7058 +   _pkcs11h_mem_free ((void *)&_data);
 7059 +
 7060 +   return ret;
 7061 +}
 7062 +#else
 7063 +static
 7064 +void *
 7065 +__pkcs11h_thread_start (void *p) {
 7066 +   __pkcs11h_thread_data_t *_data = (__pkcs11h_thread_data_t *)p;
 7067 +   void *ret;
 7068 +   int i;
 7069 +
 7070 +   /*
 7071 +    * Ignore any signal in
 7072 +    * this thread
 7073 +    */
 7074 +   for (i=1;i<16;i++) {
 7075 +       signal (i, SIG_IGN);
 7076 +   }
 7077 +
 7078 +   ret = _data->start (_data->data);
 7079 +
 7080 +   _pkcs11h_mem_free ((void *)&_data);
 7081 +
 7082 +   return ret;
 7083 +}
 7084 +#endif
 7085 +
 7086 +static
 7087 +CK_RV
 7088 +_pkcs11h_threading_threadStart (
 7089 +   OUT pkcs11h_thread_t * const thread,
 7090 +   IN pkcs11h_thread_start_t const start,
 7091 +   IN void * data
 7092 +) {
 7093 +   __pkcs11h_thread_data_t *_data = NULL;
 7094 +   CK_RV rv = CKR_OK;
 7095 +
 7096 +   if (rv == CKR_OK) {
 7097 +       rv = _pkcs11h_mem_malloc (
 7098 +           (void *)&_data,
 7099 +           sizeof (__pkcs11h_thread_data_t)
 7100 +       );
 7101 +   }
 7102 +
 7103 +   if (rv == CKR_OK) {
 7104 +       _data->start = start;
 7105 +       _data->data = data;
 7106 +   }
 7107 +
 7108 +#if defined(WIN32)
 7109 +   {
 7110 +       unsigned tmp;
 7111 +
 7112 +       if (
 7113 +           rv == CKR_OK &&
 7114 +           (*thread = (HANDLE)_beginthreadex (
 7115 +               NULL,
 7116 +               0,
 7117 +               __pkcs11h_thread_start,
 7118 +               _data,
 7119 +               0,
 7120 +               &tmp
 7121 +           )) == NULL
 7122 +       ) {
 7123 +           rv = CKR_FUNCTION_FAILED;
 7124 +       }
 7125 +   }
 7126 +#else
 7127 +   if (
 7128 +       rv == CKR_OK &&
 7129 +       pthread_create (thread, NULL, __pkcs11h_thread_start, _data)
 7130 +   ) {
 7131 +       rv = CKR_FUNCTION_FAILED;
 7132 +   }
 7133 +#endif
 7134 +   return rv;
 7135 +}
 7136 +
 7137 +static
 7138 +CK_RV
 7139 +_pkcs11h_threading_threadJoin (
 7140 +   IN pkcs11h_thread_t * const thread
 7141 +) {
 7142 +#if defined(WIN32)
 7143 +   WaitForSingleObject (*thread, INFINITE);
 7144 +   CloseHandle (*thread);
 7145 +   *thread = NULL;
 7146 +#else
 7147 +   pthread_join (*thread, NULL);
 7148 +   *thread = 0l;
 7149 +#endif
 7150 +   return CKR_OK;
 7151 +}
 7152 +
 7153 +#endif     /* ENABLE_PKCS11H_THREADING */
 7154 +
 7155 +/*======================================================================*
 7156 + * COMMON INTERNAL INTERFACE
 7157 + *======================================================================*/
 7158 +
 7159 +static
 7160 +void
 7161 +_pkcs11h_util_fixupFixedString (
 7162 +   OUT char * const target,            /* MUST BE >= length+1 */
 7163 +   IN const char * const source,
 7164 +   IN const size_t length              /* FIXED STRING LENGTH */
 7165 +) {
 7166 +   char *p;
 7167 +
 7168 +   PKCS11H_ASSERT (source!=NULL);
 7169 +   PKCS11H_ASSERT (target!=NULL);
 7170 +   
 7171 +   p = target+length;
 7172 +   memmove (target, source, length);
 7173 +   *p = '\0';
 7174 +   p--;
 7175 +   while (p >= target && *p == ' ') {
 7176 +       *p = '\0';
 7177 +       p--;
 7178 +   }
 7179 +}
 7180 +
 7181 +static
 7182 +CK_RV
 7183 +_pkcs11h_util_hexToBinary (
 7184 +   OUT unsigned char * const target,
 7185 +   IN const char * const source,
 7186 +   IN OUT size_t * const p_target_size
 7187 +) {
 7188 +   size_t target_max_size;
 7189 +   const char *p;
 7190 +   char buf[3] = {'\0', '\0', '\0'};
 7191 +   int i = 0;
 7192 +
 7193 +   PKCS11H_ASSERT (source!=NULL);
 7194 +   PKCS11H_ASSERT (target!=NULL);
 7195 +   PKCS11H_ASSERT (p_target_size!=NULL);
 7196 +
 7197 +   target_max_size = *p_target_size;
 7198 +   p = source;
 7199 +   *p_target_size = 0;
 7200 +
 7201 +   while (*p != '\x0' && *p_target_size < target_max_size) {
 7202 +       if (isxdigit ((unsigned char)*p)) {
 7203 +           buf[i%2] = *p;
 7204 +
 7205 +           if ((i%2) == 1) {
 7206 +               unsigned v;
 7207 +               if (sscanf (buf, "%x", &v) != 1) {
 7208 +                   v = 0;
 7209 +               }
 7210 +               target[*p_target_size] = v & 0xff;
 7211 +               (*p_target_size)++;
 7212 +           }
 7213 +
 7214 +           i++;
 7215 +       }
 7216 +       p++;
 7217 +   }
 7218 +
 7219 +   if (*p != '\x0') {
 7220 +       return CKR_ATTRIBUTE_VALUE_INVALID;
 7221 +   }
 7222 +   else {
 7223 +       return CKR_OK;
 7224 +   }
 7225 +}
 7226 +
 7227 +static
 7228 +CK_RV
 7229 +_pkcs11h_util_binaryToHex (
 7230 +   OUT char * const target,
 7231 +   IN const size_t target_size,
 7232 +   IN const unsigned char * const source,
 7233 +   IN const size_t source_size
 7234 +) {
 7235 +   static const char *x = "0123456789ABCDEF";
 7236 +   size_t i;
 7237 +
 7238 +   PKCS11H_ASSERT (target!=NULL);
 7239 +   PKCS11H_ASSERT (source!=NULL);
 7240 +
 7241 +   if (target_size < source_size * 2 + 1) {
 7242 +       return CKR_ATTRIBUTE_VALUE_INVALID;
 7243 +   }
 7244 +
 7245 +   for (i=0;i<source_size;i++) {
 7246 +       target[i*2] =   x[(source[i]&0xf0)>>4];
 7247 +       target[i*2+1] = x[(source[i]&0x0f)>>0];
 7248 +   }
 7249 +   target[source_size*2] = '\x0';
 7250 +
 7251 +   return CKR_OK;
 7252 +}
 7253 +
 7254 +CK_RV
 7255 +_pkcs11h_util_escapeString (
 7256 +   IN OUT char * const target,
 7257 +   IN const char * const source,
 7258 +   IN size_t * const max,
 7259 +   IN const char * const invalid_chars
 7260 +) {
 7261 +   static const char *x = "0123456789ABCDEF";
 7262 +   CK_RV rv = CKR_OK;
 7263 +   const char *s = source;
 7264 +   char *t = target;
 7265 +   size_t n = 0;
 7266 +
 7267 +   /*PKCS11H_ASSERT (target!=NULL); Not required*/
 7268 +   PKCS11H_ASSERT (source!=NULL);
 7269 +   PKCS11H_ASSERT (max!=NULL);
 7270 +
 7271 +   while (rv == CKR_OK && *s != '\x0') {
 7272 +
 7273 +       if (*s == '\\' || strchr (invalid_chars, *s) || !isgraph (*s)) {
 7274 +           if (t != NULL) {
 7275 +               if (n+4 > *max) {
 7276 +                   rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7277 +               }
 7278 +               else {
 7279 +                   t[0] = '\\';
 7280 +                   t[1] = 'x';
 7281 +                   t[2] = x[(*s&0xf0)>>4];
 7282 +                   t[3] = x[(*s&0x0f)>>0];
 7283 +                   t+=4;
 7284 +               }
 7285 +           }
 7286 +           n+=4;
 7287 +       }
 7288 +       else {
 7289 +           if (t != NULL) {
 7290 +               if (n+1 > *max) {
 7291 +                   rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7292 +               }
 7293 +               else {
 7294 +                   *t = *s;
 7295 +                   t++;
 7296 +               }
 7297 +           }
 7298 +           n+=1;
 7299 +       }
 7300 +
 7301 +       s++;
 7302 +   }
 7303 +
 7304 +   if (t != NULL) {
 7305 +       if (n+1 > *max) {
 7306 +           rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7307 +       }
 7308 +       else {
 7309 +           *t = '\x0';
 7310 +           t++;
 7311 +       }
 7312 +   }
 7313 +   n++;
 7314 +
 7315 +   *max = n;
 7316 +
 7317 +   return rv;
 7318 +}
 7319 +
 7320 +static
 7321 +CK_RV
 7322 +_pkcs11h_util_unescapeString (
 7323 +   IN OUT char * const target,
 7324 +   IN const char * const source,
 7325 +   IN size_t * const max
 7326 +) {
 7327 +   CK_RV rv = CKR_OK;
 7328 +   const char *s = source;
 7329 +   char *t = target;
 7330 +   size_t n = 0;
 7331 +
 7332 +   /*PKCS11H_ASSERT (target!=NULL); Not required*/
 7333 +   PKCS11H_ASSERT (source!=NULL);
 7334 +   PKCS11H_ASSERT (max!=NULL);
 7335 +
 7336 +   while (rv == CKR_OK && *s != '\x0') {
 7337 +       if (*s == '\\') {
 7338 +           if (t != NULL) {
 7339 +               if (n+1 > *max) {
 7340 +                   rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7341 +               }
 7342 +               else {
 7343 +                   char b[3];
 7344 +                   unsigned u;
 7345 +                   b[0] = s[2];
 7346 +                   b[1] = s[3];
 7347 +                   b[2] = '\x0';
 7348 +                   sscanf (b, "%08x", &u);
 7349 +                   *t = u&0xff;
 7350 +                   t++;
 7351 +               }
 7352 +           }
 7353 +           s+=4;
 7354 +       }
 7355 +       else {
 7356 +           if (t != NULL) {
 7357 +               if (n+1 > *max) {
 7358 +                   rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7359 +               }
 7360 +               else {
 7361 +                   *t = *s;
 7362 +                   t++;
 7363 +               }
 7364 +           }
 7365 +           s++;
 7366 +       }
 7367 +
 7368 +       n+=1;
 7369 +   }
 7370 +
 7371 +   if (t != NULL) {
 7372 +       if (n+1 > *max) {
 7373 +           rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7374 +       }
 7375 +       else {
 7376 +           *t = '\x0';
 7377 +           t++;
 7378 +       }
 7379 +   }
 7380 +   n++;
 7381 +
 7382 +   *max = n;
 7383 +
 7384 +   return rv;
 7385 +}
 7386 +
 7387 +static
 7388 +void
 7389 +_pkcs11h_log (
 7390 +   IN const unsigned flags,
 7391 +   IN const char * const format,
 7392 +   IN ...
 7393 +) {
 7394 +   va_list args;
 7395 +
 7396 +   PKCS11H_ASSERT (format!=NULL);
 7397 +
 7398 +   va_start (args, format);
 7399 +
 7400 +   if (
 7401 +       s_pkcs11h_data != NULL &&
 7402 +       s_pkcs11h_data->initialized
 7403 +   ) { 
 7404 +       if (PKCS11H_MSG_LEVEL_TEST (flags)) {
 7405 +           if (s_pkcs11h_data->hooks.log == NULL) {
 7406 +               _pkcs11h_hooks_default_log (
 7407 +                   NULL,
 7408 +                   flags,
 7409 +                   format,
 7410 +                   args
 7411 +               );
 7412 +           }
 7413 +           else {
 7414 +               s_pkcs11h_data->hooks.log (
 7415 +                   s_pkcs11h_data->hooks.log_data,
 7416 +                   flags,
 7417 +                   format,
 7418 +                   args
 7419 +               );
 7420 +           }
 7421 +       }
 7422 +   }
 7423 +
 7424 +   va_end (args);
 7425 +}
 7426 +
 7427 +static
 7428 +CK_RV
 7429 +_pkcs11h_session_getSlotList (
 7430 +   IN const pkcs11h_provider_t provider,
 7431 +   IN const CK_BBOOL token_present,
 7432 +   OUT CK_SLOT_ID_PTR * const pSlotList,
 7433 +   OUT CK_ULONG_PTR pulCount
 7434 +) {
 7435 +   CK_SLOT_ID_PTR _slots = NULL;
 7436 +   CK_ULONG _slotnum = 0;
 7437 +   CK_RV rv = CKR_OK;
 7438 +
 7439 +   PKCS11H_ASSERT (provider!=NULL);
 7440 +   PKCS11H_ASSERT (pSlotList!=NULL);
 7441 +   PKCS11H_ASSERT (pulCount!=NULL);
 7442 +
 7443 +   PKCS11H_DEBUG (
 7444 +       PKCS11H_LOG_DEBUG2,
 7445 +       "PKCS#11: _pkcs11h_session_getSlotList entry provider=%p, token_present=%d, pSlotList=%p, pulCount=%p",
 7446 +       (void *)provider,
 7447 +       token_present,
 7448 +       (void *)pSlotList,
 7449 +       (void *)pulCount
 7450 +   );
 7451 +
 7452 +   *pSlotList = NULL;
 7453 +   *pulCount = 0;
 7454 +
 7455 +   if (
 7456 +       rv == CKR_OK &&
 7457 +       !provider->enabled
 7458 +   ) {
 7459 +       rv = CKR_CRYPTOKI_NOT_INITIALIZED;
 7460 +   }
 7461 +
 7462 +   if (rv == CKR_OK) {
 7463 +       rv = provider->f->C_GetSlotList (
 7464 +           token_present,
 7465 +           NULL_PTR,
 7466 +           &_slotnum
 7467 +       );
 7468 +   }
 7469 +
 7470 +   if (rv == CKR_OK && _slotnum > 0) {
 7471 +       rv = _pkcs11h_mem_malloc ((void *)&_slots, _slotnum * sizeof (CK_SLOT_ID));
 7472 +   }
 7473 +
 7474 +   if (rv == CKR_OK && _slotnum > 0) {
 7475 +       rv = provider->f->C_GetSlotList (
 7476 +           token_present,
 7477 +           _slots,
 7478 +           &_slotnum
 7479 +       );
 7480 +   }
 7481 +
 7482 +   if (rv == CKR_OK) {
 7483 +       *pSlotList = _slots;
 7484 +       _slots = NULL;
 7485 +       *pulCount = _slotnum;
 7486 +   }
 7487 +
 7488 +   if (_slots != NULL) {
 7489 +       _pkcs11h_mem_free ((void *)&_slots);
 7490 +   }
 7491 +
 7492 +   PKCS11H_DEBUG (
 7493 +       PKCS11H_LOG_DEBUG2,
 7494 +       "PKCS#11: _pkcs11h_session_getSlotList return rv=%ld-'%s' *pulCount=%ld",
 7495 +       rv,
 7496 +       pkcs11h_getMessage (rv),
 7497 +       *pulCount
 7498 +   );
 7499 +
 7500 +   return rv;
 7501 +}
 7502 +
 7503 +static
 7504 +CK_RV
 7505 +_pkcs11h_session_getObjectAttributes (
 7506 +   IN const pkcs11h_session_t session,
 7507 +   IN const CK_OBJECT_HANDLE object,
 7508 +   IN OUT const CK_ATTRIBUTE_PTR attrs,
 7509 +   IN const unsigned count
 7510 +) {
 7511 +   /*
 7512 +    * THREADING:
 7513 +    * session->mutex must be locked
 7514 +    */
 7515 +   CK_RV rv = CKR_OK;
 7516 +
 7517 +   PKCS11H_ASSERT (session!=NULL);
 7518 +   PKCS11H_ASSERT (attrs!=NULL);
 7519 +
 7520 +   PKCS11H_DEBUG (
 7521 +       PKCS11H_LOG_DEBUG2,
 7522 +       "PKCS#11: _pkcs11h_session_getObjectAttributes entry session=%p, object=%ld, attrs=%p, count=%u",
 7523 +       (void *)session,
 7524 +       object,
 7525 +       (void *)attrs,
 7526 +       count
 7527 +   );
 7528 +
 7529 +   if (
 7530 +       rv == CKR_OK &&
 7531 +       (rv = session->provider->f->C_GetAttributeValue (
 7532 +           session->session_handle,
 7533 +           object,
 7534 +           attrs,
 7535 +           count
 7536 +       )) == CKR_OK
 7537 +   ) {
 7538 +       unsigned i;
 7539 +       for (i=0;rv == CKR_OK && i<count;i++) {
 7540 +           if (attrs[i].ulValueLen == (CK_ULONG)-1) {
 7541 +               rv = CKR_ATTRIBUTE_VALUE_INVALID;
 7542 +           }
 7543 +           else if (attrs[i].ulValueLen == 0) {
 7544 +               attrs[i].pValue = NULL;
 7545 +           }
 7546 +           else {
 7547 +               rv = _pkcs11h_mem_malloc (
 7548 +                   (void *)&attrs[i].pValue,
 7549 +                   attrs[i].ulValueLen
 7550 +               );
 7551 +           }
 7552 +       }
 7553 +   }
 7554 +
 7555 +   if (rv == CKR_OK) {
 7556 +       rv = session->provider->f->C_GetAttributeValue (
 7557 +           session->session_handle,
 7558 +           object,
 7559 +           attrs,
 7560 +           count
 7561 +       );
 7562 +   }
 7563 +
 7564 +   PKCS11H_DEBUG (
 7565 +       PKCS11H_LOG_DEBUG2,
 7566 +       "PKCS#11: _pkcs11h_session_getObjectAttributes return rv=%ld-'%s'",
 7567 +       rv,
 7568 +       pkcs11h_getMessage (rv)
 7569 +   );
 7570 +
 7571 +   return rv;
 7572 +}
 7573 +
 7574 +static
 7575 +CK_RV
 7576 +_pkcs11h_session_freeObjectAttributes (
 7577 +   IN OUT const CK_ATTRIBUTE_PTR attrs,
 7578 +   IN const unsigned count
 7579 +) {
 7580 +   unsigned i;
 7581 +
 7582 +   CK_RV rv = CKR_OK;
 7583 +
 7584 +   PKCS11H_ASSERT (attrs!=NULL);
 7585 +
 7586 +   PKCS11H_DEBUG (
 7587 +       PKCS11H_LOG_DEBUG2,
 7588 +       "PKCS#11: _pkcs11h_session_freeObjectAttributes entry attrs=%p, count=%u",
 7589 +       (void *)attrs,
 7590 +       count
 7591 +   );
 7592 +
 7593 +   for (i=0;i<count;i++) {
 7594 +       if (attrs[i].pValue != NULL) {
 7595 +           _pkcs11h_mem_free ((void *)&attrs[i].pValue);
 7596 +           attrs[i].pValue = NULL;
 7597 +       }
 7598 +   }
 7599 +
 7600 +   PKCS11H_DEBUG (
 7601 +       PKCS11H_LOG_DEBUG2,
 7602 +       "PKCS#11: _pkcs11h_session_freeObjectAttributes return rv=%ld-'%s'",
 7603 +       rv,
 7604 +       pkcs11h_getMessage (rv)
 7605 +   );
 7606 +
 7607 +   return rv;
 7608 +}
 7609 +
 7610 +static
 7611 +CK_RV
 7612 +_pkcs11h_session_findObjects (
 7613 +   IN const pkcs11h_session_t session,
 7614 +   IN const CK_ATTRIBUTE * const filter,
 7615 +   IN const CK_ULONG filter_attrs,
 7616 +   OUT CK_OBJECT_HANDLE **const p_objects,
 7617 +   OUT CK_ULONG *p_objects_found
 7618 +) {
 7619 +   /*
 7620 +    * THREADING:
 7621 +    * session->mutex must be locked
 7622 +    */
 7623 +   PKCS11H_BOOL should_FindObjectsFinal = FALSE;
 7624 +
 7625 +   CK_OBJECT_HANDLE *objects = NULL;
 7626 +   CK_ULONG objects_size = 0;
 7627 +   CK_OBJECT_HANDLE objects_buffer[100];
 7628 +   CK_ULONG objects_found;
 7629 +   CK_OBJECT_HANDLE oLast = PKCS11H_INVALID_OBJECT_HANDLE;
 7630 +   CK_RV rv = CKR_OK;
 7631 +
 7632 +   PKCS11H_ASSERT (session!=NULL);
 7633 +   PKCS11H_ASSERT (!(filter==NULL && filter_attrs!=0) || filter!=NULL);
 7634 +   PKCS11H_ASSERT (p_objects!=NULL);
 7635 +   PKCS11H_ASSERT (p_objects_found!=NULL);
 7636 +   
 7637 +   PKCS11H_DEBUG (
 7638 +       PKCS11H_LOG_DEBUG2,
 7639 +       "PKCS#11: _pkcs11h_session_findObjects entry session=%p, filter=%p, filter_attrs=%ld, p_objects=%p,
	p_objects_found=%p",
 7640 +       (void *)session,
 7641 +       (void *)filter,
 7642 +       filter_attrs,
 7643 +       (void *)p_objects,
 7644 +       (void *)p_objects_found
 7645 +   );
 7646 +
 7647 +   *p_objects = NULL;
 7648 +   *p_objects_found = 0;
 7649 +
 7650 +   if (
 7651 +       rv == CKR_OK &&
 7652 +       (rv = session->provider->f->C_FindObjectsInit (
 7653 +           session->session_handle,
 7654 +           (CK_ATTRIBUTE *)filter,
 7655 +           filter_attrs
 7656 +       )) == CKR_OK
 7657 +   ) {
 7658 +       should_FindObjectsFinal = TRUE;
 7659 +   }
 7660 +
 7661 +   while (
 7662 +       rv == CKR_OK &&
 7663 +       (rv = session->provider->f->C_FindObjects (
 7664 +           session->session_handle,
 7665 +           objects_buffer,
 7666 +           sizeof (objects_buffer) / sizeof (CK_OBJECT_HANDLE),
 7667 +           &objects_found
 7668 +       )) == CKR_OK &&
 7669 +       objects_found > 0
 7670 +   ) { 
 7671 +       CK_OBJECT_HANDLE *temp = NULL;
 7672 +       
 7673 +       /*
 7674 +        * Begin workaround
 7675 +        *
 7676 +        * Workaround iKey bug
 7677 +        * It returns the same objects over and over
 7678 +        */
 7679 +       if (oLast == objects_buffer[0]) {
 7680 +           PKCS11H_LOG (
 7681 +               PKCS11H_LOG_WARN,
 7682 +               "PKCS#11: Bad PKCS#11 C_FindObjects implementation detected, workaround applied"
 7683 +           );
 7684 +           break;
 7685 +       }
 7686 +       oLast = objects_buffer[0];
 7687 +       /* End workaround */
 7688 +       
 7689 +       if (
 7690 +           (rv = _pkcs11h_mem_malloc (
 7691 +               (void *)&temp,
 7692 +               (objects_size+objects_found) * sizeof (CK_OBJECT_HANDLE)
 7693 +           )) == CKR_OK
 7694 +       ) {
 7695 +           if (objects != NULL) {
 7696 +               memmove (
 7697 +                   temp,
 7698 +                   objects,
 7699 +                   objects_size * sizeof (CK_OBJECT_HANDLE)
 7700 +               );
 7701 +           }
 7702 +           memmove (
 7703 +               temp + objects_size,
 7704 +               objects_buffer,
 7705 +               objects_found * sizeof (CK_OBJECT_HANDLE)
 7706 +           );
 7707 +       }
 7708 +
 7709 +       if (objects != NULL) {
 7710 +           _pkcs11h_mem_free ((void *)&objects);
 7711 +           objects = NULL;
 7712 +       }
 7713 +
 7714 +       if (rv == CKR_OK) {
 7715 +           objects = temp;
 7716 +           objects_size += objects_found;
 7717 +           temp = NULL;
 7718 +       }
 7719 +
 7720 +       if (temp != NULL) {
 7721 +           _pkcs11h_mem_free ((void *)&temp);
 7722 +           temp = NULL;
 7723 +       }
 7724 +   }
 7725 +
 7726 +   if (should_FindObjectsFinal) {
 7727 +       session->provider->f->C_FindObjectsFinal (
 7728 +           session->session_handle
 7729 +       );
 7730 +       should_FindObjectsFinal = FALSE;
 7731 +   }
 7732 +   
 7733 +   if (rv == CKR_OK) {
 7734 +       *p_objects = objects;
 7735 +       *p_objects_found = objects_size;
 7736 +       objects = NULL;
 7737 +       objects_size = 0;
 7738 +   }
 7739 +
 7740 +   if (objects != NULL) {
 7741 +       _pkcs11h_mem_free ((void *)&objects);
 7742 +       objects = NULL;
 7743 +       objects_size = 0;
 7744 +   }
 7745 +
 7746 +   PKCS11H_DEBUG (
 7747 +       PKCS11H_LOG_DEBUG2,
 7748 +       "PKCS#11: _pkcs11h_session_findObjects return rv=%ld-'%s', *p_objects_found=%ld",
 7749 +       rv,
 7750 +       pkcs11h_getMessage (rv),
 7751 +       *p_objects_found
 7752 +   );
 7753 +
 7754 +   return rv;
 7755 +}
 7756 +
 7757 +static
 7758 +CK_RV
 7759 +_pkcs11h_token_getTokenId (
 7760 +   IN const CK_TOKEN_INFO_PTR info,
 7761 +   OUT pkcs11h_token_id_t * const p_token_id
 7762 +) {
 7763 +   pkcs11h_token_id_t token_id;
 7764 +   CK_RV rv = CKR_OK;
 7765 +   
 7766 +   PKCS11H_ASSERT (info!=NULL);
 7767 +   PKCS11H_ASSERT (p_token_id!=NULL);
 7768 +   
 7769 +   PKCS11H_DEBUG (
 7770 +       PKCS11H_LOG_DEBUG2,
 7771 +       "PKCS#11: _pkcs11h_token_getTokenId entry p_token_id=%p",
 7772 +       (void *)p_token_id
 7773 +   );
 7774 +
 7775 +   *p_token_id = NULL;
 7776 +
 7777 +   if (
 7778 +       rv == CKR_OK &&
 7779 +       (rv = _pkcs11h_token_newTokenId (&token_id)) == CKR_OK
 7780 +   ) {
 7781 +       _pkcs11h_util_fixupFixedString (
 7782 +           token_id->label,
 7783 +           (char *)info->label,
 7784 +           sizeof (info->label)
 7785 +       );
 7786 +       _pkcs11h_util_fixupFixedString (
 7787 +           token_id->manufacturerID,
 7788 +           (char *)info->manufacturerID,
 7789 +           sizeof (info->manufacturerID)
 7790 +       );
 7791 +       _pkcs11h_util_fixupFixedString (
 7792 +           token_id->model,
 7793 +           (char *)info->model,
 7794 +           sizeof (info->model)
 7795 +       );
 7796 +       _pkcs11h_util_fixupFixedString (
 7797 +           token_id->serialNumber,
 7798 +           (char *)info->serialNumber,
 7799 +           sizeof (info->serialNumber)
 7800 +       );
 7801 +       strncpy (
 7802 +           token_id->display,
 7803 +           token_id->label,
 7804 +           sizeof (token_id->display)
 7805 +       );
 7806 +   }
 7807 +
 7808 +   if (rv == CKR_OK) {
 7809 +       *p_token_id = token_id;
 7810 +       token_id = NULL;
 7811 +   }
 7812 +
 7813 +   if (token_id != NULL) {
 7814 +       _pkcs11h_mem_free ((void *)&token_id);
 7815 +   }
 7816 +
 7817 +   PKCS11H_DEBUG (
 7818 +       PKCS11H_LOG_DEBUG2,
 7819 +       "PKCS#11: _pkcs11h_token_getTokenId return rv=%ld-'%s', *p_token_id=%p",
 7820 +       rv,
 7821 +       pkcs11h_getMessage (rv),
 7822 +       (void *)*p_token_id
 7823 +   );
 7824 +
 7825 +   return rv;
 7826 +}
 7827 +
 7828 +static
 7829 +CK_RV
 7830 +_pkcs11h_token_newTokenId (
 7831 +   OUT pkcs11h_token_id_t * const p_token_id
 7832 +) {
 7833 +   CK_RV rv = CKR_OK;
 7834 +
 7835 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 7836 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 7837 +   PKCS11H_ASSERT (p_token_id!=NULL);
 7838 +
 7839 +   PKCS11H_DEBUG (
 7840 +       PKCS11H_LOG_DEBUG2,
 7841 +       "PKCS#11: _pkcs11h_token_newTokenId entry p_token_id=%p",
 7842 +       (void *)p_token_id
 7843 +   );
 7844 +
 7845 +   *p_token_id = NULL;
 7846 +
 7847 +   if (rv == CKR_OK) {
 7848 +       rv = _pkcs11h_mem_malloc ((void *)p_token_id, sizeof (struct pkcs11h_token_id_s));
 7849 +   }
 7850 +
 7851 +   PKCS11H_DEBUG (
 7852 +       PKCS11H_LOG_DEBUG2,
 7853 +       "PKCS#11: _pkcs11h_token_newTokenId return rv=%ld-'%s', *p_token_id=%p",
 7854 +       rv,
 7855 +       pkcs11h_getMessage (rv),
 7856 +       (void *)*p_token_id
 7857 +   );
 7858 +
 7859 +   return rv;
 7860 +}
 7861 +
 7862 +static
 7863 +CK_RV
 7864 +_pkcs11h_session_getSessionByTokenId (
 7865 +   IN const pkcs11h_token_id_t token_id,
 7866 +   OUT pkcs11h_session_t * const p_session
 7867 +) {
 7868 +#if defined(ENABLE_PKCS11H_THREADING)
 7869 +   PKCS11H_BOOL mutex_locked = FALSE;
 7870 +#endif
 7871 +   pkcs11h_session_t session = NULL;
 7872 +   PKCS11H_BOOL is_new_session = FALSE;
 7873 +   CK_RV rv = CKR_OK;
 7874 +
 7875 +   PKCS11H_ASSERT (token_id!=NULL);
 7876 +   PKCS11H_ASSERT (p_session!=NULL);
 7877 +
 7878 +   PKCS11H_DEBUG (
 7879 +       PKCS11H_LOG_DEBUG2,
 7880 +       "PKCS#11: _pkcs11h_session_getSessionByTokenId entry token_id=%p, p_session=%p",
 7881 +       (void *)token_id,
 7882 +       (void *)p_session
 7883 +   );
 7884 +
 7885 +   *p_session = NULL;
 7886 +
 7887 +#if defined(ENABLE_PKCS11H_THREADING)
 7888 +   if (
 7889 +       rv == CKR_OK &&
 7890 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.session)) == CKR_OK
 7891 +   ) {
 7892 +       mutex_locked = TRUE;
 7893 +   }
 7894 +#endif
 7895 +
 7896 +   if (rv == CKR_OK) {
 7897 +       pkcs11h_session_t current_session;
 7898 +
 7899 +       for (
 7900 +           current_session = s_pkcs11h_data->sessions;
 7901 +           current_session != NULL && session == NULL;
 7902 +           current_session = current_session->next
 7903 +       ) {
 7904 +           if (
 7905 +               pkcs11h_token_sameTokenId (
 7906 +                   current_session->token_id,
 7907 +                   token_id
 7908 +               )
 7909 +           ) {
 7910 +               PKCS11H_DEBUG (
 7911 +                   PKCS11H_LOG_DEBUG1,
 7912 +                   "PKCS#11: Using cached session"
 7913 +               );
 7914 +               session = current_session;
 7915 +               session->reference_count++;
 7916 +           }
 7917 +       }
 7918 +   }
 7919 +
 7920 +   if (
 7921 +       rv == CKR_OK &&
 7922 +       session == NULL
 7923 +   ) {
 7924 +       is_new_session = TRUE;
 7925 +   }
 7926 +
 7927 +   if (is_new_session) {
 7928 +       PKCS11H_DEBUG (
 7929 +           PKCS11H_LOG_DEBUG1,
 7930 +           "PKCS#11: Creating a new session"
 7931 +       );
 7932 +
 7933 +       if (
 7934 +           rv == CKR_OK &&
 7935 +           (rv = _pkcs11h_mem_malloc ((void *)&session, sizeof (struct pkcs11h_session_s))) == CKR_OK
 7936 +       ) {
 7937 +           session->reference_count = 1;
 7938 +           session->session_handle = PKCS11H_INVALID_SESSION_HANDLE;
 7939 +           
 7940 +           session->pin_cache_period = s_pkcs11h_data->pin_cache_period;
 7941 +
 7942 +       }
 7943 +
 7944 +       if (rv == CKR_OK) {
 7945 +           rv = pkcs11h_token_duplicateTokenId (
 7946 +               &session->token_id,
 7947 +               token_id
 7948 +           );
 7949 +       }
 7950 +
 7951 +#if defined(ENABLE_PKCS11H_THREADING)
 7952 +       if (rv == CKR_OK) {
 7953 +           rv = _pkcs11h_threading_mutexInit (&session->mutex);
 7954 +       }
 7955 +#endif
 7956 +
 7957 +       if (rv == CKR_OK) {
 7958 +           session->valid = TRUE;
 7959 +           session->next = s_pkcs11h_data->sessions;
 7960 +           s_pkcs11h_data->sessions = session;
 7961 +       }
 7962 +       else {
 7963 +#if defined(ENABLE_PKCS11H_THREADING)
 7964 +           _pkcs11h_threading_mutexFree (&session->mutex);
 7965 +#endif
 7966 +           _pkcs11h_mem_free ((void *)&session);
 7967 +       }
 7968 +   }
 7969 +
 7970 +   if (rv == CKR_OK) {
 7971 +       *p_session = session;
 7972 +       session = NULL;
 7973 +   }
 7974 +
 7975 +#if defined(ENABLE_PKCS11H_THREADING)
 7976 +   if (mutex_locked) {
 7977 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.session);
 7978 +       mutex_locked = FALSE;
 7979 +   }
 7980 +#endif
 7981 +
 7982 +   PKCS11H_DEBUG (
 7983 +       PKCS11H_LOG_DEBUG2,
 7984 +       "PKCS#11: _pkcs11h_session_getSessionByTokenId return rv=%ld-'%s', *p_session=%p",
 7985 +       rv,
 7986 +       pkcs11h_getMessage (rv),
 7987 +       (void *)*p_session
 7988 +   );
 7989 +
 7990 +   return rv;
 7991 +}
 7992 +
 7993 +static
 7994 +CK_RV
 7995 +_pkcs11h_session_release (
 7996 +   IN const pkcs11h_session_t session
 7997 +) {
 7998 +#if defined(ENABLE_PKCS11H_THREADING)
 7999 +   PKCS11H_BOOL mutex_locked = FALSE;
 8000 +#endif
 8001 +   CK_RV rv = CKR_OK;
 8002 +
 8003 +   PKCS11H_ASSERT (session!=NULL);
 8004 +   PKCS11H_ASSERT (session->reference_count>=0);
 8005 +
 8006 +   PKCS11H_DEBUG (
 8007 +       PKCS11H_LOG_DEBUG2,
 8008 +       "PKCS#11: _pkcs11h_session_release entry session=%p",
 8009 +       (void *)session
 8010 +   );
 8011 +
 8012 +#if defined(ENABLE_PKCS11H_THREADING)
 8013 +   if (
 8014 +       rv == CKR_OK &&
 8015 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
 8016 +   ) {
 8017 +       mutex_locked = TRUE;
 8018 +   }
 8019 +#endif
 8020 +
 8021 +   /*
 8022 +    * Never logout for now
 8023 +    */
 8024 +   if (rv == CKR_OK) {
 8025 +       if (session->reference_count > 0) {
 8026 +           session->reference_count--;
 8027 +       }
 8028 +   }
 8029 +
 8030 +#if defined(ENABLE_PKCS11H_THREADING)
 8031 +   if (mutex_locked) {
 8032 +       _pkcs11h_threading_mutexRelease (&session->mutex);
 8033 +       mutex_locked = FALSE;
 8034 +   }
 8035 +#endif
 8036 +
 8037 +   PKCS11H_DEBUG (
 8038 +       PKCS11H_LOG_DEBUG2,
 8039 +       "PKCS#11: _pkcs11h_session_release return rv=%ld-'%s'",
 8040 +       rv,
 8041 +       pkcs11h_getMessage (rv)
 8042 +   );
 8043 +
 8044 +   return rv;
 8045 +}
 8046 +
 8047 +static
 8048 +CK_RV
 8049 +_pkcs11h_session_reset (
 8050 +   IN const pkcs11h_session_t session,
 8051 +   IN void * const user_data,
 8052 +   IN const unsigned mask_prompt,
 8053 +   OUT CK_SLOT_ID * const p_slot
 8054 +) {
 8055 +   PKCS11H_BOOL found = FALSE;
 8056 +
 8057 +   CK_RV rv = CKR_OK;
 8058 +
 8059 +   unsigned nRetry = 0;
 8060 +
 8061 +   PKCS11H_ASSERT (session!=NULL);
 8062 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 8063 +   PKCS11H_ASSERT (p_slot!=NULL);
 8064 +
 8065 +   PKCS11H_DEBUG (
 8066 +       PKCS11H_LOG_DEBUG2,
 8067 +       "PKCS#11: _pkcs11h_session_reset entry session=%p, user_data=%p, mask_prompt=%08x, p_slot=%p",
 8068 +       (void *)session,
 8069 +       user_data,
 8070 +       mask_prompt,
 8071 +       (void *)p_slot
 8072 +   );
 8073 +
 8074 +   *p_slot = PKCS11H_INVALID_SLOT_ID;
 8075 +
 8076 +   while (
 8077 +       rv == CKR_OK &&
 8078 +       !found
 8079 +   ) {
 8080 +       pkcs11h_provider_t current_provider = NULL;
 8081 +
 8082 +       for (
 8083 +           current_provider = s_pkcs11h_data->providers;
 8084 +           (
 8085 +               rv == CKR_OK &&
 8086 +               current_provider != NULL &&
 8087 +               !found
 8088 +           );
 8089 +           current_provider = current_provider->next
 8090 +       ) {
 8091 +           CK_SLOT_ID_PTR slots = NULL;
 8092 +           CK_ULONG slotnum;
 8093 +           CK_SLOT_ID slot_index;
 8094 +
 8095 +           /*
 8096 +            * Skip all other providers,
 8097 +            * if one was set in the past
 8098 +            */
 8099 +           if (
 8100 +               session->provider != NULL &&
 8101 +               session->provider != current_provider
 8102 +           ) {
 8103 +               rv = CKR_CANCEL;
 8104 +           }
 8105 +       
 8106 +           if (rv == CKR_OK) {
 8107 +               rv = _pkcs11h_session_getSlotList (
 8108 +                   current_provider,
 8109 +                   CK_TRUE,
 8110 +                   &slots,
 8111 +                   &slotnum
 8112 +               );
 8113 +           }
 8114 +
 8115 +           for (
 8116 +               slot_index=0;
 8117 +               (
 8118 +                   slot_index < slotnum &&
 8119 +                   rv == CKR_OK && 
 8120 +                   !found
 8121 +               );
 8122 +               slot_index++
 8123 +           ) {
 8124 +               pkcs11h_token_id_t token_id = NULL;
 8125 +               CK_TOKEN_INFO info;
 8126 +
 8127 +               if (rv == CKR_OK) {
 8128 +                   rv = current_provider->f->C_GetTokenInfo (
 8129 +                       slots[slot_index],
 8130 +                       &info
 8131 +                   );
 8132 +               }
 8133 +
 8134 +               if (
 8135 +                   rv == CKR_OK &&
 8136 +                   (rv = _pkcs11h_token_getTokenId (
 8137 +                       &info,
 8138 +                       &token_id
 8139 +                   )) == CKR_OK &&
 8140 +                   pkcs11h_token_sameTokenId (
 8141 +                       session->token_id,
 8142 +                       token_id
 8143 +                   )
 8144 +               ) {
 8145 +                   found = TRUE;
 8146 +                   *p_slot = slots[slot_index];
 8147 +                   if (session->provider == NULL) {
 8148 +                       session->provider = current_provider;
 8149 +                       session->allow_protected_auth_supported = (info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) != 0;
 8150 +                   }
 8151 +               }
 8152 +
 8153 +               if (rv != CKR_OK) {
 8154 +                   PKCS11H_DEBUG (
 8155 +                       PKCS11H_LOG_DEBUG1,
 8156 +                       "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%ld-'%s'",
 8157 +                       current_provider->manufacturerID,
 8158 +                       slots[slot_index],
 8159 +                       rv,
 8160 +                       pkcs11h_getMessage (rv)
 8161 +                   );
 8162 +
 8163 +                   /*
 8164 +                    * Ignore error
 8165 +                    */
 8166 +                   rv = CKR_OK;
 8167 +               }
 8168 +
 8169 +               if (token_id != NULL) {
 8170 +                   pkcs11h_token_freeTokenId (token_id);
 8171 +               }
 8172 +           }
 8173 +
 8174 +           if (rv != CKR_OK) {
 8175 +               PKCS11H_DEBUG (
 8176 +                   PKCS11H_LOG_DEBUG1,
 8177 +                   "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
 8178 +                   current_provider->manufacturerID,
 8179 +                   rv,
 8180 +                   pkcs11h_getMessage (rv)
 8181 +               );
 8182 +
 8183 +               /*
 8184 +                * Ignore error
 8185 +                */
 8186 +               rv = CKR_OK;
 8187 +           }
 8188 +
 8189 +           if (slots != NULL) {
 8190 +               _pkcs11h_mem_free ((void *)&slots);
 8191 +               slots = NULL;
 8192 +           }
 8193 +       }
 8194 +
 8195 +       if (rv == CKR_OK && !found && (mask_prompt & PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT) == 0) {
 8196 +           rv = CKR_TOKEN_NOT_PRESENT;
 8197 +       }
 8198 +
 8199 +       if (
 8200 +           rv == CKR_OK &&
 8201 +           !found
 8202 +       ) {
 8203 +           PKCS11H_DEBUG (
 8204 +               PKCS11H_LOG_DEBUG1,
 8205 +               "PKCS#11: Calling token_prompt hook for '%s'",
 8206 +               session->token_id->display
 8207 +           );
 8208 +   
 8209 +           if (
 8210 +               !s_pkcs11h_data->hooks.token_prompt (
 8211 +                   s_pkcs11h_data->hooks.token_prompt_data,
 8212 +                   user_data,
 8213 +                   session->token_id,
 8214 +                   nRetry++
 8215 +               )
 8216 +           ) {
 8217 +               rv = CKR_CANCEL;
 8218 +           }
 8219 +
 8220 +           PKCS11H_DEBUG (
 8221 +               PKCS11H_LOG_DEBUG1,
 8222 +               "PKCS#11: token_prompt returned %ld",
 8223 +               rv
 8224 +           );
 8225 +       }
 8226 +   }
 8227 +
 8228 +   PKCS11H_DEBUG (
 8229 +       PKCS11H_LOG_DEBUG2,
 8230 +       "PKCS#11: _pkcs11h_session_reset return rv=%ld-'%s', *p_slot=%ld",
 8231 +       rv,
 8232 +       pkcs11h_getMessage (rv),
 8233 +       *p_slot
 8234 +   );
 8235 +
 8236 +   return rv;
 8237 +}
 8238 +
 8239 +static
 8240 +CK_RV
 8241 +_pkcs11h_session_getObjectById (
 8242 +   IN const pkcs11h_session_t session,
 8243 +   IN const CK_OBJECT_CLASS class,
 8244 +   IN const CK_BYTE_PTR id,
 8245 +   IN const size_t id_size,
 8246 +   OUT CK_OBJECT_HANDLE * const p_handle
 8247 +) {
 8248 +   /*
 8249 +    * THREADING:
 8250 +    * session->mutex must be locked
 8251 +    */
 8252 +   CK_ATTRIBUTE filter[] = {
 8253 +       {CKA_CLASS, (void *)&class, sizeof (class)},
 8254 +       {CKA_ID, (void *)id, id_size}
 8255 +   };
 8256 +   CK_OBJECT_HANDLE *objects = NULL;
 8257 +   CK_ULONG objects_found = 0;
 8258 +   CK_RV rv = CKR_OK;
 8259 +   
 8260 +   /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
 8261 +   PKCS11H_ASSERT (id!=NULL);
 8262 +   PKCS11H_ASSERT (p_handle!=NULL);
 8263 +
 8264 +   PKCS11H_DEBUG (
 8265 +       PKCS11H_LOG_DEBUG2,
 8266 +       "PKCS#11: _pkcs11h_session_getObjectById entry session=%p, class=%ld, id=%p, id_size=%u, p_handle=%p",
 8267 +       (void *)session,
 8268 +       class,
 8269 +       id,
 8270 +       id_size,
 8271 +       (void *)p_handle
 8272 +   );
 8273 +
 8274 +   *p_handle = PKCS11H_INVALID_OBJECT_HANDLE;
 8275 +
 8276 +   if (rv == CKR_OK) {
 8277 +       rv = _pkcs11h_session_validate (session);
 8278 +   }
 8279 +
 8280 +   if (rv == CKR_OK) { 
 8281 +       rv = _pkcs11h_session_findObjects (
 8282 +           session,
 8283 +           filter,
 8284 +           sizeof (filter) / sizeof (CK_ATTRIBUTE),
 8285 +           &objects,
 8286 +           &objects_found
 8287 +       );
 8288 +   }
 8289 +
 8290 +   if (
 8291 +       rv == CKR_OK &&
 8292 +       objects_found == 0
 8293 +   ) {
 8294 +       rv = CKR_FUNCTION_REJECTED;
 8295 +   }
 8296 +
 8297 +   if (rv == CKR_OK) {
 8298 +       *p_handle = objects[0];
 8299 +   }
 8300 +
 8301 +   if (objects != NULL) {
 8302 +       _pkcs11h_mem_free ((void *)&objects);
 8303 +   }
 8304 +
 8305 +   PKCS11H_DEBUG (
 8306 +       PKCS11H_LOG_DEBUG2,
 8307 +       "PKCS#11: _pkcs11h_session_getObjectById return rv=%ld-'%s', *p_handle=%p",
 8308 +       rv,
 8309 +       pkcs11h_getMessage (rv),
 8310 +       (void *)*p_handle
 8311 +   );
 8312 +
 8313 +   return rv;
 8314 +}
 8315 +
 8316 +static
 8317 +CK_RV
 8318 +_pkcs11h_session_validate (
 8319 +   IN const pkcs11h_session_t session
 8320 +) {
 8321 +   CK_RV rv = CKR_OK;
 8322 +
 8323 +   /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
 8324 +
 8325 +   PKCS11H_DEBUG (
 8326 +       PKCS11H_LOG_DEBUG2,
 8327 +       "PKCS#11: _pkcs11h_session_validate entry session=%p",
 8328 +       (void *)session
 8329 +   );
 8330 +
 8331 +   if (
 8332 +       rv == CKR_OK &&
 8333 +       session == NULL
 8334 +   ) {
 8335 +       rv = CKR_SESSION_HANDLE_INVALID;
 8336 +   }
 8337 +
 8338 +   if (
 8339 +       rv == CKR_OK &&
 8340 +       (
 8341 +           session->provider == NULL ||
 8342 +           !session->provider->enabled ||
 8343 +           session->session_handle == PKCS11H_INVALID_SESSION_HANDLE
 8344 +       )
 8345 +   ) {
 8346 +       rv = CKR_SESSION_HANDLE_INVALID;
 8347 +   }
 8348 +
 8349 +   if (
 8350 +       rv == CKR_OK &&
 8351 +       session->pin_expire_time != (time_t)0 &&
 8352 +       session->pin_expire_time < PKCS11H_TIME (NULL)
 8353 +   ) {
 8354 +       PKCS11H_DEBUG (
 8355 +           PKCS11H_LOG_DEBUG1,
 8356 +           "PKCS#11: Forcing logout due to pin timeout"
 8357 +       );
 8358 +       _pkcs11h_session_logout (session);
 8359 +       rv = CKR_SESSION_HANDLE_INVALID;
 8360 +   }
 8361 +
 8362 +   PKCS11H_DEBUG (
 8363 +       PKCS11H_LOG_DEBUG2,
 8364 +       "PKCS#11: _pkcs11h_session_validate return rv=%ld-'%s'",
 8365 +       rv,
 8366 +       pkcs11h_getMessage (rv)
 8367 +   );
 8368 +
 8369 +   return rv;
 8370 +}
 8371 +
 8372 +static
 8373 +CK_RV
 8374 +_pkcs11h_session_touch (
 8375 +   IN const pkcs11h_session_t session
 8376 +) {
 8377 +   /*
 8378 +    * THREADING:
 8379 +    * session->mutex must be locked
 8380 +    */
 8381 +   PKCS11H_ASSERT (session!=NULL);
 8382 +
 8383 +   if (session->pin_cache_period == PKCS11H_PIN_CACHE_INFINITE) {
 8384 +       session->pin_expire_time = 0;
 8385 +   }
 8386 +   else {
 8387 +       session->pin_expire_time = (
 8388 +           PKCS11H_TIME (NULL) +
 8389 +           (time_t)session->pin_cache_period
 8390 +       );
 8391 +   }
 8392 +
 8393 +   return CKR_OK;
 8394 +}
 8395 +
 8396 +CK_RV
 8397 +pkcs11h_token_login (
 8398 +   IN const pkcs11h_token_id_t token_id,
 8399 +   IN const PKCS11H_BOOL readonly,
 8400 +   IN const char * const pin
 8401 +) {
 8402 +#if defined(ENABLE_PKCS11H_THREADING)
 8403 +   PKCS11H_BOOL mutex_locked = FALSE;
 8404 +#endif
 8405 +   CK_SLOT_ID slot = PKCS11H_INVALID_SLOT_ID;
 8406 +   CK_ULONG pin_size = 0;
 8407 +   CK_RV rv = CKR_OK;
 8408 +
 8409 +   pkcs11h_session_t session = NULL;
 8410 +
 8411 +   PKCS11H_ASSERT (token_id!=NULL);
 8412 +   /*PKCS11H_ASSERT (pin!=NULL); NOT NEEDED*/
 8413 +
 8414 +   PKCS11H_DEBUG (
 8415 +       PKCS11H_LOG_DEBUG2,
 8416 +       "PKCS#11: pkcs11h_token_login entry token_id=%p, readonly=%d\n", 
 8417 +       (void *)token_id,
 8418 +       readonly ? 1 : 0
 8419 +   );
 8420 +
 8421 +   if (pin != NULL) {
 8422 +       pin_size = strlen (pin);
 8423 +   }
 8424 +
 8425 +   if (rv == CKR_OK) {
 8426 +       rv = _pkcs11h_session_getSessionByTokenId (
 8427 +           token_id,
 8428 +           &session
 8429 +       );
 8430 +   }
 8431 +
 8432 +#if defined(ENABLE_PKCS11H_THREADING)
 8433 +   if (
 8434 +       rv == CKR_OK &&
 8435 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
 8436 +   ) {
 8437 +       mutex_locked = TRUE;
 8438 +   }
 8439 +#endif
 8440 +
 8441 +   if (rv == CKR_OK) {
 8442 +       rv = _pkcs11h_session_logout (session);
 8443 +   }
 8444 +
 8445 +   if (rv == CKR_OK) {
 8446 +       rv = _pkcs11h_session_reset (session, NULL, 0, &slot);
 8447 +   }
 8448 +
 8449 +   if (rv == CKR_OK) {
 8450 +       rv = _pkcs11h_session_touch (session);
 8451 +   }
 8452 +
 8453 +   if (rv == CKR_OK) {
 8454 +       rv = session->provider->f->C_OpenSession (
 8455 +           slot,
 8456 +           (
 8457 +               CKF_SERIAL_SESSION |
 8458 +               (readonly ? 0 : CKF_RW_SESSION)
 8459 +           ),
 8460 +           NULL_PTR,
 8461 +           NULL_PTR,
 8462 +           &session->session_handle
 8463 +       );
 8464 +   }
 8465 +
 8466 +   if (
 8467 +       rv == CKR_OK &&
 8468 +       (rv = session->provider->f->C_Login (
 8469 +           session->session_handle,
 8470 +           CKU_USER,
 8471 +           (CK_UTF8CHAR_PTR)pin,
 8472 +           pin_size
 8473 +       )) != CKR_OK
 8474 +   ) {
 8475 +       if (rv == CKR_USER_ALREADY_LOGGED_IN) {
 8476 +           rv = CKR_OK;
 8477 +       }
 8478 +   }
 8479 +
 8480 +#if defined(ENABLE_PKCS11H_THREADING)
 8481 +   if (mutex_locked) {
 8482 +       _pkcs11h_threading_mutexRelease (&session->mutex);
 8483 +       mutex_locked = FALSE;
 8484 +   }
 8485 +#endif
 8486 +
 8487 +   if (session != NULL) {
 8488 +       _pkcs11h_session_release (session);
 8489 +       session = NULL;
 8490 +   }
 8491 +
 8492 +   PKCS11H_DEBUG (
 8493 +       PKCS11H_LOG_DEBUG2,
 8494 +       "PKCS#11: pkcs11h_token_login return rv=%ld-'%s'",
 8495 +       rv,
 8496 +       pkcs11h_getMessage (rv)
 8497 +   );
 8498 +
 8499 +   return rv;
 8500 +}
 8501 +
 8502 +static
 8503 +CK_RV
 8504 +_pkcs11h_session_login (
 8505 +   IN const pkcs11h_session_t session,
 8506 +   IN const PKCS11H_BOOL is_publicOnly,
 8507 +   IN const PKCS11H_BOOL readonly,
 8508 +   IN void * const user_data,
 8509 +   IN const unsigned mask_prompt
 8510 +) {
 8511 +   /*
 8512 +    * THREADING:
 8513 +    * session->mutex must be locked
 8514 +    */
 8515 +   CK_SLOT_ID slot = PKCS11H_INVALID_SLOT_ID;
 8516 +   CK_RV rv = CKR_OK;
 8517 +
 8518 +   PKCS11H_ASSERT (session!=NULL);
 8519 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 8520 +
 8521 +   PKCS11H_DEBUG (
 8522 +       PKCS11H_LOG_DEBUG2,
 8523 +       "PKCS#11: _pkcs11h_session_login entry session=%p, is_publicOnly=%d, readonly=%d, user_data=%p,
	mask_prompt=%08x",
 8524 +       (void *)session,
 8525 +       is_publicOnly ? 1 : 0,
 8526 +       readonly ? 1 : 0,
 8527 +       user_data,
 8528 +       mask_prompt
 8529 +   );
 8530 +
 8531 +   if (rv == CKR_OK) {
 8532 +       rv = _pkcs11h_session_logout (session);
 8533 +   }
 8534 +
 8535 +   if (rv == CKR_OK) {
 8536 +       rv = _pkcs11h_session_reset (session, user_data, mask_prompt, &slot);
 8537 +   }
 8538 +
 8539 +   if (rv == CKR_OK) {
 8540 +       rv = session->provider->f->C_OpenSession (
 8541 +           slot,
 8542 +           (
 8543 +               CKF_SERIAL_SESSION |
 8544 +               (readonly ? 0 : CKF_RW_SESSION)
 8545 +           ),
 8546 +           NULL_PTR,
 8547 +           NULL_PTR,
 8548 +           &session->session_handle
 8549 +       );
 8550 +   }
 8551 +
 8552 +   if (
 8553 +       rv == CKR_OK &&
 8554 +       (
 8555 +           !is_publicOnly ||
 8556 +           session->provider->cert_is_private
 8557 +       )
 8558 +   ) {
 8559 +       PKCS11H_BOOL login_succeeded = FALSE;
 8560 +       unsigned nRetryCount = 0;
 8561 +
 8562 +       if ((mask_prompt & PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT) == 0) {
 8563 +           rv = CKR_USER_NOT_LOGGED_IN;
 8564 +
 8565 +           PKCS11H_DEBUG (
 8566 +               PKCS11H_LOG_DEBUG1,
 8567 +               "PKCS#11: Calling pin_prompt hook denied because of prompt mask"
 8568 +           );
 8569 +       }
 8570 +
 8571 +       while (
 8572 +           rv == CKR_OK &&
 8573 +           !login_succeeded &&
 8574 +           nRetryCount < s_pkcs11h_data->max_retries 
 8575 +       ) {
 8576 +           CK_UTF8CHAR_PTR utfPIN = NULL;
 8577 +           CK_ULONG lPINLength = 0;
 8578 +           char pin[1024];
 8579 +
 8580 +           if (
 8581 +               rv == CKR_OK &&
 8582 +               !(
 8583 +                   s_pkcs11h_data->allow_protected_auth  &&
 8584 +                   session->provider->allow_protected_auth &&
 8585 +                   session->allow_protected_auth_supported
 8586 +               )
 8587 +           ) {
 8588 +               PKCS11H_DEBUG (
 8589 +                   PKCS11H_LOG_DEBUG1,
 8590 +                   "PKCS#11: Calling pin_prompt hook for '%s'",
 8591 +                   session->token_id->display
 8592 +               );
 8593 +
 8594 +               if (
 8595 +                   !s_pkcs11h_data->hooks.pin_prompt (
 8596 +                       s_pkcs11h_data->hooks.pin_prompt_data,
 8597 +                       user_data,
 8598 +                       session->token_id,
 8599 +                       nRetryCount,
 8600 +                       pin,
 8601 +                       sizeof (pin)
 8602 +                   )
 8603 +               ) {
 8604 +                   rv = CKR_CANCEL;
 8605 +               }
 8606 +               else {
 8607 +                   utfPIN = (CK_UTF8CHAR_PTR)pin;
 8608 +                   lPINLength = strlen (pin);
 8609 +               }
 8610 +
 8611 +               PKCS11H_DEBUG (
 8612 +                   PKCS11H_LOG_DEBUG1,
 8613 +                   "PKCS#11: pin_prompt hook return rv=%ld",
 8614 +                   rv
 8615 +               );
 8616 +           }
 8617 +
 8618 +           if (rv == CKR_OK) {
 8619 +               rv = _pkcs11h_session_touch (session);
 8620 +           }
 8621 +
 8622 +           if (
 8623 +               rv == CKR_OK &&
 8624 +               (rv = session->provider->f->C_Login (
 8625 +                   session->session_handle,
 8626 +                   CKU_USER,
 8627 +                   utfPIN,
 8628 +                   lPINLength
 8629 +               )) != CKR_OK
 8630 +           ) {
 8631 +               if (rv == CKR_USER_ALREADY_LOGGED_IN) {
 8632 +                   rv = CKR_OK;
 8633 +               }
 8634 +           }
 8635 +
 8636 +           /*
 8637 +            * Clean PIN buffer
 8638 +            */
 8639 +           memset (pin, 0, sizeof (pin));
 8640 +
 8641 +           if (rv == CKR_OK) {
 8642 +               login_succeeded = TRUE;
 8643 +           }
 8644 +           else if (
 8645 +               rv == CKR_PIN_INCORRECT ||
 8646 +               rv == CKR_PIN_INVALID
 8647 +           ) {
 8648 +               /*
 8649 +                * Ignore these errors
 8650 +                * so retry can be performed
 8651 +                */
 8652 +               rv = CKR_OK;
 8653 +           }
 8654 +
 8655 +           nRetryCount++;
 8656 +       }
 8657 +
 8658 +       /*
 8659 +        * Retry limit
 8660 +        */
 8661 +       if (!login_succeeded && rv == CKR_OK) {
 8662 +           rv = CKR_PIN_INCORRECT;
 8663 +       }
 8664 +   }
 8665 +
 8666 +   PKCS11H_DEBUG (
 8667 +       PKCS11H_LOG_DEBUG2,
 8668 +       "PKCS#11: _pkcs11h_session_login return rv=%ld-'%s'",
 8669 +       rv,
 8670 +       pkcs11h_getMessage (rv)
 8671 +   );
 8672 +
 8673 +   return rv;
 8674 +}
 8675 +
 8676 +static
 8677 +CK_RV
 8678 +_pkcs11h_session_logout (
 8679 +   IN const pkcs11h_session_t session
 8680 +) {
 8681 +   /*
 8682 +    * THREADING:
 8683 +    * session->mutex must be locked
 8684 +    */
 8685 +   /*PKCS11H_ASSERT (session!=NULL); NOT NEEDED*/
 8686 +
 8687 +   PKCS11H_DEBUG (
 8688 +       PKCS11H_LOG_DEBUG2,
 8689 +       "PKCS#11: _pkcs11h_session_logout entry session=%p",
 8690 +       (void *)session
 8691 +   );
 8692 +
 8693 +   if (
 8694 +       session != NULL &&
 8695 +       session->session_handle != PKCS11H_INVALID_SESSION_HANDLE
 8696 +   ) {
 8697 +       CK_RV rv = CKR_OK;
 8698 +
 8699 +       if (rv == CKR_OK) {
 8700 +           if (session->provider != NULL) {
 8701 +               session->provider->f->C_Logout (session->session_handle);
 8702 +               session->provider->f->C_CloseSession (session->session_handle);
 8703 +           }
 8704 +           session->session_handle = PKCS11H_INVALID_SESSION_HANDLE;
 8705 +       }
 8706 +   }
 8707 +
 8708 +   PKCS11H_DEBUG (
 8709 +       PKCS11H_LOG_DEBUG2,
 8710 +       "PKCS#11: _pkcs11h_session_logout return"
 8711 +   );
 8712 +
 8713 +   return CKR_OK;
 8714 +}
 8715 +
 8716 +static
 8717 +void
 8718 +_pkcs11h_hooks_default_log (
 8719 +   IN void * const global_data,
 8720 +   IN const unsigned flags,
 8721 +   IN const char * const format,
 8722 +   IN va_list args
 8723 +) {
 8724 +   (void)global_data;
 8725 +   (void)flags;
 8726 +   (void)format;
 8727 +   (void)args;
 8728 +}
 8729 +
 8730 +static
 8731 +PKCS11H_BOOL
 8732 +_pkcs11h_hooks_default_token_prompt (
 8733 +   IN void * const global_data,
 8734 +   IN void * const user_data,
 8735 +   IN const pkcs11h_token_id_t token,
 8736 +   IN const unsigned retry
 8737 +) {
 8738 +   /*PKCS11H_ASSERT (global_data) NOT NEEDED */
 8739 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 8740 +   PKCS11H_ASSERT (token!=NULL);
 8741 +
 8742 +   (void)global_data;
 8743 +   (void)user_data;
 8744 +   (void)retry;
 8745 +
 8746 +   PKCS11H_DEBUG (
 8747 +       PKCS11H_LOG_DEBUG2,
 8748 +       "PKCS#11: _pkcs11h_hooks_default_token_prompt global_data=%p, user_data=%p, display='%s'",
 8749 +       global_data,
 8750 +       user_data,
 8751 +       token->display
 8752 +   );
 8753 +
 8754 +   return FALSE;
 8755 +}
 8756 +
 8757 +static
 8758 +PKCS11H_BOOL
 8759 +_pkcs11h_hooks_default_pin_prompt (
 8760 +   IN void * const global_data,
 8761 +   IN void * const user_data,
 8762 +   IN const pkcs11h_token_id_t token,
 8763 +   IN const unsigned retry,
 8764 +   OUT char * const pin,
 8765 +   IN const size_t pin_max
 8766 +) {
 8767 +   /*PKCS11H_ASSERT (global_data) NOT NEEDED */
 8768 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 8769 +   PKCS11H_ASSERT (token!=NULL);
 8770 +
 8771 +   (void)global_data;
 8772 +   (void)user_data;
 8773 +   (void)retry;
 8774 +   (void)pin;
 8775 +   (void)pin_max;
 8776 +
 8777 +   PKCS11H_DEBUG (
 8778 +       PKCS11H_LOG_DEBUG2,
 8779 +       "PKCS#11: _pkcs11h_hooks_default_pin_prompt global_data=%p, user_data=%p, display='%s'",
 8780 +       global_data,
 8781 +       user_data,
 8782 +       token->display
 8783 +   );
 8784 +   
 8785 +   return FALSE;
 8786 +}
 8787 +
 8788 +#if !defined(WIN32)
 8789 +#if defined(ENABLE_PKCS11H_THREADING)
 8790 +
 8791 +static
 8792 +void
 8793 +__pkcs11h_threading_atfork_prepare  () {
 8794 +   __pkcs1h_threading_mutexLockAll ();
 8795 +}
 8796 +static
 8797 +void
 8798 +__pkcs11h_threading_atfork_parent () {
 8799 +   __pkcs1h_threading_mutexReleaseAll ();
 8800 +}
 8801 +static
 8802 +void
 8803 +__pkcs11h_threading_atfork_child () {
 8804 +   __pkcs1h_threading_mutexReleaseAll ();
 8805 +   _pkcs11h_forkFixup ();
 8806 +}
 8807 +
 8808 +#endif             /* ENABLE_PKCS11H_THREADING */
 8809 +
 8810 +static
 8811 +CK_RV
 8812 +_pkcs11h_forkFixup () {
 8813 +#if defined(ENABLE_PKCS11H_THREADING)
 8814 +   PKCS11H_BOOL mutex_locked = FALSE;
 8815 +#endif
 8816 +   pid_t mypid = getpid ();
 8817 +
 8818 +   PKCS11H_DEBUG (
 8819 +       PKCS11H_LOG_DEBUG2,
 8820 +       "PKCS#11: pkcs11h_forkFixup entry pid=%d",
 8821 +       mypid
 8822 +   );
 8823 +
 8824 +   if (s_pkcs11h_data != NULL && s_pkcs11h_data->initialized) {
 8825 +       pkcs11h_provider_t current;
 8826 +
 8827 +#if defined(ENABLE_PKCS11H_THREADING)
 8828 +       if (_pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global) == CKR_OK) {
 8829 +           mutex_locked = TRUE;
 8830 +       }
 8831 +#endif
 8832 +
 8833 +       for (
 8834 +           current = s_pkcs11h_data->providers;
 8835 +           current != NULL;
 8836 +           current = current->next
 8837 +       ) {
 8838 +           if (current->enabled) {
 8839 +               current->f->C_Initialize (NULL);
 8840 +           }
 8841 +
 8842 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
 8843 +           /*
 8844 +            * After fork we have no threads...
 8845 +            * So just initialized.
 8846 +            */
 8847 +           if (s_pkcs11h_data->slotevent.initialized) {
 8848 +               s_pkcs11h_data->slotevent.initialized = FALSE;
 8849 +               _pkcs11h_slotevent_init ();
 8850 +           }
 8851 +#endif
 8852 +       }
 8853 +   }
 8854 +
 8855 +#if defined(ENABLE_PKCS11H_THREADING)
 8856 +   if (mutex_locked) {
 8857 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
 8858 +       mutex_locked = FALSE;
 8859 +   }
 8860 +#endif
 8861 +
 8862 +   PKCS11H_DEBUG (
 8863 +       PKCS11H_LOG_DEBUG2,
 8864 +       "PKCS#11: pkcs11h_forkFixup return"
 8865 +   );
 8866 +
 8867 +   return CKR_OK;
 8868 +}
 8869 +
 8870 +#endif             /* !WIN32 */
 8871 +
 8872 +#if defined(ENABLE_PKCS11H_TOKEN)
 8873 +/*======================================================================*
 8874 + * TOKEN INTERFACE
 8875 + *======================================================================*/
 8876 +
 8877 +CK_RV
 8878 +pkcs11h_token_ensureAccess (
 8879 +   IN const pkcs11h_token_id_t token_id,
 8880 +   IN void * const user_data,
 8881 +   IN const unsigned mask_prompt
 8882 +) {
 8883 +#if defined(ENABLE_PKCS11H_THREADING)
 8884 +   PKCS11H_BOOL mutex_locked = FALSE;
 8885 +#endif
 8886 +   pkcs11h_session_t session = NULL;
 8887 +   CK_RV rv = CKR_OK;
 8888 +
 8889 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 8890 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 8891 +   PKCS11H_ASSERT (token_id!=NULL);
 8892 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 8893 +
 8894 +   PKCS11H_DEBUG (
 8895 +       PKCS11H_LOG_DEBUG2,
 8896 +       "PKCS#11: pkcs11h_token_ensureAccess entry token_id=%p, user_data=%p, mask_prompt=%08x",
 8897 +       (void *)token_id,
 8898 +       user_data,
 8899 +       mask_prompt
 8900 +   );
 8901 +
 8902 +   if (rv == CKR_OK) {
 8903 +       rv = _pkcs11h_session_getSessionByTokenId (
 8904 +           token_id,
 8905 +           &session
 8906 +       );
 8907 +   }
 8908 +
 8909 +#if defined(ENABLE_PKCS11H_THREADING)
 8910 +   if (
 8911 +       rv == CKR_OK &&
 8912 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
 8913 +   ) {
 8914 +       mutex_locked = TRUE;
 8915 +   }
 8916 +#endif
 8917 +
 8918 +   if (rv == CKR_OK) {
 8919 +       CK_SLOT_ID slot;
 8920 +
 8921 +       rv = _pkcs11h_session_reset (
 8922 +           session,
 8923 +           user_data,
 8924 +           mask_prompt,
 8925 +           &slot
 8926 +       );
 8927 +   }
 8928 +
 8929 +#if defined(ENABLE_PKCS11H_THREADING)
 8930 +   if (mutex_locked) {
 8931 +       _pkcs11h_threading_mutexRelease (&session->mutex);
 8932 +       mutex_locked = FALSE;
 8933 +   }
 8934 +#endif
 8935 +
 8936 +   if (session != NULL) {
 8937 +       _pkcs11h_session_release (session);
 8938 +       session = NULL;
 8939 +   }
 8940 +
 8941 +   PKCS11H_DEBUG (
 8942 +       PKCS11H_LOG_DEBUG2,
 8943 +       "PKCS#11: pkcs11h_token_ensureAccess return rv=%ld-'%s'",
 8944 +       rv,
 8945 +       pkcs11h_getMessage (rv)
 8946 +   );
 8947 +
 8948 +   return rv;
 8949 +}
 8950 +
 8951 +#endif             /* ENABLE_PKCS11H_TOKEN */
 8952 +
 8953 +#if defined(ENABLE_PKCS11H_DATA)
 8954 +/*======================================================================*
 8955 + * DATA INTERFACE
 8956 + *======================================================================*/
 8957 +
 8958 +static
 8959 +CK_RV
 8960 +_pkcs11h_data_getObject (
 8961 +   IN const pkcs11h_session_t session,
 8962 +   IN const char * const application,
 8963 +   IN const char * const label,
 8964 +   OUT CK_OBJECT_HANDLE * const p_handle
 8965 +) {
 8966 +   CK_OBJECT_CLASS class = CKO_DATA;
 8967 +   CK_ATTRIBUTE filter[] = {
 8968 +       {CKA_CLASS, (void *)&class, sizeof (class)},
 8969 +       {CKA_APPLICATION, (void *)application, application == NULL ? 0 : strlen (application)},
 8970 +       {CKA_LABEL, (void *)label, label == NULL ? 0 : strlen (label)}
 8971 +   };
 8972 +   CK_OBJECT_HANDLE *objects = NULL;
 8973 +   CK_ULONG objects_found = 0;
 8974 +   CK_RV rv = CKR_OK;
 8975 +   
 8976 +   PKCS11H_ASSERT (session!=NULL);
 8977 +   PKCS11H_ASSERT (application!=NULL);
 8978 +   PKCS11H_ASSERT (label!=NULL);
 8979 +
 8980 +   PKCS11H_DEBUG (
 8981 +       PKCS11H_LOG_DEBUG2,
 8982 +       "PKCS#11: _pkcs11h_data_getObject entry session=%p, application='%s', label='%s', p_handle=%p",
 8983 +       (void *)session,
 8984 +       application,
 8985 +       label,
 8986 +       (void *)p_handle
 8987 +   );
 8988 +
 8989 +   *p_handle = PKCS11H_INVALID_OBJECT_HANDLE;
 8990 +
 8991 +   if (rv == CKR_OK) {
 8992 +       rv = _pkcs11h_session_validate (session);
 8993 +   }
 8994 +
 8995 +   if (rv == CKR_OK) {
 8996 +       rv = _pkcs11h_session_findObjects (
 8997 +           session,
 8998 +           filter,
 8999 +           sizeof (filter) / sizeof (CK_ATTRIBUTE),
 9000 +           &objects,
 9001 +           &objects_found
 9002 +       );
 9003 +   }
 9004 +
 9005 +   if (
 9006 +       rv == CKR_OK &&
 9007 +       objects_found == 0
 9008 +   ) {
 9009 +       rv = CKR_FUNCTION_REJECTED;
 9010 +   }
 9011 +
 9012 +   if (rv == CKR_OK) {
 9013 +       *p_handle = objects[0];
 9014 +   }
 9015 +
 9016 +   if (objects != NULL) {
 9017 +       _pkcs11h_mem_free ((void *)&objects);
 9018 +   }
 9019 +
 9020 +   PKCS11H_DEBUG (
 9021 +       PKCS11H_LOG_DEBUG2,
 9022 +       "PKCS#11: _pkcs11h_data_getObject return rv=%ld-'%s', *p_handle=%p",
 9023 +       rv,
 9024 +       pkcs11h_getMessage (rv),
 9025 +       (void *)*p_handle
 9026 +   );
 9027 +
 9028 +   return rv;
 9029 +}
 9030 +
 9031 +CK_RV
 9032 +pkcs11h_data_get (
 9033 +   IN const pkcs11h_token_id_t token_id,
 9034 +   IN const PKCS11H_BOOL is_public,
 9035 +   IN const char * const application,
 9036 +   IN const char * const label,
 9037 +   IN void * const user_data,
 9038 +   IN const unsigned mask_prompt,
 9039 +   OUT unsigned char * const blob,
 9040 +   IN OUT size_t * const p_blob_size
 9041 +) {
 9042 +   CK_ATTRIBUTE attrs[] = {
 9043 +       {CKA_VALUE, NULL, 0}
 9044 +   };
 9045 +   CK_OBJECT_HANDLE handle = PKCS11H_INVALID_OBJECT_HANDLE;
 9046 +   CK_RV rv = CKR_OK;
 9047 +
 9048 +#if defined(ENABLE_PKCS11H_THREADING)
 9049 +   PKCS11H_BOOL mutex_locked = FALSE;
 9050 +#endif
 9051 +   pkcs11h_session_t session = NULL;
 9052 +   PKCS11H_BOOL op_succeed = FALSE;
 9053 +   PKCS11H_BOOL login_retry = FALSE;
 9054 +   size_t blob_size_max = 0;
 9055 +
 9056 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 9057 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 9058 +   PKCS11H_ASSERT (token_id!=NULL);
 9059 +   PKCS11H_ASSERT (application!=NULL);
 9060 +   PKCS11H_ASSERT (label!=NULL);
 9061 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 9062 +   /*PKCS11H_ASSERT (blob!=NULL); NOT NEEDED*/
 9063 +   PKCS11H_ASSERT (p_blob_size!=NULL);
 9064 +
 9065 +   PKCS11H_DEBUG (
 9066 +       PKCS11H_LOG_DEBUG2,
 9067 +       "PKCS#11: pkcs11h_data_get entry token_id=%p, application='%s', label='%s', user_data=%p, mask_prompt=%08x,
	blob=%p, *p_blob_size=%u",
 9068 +       (void *)token_id,
 9069 +       application,
 9070 +       label,
 9071 +       user_data,
 9072 +       mask_prompt,
 9073 +       blob,
 9074 +       blob != NULL ? *p_blob_size : 0
 9075 +   );
 9076 +
 9077 +   if (blob != NULL) {
 9078 +       blob_size_max = *p_blob_size;
 9079 +   }
 9080 +   *p_blob_size = 0;
 9081 +
 9082 +   if (rv == CKR_OK) {
 9083 +       rv = _pkcs11h_session_getSessionByTokenId (
 9084 +           token_id,
 9085 +           &session
 9086 +       );
 9087 +   }
 9088 +
 9089 +#if defined(ENABLE_PKCS11H_THREADING)
 9090 +   if (
 9091 +       rv == CKR_OK &&
 9092 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
 9093 +   ) {
 9094 +       mutex_locked = TRUE;
 9095 +   }
 9096 +#endif
 9097 +
 9098 +   while (rv == CKR_OK && !op_succeed) {
 9099 +
 9100 +       if (rv == CKR_OK) {
 9101 +           rv = _pkcs11h_session_validate (session);
 9102 +       }
 9103 +
 9104 +       if (rv == CKR_OK) {
 9105 +           rv = _pkcs11h_data_getObject (
 9106 +               session,
 9107 +               application,
 9108 +               label,
 9109 +               &handle
 9110 +           );
 9111 +       }
 9112 +
 9113 +       if (rv == CKR_OK) {
 9114 +           rv = _pkcs11h_session_getObjectAttributes (
 9115 +               session,
 9116 +               handle,
 9117 +               attrs,
 9118 +               sizeof (attrs)/sizeof (CK_ATTRIBUTE)
 9119 +           );
 9120 +       }
 9121 +
 9122 +       if (rv == CKR_OK) {
 9123 +           op_succeed = TRUE;
 9124 +       }
 9125 +       else {
 9126 +           if (!login_retry) {
 9127 +               PKCS11H_DEBUG (
 9128 +                   PKCS11H_LOG_DEBUG1,
 9129 +                   "PKCS#11: Read data object failed rv=%ld-'%s'",
 9130 +                   rv,
 9131 +                   pkcs11h_getMessage (rv)
 9132 +               );
 9133 +               login_retry = TRUE;
 9134 +               rv = _pkcs11h_session_login (
 9135 +                   session,
 9136 +                   is_public,
 9137 +                   TRUE,
 9138 +                   user_data,
 9139 +                   mask_prompt
 9140 +               );
 9141 +           }
 9142 +       }
 9143 +   }
 9144 +
 9145 +#if defined(ENABLE_PKCS11H_THREADING)
 9146 +   if (mutex_locked) {
 9147 +       _pkcs11h_threading_mutexRelease (&session->mutex);
 9148 +       mutex_locked = FALSE;
 9149 +   }
 9150 +#endif
 9151 +
 9152 +   if (rv == CKR_OK) {
 9153 +       *p_blob_size = attrs[0].ulValueLen;
 9154 +   }
 9155 +
 9156 +   if (rv == CKR_OK) {
 9157 +       if (blob != NULL) {
 9158 +           if (*p_blob_size > blob_size_max) {
 9159 +               rv = CKR_BUFFER_TOO_SMALL;
 9160 +           }
 9161 +           else {
 9162 +               memmove (blob, attrs[0].pValue, *p_blob_size);
 9163 +           }
 9164 +       }
 9165 +   }
 9166 +
 9167 +   _pkcs11h_session_freeObjectAttributes (
 9168 +       attrs,
 9169 +       sizeof (attrs)/sizeof (CK_ATTRIBUTE)
 9170 +   );
 9171 +
 9172 +   if (session != NULL) {
 9173 +       _pkcs11h_session_release (session);
 9174 +       session = NULL;
 9175 +   }
 9176 +
 9177 +   PKCS11H_DEBUG (
 9178 +       PKCS11H_LOG_DEBUG2,
 9179 +       "PKCS#11: pkcs11h_data_get return rv=%ld-'%s', *p_blob_size=%u",
 9180 +       rv,
 9181 +       pkcs11h_getMessage (rv),
 9182 +       *p_blob_size
 9183 +   );
 9184 +
 9185 +   return rv;
 9186 +}
 9187 +
 9188 +CK_RV
 9189 +pkcs11h_data_put (
 9190 +   IN const pkcs11h_token_id_t token_id,
 9191 +   IN const PKCS11H_BOOL is_public,
 9192 +   IN const char * const application,
 9193 +   IN const char * const label,
 9194 +   IN void * const user_data,
 9195 +   IN const unsigned mask_prompt,
 9196 +   OUT unsigned char * const blob,
 9197 +   IN const size_t blob_size
 9198 +) {
 9199 +   CK_OBJECT_CLASS class = CKO_DATA;
 9200 +   CK_BBOOL ck_true = CK_TRUE;
 9201 +   CK_BBOOL ck_false = CK_FALSE;
 9202 +
 9203 +   CK_ATTRIBUTE attrs[] = {
 9204 +       {CKA_CLASS, &class, sizeof (class)},
 9205 +       {CKA_TOKEN, &ck_true, sizeof (ck_true)},
 9206 +       {CKA_PRIVATE, is_public ? &ck_false : &ck_true, sizeof (CK_BBOOL)},
 9207 +       {CKA_APPLICATION, (void *)application, strlen (application)},
 9208 +       {CKA_LABEL, (void *)label, strlen (label)},
 9209 +       {CKA_VALUE, blob, blob_size}
 9210 +   };
 9211 +
 9212 +   CK_OBJECT_HANDLE handle = PKCS11H_INVALID_OBJECT_HANDLE;
 9213 +   CK_RV rv = CKR_OK;
 9214 +
 9215 +#if defined(ENABLE_PKCS11H_THREADING)
 9216 +   PKCS11H_BOOL mutex_locked = FALSE;
 9217 +#endif
 9218 +   pkcs11h_session_t session = NULL;
 9219 +   PKCS11H_BOOL op_succeed = FALSE;
 9220 +   PKCS11H_BOOL login_retry = FALSE;
 9221 +
 9222 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 9223 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 9224 +   PKCS11H_ASSERT (token_id!=NULL);
 9225 +   PKCS11H_ASSERT (application!=NULL);
 9226 +   PKCS11H_ASSERT (label!=NULL);
 9227 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 9228 +   PKCS11H_ASSERT (blob!=NULL);
 9229 +
 9230 +   PKCS11H_DEBUG (
 9231 +       PKCS11H_LOG_DEBUG2,
 9232 +       "PKCS#11: pkcs11h_data_put entry token_id=%p, application='%s', label='%s', user_data=%p, mask_prompt=%08x,
	blob=%p, blob_size=%u",
 9233 +       (void *)token_id,
 9234 +       application,
 9235 +       label,
 9236 +       user_data,
 9237 +       mask_prompt,
 9238 +       blob,
 9239 +       blob != NULL ? blob_size : 0
 9240 +   );
 9241 +
 9242 +   if (rv == CKR_OK) {
 9243 +       rv = _pkcs11h_session_getSessionByTokenId (
 9244 +           token_id,
 9245 +           &session
 9246 +       );
 9247 +   }
 9248 +
 9249 +#if defined(ENABLE_PKCS11H_THREADING)
 9250 +   if (
 9251 +       rv == CKR_OK &&
 9252 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
 9253 +   ) {
 9254 +       mutex_locked = TRUE;
 9255 +   }
 9256 +#endif
 9257 +
 9258 +   while (rv == CKR_OK && !op_succeed) {
 9259 +
 9260 +       if (rv == CKR_OK) {
 9261 +           rv = _pkcs11h_session_validate (session);
 9262 +       }
 9263 +
 9264 +       if (rv == CKR_OK) {
 9265 +           rv = session->provider->f->C_CreateObject (
 9266 +               session->session_handle,
 9267 +               attrs,
 9268 +               sizeof (attrs)/sizeof (CK_ATTRIBUTE),
 9269 +               &handle
 9270 +           );
 9271 +       }
 9272 +
 9273 +       if (rv == CKR_OK) {
 9274 +           op_succeed = TRUE;
 9275 +       }
 9276 +       else {
 9277 +           if (!login_retry) {
 9278 +               PKCS11H_DEBUG (
 9279 +                   PKCS11H_LOG_DEBUG1,
 9280 +                   "PKCS#11: Write data object failed rv=%ld-'%s'",
 9281 +                   rv,
 9282 +                   pkcs11h_getMessage (rv)
 9283 +               );
 9284 +               login_retry = TRUE;
 9285 +               rv = _pkcs11h_session_login (
 9286 +                   session,
 9287 +                   is_public,
 9288 +                   FALSE,
 9289 +                   user_data,
 9290 +                   mask_prompt
 9291 +               );
 9292 +           }
 9293 +       }
 9294 +   }
 9295 +
 9296 +#if defined(ENABLE_PKCS11H_THREADING)
 9297 +   if (mutex_locked) {
 9298 +       _pkcs11h_threading_mutexRelease (&session->mutex);
 9299 +       mutex_locked = FALSE;
 9300 +   }
 9301 +#endif
 9302 +
 9303 +   if (session != NULL) {
 9304 +       _pkcs11h_session_release (session);
 9305 +       session = NULL;
 9306 +   }
 9307 +
 9308 +   PKCS11H_DEBUG (
 9309 +       PKCS11H_LOG_DEBUG2,
 9310 +       "PKCS#11: pkcs11h_data_put return rv=%ld-'%s'",
 9311 +       rv,
 9312 +       pkcs11h_getMessage (rv)
 9313 +   );
 9314 +
 9315 +   return rv;
 9316 +}
 9317 +
 9318 +CK_RV
 9319 +pkcs11h_data_del (
 9320 +   IN const pkcs11h_token_id_t token_id,
 9321 +   IN const PKCS11H_BOOL is_public,
 9322 +   IN const char * const application,
 9323 +   IN const char * const label,
 9324 +   IN void * const user_data,
 9325 +   IN const unsigned mask_prompt
 9326 +) {
 9327 +#if defined(ENABLE_PKCS11H_THREADING)
 9328 +   PKCS11H_BOOL mutex_locked = FALSE;
 9329 +#endif
 9330 +   pkcs11h_session_t session = NULL;
 9331 +   PKCS11H_BOOL op_succeed = FALSE;
 9332 +   PKCS11H_BOOL login_retry = FALSE;
 9333 +   CK_OBJECT_HANDLE handle = PKCS11H_INVALID_OBJECT_HANDLE;
 9334 +   CK_RV rv = CKR_OK;
 9335 +
 9336 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
 9337 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
 9338 +   PKCS11H_ASSERT (token_id!=NULL);
 9339 +   PKCS11H_ASSERT (application!=NULL);
 9340 +   PKCS11H_ASSERT (label!=NULL);
 9341 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
 9342 +
 9343 +   PKCS11H_DEBUG (
 9344 +       PKCS11H_LOG_DEBUG2,
 9345 +       "PKCS#11: pkcs11h_data_del entry token_id=%p, application='%s', label='%s', user_data=%p, mask_prompt=%08x",
 9346 +       (void *)token_id,
 9347 +       application,
 9348 +       label,
 9349 +       user_data,
 9350 +       mask_prompt
 9351 +   );
 9352 +
 9353 +   if (rv == CKR_OK) {
 9354 +       rv = _pkcs11h_session_getSessionByTokenId (
 9355 +           token_id,
 9356 +           &session
 9357 +       );
 9358 +   }
 9359 +
 9360 +#if defined(ENABLE_PKCS11H_THREADING)
 9361 +   if (
 9362 +       rv == CKR_OK &&
 9363 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
 9364 +   ) {
 9365 +       mutex_locked = TRUE;
 9366 +   }
 9367 +#endif
 9368 +
 9369 +   while (rv == CKR_OK && !op_succeed) {
 9370 +
 9371 +       if (rv == CKR_OK) {
 9372 +           rv = _pkcs11h_session_validate (session);
 9373 +       }
 9374 +
 9375 +       if (rv == CKR_OK) {
 9376 +           rv = _pkcs11h_data_getObject (
 9377 +               session,
 9378 +               application,
 9379 +               label,
 9380 +               &handle
 9381 +           );
 9382 +       }
 9383 +
 9384 +       if (rv == CKR_OK) {
 9385 +           rv = session->provider->f->C_DestroyObject (
 9386 +               session->session_handle,
 9387 +               handle
 9388 +           );
 9389 +       }
 9390 +
 9391 +       if (rv == CKR_OK) {
 9392 +           op_succeed = TRUE;
 9393 +       }
 9394 +       else {
 9395 +           if (!login_retry) {
 9396 +               PKCS11H_DEBUG (
 9397 +                   PKCS11H_LOG_DEBUG1,
 9398 +                   "PKCS#11: Remove data object failed rv=%ld-'%s'",
 9399 +                   rv,
 9400 +                   pkcs11h_getMessage (rv)
 9401 +               );
 9402 +               login_retry = TRUE;
 9403 +               rv = _pkcs11h_session_login (
 9404 +                   session,
 9405 +                   is_public,
 9406 +                   FALSE,
 9407 +                   user_data,
 9408 +                   mask_prompt
 9409 +               );
 9410 +           }
 9411 +       }
 9412 +   }
 9413 +
 9414 +#if defined(ENABLE_PKCS11H_THREADING)
 9415 +       if (mutex_locked) {
 9416 +           _pkcs11h_threading_mutexRelease (&session->mutex);
 9417 +           mutex_locked = FALSE;
 9418 +       }
 9419 +#endif
 9420 +
 9421 +   if (session != NULL) {
 9422 +       _pkcs11h_session_release (session);
 9423 +       session = NULL;
 9424 +   }
 9425 +
 9426 +   PKCS11H_DEBUG (
 9427 +       PKCS11H_LOG_DEBUG2,
 9428 +       "PKCS#11: pkcs11h_data_del return rv=%ld-'%s'",
 9429 +       rv,
 9430 +       pkcs11h_getMessage (rv)
 9431 +   );
 9432 +
 9433 +   return rv;
 9434 +}
 9435 +
 9436 +#endif             /* ENABLE_PKCS11H_DATA */
 9437 +
 9438 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
 9439 +/*======================================================================*
 9440 + * CERTIFICATE INTERFACE
 9441 + *======================================================================*/
 9442 +
 9443 +static
 9444 +time_t
 9445 +_pkcs11h_certificate_getExpiration (
 9446 +   IN const unsigned char * const certificate,
 9447 +   IN const size_t certificate_size
 9448 +) {
 9449 +   /*
 9450 +    * This function compare the notAfter
 9451 +    * and select the most recent certificate
 9452 +    */
 9453 +
 9454 +#if defined(USE_PKCS11H_OPENSSL)
 9455 +   X509 *x509 = NULL;
 9456 +#elif defined(USE_PKCS11H_GNUTLS)
 9457 +   gnutls_x509_crt_t cert = NULL;
 9458 +#endif
 9459 +   time_t expire = (time_t)0;
 9460 +
 9461 +   PKCS11H_ASSERT (certificate!=NULL);
 9462 +
 9463 +#if defined(USE_PKCS11H_OPENSSL)
 9464 +   x509 = X509_new ();
 9465 +
 9466 +   if (x509 != NULL) {
 9467 +       pkcs11_openssl_d2i_t d2i = (pkcs11_openssl_d2i_t)certificate;
 9468 +
 9469 +       if (
 9470 +           d2i_X509 (&x509, &d2i, certificate_size)
 9471 +       ) {
 9472 +           ASN1_TIME *notBefore = X509_get_notBefore (x509);
 9473 +           ASN1_TIME *notAfter = X509_get_notAfter (x509);
 9474 +
 9475 +           if (
 9476 +               notBefore != NULL &&
 9477 +               notAfter != NULL &&
 9478 +               X509_cmp_current_time (notBefore) <= 0 &&
 9479 +               X509_cmp_current_time (notAfter) >= 0 &&
 9480 +               notAfter->length >= 12
 9481 +           ) {
 9482 +               struct tm tm1;
 9483 +               time_t now = time (NULL);
 9484 +
 9485 +               memset (&tm1, 0, sizeof (tm1));
 9486 +               tm1.tm_year = (notAfter->data[ 0] - '0') * 10 + (notAfter->data[ 1] - '0') + 100;
 9487 +               tm1.tm_mon  = (notAfter->data[ 2] - '0') * 10 + (notAfter->data[ 3] - '0') - 1;
 9488 +               tm1.tm_mday = (notAfter->data[ 4] - '0') * 10 + (notAfter->data[ 5] - '0');
 9489 +               tm1.tm_hour = (notAfter->data[ 6] - '0') * 10 + (notAfter->data[ 7] - '0');
 9490 +               tm1.tm_min  = (notAfter->data[ 8] - '0') * 10 + (notAfter->data[ 9] - '0');
 9491 +               tm1.tm_sec  = (notAfter->data[10] - '0') * 10 + (notAfter->data[11] - '0');
 9492 +
 9493 +               tm1.tm_sec += (int)(mktime (localtime (&now)) - mktime (gmtime (&now)));
 9494 +
 9495 +               expire = mktime (&tm1);
 9496 +           }
 9497 +       }
 9498 +   }
 9499 +
 9500 +   if (x509 != NULL) {
 9501 +       X509_free (x509);
 9502 +       x509 = NULL;
 9503 +   }
 9504 +#elif defined(USE_PKCS11H_GNUTLS)
 9505 +   if (gnutls_x509_crt_init (&cert) == GNUTLS_E_SUCCESS) {
 9506 +       gnutls_datum_t datum = {(unsigned char *)certificate, certificate_size};
 9507 +
 9508 +       if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) == GNUTLS_E_SUCCESS) {
 9509 +
 9510 +           time_t activation_time = gnutls_x509_crt_get_activation_time (cert);
 9511 +           time_t expiration_time = gnutls_x509_crt_get_expiration_time (cert);
 9512 +           time_t now = time (NULL);
 9513 +
 9514 +           if (
 9515 +               now >= activation_time &&
 9516 +               now <= expiration_time
 9517 +           ) {
 9518 +               expire = expiration_time;
 9519 +           }
 9520 +       }
 9521 +       gnutls_x509_crt_deinit (cert);
 9522 +   }
 9523 +#else
 9524 +#error Invalid configuration
 9525 +#endif
 9526 +
 9527 +   return expire;
 9528 +}
 9529 +
 9530 +static
 9531 +PKCS11H_BOOL
 9532 +_pkcs11h_certificate_isBetterCertificate (
 9533 +   IN const unsigned char * const current,
 9534 +   IN const size_t current_size,
 9535 +   IN const unsigned char * const newone,
 9536 +   IN const size_t newone_size
 9537 +) {
 9538 +   PKCS11H_BOOL is_better = FALSE;
 9539 +
 9540 +   /*PKCS11H_ASSERT (current!=NULL); NOT NEEDED */
 9541 +   PKCS11H_ASSERT (newone!=NULL);
 9542 +
 9543 +   PKCS11H_DEBUG (
 9544 +       PKCS11H_LOG_DEBUG2,
 9545 +       "PKCS#11: _pkcs11h_certificate_isBetterCertificate entry current=%p, current_size=%u, newone=%p,
	newone_size=%u",
 9546 +       current,
 9547 +       current_size,
 9548 +       newone,
 9549 +       newone_size
 9550 +   );
 9551 +
 9552 +   /*
 9553 +    * First certificae
 9554 +    * always select
 9555 +    */
 9556 +   if (current_size == 0 || current == NULL) {
 9557 +       is_better = TRUE;
 9558 +   }
 9559 +   else {
 9560 +       time_t notAfterCurrent, notAfterNew;
 9561 +
 9562 +       notAfterCurrent = _pkcs11h_certificate_getExpiration (
 9563 +           current,
 9564 +           current_size
 9565 +       );
 9566 +       notAfterNew = _pkcs11h_certificate_getExpiration (
 9567 +           newone,
 9568 +           newone_size
 9569 +       );
 9570 +
 9571 +       PKCS11H_DEBUG (
 9572 +           PKCS11H_LOG_DEBUG2,
 9573 +           "PKCS#11: _pkcs11h_certificate_isBetterCertificate notAfterCurrent='%s', notAfterNew='%s'",
 9574 +           asctime (localtime (&notAfterCurrent)),
 9575 +           asctime (localtime (&notAfterNew))
 9576 +       );
 9577 +
 9578 +       is_better = notAfterNew > notAfterCurrent;
 9579 +   }
 9580 +
 9581 +   PKCS11H_DEBUG (
 9582 +       PKCS11H_LOG_DEBUG2,
 9583 +       "PKCS#11: _pkcs11h_certificate_isBetterCertificate return is_better=%d",
 9584 +       is_better ? 1 : 0
 9585 +   );
 9586 +   
 9587 +   return is_better;
 9588 +}
 9589 +
 9590 +static
 9591 +CK_RV
 9592 +_pkcs11h_certificate_newCertificateId (
 9593 +   OUT pkcs11h_certificate_id_t * const p_certificate_id
 9594 +) {
 9595 +   CK_RV rv = CKR_OK;
 9596 +
 9597 +   PKCS11H_ASSERT (p_certificate_id!=NULL);
 9598 +
 9599 +   PKCS11H_DEBUG (
 9600 +       PKCS11H_LOG_DEBUG2,
 9601 +       "PKCS#11: _pkcs11h_certificate_newCertificateId entry p_certificate_id=%p",
 9602 +       (void *)p_certificate_id
 9603 +   );
 9604 +
 9605 +   *p_certificate_id = NULL;
 9606 +
 9607 +   if (rv == CKR_OK) {
 9608 +       rv = _pkcs11h_mem_malloc ((void *)p_certificate_id, sizeof (struct pkcs11h_certificate_id_s));
 9609 +   }
 9610 +
 9611 +   PKCS11H_DEBUG (
 9612 +       PKCS11H_LOG_DEBUG2,
 9613 +       "PKCS#11: _pkcs11h_certificate_newCertificateId return rv=%ld-'%s', *p_certificate_id=%p",
 9614 +       rv,
 9615 +       pkcs11h_getMessage (rv),
 9616 +       (void *)*p_certificate_id
 9617 +   );
 9618 +
 9619 +   return rv;
 9620 +}
 9621 +
 9622 +static
 9623 +CK_RV
 9624 +_pkcs11h_certificate_getDN (
 9625 +   IN const unsigned char * const blob,
 9626 +   IN const size_t blob_size,
 9627 +   OUT char * const dn,
 9628 +   IN const size_t dn_size
 9629 +) {
 9630 +#if defined(USE_PKCS11H_OPENSSL)
 9631 +   X509 *x509 = NULL;
 9632 +   pkcs11_openssl_d2i_t d2i1;
 9633 +#elif defined(USE_PKCS11H_GNUTLS)
 9634 +   gnutls_x509_crt_t cert = NULL;
 9635 +#endif
 9636 +
 9637 +   PKCS11H_ASSERT (blob_size==0||blob!=NULL);
 9638 +   PKCS11H_ASSERT (dn!=NULL);
 9639 +
 9640 +   dn[0] = '\x0';
 9641 +
 9642 +#if defined(USE_PKCS11H_OPENSSL)
 9643 +
 9644 +   if (blob_size > 0) {
 9645 +       x509 = X509_new ();
 9646 +
 9647 +       d2i1 = (pkcs11_openssl_d2i_t)blob;
 9648 +       if (d2i_X509 (&x509, &d2i1, blob_size)) {
 9649 +           X509_NAME_oneline (
 9650 +               X509_get_subject_name (x509),
 9651 +               dn,
 9652 +               dn_size
 9653 +           );
 9654 +       }
 9655 +
 9656 +       if (x509 != NULL) {
 9657 +           X509_free (x509);
 9658 +           x509 = NULL;
 9659 +       }
 9660 +   }
 9661 +
 9662 +#elif defined(USE_PKCS11H_GNUTLS)
 9663 +
 9664 +   if (blob_size > 0) {
 9665 +       if (gnutls_x509_crt_init (&cert) == GNUTLS_E_SUCCESS) {
 9666 +           gnutls_datum_t datum = {(unsigned char *)blob, blob_size};
 9667 +
 9668 +           if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) == GNUTLS_E_SUCCESS) {
 9669 +               size_t s = dn_size;
 9670 +               if (
 9671 +                   gnutls_x509_crt_get_dn (
 9672 +                       cert,
 9673 +                       dn,
 9674 +                       &s
 9675 +                   ) != GNUTLS_E_SUCCESS
 9676 +               ) {
 9677 +                   /* gnutls sets output parameters */
 9678 +                   dn[0] = '\x0';
 9679 +               }
 9680 +           }
 9681 +           gnutls_x509_crt_deinit (cert);
 9682 +       }
 9683 +   }
 9684 +
 9685 +#else
 9686 +#error Invalid configuration
 9687 +#endif
 9688 +
 9689 +   return CKR_OK;
 9690 +}
 9691 +
 9692 +static
 9693 +CK_RV
 9694 +_pkcs11h_certificate_loadCertificate (
 9695 +   IN const pkcs11h_certificate_t certificate
 9696 +) {
 9697 +   /*
 9698 +    * THREADING:
 9699 +    * certificate->mutex must be locked
 9700 +    */
 9701 +#if defined(ENABLE_PKCS11H_THREADING)
 9702 +   PKCS11H_BOOL mutex_locked = FALSE;
 9703 +#endif
 9704 +   CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
 9705 +   CK_ATTRIBUTE cert_filter[] = {
 9706 +       {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
 9707 +       {CKA_ID, NULL, 0}
 9708 +   };
 9709 +
 9710 +   CK_OBJECT_HANDLE *objects = NULL;
 9711 +   CK_ULONG objects_found = 0;
 9712 +   CK_RV rv = CKR_OK;
 9713 +
 9714 +   CK_ULONG i;
 9715 +
 9716 +   PKCS11H_ASSERT (certificate!=NULL);
 9717 +   PKCS11H_ASSERT (certificate->id!=NULL);
 9718 +   
 9719 +   /* Must be after assert */
 9720 +   cert_filter[1].pValue = certificate->id->attrCKA_ID;
 9721 +   cert_filter[1].ulValueLen = certificate->id->attrCKA_ID_size;
 9722 +
 9723 +   PKCS11H_DEBUG (
 9724 +       PKCS11H_LOG_DEBUG2,
 9725 +       "PKCS#11: _pkcs11h_certificate_loadCertificate entry certificate=%p",
 9726 +       (void *)certificate
 9727 +   );
 9728 +
 9729 +#if defined(ENABLE_PKCS11H_THREADING)
 9730 +   if (
 9731 +       rv == CKR_OK &&
 9732 +       (rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) == CKR_OK
 9733 +   ) {
 9734 +       mutex_locked = TRUE;
 9735 +   }
 9736 +#endif
 9737 +
 9738 +   if (rv == CKR_OK) {
 9739 +       rv = _pkcs11h_session_validate (certificate->session);
 9740 +   }
 9741 +
 9742 +   if (rv == CKR_OK) {
 9743 +       rv = _pkcs11h_session_findObjects (
 9744 +           certificate->session,
 9745 +           cert_filter,
 9746 +           sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
 9747 +           &objects,
 9748 +           &objects_found
 9749 +       );
 9750 +   }
 9751 +
 9752 +   for (i=0;rv == CKR_OK && i < objects_found;i++) {
 9753 +       CK_ATTRIBUTE attrs[] = {
 9754 +           {CKA_VALUE, NULL, 0}
 9755 +       };
 9756 +
 9757 +       if (
 9758 +           rv == CKR_OK &&
 9759 +           (rv = _pkcs11h_session_getObjectAttributes (
 9760 +               certificate->session,
 9761 +               objects[i],
 9762 +               attrs,
 9763 +               sizeof (attrs) / sizeof (CK_ATTRIBUTE)
 9764 +           )) == CKR_OK
 9765 +       ) {
 9766 +           if (
 9767 +               _pkcs11h_certificate_isBetterCertificate (
 9768 +                   certificate->id->certificate_blob,
 9769 +                   certificate->id->certificate_blob_size,
 9770 +                   attrs[0].pValue,
 9771 +                   attrs[0].ulValueLen
 9772 +               )
 9773 +           ) {
 9774 +               if (certificate->id->certificate_blob != NULL) {
 9775 +                   _pkcs11h_mem_free ((void *)&certificate->id->certificate_blob);
 9776 +               }
 9777 +
 9778 +               rv = _pkcs11h_mem_duplicate (
 9779 +                   (void*)&certificate->id->certificate_blob,
 9780 +                   &certificate->id->certificate_blob_size,
 9781 +                   attrs[0].pValue,
 9782 +                   attrs[0].ulValueLen
 9783 +               );
 9784 +           }
 9785 +       }
 9786 +
 9787 +       if (rv != CKR_OK) {
 9788 +           PKCS11H_DEBUG (
 9789 +               PKCS11H_LOG_DEBUG1,
 9790 +               "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
 9791 +               certificate->session->provider->manufacturerID,
 9792 +               objects[i],
 9793 +               rv,
 9794 +               pkcs11h_getMessage (rv)
 9795 +           );
 9796 +
 9797 +           /*
 9798 +            * Ignore error
 9799 +            */
 9800 +           rv = CKR_OK;
 9801 +       }
 9802 +
 9803 +       _pkcs11h_session_freeObjectAttributes (
 9804 +           attrs,
 9805 +           sizeof (attrs) / sizeof (CK_ATTRIBUTE)
 9806 +       );
 9807 +   }
 9808 +   
 9809 +#if defined(ENABLE_PKCS11H_THREADING)
 9810 +   if (mutex_locked) {
 9811 +       _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
 9812 +       mutex_locked = FALSE;
 9813 +   }
 9814 +#endif
 9815 +
 9816 +   if (
 9817 +       rv == CKR_OK &&
 9818 +       certificate->id->certificate_blob == NULL
 9819 +   ) {
 9820 +       rv = CKR_ATTRIBUTE_VALUE_INVALID;
 9821 +   }
 9822 +
 9823 +   if (objects != NULL) {
 9824 +       _pkcs11h_mem_free ((void *)&objects);
 9825 +   }
 9826 +
 9827 +   /*
 9828 +    * No need to free allocated objects
 9829 +    * on error, since the certificate_id
 9830 +    * should be free by caller.
 9831 +    */
 9832 +
 9833 +   PKCS11H_DEBUG (
 9834 +       PKCS11H_LOG_DEBUG2,
 9835 +       "PKCS#11: _pkcs11h_certificate_loadCertificate return rv=%ld-'%s'",
 9836 +       rv,
 9837 +       pkcs11h_getMessage (rv)
 9838 +   );
 9839 +
 9840 +   return rv;
 9841 +}
 9842 +
 9843 +static
 9844 +CK_RV
 9845 +_pkcs11h_certificate_updateCertificateIdDescription (
 9846 +   IN OUT pkcs11h_certificate_id_t certificate_id
 9847 +) {
 9848 +   static const char * separator = " on ";
 9849 +   static const char * unknown = "UNKNOWN";
 9850 +
 9851 +   PKCS11H_ASSERT (certificate_id!=NULL);
 9852 +
 9853 +   PKCS11H_DEBUG (
 9854 +       PKCS11H_LOG_DEBUG2,
 9855 +       "PKCS#11: _pkcs11h_certificate_updateCertificateIdDescription entry certificate_id=%p",
 9856 +       (void *)certificate_id
 9857 +   );
 9858 +
 9859 +   certificate_id->displayName[0] = '\x0';
 9860 +
 9861 +   _pkcs11h_certificate_getDN (
 9862 +       certificate_id->certificate_blob,
 9863 +       certificate_id->certificate_blob_size,
 9864 +       certificate_id->displayName,
 9865 +       sizeof (certificate_id->displayName)
 9866 +   );
 9867 +
 9868 +   if (strlen (certificate_id->displayName) == 0) {
 9869 +       strncpy (
 9870 +           certificate_id->displayName,
 9871 +           unknown,
 9872 +           sizeof (certificate_id->displayName)-1
 9873 +       );
 9874 +   }
 9875 +
 9876 +   /*
 9877 +    * Try to avoid using snprintf,
 9878 +    * may be unavailable
 9879 +    */
 9880 +   strncat (
 9881 +       certificate_id->displayName,
 9882 +       separator,
 9883 +       sizeof (certificate_id->displayName)-1-strlen (certificate_id->displayName)
 9884 +   );
 9885 +   strncat (
 9886 +       certificate_id->displayName,
 9887 +       certificate_id->token_id->display,
 9888 +       sizeof (certificate_id->displayName)-1-strlen (certificate_id->displayName)
 9889 +   );
 9890 +   certificate_id->displayName[sizeof (certificate_id->displayName) - 1] = '\0';
 9891 +
 9892 +   PKCS11H_DEBUG (
 9893 +       PKCS11H_LOG_DEBUG2,
 9894 +       "PKCS#11: _pkcs11h_certificate_updateCertificateIdDescription return displayName='%s'",
 9895 +       certificate_id->displayName
 9896 +   );
 9897 +
 9898 +   return CKR_OK;
 9899 +}
 9900 +
 9901 +static
 9902 +CK_RV
 9903 +_pkcs11h_certificate_getKeyAttributes (
 9904 +   IN const pkcs11h_certificate_t certificate
 9905 +) {
 9906 +#if defined(ENABLE_PKCS11H_THREADING)
 9907 +   PKCS11H_BOOL mutex_locked = FALSE;
 9908 +#endif
 9909 +   CK_RV rv = CKR_OK;
 9910 +
 9911 +   PKCS11H_BOOL op_succeed = FALSE;
 9912 +   PKCS11H_BOOL login_retry = FALSE;
 9913 +
 9914 +   PKCS11H_ASSERT (certificate!=NULL);
 9915 +
 9916 +   PKCS11H_DEBUG (
 9917 +       PKCS11H_LOG_DEBUG2,
 9918 +       "PKCS#11: _pkcs11h_certificate_getKeyAttributes entry certificate=%p",
 9919 +       (void *)certificate
 9920 +   );
 9921 +
 9922 +#if defined(ENABLE_PKCS11H_THREADING)
 9923 +   if (
 9924 +       rv == CKR_OK &&
 9925 +       (rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) == CKR_OK
 9926 +   ) {
 9927 +       mutex_locked = TRUE;
 9928 +   }
 9929 +#endif
 9930 +
 9931 +   certificate->mask_sign_mode = 0;
 9932 +
 9933 +   while (rv == CKR_OK && !op_succeed) {
 9934 +       CK_ATTRIBUTE key_attrs[] = {
 9935 +           {CKA_SIGN, NULL, 0},
 9936 +           {CKA_SIGN_RECOVER, NULL, 0}
 9937 +       };
 9938 +
 9939 +       /*
 9940 +        * Don't try invalid object
 9941 +        */
 9942 +       if (
 9943 +           rv == CKR_OK &&
 9944 +           certificate->key_handle == PKCS11H_INVALID_OBJECT_HANDLE
 9945 +       ) {
 9946 +           rv = CKR_OBJECT_HANDLE_INVALID;
 9947 +       }
 9948 +
 9949 +       if (rv == CKR_OK) {
 9950 +           if (certificate->session->provider->mask_sign_mode != 0) {
 9951 +               certificate->mask_sign_mode = certificate->session->provider->mask_sign_mode;
 9952 +               op_succeed = TRUE;
 9953 +               PKCS11H_DEBUG (
 9954 +                   PKCS11H_LOG_DEBUG1,
 9955 +                   "PKCS#11: Key attributes enforced by provider (%08x)",
 9956 +                   certificate->mask_sign_mode
 9957 +               );
 9958 +           }
 9959 +       }
 9960 +
 9961 +       if (rv == CKR_OK && !op_succeed) {
 9962 +           rv = _pkcs11h_session_getObjectAttributes (
 9963 +               certificate->session,
 9964 +               certificate->key_handle,
 9965 +               key_attrs,
 9966 +               sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
 9967 +           );
 9968 +       }
 9969 +
 9970 +       if (rv == CKR_OK && !op_succeed) {
 9971 +           CK_BBOOL *key_attrs_sign = (CK_BBOOL *)key_attrs[0].pValue;
 9972 +           CK_BBOOL *key_attrs_sign_recover = (CK_BBOOL *)key_attrs[1].pValue;
 9973 +
 9974 +           if (key_attrs_sign != NULL && *key_attrs_sign != CK_FALSE) {
 9975 +               certificate->mask_sign_mode |= PKCS11H_SIGNMODE_MASK_SIGN;
 9976 +           }
 9977 +           if (key_attrs_sign_recover != NULL && *key_attrs_sign_recover != CK_FALSE) {
 9978 +               certificate->mask_sign_mode |= PKCS11H_SIGNMODE_MASK_RECOVER;
 9979 +           }
 9980 +           if (certificate->mask_sign_mode == 0) {
 9981 +               rv = CKR_KEY_TYPE_INCONSISTENT;
 9982 +           }
 9983 +           PKCS11H_DEBUG (
 9984 +               PKCS11H_LOG_DEBUG1,
 9985 +               "PKCS#11: Key attributes loaded (%08x)",
 9986 +               certificate->mask_sign_mode
 9987 +           );
 9988 +       }
 9989 +
 9990 +       _pkcs11h_session_freeObjectAttributes (
 9991 +           key_attrs,
 9992 +           sizeof (key_attrs) / sizeof (CK_ATTRIBUTE)
 9993 +       );
 9994 +
 9995 +       if (rv == CKR_OK) {
 9996 +           op_succeed = TRUE;
 9997 +       }
 9998 +       else {
 9999 +           if (!login_retry) {
10000 +               PKCS11H_DEBUG (
10001 +                   PKCS11H_LOG_DEBUG1,
10002 +                   "PKCS#11: Get private key attributes failed: %ld:'%s'",
10003 +                   rv,
10004 +                   pkcs11h_getMessage (rv)
10005 +               );
10006 +
10007 +               rv = _pkcs11h_certificate_resetSession (
10008 +                   certificate,
10009 +                   FALSE,
10010 +                   TRUE
10011 +               );
10012 +
10013 +               login_retry = TRUE;
10014 +           }
10015 +       }
10016 +   }
10017 +
10018 +#if defined(ENABLE_PKCS11H_THREADING)
10019 +   if (mutex_locked) {
10020 +       _pkcs11h_threading_mutexRelease (&certificate->mutex);
10021 +       mutex_locked = FALSE;
10022 +   }
10023 +#endif
10024 +   
10025 +   PKCS11H_DEBUG (
10026 +       PKCS11H_LOG_DEBUG2,
10027 +       "PKCS#11: _pkcs11h_certificate_getKeyAttributes return rv=%ld-'%s'",
10028 +       rv,
10029 +       pkcs11h_getMessage (rv)
10030 +   );
10031 +
10032 +   return rv;
10033 +}
10034 +
10035 +static
10036 +CK_RV
10037 +_pkcs11h_certificate_validateSession (
10038 +   IN const pkcs11h_certificate_t certificate
10039 +) {
10040 +   /*
10041 +    * THREADING:
10042 +    * certificate->mutex must be locked
10043 +    * certificate->session->mutex must be locked
10044 +    */
10045 +   CK_RV rv = CKR_OK;
10046 +
10047 +   PKCS11H_ASSERT (certificate!=NULL);
10048 +
10049 +   PKCS11H_DEBUG (
10050 +       PKCS11H_LOG_DEBUG2,
10051 +       "PKCS#11: _pkcs11h_certificate_validateSession entry certificate=%p",
10052 +       (void *)certificate
10053 +   );
10054 +
10055 +   if (certificate->session == NULL) {
10056 +       rv = CKR_SESSION_HANDLE_INVALID;
10057 +   }
10058 +
10059 +   if (rv == CKR_OK) {
10060 +       rv = _pkcs11h_session_validate (certificate->session);
10061 +   }
10062 +
10063 +   if (rv == CKR_OK) {
10064 +       if (certificate->key_handle == PKCS11H_INVALID_OBJECT_HANDLE) {
10065 +           rv = CKR_OBJECT_HANDLE_INVALID;
10066 +       }
10067 +   }
10068 +
10069 +   PKCS11H_DEBUG (
10070 +       PKCS11H_LOG_DEBUG2,
10071 +       "PKCS#11: _pkcs11h_certificate_validateSession return rv=%ld-'%s'",
10072 +       rv,
10073 +       pkcs11h_getMessage (rv)
10074 +   );
10075 +
10076 +   return rv;
10077 +}
10078 +
10079 +CK_RV
10080 +_pkcs11h_certificate_resetSession (
10081 +   IN const pkcs11h_certificate_t certificate,
10082 +   IN const PKCS11H_BOOL public_only,
10083 +   IN const PKCS11H_BOOL session_mutex_locked
10084 +) {
10085 +   /*
10086 +    * THREADING:
10087 +    * certificate->mutex must be locked
10088 +    */
10089 +#if defined(ENABLE_PKCS11H_THREADING)
10090 +   PKCS11H_BOOL mutex_locked = FALSE;
10091 +#endif
10092 +   PKCS11H_BOOL is_key_valid = FALSE;
10093 +   CK_RV rv = CKR_OK;
10094 +
10095 +   PKCS11H_ASSERT (certificate!=NULL);
10096 +   
10097 +   PKCS11H_DEBUG (
10098 +       PKCS11H_LOG_DEBUG2,
10099 +       "PKCS#11: _pkcs11h_certificate_resetSession entry certificate=%p, public_only=%d, session_mutex_locked=%d",
10100 +       (void *)certificate,
10101 +       public_only ? 1 : 0,
10102 +       session_mutex_locked ? 1 : 0
10103 +   );
10104 +
10105 +   if (rv == CKR_OK && certificate->session == NULL) {
10106 +       rv = _pkcs11h_session_getSessionByTokenId (certificate->id->token_id, &certificate->session);
10107 +   }
10108 +
10109 +#if defined(ENABLE_PKCS11H_THREADING)
10110 +   if (
10111 +       rv == CKR_OK &&
10112 +       !session_mutex_locked &&
10113 +       (rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) == CKR_OK
10114 +   ) {
10115 +       mutex_locked = TRUE;
10116 +   }
10117 +#endif
10118 +
10119 +   if (
10120 +       rv == CKR_OK &&
10121 +       !certificate->pin_cache_populated_to_session
10122 +   ) {
10123 +       certificate->pin_cache_populated_to_session = TRUE;
10124 +
10125 +       if (certificate->pin_cache_period != PKCS11H_PIN_CACHE_INFINITE) {
10126 +           if (certificate->session->pin_cache_period != PKCS11H_PIN_CACHE_INFINITE) {
10127 +               if (certificate->session->pin_cache_period > certificate->pin_cache_period) {
10128 +                   certificate->session->pin_expire_time = (
10129 +                       certificate->session->pin_expire_time -
10130 +                       (time_t)certificate->session->pin_cache_period +
10131 +                       (time_t)certificate->pin_cache_period
10132 +                   );
10133 +                   certificate->session->pin_cache_period = certificate->pin_cache_period;
10134 +               }
10135 +           }
10136 +           else {
10137 +               certificate->session->pin_expire_time = (
10138 +                   PKCS11H_TIME (NULL) +
10139 +                   (time_t)certificate->pin_cache_period
10140 +               );
10141 +               certificate->session->pin_cache_period = certificate->pin_cache_period;
10142 +           }
10143 +       }   
10144 +   }
10145 +
10146 +   /*
10147 +    * First, if session seems to be valid
10148 +    * and key handle is invalid (hard-set),
10149 +    * try to fetch key handle,
10150 +    * maybe the token is already logged in
10151 +    */
10152 +   if (rv == CKR_OK) {
10153 +       if (
10154 +           certificate->session->session_handle != PKCS11H_INVALID_SESSION_HANDLE &&
10155 +           certificate->key_handle == PKCS11H_INVALID_OBJECT_HANDLE
10156 +       ) {
10157 +           if (!public_only || certificate->session->provider->cert_is_private) {
10158 +               if (
10159 +                   (rv = _pkcs11h_session_getObjectById (
10160 +                       certificate->session,
10161 +                       CKO_PRIVATE_KEY,
10162 +                       certificate->id->attrCKA_ID,
10163 +                       certificate->id->attrCKA_ID_size,
10164 +                       &certificate->key_handle
10165 +                   )) == CKR_OK
10166 +               ) {
10167 +                   is_key_valid = TRUE;
10168 +               }
10169 +               else {
10170 +                   /*
10171 +                    * Ignore error
10172 +                    */
10173 +                   rv = CKR_OK;
10174 +                   certificate->key_handle = PKCS11H_INVALID_OBJECT_HANDLE;
10175 +               }
10176 +           }
10177 +       }
10178 +   }
10179 +
10180 +   if (
10181 +       !is_key_valid &&
10182 +       rv == CKR_OK &&
10183 +       (rv = _pkcs11h_session_login (
10184 +           certificate->session,
10185 +           public_only,
10186 +           TRUE,
10187 +           certificate->user_data,
10188 +           certificate->mask_prompt
10189 +       )) == CKR_OK
10190 +   ) {
10191 +       rv = _pkcs11h_certificate_updateCertificateIdDescription (certificate->id);
10192 +   }
10193 +
10194 +   if (
10195 +       !is_key_valid &&
10196 +       rv == CKR_OK &&
10197 +       !public_only &&
10198 +       (rv = _pkcs11h_session_getObjectById (
10199 +           certificate->session,
10200 +           CKO_PRIVATE_KEY,
10201 +           certificate->id->attrCKA_ID,
10202 +           certificate->id->attrCKA_ID_size,
10203 +           &certificate->key_handle
10204 +       )) == CKR_OK
10205 +   ) {
10206 +       is_key_valid = TRUE;
10207 +   }
10208 +
10209 +   if (
10210 +       rv == CKR_OK &&
10211 +       !public_only &&
10212 +       !is_key_valid
10213 +   ) {
10214 +       rv = CKR_FUNCTION_REJECTED;
10215 +   }
10216 +
10217 +#if defined(ENABLE_PKCS11H_THREADING)
10218 +   if (mutex_locked) {
10219 +       _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
10220 +       mutex_locked = FALSE;
10221 +   }
10222 +#endif
10223 +
10224 +   PKCS11H_DEBUG (
10225 +       PKCS11H_LOG_DEBUG2,
10226 +       "PKCS#11: _pkcs11h_certificate_resetSession return rv=%ld-'%s'",
10227 +       rv,
10228 +       pkcs11h_getMessage (rv)
10229 +   );
10230 +
10231 +   return rv;
10232 +}
10233 +
10234 +static
10235 +CK_RV
10236 +_pkcs11h_certificate_doPrivateOperation (
10237 +   IN const pkcs11h_certificate_t certificate,
10238 +   IN const enum _pkcs11h_private_op_e op,
10239 +   IN const CK_MECHANISM_TYPE mech_type,
10240 +   IN const unsigned char * const source,
10241 +   IN const size_t source_size,
10242 +   OUT unsigned char * const target,
10243 +   IN OUT size_t * const p_target_size
10244 +) {
10245 +#if defined(ENABLE_PKCS11H_THREADING)
10246 +   PKCS11H_BOOL mutex_locked = FALSE;
10247 +#endif
10248 +   CK_MECHANISM mech = {
10249 +       mech_type, NULL, 0
10250 +   };
10251 +   
10252 +   CK_RV rv = CKR_OK;
10253 +   PKCS11H_BOOL login_retry = FALSE;
10254 +   PKCS11H_BOOL op_succeed = FALSE;
10255 +
10256 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10257 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10258 +   PKCS11H_ASSERT (certificate!=NULL);
10259 +   PKCS11H_ASSERT (source!=NULL);
10260 +   /*PKCS11H_ASSERT (target); NOT NEEDED*/
10261 +   PKCS11H_ASSERT (p_target_size!=NULL);
10262 +
10263 +   PKCS11H_DEBUG (
10264 +       PKCS11H_LOG_DEBUG2,
10265 +       "PKCS#11: _pkcs11h_certificate_doPrivateOperation entry certificate=%p, op=%d, mech_type=%ld, source=%p,
	source_size=%u, target=%p, *p_target_size=%u",
10266 +       (void *)certificate,
10267 +       op,
10268 +       mech_type,
10269 +       source,
10270 +       source_size,
10271 +       target,
10272 +       target != NULL ? *p_target_size : 0
10273 +   );
10274 +
10275 +   if (target == NULL) {
10276 +       *p_target_size = 0;
10277 +   }
10278 +
10279 +#if defined(ENABLE_PKCS11H_THREADING)
10280 +   if (
10281 +       rv == CKR_OK &&
10282 +       (rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) == CKR_OK
10283 +   ) {
10284 +       mutex_locked = TRUE;
10285 +   }
10286 +#endif
10287 +
10288 +   while (rv == CKR_OK && !op_succeed) {
10289 +       if (rv == CKR_OK && !certificate->operation_active) {
10290 +           rv = _pkcs11h_certificate_validateSession (certificate);
10291 +       }
10292 +
10293 +       if (rv == CKR_OK && !certificate->operation_active) {
10294 +           switch (op) {
10295 +               case _pkcs11h_private_op_sign:
10296 +                   rv = certificate->session->provider->f->C_SignInit (
10297 +                       certificate->session->session_handle,
10298 +                       &mech,
10299 +                       certificate->key_handle
10300 +                   );
10301 +               break;
10302 +               case _pkcs11h_private_op_sign_recover:
10303 +                   rv = certificate->session->provider->f->C_SignRecoverInit (
10304 +                       certificate->session->session_handle,
10305 +                       &mech,
10306 +                       certificate->key_handle
10307 +                   );
10308 +               break;
10309 +               case _pkcs11h_private_op_decrypt:
10310 +                   rv = certificate->session->provider->f->C_DecryptInit (
10311 +                       certificate->session->session_handle,
10312 +                       &mech,
10313 +                       certificate->key_handle
10314 +                   );
10315 +               break;
10316 +               default:
10317 +                   rv = CKR_ARGUMENTS_BAD;
10318 +               break;
10319 +           }
10320 +
10321 +           PKCS11H_DEBUG (
10322 +               PKCS11H_LOG_DEBUG2,
10323 +               "PKCS#11: _pkcs11h_certificate_doPrivateOperation init rv=%ld",
10324 +               rv
10325 +           );
10326 +       }
10327 +
10328 +       if (rv == CKR_OK) {
10329 +           CK_ULONG size = *p_target_size;
10330 +
10331 +           switch (op) {
10332 +               case _pkcs11h_private_op_sign:
10333 +                   rv = certificate->session->provider->f->C_Sign (
10334 +                       certificate->session->session_handle,
10335 +                       (CK_BYTE_PTR)source,
10336 +                       source_size,
10337 +                       (CK_BYTE_PTR)target,
10338 +                       &size
10339 +                   );
10340 +               break;
10341 +               case _pkcs11h_private_op_sign_recover:
10342 +                   rv = certificate->session->provider->f->C_SignRecover (
10343 +                       certificate->session->session_handle,
10344 +                       (CK_BYTE_PTR)source,
10345 +                       source_size,
10346 +                       (CK_BYTE_PTR)target,
10347 +                       &size
10348 +                   );
10349 +               break;
10350 +               case _pkcs11h_private_op_decrypt:
10351 +                   rv = certificate->session->provider->f->C_Decrypt (
10352 +                       certificate->session->session_handle,
10353 +                       (CK_BYTE_PTR)source,
10354 +                       source_size,
10355 +                       (CK_BYTE_PTR)target,
10356 +                       &size
10357 +                   );
10358 +               break;
10359 +               default:
10360 +                   rv = CKR_ARGUMENTS_BAD;
10361 +               break;
10362 +           }
10363 +
10364 +           *p_target_size = size;
10365 +
10366 +           PKCS11H_DEBUG (
10367 +               PKCS11H_LOG_DEBUG2,
10368 +               "PKCS#11: _pkcs11h_certificate_doPrivateOperation op rv=%ld",
10369 +               rv
10370 +           );
10371 +       }
10372 +       
10373 +       if (
10374 +           target == NULL &&
10375 +           (
10376 +               rv == CKR_BUFFER_TOO_SMALL ||
10377 +               rv == CKR_OK
10378 +           )
10379 +       ) {
10380 +           certificate->operation_active = TRUE;
10381 +           rv = CKR_OK;
10382 +       }
10383 +       else {
10384 +           certificate->operation_active = FALSE;
10385 +       }
10386 +
10387 +       if (rv == CKR_OK) {
10388 +           op_succeed = TRUE;
10389 +       }
10390 +       else {
10391 +           /*
10392 +            * OpenSC workaround
10393 +            * It still allows C_FindObjectsInit when
10394 +            * token is removed/inserted but fails
10395 +            * private key operation.
10396 +            * So we force logout.
10397 +            * bug#108 at OpenSC trac
10398 +            */
10399 +           if (login_retry && rv == CKR_DEVICE_REMOVED) {
10400 +               login_retry = FALSE;
10401 +               _pkcs11h_session_logout (certificate->session);
10402 +           }
10403 +
10404 +           if (!login_retry) {
10405 +               PKCS11H_DEBUG (
10406 +                   PKCS11H_LOG_DEBUG1,
10407 +                   "PKCS#11: Private key operation failed rv=%ld-'%s'",
10408 +                   rv,
10409 +                   pkcs11h_getMessage (rv)
10410 +               );
10411 +               login_retry = TRUE;
10412 +               rv = _pkcs11h_certificate_resetSession (
10413 +                   certificate,
10414 +                   FALSE,
10415 +                   TRUE
10416 +               );
10417 +           }
10418 +       }
10419 +
10420 +   }
10421 +
10422 +#if defined(ENABLE_PKCS11H_THREADING)
10423 +   if (mutex_locked) {
10424 +       _pkcs11h_threading_mutexRelease (&certificate->mutex);
10425 +       mutex_locked = FALSE;
10426 +   }
10427 +#endif
10428 +
10429 +   PKCS11H_DEBUG (
10430 +       PKCS11H_LOG_DEBUG2,
10431 +       "PKCS#11: _pkcs11h_certificate_doPrivateOperation return rv=%ld-'%s', *p_target_size=%u",
10432 +       rv,
10433 +       pkcs11h_getMessage (rv),
10434 +       *p_target_size
10435 +   );
10436 +   
10437 +   return rv;
10438 +}
10439 +
10440 +CK_RV
10441 +pkcs11h_certificate_freeCertificateId (
10442 +   IN pkcs11h_certificate_id_t certificate_id
10443 +) {
10444 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10445 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10446 +   PKCS11H_ASSERT (certificate_id!=NULL);
10447 +
10448 +   PKCS11H_DEBUG (
10449 +       PKCS11H_LOG_DEBUG2,
10450 +       "PKCS#11: pkcs11h_certificate_freeCertificateId entry certificate_id=%p",
10451 +       (void *)certificate_id
10452 +   );
10453 +
10454 +   if (certificate_id->attrCKA_ID != NULL) {
10455 +       _pkcs11h_mem_free ((void *)&certificate_id->attrCKA_ID);
10456 +   }
10457 +   if (certificate_id->certificate_blob != NULL) {
10458 +       _pkcs11h_mem_free ((void *)&certificate_id->certificate_blob);
10459 +   }
10460 +   if (certificate_id->token_id != NULL) {
10461 +       pkcs11h_token_freeTokenId (certificate_id->token_id);
10462 +       certificate_id->token_id = NULL;
10463 +   }
10464 +   _pkcs11h_mem_free ((void *)&certificate_id);
10465 +
10466 +   PKCS11H_DEBUG (
10467 +       PKCS11H_LOG_DEBUG2,
10468 +       "PKCS#11: pkcs11h_certificate_freeCertificateId return"
10469 +   );
10470 +
10471 +   return CKR_OK;
10472 +}
10473 +
10474 +CK_RV
10475 +pkcs11h_certificate_duplicateCertificateId (
10476 +   OUT pkcs11h_certificate_id_t * const to,
10477 +   IN const pkcs11h_certificate_id_t from
10478 +) {
10479 +   CK_RV rv = CKR_OK;
10480 +
10481 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10482 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10483 +   PKCS11H_ASSERT (to!=NULL);
10484 +   PKCS11H_ASSERT (from!=NULL);
10485 +
10486 +   PKCS11H_DEBUG (
10487 +       PKCS11H_LOG_DEBUG2,
10488 +       "PKCS#11: pkcs11h_certificate_duplicateCertificateId entry to=%p form=%p",
10489 +       (void *)to,
10490 +       (void *)from
10491 +   );
10492 +
10493 +   *to = NULL;
10494 +
10495 +   if (rv == CKR_OK) {
10496 +       rv = _pkcs11h_mem_duplicate (
10497 +           (void*)to,
10498 +           NULL,
10499 +           from,
10500 +           sizeof (struct pkcs11h_certificate_id_s)
10501 +       );
10502 +   }
10503 +
10504 +   if (rv == CKR_OK) {
10505 +       rv = _pkcs11h_mem_duplicate (
10506 +           (void*)&(*to)->token_id,
10507 +           NULL,
10508 +           from->token_id,
10509 +           sizeof (struct pkcs11h_token_id_s)
10510 +       );
10511 +   }
10512 +
10513 +   if (rv == CKR_OK) {
10514 +       rv = _pkcs11h_mem_duplicate (
10515 +           (void*)&(*to)->attrCKA_ID,
10516 +           &(*to)->attrCKA_ID_size,
10517 +           from->attrCKA_ID,
10518 +           from->attrCKA_ID_size
10519 +       );
10520 +   }
10521 +
10522 +   if (rv == CKR_OK) {
10523 +       rv = _pkcs11h_mem_duplicate (
10524 +           (void*)&(*to)->certificate_blob,
10525 +           &(*to)->certificate_blob_size,
10526 +           from->certificate_blob,
10527 +           from->certificate_blob_size
10528 +       );
10529 +   }
10530 +
10531 +   PKCS11H_DEBUG (
10532 +       PKCS11H_LOG_DEBUG2,
10533 +       "PKCS#11: pkcs11h_certificate_duplicateCertificateId return rv=%ld-'%s', *to=%p",
10534 +       rv,
10535 +       pkcs11h_getMessage (rv),
10536 +       (void *)*to
10537 +   );
10538 +   
10539 +   return rv;
10540 +}
10541 +
10542 +CK_RV
10543 +pkcs11h_certificate_setCertificateIdCertificateBlob (
10544 +   IN const pkcs11h_certificate_id_t certificate_id,
10545 +   IN const unsigned char * const blob,
10546 +   IN const size_t blob_size
10547 +) {
10548 +   CK_RV rv = CKR_OK;
10549 +
10550 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10551 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10552 +   PKCS11H_ASSERT (certificate_id!=NULL);
10553 +   PKCS11H_ASSERT (blob!=NULL);
10554 +
10555 +   PKCS11H_DEBUG (
10556 +       PKCS11H_LOG_DEBUG2,
10557 +       "PKCS#11: pkcs11h_certificate_setCertificateIdCertificateBlob entry certificate_id=%p",
10558 +       (void *)certificate_id
10559 +   );
10560 +
10561 +   if (rv == CKR_OK && certificate_id->certificate_blob != NULL) {
10562 +       rv = _pkcs11h_mem_free ((void *)&certificate_id->certificate_blob);
10563 +   }
10564 +
10565 +   if (rv == CKR_OK) {
10566 +       rv = _pkcs11h_mem_duplicate (
10567 +           (void *)&certificate_id->certificate_blob,
10568 +           &certificate_id->certificate_blob_size,
10569 +           blob,
10570 +           blob_size
10571 +       );
10572 +   }
10573 +
10574 +   PKCS11H_DEBUG (
10575 +       PKCS11H_LOG_DEBUG2,
10576 +       "PKCS#11: pkcs11h_certificate_setCertificateIdCertificateBlob return rv=%ld-'%s'",
10577 +       rv,
10578 +       pkcs11h_getMessage (rv)
10579 +   );
10580 +   
10581 +   return rv;
10582 +}
10583 +
10584 +CK_RV
10585 +pkcs11h_certificate_freeCertificate (
10586 +   IN pkcs11h_certificate_t certificate
10587 +) {
10588 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10589 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10590 +
10591 +   PKCS11H_DEBUG (
10592 +       PKCS11H_LOG_DEBUG2,
10593 +       "PKCS#11: pkcs11h_certificate_freeCertificate entry certificate=%p",
10594 +       (void *)certificate
10595 +   );
10596 +
10597 +   if (certificate != NULL) {
10598 +       if (certificate->session != NULL) {
10599 +           _pkcs11h_session_release (certificate->session);
10600 +       }
10601 +       pkcs11h_certificate_freeCertificateId (certificate->id);
10602 +       certificate->id = NULL;
10603 +
10604 +#if defined(ENABLE_PKCS11H_THREADING)
10605 +       _pkcs11h_threading_mutexFree (&certificate->mutex);
10606 +#endif
10607 +
10608 +       _pkcs11h_mem_free ((void *)&certificate);
10609 +   }
10610 +
10611 +   PKCS11H_DEBUG (
10612 +       PKCS11H_LOG_DEBUG2,
10613 +       "PKCS#11: pkcs11h_certificate_freeCertificate return"
10614 +   );
10615 +
10616 +   return CKR_OK;
10617 +}
10618 +
10619 +CK_RV
10620 +pkcs11h_certificate_lockSession (
10621 +   IN const pkcs11h_certificate_t certificate
10622 +) {
10623 +#if defined(ENABLE_PKCS11H_THREADING)
10624 +   CK_RV rv = CKR_OK;
10625 +
10626 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10627 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10628 +   PKCS11H_ASSERT (certificate!=NULL);
10629 +
10630 +   if (rv == CKR_OK && certificate->session == NULL) {
10631 +       rv = _pkcs11h_session_getSessionByTokenId (certificate->id->token_id, &certificate->session);
10632 +   }
10633 +
10634 +   if (rv == CKR_OK) {
10635 +       rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex);
10636 +   }
10637 +
10638 +   return rv;
10639 +#else
10640 +   return CKR_OK;
10641 +#endif
10642 +}
10643 +
10644 +CK_RV
10645 +pkcs11h_certificate_releaseSession (
10646 +   IN const pkcs11h_certificate_t certificate
10647 +) {
10648 +#if defined(ENABLE_PKCS11H_THREADING)
10649 +   CK_RV rv = CKR_OK;
10650 +
10651 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10652 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10653 +   PKCS11H_ASSERT (certificate!=NULL);
10654 +
10655 +   if (certificate->session != NULL) {
10656 +       rv = _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
10657 +   }
10658 +
10659 +   return rv;
10660 +#else
10661 +   return CKR_OK;
10662 +#endif
10663 +}
10664 +
10665 +CK_RV
10666 +pkcs11h_certificate_sign (
10667 +   IN const pkcs11h_certificate_t certificate,
10668 +   IN const CK_MECHANISM_TYPE mech_type,
10669 +   IN const unsigned char * const source,
10670 +   IN const size_t source_size,
10671 +   OUT unsigned char * const target,
10672 +   IN OUT size_t * const p_target_size
10673 +) {
10674 +   CK_RV rv = CKR_OK;
10675 +
10676 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10677 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10678 +   PKCS11H_ASSERT (certificate!=NULL);
10679 +   PKCS11H_ASSERT (source!=NULL);
10680 +   /*PKCS11H_ASSERT (target); NOT NEEDED*/
10681 +   PKCS11H_ASSERT (p_target_size!=NULL);
10682 +
10683 +   PKCS11H_DEBUG (
10684 +       PKCS11H_LOG_DEBUG2,
10685 +       "PKCS#11: pkcs11h_certificate_sign entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p,
	*p_target_size=%u",
10686 +       (void *)certificate,
10687 +       mech_type,
10688 +       source,
10689 +       source_size,
10690 +       target,
10691 +       target != NULL ? *p_target_size : 0
10692 +   );
10693 +
10694 +   if (target == NULL) {
10695 +       *p_target_size = 0;
10696 +   }
10697 +
10698 +   if (rv == CKR_OK) {
10699 +       rv = _pkcs11h_certificate_doPrivateOperation (
10700 +           certificate,
10701 +           _pkcs11h_private_op_sign,
10702 +           mech_type,
10703 +           source,
10704 +           source_size,
10705 +           target,
10706 +           p_target_size
10707 +       );
10708 +   }
10709 +
10710 +   PKCS11H_DEBUG (
10711 +       PKCS11H_LOG_DEBUG2,
10712 +       "PKCS#11: pkcs11h_certificate_sign return rv=%ld-'%s', *p_target_size=%u",
10713 +       rv,
10714 +       pkcs11h_getMessage (rv),
10715 +       *p_target_size
10716 +   );
10717 +   
10718 +   return rv;
10719 +}
10720 +
10721 +CK_RV
10722 +pkcs11h_certificate_signRecover (
10723 +   IN const pkcs11h_certificate_t certificate,
10724 +   IN const CK_MECHANISM_TYPE mech_type,
10725 +   IN const unsigned char * const source,
10726 +   IN const size_t source_size,
10727 +   OUT unsigned char * const target,
10728 +   IN OUT size_t * const p_target_size
10729 +) {
10730 +   CK_RV rv = CKR_OK;
10731 +
10732 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10733 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10734 +   PKCS11H_ASSERT (certificate!=NULL);
10735 +   PKCS11H_ASSERT (source!=NULL);
10736 +   /*PKCS11H_ASSERT (target); NOT NEEDED*/
10737 +   PKCS11H_ASSERT (p_target_size!=NULL);
10738 +
10739 +   PKCS11H_DEBUG (
10740 +       PKCS11H_LOG_DEBUG2,
10741 +       "PKCS#11: pkcs11h_certificate_signRecover entry certificate=%p, mech_type=%ld, source=%p, source_size=%u,
	target=%p, *p_target_size=%u",
10742 +       (void *)certificate,
10743 +       mech_type,
10744 +       source,
10745 +       source_size,
10746 +       target,
10747 +       target != NULL ? *p_target_size : 0
10748 +   );
10749 +
10750 +   if (target == NULL) {
10751 +       *p_target_size = 0;
10752 +   }
10753 +
10754 +   if (rv == CKR_OK) {
10755 +       rv = _pkcs11h_certificate_doPrivateOperation (
10756 +           certificate,
10757 +           _pkcs11h_private_op_sign_recover,
10758 +           mech_type,
10759 +           source,
10760 +           source_size,
10761 +           target,
10762 +           p_target_size
10763 +       );
10764 +   }
10765 +
10766 +   PKCS11H_DEBUG (
10767 +       PKCS11H_LOG_DEBUG2,
10768 +       "PKCS#11: pkcs11h_certificate_signRecover return rv=%ld-'%s', *p_target_size=%u",
10769 +       rv,
10770 +       pkcs11h_getMessage (rv),
10771 +       *p_target_size
10772 +   );
10773 +
10774 +   return rv;
10775 +}
10776 +
10777 +CK_RV
10778 +pkcs11h_certificate_signAny (
10779 +   IN const pkcs11h_certificate_t certificate,
10780 +   IN const CK_MECHANISM_TYPE mech_type,
10781 +   IN const unsigned char * const source,
10782 +   IN const size_t source_size,
10783 +   OUT unsigned char * const target,
10784 +   IN OUT size_t * const p_target_size
10785 +) {
10786 +   CK_RV rv = CKR_OK;
10787 +   PKCS11H_BOOL fSigned = FALSE;
10788 +
10789 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10790 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10791 +   PKCS11H_ASSERT (certificate!=NULL);
10792 +   PKCS11H_ASSERT (source!=NULL);
10793 +   /*PKCS11H_ASSERT (target); NOT NEEDED*/
10794 +   PKCS11H_ASSERT (p_target_size!=NULL);
10795 +
10796 +   PKCS11H_DEBUG (
10797 +       PKCS11H_LOG_DEBUG2,
10798 +       "PKCS#11: pkcs11h_certificate_signAny entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p,
	*p_target_size=%u",
10799 +       (void *)certificate,
10800 +       mech_type,
10801 +       source,
10802 +       source_size,
10803 +       target,
10804 +       target != NULL ? *p_target_size : 0
10805 +   );
10806 +
10807 +   if (
10808 +       rv == CKR_OK &&
10809 +       certificate->mask_sign_mode == 0
10810 +   ) {
10811 +       PKCS11H_DEBUG (
10812 +           PKCS11H_LOG_DEBUG1,
10813 +           "PKCS#11: Getting key attributes"
10814 +       );
10815 +       rv = _pkcs11h_certificate_getKeyAttributes (certificate);
10816 +   }
10817 +
10818 +   if (
10819 +       rv == CKR_OK &&
10820 +       !fSigned &&
10821 +       (certificate->mask_sign_mode & PKCS11H_SIGNMODE_MASK_SIGN) != 0
10822 +   ) {
10823 +       rv = pkcs11h_certificate_sign (
10824 +           certificate,
10825 +           mech_type,
10826 +           source,
10827 +           source_size,
10828 +           target,
10829 +           p_target_size
10830 +       );
10831 +
10832 +       if (rv == CKR_OK) {
10833 +           fSigned = TRUE;
10834 +       }
10835 +       else if (
10836 +           rv == CKR_FUNCTION_NOT_SUPPORTED ||
10837 +           rv == CKR_KEY_FUNCTION_NOT_PERMITTED
10838 +       ) {
10839 +           certificate->mask_sign_mode &= ~PKCS11H_SIGNMODE_MASK_SIGN;
10840 +           rv = CKR_OK;
10841 +       }
10842 +   }
10843 +   
10844 +   if (
10845 +       rv == CKR_OK &&
10846 +       !fSigned &&
10847 +       (certificate->mask_sign_mode & PKCS11H_SIGNMODE_MASK_RECOVER) != 0
10848 +   ) {
10849 +       rv = pkcs11h_certificate_signRecover (
10850 +           certificate,
10851 +           mech_type,
10852 +           source,
10853 +           source_size,
10854 +           target,
10855 +           p_target_size
10856 +       );
10857 +
10858 +       if (rv == CKR_OK) {
10859 +           fSigned = TRUE;
10860 +       }
10861 +       else if (
10862 +           rv == CKR_FUNCTION_NOT_SUPPORTED ||
10863 +           rv == CKR_KEY_FUNCTION_NOT_PERMITTED
10864 +       ) {
10865 +           certificate->mask_sign_mode &= ~PKCS11H_SIGNMODE_MASK_RECOVER;
10866 +           rv = CKR_OK;
10867 +       }
10868 +   }
10869 +
10870 +   if (rv == CKR_OK && !fSigned) {
10871 +       rv = CKR_FUNCTION_FAILED;
10872 +   }
10873 +   
10874 +   PKCS11H_DEBUG (
10875 +       PKCS11H_LOG_DEBUG2,
10876 +       "PKCS#11: pkcs11h_certificate_signAny return rv=%ld-'%s', *p_target_size=%p",
10877 +       rv,
10878 +       pkcs11h_getMessage (rv),
10879 +       (void *)*p_target_size
10880 +   );
10881 +
10882 +   return rv;
10883 +}
10884 +
10885 +CK_RV
10886 +pkcs11h_certificate_decrypt (
10887 +   IN const pkcs11h_certificate_t certificate,
10888 +   IN const CK_MECHANISM_TYPE mech_type,
10889 +   IN const unsigned char * const source,
10890 +   IN const size_t source_size,
10891 +   OUT unsigned char * const target,
10892 +   IN OUT size_t * const p_target_size
10893 +) {
10894 +   CK_RV rv = CKR_OK;
10895 +
10896 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10897 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10898 +   PKCS11H_ASSERT (certificate!=NULL);
10899 +   PKCS11H_ASSERT (source!=NULL);
10900 +   /*PKCS11H_ASSERT (target); NOT NEEDED*/
10901 +   PKCS11H_ASSERT (p_target_size!=NULL);
10902 +
10903 +   PKCS11H_DEBUG (
10904 +       PKCS11H_LOG_DEBUG2,
10905 +       "PKCS#11: pkcs11h_decrypt entry certificate=%p, mech_type=%ld, source=%p, source_size=%u, target=%p,
	*p_target_size=%u",
10906 +       (void *)certificate,
10907 +       mech_type,
10908 +       source,
10909 +       source_size,
10910 +       target,
10911 +       target != NULL ? *p_target_size : 0
10912 +   );
10913 +
10914 +   if (target == NULL) {
10915 +       *p_target_size = 0;
10916 +   }
10917 +
10918 +   if (rv == CKR_OK) {
10919 +       rv = _pkcs11h_certificate_doPrivateOperation (
10920 +           certificate,
10921 +           _pkcs11h_private_op_decrypt,
10922 +           mech_type,
10923 +           source,
10924 +           source_size,
10925 +           target,
10926 +           p_target_size
10927 +       );
10928 +   }
10929 +
10930 +   PKCS11H_DEBUG (
10931 +       PKCS11H_LOG_DEBUG2,
10932 +       "PKCS#11: pkcs11h_decrypt return rv=%ld-'%s', *p_target_size=%u",
10933 +       rv,
10934 +       pkcs11h_getMessage (rv),
10935 +       *p_target_size
10936 +   );
10937 +
10938 +   return rv;
10939 +}
10940 +
10941 +CK_RV
10942 +pkcs11h_certificate_create (
10943 +   IN const pkcs11h_certificate_id_t certificate_id,
10944 +   IN void * const user_data,
10945 +   IN const unsigned mask_prompt,
10946 +   IN const int pin_cache_period,
10947 +   OUT pkcs11h_certificate_t * const p_certificate
10948 +) {
10949 +   pkcs11h_certificate_t certificate = NULL;
10950 +   CK_RV rv = CKR_OK;
10951 +
10952 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
10953 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
10954 +   /*PKCS11H_ASSERT (user_data!=NULL); NOT NEEDED */
10955 +   PKCS11H_ASSERT (p_certificate!=NULL);
10956 +
10957 +   PKCS11H_DEBUG (
10958 +       PKCS11H_LOG_DEBUG2,
10959 +       "PKCS#11: pkcs11h_certificate_create entry certificate_id=%p, user_data=%p, mask_prompt=%08x,
	pin_cache_period=%d, p_certificate=%p",
10960 +       (void *)certificate_id,
10961 +       user_data,
10962 +       mask_prompt,
10963 +       pin_cache_period,
10964 +       (void *)p_certificate
10965 +   );
10966 +
10967 +   *p_certificate = NULL;
10968 +
10969 +   if (
10970 +       rv == CKR_OK &&
10971 +       (rv = _pkcs11h_mem_malloc ((void*)&certificate, sizeof (struct pkcs11h_certificate_s))) == CKR_OK
10972 +   ) {
10973 +       certificate->user_data = user_data;
10974 +       certificate->mask_prompt = mask_prompt;
10975 +       certificate->key_handle = PKCS11H_INVALID_OBJECT_HANDLE;
10976 +       certificate->pin_cache_period = pin_cache_period;
10977 +   }
10978 +
10979 +#if defined(ENABLE_PKCS11H_THREADING)
10980 +   if (rv == CKR_OK) {
10981 +       rv = _pkcs11h_threading_mutexInit (&certificate->mutex);
10982 +   }
10983 +#endif
10984 +
10985 +   if (rv == CKR_OK) {
10986 +       rv = pkcs11h_certificate_duplicateCertificateId (&certificate->id, certificate_id);
10987 +   }
10988 +
10989 +   if (rv == CKR_OK) {
10990 +       *p_certificate = certificate;
10991 +       certificate = NULL;
10992 +   }
10993 +
10994 +   if (certificate != NULL) {
10995 +#if defined(ENABLE_PKCS11H_THREADING)
10996 +       _pkcs11h_threading_mutexFree (&certificate->mutex);
10997 +#endif
10998 +       _pkcs11h_mem_free ((void *)&certificate);
10999 +   }
11000 +
11001 +   PKCS11H_DEBUG (
11002 +       PKCS11H_LOG_DEBUG2,
11003 +       "PKCS#11: pkcs11h_certificate_create return rv=%ld-'%s' *p_certificate=%p",
11004 +       rv,
11005 +       pkcs11h_getMessage (rv),
11006 +       (void *)*p_certificate
11007 +   );
11008 +   
11009 +   return rv;
11010 +}
11011 +
11012 +unsigned
11013 +pkcs11h_certificate_getPromptMask (
11014 +   IN const pkcs11h_certificate_t certificate
11015 +) {
11016 +   PKCS11H_ASSERT (certificate!=NULL);
11017 +
11018 +   return certificate->mask_prompt;
11019 +}
11020 +
11021 +void
11022 +pkcs11h_certificate_setPromptMask (
11023 +   IN const pkcs11h_certificate_t certificate,
11024 +   IN const unsigned mask_prompt
11025 +) {
11026 +   PKCS11H_ASSERT (certificate!=NULL);
11027 +
11028 +   certificate->mask_prompt = mask_prompt;
11029 +}
11030 +
11031 +void *
11032 +pkcs11h_certificate_getUserData (
11033 +   IN const pkcs11h_certificate_t certificate
11034 +) {
11035 +   PKCS11H_ASSERT (certificate!=NULL);
11036 +
11037 +   return certificate->user_data;
11038 +}
11039 +
11040 +void
11041 +pkcs11h_certificate_setUserData (
11042 +   IN const pkcs11h_certificate_t certificate,
11043 +   IN void * const user_data
11044 +) {
11045 +   PKCS11H_ASSERT (certificate!=NULL);
11046 +
11047 +   certificate->user_data = user_data;
11048 +}
11049 +
11050 +CK_RV
11051 +pkcs11h_certificate_getCertificateId (
11052 +   IN const pkcs11h_certificate_t certificate,
11053 +   OUT pkcs11h_certificate_id_t * const p_certificate_id
11054 +) {
11055 +   CK_RV rv = CKR_OK;
11056 +
11057 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
11058 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
11059 +   PKCS11H_ASSERT (certificate!=NULL);
11060 +   PKCS11H_ASSERT (p_certificate_id!=NULL);
11061 +
11062 +   PKCS11H_DEBUG (
11063 +       PKCS11H_LOG_DEBUG2,
11064 +       "PKCS#11: pkcs11h_certificate_getCertificateId entry certificate=%p, certificate_id=%p",
11065 +       (void *)certificate,
11066 +       (void *)p_certificate_id
11067 +   );
11068 +
11069 +   if (rv == CKR_OK) {
11070 +       rv = pkcs11h_certificate_duplicateCertificateId (
11071 +           p_certificate_id,
11072 +           certificate->id
11073 +       );
11074 +   }
11075 +
11076 +   PKCS11H_DEBUG (
11077 +       PKCS11H_LOG_DEBUG2,
11078 +       "PKCS#11: pkcs11h_certificate_getCertificateId return rv=%ld-'%s'",
11079 +       rv,
11080 +       pkcs11h_getMessage (rv)
11081 +   );
11082 +
11083 +   return rv;
11084 +}
11085 +
11086 +CK_RV
11087 +pkcs11h_certificate_getCertificateBlob (
11088 +   IN const pkcs11h_certificate_t certificate,
11089 +   OUT unsigned char * const certificate_blob,
11090 +   IN OUT size_t * const p_certificate_blob_size
11091 +) {
11092 +#if defined(ENABLE_PKCS11H_THREADING)
11093 +   PKCS11H_BOOL mutex_locked = FALSE;
11094 +#endif
11095 +   CK_RV rv = CKR_OK;
11096 +   size_t certifiate_blob_size_max = 0;
11097 +   
11098 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
11099 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
11100 +   PKCS11H_ASSERT (certificate!=NULL);
11101 +   /*PKCS11H_ASSERT (certificate_blob!=NULL); NOT NEEDED */
11102 +   PKCS11H_ASSERT (p_certificate_blob_size!=NULL);
11103 +
11104 +   PKCS11H_DEBUG (
11105 +       PKCS11H_LOG_DEBUG2,
11106 +       "PKCS#11: pkcs11h_certificate_getCertificateBlob entry certificate=%p, certificate_blob=%p,
	*p_certificate_blob_size=%u",
11107 +       (void *)certificate,
11108 +       certificate_blob,
11109 +       certificate_blob != NULL ? *p_certificate_blob_size : 0
11110 +   );
11111 +
11112 +   if (certificate_blob != NULL) {
11113 +       certifiate_blob_size_max = *p_certificate_blob_size;
11114 +   }
11115 +   *p_certificate_blob_size = 0;
11116 +
11117 +#if defined(ENABLE_PKCS11H_THREADING)
11118 +   if (
11119 +       rv == CKR_OK &&
11120 +       (rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) == CKR_OK
11121 +   ) {
11122 +       mutex_locked = TRUE;
11123 +   }
11124 +#endif
11125 +
11126 +   if (rv == CKR_OK && certificate->id->certificate_blob == NULL) {
11127 +       PKCS11H_BOOL op_succeed = FALSE;
11128 +       PKCS11H_BOOL login_retry = FALSE;
11129 +       while (rv == CKR_OK && !op_succeed) {
11130 +           if (certificate->session == NULL) {
11131 +               rv = CKR_SESSION_HANDLE_INVALID;
11132 +           }
11133 +
11134 +           if (rv == CKR_OK) {
11135 +               rv = _pkcs11h_certificate_loadCertificate (certificate);
11136 +           }
11137 +
11138 +           if (rv == CKR_OK) {
11139 +               op_succeed = TRUE;
11140 +           }
11141 +           else {
11142 +               if (!login_retry) {
11143 +                   login_retry = TRUE;
11144 +                   rv = _pkcs11h_certificate_resetSession (
11145 +                       certificate,
11146 +                       TRUE,
11147 +                       FALSE
11148 +                   );
11149 +               }
11150 +           }
11151 +       }
11152 +   }
11153 +   
11154 +   if (
11155 +       rv == CKR_OK &&
11156 +       certificate->id->certificate_blob == NULL
11157 +   ) {
11158 +       rv = CKR_FUNCTION_REJECTED;
11159 +   }
11160 +
11161 +   if (rv == CKR_OK) {
11162 +       _pkcs11h_certificate_updateCertificateIdDescription (certificate->id);
11163 +   }
11164 +
11165 +   if (rv == CKR_OK) {
11166 +       *p_certificate_blob_size = certificate->id->certificate_blob_size;
11167 +   }
11168 +
11169 +   if (certificate_blob != NULL) {
11170 +       if (
11171 +           rv == CKR_OK &&
11172 +           certificate->id->certificate_blob_size > certifiate_blob_size_max
11173 +       ) {
11174 +           rv = CKR_BUFFER_TOO_SMALL;
11175 +       }
11176 +   
11177 +       if (rv == CKR_OK) {
11178 +           memmove (
11179 +               certificate_blob,
11180 +               certificate->id->certificate_blob,
11181 +               *p_certificate_blob_size
11182 +           );
11183 +       }
11184 +   }
11185 +
11186 +#if defined(ENABLE_PKCS11H_THREADING)
11187 +   if (mutex_locked) {
11188 +       _pkcs11h_threading_mutexRelease (&certificate->mutex);
11189 +       mutex_locked = FALSE;
11190 +   }
11191 +#endif
11192 +
11193 +   PKCS11H_DEBUG (
11194 +       PKCS11H_LOG_DEBUG2,
11195 +       "PKCS#11: pkcs11h_certificate_getCertificateBlob return rv=%ld-'%s'",
11196 +       rv,
11197 +       pkcs11h_getMessage (rv)
11198 +   );
11199 +
11200 +   return rv;
11201 +}
11202 +
11203 +#if defined(ENABLE_PKCS11H_SERIALIZATION)
11204 +
11205 +CK_RV
11206 +pkcs11h_certificate_serializeCertificateId (
11207 +   OUT char * const sz,
11208 +   IN OUT size_t *max,
11209 +   IN const pkcs11h_certificate_id_t certificate_id
11210 +) {
11211 +   CK_RV rv = CKR_OK;
11212 +   size_t saved_max = 0;
11213 +   size_t n = 0;
11214 +   size_t _max = 0;
11215 +
11216 +   /*PKCS11H_ASSERT (sz!=NULL); Not required */
11217 +   PKCS11H_ASSERT (max!=NULL);
11218 +   PKCS11H_ASSERT (certificate_id!=NULL);
11219 +
11220 +   PKCS11H_DEBUG (
11221 +       PKCS11H_LOG_DEBUG2,
11222 +       "PKCS#11: pkcs11h_certificate_serializeCertificateId entry sz=%p, *max=%u, certificate_id=%p",
11223 +       sz,
11224 +       sz != NULL ? *max : 0,
11225 +       (void *)certificate_id
11226 +   );
11227 +
11228 +   if (sz != NULL) {
11229 +       saved_max = n = *max;
11230 +   }
11231 +   *max = 0;
11232 +
11233 +   if (rv == CKR_OK) {
11234 +       rv = pkcs11h_token_serializeTokenId (
11235 +           sz,
11236 +           &n,
11237 +           certificate_id->token_id
11238 +       );
11239 +   }
11240 +
11241 +   if (rv == CKR_OK) {
11242 +       _max = n + certificate_id->attrCKA_ID_size*2 + 1;
11243 +   }
11244 +
11245 +   if (sz != NULL) {
11246 +       if (saved_max < _max) {
11247 +           rv = CKR_ATTRIBUTE_VALUE_INVALID;
11248 +       }
11249 +
11250 +       if (rv == CKR_OK) {
11251 +           sz[n-1] = '/';
11252 +           rv = _pkcs11h_util_binaryToHex (
11253 +               sz+n,
11254 +               saved_max-n,
11255 +               certificate_id->attrCKA_ID,
11256 +               certificate_id->attrCKA_ID_size
11257 +           );
11258 +
11259 +       }
11260 +   }
11261 +
11262 +   *max = _max;
11263 +
11264 +   PKCS11H_DEBUG (
11265 +       PKCS11H_LOG_DEBUG2,
11266 +       "PKCS#11: pkcs11h_certificate_serializeCertificateId return rv=%ld-'%s', *max=%u, sz='%s'",
11267 +       rv,
11268 +       pkcs11h_getMessage (rv),
11269 +       *max,
11270 +       sz
11271 +   );
11272 +
11273 +   return rv;
11274 +}
11275 +
11276 +CK_RV
11277 +pkcs11h_certificate_deserializeCertificateId (
11278 +   OUT pkcs11h_certificate_id_t * const p_certificate_id,
11279 +   IN const char * const sz
11280 +) {
11281 +   pkcs11h_certificate_id_t certificate_id = NULL;
11282 +   CK_RV rv = CKR_OK;
11283 +   char *p = NULL;
11284 +   char *_sz = NULL;
11285 +
11286 +   PKCS11H_ASSERT (p_certificate_id!=NULL);
11287 +   PKCS11H_ASSERT (sz!=NULL);
11288 +
11289 +   *p_certificate_id = NULL;
11290 +
11291 +   PKCS11H_DEBUG (
11292 +       PKCS11H_LOG_DEBUG2,
11293 +       "PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'",
11294 +       (void *)p_certificate_id,
11295 +       sz
11296 +   );
11297 +
11298 +   if (rv == CKR_OK) {
11299 +       rv = _pkcs11h_mem_strdup (
11300 +           (void *)&_sz,
11301 +           sz
11302 +       );
11303 +   }
11304 +
11305 +   if (rv == CKR_OK) {
11306 +       p = _sz;
11307 +   }
11308 +
11309 +   if (rv == CKR_OK) {
11310 +       rv = _pkcs11h_certificate_newCertificateId (&certificate_id);
11311 +   }
11312 +
11313 +   if (
11314 +       rv == CKR_OK &&
11315 +       (p = strrchr (_sz, '/')) == NULL
11316 +   ) {
11317 +       rv = CKR_ATTRIBUTE_VALUE_INVALID;
11318 +   }
11319 +
11320 +   if (rv == CKR_OK) {
11321 +       *p = '\x0';
11322 +       p++;
11323 +   }
11324 +
11325 +   if (rv == CKR_OK) {
11326 +       rv = pkcs11h_token_deserializeTokenId (
11327 +           &certificate_id->token_id,
11328 +           _sz
11329 +       );
11330 +   }
11331 +
11332 +   if (rv == CKR_OK) {
11333 +       certificate_id->attrCKA_ID_size = strlen (p)/2;
11334 +   }
11335 +
11336 +   if (
11337 +       rv == CKR_OK &&
11338 +       (rv = _pkcs11h_mem_malloc (
11339 +           (void *)&certificate_id->attrCKA_ID,
11340 +           certificate_id->attrCKA_ID_size)
11341 +       ) == CKR_OK
11342 +   ) {
11343 +       rv = _pkcs11h_util_hexToBinary (
11344 +           certificate_id->attrCKA_ID,
11345 +           p,
11346 +           &certificate_id->attrCKA_ID_size
11347 +       );
11348 +   }
11349 +
11350 +   if (rv == CKR_OK) {
11351 +       *p_certificate_id = certificate_id;
11352 +       certificate_id = NULL;
11353 +   }
11354 +
11355 +   if (certificate_id != NULL) {
11356 +       pkcs11h_certificate_freeCertificateId (certificate_id);
11357 +       certificate_id = NULL;
11358 +   }
11359 +
11360 +   if (_sz != NULL) {
11361 +       _pkcs11h_mem_free ((void *)&_sz);
11362 +   }
11363 +
11364 +   PKCS11H_DEBUG (
11365 +       PKCS11H_LOG_DEBUG2,
11366 +       "PKCS#11: pkcs11h_certificate_deserializeCertificateId return rv=%ld-'%s'",
11367 +       rv,
11368 +       pkcs11h_getMessage (rv)
11369 +   );
11370 +
11371 +   return rv;
11372 +
11373 +}
11374 +
11375 +#endif             /* ENABLE_PKCS11H_SERIALIZATION */
11376 +
11377 +CK_RV
11378 +pkcs11h_certificate_ensureCertificateAccess (
11379 +   IN const pkcs11h_certificate_t certificate
11380 +) {
11381 +#if defined(ENABLE_PKCS11H_THREADING)
11382 +   PKCS11H_BOOL mutex_locked_cert = FALSE;
11383 +   PKCS11H_BOOL mutex_locked_sess = FALSE;
11384 +#endif
11385 +   PKCS11H_BOOL validCert = FALSE;
11386 +   CK_RV rv = CKR_OK;
11387 +
11388 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
11389 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
11390 +   PKCS11H_ASSERT (certificate!=NULL);
11391 +
11392 +   PKCS11H_DEBUG (
11393 +       PKCS11H_LOG_DEBUG2,
11394 +       "PKCS#11: pkcs11h_certificate_ensureCertificateAccess entry certificate=%p",
11395 +       (void *)certificate
11396 +   );
11397 +
11398 +#if defined(ENABLE_PKCS11H_THREADING)
11399 +   if (
11400 +       rv == CKR_OK &&
11401 +       (rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) == CKR_OK
11402 +   ) {
11403 +       mutex_locked_cert = TRUE;
11404 +   }
11405 +#endif
11406 +
11407 +   if (!validCert && rv == CKR_OK) {
11408 +       CK_OBJECT_HANDLE h = PKCS11H_INVALID_OBJECT_HANDLE;
11409 +
11410 +       if (certificate->session == NULL) {
11411 +           rv = CKR_SESSION_HANDLE_INVALID;
11412 +       }
11413 +
11414 +#if defined(ENABLE_PKCS11H_THREADING)
11415 +       if (
11416 +           rv == CKR_OK &&
11417 +           (rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) == CKR_OK
11418 +       ) {
11419 +           mutex_locked_sess = TRUE;
11420 +       }
11421 +#endif
11422 +
11423 +       if (
11424 +           (rv = _pkcs11h_session_getObjectById (
11425 +               certificate->session,
11426 +               CKO_CERTIFICATE,
11427 +               certificate->id->attrCKA_ID,
11428 +               certificate->id->attrCKA_ID_size,
11429 +               &h
11430 +           )) == CKR_OK
11431 +       ) {
11432 +           validCert = TRUE;
11433 +       }
11434 +
11435 +#if defined(ENABLE_PKCS11H_THREADING)
11436 +       if (mutex_locked_sess) {
11437 +           _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
11438 +           mutex_locked_sess = FALSE;
11439 +       }
11440 +#endif
11441 +
11442 +       if (rv != CKR_OK) {
11443 +           PKCS11H_DEBUG (
11444 +               PKCS11H_LOG_DEBUG1,
11445 +               "PKCS#11: Cannot access existing object rv=%ld-'%s'",
11446 +               rv,
11447 +               pkcs11h_getMessage (rv)
11448 +           );
11449 +
11450 +           /*
11451 +            * Ignore error
11452 +            */
11453 +           rv = CKR_OK;
11454 +       }
11455 +   }
11456 +
11457 +   if (!validCert && rv == CKR_OK) {
11458 +       if (
11459 +           (rv = _pkcs11h_certificate_resetSession (
11460 +               certificate,
11461 +               TRUE,
11462 +               FALSE
11463 +           )) == CKR_OK
11464 +       ) {
11465 +           validCert = TRUE;
11466 +       }
11467 +   }
11468 +
11469 +#if defined(ENABLE_PKCS11H_THREADING)
11470 +   if (mutex_locked_cert) {
11471 +       _pkcs11h_threading_mutexRelease (&certificate->mutex);
11472 +       mutex_locked_cert = FALSE;
11473 +   }
11474 +#endif
11475 +
11476 +   PKCS11H_DEBUG (
11477 +       PKCS11H_LOG_DEBUG2,
11478 +       "PKCS#11: pkcs11h_certificate_ensureCertificateAccess return rv=%ld-'%s'",
11479 +       rv,
11480 +       pkcs11h_getMessage (rv)
11481 +   );
11482 +   
11483 +   return rv;
11484 +}
11485 +
11486 +CK_RV
11487 +pkcs11h_certificate_ensureKeyAccess (
11488 +   IN const pkcs11h_certificate_t certificate
11489 +) {
11490 +#if defined(ENABLE_PKCS11H_THREADING)
11491 +   PKCS11H_BOOL mutex_locked_cert = FALSE;
11492 +   PKCS11H_BOOL mutex_locked_sess = FALSE;
11493 +#endif
11494 +   CK_RV rv = CKR_OK;
11495 +   PKCS11H_BOOL valid_key = FALSE;
11496 +
11497 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
11498 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
11499 +   PKCS11H_ASSERT (certificate!=NULL);
11500 +
11501 +   PKCS11H_DEBUG (
11502 +       PKCS11H_LOG_DEBUG2,
11503 +       "PKCS#11: pkcs11h_certificate_ensureKeyAccess entry certificate=%p",
11504 +       (void *)certificate
11505 +   );
11506 +
11507 +#if defined(ENABLE_PKCS11H_THREADING)
11508 +   if (
11509 +       rv == CKR_OK &&
11510 +       (rv = _pkcs11h_threading_mutexLock (&certificate->mutex)) == CKR_OK
11511 +   ) {
11512 +       mutex_locked_cert = TRUE;
11513 +   }
11514 +#endif
11515 +
11516 +   if (!valid_key && rv == CKR_OK) {
11517 +
11518 +       if (certificate->session == NULL) {
11519 +           rv = CKR_SESSION_HANDLE_INVALID;
11520 +       }
11521 +
11522 +#if defined(ENABLE_PKCS11H_THREADING)
11523 +       if (
11524 +           rv == CKR_OK &&
11525 +           (rv = _pkcs11h_threading_mutexLock (&certificate->session->mutex)) == CKR_OK
11526 +       ) {
11527 +           mutex_locked_sess = TRUE;
11528 +       }
11529 +#endif
11530 +
11531 +       if (
11532 +           (rv = _pkcs11h_session_getObjectById (
11533 +               certificate->session,
11534 +               CKO_PRIVATE_KEY,
11535 +               certificate->id->attrCKA_ID,
11536 +               certificate->id->attrCKA_ID_size,
11537 +               &certificate->key_handle
11538 +           )) == CKR_OK
11539 +       ) {
11540 +           valid_key = TRUE;
11541 +       }
11542 +
11543 +#if defined(ENABLE_PKCS11H_THREADING)
11544 +       if (mutex_locked_sess) {
11545 +           _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
11546 +           mutex_locked_sess = FALSE;
11547 +       }
11548 +#endif
11549 +
11550 +       if (rv != CKR_OK) {
11551 +           PKCS11H_DEBUG (
11552 +               PKCS11H_LOG_DEBUG1,
11553 +               "PKCS#11: Cannot access existing object rv=%ld-'%s'",
11554 +               rv,
11555 +               pkcs11h_getMessage (rv)
11556 +           );
11557 +
11558 +           /*
11559 +            * Ignore error
11560 +            */
11561 +           rv = CKR_OK;
11562 +           certificate->key_handle = PKCS11H_INVALID_OBJECT_HANDLE;
11563 +       }
11564 +   }
11565 +
11566 +   if (!valid_key && rv == CKR_OK) {
11567 +       if (
11568 +           (rv = _pkcs11h_certificate_resetSession (
11569 +               certificate,
11570 +               FALSE,
11571 +               FALSE
11572 +           )) == CKR_OK
11573 +       ) {
11574 +           valid_key = TRUE;
11575 +       }
11576 +   }
11577 +
11578 +#if defined(ENABLE_PKCS11H_THREADING)
11579 +   if (mutex_locked_sess) {
11580 +       _pkcs11h_threading_mutexRelease (&certificate->session->mutex);
11581 +       mutex_locked_sess = FALSE;
11582 +   }
11583 +#endif
11584 +
11585 +   PKCS11H_DEBUG (
11586 +       PKCS11H_LOG_DEBUG2,
11587 +       "PKCS#11: pkcs11h_certificate_ensureKeyAccess return rv=%ld-'%s'",
11588 +       rv,
11589 +       pkcs11h_getMessage (rv)
11590 +   );
11591 +   
11592 +   return rv;
11593 +}
11594 +
11595 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
11596 +
11597 +#if defined(ENABLE_PKCS11H_LOCATE)
11598 +/*======================================================================*
11599 + * LOCATE INTERFACE
11600 + *======================================================================*/
11601 +
11602 +#if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE)
11603 +
11604 +static
11605 +CK_RV
11606 +_pkcs11h_locate_getTokenIdBySlotId (
11607 +   IN const char * const slot,
11608 +   OUT pkcs11h_token_id_t * const p_token_id
11609 +) {
11610 +   pkcs11h_provider_t current_provider = NULL;
11611 +   char reference[sizeof (((pkcs11h_provider_t)NULL)->reference)];
11612 +
11613 +   CK_SLOT_ID selected_slot = PKCS11H_INVALID_SLOT_ID;
11614 +   CK_TOKEN_INFO info;
11615 +   CK_RV rv = CKR_OK;
11616 +
11617 +   PKCS11H_ASSERT (slot!=NULL);
11618 +   PKCS11H_ASSERT (p_token_id!=NULL);
11619 +
11620 +   PKCS11H_DEBUG (
11621 +       PKCS11H_LOG_DEBUG2,
11622 +       "PKCS#11: _pkcs11h_locate_getTokenIdBySlotId entry slot='%s', p_token_id=%p",
11623 +       slot,
11624 +       (void *)p_token_id
11625 +   );
11626 +
11627 +   *p_token_id = NULL;
11628 +
11629 +   if (rv == CKR_OK) {
11630 +       if (strchr (slot, ':') == NULL) {
11631 +           reference[0] = '\0';
11632 +           selected_slot = atol (slot);
11633 +       }
11634 +       else {
11635 +           char *p;
11636 +
11637 +           strncpy (reference, slot, sizeof (reference));
11638 +           reference[sizeof (reference)-1] = '\0';
11639 +
11640 +           p = strchr (reference, ':');
11641 +
11642 +           *p = '\0';
11643 +           p++;
11644 +           selected_slot = atol (p);
11645 +       }
11646 +   }
11647 +   
11648 +   if (rv == CKR_OK) {
11649 +       current_provider=s_pkcs11h_data->providers;
11650 +       while (
11651 +           current_provider != NULL &&
11652 +           reference[0] != '\0' &&     /* So first provider will be selected */
11653 +           strcmp (current_provider->reference, reference)
11654 +       ) {
11655 +           current_provider = current_provider->next;
11656 +       }
11657 +   
11658 +       if (
11659 +           current_provider == NULL ||
11660 +           (
11661 +               current_provider != NULL &&
11662 +               !current_provider->enabled
11663 +           )
11664 +       ) {
11665 +           rv = CKR_SLOT_ID_INVALID;
11666 +       }
11667 +   }
11668 +
11669 +   if (
11670 +       rv == CKR_OK &&
11671 +       (rv = current_provider->f->C_GetTokenInfo (selected_slot, &info)) == CKR_OK
11672 +   ) {
11673 +       rv = _pkcs11h_token_getTokenId (
11674 +           &info,
11675 +           p_token_id
11676 +       );
11677 +   }
11678 +
11679 +   PKCS11H_DEBUG (
11680 +       PKCS11H_LOG_DEBUG2,
11681 +       "PKCS#11: _pkcs11h_locate_getTokenIdBySlotId return rv=%ld-'%s', *p_token_id=%p",
11682 +       rv,
11683 +       pkcs11h_getMessage (rv),
11684 +       (void *)*p_token_id
11685 +   );
11686 +
11687 +   return rv;
11688 +}
11689 +
11690 +static
11691 +CK_RV
11692 +_pkcs11h_locate_getTokenIdBySlotName (
11693 +   IN const char * const name,
11694 +   OUT pkcs11h_token_id_t * const p_token_id
11695 +) {
11696 +   pkcs11h_provider_t current_provider = NULL;
11697 +
11698 +   CK_SLOT_ID selected_slot = PKCS11H_INVALID_SLOT_ID;
11699 +   CK_TOKEN_INFO info;
11700 +   CK_RV rv = CKR_OK;
11701 +
11702 +   PKCS11H_BOOL found = FALSE;
11703 +
11704 +   PKCS11H_ASSERT (name!=NULL);
11705 +   PKCS11H_ASSERT (p_token_id!=NULL);
11706 +
11707 +   PKCS11H_DEBUG (
11708 +       PKCS11H_LOG_DEBUG2,
11709 +       "PKCS#11: _pkcs11h_locate_getTokenIdBySlotName entry name='%s', p_token_id=%p",
11710 +       name,
11711 +       (void *)p_token_id
11712 +   );
11713 +
11714 +   *p_token_id = NULL;
11715 +
11716 +   current_provider = s_pkcs11h_data->providers;
11717 +   while (
11718 +       current_provider != NULL &&
11719 +       rv == CKR_OK &&
11720 +       !found
11721 +   ) {
11722 +       CK_SLOT_ID_PTR slots = NULL;
11723 +       CK_ULONG slotnum;
11724 +       CK_SLOT_ID slot_index;
11725 +
11726 +       if (!current_provider->enabled) {
11727 +           rv = CKR_CRYPTOKI_NOT_INITIALIZED;
11728 +       }
11729 +
11730 +       if (rv == CKR_OK) {
11731 +           rv = _pkcs11h_session_getSlotList (
11732 +               current_provider,
11733 +               CK_TRUE,
11734 +               &slots,
11735 +               &slotnum
11736 +           );
11737 +       }
11738 +
11739 +       for (
11740 +           slot_index=0;
11741 +           (
11742 +               slot_index < slotnum &&
11743 +               rv == CKR_OK &&
11744 +               !found
11745 +           );
11746 +           slot_index++
11747 +       ) {
11748 +           CK_SLOT_INFO info;
11749 +
11750 +           if (
11751 +               (rv = current_provider->f->C_GetSlotInfo (
11752 +                   slots[slot_index],
11753 +                   &info
11754 +               )) == CKR_OK
11755 +           ) {
11756 +               char current_name[sizeof (info.slotDescription)+1];
11757 +
11758 +               _pkcs11h_util_fixupFixedString (
11759 +                   current_name,
11760 +                   (char *)info.slotDescription,
11761 +                   sizeof (info.slotDescription)
11762 +               );
11763 +
11764 +               if (!strcmp (current_name, name)) {
11765 +                   found = TRUE;
11766 +                   selected_slot = slots[slot_index];
11767 +               }
11768 +           }
11769 +
11770 +           if (rv != CKR_OK) {
11771 +               PKCS11H_DEBUG (
11772 +                   PKCS11H_LOG_DEBUG1,
11773 +                   "PKCS#11: Cannot get slot information for provider '%s' slot %ld rv=%ld-'%s'",
11774 +                   current_provider->manufacturerID,
11775 +                   slots[slot_index],
11776 +                   rv,
11777 +                   pkcs11h_getMessage (rv)
11778 +               );
11779 +
11780 +               /*
11781 +                * Ignore error
11782 +                */
11783 +               rv = CKR_OK;
11784 +           }
11785 +       }
11786 +
11787 +       if (rv != CKR_OK) {
11788 +           PKCS11H_DEBUG (
11789 +               PKCS11H_LOG_DEBUG1,
11790 +               "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
11791 +               current_provider->manufacturerID,
11792 +               rv,
11793 +               pkcs11h_getMessage (rv)
11794 +           );
11795 +
11796 +           /*
11797 +            * Ignore error
11798 +            */
11799 +           rv = CKR_OK;
11800 +       }
11801 +
11802 +       if (slots != NULL) {
11803 +           _pkcs11h_mem_free ((void *)&slots);
11804 +           slots = NULL;
11805 +       }
11806 +
11807 +       if (!found) {
11808 +           current_provider = current_provider->next;
11809 +       }
11810 +   }
11811 +
11812 +   if (rv == CKR_OK && !found) {
11813 +       rv = CKR_SLOT_ID_INVALID;
11814 +   }
11815 +
11816 +   if (
11817 +       rv == CKR_OK &&
11818 +       (rv = current_provider->f->C_GetTokenInfo (selected_slot, &info)) == CKR_OK
11819 +   ) {
11820 +       rv = _pkcs11h_token_getTokenId (
11821 +           &info,
11822 +           p_token_id
11823 +       );
11824 +   }
11825 +
11826 +   PKCS11H_DEBUG (
11827 +       PKCS11H_LOG_DEBUG2,
11828 +       "PKCS#11: _pkcs11h_locate_getTokenIdBySlotName return rv=%ld-'%s' *p_token_id=%p",
11829 +       rv,
11830 +       pkcs11h_getMessage (rv),
11831 +       (void *)*p_token_id
11832 +   );
11833 +
11834 +   return rv; 
11835 +}
11836 +
11837 +static
11838 +CK_RV
11839 +_pkcs11h_locate_getTokenIdByLabel (
11840 +   IN const char * const label,
11841 +   OUT pkcs11h_token_id_t * const p_token_id
11842 +) {
11843 +   pkcs11h_provider_t current_provider = NULL;
11844 +
11845 +   CK_SLOT_ID selected_slot = PKCS11H_INVALID_SLOT_ID;
11846 +   CK_TOKEN_INFO info;
11847 +   CK_RV rv = CKR_OK;
11848 +
11849 +   PKCS11H_BOOL found = FALSE;
11850 +
11851 +   PKCS11H_ASSERT (label!=NULL);
11852 +   PKCS11H_ASSERT (p_token_id!=NULL);
11853 +
11854 +   PKCS11H_DEBUG (
11855 +       PKCS11H_LOG_DEBUG2,
11856 +       "PKCS#11: _pkcs11h_locate_getTokenIdByLabel entry label='%s', p_token_id=%p",
11857 +       label,
11858 +       (void *)p_token_id
11859 +   );
11860 +
11861 +   *p_token_id = NULL;
11862 +
11863 +   current_provider = s_pkcs11h_data->providers;
11864 +   while (
11865 +       current_provider != NULL &&
11866 +       rv == CKR_OK &&
11867 +       !found
11868 +   ) {
11869 +       CK_SLOT_ID_PTR slots = NULL;
11870 +       CK_ULONG slotnum;
11871 +       CK_SLOT_ID slot_index;
11872 +
11873 +       if (!current_provider->enabled) {
11874 +           rv = CKR_CRYPTOKI_NOT_INITIALIZED;
11875 +       }
11876 +
11877 +       if (rv == CKR_OK) {
11878 +           rv = _pkcs11h_session_getSlotList (
11879 +               current_provider,
11880 +               CK_TRUE,
11881 +               &slots,
11882 +               &slotnum
11883 +           );
11884 +       }
11885 +
11886 +       for (
11887 +           slot_index=0;
11888 +           (
11889 +               slot_index < slotnum &&
11890 +               rv == CKR_OK &&
11891 +               !found
11892 +           );
11893 +           slot_index++
11894 +       ) {
11895 +           CK_TOKEN_INFO info;
11896 +
11897 +           if (rv == CKR_OK) {
11898 +               rv = current_provider->f->C_GetTokenInfo (
11899 +                   slots[slot_index],
11900 +                   &info
11901 +               );
11902 +           }
11903 +
11904 +           if (rv == CKR_OK) {
11905 +               char current_label[sizeof (info.label)+1];
11906 +       
11907 +               _pkcs11h_util_fixupFixedString (
11908 +                   current_label,
11909 +                   (char *)info.label,
11910 +                   sizeof (info.label)
11911 +               );
11912 +
11913 +               if (!strcmp (current_label, label)) {
11914 +                   found = TRUE;
11915 +                   selected_slot = slots[slot_index];
11916 +               }
11917 +           }
11918 +
11919 +           if (rv != CKR_OK) {
11920 +               PKCS11H_DEBUG (
11921 +                   PKCS11H_LOG_DEBUG1,
11922 +                   "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%ld-'%s'",
11923 +                   current_provider->manufacturerID,
11924 +                   slots[slot_index],
11925 +                   rv,
11926 +                   pkcs11h_getMessage (rv)
11927 +               );
11928 +
11929 +               /*
11930 +                * Ignore error
11931 +                */
11932 +               rv = CKR_OK;
11933 +           }
11934 +       }
11935 +
11936 +       if (rv != CKR_OK) {
11937 +           PKCS11H_DEBUG (
11938 +               PKCS11H_LOG_DEBUG1,
11939 +               "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
11940 +               current_provider->manufacturerID,
11941 +               rv,
11942 +               pkcs11h_getMessage (rv)
11943 +           );
11944 +
11945 +           /*
11946 +            * Ignore error
11947 +            */
11948 +           rv = CKR_OK;
11949 +       }
11950 +
11951 +       if (slots != NULL) {
11952 +           _pkcs11h_mem_free ((void *)&slots);
11953 +           slots = NULL;
11954 +       }
11955 +
11956 +       if (!found) {
11957 +           current_provider = current_provider->next;
11958 +       }
11959 +   }
11960 +
11961 +   if (rv == CKR_OK && !found) {
11962 +       rv = CKR_SLOT_ID_INVALID;
11963 +   }
11964 +
11965 +   if (
11966 +       rv == CKR_OK &&
11967 +       (rv = current_provider->f->C_GetTokenInfo (selected_slot, &info)) == CKR_OK
11968 +   ) {
11969 +       rv = _pkcs11h_token_getTokenId (
11970 +           &info,
11971 +           p_token_id
11972 +       );
11973 +   }
11974 +
11975 +   PKCS11H_DEBUG (
11976 +       PKCS11H_LOG_DEBUG2,
11977 +       "PKCS#11: _pkcs11h_locate_getTokenIdByLabel return rv=%ld-'%s', *p_token_id=%p",
11978 +       rv,
11979 +       pkcs11h_getMessage (rv),
11980 +       (void *)*p_token_id
11981 +   );
11982 +
11983 +   return rv;
11984 +}
11985 +
11986 +CK_RV
11987 +pkcs11h_locate_token (
11988 +   IN const char * const slot_type,
11989 +   IN const char * const slot,
11990 +   IN void * const user_data,
11991 +   IN const unsigned mask_prompt,
11992 +   OUT pkcs11h_token_id_t * const p_token_id
11993 +) {
11994 +#if defined(ENABLE_PKCS11H_THREADING)
11995 +   PKCS11H_BOOL mutex_locked = FALSE;
11996 +#endif
11997 +
11998 +   pkcs11h_token_id_t dummy_token_id = NULL;
11999 +   pkcs11h_token_id_t token_id = NULL;
12000 +   PKCS11H_BOOL found = FALSE;
12001 +   
12002 +   CK_RV rv = CKR_OK;
12003 +
12004 +   unsigned nRetry = 0;
12005 +
12006 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
12007 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
12008 +   PKCS11H_ASSERT (slot_type!=NULL);
12009 +   PKCS11H_ASSERT (slot!=NULL);
12010 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
12011 +   PKCS11H_ASSERT (p_token_id!=NULL);
12012 +
12013 +   PKCS11H_DEBUG (
12014 +       PKCS11H_LOG_DEBUG2,
12015 +       "PKCS#11: pkcs11h_locate_token entry slot_type='%s', slot='%s', user_data=%p, p_token_id=%p",
12016 +       slot_type,
12017 +       slot,
12018 +       user_data,
12019 +       (void *)p_token_id
12020 +   );
12021 +
12022 +   *p_token_id = NULL;
12023 +
12024 +#if defined(ENABLE_PKCS11H_THREADING)
12025 +   if (
12026 +       rv == CKR_OK &&
12027 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global)) == CKR_OK
12028 +   ) {
12029 +       mutex_locked = TRUE;
12030 +   }
12031 +#endif
12032 +
12033 +   if (
12034 +       rv == CKR_OK &&
12035 +       (rv = _pkcs11h_token_newTokenId (&dummy_token_id)) == CKR_OK
12036 +   ) {
12037 +       /*
12038 +        * Temperary slot id
12039 +        */
12040 +       strcpy (dummy_token_id->display, "SLOT(");
12041 +       strncat (dummy_token_id->display, slot_type, sizeof (dummy_token_id->display)-1-strlen
	(dummy_token_id->display));
12042 +       strncat (dummy_token_id->display, "=", sizeof (dummy_token_id->display)-1-strlen (dummy_token_id->display));
12043 +       strncat (dummy_token_id->display, slot, sizeof (dummy_token_id->display)-1-strlen (dummy_token_id->display));
12044 +       strncat (dummy_token_id->display, ")", sizeof (dummy_token_id->display)-1-strlen (dummy_token_id->display));
12045 +       dummy_token_id->display[sizeof (dummy_token_id->display)-1] = 0;
12046 +   }
12047 +
12048 +   while (rv == CKR_OK && !found) {
12049 +       if (!strcmp (slot_type, "id")) {
12050 +           rv = _pkcs11h_locate_getTokenIdBySlotId (
12051 +               slot,
12052 +               &token_id
12053 +           );
12054 +       }
12055 +       else if (!strcmp (slot_type, "name")) {
12056 +           rv = _pkcs11h_locate_getTokenIdBySlotName (
12057 +               slot,
12058 +               &token_id
12059 +           );
12060 +       }
12061 +       else if (!strcmp (slot_type, "label")) {
12062 +           rv = _pkcs11h_locate_getTokenIdByLabel (
12063 +               slot,
12064 +               &token_id
12065 +           );
12066 +       }
12067 +       else {
12068 +           rv = CKR_ARGUMENTS_BAD;
12069 +       }
12070 +
12071 +       if (rv == CKR_OK) {
12072 +           found = TRUE;
12073 +       }
12074 +
12075 +       /*
12076 +        * Ignore error, since we have what we
12077 +        * want in found.
12078 +        */
12079 +       if (rv != CKR_OK && rv != CKR_ARGUMENTS_BAD) {
12080 +           PKCS11H_DEBUG (
12081 +               PKCS11H_LOG_DEBUG1,
12082 +               "PKCS#11: pkcs11h_locate_token failed rv=%ld-'%s'",
12083 +               rv,
12084 +               pkcs11h_getMessage (rv)
12085 +           );
12086 +
12087 +           rv = CKR_OK;
12088 +       }
12089 +
12090 +       if (rv == CKR_OK && !found && (mask_prompt & PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT) == 0) {
12091 +           rv = CKR_TOKEN_NOT_PRESENT;
12092 +       }
12093 +
12094 +       if (rv == CKR_OK && !found) {
12095 +
12096 +           PKCS11H_DEBUG (
12097 +               PKCS11H_LOG_DEBUG1,
12098 +               "PKCS#11: Calling token_prompt hook for '%s'",
12099 +               dummy_token_id->display
12100 +           );
12101 +   
12102 +           if (
12103 +               !s_pkcs11h_data->hooks.token_prompt (
12104 +                   s_pkcs11h_data->hooks.token_prompt_data,
12105 +                   user_data,
12106 +                   dummy_token_id,
12107 +                   nRetry++
12108 +               )
12109 +           ) {
12110 +               rv = CKR_CANCEL;
12111 +           }
12112 +
12113 +           PKCS11H_DEBUG (
12114 +               PKCS11H_LOG_DEBUG1,
12115 +               "PKCS#11: token_prompt returned %ld",
12116 +               rv
12117 +           );
12118 +       }
12119 +   }
12120 +
12121 +   if (rv == CKR_OK && !found) {
12122 +       rv = CKR_SLOT_ID_INVALID;
12123 +   }
12124 +
12125 +   if (rv == CKR_OK) {
12126 +       *p_token_id = token_id;
12127 +       token_id = NULL;
12128 +   }
12129 +
12130 +   if (dummy_token_id != NULL) {
12131 +       pkcs11h_token_freeTokenId (dummy_token_id);
12132 +       dummy_token_id = NULL;
12133 +   }
12134 +
12135 +#if defined(ENABLE_PKCS11H_THREADING)
12136 +   if (mutex_locked) {
12137 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
12138 +       mutex_locked = FALSE;
12139 +   }
12140 +#endif
12141 +
12142 +   PKCS11H_DEBUG (
12143 +       PKCS11H_LOG_DEBUG2,
12144 +       "PKCS#11: pkcs11h_locate_token return rv=%ld-'%s', *p_token_id=%p",
12145 +       rv,
12146 +       pkcs11h_getMessage (rv),
12147 +       (void *)*p_token_id
12148 +   );
12149 +
12150 +   return rv;
12151 +}
12152 +
12153 +#endif             /* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
12154 +
12155 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
12156 +
12157 +static
12158 +CK_RV
12159 +_pkcs11h_locate_getCertificateIdByLabel (
12160 +   IN const pkcs11h_session_t session,
12161 +   IN OUT const pkcs11h_certificate_id_t certificate_id,
12162 +   IN const char * const label
12163 +) {
12164 +#if defined(ENABLE_PKCS11H_THREADING)
12165 +   PKCS11H_BOOL mutex_locked = FALSE;
12166 +#endif
12167 +   CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
12168 +   CK_ATTRIBUTE cert_filter[] = {
12169 +       {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)},
12170 +       {CKA_LABEL, (CK_BYTE_PTR)label, strlen (label)}
12171 +   };
12172 +
12173 +   CK_OBJECT_HANDLE *objects = NULL;
12174 +   CK_ULONG objects_found = 0;
12175 +   CK_RV rv = CKR_OK;
12176 +
12177 +   CK_ULONG i;
12178 +
12179 +   PKCS11H_ASSERT (session!=NULL);
12180 +   PKCS11H_ASSERT (certificate_id!=NULL);
12181 +   PKCS11H_ASSERT (label!=NULL);
12182 +
12183 +   PKCS11H_DEBUG (
12184 +       PKCS11H_LOG_DEBUG2,
12185 +       "PKCS#11: _pkcs11h_locate_getCertificateIdByLabel entry session=%p, certificate_id=%p, label='%s'",
12186 +       (void *)session,
12187 +       (void *)certificate_id,
12188 +       label
12189 +   );
12190 +
12191 +#if defined(ENABLE_PKCS11H_THREADING)
12192 +   if (
12193 +       rv == CKR_OK &&
12194 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
12195 +   ) {
12196 +       mutex_locked = TRUE;
12197 +   }
12198 +#endif
12199 +
12200 +   if (rv == CKR_OK) {
12201 +       rv = _pkcs11h_session_validate (session);
12202 +   }
12203 +
12204 +   if (rv == CKR_OK) {
12205 +       rv = _pkcs11h_session_findObjects (
12206 +           session,
12207 +           cert_filter,
12208 +           sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
12209 +           &objects,
12210 +           &objects_found
12211 +       );
12212 +   }
12213 +
12214 +   for (i=0;rv == CKR_OK && i < objects_found;i++) {
12215 +       CK_ATTRIBUTE attrs[] = {
12216 +           {CKA_ID, NULL, 0},
12217 +           {CKA_VALUE, NULL, 0}
12218 +       };
12219 +
12220 +       if (rv == CKR_OK) {
12221 +           rv = _pkcs11h_session_getObjectAttributes (
12222 +               session,
12223 +               objects[i],
12224 +               attrs,
12225 +               sizeof (attrs) / sizeof (CK_ATTRIBUTE)
12226 +           );
12227 +       }
12228 +
12229 +       if (
12230 +           rv == CKR_OK &&
12231 +           _pkcs11h_certificate_isBetterCertificate (
12232 +               certificate_id->certificate_blob,
12233 +               certificate_id->certificate_blob_size,
12234 +               attrs[1].pValue,
12235 +               attrs[1].ulValueLen
12236 +           )
12237 +       ) {
12238 +           if (certificate_id->attrCKA_ID != NULL) {
12239 +               _pkcs11h_mem_free ((void *)&certificate_id->attrCKA_ID);
12240 +           }
12241 +           if (certificate_id->certificate_blob != NULL) {
12242 +               _pkcs11h_mem_free ((void *)&certificate_id->certificate_blob);
12243 +           }
12244 +           rv = _pkcs11h_mem_duplicate (
12245 +               (void *)&certificate_id->attrCKA_ID,
12246 +               &certificate_id->attrCKA_ID_size,
12247 +               attrs[0].pValue,
12248 +               attrs[0].ulValueLen
12249 +           );
12250 +           rv = _pkcs11h_mem_duplicate (
12251 +               (void *)&certificate_id->certificate_blob,
12252 +               &certificate_id->certificate_blob_size,
12253 +               attrs[1].pValue,
12254 +               attrs[1].ulValueLen
12255 +           );
12256 +       }
12257 +
12258 +       if (rv != CKR_OK) {
12259 +           PKCS11H_DEBUG (
12260 +               PKCS11H_LOG_DEBUG1,
12261 +               "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
12262 +               session->provider->manufacturerID,
12263 +               objects[i],
12264 +               rv,
12265 +               pkcs11h_getMessage (rv)
12266 +           );
12267 +
12268 +           /*
12269 +            * Ignore error
12270 +            */
12271 +           rv = CKR_OK;
12272 +       }
12273 +
12274 +       _pkcs11h_session_freeObjectAttributes (
12275 +           attrs,
12276 +           sizeof (attrs) / sizeof (CK_ATTRIBUTE)
12277 +       );
12278 +   }
12279 +   
12280 +   if (
12281 +       rv == CKR_OK &&
12282 +       certificate_id->certificate_blob == NULL
12283 +   ) {
12284 +       rv = CKR_ATTRIBUTE_VALUE_INVALID;
12285 +   }
12286 +
12287 +   if (objects != NULL) {
12288 +       _pkcs11h_mem_free ((void *)&objects);
12289 +   }
12290 +
12291 +#if defined(ENABLE_PKCS11H_THREADING)
12292 +   if (mutex_locked) {
12293 +       _pkcs11h_threading_mutexRelease (&session->mutex);
12294 +       mutex_locked = FALSE;
12295 +   }
12296 +#endif
12297 +
12298 +   /*
12299 +    * No need to free allocated objects
12300 +    * on error, since the certificate_id
12301 +    * should be free by caller.
12302 +    */
12303 +
12304 +   PKCS11H_DEBUG (
12305 +       PKCS11H_LOG_DEBUG2,
12306 +       "PKCS#11: _pkcs11h_locate_getCertificateIdByLabel return rv=%ld-'%s'",
12307 +       rv,
12308 +       pkcs11h_getMessage (rv)
12309 +   );
12310 +
12311 +   return rv;
12312 +}
12313 +
12314 +static
12315 +CK_RV
12316 +_pkcs11h_locate_getCertificateIdBySubject (
12317 +   IN const pkcs11h_session_t session,
12318 +   IN OUT const pkcs11h_certificate_id_t certificate_id,
12319 +   IN const char * const subject
12320 +) {
12321 +#if defined(ENABLE_PKCS11H_THREADING)
12322 +   PKCS11H_BOOL mutex_locked = FALSE;
12323 +#endif
12324 +   CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
12325 +   CK_ATTRIBUTE cert_filter[] = {
12326 +       {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)}
12327 +   };
12328 +
12329 +   CK_OBJECT_HANDLE *objects = NULL;
12330 +   CK_ULONG objects_found = 0;
12331 +   CK_RV rv = CKR_OK;
12332 +
12333 +   CK_ULONG i;
12334 +
12335 +   PKCS11H_ASSERT (session!=NULL);
12336 +   PKCS11H_ASSERT (certificate_id!=NULL);
12337 +   PKCS11H_ASSERT (subject!=NULL);
12338 +
12339 +   PKCS11H_DEBUG (
12340 +       PKCS11H_LOG_DEBUG2,
12341 +       "PKCS#11: _pkcs11h_locate_getCertificateIdBySubject entry session=%p, certificate_id=%p, subject='%s'",
12342 +       (void *)session,
12343 +       (void *)certificate_id,
12344 +       subject
12345 +   );
12346 +
12347 +#if defined(ENABLE_PKCS11H_THREADING)
12348 +   if (
12349 +       rv == CKR_OK &&
12350 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
12351 +   ) {
12352 +       mutex_locked = TRUE;
12353 +   }
12354 +#endif
12355 +
12356 +   if (rv == CKR_OK) {
12357 +       rv = _pkcs11h_session_validate (session);
12358 +   }
12359 +
12360 +   if (rv == CKR_OK) {
12361 +       rv = _pkcs11h_session_findObjects (
12362 +           session,
12363 +           cert_filter,
12364 +           sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
12365 +           &objects,
12366 +           &objects_found
12367 +       );
12368 +   }
12369 +
12370 +#if defined(ENABLE_PKCS11H_THREADING)
12371 +   if (mutex_locked) {
12372 +       _pkcs11h_threading_mutexRelease (&session->mutex);
12373 +       mutex_locked = FALSE;
12374 +   }
12375 +#endif
12376 +
12377 +   for (i=0;rv == CKR_OK && i < objects_found;i++) {
12378 +       CK_ATTRIBUTE attrs[] = {
12379 +           {CKA_ID, NULL, 0},
12380 +           {CKA_VALUE, NULL, 0}
12381 +       };
12382 +       char current_subject[1024];
12383 +       current_subject[0] = '\0';
12384 +
12385 +       if (rv == CKR_OK) {
12386 +           rv = _pkcs11h_session_getObjectAttributes (
12387 +               session,
12388 +               objects[i],
12389 +               attrs,
12390 +               sizeof (attrs) / sizeof (CK_ATTRIBUTE)
12391 +           );
12392 +       }
12393 +
12394 +       if (rv == CKR_OK) {
12395 +           rv = _pkcs11h_certificate_getDN (
12396 +               attrs[1].pValue,
12397 +               attrs[1].ulValueLen,
12398 +               current_subject,
12399 +               sizeof (current_subject)
12400 +           );
12401 +       }
12402 +
12403 +       if (
12404 +           rv == CKR_OK &&
12405 +           !strcmp (subject, current_subject) &&
12406 +           _pkcs11h_certificate_isBetterCertificate (
12407 +               certificate_id->certificate_blob,
12408 +               certificate_id->certificate_blob_size,
12409 +               attrs[1].pValue,
12410 +               attrs[1].ulValueLen
12411 +           )
12412 +       ) {
12413 +           if (certificate_id->attrCKA_ID != NULL) {
12414 +               _pkcs11h_mem_free ((void *)&certificate_id->attrCKA_ID);
12415 +           }
12416 +           if (certificate_id->certificate_blob != NULL) {
12417 +               _pkcs11h_mem_free ((void *)&certificate_id->certificate_blob);
12418 +           }
12419 +           rv = _pkcs11h_mem_duplicate (
12420 +               (void *)&certificate_id->attrCKA_ID,
12421 +               &certificate_id->attrCKA_ID_size,
12422 +               attrs[0].pValue,
12423 +               attrs[0].ulValueLen
12424 +           );
12425 +           rv = _pkcs11h_mem_duplicate (
12426 +               (void *)&certificate_id->certificate_blob,
12427 +               &certificate_id->certificate_blob_size,
12428 +               attrs[1].pValue,
12429 +               attrs[1].ulValueLen
12430 +           );
12431 +       }
12432 +
12433 +       if (rv != CKR_OK) {
12434 +           PKCS11H_DEBUG (
12435 +               PKCS11H_LOG_DEBUG1,
12436 +               "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
12437 +               session->provider->manufacturerID,
12438 +               objects[i],
12439 +               rv,
12440 +               pkcs11h_getMessage (rv)
12441 +           );
12442 +
12443 +           /*
12444 +            * Ignore error
12445 +            */
12446 +           rv = CKR_OK;
12447 +       }
12448 +
12449 +       _pkcs11h_session_freeObjectAttributes (
12450 +           attrs,
12451 +           sizeof (attrs) / sizeof (CK_ATTRIBUTE)
12452 +       );
12453 +   }
12454 +   
12455 +   if (
12456 +       rv == CKR_OK &&
12457 +       certificate_id->certificate_blob == NULL
12458 +   ) {
12459 +       rv = CKR_ATTRIBUTE_VALUE_INVALID;
12460 +   }
12461 +
12462 +   if (objects != NULL) {
12463 +       _pkcs11h_mem_free ((void *)&objects);
12464 +   }
12465 +
12466 +   /*
12467 +    * No need to free allocated objects
12468 +    * on error, since the certificate_id
12469 +    * should be free by caller.
12470 +    */
12471 +
12472 +   PKCS11H_DEBUG (
12473 +       PKCS11H_LOG_DEBUG2,
12474 +       "PKCS#11: _pkcs11h_locate_getCertificateIdBySubject return rv=%ld-'%s'",
12475 +       rv,
12476 +       pkcs11h_getMessage (rv)
12477 +   );
12478 +
12479 +   return rv;
12480 +}
12481 +
12482 +CK_RV
12483 +pkcs11h_locate_certificate (
12484 +   IN const char * const slot_type,
12485 +   IN const char * const slot,
12486 +   IN const char * const id_type,
12487 +   IN const char * const id,
12488 +   IN void * const user_data,
12489 +   IN const unsigned mask_prompt,
12490 +   OUT pkcs11h_certificate_id_t * const p_certificate_id
12491 +) {
12492 +#if defined(ENABLE_PKCS11H_THREADING)
12493 +   PKCS11H_BOOL mutex_locked = FALSE;
12494 +#endif
12495 +   pkcs11h_certificate_id_t certificate_id = NULL;
12496 +   pkcs11h_session_t session = NULL;
12497 +   PKCS11H_BOOL op_succeed = FALSE;
12498 +   PKCS11H_BOOL login_retry = FALSE;
12499 +   
12500 +   CK_RV rv = CKR_OK;
12501 +
12502 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
12503 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
12504 +   PKCS11H_ASSERT (slot_type!=NULL);
12505 +   PKCS11H_ASSERT (slot!=NULL);
12506 +   PKCS11H_ASSERT (id_type!=NULL);
12507 +   PKCS11H_ASSERT (id!=NULL);
12508 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
12509 +   PKCS11H_ASSERT (p_certificate_id!=NULL);
12510 +
12511 +   PKCS11H_DEBUG (
12512 +       PKCS11H_LOG_DEBUG2,
12513 +       "PKCS#11: pkcs11h_locateCertificate entry slot_type='%s', slot='%s', id_type='%s', id='%s', user_data=%p,
	mask_prompt=%08x, p_certificate_id=%p",
12514 +       slot_type,
12515 +       slot,
12516 +       id_type,
12517 +       id,
12518 +       user_data,
12519 +       mask_prompt,
12520 +       (void *)p_certificate_id
12521 +   );
12522 +
12523 +   *p_certificate_id = NULL;
12524 +
12525 +   if (rv == CKR_OK) {
12526 +       rv = _pkcs11h_certificate_newCertificateId (&certificate_id);
12527 +   }
12528 +
12529 +   if (rv == CKR_OK) {
12530 +       rv = pkcs11h_locate_token (
12531 +           slot_type,
12532 +           slot,
12533 +           user_data,
12534 +           mask_prompt,
12535 +           &certificate_id->token_id
12536 +       );
12537 +   }
12538 +
12539 +   if (rv == CKR_OK) {
12540 +       rv = _pkcs11h_session_getSessionByTokenId (
12541 +           certificate_id->token_id,
12542 +           &session
12543 +       );
12544 +   }
12545 +
12546 +#if defined(ENABLE_PKCS11H_THREADING)
12547 +   if (
12548 +       rv == CKR_OK &&
12549 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global)) == CKR_OK
12550 +   ) {
12551 +       mutex_locked = TRUE;
12552 +   }
12553 +#endif
12554 +
12555 +   while (rv == CKR_OK && !op_succeed) {
12556 +       if (!strcmp (id_type, "id")) {
12557 +           certificate_id->attrCKA_ID_size = strlen (id)/2;
12558 +
12559 +           if (certificate_id->attrCKA_ID_size == 0) {
12560 +               rv = CKR_FUNCTION_FAILED;
12561 +           }
12562 +
12563 +           if (
12564 +               rv == CKR_OK &&
12565 +               (rv = _pkcs11h_mem_malloc (
12566 +                   (void*)&certificate_id->attrCKA_ID,
12567 +                   certificate_id->attrCKA_ID_size
12568 +               )) == CKR_OK
12569 +           ) {
12570 +               _pkcs11h_util_hexToBinary (
12571 +                   certificate_id->attrCKA_ID,
12572 +                   id,
12573 +                   &certificate_id->attrCKA_ID_size
12574 +               );
12575 +           }
12576 +       }
12577 +       else if (!strcmp (id_type, "label")) {
12578 +           rv = _pkcs11h_locate_getCertificateIdByLabel (
12579 +               session,
12580 +               certificate_id,
12581 +               id
12582 +           );
12583 +       }
12584 +       else if (!strcmp (id_type, "subject")) {
12585 +           rv = _pkcs11h_locate_getCertificateIdBySubject (
12586 +               session,
12587 +               certificate_id,
12588 +               id
12589 +           );
12590 +       }
12591 +       else {
12592 +           rv = CKR_ARGUMENTS_BAD;
12593 +       }
12594 +
12595 +       if (rv == CKR_OK) {
12596 +           op_succeed = TRUE;
12597 +       }
12598 +       else {
12599 +           if (!login_retry) {
12600 +               PKCS11H_DEBUG (
12601 +                   PKCS11H_LOG_DEBUG1,
12602 +                   "PKCS#11: Get certificate failed: %ld:'%s'",
12603 +                   rv,
12604 +                   pkcs11h_getMessage (rv)
12605 +               );
12606 +
12607 +               rv = _pkcs11h_session_login (
12608 +                   session,
12609 +                   TRUE,
12610 +                   TRUE,
12611 +                   user_data,
12612 +                   mask_prompt
12613 +               );
12614 +
12615 +               login_retry = TRUE;
12616 +           }
12617 +       }
12618 +   }
12619 +
12620 +#if defined(ENABLE_PKCS11H_THREADING)
12621 +   if (mutex_locked) {
12622 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
12623 +       mutex_locked = FALSE;
12624 +   }
12625 +#endif
12626 +
12627 +   if (rv == CKR_OK) {
12628 +       *p_certificate_id = certificate_id;
12629 +       certificate_id = NULL;
12630 +   }
12631 +
12632 +   if (certificate_id != NULL) {
12633 +       pkcs11h_certificate_freeCertificateId (certificate_id);
12634 +       certificate_id = NULL;
12635 +   }
12636 +
12637 +   if (session != NULL) {
12638 +       _pkcs11h_session_release (session);
12639 +       session = NULL;
12640 +   }
12641 +
12642 +   PKCS11H_DEBUG (
12643 +       PKCS11H_LOG_DEBUG2,
12644 +       "PKCS#11: pkcs11h_locateCertificate return rv=%ld-'%s' *p_certificate_id=%p",
12645 +       rv,
12646 +       pkcs11h_getMessage (rv),
12647 +       (void *)*p_certificate_id
12648 +   );
12649 +   
12650 +   return rv;
12651 +}
12652 +
12653 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
12654 +
12655 +#endif             /* ENABLE_PKCS11H_LOCATE */
12656 +
12657 +#if defined(ENABLE_PKCS11H_ENUM)
12658 +/*======================================================================*
12659 + * ENUM INTERFACE
12660 + *======================================================================*/
12661 +
12662 +#if defined(ENABLE_PKCS11H_TOKEN)
12663 +
12664 +CK_RV
12665 +pkcs11h_token_freeTokenIdList (
12666 +   IN const pkcs11h_token_id_list_t token_id_list
12667 +) {
12668 +   pkcs11h_token_id_list_t _id = token_id_list;
12669 +
12670 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
12671 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
12672 +   /*PKCS11H_ASSERT (token_id_list!=NULL); NOT NEEDED*/
12673 +
12674 +   PKCS11H_DEBUG (
12675 +       PKCS11H_LOG_DEBUG2,
12676 +       "PKCS#11: pkcs11h_token_freeTokenIdList entry token_id_list=%p",
12677 +       (void *)token_id_list
12678 +   );
12679 +
12680 +   while (_id != NULL) {
12681 +       pkcs11h_token_id_list_t x = _id;
12682 +       _id = _id->next;
12683 +       if (x->token_id != NULL) {
12684 +           pkcs11h_token_freeTokenId (x->token_id);
12685 +       }
12686 +       x->next = NULL;
12687 +       _pkcs11h_mem_free ((void *)&x);
12688 +   }
12689 +
12690 +   PKCS11H_DEBUG (
12691 +       PKCS11H_LOG_DEBUG2,
12692 +       "PKCS#11: pkcs11h_token_freeTokenIdList return"
12693 +   );
12694 +
12695 +   return CKR_OK;
12696 +}
12697 +
12698 +CK_RV
12699 +pkcs11h_token_enumTokenIds (
12700 +   IN const int method,
12701 +   OUT pkcs11h_token_id_list_t * const p_token_id_list
12702 +) {
12703 +#if defined(ENABLE_PKCS11H_THREADING)
12704 +   PKCS11H_BOOL mutex_locked = FALSE;
12705 +#endif
12706 +
12707 +   pkcs11h_token_id_list_t token_id_list = NULL;
12708 +   pkcs11h_provider_t current_provider;
12709 +   CK_RV rv = CKR_OK;
12710 +
12711 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
12712 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
12713 +   PKCS11H_ASSERT (p_token_id_list!=NULL);
12714 +
12715 +   PKCS11H_DEBUG (
12716 +       PKCS11H_LOG_DEBUG2,
12717 +       "PKCS#11: pkcs11h_token_enumTokenIds entry p_token_id_list=%p",
12718 +       (void *)p_token_id_list
12719 +   );
12720 +
12721 +   *p_token_id_list = NULL;
12722 +
12723 +#if defined(ENABLE_PKCS11H_THREADING)
12724 +   if (
12725 +       rv == CKR_OK &&
12726 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.global)) == CKR_OK
12727 +   ) {
12728 +       mutex_locked = TRUE;
12729 +   }
12730 +#endif
12731 +
12732 +   for (
12733 +       current_provider = s_pkcs11h_data->providers;
12734 +       (
12735 +           current_provider != NULL &&
12736 +           rv == CKR_OK
12737 +       );
12738 +       current_provider = current_provider->next
12739 +   ) {
12740 +       CK_SLOT_ID_PTR slots = NULL;
12741 +       CK_ULONG slotnum;
12742 +       CK_SLOT_ID slot_index;
12743 +
12744 +       if (!current_provider->enabled) {
12745 +           rv = CKR_CRYPTOKI_NOT_INITIALIZED;
12746 +       }
12747 +
12748 +       if (rv == CKR_OK) {
12749 +           rv = _pkcs11h_session_getSlotList (
12750 +               current_provider,
12751 +               CK_TRUE,
12752 +               &slots,
12753 +               &slotnum
12754 +           );
12755 +       }
12756 +
12757 +       for (
12758 +           slot_index=0;
12759 +           (
12760 +               slot_index < slotnum &&
12761 +               rv == CKR_OK
12762 +           );
12763 +           slot_index++
12764 +       ) {
12765 +           pkcs11h_token_id_list_t entry = NULL;
12766 +           CK_TOKEN_INFO info;
12767 +
12768 +           if (rv == CKR_OK) {
12769 +               rv = _pkcs11h_mem_malloc ((void *)&entry, sizeof (struct pkcs11h_token_id_list_s));
12770 +           }
12771 +
12772 +           if (rv == CKR_OK) {
12773 +               rv = current_provider->f->C_GetTokenInfo (
12774 +                   slots[slot_index],
12775 +                   &info
12776 +               );
12777 +           }
12778 +
12779 +           if (rv == CKR_OK) {
12780 +               rv = _pkcs11h_token_getTokenId (
12781 +                   &info,
12782 +                   &entry->token_id
12783 +               );
12784 +           }
12785 +
12786 +           if (rv == CKR_OK) {
12787 +               entry->next = token_id_list;
12788 +               token_id_list = entry;
12789 +               entry = NULL;
12790 +           }
12791 +
12792 +           if (entry != NULL) {
12793 +               pkcs11h_token_freeTokenIdList (entry);
12794 +               entry = NULL;
12795 +           }
12796 +       }
12797 +
12798 +       if (rv != CKR_OK) {
12799 +           PKCS11H_DEBUG (
12800 +               PKCS11H_LOG_DEBUG1,
12801 +               "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
12802 +               current_provider->manufacturerID,
12803 +               rv,
12804 +               pkcs11h_getMessage (rv)
12805 +           );
12806 +
12807 +           /*
12808 +            * Ignore error
12809 +            */
12810 +           rv = CKR_OK;
12811 +       }
12812 +
12813 +       if (slots != NULL) {
12814 +           _pkcs11h_mem_free ((void *)&slots);
12815 +           slots = NULL;
12816 +       }
12817 +   }
12818 +
12819 +   if (rv == CKR_OK && method == PKCS11H_ENUM_METHOD_CACHE) {
12820 +       pkcs11h_session_t session = NULL;
12821 +
12822 +       for (
12823 +           session = s_pkcs11h_data->sessions;
12824 +           session != NULL && rv == CKR_OK;
12825 +           session = session->next
12826 +       ) {
12827 +           pkcs11h_token_id_list_t entry = NULL;
12828 +           PKCS11H_BOOL found = FALSE;
12829 +
12830 +           for (
12831 +               entry = token_id_list;
12832 +               entry != NULL && !found;
12833 +               entry = entry->next
12834 +           ) {
12835 +               if (
12836 +                   pkcs11h_token_sameTokenId (
12837 +                       session->token_id,
12838 +                       entry->token_id
12839 +                   )
12840 +               ) {
12841 +                   found = TRUE;
12842 +               }
12843 +           }
12844 +
12845 +           if (!found) {
12846 +               entry = NULL;
12847 +
12848 +               if (rv == CKR_OK) {
12849 +                   rv = _pkcs11h_mem_malloc (
12850 +                       (void *)&entry,
12851 +                       sizeof (struct pkcs11h_token_id_list_s)
12852 +                   );
12853 +               }
12854 +
12855 +               if (rv == CKR_OK) {
12856 +                   rv = pkcs11h_token_duplicateTokenId (
12857 +                       &entry->token_id,
12858 +                       session->token_id
12859 +                   );
12860 +               }
12861 +
12862 +               if (rv == CKR_OK) {
12863 +                   entry->next = token_id_list;
12864 +                   token_id_list = entry;
12865 +                   entry = NULL;
12866 +               }
12867 +
12868 +               if (entry != NULL) {
12869 +                   if (entry->token_id != NULL) {
12870 +                       pkcs11h_token_freeTokenId (entry->token_id);
12871 +                   }
12872 +                   _pkcs11h_mem_free ((void *)&entry);
12873 +               }
12874 +           }
12875 +       }
12876 +   }
12877 +
12878 +   if (rv == CKR_OK) {
12879 +       *p_token_id_list = token_id_list;
12880 +       token_id_list = NULL;
12881 +   }
12882 +
12883 +   if (token_id_list != NULL) {
12884 +       pkcs11h_token_freeTokenIdList (token_id_list);
12885 +       token_id_list = NULL;
12886 +   }
12887 +
12888 +#if defined(ENABLE_PKCS11H_THREADING)
12889 +   if (mutex_locked) {
12890 +       rv = _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.global);
12891 +       mutex_locked = FALSE;
12892 +   }
12893 +#endif
12894 +
12895 +   PKCS11H_DEBUG (
12896 +       PKCS11H_LOG_DEBUG2,
12897 +       "PKCS#11: pkcs11h_token_enumTokenIds return rv=%ld-'%s', *p_token_id_list=%p",
12898 +       rv,
12899 +       pkcs11h_getMessage (rv),
12900 +       (void *)p_token_id_list
12901 +   );
12902 +   
12903 +   return rv;
12904 +}
12905 +
12906 +#endif
12907 +
12908 +#if defined(ENABLE_PKCS11H_DATA)
12909 +
12910 +CK_RV
12911 +pkcs11h_data_freeDataIdList (
12912 +   IN const pkcs11h_data_id_list_t data_id_list
12913 +) {
12914 +   pkcs11h_data_id_list_t _id = data_id_list;
12915 +
12916 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
12917 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
12918 +   /*PKCS11H_ASSERT (data_id_list!=NULL); NOT NEEDED*/
12919 +
12920 +   PKCS11H_DEBUG (
12921 +       PKCS11H_LOG_DEBUG2,
12922 +       "PKCS#11: pkcs11h_freeDataIdList entry token_id_list=%p",
12923 +       (void *)data_id_list
12924 +   );
12925 +
12926 +   while (_id != NULL) {
12927 +       pkcs11h_data_id_list_t x = _id;
12928 +       _id = _id->next;
12929 +
12930 +       if (x->application != NULL) {
12931 +           _pkcs11h_mem_free ((void *)&x->application);
12932 +       }
12933 +       if (x->label != NULL) {
12934 +           _pkcs11h_mem_free ((void *)&x->label);
12935 +       }
12936 +       _pkcs11h_mem_free ((void *)&x);
12937 +   }
12938 +
12939 +   PKCS11H_DEBUG (
12940 +       PKCS11H_LOG_DEBUG2,
12941 +       "PKCS#11: pkcs11h_token_freeDataIdList return"
12942 +   );
12943 +
12944 +   return CKR_OK;
12945 +}
12946 +
12947 +CK_RV
12948 +pkcs11h_data_enumDataObjects (
12949 +   IN const pkcs11h_token_id_t token_id,
12950 +   IN const PKCS11H_BOOL is_public,
12951 +   IN void * const user_data,
12952 +   IN const unsigned mask_prompt,
12953 +   OUT pkcs11h_data_id_list_t * const p_data_id_list
12954 +) {
12955 +#if defined(ENABLE_PKCS11H_THREADING)
12956 +   PKCS11H_BOOL mutex_locked = FALSE;
12957 +#endif
12958 +   pkcs11h_session_t session = NULL;
12959 +   pkcs11h_data_id_list_t data_id_list = NULL;
12960 +   CK_RV rv = CKR_OK;
12961 +
12962 +   PKCS11H_BOOL op_succeed = FALSE;
12963 +   PKCS11H_BOOL login_retry = FALSE;
12964 +
12965 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
12966 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
12967 +   PKCS11H_ASSERT (p_data_id_list!=NULL);
12968 +
12969 +   PKCS11H_DEBUG (
12970 +       PKCS11H_LOG_DEBUG2,
12971 +       "PKCS#11: pkcs11h_data_enumDataObjects entry token_id=%p, is_public=%d, user_data=%p, mask_prompt=%08x,
	p_data_id_list=%p",
12972 +       (void *)token_id,
12973 +       is_public ? 1 : 0,
12974 +       user_data,
12975 +       mask_prompt,
12976 +       (void *)p_data_id_list
12977 +   );
12978 +
12979 +   *p_data_id_list = NULL;
12980 +
12981 +   if (rv == CKR_OK) {
12982 +       rv = _pkcs11h_session_getSessionByTokenId (
12983 +           token_id,
12984 +           &session
12985 +       );
12986 +   }
12987 +
12988 +#if defined(ENABLE_PKCS11H_THREADING)
12989 +   if (
12990 +       rv == CKR_OK &&
12991 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
12992 +   ) {
12993 +       mutex_locked = TRUE;
12994 +   }
12995 +#endif
12996 +
12997 +   while (rv == CKR_OK && !op_succeed) {
12998 +
12999 +       CK_OBJECT_CLASS class = CKO_DATA;
13000 +       CK_ATTRIBUTE filter[] = {
13001 +           {CKA_CLASS, (void *)&class, sizeof (class)}
13002 +       };
13003 +       CK_OBJECT_HANDLE *objects = NULL;
13004 +       CK_ULONG objects_found = 0;
13005 +
13006 +       CK_ULONG i;
13007 +
13008 +       if (rv == CKR_OK) {
13009 +           rv = _pkcs11h_session_validate (session);
13010 +       }
13011 +
13012 +       if (rv == CKR_OK) {
13013 +           rv = _pkcs11h_session_findObjects (
13014 +               session,
13015 +               filter,
13016 +               sizeof (filter) / sizeof (CK_ATTRIBUTE),
13017 +               &objects,
13018 +               &objects_found
13019 +           );
13020 +       }
13021 +
13022 +       for (i = 0;rv == CKR_OK && i < objects_found;i++) {
13023 +           pkcs11h_data_id_list_t entry = NULL;
13024 +
13025 +           CK_ATTRIBUTE attrs[] = {
13026 +               {CKA_APPLICATION, NULL, 0},
13027 +               {CKA_LABEL, NULL, 0}
13028 +           };
13029 +
13030 +           if (rv == CKR_OK) {
13031 +               rv = _pkcs11h_session_getObjectAttributes (
13032 +                   session,
13033 +                   objects[i],
13034 +                   attrs,
13035 +                   sizeof (attrs) / sizeof (CK_ATTRIBUTE)
13036 +               );
13037 +           }
13038 +           
13039 +           if (rv == CKR_OK) {
13040 +               rv = _pkcs11h_mem_malloc (
13041 +                   (void *)&entry,
13042 +                   sizeof (struct pkcs11h_data_id_list_s)
13043 +               );
13044 +           }
13045 +
13046 +           if (
13047 +               rv == CKR_OK &&
13048 +               (rv = _pkcs11h_mem_malloc (
13049 +                   (void *)&entry->application,
13050 +                   attrs[0].ulValueLen+1
13051 +               )) == CKR_OK
13052 +           ) {
13053 +               memmove (entry->application, attrs[0].pValue, attrs[0].ulValueLen);
13054 +               entry->application[attrs[0].ulValueLen] = '\0';
13055 +           }
13056 +
13057 +           if (
13058 +               rv == CKR_OK &&
13059 +               (rv = _pkcs11h_mem_malloc (
13060 +                   (void *)&entry->label,
13061 +                   attrs[1].ulValueLen+1
13062 +               )) == CKR_OK
13063 +           ) {
13064 +               memmove (entry->label, attrs[1].pValue, attrs[1].ulValueLen);
13065 +               entry->label[attrs[1].ulValueLen] = '\0';
13066 +           }
13067 +
13068 +           if (rv == CKR_OK) {
13069 +               entry->next = data_id_list;
13070 +               data_id_list = entry;
13071 +               entry = NULL;
13072 +           }
13073 +
13074 +           _pkcs11h_session_freeObjectAttributes (
13075 +               attrs,
13076 +               sizeof (attrs) / sizeof (CK_ATTRIBUTE)
13077 +           );
13078 +
13079 +           if (entry != NULL) {
13080 +               if (entry->application != NULL) {
13081 +                   _pkcs11h_mem_free ((void *)&entry->application);
13082 +               }
13083 +               if (entry->label != NULL) {
13084 +                   _pkcs11h_mem_free ((void *)&entry->label);
13085 +               }
13086 +               _pkcs11h_mem_free ((void *)&entry);
13087 +           }
13088 +       }
13089 +
13090 +       if (objects != NULL) {
13091 +           _pkcs11h_mem_free ((void *)&objects);
13092 +       }
13093 +
13094 +       if (rv == CKR_OK) {
13095 +           op_succeed = TRUE;
13096 +       }
13097 +       else {
13098 +           if (!login_retry) {
13099 +               PKCS11H_DEBUG (
13100 +                   PKCS11H_LOG_DEBUG1,
13101 +                   "PKCS#11: Enumerate data objects failed rv=%ld-'%s'",
13102 +                   rv,
13103 +                   pkcs11h_getMessage (rv)
13104 +               );
13105 +               login_retry = TRUE;
13106 +               rv = _pkcs11h_session_login (
13107 +                   session,
13108 +                   is_public,
13109 +                   TRUE,
13110 +                   user_data,
13111 +                   mask_prompt
13112 +               );
13113 +           }
13114 +       }
13115 +   }
13116 +
13117 +#if defined(ENABLE_PKCS11H_THREADING)
13118 +   if (mutex_locked) {
13119 +       _pkcs11h_threading_mutexRelease (&session->mutex);
13120 +       mutex_locked = FALSE;
13121 +   }
13122 +#endif
13123 +
13124 +   if (rv == CKR_OK) {
13125 +       *p_data_id_list = data_id_list;
13126 +       data_id_list = NULL;
13127 +   }
13128 +
13129 +   if (session != NULL) {
13130 +       _pkcs11h_session_release (session);
13131 +       session = NULL;
13132 +   }
13133 +
13134 +   if (data_id_list != NULL) {
13135 +       pkcs11h_data_freeDataIdList (data_id_list);
13136 +       data_id_list = NULL;
13137 +   }
13138 +
13139 +   PKCS11H_DEBUG (
13140 +       PKCS11H_LOG_DEBUG2,
13141 +       "PKCS#11: pkcs11h_data_enumDataObjects return rv=%ld-'%s', *p_data_id_list=%p",
13142 +       rv,
13143 +       pkcs11h_getMessage (rv),
13144 +       (void *)*p_data_id_list
13145 +   );
13146 +   
13147 +   return rv;
13148 +}
13149 +
13150 +#endif             /* ENABLE_PKCS11H_DATA */
13151 +
13152 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
13153 +
13154 +static
13155 +CK_RV
13156 +_pkcs11h_certificate_enumSessionCertificates (
13157 +   IN const pkcs11h_session_t session,
13158 +   IN void * const user_data,
13159 +   IN const unsigned mask_prompt
13160 +) {
13161 +#if defined(ENABLE_PKCS11H_THREADING)
13162 +   PKCS11H_BOOL mutex_locked = FALSE;
13163 +#endif
13164 +   PKCS11H_BOOL op_succeed = FALSE;
13165 +   PKCS11H_BOOL login_retry = FALSE;
13166 +
13167 +   CK_RV rv = CKR_OK;
13168 +
13169 +   PKCS11H_ASSERT (session!=NULL);
13170 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
13171 +
13172 +   PKCS11H_DEBUG (
13173 +       PKCS11H_LOG_DEBUG2,
13174 +       "PKCS#11: _pkcs11h_certificate_enumSessionCertificates entry session=%p, user_data=%p, mask_prompt=%08x",
13175 +       (void *)session,
13176 +       user_data,
13177 +       mask_prompt
13178 +   );
13179 +   
13180 +   /* THREADS: NO NEED TO LOCK, GLOBAL CACHE IS LOCKED */
13181 +#if defined(ENABLE_PKCS11H_THREADING)
13182 +   if (
13183 +       rv == CKR_OK &&
13184 +       (rv = _pkcs11h_threading_mutexLock (&session->mutex)) == CKR_OK
13185 +   ) {
13186 +       mutex_locked = TRUE;
13187 +   }
13188 +#endif
13189 +
13190 +   while (rv == CKR_OK && !op_succeed) {
13191 +       CK_OBJECT_CLASS cert_filter_class = CKO_CERTIFICATE;
13192 +       CK_ATTRIBUTE cert_filter[] = {
13193 +           {CKA_CLASS, &cert_filter_class, sizeof (cert_filter_class)}
13194 +       };
13195 +
13196 +       CK_OBJECT_HANDLE *objects = NULL;
13197 +       CK_ULONG objects_found = 0;
13198 +
13199 +       CK_ULONG i;
13200 +
13201 +       if (rv == CKR_OK) {
13202 +           rv = _pkcs11h_session_validate (session);
13203 +       }
13204 +
13205 +       if (rv == CKR_OK) {
13206 +           rv = _pkcs11h_session_findObjects (
13207 +               session,
13208 +               cert_filter,
13209 +               sizeof (cert_filter) / sizeof (CK_ATTRIBUTE),
13210 +               &objects,
13211 +               &objects_found
13212 +           );
13213 +       }
13214 +           
13215 +       for (i=0;rv == CKR_OK && i < objects_found;i++) {
13216 +           pkcs11h_certificate_id_t certificate_id = NULL;
13217 +           pkcs11h_certificate_id_list_t new_element = NULL;
13218 +           
13219 +           CK_ATTRIBUTE attrs[] = {
13220 +               {CKA_ID, NULL, 0},
13221 +               {CKA_VALUE, NULL, 0}
13222 +           };
13223 +
13224 +           if (rv == CKR_OK) {
13225 +               rv = _pkcs11h_session_getObjectAttributes (
13226 +                   session,
13227 +                   objects[i],
13228 +                   attrs,
13229 +                   sizeof (attrs) / sizeof (CK_ATTRIBUTE)
13230 +               );
13231 +           }
13232 +
13233 +           if (
13234 +               rv == CKR_OK &&
13235 +               (rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) == CKR_OK
13236 +           ) {
13237 +               rv = pkcs11h_token_duplicateTokenId (
13238 +                   &certificate_id->token_id,
13239 +                   session->token_id
13240 +               );
13241 +           }
13242 +
13243 +           if (rv == CKR_OK) {
13244 +               rv = _pkcs11h_mem_duplicate (
13245 +                   (void*)&certificate_id->attrCKA_ID,
13246 +                   &certificate_id->attrCKA_ID_size,
13247 +                   attrs[0].pValue,
13248 +                   attrs[0].ulValueLen
13249 +               );
13250 +           }
13251 +
13252 +           if (rv == CKR_OK) {
13253 +               rv = _pkcs11h_mem_duplicate (
13254 +                   (void*)&certificate_id->certificate_blob,
13255 +                   &certificate_id->certificate_blob_size,
13256 +                   attrs[1].pValue,
13257 +                   attrs[1].ulValueLen
13258 +               );
13259 +           }
13260 +
13261 +           if (rv == CKR_OK) {
13262 +               rv = _pkcs11h_certificate_updateCertificateIdDescription (certificate_id);
13263 +           }
13264 +
13265 +           if (
13266 +               rv == CKR_OK &&
13267 +               (rv = _pkcs11h_mem_malloc (
13268 +                   (void *)&new_element,
13269 +                   sizeof (struct pkcs11h_certificate_id_list_s)
13270 +               )) == CKR_OK
13271 +           ) {
13272 +               new_element->next = session->cached_certs;
13273 +               new_element->certificate_id = certificate_id;
13274 +               certificate_id = NULL;
13275 +
13276 +               session->cached_certs = new_element;
13277 +               new_element = NULL;
13278 +           }
13279 +
13280 +           if (certificate_id != NULL) {
13281 +               pkcs11h_certificate_freeCertificateId (certificate_id);
13282 +               certificate_id = NULL;
13283 +           }
13284 +
13285 +           if (new_element != NULL) {
13286 +               _pkcs11h_mem_free ((void *)&new_element);
13287 +               new_element = NULL;
13288 +           }
13289 +
13290 +           _pkcs11h_session_freeObjectAttributes (
13291 +               attrs,
13292 +               sizeof (attrs) / sizeof (CK_ATTRIBUTE)
13293 +           );
13294 +
13295 +           if (rv != CKR_OK) {
13296 +               PKCS11H_DEBUG (
13297 +                   PKCS11H_LOG_DEBUG1,
13298 +                   "PKCS#11: Cannot get object attribute for provider '%s' object %ld rv=%ld-'%s'",
13299 +                   session->provider->manufacturerID,
13300 +                   objects[i],
13301 +                   rv,
13302 +                   pkcs11h_getMessage (rv)
13303 +               );
13304 +
13305 +               /*
13306 +                * Ignore error
13307 +                */
13308 +               rv = CKR_OK;
13309 +           }
13310 +       }
13311 +
13312 +       if (objects != NULL) {
13313 +           _pkcs11h_mem_free ((void *)&objects);
13314 +       }
13315 +
13316 +       if (rv == CKR_OK) {
13317 +           op_succeed = TRUE;
13318 +       }
13319 +       else {
13320 +           if (!login_retry) {
13321 +               PKCS11H_DEBUG (
13322 +                   PKCS11H_LOG_DEBUG1,
13323 +                   "PKCS#11: Get certificate attributes failed: %ld:'%s'",
13324 +                   rv,
13325 +                   pkcs11h_getMessage (rv)
13326 +               );
13327 +
13328 +               rv = _pkcs11h_session_login (
13329 +                   session,
13330 +                   TRUE,
13331 +                   TRUE,
13332 +                   user_data,
13333 +                   (mask_prompt & PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT)
13334 +               );
13335 +
13336 +               login_retry = TRUE;
13337 +           }
13338 +       }
13339 +   }
13340 +
13341 +#if defined(ENABLE_PKCS11H_THREADING)
13342 +   if (mutex_locked) {
13343 +       _pkcs11h_threading_mutexRelease (&session->mutex);
13344 +       mutex_locked = FALSE;
13345 +   }
13346 +#endif
13347 +
13348 +   PKCS11H_DEBUG (
13349 +       PKCS11H_LOG_DEBUG2,
13350 +       "PKCS#11: _pkcs11h_certificate_enumSessionCertificates return rv=%ld-'%s'",
13351 +       rv,
13352 +       pkcs11h_getMessage (rv)
13353 +   );
13354 +
13355 +   return rv;
13356 +}
13357 +
13358 +static
13359 +CK_RV
13360 +_pkcs11h_certificate_splitCertificateIdList (
13361 +   IN const pkcs11h_certificate_id_list_t cert_id_all,
13362 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
13363 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
13364 +) {
13365 +   typedef struct info_s {
13366 +       struct info_s *next;
13367 +       pkcs11h_certificate_id_t e;
13368 +#if defined(USE_PKCS11H_OPENSSL)
13369 +       X509 *x509;
13370 +#elif defined(USE_PKCS11H_GNUTLS)
13371 +       gnutls_x509_crt_t cert;
13372 +#endif
13373 +       PKCS11H_BOOL is_issuer;
13374 +   } *info_t;
13375 +
13376 +   pkcs11h_certificate_id_list_t cert_id_issuers_list = NULL;
13377 +   pkcs11h_certificate_id_list_t cert_id_end_list = NULL;
13378 +
13379 +   info_t head = NULL;
13380 +   info_t info = NULL;
13381 +
13382 +   CK_RV rv = CKR_OK;
13383 +
13384 +   /*PKCS11H_ASSERT (cert_id_all!=NULL); NOT NEEDED */
13385 +   /*PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
13386 +   PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
13387 +
13388 +   PKCS11H_DEBUG (
13389 +       PKCS11H_LOG_DEBUG2,
13390 +       "PKCS#11: _pkcs11h_certificate_splitCertificateIdList entry cert_id_all=%p, p_cert_id_issuers_list=%p,
	p_cert_id_end_list=%p",
13391 +       (void *)cert_id_all,
13392 +       (void *)p_cert_id_issuers_list,
13393 +       (void *)p_cert_id_end_list
13394 +   );
13395 +
13396 +   if (p_cert_id_issuers_list != NULL) {
13397 +       *p_cert_id_issuers_list = NULL;
13398 +   }
13399 +   *p_cert_id_end_list = NULL;
13400 +
13401 +   if (rv == CKR_OK) {
13402 +       pkcs11h_certificate_id_list_t entry = NULL;
13403 +
13404 +       for (
13405 +           entry = cert_id_all;
13406 +           entry != NULL && rv == CKR_OK;
13407 +           entry = entry->next
13408 +       ) {
13409 +           info_t new_info = NULL;
13410 +
13411 +           if (
13412 +               rv == CKR_OK &&
13413 +               (rv = _pkcs11h_mem_malloc ((void *)&new_info, sizeof (struct info_s))) == CKR_OK &&
13414 +               entry->certificate_id->certificate_blob != NULL
13415 +           ) {
13416 +#if defined(USE_PKCS11H_OPENSSL)
13417 +               pkcs11_openssl_d2i_t d2i = (pkcs11_openssl_d2i_t)entry->certificate_id->certificate_blob;
13418 +#endif
13419 +
13420 +               new_info->next = head;
13421 +               new_info->e = entry->certificate_id;
13422 +#if defined(USE_PKCS11H_OPENSSL)
13423 +               new_info->x509 = X509_new ();
13424 +               if (
13425 +                   new_info->x509 != NULL &&
13426 +                   !d2i_X509 (
13427 +                       &new_info->x509,
13428 +                       &d2i,
13429 +                       entry->certificate_id->certificate_blob_size
13430 +                   )
13431 +               ) {
13432 +                   X509_free (new_info->x509);
13433 +                   new_info->x509 = NULL;
13434 +               }
13435 +#elif defined(USE_PKCS11H_GNUTLS)
13436 +               if (gnutls_x509_crt_init (&new_info->cert) != GNUTLS_E_SUCCESS) {
13437 +                   /* gnutls sets output */
13438 +                   new_info->cert = NULL;
13439 +               }
13440 +               else {
13441 +                   gnutls_datum_t datum = {
13442 +                       entry->certificate_id->certificate_blob,
13443 +                       entry->certificate_id->certificate_blob_size
13444 +                   };
13445 +
13446 +                   if (
13447 +                       gnutls_x509_crt_import (
13448 +                           new_info->cert,
13449 +                           &datum,
13450 +                           GNUTLS_X509_FMT_DER
13451 +                       ) != GNUTLS_E_SUCCESS
13452 +                   ) {
13453 +                       gnutls_x509_crt_deinit (new_info->cert);
13454 +                       new_info->cert = NULL;
13455 +                   }
13456 +               }
13457 +#else
13458 +#error Invalid configuration.
13459 +#endif
13460 +               head = new_info;
13461 +               new_info = NULL;
13462 +           }
13463 +       }
13464 +
13465 +   }
13466 +
13467 +   if (rv == CKR_OK) {
13468 +       for (
13469 +           info = head;
13470 +           info != NULL;
13471 +           info = info->next
13472 +       ) {
13473 +           info_t info2 = NULL;
13474 +#if defined(USE_PKCS11H_OPENSSL)
13475 +           EVP_PKEY *pub = X509_get_pubkey (info->x509);
13476 +#endif
13477 +
13478 +           for (
13479 +               info2 = head;
13480 +               info2 != NULL && !info->is_issuer;
13481 +               info2 = info2->next
13482 +           ) {
13483 +               if (info != info2) {
13484 +#if defined(USE_PKCS11H_OPENSSL)
13485 +                   if (
13486 +                       info->x509 != NULL &&
13487 +                       info2->x509 != NULL &&
13488 +                       !X509_NAME_cmp (
13489 +                           X509_get_subject_name (info->x509),
13490 +                           X509_get_issuer_name (info2->x509)
13491 +                       ) &&
13492 +                       X509_verify (info2->x509, pub) == 1
13493 +                   ) {
13494 +                       info->is_issuer = TRUE;
13495 +                   }
13496 +#elif defined(USE_PKCS11H_GNUTLS)
13497 +                   unsigned result;
13498 +
13499 +                   if (
13500 +                       info->cert != NULL &&
13501 +                       info2->cert != NULL &&
13502 +                       gnutls_x509_crt_verify (
13503 +                           info2->cert,
13504 +                           &info->cert,
13505 +                           1,
13506 +                           0,
13507 +                           &result
13508 +                       ) &&
13509 +                       (result & GNUTLS_CERT_INVALID) == 0
13510 +                   ) {
13511 +                       info->is_issuer = TRUE;
13512 +                   }
13513 +#else
13514 +#error Invalid configuration.
13515 +#endif
13516 +               }
13517 +
13518 +           }
13519 +
13520 +#if defined(USE_PKCS11H_OPENSSL)
13521 +           if (pub != NULL) {
13522 +               EVP_PKEY_free (pub);
13523 +               pub = NULL;
13524 +           }
13525 +#endif
13526 +       }
13527 +   }
13528 +
13529 +   if (rv == CKR_OK) {
13530 +       for (
13531 +           info = head;
13532 +           info != NULL && rv == CKR_OK;
13533 +           info = info->next
13534 +       ) {
13535 +           pkcs11h_certificate_id_list_t new_entry = NULL;
13536 +
13537 +           if (rv == CKR_OK) {
13538 +               rv = _pkcs11h_mem_malloc (
13539 +                   (void *)&new_entry,
13540 +                   sizeof (struct pkcs11h_certificate_id_list_s)
13541 +               );
13542 +           }
13543 +
13544 +           if (
13545 +               rv == CKR_OK &&
13546 +               (rv = pkcs11h_certificate_duplicateCertificateId (
13547 +                   &new_entry->certificate_id,
13548 +                   info->e
13549 +               )) == CKR_OK
13550 +           ) {
13551 +               /*
13552 +                * Should not free base list
13553 +                */
13554 +               info->e = NULL;
13555 +           }
13556 +
13557 +           if (rv == CKR_OK) {
13558 +               if (info->is_issuer) {
13559 +                   new_entry->next = cert_id_issuers_list;
13560 +                   cert_id_issuers_list = new_entry;
13561 +                   new_entry = NULL;
13562 +               }
13563 +               else {
13564 +                   new_entry->next = cert_id_end_list;
13565 +                   cert_id_end_list = new_entry;
13566 +                   new_entry = NULL;
13567 +               }
13568 +           }
13569 +
13570 +           if (new_entry != NULL) {
13571 +               if (new_entry->certificate_id != NULL) {
13572 +                   pkcs11h_certificate_freeCertificateId (new_entry->certificate_id);
13573 +               }
13574 +               _pkcs11h_mem_free ((void *)&new_entry);
13575 +           }
13576 +       }
13577 +   }
13578 +
13579 +   if (rv == CKR_OK) {
13580 +       while (head != NULL) {
13581 +           info_t entry = head;
13582 +           head = head->next;
13583 +
13584 +#if defined(USE_PKCS11H_OPENSSL)
13585 +           if (entry->x509 != NULL) {
13586 +               X509_free (entry->x509);
13587 +               entry->x509 = NULL;
13588 +           }
13589 +#elif defined(USE_PKCS11H_GNUTLS)
13590 +           if (entry->cert != NULL) {
13591 +               gnutls_x509_crt_deinit (entry->cert);
13592 +               entry->cert = NULL;
13593 +           }
13594 +#else
13595 +#error Invalid configuration.
13596 +#endif
13597 +
13598 +           _pkcs11h_mem_free ((void *)&entry);
13599 +       }
13600 +   }
13601 +
13602 +   if (rv == CKR_OK && p_cert_id_issuers_list != NULL ) {
13603 +       *p_cert_id_issuers_list = cert_id_issuers_list;
13604 +       cert_id_issuers_list = NULL;
13605 +   }
13606 +
13607 +   if (rv == CKR_OK) {
13608 +       *p_cert_id_end_list = cert_id_end_list;
13609 +       cert_id_end_list = NULL;
13610 +   }
13611 +
13612 +   if (cert_id_issuers_list != NULL) {
13613 +       pkcs11h_certificate_freeCertificateIdList (cert_id_issuers_list);
13614 +   }
13615 +
13616 +   if (cert_id_end_list != NULL) {
13617 +       pkcs11h_certificate_freeCertificateIdList (cert_id_end_list);
13618 +   }
13619 +
13620 +   PKCS11H_DEBUG (
13621 +       PKCS11H_LOG_DEBUG2,
13622 +       "PKCS#11: _pkcs11h_certificate_splitCertificateIdList return rv=%ld-'%s'",
13623 +       rv,
13624 +       pkcs11h_getMessage (rv)
13625 +   );
13626 +
13627 +   return rv;
13628 +}
13629 +
13630 +CK_RV
13631 +pkcs11h_certificate_freeCertificateIdList (
13632 +   IN const pkcs11h_certificate_id_list_t cert_id_list
13633 +) {
13634 +   pkcs11h_certificate_id_list_t _id = cert_id_list;
13635 +
13636 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
13637 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
13638 +   /*PKCS11H_ASSERT (cert_id_list!=NULL); NOT NEEDED*/
13639 +
13640 +   PKCS11H_DEBUG (
13641 +       PKCS11H_LOG_DEBUG2,
13642 +       "PKCS#11: pkcs11h_certificate_freeCertificateIdList entry cert_id_list=%p",
13643 +       (void *)cert_id_list
13644 +   );
13645 +
13646 +   while (_id != NULL) {
13647 +       pkcs11h_certificate_id_list_t x = _id;
13648 +       _id = _id->next;
13649 +       if (x->certificate_id != NULL) {
13650 +           pkcs11h_certificate_freeCertificateId (x->certificate_id);
13651 +       }
13652 +       x->next = NULL;
13653 +       _pkcs11h_mem_free ((void *)&x);
13654 +   }
13655 +
13656 +   PKCS11H_DEBUG (
13657 +       PKCS11H_LOG_DEBUG2,
13658 +       "PKCS#11: pkcs11h_certificate_freeCertificateIdList return"
13659 +   );
13660 +
13661 +   return CKR_OK;
13662 +}
13663 +
13664 +CK_RV
13665 +pkcs11h_certificate_enumTokenCertificateIds (
13666 +   IN const pkcs11h_token_id_t token_id,
13667 +   IN const int method,
13668 +   IN void * const user_data,
13669 +   IN const unsigned mask_prompt,
13670 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
13671 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
13672 +) {
13673 +#if defined(ENABLE_PKCS11H_THREADING)
13674 +   PKCS11H_BOOL mutex_locked = FALSE;
13675 +#endif
13676 +   pkcs11h_session_t session = NULL;
13677 +   CK_RV rv = CKR_OK;
13678 +
13679 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
13680 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
13681 +   PKCS11H_ASSERT (token_id!=NULL);
13682 +   /*PKCS11H_ASSERT (user_data) NOT NEEDED */
13683 +   /*PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
13684 +   PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
13685 +
13686 +   PKCS11H_DEBUG (
13687 +       PKCS11H_LOG_DEBUG2,
13688 +       "PKCS#11: pkcs11h_certificate_enumTokenCertificateIds entry token_id=%p, method=%d, user_data=%p,
	mask_prompt=%08x, p_cert_id_issuers_list=%p, p_cert_id_end_list=%p",
13689 +       (void *)token_id,
13690 +       method,
13691 +       user_data,
13692 +       mask_prompt,
13693 +       (void *)p_cert_id_issuers_list,
13694 +       (void *)p_cert_id_end_list
13695 +   );
13696 +
13697 +   if (p_cert_id_issuers_list != NULL) {
13698 +       *p_cert_id_issuers_list = NULL;
13699 +   }
13700 +   *p_cert_id_end_list = NULL;
13701 +
13702 +#if defined(ENABLE_PKCS11H_THREADING)
13703 +   if (
13704 +       rv == CKR_OK &&
13705 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.cache)) == CKR_OK
13706 +   ) {
13707 +       mutex_locked = TRUE;
13708 +   }
13709 +#endif
13710 +
13711 +   if (
13712 +       rv == CKR_OK &&
13713 +       (rv = _pkcs11h_session_getSessionByTokenId (
13714 +           token_id,
13715 +           &session
13716 +       )) == CKR_OK
13717 +   ) {
13718 +       if (method == PKCS11H_ENUM_METHOD_RELOAD) {
13719 +           pkcs11h_certificate_freeCertificateIdList (session->cached_certs);
13720 +           session->cached_certs = NULL;
13721 +       }
13722 +
13723 +       if (session->cached_certs == NULL) {
13724 +           rv = _pkcs11h_certificate_enumSessionCertificates (session, user_data, mask_prompt);
13725 +       }
13726 +   }
13727 +
13728 +   if (rv == CKR_OK) {
13729 +       rv = _pkcs11h_certificate_splitCertificateIdList (
13730 +           session->cached_certs,
13731 +           p_cert_id_issuers_list,
13732 +           p_cert_id_end_list
13733 +       );
13734 +   }
13735 +
13736 +   if (session != NULL) {
13737 +       _pkcs11h_session_release (session);
13738 +   }
13739 +
13740 +#if defined(ENABLE_PKCS11H_THREADING)
13741 +   if (mutex_locked) {
13742 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.cache);
13743 +       mutex_locked = FALSE;
13744 +   }
13745 +#endif
13746 +
13747 +   PKCS11H_DEBUG (
13748 +       PKCS11H_LOG_DEBUG2,
13749 +       "PKCS#11: pkcs11h_certificate_enumTokenCertificateIds return rv=%ld-'%s'",
13750 +       rv,
13751 +       pkcs11h_getMessage (rv)
13752 +   );
13753 +   
13754 +   return rv;
13755 +}
13756 +
13757 +CK_RV
13758 +pkcs11h_certificate_enumCertificateIds (
13759 +   IN const int method,
13760 +   IN void * const user_data,
13761 +   IN const unsigned mask_prompt,
13762 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
13763 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
13764 +) {
13765 +#if defined(ENABLE_PKCS11H_THREADING)
13766 +   PKCS11H_BOOL mutex_locked = FALSE;
13767 +#endif
13768 +   pkcs11h_certificate_id_list_t cert_id_list = NULL;
13769 +   pkcs11h_provider_t current_provider;
13770 +   pkcs11h_session_t current_session;
13771 +   CK_RV rv = CKR_OK;
13772 +
13773 +   PKCS11H_ASSERT (s_pkcs11h_data!=NULL);
13774 +   PKCS11H_ASSERT (s_pkcs11h_data->initialized);
13775 +   /*PKCS11H_ASSERT (user_data!=NULL); NOT NEEDED*/
13776 +   /*PKCS11H_ASSERT (p_cert_id_issuers_list!=NULL); NOT NEEDED*/
13777 +   PKCS11H_ASSERT (p_cert_id_end_list!=NULL);
13778 +
13779 +   PKCS11H_DEBUG (
13780 +       PKCS11H_LOG_DEBUG2,
13781 +       "PKCS#11: pkcs11h_certificate_enumCertificateIds entry method=%d, mask_prompt=%08x, p_cert_id_issuers_list=%p,
	p_cert_id_end_list=%p",
13782 +       method,
13783 +       mask_prompt,
13784 +       (void *)p_cert_id_issuers_list,
13785 +       (void *)p_cert_id_end_list
13786 +   );
13787 +
13788 +   if (p_cert_id_issuers_list != NULL) {
13789 +       *p_cert_id_issuers_list = NULL;
13790 +   }
13791 +   *p_cert_id_end_list = NULL;
13792 +
13793 +#if defined(ENABLE_PKCS11H_THREADING)
13794 +   if (
13795 +       rv == CKR_OK &&
13796 +       (rv = _pkcs11h_threading_mutexLock (&s_pkcs11h_data->mutexes.cache)) == CKR_OK
13797 +   ) {
13798 +       mutex_locked = TRUE;
13799 +   }
13800 +#endif
13801 +
13802 +   for (
13803 +       current_session = s_pkcs11h_data->sessions;
13804 +       current_session != NULL;
13805 +       current_session = current_session->next
13806 +   ) {
13807 +       current_session->touch = FALSE;
13808 +       if (method == PKCS11H_ENUM_METHOD_RELOAD) {
13809 +           pkcs11h_certificate_freeCertificateIdList (current_session->cached_certs);
13810 +           current_session->cached_certs = NULL;
13811 +       }
13812 +   }
13813 +
13814 +   for (
13815 +       current_provider = s_pkcs11h_data->providers;
13816 +       (
13817 +           current_provider != NULL &&
13818 +           rv == CKR_OK
13819 +       );
13820 +       current_provider = current_provider->next
13821 +   ) {
13822 +       CK_SLOT_ID_PTR slots = NULL;
13823 +       CK_ULONG slotnum;
13824 +       CK_SLOT_ID slot_index;
13825 +
13826 +       if (!current_provider->enabled) {
13827 +           rv = CKR_CRYPTOKI_NOT_INITIALIZED;
13828 +       }
13829 +
13830 +       if (rv == CKR_OK) {
13831 +           rv = _pkcs11h_session_getSlotList (
13832 +               current_provider,
13833 +               CK_TRUE,
13834 +               &slots,
13835 +               &slotnum
13836 +           );
13837 +       }
13838 +
13839 +       for (
13840 +           slot_index=0;
13841 +           (
13842 +               slot_index < slotnum &&
13843 +               rv == CKR_OK
13844 +           );
13845 +           slot_index++
13846 +       ) {
13847 +           pkcs11h_session_t session = NULL;
13848 +           pkcs11h_token_id_t token_id = NULL;
13849 +           CK_TOKEN_INFO info;
13850 +
13851 +           if (rv == CKR_OK) {
13852 +               rv = current_provider->f->C_GetTokenInfo (
13853 +                   slots[slot_index],
13854 +                   &info
13855 +               );
13856 +           }
13857 +
13858 +           if (
13859 +               rv == CKR_OK &&
13860 +               (rv = _pkcs11h_token_getTokenId (
13861 +                   &info,
13862 +                   &token_id
13863 +               )) == CKR_OK &&
13864 +               (rv = _pkcs11h_session_getSessionByTokenId (
13865 +                   token_id,
13866 +                   &session
13867 +               )) == CKR_OK
13868 +           ) {
13869 +               session->touch = TRUE;
13870 +
13871 +               if (session->cached_certs == NULL) {
13872 +                   rv = _pkcs11h_certificate_enumSessionCertificates (session, user_data, mask_prompt);
13873 +               }
13874 +           }
13875 +
13876 +           if (rv != CKR_OK) {
13877 +               PKCS11H_DEBUG (
13878 +                   PKCS11H_LOG_DEBUG1,
13879 +                   "PKCS#11: Cannot get token information for provider '%s' slot %ld rv=%ld-'%s'",
13880 +                   current_provider->manufacturerID,
13881 +                   slots[slot_index],
13882 +                   rv,
13883 +                   pkcs11h_getMessage (rv)
13884 +               );
13885 +
13886 +               /*
13887 +                * Ignore error
13888 +                */
13889 +               rv = CKR_OK;
13890 +           }
13891 +
13892 +           if (session != NULL) {
13893 +               _pkcs11h_session_release (session);
13894 +               session = NULL;
13895 +           }
13896 +
13897 +           if (token_id != NULL) {
13898 +               pkcs11h_token_freeTokenId (token_id);
13899 +               token_id = NULL;
13900 +           }
13901 +       }
13902 +
13903 +       if (rv != CKR_OK) {
13904 +           PKCS11H_DEBUG (
13905 +               PKCS11H_LOG_DEBUG1,
13906 +               "PKCS#11: Cannot get slot list for provider '%s' rv=%ld-'%s'",
13907 +               current_provider->manufacturerID,
13908 +               rv,
13909 +               pkcs11h_getMessage (rv)
13910 +           );
13911 +
13912 +           /*
13913 +            * Ignore error
13914 +            */
13915 +           rv = CKR_OK;
13916 +       }
13917 +
13918 +       if (slots != NULL) {
13919 +           _pkcs11h_mem_free ((void *)&slots);
13920 +           slots = NULL;
13921 +       }
13922 +   }
13923 +
13924 +   for (
13925 +       current_session = s_pkcs11h_data->sessions;
13926 +       (
13927 +           current_session != NULL &&
13928 +           rv == CKR_OK
13929 +       );
13930 +       current_session = current_session->next
13931 +   ) {
13932 +       if (
13933 +           method == PKCS11H_ENUM_METHOD_CACHE ||
13934 +           (
13935 +               (
13936 +                   method == PKCS11H_ENUM_METHOD_RELOAD ||
13937 +                   method == PKCS11H_ENUM_METHOD_CACHE_EXIST
13938 +               ) &&
13939 +               current_session->touch
13940 +           )
13941 +       ) {
13942 +           pkcs11h_certificate_id_list_t entry = NULL;
13943 +
13944 +           for (
13945 +               entry = current_session->cached_certs;
13946 +               (
13947 +                   entry != NULL &&
13948 +                   rv == CKR_OK
13949 +               );
13950 +               entry = entry->next
13951 +           ) {
13952 +               pkcs11h_certificate_id_list_t new_entry = NULL;
13953 +
13954 +               if (
13955 +                   rv == CKR_OK &&
13956 +                   (rv = _pkcs11h_mem_malloc (
13957 +                       (void *)&new_entry,
13958 +                       sizeof (struct pkcs11h_certificate_id_list_s)
13959 +                   )) == CKR_OK &&
13960 +                   (rv = pkcs11h_certificate_duplicateCertificateId (
13961 +                       &new_entry->certificate_id,
13962 +                       entry->certificate_id
13963 +                   )) == CKR_OK
13964 +               ) {
13965 +                   new_entry->next = cert_id_list;
13966 +                   cert_id_list = new_entry;
13967 +                   new_entry = NULL;
13968 +               }
13969 +
13970 +               if (new_entry != NULL) {
13971 +                   new_entry->next = NULL;
13972 +                   pkcs11h_certificate_freeCertificateIdList (new_entry);
13973 +                   new_entry = NULL;
13974 +               }
13975 +           }
13976 +       }
13977 +   }
13978 +
13979 +   if (rv == CKR_OK) {
13980 +       rv = _pkcs11h_certificate_splitCertificateIdList (
13981 +           cert_id_list,
13982 +           p_cert_id_issuers_list,
13983 +           p_cert_id_end_list
13984 +       );
13985 +   }
13986 +
13987 +   if (cert_id_list != NULL) {
13988 +       pkcs11h_certificate_freeCertificateIdList (cert_id_list);
13989 +       cert_id_list = NULL;
13990 +   }
13991 +
13992 +
13993 +#if defined(ENABLE_PKCS11H_THREADING)
13994 +   if (mutex_locked) {
13995 +       _pkcs11h_threading_mutexRelease (&s_pkcs11h_data->mutexes.cache);
13996 +       mutex_locked = FALSE;
13997 +   }
13998 +#endif
13999 +
14000 +   PKCS11H_DEBUG (
14001 +       PKCS11H_LOG_DEBUG2,
14002 +       "PKCS#11: pkcs11h_certificate_enumCertificateIds return rv=%ld-'%s'",
14003 +       rv,
14004 +       pkcs11h_getMessage (rv)
14005 +   );
14006 +   
14007 +   return rv;
14008 +}
14009 +
14010 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
14011 +
14012 +#endif             /* ENABLE_PKCS11H_ENUM */
14013 +
14014 +#if defined(ENABLE_PKCS11H_SLOTEVENT)
14015 +/*======================================================================*
14016 + * SLOTEVENT INTERFACE
14017 + *======================================================================*/
14018 +
14019 +static
14020 +unsigned long
14021 +_pkcs11h_slotevent_checksum (
14022 +   IN const unsigned char * const p,
14023 +   IN const size_t s
14024 +) {
14025 +   unsigned long r = 0;
14026 +   size_t i;
14027 +   for (i=0;i<s;i++) {
14028 +       r += p[i];
14029 +   }
14030 +   return r;
14031 +}
14032 +
14033 +static
14034 +void *
14035 +_pkcs11h_slotevent_provider (
14036 +   IN void *p
14037 +) {
14038 +   pkcs11h_provider_t provider = (pkcs11h_provider_t)p;
14039 +   CK_SLOT_ID slot;
14040 +   CK_RV rv = CKR_OK;
14041 +
14042 +   PKCS11H_DEBUG (
14043 +       PKCS11H_LOG_DEBUG2,
14044 +       "PKCS#11: _pkcs11h_slotevent_provider provider='%s' entry",
14045 +       provider->manufacturerID
14046 +   );
14047 +
14048 +   if (rv == CKR_OK && !provider->enabled) {
14049 +       rv = CKR_OPERATION_NOT_INITIALIZED;
14050 +   }
14051 +
14052 +   if (rv == CKR_OK) {
14053 +
14054 +       if (provider->slot_poll_interval == 0) {
14055 +           provider->slot_poll_interval = PKCS11H_DEFAULT_SLOTEVENT_POLL;
14056 +       }
14057 +
14058 +       /*
14059 +        * If we cannot finalize, we cannot cause
14060 +        * WaitForSlotEvent to terminate
14061 +        */
14062 +       if (!provider->should_finalize) {
14063 +           PKCS11H_DEBUG (
14064 +               PKCS11H_LOG_DEBUG1,
14065 +               "PKCS#11: Setup slotevent provider='%s' mode hardset to poll",
14066 +               provider->manufacturerID
14067 +           );
14068 +           provider->slot_event_method = PKCS11H_SLOTEVENT_METHOD_POLL;
14069 +       }
14070 +
14071 +       if (
14072 +           provider->slot_event_method == PKCS11H_SLOTEVENT_METHOD_AUTO ||
14073 +           provider->slot_event_method == PKCS11H_SLOTEVENT_METHOD_TRIGGER
14074 +       ) { 
14075 +           if (
14076 +               provider->f->C_WaitForSlotEvent (
14077 +                   CKF_DONT_BLOCK,
14078 +                   &slot,
14079 +                   NULL_PTR
14080 +               ) == CKR_FUNCTION_NOT_SUPPORTED
14081 +           ) {
14082 +               PKCS11H_DEBUG (
14083 +                   PKCS11H_LOG_DEBUG1,
14084 +                   "PKCS#11: Setup slotevent provider='%s' mode is poll",
14085 +                   provider->manufacturerID
14086 +               );
14087 +
14088 +               provider->slot_event_method = PKCS11H_SLOTEVENT_METHOD_POLL;
14089 +           }
14090 +           else {
14091 +               PKCS11H_DEBUG (
14092 +                   PKCS11H_LOG_DEBUG1,
14093 +                   "PKCS#11: Setup slotevent provider='%s' mode is trigger",
14094 +                   provider->manufacturerID
14095 +               );
14096 +
14097 +               provider->slot_event_method = PKCS11H_SLOTEVENT_METHOD_TRIGGER;
14098 +           }
14099 +       }
14100 +   }
14101 +
14102 +   if (provider->slot_event_method == PKCS11H_SLOTEVENT_METHOD_TRIGGER) {
14103 +       while (
14104 +           !s_pkcs11h_data->slotevent.should_terminate &&
14105 +           provider->enabled &&
14106 +           rv == CKR_OK &&
14107 +           (rv = provider->f->C_WaitForSlotEvent (
14108 +               0,
14109 +               &slot,
14110 +               NULL_PTR
14111 +           )) == CKR_OK
14112 +       ) {
14113 +           PKCS11H_DEBUG (
14114 +               PKCS11H_LOG_DEBUG1,
14115 +               "PKCS#11: Slotevent provider='%s' event",
14116 +               provider->manufacturerID
14117 +           );
14118 +
14119 +           _pkcs11h_threading_condSignal (&s_pkcs11h_data->slotevent.cond_event);
14120 +       }
14121 +   }
14122 +   else {
14123 +       unsigned long ulLastChecksum = 0;
14124 +       PKCS11H_BOOL is_first_time = TRUE;
14125 +
14126 +       while (
14127 +           !s_pkcs11h_data->slotevent.should_terminate &&
14128 +           provider->enabled &&
14129 +           rv == CKR_OK
14130 +       ) {
14131 +           unsigned long ulCurrentChecksum = 0;
14132 +
14133 +           CK_SLOT_ID_PTR slots = NULL;
14134 +           CK_ULONG slotnum;
14135 +
14136 +           PKCS11H_DEBUG (
14137 +               PKCS11H_LOG_DEBUG1,
14138 +               "PKCS#11: Slotevent provider='%s' poll",
14139 +               provider->manufacturerID
14140 +           );
14141 +
14142 +           if (
14143 +               rv == CKR_OK &&
14144 +               (rv = _pkcs11h_session_getSlotList (
14145 +                   provider,
14146 +                   TRUE,
14147 +                   &slots,
14148 +                   &slotnum
14149 +               )) == CKR_OK
14150 +           ) {
14151 +               CK_ULONG i;
14152 +               
14153 +               for (i=0;i<slotnum;i++) {
14154 +                   CK_TOKEN_INFO info;
14155 +
14156 +                   if (provider->f->C_GetTokenInfo (slots[i], &info) == CKR_OK) {
14157 +                       ulCurrentChecksum += (
14158 +                           _pkcs11h_slotevent_checksum (
14159 +                               info.label,
14160 +                               sizeof (info.label)
14161 +                           ) +
14162 +                           _pkcs11h_slotevent_checksum (
14163 +                               info.manufacturerID,
14164 +                               sizeof (info.manufacturerID)
14165 +                           ) +
14166 +                           _pkcs11h_slotevent_checksum (
14167 +                               info.model,
14168 +                               sizeof (info.model)
14169 +                           ) +
14170 +                           _pkcs11h_slotevent_checksum (
14171 +                               info.serialNumber,
14172 +                               sizeof (info.serialNumber)
14173 +                           )
14174 +                       );
14175 +                   }
14176 +               }
14177 +           }
14178 +           
14179 +           if (rv == CKR_OK) {
14180 +               if (is_first_time) {
14181 +                   is_first_time = FALSE;
14182 +               }
14183 +               else {
14184 +                   if (ulLastChecksum != ulCurrentChecksum) {
14185 +                       PKCS11H_DEBUG (
14186 +                           PKCS11H_LOG_DEBUG1,
14187 +                           "PKCS#11: Slotevent provider='%s' event",
14188 +                           provider->manufacturerID
14189 +                       );
14190 +
14191 +                       _pkcs11h_threading_condSignal (&s_pkcs11h_data->slotevent.cond_event);
14192 +                   }
14193 +               }
14194 +               ulLastChecksum = ulCurrentChecksum;
14195 +           }
14196 +
14197 +           if (slots != NULL) {
14198 +               _pkcs11h_mem_free ((void *)&slots);
14199 +           }
14200 +           
14201 +           if (!s_pkcs11h_data->slotevent.should_terminate) {
14202 +               _pkcs11h_threading_sleep (provider->slot_poll_interval);
14203 +           }
14204 +       }
14205 +   }
14206 +
14207 +   PKCS11H_DEBUG (
14208 +       PKCS11H_LOG_DEBUG2,
14209 +       "PKCS#11: _pkcs11h_slotevent_provider provider='%s' return",
14210 +       provider->manufacturerID
14211 +   );
14212 +
14213 +   return NULL;
14214 +}
14215 +
14216 +static
14217 +void *
14218 +_pkcs11h_slotevent_manager (
14219 +   IN void *p
14220 +) {
14221 +   PKCS11H_BOOL first_time = TRUE;
14222 +
14223 +   (void)p;
14224 +
14225 +   PKCS11H_DEBUG (
14226 +       PKCS11H_LOG_DEBUG2,
14227 +       "PKCS#11: _pkcs11h_slotevent_manager entry"
14228 +   );
14229 +
14230 +   /*
14231 +    * Trigger hook, so application may
14232 +    * depend on initial slot change
14233 +    */
14234 +   PKCS11H_DEBUG (
14235 +       PKCS11H_LOG_DEBUG1,
14236 +       "PKCS#11: Calling slotevent hook"
14237 +   );
14238 +   s_pkcs11h_data->hooks.slotevent (s_pkcs11h_data->hooks.slotevent_data);
14239 +
14240 +   while (
14241 +       first_time ||   /* Must enter wait or mutex will never be free */
14242 +       !s_pkcs11h_data->slotevent.should_terminate
14243 +   ) {
14244 +       pkcs11h_provider_t current_provider;
14245 +
14246 +       first_time = FALSE;
14247 +
14248 +       /*
14249 +        * Start each provider thread
14250 +        * if not already started.
14251 +        * This is required in order to allow
14252 +        * adding new providers.
14253 +        */
14254 +       for (
14255 +           current_provider = s_pkcs11h_data->providers;
14256 +           current_provider != NULL;
14257 +           current_provider = current_provider->next
14258 +       ) {
14259 +           if (!current_provider->enabled) {
14260 +               if (current_provider->slotevent_thread == PKCS11H_THREAD_NULL) {
14261 +                   _pkcs11h_threading_threadStart (
14262 +                       &current_provider->slotevent_thread,
14263 +                       _pkcs11h_slotevent_provider,
14264 +                       current_provider
14265 +                   );
14266 +               }
14267 +           }
14268 +           else {
14269 +               if (current_provider->slotevent_thread != PKCS11H_THREAD_NULL) {
14270 +                   _pkcs11h_threading_threadJoin (&current_provider->slotevent_thread);
14271 +               }
14272 +           }
14273 +       }
14274 +
14275 +       PKCS11H_DEBUG (
14276 +           PKCS11H_LOG_DEBUG2,
14277 +           "PKCS#11: _pkcs11h_slotevent_manager waiting for slotevent"
14278 +       );
14279 +       _pkcs11h_threading_condWait (&s_pkcs11h_data->slotevent.cond_event, PKCS11H_COND_INFINITE);
14280 +
14281 +       if (s_pkcs11h_data->slotevent.skip_event) {
14282 +           PKCS11H_DEBUG (
14283 +               PKCS11H_LOG_DEBUG1,
14284 +               "PKCS#11: Slotevent skipping event"
14285 +           );
14286 +           s_pkcs11h_data->slotevent.skip_event = FALSE;
14287 +       }
14288 +       else {
14289 +           PKCS11H_DEBUG (
14290 +               PKCS11H_LOG_DEBUG1,
14291 +               "PKCS#11: Calling slotevent hook"
14292 +           );
14293 +           s_pkcs11h_data->hooks.slotevent (s_pkcs11h_data->hooks.slotevent_data);
14294 +       }
14295 +   }
14296 +
14297 +   {
14298 +       pkcs11h_provider_t current_provider;
14299 +
14300 +       PKCS11H_DEBUG (
14301 +           PKCS11H_LOG_DEBUG2,
14302 +           "PKCS#11: _pkcs11h_slotevent_manager joining threads"
14303 +       );
14304 +
14305 +
14306 +       for (
14307 +           current_provider = s_pkcs11h_data->providers;
14308 +           current_provider != NULL;
14309 +           current_provider = current_provider->next
14310 +       ) {
14311 +           if (current_provider->slotevent_thread != PKCS11H_THREAD_NULL) {
14312 +               _pkcs11h_threading_threadJoin (&current_provider->slotevent_thread);
14313 +           }
14314 +       }
14315 +   }
14316 +
14317 +   PKCS11H_DEBUG (
14318 +       PKCS11H_LOG_DEBUG2,
14319 +       "PKCS#11: _pkcs11h_slotevent_manager return"
14320 +   );
14321 +
14322 +   return NULL;
14323 +}
14324 +
14325 +static
14326 +CK_RV
14327 +_pkcs11h_slotevent_init () {
14328 +   CK_RV rv = CKR_OK;
14329 +
14330 +   PKCS11H_DEBUG (
14331 +       PKCS11H_LOG_DEBUG2,
14332 +       "PKCS#11: _pkcs11h_slotevent_init entry"
14333 +   );
14334 +
14335 +   if (!s_pkcs11h_data->slotevent.initialized) {
14336 +       if (rv == CKR_OK) {
14337 +           rv = _pkcs11h_threading_condInit (&s_pkcs11h_data->slotevent.cond_event);
14338 +       }
14339 +       
14340 +       if (rv == CKR_OK) {
14341 +           rv = _pkcs11h_threading_threadStart (
14342 +               &s_pkcs11h_data->slotevent.thread,
14343 +               _pkcs11h_slotevent_manager,
14344 +               NULL
14345 +           );
14346 +       }
14347 +       
14348 +       if (rv == CKR_OK) {
14349 +           s_pkcs11h_data->slotevent.initialized = TRUE;
14350 +       }
14351 +   }
14352 +
14353 +   PKCS11H_DEBUG (
14354 +       PKCS11H_LOG_DEBUG2,
14355 +       "PKCS#11: _pkcs11h_slotevent_init return rv=%ld-'%s'",
14356 +       rv,
14357 +       pkcs11h_getMessage (rv)
14358 +   );
14359 +
14360 +   return rv;
14361 +}
14362 +
14363 +static
14364 +CK_RV
14365 +_pkcs11h_slotevent_notify () {
14366 +   
14367 +   PKCS11H_DEBUG (
14368 +       PKCS11H_LOG_DEBUG2,
14369 +       "PKCS#11: _pkcs11h_slotevent_notify entry"
14370 +   );
14371 +
14372 +   if (s_pkcs11h_data->slotevent.initialized) {
14373 +       s_pkcs11h_data->slotevent.skip_event = TRUE;
14374 +       _pkcs11h_threading_condSignal (&s_pkcs11h_data->slotevent.cond_event);
14375 +   }
14376 +
14377 +   PKCS11H_DEBUG (
14378 +       PKCS11H_LOG_DEBUG2,
14379 +       "PKCS#11: _pkcs11h_slotevent_notify return"
14380 +   );
14381 +
14382 +   return CKR_OK;
14383 +}
14384 +
14385 +static
14386 +CK_RV
14387 +_pkcs11h_slotevent_terminate () {
14388 +   
14389 +   PKCS11H_DEBUG (
14390 +       PKCS11H_LOG_DEBUG2,
14391 +       "PKCS#11: _pkcs11h_slotevent_terminate entry"
14392 +   );
14393 +
14394 +   if (s_pkcs11h_data->slotevent.initialized) {
14395 +       s_pkcs11h_data->slotevent.should_terminate = TRUE;
14396 +
14397 +       _pkcs11h_slotevent_notify ();
14398 +
14399 +       if (s_pkcs11h_data->slotevent.thread != PKCS11H_THREAD_NULL) {
14400 +           _pkcs11h_threading_threadJoin (&s_pkcs11h_data->slotevent.thread);
14401 +       }
14402 +
14403 +       _pkcs11h_threading_condFree (&s_pkcs11h_data->slotevent.cond_event);
14404 +       s_pkcs11h_data->slotevent.initialized = FALSE;
14405 +   }
14406 +
14407 +   PKCS11H_DEBUG (
14408 +       PKCS11H_LOG_DEBUG2,
14409 +       "PKCS#11: _pkcs11h_slotevent_terminate return"
14410 +   );
14411 +
14412 +   return CKR_OK;
14413 +}
14414 +
14415 +#endif
14416 +
14417 +#if defined(ENABLE_PKCS11H_OPENSSL)
14418 +/*======================================================================*
14419 + * OPENSSL INTERFACE
14420 + *======================================================================*/
14421 +
14422 +static
14423 +pkcs11h_openssl_session_t
14424 +_pkcs11h_openssl_get_openssl_session (
14425 +   IN OUT const RSA *rsa
14426 +) {
14427 +   pkcs11h_openssl_session_t session;
14428 +       
14429 +   PKCS11H_ASSERT (rsa!=NULL);
14430 +#if OPENSSL_VERSION_NUMBER < 0x00907000L
14431 +   session = (pkcs11h_openssl_session_t)RSA_get_app_data ((RSA *)rsa);
14432 +#else
14433 +   session = (pkcs11h_openssl_session_t)RSA_get_app_data (rsa);
14434 +#endif
14435 +   PKCS11H_ASSERT (session!=NULL);
14436 +
14437 +   return session;
14438 +}
14439 +
14440 +static
14441 +pkcs11h_certificate_t
14442 +_pkcs11h_openssl_get_pkcs11h_certificate (
14443 +   IN OUT const RSA *rsa
14444 +) {
14445 +   pkcs11h_openssl_session_t session = _pkcs11h_openssl_get_openssl_session (rsa);
14446 +   
14447 +   PKCS11H_ASSERT (session!=NULL);
14448 +   PKCS11H_ASSERT (session->certificate!=NULL);
14449 +
14450 +   return session->certificate;
14451 +}
14452 +
14453 +#if OPENSSL_VERSION_NUMBER < 0x00907000L
14454 +static
14455 +int
14456 +_pkcs11h_openssl_dec (
14457 +   IN int flen,
14458 +   IN unsigned char *from,
14459 +   OUT unsigned char *to,
14460 +   IN OUT RSA *rsa,
14461 +   IN int padding
14462 +) {
14463 +#else
14464 +static
14465 +int
14466 +_pkcs11h_openssl_dec (
14467 +   IN int flen,
14468 +   IN const unsigned char *from,
14469 +   OUT unsigned char *to,
14470 +   IN OUT RSA *rsa,
14471 +   IN int padding
14472 +) {
14473 +#endif
14474 +   PKCS11H_ASSERT (from!=NULL);
14475 +   PKCS11H_ASSERT (to!=NULL);
14476 +   PKCS11H_ASSERT (rsa!=NULL);
14477 +
14478 +   PKCS11H_DEBUG (
14479 +       PKCS11H_LOG_DEBUG2,
14480 +       "PKCS#11: _pkcs11h_openssl_dec entered - flen=%d, from=%p, to=%p, rsa=%p, padding=%d",
14481 +       flen,
14482 +       from,
14483 +       to,
14484 +       (void *)rsa,
14485 +       padding
14486 +   );
14487 +
14488 +   PKCS11H_LOG (
14489 +       PKCS11H_LOG_ERROR,
14490 +       "PKCS#11: Private key decryption is not supported"
14491 +   );
14492 +
14493 +   PKCS11H_DEBUG (
14494 +       PKCS11H_LOG_DEBUG2,
14495 +       "PKCS#11: _pkcs11h_openssl_dec return"
14496 +   );
14497 +
14498 +   return -1;
14499 +}
14500 +
14501 +#if OPENSSL_VERSION_NUMBER < 0x00907000L
14502 +static
14503 +int
14504 +_pkcs11h_openssl_sign (
14505 +   IN int type,
14506 +   IN unsigned char *m,
14507 +   IN unsigned int m_len,
14508 +   OUT unsigned char *sigret,
14509 +   OUT unsigned int *siglen,
14510 +   IN OUT RSA *rsa
14511 +) {
14512 +#else
14513 +static
14514 +int
14515 +_pkcs11h_openssl_sign (
14516 +   IN int type,
14517 +   IN const unsigned char *m,
14518 +   IN unsigned int m_len,
14519 +   OUT unsigned char *sigret,
14520 +   OUT unsigned int *siglen,
14521 +   IN OUT const RSA *rsa
14522 +) {
14523 +#endif
14524 +   pkcs11h_certificate_t certificate = _pkcs11h_openssl_get_pkcs11h_certificate (rsa);
14525 +   PKCS11H_BOOL session_locked = FALSE;
14526 +   CK_RV rv = CKR_OK;
14527 +
14528 +   int myrsa_size = 0;
14529 +   
14530 +   unsigned char *enc_alloc = NULL;
14531 +   unsigned char *enc = NULL;
14532 +   int enc_len = 0;
14533 +
14534 +   PKCS11H_ASSERT (m!=NULL);
14535 +   PKCS11H_ASSERT (sigret!=NULL);
14536 +   PKCS11H_ASSERT (siglen!=NULL);
14537 +
14538 +   PKCS11H_DEBUG (
14539 +       PKCS11H_LOG_DEBUG2,
14540 +       "PKCS#11: _pkcs11h_openssl_sign entered - type=%d, m=%p, m_len=%u, signret=%p, *signlen=%u, rsa=%p",
14541 +       type,
14542 +       m,
14543 +       m_len,
14544 +       sigret,
14545 +       sigret != NULL ? *siglen : 0,
14546 +       (void *)rsa
14547 +   );
14548 +
14549 +   if (rv == CKR_OK) {
14550 +       myrsa_size=RSA_size(rsa);
14551 +   }
14552 +
14553 +   if (type == NID_md5_sha1) {
14554 +       if (rv == CKR_OK) {
14555 +           enc = (unsigned char *)m;
14556 +           enc_len = m_len;
14557 +       }
14558 +   }
14559 +   else {
14560 +       X509_SIG sig;
14561 +       ASN1_TYPE parameter;
14562 +       X509_ALGOR algor;
14563 +       ASN1_OCTET_STRING digest;
14564 +       unsigned char *p = NULL;
14565 +
14566 +       if (
14567 +           rv == CKR_OK &&
14568 +           (rv = _pkcs11h_mem_malloc ((void*)&enc, myrsa_size+1)) == CKR_OK
14569 +       ) {
14570 +           enc_alloc = enc;
14571 +       }
14572 +       
14573 +       if (rv == CKR_OK) {
14574 +           sig.algor = &algor;
14575 +       }
14576 +
14577 +       if (
14578 +           rv == CKR_OK &&
14579 +           (sig.algor->algorithm = OBJ_nid2obj (type)) == NULL
14580 +       ) {
14581 +           rv = CKR_FUNCTION_FAILED;
14582 +       }
14583 +   
14584 +       if (
14585 +           rv == CKR_OK &&
14586 +           sig.algor->algorithm->length == 0
14587 +       ) {
14588 +           rv = CKR_KEY_SIZE_RANGE;
14589 +       }
14590 +   
14591 +       if (rv == CKR_OK) {
14592 +           parameter.type = V_ASN1_NULL;
14593 +           parameter.value.ptr = NULL;
14594 +   
14595 +           sig.algor->parameter = &parameter;
14596 +
14597 +           sig.digest = &digest;
14598 +           sig.digest->data = (unsigned char *)m;
14599 +           sig.digest->length = m_len;
14600 +       }
14601 +   
14602 +       if (
14603 +           rv == CKR_OK &&
14604 +           (enc_len=i2d_X509_SIG (&sig, NULL)) < 0
14605 +       ) {
14606 +           rv = CKR_FUNCTION_FAILED;
14607 +       }
14608 +
14609 +       /*
14610 +        * d_X509_SIG increments pointer!
14611 +        */
14612 +       p = enc;
14613 +   
14614 +       if (
14615 +           rv == CKR_OK &&
14616 +           (enc_len=i2d_X509_SIG (&sig, &p)) < 0
14617 +       ) {
14618 +           rv = CKR_FUNCTION_FAILED;
14619 +       }
14620 +   }
14621 +
14622 +   if (
14623 +       rv == CKR_OK &&
14624 +       enc_len > (myrsa_size-RSA_PKCS1_PADDING_SIZE)
14625 +   ) {
14626 +       rv = CKR_KEY_SIZE_RANGE;
14627 +   }
14628 +
14629 +   if (
14630 +       rv == CKR_OK &&
14631 +       (rv = pkcs11h_certificate_lockSession (certificate)) == CKR_OK
14632 +   ) {
14633 +       session_locked = TRUE;
14634 +   }
14635 +
14636 +   if (rv == CKR_OK) {
14637 +       PKCS11H_DEBUG (
14638 +           PKCS11H_LOG_DEBUG1,
14639 +           "PKCS#11: Performing signature"
14640 +       );
14641 +
14642 +       *siglen = myrsa_size;
14643 +
14644 +       if (
14645 +           (rv = pkcs11h_certificate_signAny (
14646 +               certificate,
14647 +               CKM_RSA_PKCS,
14648 +               enc,
14649 +               enc_len,
14650 +               sigret,
14651 +               siglen
14652 +           )) != CKR_OK
14653 +       ) {
14654 +           PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot perform signature %ld:'%s'", rv, pkcs11h_getMessage (rv));
14655 +       }
14656 +   }
14657 +
14658 +   if (session_locked) {
14659 +       pkcs11h_certificate_releaseSession (certificate);
14660 +       session_locked = FALSE;
14661 +   }
14662 +
14663 +   if (enc_alloc != NULL) {
14664 +       _pkcs11h_mem_free ((void *)&enc_alloc);
14665 +   }
14666 +   
14667 +   PKCS11H_DEBUG (
14668 +       PKCS11H_LOG_DEBUG2,
14669 +       "PKCS#11: _pkcs11h_openssl_sign - return rv=%ld-'%s'",
14670 +       rv,
14671 +       pkcs11h_getMessage (rv)
14672 +   );
14673 +
14674 +   return rv == CKR_OK ? 1 : -1; 
14675 +}
14676 +
14677 +static
14678 +int
14679 +_pkcs11h_openssl_finish (
14680 +   IN OUT RSA *rsa
14681 +) {
14682 +   pkcs11h_openssl_session_t openssl_session = _pkcs11h_openssl_get_openssl_session (rsa);
14683 +
14684 +   PKCS11H_DEBUG (
14685 +       PKCS11H_LOG_DEBUG2,
14686 +       "PKCS#11: _pkcs11h_openssl_finish - entered rsa=%p",
14687 +       (void *)rsa
14688 +   );
14689 +
14690 +   RSA_set_app_data (rsa, NULL);
14691 +   
14692 +   if (openssl_session->orig_finish != NULL) {
14693 +       openssl_session->orig_finish (rsa);
14694 +
14695 +#ifdef BROKEN_OPENSSL_ENGINE
14696 +       {
14697 +           /* We get called TWICE here, once for
14698 +            * releasing the key and also for
14699 +            * releasing the engine.
14700 +            * To prevent endless recursion, FIRST
14701 +            * clear rsa->engine, THEN call engine->finish
14702 +            */
14703 +           ENGINE *e = rsa->engine;
14704 +           rsa->engine = NULL;
14705 +           if (e) {
14706 +               ENGINE_finish(e);
14707 +           }
14708 +       }
14709 +#endif
14710 +   }
14711 +
14712 +   pkcs11h_openssl_freeSession (openssl_session);
14713 +
14714 +   PKCS11H_DEBUG (
14715 +       PKCS11H_LOG_DEBUG2,
14716 +       "PKCS#11: _pkcs11h_openssl_finish - return"
14717 +   );
14718 +   
14719 +   return 1;
14720 +}
14721 +
14722 +X509 *
14723 +pkcs11h_openssl_getX509 (
14724 +   IN const pkcs11h_certificate_t certificate
14725 +) {
14726 +   unsigned char *certificate_blob = NULL;
14727 +   size_t certificate_blob_size = 0;
14728 +   X509 *x509 = NULL;
14729 +   CK_RV rv = CKR_OK;
14730 +
14731 +   pkcs11_openssl_d2i_t d2i1 = NULL;
14732 +   PKCS11H_BOOL ok = TRUE;
14733 +
14734 +   PKCS11H_ASSERT (certificate!=NULL);
14735 +
14736 +   PKCS11H_DEBUG (
14737 +       PKCS11H_LOG_DEBUG2,
14738 +       "PKCS#11: pkcs11h_openssl_getX509 - entry certificate=%p",
14739 +       (void *)certificate
14740 +   );
14741 +
14742 +   if (
14743 +       ok &&
14744 +       (x509 = X509_new ()) == NULL
14745 +   ) {
14746 +       ok = FALSE;
14747 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Unable to allocate certificate object");
14748 +   }
14749 +
14750 +   if (
14751 +       ok &&
14752 +       pkcs11h_certificate_getCertificateBlob (
14753 +           certificate,
14754 +           NULL,
14755 +           &certificate_blob_size
14756 +       ) != CKR_OK
14757 +   ) {
14758 +       ok = FALSE;
14759 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot read X.509 certificate from token %ld-'%s'", rv,
	pkcs11h_getMessage (rv));
14760 +   }
14761 +
14762 +   if (
14763 +       ok &&
14764 +       (rv = _pkcs11h_mem_malloc ((void *)&certificate_blob, certificate_blob_size)) != CKR_OK
14765 +   ) {
14766 +       ok = FALSE;
14767 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot allocate X.509 memory %ld-'%s'", rv, pkcs11h_getMessage (rv));
14768 +   }
14769 +
14770 +   if (
14771 +       ok &&
14772 +       pkcs11h_certificate_getCertificateBlob (
14773 +           certificate,
14774 +           certificate_blob,
14775 +           &certificate_blob_size
14776 +       ) != CKR_OK
14777 +   ) {
14778 +       ok = FALSE;
14779 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot read X.509 certificate from token %ld-'%s'", rv,
	pkcs11h_getMessage (rv));
14780 +   }
14781 +
14782 +   d2i1 = (pkcs11_openssl_d2i_t)certificate_blob;
14783 +   if (
14784 +       ok &&
14785 +       !d2i_X509 (&x509, &d2i1, certificate_blob_size)
14786 +   ) {
14787 +       ok = FALSE;
14788 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Unable to parse X.509 certificate");
14789 +   }
14790 +
14791 +   if (!ok) {
14792 +       X509_free (x509);
14793 +       x509 = NULL;
14794 +   }
14795 +   
14796 +   PKCS11H_DEBUG (
14797 +       PKCS11H_LOG_DEBUG2,
14798 +       "PKCS#11: pkcs11h_openssl_getX509 - return x509=%p",
14799 +       (void *)x509
14800 +   );
14801 +
14802 +   return x509;
14803 +}
14804 +
14805 +pkcs11h_openssl_session_t
14806 +pkcs11h_openssl_createSession (
14807 +   IN const pkcs11h_certificate_t certificate
14808 +) {
14809 +   pkcs11h_openssl_session_t openssl_session = NULL;
14810 +   PKCS11H_BOOL ok = TRUE;
14811 +
14812 +   PKCS11H_DEBUG (
14813 +       PKCS11H_LOG_DEBUG2,
14814 +       "PKCS#11: pkcs11h_openssl_createSession - entry"
14815 +   );
14816 +
14817 +   if (
14818 +       ok &&
14819 +       _pkcs11h_mem_malloc (
14820 +           (void*)&openssl_session,
14821 +           sizeof (struct pkcs11h_openssl_session_s)) != CKR_OK
14822 +   ) {
14823 +       ok = FALSE;
14824 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot allocate memory");
14825 +   }
14826 +
14827 +   if (ok) {
14828 +       const RSA_METHOD *def = RSA_get_default_method();
14829 +
14830 +       memmove (&openssl_session->smart_rsa, def, sizeof(RSA_METHOD));
14831 +
14832 +       openssl_session->orig_finish = def->finish;
14833 +
14834 +       openssl_session->smart_rsa.name = "pkcs11";
14835 +       openssl_session->smart_rsa.rsa_priv_dec = _pkcs11h_openssl_dec;
14836 +       openssl_session->smart_rsa.rsa_sign = _pkcs11h_openssl_sign;
14837 +       openssl_session->smart_rsa.finish = _pkcs11h_openssl_finish;
14838 +       openssl_session->smart_rsa.flags  = RSA_METHOD_FLAG_NO_CHECK | RSA_FLAG_EXT_PKEY;
14839 +       openssl_session->certificate = certificate;
14840 +       openssl_session->reference_count = 1;
14841 +   }
14842 +
14843 +   if (!ok) {
14844 +       _pkcs11h_mem_free ((void *)&openssl_session);
14845 +   }
14846 +   
14847 +   PKCS11H_DEBUG (
14848 +       PKCS11H_LOG_DEBUG2,
14849 +       "PKCS#11: pkcs11h_openssl_createSession - return openssl_session=%p",
14850 +       (void *)openssl_session
14851 +   );
14852 +
14853 +   return openssl_session;
14854 +}
14855 +
14856 +pkcs11h_hook_openssl_cleanup_t
14857 +pkcs11h_openssl_getCleanupHook (
14858 +   IN const pkcs11h_openssl_session_t openssl_session
14859 +) {
14860 +   PKCS11H_ASSERT (openssl_session!=NULL);
14861 +
14862 +   return openssl_session->cleanup_hook;
14863 +}
14864 +
14865 +void
14866 +pkcs11h_openssl_setCleanupHook (
14867 +   IN const pkcs11h_openssl_session_t openssl_session,
14868 +   IN const pkcs11h_hook_openssl_cleanup_t cleanup
14869 +) {
14870 +   PKCS11H_ASSERT (openssl_session!=NULL);
14871 +
14872 +   openssl_session->cleanup_hook = cleanup;
14873 +}
14874 +
14875 +void
14876 +pkcs11h_openssl_freeSession (
14877 +   IN const pkcs11h_openssl_session_t openssl_session
14878 +) {
14879 +   PKCS11H_ASSERT (openssl_session!=NULL);
14880 +   PKCS11H_ASSERT (openssl_session->reference_count>0);
14881 +   
14882 +   PKCS11H_DEBUG (
14883 +       PKCS11H_LOG_DEBUG2,
14884 +       "PKCS#11: pkcs11h_openssl_freeSession - entry openssl_session=%p, count=%d",
14885 +       (void *)openssl_session,
14886 +       openssl_session->reference_count
14887 +   );
14888 +
14889 +   openssl_session->reference_count--;
14890 +   
14891 +   if (openssl_session->reference_count == 0) {
14892 +       if (openssl_session->cleanup_hook != NULL) {
14893 +           openssl_session->cleanup_hook (openssl_session->certificate);
14894 +       }
14895 +
14896 +       if (openssl_session->x509 != NULL) {
14897 +           X509_free (openssl_session->x509);
14898 +           openssl_session->x509 = NULL;
14899 +       }
14900 +       if (openssl_session->certificate != NULL) {
14901 +           pkcs11h_certificate_freeCertificate (openssl_session->certificate);
14902 +           openssl_session->certificate = NULL;
14903 +       }
14904 +       
14905 +       _pkcs11h_mem_free ((void *)&openssl_session);
14906 +   }
14907 +
14908 +   PKCS11H_DEBUG (
14909 +       PKCS11H_LOG_DEBUG2,
14910 +       "PKCS#11: pkcs11h_openssl_freeSession - return"
14911 +   );
14912 +}
14913 +
14914 +RSA *
14915 +pkcs11h_openssl_session_getRSA (
14916 +   IN const pkcs11h_openssl_session_t openssl_session
14917 +) {
14918 +   X509 *x509 = NULL;
14919 +   RSA *rsa = NULL;
14920 +   EVP_PKEY *pubkey = NULL;
14921 +   PKCS11H_BOOL ok = TRUE;
14922 +
14923 +   PKCS11H_ASSERT (openssl_session!=NULL);
14924 +   PKCS11H_ASSERT (!openssl_session->initialized);
14925 +   PKCS11H_ASSERT (openssl_session!=NULL);
14926 +
14927 +   PKCS11H_DEBUG (
14928 +       PKCS11H_LOG_DEBUG2,
14929 +       "PKCS#11: pkcs11h_openssl_session_getRSA - entry openssl_session=%p",
14930 +       (void *)openssl_session
14931 +   );
14932 +   
14933 +   /*
14934 +    * Dup x509 so RSA will not hold session x509
14935 +    */
14936 +   if (
14937 +       ok &&
14938 +       (x509 = pkcs11h_openssl_session_getX509 (openssl_session)) == NULL
14939 +   ) {
14940 +       ok = FALSE;
14941 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get certificate object");
14942 +   }
14943 +
14944 +   if (
14945 +       ok &&
14946 +       (pubkey = X509_get_pubkey (x509)) == NULL
14947 +   ) {
14948 +       ok = FALSE;
14949 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get public key");
14950 +   }
14951 +   
14952 +   if (
14953 +       ok &&
14954 +       pubkey->type != EVP_PKEY_RSA
14955 +   ) {
14956 +       ok = FALSE;
14957 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Invalid public key algorithm");
14958 +   }
14959 +
14960 +   if (
14961 +       ok &&
14962 +       (rsa = EVP_PKEY_get1_RSA (pubkey)) == NULL
14963 +   ) {
14964 +       ok = FALSE;
14965 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get RSA key");
14966 +   }
14967 +
14968 +   if (ok) {
14969 +       RSA_set_method (rsa, &openssl_session->smart_rsa);
14970 +       RSA_set_app_data (rsa, openssl_session);
14971 +       openssl_session->reference_count++;
14972 +   }
14973 +   
14974 +#ifdef BROKEN_OPENSSL_ENGINE
14975 +   if (ok) {
14976 +       if (!rsa->engine) {
14977 +           rsa->engine = ENGINE_get_default_RSA();
14978 +       }
14979 +
14980 +       ENGINE_set_RSA(ENGINE_get_default_RSA(), &openssl_session->smart_rsa);
14981 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: OpenSSL engine support is broken! Workaround enabled");
14982 +   }
14983 +#endif
14984 +       
14985 +   if (ok) {
14986 +       rsa->flags |= RSA_FLAG_SIGN_VER;
14987 +       openssl_session->initialized = TRUE;
14988 +   }
14989 +   else {
14990 +       if (rsa != NULL) {
14991 +           RSA_free (rsa);
14992 +           rsa = NULL;
14993 +       }
14994 +   }
14995 +
14996 +   /*
14997 +    * openssl objects have reference
14998 +    * count, so release them
14999 +    */
15000 +   if (pubkey != NULL) {
15001 +       EVP_PKEY_free (pubkey);
15002 +       pubkey = NULL;
15003 +   }
15004 +
15005 +   if (x509 != NULL) {
15006 +       X509_free (x509);
15007 +       x509 = NULL;
15008 +   }
15009 +   
15010 +   PKCS11H_DEBUG (
15011 +       PKCS11H_LOG_DEBUG2,
15012 +       "PKCS#11: pkcs11h_openssl_session_getRSA - return rsa=%p",
15013 +       (void *)rsa
15014 +   );
15015 +
15016 +   return rsa;
15017 +}
15018 +
15019 +X509 *
15020 +pkcs11h_openssl_session_getX509 (
15021 +   IN const pkcs11h_openssl_session_t openssl_session
15022 +) {
15023 +   X509 *x509 = NULL;
15024 +   PKCS11H_BOOL ok = TRUE;
15025 +   
15026 +   PKCS11H_ASSERT (openssl_session!=NULL);
15027 +
15028 +   PKCS11H_DEBUG (
15029 +       PKCS11H_LOG_DEBUG2,
15030 +       "PKCS#11: pkcs11h_openssl_session_getX509 - entry openssl_session=%p",
15031 +       (void *)openssl_session
15032 +   );
15033 +
15034 +   if (
15035 +       ok &&
15036 +       openssl_session->x509 == NULL &&
15037 +       (openssl_session->x509 = pkcs11h_openssl_getX509 (openssl_session->certificate)) == NULL
15038 +   ) { 
15039 +       ok = FALSE;
15040 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot get certificate object");
15041 +   }
15042 +
15043 +   if (
15044 +       ok &&
15045 +       (x509 = X509_dup (openssl_session->x509)) == NULL
15046 +   ) {
15047 +       ok = FALSE;
15048 +       PKCS11H_LOG (PKCS11H_LOG_WARN, "PKCS#11: Cannot duplicate certificate object");
15049 +   }
15050 +   
15051 +   PKCS11H_DEBUG (
15052 +       PKCS11H_LOG_DEBUG2,
15053 +       "PKCS#11: pkcs11h_openssl_session_getX509 - return x509=%p",
15054 +       (void *)x509
15055 +   );
15056 +
15057 +   return x509;
15058 +}
15059 +
15060 +#endif             /* ENABLE_PKCS11H_OPENSSL */
15061 +
15062 +#if defined(ENABLE_PKCS11H_STANDALONE)
15063 +/*======================================================================*
15064 + * STANDALONE INTERFACE
15065 + *======================================================================*/
15066 +
15067 +void
15068 +pkcs11h_standalone_dump_slots (
15069 +   IN const pkcs11h_output_print_t my_output,
15070 +   IN void * const global_data,
15071 +   IN const char * const provider
15072 +) {
15073 +   CK_RV rv = CKR_OK;
15074 +
15075 +   pkcs11h_provider_t pkcs11h_provider;
15076 +
15077 +   PKCS11H_ASSERT (my_output!=NULL);
15078 +   /*PKCS11H_ASSERT (global_data) NOT NEEDED */
15079 +   PKCS11H_ASSERT (provider!=NULL);
15080 +
15081 +   if (
15082 +       rv == CKR_OK &&
15083 +       (rv = pkcs11h_initialize ()) != CKR_OK
15084 +   ) {
15085 +       my_output (global_data, "PKCS#11: Cannot initialize interface %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15086 +   }
15087 +
15088 +   if (
15089 +       rv == CKR_OK &&
15090 +       (rv = pkcs11h_addProvider (
15091 +           provider,
15092 +           provider,
15093 +           FALSE,
15094 +           (
15095 +               PKCS11H_SIGNMODE_MASK_SIGN |
15096 +               PKCS11H_SIGNMODE_MASK_RECOVER
15097 +           ),
15098 +           PKCS11H_SLOTEVENT_METHOD_AUTO,
15099 +           0,
15100 +           FALSE
15101 +       )) != CKR_OK
15102 +   ) {
15103 +       my_output (global_data, "PKCS#11: Cannot initialize provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15104 +   }
15105 +
15106 +   /*
15107 +    * our provider is head
15108 +    */
15109 +   if (rv == CKR_OK) {
15110 +       pkcs11h_provider = s_pkcs11h_data->providers;
15111 +       if (pkcs11h_provider == NULL || !pkcs11h_provider->enabled) {
15112 +           my_output (global_data, "PKCS#11: Cannot get provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15113 +           rv = CKR_GENERAL_ERROR;
15114 +       }
15115 +   }
15116 +
15117 +   if (rv == CKR_OK) {
15118 +       CK_INFO info;
15119 +       
15120 +       if ((rv = pkcs11h_provider->f->C_GetInfo (&info)) != CKR_OK) {
15121 +           my_output (global_data, "PKCS#11: Cannot get PKCS#11 provider information %ld-'%s'\n", rv,
	pkcs11h_getMessage (rv));
15122 +           rv = CKR_OK;
15123 +       }
15124 +       else {
15125 +           char manufacturerID[sizeof (info.manufacturerID)+1];
15126 +   
15127 +           _pkcs11h_util_fixupFixedString (
15128 +               manufacturerID,
15129 +               (char *)info.manufacturerID,
15130 +               sizeof (info.manufacturerID)
15131 +           );
15132 +   
15133 +           my_output (
15134 +               global_data,
15135 +               (
15136 +                   "Provider Information:\n"
15137 +                   "\tcryptokiVersion:\t%u.%u\n"
15138 +                   "\tmanufacturerID:\t\t%s\n"
15139 +                   "\tflags:\t\t\t%08x\n"
15140 +                   "\n"
15141 +               ),
15142 +               info.cryptokiVersion.major,
15143 +               info.cryptokiVersion.minor,
15144 +               manufacturerID,
15145 +               (unsigned)info.flags
15146 +           );
15147 +       }
15148 +   }
15149 +   
15150 +   if (rv == CKR_OK) {
15151 +       CK_SLOT_ID_PTR slots = NULL;
15152 +       CK_ULONG slotnum;
15153 +       CK_SLOT_ID slot_index;
15154 +       
15155 +       if (
15156 +            _pkcs11h_session_getSlotList (
15157 +               pkcs11h_provider,
15158 +               CK_FALSE,
15159 +               &slots,
15160 +               &slotnum
15161 +           ) != CKR_OK
15162 +       ) {
15163 +           my_output (global_data, "PKCS#11: Cannot get slot list %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15164 +       }
15165 +       else {
15166 +           my_output (
15167 +               global_data,
15168 +               "The following slots are available for use with this provider.\n"
15169 +           );
15170 +
15171 +#if defined(PKCS11H_PRM_SLOT_TYPE)
15172 +           my_output (
15173 +               global_data,
15174 +               (
15175 +                   "Each slot shown below may be used as a parameter to a\n"
15176 +                   "%s and %s options.\n"
15177 +               ),
15178 +               PKCS11H_PRM_SLOT_TYPE,
15179 +               PKCS11H_PRM_SLOT_ID
15180 +           );
15181 +#endif
15182 +
15183 +           my_output (
15184 +               global_data,
15185 +               (
15186 +                   "\n"
15187 +                   "Slots: (id - name)\n"
15188 +               )
15189 +           );
15190 +
15191 +           for (slot_index=0;slot_index < slotnum;slot_index++) {
15192 +               CK_SLOT_INFO info;
15193 +   
15194 +               if (
15195 +                   (rv = pkcs11h_provider->f->C_GetSlotInfo (
15196 +                       slots[slot_index],
15197 +                       &info
15198 +                   )) == CKR_OK
15199 +               ) {
15200 +                   char current_name[sizeof (info.slotDescription)+1];
15201 +               
15202 +                   _pkcs11h_util_fixupFixedString (
15203 +                       current_name,
15204 +                       (char *)info.slotDescription,
15205 +                       sizeof (info.slotDescription)
15206 +                   );
15207 +   
15208 +                   my_output (global_data, "\t%lu - %s\n", slots[slot_index], current_name);
15209 +               }
15210 +           }
15211 +       }
15212 +
15213 +       if (slots != NULL) {
15214 +           _pkcs11h_mem_free ((void *)&slots);
15215 +       }
15216 +   }
15217 +   
15218 +   pkcs11h_terminate ();
15219 +}
15220 +
15221 +static
15222 +PKCS11H_BOOL
15223 +_pkcs11h_standalone_dump_objects_pin_prompt (
15224 +   IN void * const global_data,
15225 +   IN void * const user_data,
15226 +   IN const pkcs11h_token_id_t token,
15227 +   IN const unsigned retry,
15228 +   OUT char * const pin,
15229 +   IN const size_t pin_max
15230 +) {
15231 +   (void)user_data;
15232 +   (void)token;
15233 +
15234 +   /*
15235 +    * Don't lock card
15236 +    */
15237 +   if (retry == 0) {
15238 +       strncpy (pin, (char *)global_data, pin_max);
15239 +       return TRUE;
15240 +   }
15241 +   else {
15242 +       return FALSE;
15243 +   }
15244 +}
15245 +
15246 +void
15247 +_pkcs11h_standalone_dump_objects_hex (
15248 +   IN const unsigned char * const p,
15249 +   IN const size_t p_size,
15250 +   OUT char * const sz,
15251 +   IN const size_t max,
15252 +   IN const char * const prefix
15253 +) {
15254 +   size_t j;
15255 +
15256 +   sz[0] = '\0';
15257 +
15258 +   for (j=0;j<p_size;j+=16) {
15259 +       char line[3*16+1];
15260 +       size_t k;
15261 +
15262 +       line[0] = '\0';
15263 +       for (k=0;k<16 && j+k<p_size;k++) {
15264 +           sprintf (line+strlen (line), "%02x ", p[j+k]);
15265 +       }
15266 +
15267 +       strncat (
15268 +           sz,
15269 +           prefix,
15270 +           max-1-strlen (sz)
15271 +       );
15272 +       strncat (
15273 +           sz,
15274 +           line,
15275 +           max-1-strlen (sz)
15276 +       );
15277 +       strncat (
15278 +           sz,
15279 +           "\n",
15280 +           max-1-strlen (sz)
15281 +       );
15282 +   }
15283 +
15284 +   sz[max-1] = '\0';
15285 +}
15286 +   
15287 +void
15288 +pkcs11h_standalone_dump_objects (
15289 +   IN const pkcs11h_output_print_t my_output,
15290 +   IN void * const global_data,
15291 +   IN const char * const provider,
15292 +   IN const char * const slot,
15293 +   IN const char * const pin
15294 +) {
15295 +   CK_SLOT_ID s;
15296 +   CK_RV rv = CKR_OK;
15297 +
15298 +   pkcs11h_provider_t pkcs11h_provider = NULL;
15299 +   pkcs11h_token_id_t token_id = NULL;
15300 +   pkcs11h_session_t session = NULL;
15301 +
15302 +   PKCS11H_ASSERT (my_output!=NULL);
15303 +   /*PKCS11H_ASSERT (global_data) NOT NEEDED */
15304 +   PKCS11H_ASSERT (provider!=NULL);
15305 +   PKCS11H_ASSERT (slot!=NULL);
15306 +   PKCS11H_ASSERT (pin!=NULL);
15307 +
15308 +   s = atoi (slot);
15309 +
15310 +   if (
15311 +       rv == CKR_OK &&
15312 +       (rv = pkcs11h_initialize ()) != CKR_OK
15313 +   ) {
15314 +       my_output (global_data, "PKCS#11: Cannot initialize interface %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15315 +   }
15316 +
15317 +   if (
15318 +       rv == CKR_OK &&
15319 +       (rv = pkcs11h_setPINPromptHook (_pkcs11h_standalone_dump_objects_pin_prompt, (void *)pin)) != CKR_OK
15320 +   ) {
15321 +       my_output (global_data, "PKCS#11: Cannot set hooks %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15322 +   }
15323 +
15324 +   if (
15325 +       rv == CKR_OK &&
15326 +       (rv = pkcs11h_addProvider (
15327 +           provider,
15328 +           provider,
15329 +           FALSE,
15330 +           (
15331 +               PKCS11H_SIGNMODE_MASK_SIGN |
15332 +               PKCS11H_SIGNMODE_MASK_RECOVER
15333 +           ),
15334 +           PKCS11H_SLOTEVENT_METHOD_AUTO,
15335 +           0,
15336 +           FALSE
15337 +       )) != CKR_OK
15338 +   ) {
15339 +       my_output (global_data, "PKCS#11: Cannot initialize provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15340 +   }
15341 +
15342 +   /*
15343 +    * our provider is head
15344 +    */
15345 +   if (rv == CKR_OK) {
15346 +       pkcs11h_provider = s_pkcs11h_data->providers;
15347 +       if (pkcs11h_provider == NULL || !pkcs11h_provider->enabled) {
15348 +           my_output (global_data, "PKCS#11: Cannot get provider %ld-'%s'\n", rv, pkcs11h_getMessage (rv));
15349 +           rv = CKR_GENERAL_ERROR;
15350 +       }
15351 +   }
15352 +
15353 +   if (rv == CKR_OK) {
15354 +       CK_TOKEN_INFO info;
15355 +       
15356 +       if (
15357 +           (rv = pkcs11h_provider->f->C_GetTokenInfo (
15358 +               s,
15359 +               &info
15360 +           )) != CKR_OK
15361 +       ) {
15362 +           my_output (global_data, "PKCS#11: Cannot get token information for slot %ld %ld-'%s'\n", s, rv,
	pkcs11h_getMessage (rv));
15363 +           /* Ignore this error */
15364 +           rv = CKR_OK;
15365 +       }
15366 +       else {
15367 +           char label[sizeof (info.label)+1];
15368 +           char manufacturerID[sizeof (info.manufacturerID)+1];
15369 +           char model[sizeof (info.model)+1];
15370 +           char serialNumberNumber[sizeof (info.serialNumber)+1];
15371 +           
15372 +           _pkcs11h_util_fixupFixedString (
15373 +               label,
15374 +               (char *)info.label,
15375 +               sizeof (info.label)
15376 +           );
15377 +           _pkcs11h_util_fixupFixedString (
15378 +               manufacturerID,
15379 +               (char *)info.manufacturerID,
15380 +               sizeof (info.manufacturerID)
15381 +           );
15382 +           _pkcs11h_util_fixupFixedString (
15383 +               model,
15384 +               (char *)info.model,
15385 +               sizeof (info.model)
15386 +           );
15387 +           _pkcs11h_util_fixupFixedString (
15388 +               serialNumberNumber,
15389 +               (char *)info.serialNumber,
15390 +               sizeof (info.serialNumber)
15391 +           );
15392 +   
15393 +           my_output (
15394 +               global_data,
15395 +               (
15396 +                   "Token Information:\n"
15397 +                   "\tlabel:\t\t%s\n"
15398 +                   "\tmanufacturerID:\t%s\n"
15399 +                   "\tmodel:\t\t%s\n"
15400 +                   "\tserialNumber:\t%s\n"
15401 +                   "\tflags:\t\t%08x\n"
15402 +                   "\n"
15403 +               ),
15404 +               label,
15405 +               manufacturerID,
15406 +               model,
15407 +               serialNumberNumber,
15408 +               (unsigned)info.flags
15409 +           );
15410 +
15411 +#if defined(PKCS11H_PRM_SLOT_TYPE)
15412 +           my_output (
15413 +               global_data,
15414 +               (
15415 +                   "You can access this token using\n"
15416 +                   "%s \"label\" %s \"%s\" options.\n"
15417 +                   "\n"
15418 +               ),
15419 +               PKCS11H_PRM_SLOT_TYPE,
15420 +               PKCS11H_PRM_SLOT_ID,
15421 +               label
15422 +           );
15423 +#endif
15424 +
15425 +           if (
15426 +               rv == CKR_OK &&
15427 +               (rv = _pkcs11h_token_getTokenId (
15428 +                   &info,
15429 +                   &token_id
15430 +               )) != CKR_OK
15431 +           ) {
15432 +               my_output (global_data, "PKCS#11: Cannot get token id for slot %ld %ld-'%s'\n", s, rv,
	pkcs11h_getMessage (rv));        
15433 +               rv = CKR_OK;
15434 +           }
15435 +       }
15436 +   }
15437 +
15438 +   if (token_id != NULL) {
15439 +       if (
15440 +           (rv = _pkcs11h_session_getSessionByTokenId (
15441 +               token_id,
15442 +               &session
15443 +           )) != CKR_OK
15444 +       ) {
15445 +           my_output (global_data, "PKCS#11: Cannot session for token '%s' %ld-'%s'\n", token_id->display, rv,
	pkcs11h_getMessage (rv));       
15446 +           rv = CKR_OK;
15447 +       }
15448 +   }
15449 +
15450 +   if (session != NULL) {
15451 +       CK_OBJECT_HANDLE *objects = NULL;
15452 +       CK_ULONG objects_found = 0;
15453 +       CK_ULONG i;
15454 +
15455 +       if (
15456 +           (rv = _pkcs11h_session_login (
15457 +               session,
15458 +               FALSE,
15459 +               TRUE,
15460 +               NULL,
15461 +               PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT
15462 +           )) != CKR_OK
15463 +       ) {
15464 +           my_output (global_data, "PKCS#11: Cannot open session to token '%s' %ld-'%s'\n", session->token_id->display,
	rv, pkcs11h_getMessage (rv));
15465 +       }
15466 +   
15467 +       my_output (
15468 +           global_data,
15469 +           "The following objects are available for use with this token.\n"
15470 +       );
15471 +
15472 +#if defined(PKCS11H_PRM_OBJ_TYPE)
15473 +       my_output (
15474 +           global_data,
15475 +           (
15476 +               "Each object shown below may be used as a parameter to\n"
15477 +               "%s and %s options.\n"
15478 +           ),
15479 +           PKCS11H_PRM_OBJ_TYPE,
15480 +           PKCS11H_PRM_OBJ_ID
15481 +       );
15482 +#endif
15483 +
15484 +       my_output (
15485 +           global_data,
15486 +           "\n"
15487 +       );
15488 +
15489 +       if (
15490 +           rv == CKR_OK &&
15491 +           (rv = _pkcs11h_session_findObjects (
15492 +               session,
15493 +               NULL,
15494 +               0,
15495 +               &objects,
15496 +               &objects_found
15497 +           )) != CKR_OK
15498 +       ) {
15499 +           my_output (global_data, "PKCS#11: Cannot query objects for token '%s' %ld-'%s'\n",
	session->token_id->display, rv, pkcs11h_getMessage (rv));
15500 +       }
15501 +   
15502 +       for (i=0;rv == CKR_OK && i < objects_found;i++) {
15503 +           CK_OBJECT_CLASS attrs_class = 0;
15504 +           CK_ATTRIBUTE attrs[] = {
15505 +               {CKA_CLASS, &attrs_class, sizeof (attrs_class)}
15506 +           };
15507 +
15508 +           if (
15509 +               _pkcs11h_session_getObjectAttributes (
15510 +                   session,
15511 +                   objects[i],
15512 +                   attrs,
15513 +                   sizeof (attrs) / sizeof (CK_ATTRIBUTE)
15514 +               ) == CKR_OK
15515 +           ) {
15516 +               if (attrs_class == CKO_CERTIFICATE) {
15517 +                   CK_ATTRIBUTE attrs_cert[] = {
15518 +                       {CKA_ID, NULL, 0},
15519 +                       {CKA_LABEL, NULL, 0},
15520 +                       {CKA_VALUE, NULL, 0}
15521 +                   };
15522 +                   unsigned char *attrs_id = NULL;
15523 +                   int attrs_id_size = 0;
15524 +                   unsigned char *attrs_value = NULL;
15525 +                   int attrs_value_size = 0;
15526 +                   char *attrs_label = NULL;
15527 +                   char hex_id[1024];
15528 +                   char subject[1024];
15529 +                   char serialNumber[1024];
15530 +                   time_t notAfter = 0;
15531 +
15532 +                   subject[0] = '\0';
15533 +                   serialNumber[0] = '\0';
15534 +
15535 +
15536 +                   if (
15537 +                       _pkcs11h_session_getObjectAttributes (
15538 +                           session,
15539 +                           objects[i],
15540 +                           attrs_cert,
15541 +                           sizeof (attrs_cert) / sizeof (CK_ATTRIBUTE)
15542 +                       ) == CKR_OK &&
15543 +                       _pkcs11h_mem_malloc (
15544 +                           (void *)&attrs_label,
15545 +                           attrs_cert[1].ulValueLen+1
15546 +                       ) == CKR_OK
15547 +                   ) {
15548 +                       attrs_id = (unsigned char *)attrs_cert[0].pValue;
15549 +                       attrs_id_size = attrs_cert[0].ulValueLen;
15550 +                       attrs_value = (unsigned char *)attrs_cert[2].pValue;
15551 +                       attrs_value_size = attrs_cert[2].ulValueLen;
15552 +
15553 +                       memset (attrs_label, 0, attrs_cert[1].ulValueLen+1);
15554 +                       memmove (attrs_label, attrs_cert[1].pValue, attrs_cert[1].ulValueLen);
15555 +                       _pkcs11h_standalone_dump_objects_hex (
15556 +                           attrs_id,
15557 +                           attrs_id_size,
15558 +                           hex_id,
15559 +                           sizeof (hex_id),
15560 +                           "\t\t"
15561 +                       );
15562 +                   }
15563 +
15564 +                   if (attrs_value != NULL) {
15565 +#if defined(USE_PKCS11H_OPENSSL)
15566 +                       X509 *x509 = NULL;
15567 +                       BIO *bioSerial = NULL;
15568 +#elif defined(USE_PKCS11H_GNUTLS)
15569 +                       gnutls_x509_crt_t cert = NULL;
15570 +#endif
15571 +
15572 +                       _pkcs11h_certificate_getDN (
15573 +                           attrs_value,
15574 +                           attrs_value_size,
15575 +                           subject,
15576 +                           sizeof (subject)
15577 +                       );
15578 +                       notAfter = _pkcs11h_certificate_getExpiration (
15579 +                           attrs_value,
15580 +                           attrs_value_size
15581 +                       );
15582 +#if defined(USE_PKCS11H_OPENSSL)
15583 +                       if ((x509 = X509_new ()) == NULL) {
15584 +                           my_output (global_data, "Cannot create x509 context\n");
15585 +                       }
15586 +                       else {
15587 +                           pkcs11_openssl_d2i_t d2i1 = (pkcs11_openssl_d2i_t)attrs_value;
15588 +                           if (d2i_X509 (&x509, &d2i1, attrs_value_size)) {
15589 +                               if ((bioSerial = BIO_new (BIO_s_mem ())) == NULL) {
15590 +                                   my_output (global_data, "Cannot create BIO context\n");
15591 +                               }
15592 +                               else {
15593 +                                   int n;
15594 +
15595 +                                   i2a_ASN1_INTEGER(bioSerial, X509_get_serialNumber (x509));
15596 +                                   n = BIO_read (bioSerial, serialNumber, sizeof (serialNumber)-1);
15597 +                                   if (n<0) {
15598 +                                       serialNumber[0] = '\0';
15599 +                                   }
15600 +                                   else {
15601 +                                       serialNumber[n] = '\0';
15602 +                                   }
15603 +                               }
15604 +                           }
15605 +                       }
15606 +
15607 +
15608 +                       if (bioSerial != NULL) {
15609 +                           BIO_free_all (bioSerial);
15610 +                           bioSerial = NULL;
15611 +                       }
15612 +                       if (x509 != NULL) {
15613 +                           X509_free (x509);
15614 +                           x509 = NULL;
15615 +                       }
15616 +#elif defined(USE_PKCS11H_GNUTLS)
15617 +                       if (gnutls_x509_crt_init (&cert) == GNUTLS_E_SUCCESS) {
15618 +                           gnutls_datum_t datum = {attrs_value, attrs_value_size};
15619 +
15620 +                           if (gnutls_x509_crt_import (cert, &datum, GNUTLS_X509_FMT_DER) == GNUTLS_E_SUCCESS) {
15621 +                               unsigned char ser[1024];
15622 +                               size_t ser_size = sizeof (ser);
15623 +                               if (gnutls_x509_crt_get_serial (cert, ser, &ser_size) == GNUTLS_E_SUCCESS) {
15624 +                                   _pkcs11h_util_binaryToHex (
15625 +                                       serialNumber,
15626 +                                       sizeof (serialNumber),
15627 +                                       ser,
15628 +                                       ser_size
15629 +                                   );
15630 +                               }
15631 +                           }
15632 +                           gnutls_x509_crt_deinit (cert);
15633 +                       }
15634 +#else
15635 +#error Invalid configuration.
15636 +#endif
15637 +                   }
15638 +
15639 +                   my_output (
15640 +                       global_data,
15641 +                       (
15642 +                           "Object\n"
15643 +                           "\tType:\t\t\tCertificate\n"
15644 +                           "\tCKA_ID:\n"
15645 +                           "%s"
15646 +                           "\tCKA_LABEL:\t\t%s\n"
15647 +                           "\tsubject:\t\t%s\n"
15648 +                           "\tserialNumber:\t\t%s\n"
15649 +                           "\tnotAfter:\t\t%s\n"
15650 +                       ),
15651 +                       hex_id,
15652 +                       attrs_label,
15653 +                       subject,
15654 +                       serialNumber,
15655 +                       asctime (localtime (&notAfter))
15656 +                   );
15657 +
15658 +                   _pkcs11h_mem_free ((void *)&attrs_label);
15659 +
15660 +                   _pkcs11h_session_freeObjectAttributes (
15661 +                       attrs_cert,
15662 +                       sizeof (attrs_cert) / sizeof (CK_ATTRIBUTE)
15663 +                   );
15664 +               }
15665 +               else if (attrs_class == CKO_PRIVATE_KEY) {
15666 +                   CK_BBOOL sign_recover = CK_FALSE;
15667 +                   CK_BBOOL sign = CK_FALSE;
15668 +                   CK_ATTRIBUTE attrs_key[] = {
15669 +                       {CKA_SIGN, &sign, sizeof (sign)},
15670 +                       {CKA_SIGN_RECOVER, &sign_recover, sizeof (sign_recover)}
15671 +                   };
15672 +                   CK_ATTRIBUTE attrs_key_common[] = {
15673 +                       {CKA_ID, NULL, 0},
15674 +                       {CKA_LABEL, NULL, 0}
15675 +                   };
15676 +                   unsigned char *attrs_id = NULL;
15677 +                   int attrs_id_size = 0;
15678 +                   char *attrs_label = NULL;
15679 +                   char hex_id[1024];
15680 +
15681 +                   pkcs11h_provider->f->C_GetAttributeValue (
15682 +                       session->session_handle,
15683 +                       objects[i],
15684 +                       attrs_key,
15685 +                       sizeof (attrs_key) / sizeof (CK_ATTRIBUTE)
15686 +                   );
15687 +
15688 +                   if (
15689 +                       _pkcs11h_session_getObjectAttributes (
15690 +                           session,
15691 +                           objects[i],
15692 +                           attrs_key_common,
15693 +                           sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
15694 +                       ) == CKR_OK &&
15695 +                       _pkcs11h_mem_malloc (
15696 +                           (void *)&attrs_label,
15697 +                           attrs_key_common[1].ulValueLen+1
15698 +                       ) == CKR_OK
15699 +                   ) {
15700 +                       attrs_id = (unsigned char *)attrs_key_common[0].pValue;
15701 +                       attrs_id_size = attrs_key_common[0].ulValueLen;
15702 +
15703 +                       memset (attrs_label, 0, attrs_key_common[1].ulValueLen+1);
15704 +                       memmove (attrs_label, attrs_key_common[1].pValue, attrs_key_common[1].ulValueLen);
15705 +
15706 +                       _pkcs11h_standalone_dump_objects_hex (
15707 +                           attrs_id,
15708 +                           attrs_id_size,
15709 +                           hex_id,
15710 +                           sizeof (hex_id),
15711 +                           "\t\t"
15712 +                       );
15713 +                           
15714 +                   }
15715 +
15716 +                   my_output (
15717 +                       global_data,
15718 +                       (
15719 +                           "Object\n"
15720 +                           "\tType:\t\t\tPrivate Key\n"
15721 +                           "\tCKA_ID:\n"
15722 +                           "%s"
15723 +                           "\tCKA_LABEL:\t\t%s\n"
15724 +                           "\tCKA_SIGN:\t\t%s\n"
15725 +                           "\tCKA_SIGN_RECOVER:\t%s\n"
15726 +                       ),
15727 +                       hex_id,
15728 +                       attrs_label,
15729 +                       sign ? "TRUE" : "FALSE",
15730 +                       sign_recover ? "TRUE" : "FALSE"
15731 +                   );
15732 +
15733 +                   _pkcs11h_mem_free ((void *)&attrs_label);
15734 +
15735 +                   _pkcs11h_session_freeObjectAttributes (
15736 +                       attrs_key_common,
15737 +                       sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
15738 +                   );
15739 +               }
15740 +               else if (attrs_class == CKO_PUBLIC_KEY) {
15741 +                   CK_ATTRIBUTE attrs_key_common[] = {
15742 +                       {CKA_ID, NULL, 0},
15743 +                       {CKA_LABEL, NULL, 0}
15744 +                   };
15745 +                   unsigned char *attrs_id = NULL;
15746 +                   int attrs_id_size = 0;
15747 +                   char *attrs_label = NULL;
15748 +                   char hex_id[1024];
15749 +
15750 +                   if (
15751 +                       _pkcs11h_session_getObjectAttributes (
15752 +                           session,
15753 +                           objects[i],
15754 +                           attrs_key_common,
15755 +                           sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
15756 +                       ) == CKR_OK &&
15757 +                       _pkcs11h_mem_malloc (
15758 +                           (void *)&attrs_label,
15759 +                           attrs_key_common[1].ulValueLen+1
15760 +                       ) == CKR_OK
15761 +                   ) {
15762 +                       attrs_id = (unsigned char *)attrs_key_common[0].pValue;
15763 +                       attrs_id_size = attrs_key_common[0].ulValueLen;
15764 +
15765 +                       memset (attrs_label, 0, attrs_key_common[1].ulValueLen+1);
15766 +                       memmove (attrs_label, attrs_key_common[1].pValue, attrs_key_common[1].ulValueLen);
15767 +
15768 +                       _pkcs11h_standalone_dump_objects_hex (
15769 +                           attrs_id,
15770 +                           attrs_id_size,
15771 +                           hex_id,
15772 +                           sizeof (hex_id),
15773 +                           "\t\t"
15774 +                       );
15775 +                           
15776 +                   }
15777 +
15778 +                   my_output (
15779 +                       global_data,
15780 +                       (
15781 +                           "Object\n"
15782 +                           "\tType:\t\t\tPublic Key\n"
15783 +                           "\tCKA_ID:\n"
15784 +                           "%s"
15785 +                           "\tCKA_LABEL:\t\t%s\n"
15786 +                       ),
15787 +                       hex_id,
15788 +                       attrs_label
15789 +                   );
15790 +
15791 +                   _pkcs11h_mem_free ((void *)&attrs_label);
15792 +
15793 +                   _pkcs11h_session_freeObjectAttributes (
15794 +                       attrs_key_common,
15795 +                       sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
15796 +                   );
15797 +               }
15798 +               else if (attrs_class == CKO_DATA) {
15799 +                   CK_ATTRIBUTE attrs_key_common[] = {
15800 +                       {CKA_APPLICATION, NULL, 0},
15801 +                       {CKA_LABEL, NULL, 0}
15802 +                   };
15803 +                   char *attrs_application = NULL;
15804 +                   char *attrs_label = NULL;
15805 +
15806 +                   if (
15807 +                       _pkcs11h_session_getObjectAttributes (
15808 +                           session,
15809 +                           objects[i],
15810 +                           attrs_key_common,
15811 +                           sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
15812 +                       ) == CKR_OK &&
15813 +                       _pkcs11h_mem_malloc (
15814 +                           (void *)&attrs_application,
15815 +                           attrs_key_common[0].ulValueLen+1
15816 +                       ) == CKR_OK &&
15817 +                       _pkcs11h_mem_malloc (
15818 +                           (void *)&attrs_label,
15819 +                           attrs_key_common[1].ulValueLen+1
15820 +                       ) == CKR_OK
15821 +                   ) {
15822 +                       memset (attrs_application, 0, attrs_key_common[0].ulValueLen+1);
15823 +                       memmove (attrs_application, attrs_key_common[0].pValue, attrs_key_common[0].ulValueLen);
15824 +                       memset (attrs_label, 0, attrs_key_common[1].ulValueLen+1);
15825 +                       memmove (attrs_label, attrs_key_common[1].pValue, attrs_key_common[1].ulValueLen);
15826 +                   }
15827 +
15828 +                   my_output (
15829 +                       global_data,
15830 +                       (
15831 +                           "Object\n"
15832 +                           "\tType:\t\t\tData\n"
15833 +                           "\tCKA_APPLICATION\t\t%s\n"
15834 +                           "\tCKA_LABEL:\t\t%s\n"
15835 +                       ),
15836 +                       attrs_application,
15837 +                       attrs_label
15838 +                   );
15839 +
15840 +                   _pkcs11h_mem_free ((void *)&attrs_application);
15841 +                   _pkcs11h_mem_free ((void *)&attrs_label);
15842 +
15843 +                   _pkcs11h_session_freeObjectAttributes (
15844 +                       attrs_key_common,
15845 +                       sizeof (attrs_key_common) / sizeof (CK_ATTRIBUTE)
15846 +                   );
15847 +               }
15848 +               else {
15849 +                   my_output (
15850 +                       global_data,
15851 +                       (
15852 +                           "Object\n"
15853 +                           "\tType:\t\t\tUnsupported\n"
15854 +                       )
15855 +                   );
15856 +               }
15857 +           }
15858 +
15859 +           _pkcs11h_session_freeObjectAttributes (
15860 +               attrs,
15861 +               sizeof (attrs) / sizeof (CK_ATTRIBUTE)
15862 +           );
15863 +
15864 +           /*
15865 +            * Ignore any error and
15866 +            * perform next iteration
15867 +            */
15868 +           rv = CKR_OK;
15869 +       }
15870 +   
15871 +       if (objects != NULL) {
15872 +           _pkcs11h_mem_free ((void *)&objects);
15873 +       }
15874 +
15875 +       /*
15876 +        * Ignore this error
15877 +        */
15878 +       rv = CKR_OK;
15879 +   }
15880 +
15881 +   if (session != NULL) {
15882 +       _pkcs11h_session_release (session);
15883 +       session = NULL;
15884 +   }
15885 +
15886 +   if (token_id != NULL) {
15887 +       pkcs11h_token_freeTokenId (token_id);
15888 +       token_id = NULL;
15889 +   }
15890 +   
15891 +   pkcs11h_terminate ();
15892 +}
15893 +
15894 +#endif             /* ENABLE_PKCS11H_STANDALONE */
15895 +
15896 +#ifdef BROKEN_OPENSSL_ENGINE
15897 +static void broken_openssl_init() __attribute__ ((constructor));
15898 +static void  broken_openssl_init()
15899 +{
15900 +   SSL_library_init();
15901 +   ENGINE_load_openssl();
15902 +   ENGINE_register_all_RSA();
15903 +}
15904 +#endif
15905 +
15906 +#else
15907 +static void dummy (void) {}
15908 +#endif             /* PKCS11H_HELPER_ENABLE */
15909 +
15910 diff -urNp openssh-4.4p1/pkcs11-helper-config.h openssh-4.4p1+pkcs11-0.17/pkcs11-helper-config.h
15911 --- openssh-4.4p1/pkcs11-helper-config.h    1970-01-01 02:00:00.000000000 +0200
15912 +++ openssh-4.4p1+pkcs11-0.17/pkcs11-helper-config.h    2006-10-12 16:43:38.000000000 +0200
15913 @@ -0,0 +1,103 @@
15914 +/*
15915 + * Copyright (c) 2005-2006 Alon Bar-Lev.  All rights reserved.
15916 + *
15917 + * Redistribution and use in source and binary forms, with or without
15918 + * modification, are permitted provided that the following conditions
15919 + * are met:
15920 + * 1. Redistributions of source code must retain the above copyright
15921 + *    notice, this list of conditions and the following disclaimer.
15922 + * 2. Redistributions in binary form must reproduce the above copyright
15923 + *    notice, this list of conditions and the following disclaimer in the
15924 + *    documentation and/or other materials provided with the distribution.
15925 + *
15926 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15927 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15928 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
15929 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
15930 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15931 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15932 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
15933 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
15934 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
15935 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15936 + */
15937 +
15938 +#ifndef __PKCS11H_HELPER_CONFIG_H
15939 +#define __PKCS11H_HELPER_CONFIG_H
15940 +
15941 +#if !defined(PKCS11H_NO_NEED_INCLUDE_CONFIG)
15942 +
15943 +#include "includes.h"
15944 +
15945 +#endif /* PKCS11H_NO_NEED_INCLUDE_CONFIG */
15946 +
15947 +#ifndef SSH_PKCS11H_DISABLED
15948 +#define ENABLE_PKCS11H_HELPER
15949 +#endif
15950 +
15951 +#include <assert.h>
15952 +#include <string.h>
15953 +#include <ctype.h>
15954 +#if !defined(WIN32)
15955 +#include <unistd.h>
15956 +#include <dlfcn.h>
15957 +#endif
15958 +
15959 +#include "log.h"
15960 +#include "xmalloc.h"
15961 +#include "openssl/x509.h"
15962 +
15963 +#if defined(HAVE_CYGWIN)
15964 +#define PKCS11H_USE_CYGWIN
15965 +#endif
15966 +
15967 +#if !defined(FALSE)
15968 +#define FALSE 0
15969 +#endif
15970 +#if !defined(TRUE)
15971 +#define TRUE (!FALSE)
15972 +#endif
15973 +
15974 +typedef int PKCS11H_BOOL;
15975 +
15976 +#if !defined(IN)
15977 +#define IN
15978 +#endif
15979 +#if !defined(OUT)
15980 +#define OUT
15981 +#endif
15982 +
15983 +#define USE_PKCS11H_OPENSSL
15984 +#define ENABLE_PKCS11H_DEBUG
15985 +#undef  ENABLE_PKCS11H_THREADING
15986 +#undef  ENABLE_PKCS11H_TOKEN
15987 +#undef  ENABLE_PKCS11H_DATA
15988 +#define ENABLE_PKCS11H_CERTIFICATE
15989 +#undef  ENABLE_PKCS11H_LOCATE
15990 +#define ENABLE_PKCS11H_ENUM
15991 +#define ENABLE_PKCS11H_SERIALIZATION
15992 +#undef  ENABLE_PKCS11H_SLOTEVENT
15993 +#define ENABLE_PKCS11H_OPENSSL
15994 +#define ENABLE_PKCS11H_STANDALONE
15995 +
15996 +/*
15997 +#define PKCS11H_PRM_SLOT_TYPE  "--pkcs11-slot-type"
15998 +#define PKCS11H_PRM_SLOT_ID    "--pkcs11-slot"
15999 +#define PKCS11H_PRM_OBJ_TYPE   "--pkcs11-id-type"
16000 +#define PKCS11H_PRM_OBJ_ID "--pkcs11-id"
16001 +*/
16002 +
16003 +#define PKCS11H_ASSERT     assert
16004 +#define PKCS11H_TIME       time
16005 +#define PKCS11H_MALLOC     xmalloc
16006 +#define PKCS11H_FREE       xfree
16007 +
16008 +#ifdef ENABLE_PKCS11H_HELPER
16009 +#if defined(WIN32) || defined(PKCS11H_USE_CYGWIN)
16010 +#include "cryptoki-win32.h"
16011 +#else
16012 +#include "cryptoki.h"
16013 +#endif
16014 +
16015 +#endif     /* ENABLE_PKCS11H_HELPER */
16016 +#endif     /* __PKCS11H_HELPER_CONFIG_H */
16017 diff -urNp openssh-4.4p1/pkcs11-helper.h openssh-4.4p1+pkcs11-0.17/pkcs11-helper.h
16018 --- openssh-4.4p1/pkcs11-helper.h   1970-01-01 02:00:00.000000000 +0200
16019 +++ openssh-4.4p1+pkcs11-0.17/pkcs11-helper.h   2006-10-22 17:11:14.000000000 +0200
16020 @@ -0,0 +1,1303 @@
16021 +/*
16022 + * Copyright (c) 2005-2006 Alon Bar-Lev <alon.barlev@gmail.com>
16023 + * All rights reserved.
16024 + *
16025 + * This software is available to you under a choice of one of two
16026 + * licenses.  You may choose to be licensed under the terms of the GNU
16027 + * General Public License (GPL) Version 2, or the OpenIB.org BSD license.
16028 + *
16029 + * GNU General Public License (GPL) Version 2
16030 + * ===========================================
16031 + *  This program is free software; you can redistribute it and/or modify
16032 + *  it under the terms of the GNU General Public License version 2
16033 + *  as published by the Free Software Foundation.
16034 + *
16035 + *  This program is distributed in the hope that it will be useful,
16036 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16037 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16038 + *  GNU General Public License for more details.
16039 + *
16040 + *  You should have received a copy of the GNU General Public License
16041 + *  along with this program (see the file COPYING[.GPL2] included with this
16042 + *  distribution); if not, write to the Free Software Foundation, Inc.,
16043 + *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16044 + *
16045 + * OpenIB.org BSD license
16046 + * =======================
16047 + * Redistribution and use in source and binary forms, with or without modifi-
16048 + * cation, are permitted provided that the following conditions are met:
16049 + *
16050 + *   o  Redistributions of source code must retain the above copyright notice,
16051 + *      this list of conditions and the following disclaimer.
16052 + *
16053 + *   o  Redistributions in binary form must reproduce the above copyright no-
16054 + *      tice, this list of conditions and the following disclaimer in the do-
16055 + *      cumentation and/or other materials provided with the distribution.
16056 + *
16057 + *   o  The names of the contributors may not be used to endorse or promote
16058 + *      products derived from this software without specific prior written
16059 + *      permission.
16060 + *
16061 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16062 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
16063 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16064 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LI-
16065 + * ABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUEN-
16066 + * TIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
16067 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEV-
16068 + * ER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABI-
16069 + * LITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
16070 + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16071 + */
16072 +
16073 +/*
16074 + * The routines in this file deal with providing private key cryptography
16075 + * using RSA Security Inc. PKCS #11 Cryptographic Token Interface (Cryptoki).
16076 + *
16077 + */
16078 +
16079 +#ifndef __PKCS11H_HELPER_H
16080 +#define __PKCS11H_HELPER_H
16081 +
16082 +#if defined(__cplusplus)
16083 +extern "C" {
16084 +#endif
16085 +
16086 +#include "pkcs11-helper-config.h"
16087 +
16088 +#if !defined(USE_PKCS11H_OPENSSL) && !defined(USE_PKCS11H_GNUTLS)
16089 +#error PKCS#11: USE_PKCS11H_OPENSSL or USE_PKCS11H_GNUTLS must be defined
16090 +#endif
16091 +
16092 +#if defined(ENABLE_PKCS11H_SLOTEVENT) && !defined(ENABLE_PKCS11H_THREADING)
16093 +#error PKCS#11: ENABLE_PKCS11H_SLOTEVENT requires ENABLE_PKCS11H_THREADING
16094 +#endif
16095 +#if defined(ENABLE_PKCS11H_OPENSSL) && !defined(ENABLE_PKCS11H_CERTIFICATE)
16096 +#error PKCS#11: ENABLE_PKCS11H_OPENSSL requires ENABLE_PKCS11H_CERTIFICATE
16097 +#endif
16098 +
16099 +#define PKCS11H_LOG_DEBUG2 5
16100 +#define PKCS11H_LOG_DEBUG1 4
16101 +#define PKCS11H_LOG_INFO   3
16102 +#define PKCS11H_LOG_WARN   2
16103 +#define PKCS11H_LOG_ERROR  1
16104 +#define PKCS11H_LOG_QUITE  0
16105 +
16106 +#define PKCS11H_PIN_CACHE_INFINITE -1
16107 +
16108 +#define PKCS11H_SIGNMODE_MASK_SIGN (1<<0)
16109 +#define PKCS11H_SIGNMODE_MASK_RECOVER  (1<<1)
16110 +
16111 +#define PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT   (1<<0)
16112 +#define PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT  (1<<1)
16113 +#define PKCS11H_PROMPT_MASK_ALLOW_ALL ( \
16114 +       PKCS11H_PROMPT_MASK_ALLOW_PIN_PROMPT | \
16115 +       PKCS11H_PROMPT_MAST_ALLOW_CARD_PROMPT \
16116 +   )
16117 +
16118 +#define PKCS11H_SLOTEVENT_METHOD_AUTO      0
16119 +#define PKCS11H_SLOTEVENT_METHOD_TRIGGER   1
16120 +#define PKCS11H_SLOTEVENT_METHOD_POLL      2
16121 +
16122 +#define PKCS11H_ENUM_METHOD_CACHE      0
16123 +#define PKCS11H_ENUM_METHOD_CACHE_EXIST        1
16124 +#define PKCS11H_ENUM_METHOD_RELOAD     2
16125 +
16126 +typedef void (*pkcs11h_output_print_t)(
16127 +   IN void * const global_data,
16128 +   IN const char * const format,
16129 +   IN ...
16130 +)
16131 +#if __GNUC__ > 2
16132 +    __attribute__ ((format (printf, 2, 3)))
16133 +#endif
16134 + ;
16135 +
16136 +struct pkcs11h_token_id_s;
16137 +typedef struct pkcs11h_token_id_s *pkcs11h_token_id_t;
16138 +
16139 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
16140 +
16141 +struct pkcs11h_certificate_id_s;
16142 +struct pkcs11h_certificate_s;
16143 +typedef struct pkcs11h_certificate_id_s *pkcs11h_certificate_id_t;
16144 +typedef struct pkcs11h_certificate_s *pkcs11h_certificate_t;
16145 +
16146 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
16147 +
16148 +#if defined(ENABLE_PKCS11H_ENUM)
16149 +
16150 +struct pkcs11h_token_id_list_s;
16151 +typedef struct pkcs11h_token_id_list_s *pkcs11h_token_id_list_t;
16152 +
16153 +#if defined(ENABLE_PKCS11H_DATA)
16154 +
16155 +struct pkcs11h_data_id_list_s;
16156 +typedef struct pkcs11h_data_id_list_s *pkcs11h_data_id_list_t;
16157 +
16158 +#endif             /* ENABLE_PKCS11H_DATA */
16159 +
16160 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
16161 +
16162 +struct pkcs11h_certificate_id_list_s;
16163 +typedef struct pkcs11h_certificate_id_list_s *pkcs11h_certificate_id_list_t;
16164 +
16165 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
16166 +
16167 +#endif             /* ENABLE_PKCS11H_ENUM */
16168 +
16169 +typedef void (*pkcs11h_hook_log_t)(
16170 +   IN void * const global_data,
16171 +   IN const unsigned flags,
16172 +   IN const char * const format,
16173 +   IN va_list args
16174 +);
16175 +
16176 +typedef void (*pkcs11h_hook_slotevent_t)(
16177 +   IN void * const global_data
16178 +);
16179 +
16180 +typedef PKCS11H_BOOL (*pkcs11h_hook_token_prompt_t)(
16181 +   IN void * const global_data,
16182 +   IN void * const user_data,
16183 +   IN const pkcs11h_token_id_t token,
16184 +   IN const unsigned retry
16185 +);
16186 +
16187 +typedef PKCS11H_BOOL (*pkcs11h_hook_pin_prompt_t)(
16188 +   IN void * const global_data,
16189 +   IN void * const user_data,
16190 +   IN const pkcs11h_token_id_t token,
16191 +   IN const unsigned retry,
16192 +   OUT char * const pin,
16193 +   IN const size_t pin_max
16194 +);
16195 +
16196 +struct pkcs11h_token_id_s {
16197 +   char display[1024];
16198 +   char manufacturerID[sizeof (((CK_TOKEN_INFO *)NULL)->manufacturerID)+1];
16199 +   char model[sizeof (((CK_TOKEN_INFO *)NULL)->model)+1];
16200 +   char serialNumber[sizeof (((CK_TOKEN_INFO *)NULL)->serialNumber)+1];
16201 +   char label[sizeof (((CK_TOKEN_INFO *)NULL)->label)+1];
16202 +};
16203 +
16204 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
16205 +
16206 +struct pkcs11h_certificate_id_s {
16207 +   pkcs11h_token_id_t token_id;
16208 +
16209 +   char displayName[1024];
16210 +   CK_BYTE_PTR attrCKA_ID;
16211 +   size_t attrCKA_ID_size;
16212 +
16213 +   unsigned char *certificate_blob;
16214 +   size_t certificate_blob_size;
16215 +};
16216 +
16217 +#endif
16218 +
16219 +#if defined(ENABLE_PKCS11H_ENUM)
16220 +
16221 +struct pkcs11h_token_id_list_s {
16222 +   pkcs11h_token_id_list_t next;
16223 +   pkcs11h_token_id_t token_id;
16224 +};
16225 +
16226 +#if defined(ENABLE_PKCS11H_DATA)
16227 +
16228 +struct pkcs11h_data_id_list_s {
16229 +   pkcs11h_data_id_list_t next;
16230 +
16231 +   char *application;
16232 +   char *label;
16233 +};
16234 +
16235 +#endif             /* ENABLE_PKCS11H_DATA */
16236 +
16237 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
16238 +
16239 +struct pkcs11h_certificate_id_list_s {
16240 +   pkcs11h_certificate_id_list_t next;
16241 +   pkcs11h_certificate_id_t certificate_id;
16242 +};
16243 +
16244 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
16245 +
16246 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
16247 +
16248 +#if defined(ENABLE_PKCS11H_OPENSSL)
16249 +
16250 +typedef void (*pkcs11h_hook_openssl_cleanup_t) (
16251 +   IN const pkcs11h_certificate_t certificate
16252 +);
16253 +
16254 +struct pkcs11h_openssl_session_s;
16255 +typedef struct pkcs11h_openssl_session_s *pkcs11h_openssl_session_t;
16256 +
16257 +#endif             /* ENABLE_PKCS11H_OPENSSL */
16258 +
16259 +/*
16260 + * pkcs11h_getMessage - Get message by return value.
16261 + *
16262 + * Parameters:
16263 + *     rv      - Return value.
16264 + */
16265 +const char *
16266 +pkcs11h_getMessage (
16267 +   IN const CK_RV rv
16268 +);
16269 +
16270 +/*
16271 + * pkcs11h_initialize - Inititalize helper interface.
16272 + *
16273 + * Must be called once, from main thread.
16274 + * Defaults:
16275 + *     Protected authentication enabled.
16276 + *     PIN cached is infinite.
16277 + */
16278 +CK_RV
16279 +pkcs11h_initialize ();
16280 +
16281 +/*
16282 + * pkcs11h_terminate - Terminate helper interface.
16283 + *
16284 + * Must be called once, from main thread, after all
16285 + * related resources freed.
16286 + */
16287 +CK_RV
16288 +pkcs11h_terminate ();
16289 +
16290 +/*
16291 + * pkcs11h_setLogLevel - Set current log level of the helper.
16292 + *
16293 + * Parameters:
16294 + *     flags       - current log level.
16295 + *
16296 + * The log level can be set to maximum, but setting it to lower
16297 + * level will improve performance.
16298 + */
16299 +void
16300 +pkcs11h_setLogLevel (
16301 +   IN const unsigned flags
16302 +);
16303 +
16304 +/*
16305 + * pkcs11h_getLogLevel - Get current log level.
16306 + */
16307 +unsigned
16308 +pkcs11h_getLogLevel ();
16309 +
16310 +/*
16311 + * pkcs11h_setLogHook - Set a log callback.
16312 + *
16313 + * Parameters:
16314 + *     hook        - Callback.
16315 + *     pData       - Data to send to callback.
16316 + */
16317 +CK_RV
16318 +pkcs11h_setLogHook (
16319 +   IN const pkcs11h_hook_log_t hook,
16320 +   IN void * const global_data
16321 +);
16322 +
16323 +/*
16324 + * pkcs11h_setSlotEventHook - Set a slot event callback.
16325 + *
16326 + * Parameters:
16327 + *     hook        - Callback.
16328 + *     pData       - Data to send to callback.
16329 + *
16330 + * Calling this function initialize slot event notifications, these
16331 + * notifications can be started, but never terminate due to PKCS#11 limitation.
16332 + *
16333 + * In order to use slot events you must have threading enabled.
16334 + */
16335 +CK_RV
16336 +pkcs11h_setSlotEventHook (
16337 +   IN const pkcs11h_hook_slotevent_t hook,
16338 +   IN void * const global_data
16339 +);
16340 +
16341 +/*
16342 + * pkcs11h_setTokenPromptHook - Set a token prompt callback.
16343 + *
16344 + * Parameters:
16345 + *     hook        - Callback.
16346 + *     pData       - Data to send to callback.
16347 + */
16348 +CK_RV
16349 +pkcs11h_setTokenPromptHook (
16350 +   IN const pkcs11h_hook_token_prompt_t hook,
16351 +   IN void * const global_data
16352 +);
16353 +
16354 +/*
16355 + * pkcs11h_setPINPromptHook - Set a pin prompt callback.
16356 + *
16357 + * Parameters:
16358 + *     hook        - Callback.
16359 + *     pData       - Data to send to callback.
16360 + */
16361 +CK_RV
16362 +pkcs11h_setPINPromptHook (
16363 +   IN const pkcs11h_hook_pin_prompt_t hook,
16364 +   IN void * const global_data
16365 +);
16366 +
16367 +/*
16368 + * pkcs11h_setProtectedAuthentication - Set global protected authentication mode.
16369 + *
16370 + * Parameters:
16371 + *     allow_protected_auth    - Allow protected authentication if enabled by token.
16372 + */
16373 +CK_RV
16374 +pkcs11h_setProtectedAuthentication (
16375 +   IN const PKCS11H_BOOL allow_protected_auth
16376 +);
16377 +
16378 +/*
16379 + * pkcs11h_setPINCachePeriod - Set global PIN cache timeout.
16380 + *
16381 + * Parameters:
16382 + *     pin_cache_period    - Cache period in seconds, or PKCS11H_PIN_CACHE_INFINITE.
16383 + */
16384 +CK_RV
16385 +pkcs11h_setPINCachePeriod (
16386 +   IN const int pin_cache_period
16387 +);
16388 +
16389 +/*
16390 + * pkcs11h_setMaxLoginRetries - Set global login retries attempts.
16391 + *
16392 + * Parameters:
16393 + *     max_retries     - Login retries handled by the helper.
16394 + */
16395 +CK_RV
16396 +pkcs11h_setMaxLoginRetries (
16397 +   IN const unsigned max_retries
16398 +);
16399 +
16400 +/*
16401 + * pkcs11h_addProvider - Add a PKCS#11 provider.
16402 + *
16403 + * Parameters:
16404 + *     reference       - Reference name for this provider.
16405 + *     provider        - Provider library location.
16406 + *     allow_protected_auth    - Allow this provider to use protected authentication.
16407 + *     mask_sign_mode      - Provider signmode override.
16408 + *     slot_event_method   - Provider slot event method.
16409 + *     slot_poll_interval  - Slot event poll interval (If in polling mode).
16410 + *     cert_is_private     - Provider's certificate access should be done after login.
16411 + *
16412 + * This function must be called from the main thread.
16413 + *
16414 + * The global allow_protected_auth must be enabled in order to allow provider specific.
16415 + * The mask_sign_mode can be 0 in order to automatically detect key sign mode.
16416 + */
16417 +CK_RV
16418 +pkcs11h_addProvider (
16419 +   IN const char * const reference,
16420 +   IN const char * const provider_location,
16421 +   IN const PKCS11H_BOOL allow_protected_auth,
16422 +   IN const unsigned mask_sign_mode,
16423 +   IN const int slot_event_method,
16424 +   IN const int slot_poll_interval,
16425 +   IN const PKCS11H_BOOL cert_is_private
16426 +);
16427 +
16428 +/*
16429 + * pkcs11h_delProvider - Delete a PKCS#11 provider.
16430 + *
16431 + * Parameters:
16432 + *     reference       - Reference name for this provider.
16433 + *
16434 + * This function must be called from the main thread.
16435 + */
16436 +CK_RV
16437 +pkcs11h_removeProvider (
16438 +   IN const char * const reference
16439 +);
16440 +
16441 +/*
16442 + * pkcs11h_forkFixup - Handle special case of Unix fork()
16443 + *
16444 + * This function should be called after fork is called. This is required
16445 + * due to a limitation of the PKCS#11 standard.
16446 + *
16447 + * This function must be called from the main thread.
16448 + *
16449 + * The helper library handles fork automatically if ENABLE_PKCS11H_THREADING
16450 + * is set on configuration file, by use of pthread_atfork.
16451 + */
16452 +CK_RV
16453 +pkcs11h_forkFixup ();
16454 +
16455 +/*
16456 + * pkcs11h_plugAndPlay - Handle slot rescan.
16457 + *
16458 + * This function must be called from the main thread.
16459 + *
16460 + * PKCS#11 providers do not allow plug&play, plug&play can be established by
16461 + * finalizing all providers and initializing them again.
16462 + *
16463 + * The cost of this process is invalidating all sessions, and require user
16464 + * login at the next access.
16465 + */
16466 +CK_RV
16467 +pkcs11h_plugAndPlay ();
16468 +
16469 +/*
16470 + * pkcs11h_token_freeTokenId - Free token_id object.
16471 + *
16472 + * Parameters:
16473 + *     token_id        - token_id.
16474 + */
16475 +CK_RV
16476 +pkcs11h_token_freeTokenId (
16477 +   IN pkcs11h_token_id_t token_id
16478 +);
16479 +
16480 +/*
16481 + * pkcs11h_duplicateTokenId - Duplicate token_id object.
16482 + *
16483 + * Parameters:
16484 + *     to          - target.
16485 + *     from            - source.
16486 + */
16487 +CK_RV
16488 +pkcs11h_token_duplicateTokenId (
16489 +   OUT pkcs11h_token_id_t * const to,
16490 +   IN const pkcs11h_token_id_t from
16491 +);
16492 +
16493 +/*
16494 + * pkcs11h_sameTokenId - Returns TRUE if same token id
16495 + *
16496 + * Parameters:
16497 + *     a           - a.
16498 + *     b           - b.
16499 + */
16500 +PKCS11H_BOOL
16501 +pkcs11h_token_sameTokenId (
16502 +   IN const pkcs11h_token_id_t a,
16503 +   IN const pkcs11h_token_id_t b
16504 +);
16505 +
16506 +/*
16507 + * pkcs11h_token_login - Force login, avoid hooks.
16508 + *
16509 + * Parameters:
16510 + *     token_id        - Token to login into.
16511 + *     readonly        - Should session be readonly.
16512 + *     pin         - PIN to login, NULL for protected authentication
16513 + */
16514 +CK_RV
16515 +pkcs11h_token_login (
16516 +   IN const pkcs11h_token_id_t token_id,
16517 +   IN const PKCS11H_BOOL readonly,
16518 +   IN const char * const pin
16519 +);
16520 +
16521 +#if defined(ENABLE_PKCS11H_SERIALIZATION)
16522 +
16523 +/*
16524 + * pkcs11h_serializeTokenId - Serialize token_id into string.
16525 + *
16526 + * Parameters:
16527 + *     sz          - Output string.
16528 + *     max         - Maximum string size.
16529 + *     token_id        - id to serialize
16530 + *
16531 + * sz may be NULL to get size
16532 + */
16533 +CK_RV
16534 +pkcs11h_token_serializeTokenId (
16535 +   OUT char * const sz,
16536 +   IN OUT size_t *max,
16537 +   IN const pkcs11h_token_id_t token_id
16538 +);
16539 +
16540 +/*
16541 + * pkcs11h_deserializeTokenId - Deserialize token_id from string.
16542 + *
16543 + * Parameters:
16544 + *     p_token_id      - id.
16545 + *     sz          - Input string
16546 + */
16547 +CK_RV
16548 +pkcs11h_token_deserializeTokenId (
16549 +   OUT pkcs11h_token_id_t *p_token_id,
16550 +   IN const char * const sz
16551 +);
16552 +
16553 +#endif             /* ENABLE_PKCS11H_SERIALIZATION */
16554 +
16555 +#if defined(ENABLE_PKCS11H_TOKEN)
16556 +
16557 +/*
16558 + * pkcs11h_token_ensureAccess - Ensure token is accessible.
16559 + *
16560 + * Parameters:
16561 + *     token_id        - Token id object.
16562 + *     user_data       - Optional user data, to be passed to hooks.
16563 + *     mask_prompt     - Allow prompt.
16564 + */
16565 +CK_RV
16566 +pkcs11h_token_ensureAccess (
16567 +   IN const pkcs11h_token_id_t token_id,
16568 +   IN void * const user_data,
16569 +   IN const unsigned mask_prompt
16570 +);
16571 +
16572 +#endif             /* ENABLE_PKCS11H_TOKEN */
16573 +
16574 +#if defined(ENABLE_PKCS11H_DATA)
16575 +
16576 +/*
16577 + * pkcs11h_data_get - get data object.
16578 + *
16579 + * Parameters:
16580 + *     token_id        - Token id object.
16581 + *     is_public       - Object is public.
16582 + *     application     - Object application attribute.
16583 + *     label           - Object label attribute.
16584 + *     user_data       - Optional user data, to be passed to hooks.
16585 + *     mask_prompt     - Allow prompt.
16586 + *     blob            - blob, set to NULL to get size.
16587 + *     p_blob_size     - blob size.
16588 + */
16589 +CK_RV
16590 +pkcs11h_data_get (
16591 +   IN const pkcs11h_token_id_t token_id,
16592 +   IN const PKCS11H_BOOL is_public,
16593 +   IN const char * const application,
16594 +   IN const char * const label,
16595 +   IN void * const user_data,
16596 +   IN const unsigned mask_prompt,
16597 +   OUT unsigned char * const blob,
16598 +   IN OUT size_t * const p_blob_size
16599 +);
16600 +
16601 +/*
16602 + * pkcs11h_data_put - put data object.
16603 + *
16604 + * Parameters:
16605 + *     token_id        - Token id object.
16606 + *     is_public       - Object is public.
16607 + *     application     - Object application attribute.
16608 + *     label           - Object label attribute.
16609 + *     user_data       - Optional user data, to be passed to hooks.
16610 + *     mask_prompt     - Allow prompt.
16611 + *     blob            - blob.
16612 + *     blob_size       - blob size.
16613 + */
16614 +CK_RV
16615 +pkcs11h_data_put (
16616 +   IN const pkcs11h_token_id_t token_id,
16617 +   IN const PKCS11H_BOOL is_public,
16618 +   IN const char * const application,
16619 +   IN const char * const label,
16620 +   IN void * const user_data,
16621 +   IN const unsigned mask_prompt,
16622 +   OUT unsigned char * const blob,
16623 +   IN const size_t blob_size
16624 +);
16625 +
16626 +/*
16627 + * pkcs11h_data_del - delete data object.
16628 + *
16629 + * Parameters:
16630 + *     token_id        - Token id object.
16631 + *     is_public       - Object is public.
16632 + *     application     - Object application attribute.
16633 + *     label           - Object label attribute.
16634 + *     user_data       - Optional user data, to be passed to hooks.
16635 + *     mask_prompt     - Allow prompt.
16636 + */
16637 +CK_RV
16638 +pkcs11h_data_del (
16639 +   IN const pkcs11h_token_id_t token_id,
16640 +   IN const PKCS11H_BOOL is_public,
16641 +   IN const char * const application,
16642 +   IN const char * const label,
16643 +   IN void * const user_data,
16644 +   IN const unsigned mask_prompt
16645 +);
16646 +
16647 +#endif             /* ENABLE_PKCS11H_DATA */
16648 +
16649 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
16650 +/*======================================================================*
16651 + * CERTIFICATE INTERFACE
16652 + *======================================================================*/
16653 +
16654 +/*
16655 + * pkcs11h_certificate_freeCertificateId - Free certificate_id object.
16656 + */
16657 +CK_RV
16658 +pkcs11h_certificate_freeCertificateId (
16659 +   IN pkcs11h_certificate_id_t certificate_id
16660 +);
16661 +
16662 +/*
16663 + * pkcs11h_duplicateCertificateId - Duplicate certificate_id object.
16664 + */
16665 +CK_RV
16666 +pkcs11h_certificate_duplicateCertificateId (
16667 +   OUT pkcs11h_certificate_id_t * const to,
16668 +   IN const pkcs11h_certificate_id_t from
16669 +);
16670 +
16671 +/*
16672 + * pkcs11h_certificate_setCertificateIdCertificateBlob - Sets internal certificate_id blob.
16673 + *
16674 + * Parameters:
16675 + *     certificate_id      - Certificate id ojbect.
16676 + *     blob            - blob.
16677 + *     blob_size       - blob size.
16678 + *
16679 + * Useful to set after deserialization so certificate is available and not read from token.
16680 + */
16681 +CK_RV
16682 +pkcs11h_certificate_setCertificateIdCertificateBlob (
16683 +   IN const pkcs11h_certificate_id_t certificate_id,
16684 +   IN const unsigned char * const blob,
16685 +   IN const size_t blob_size
16686 +);
16687 +
16688 +/*
16689 + * pkcs11h_certificate_freeCertificate - Free certificate object.
16690 + *
16691 + * Parameters:
16692 + *     certificate     - Certificate ojbect.
16693 + */
16694 +CK_RV
16695 +pkcs11h_certificate_freeCertificate (
16696 +   IN pkcs11h_certificate_t certificate
16697 +);
16698 +
16699 +/*
16700 + * pkcs11h_certificate_create - Create a certificate object out of certificate_id.
16701 + *
16702 + * Parameters:
16703 + * certificate_id      - Certificate id object to be based on.
16704 + *     user_data       - Optional user data, to be passed to hooks.
16705 + *     mask_prompt     - Allow prompt.
16706 + * pin_cache_period    - Session specific cache period.
16707 + * p_certificate       - Receives certificate object.
16708 + *
16709 + * The certificate id object may not specify the full certificate.
16710 + * The certificate object must be freed by caller.
16711 + */    
16712 +CK_RV
16713 +pkcs11h_certificate_create (
16714 +   IN const pkcs11h_certificate_id_t certificate_id,
16715 +   IN void * const user_data,
16716 +   IN const unsigned mask_prompt,
16717 +   IN const int pin_cache_period,
16718 +   OUT pkcs11h_certificate_t * const p_certificate
16719 +);
16720 +
16721 +/*
16722 + * pkcs11h_certificate_getPromptMask - Extract user data out of certificate.
16723 + *
16724 + * Parameters:
16725 + *     certificate     - Certificate ojbect.
16726 + *
16727 + * Returns:
16728 + *     mask_prompt     - Allow prompt.
16729 + *
16730 + */
16731 +unsigned
16732 +pkcs11h_certificate_getPromptMask (
16733 +   IN const pkcs11h_certificate_t certificate
16734 +);
16735 +
16736 +/*
16737 + * pkcs11h_certificate_setPromptMask - Extract user data out of certificate.
16738 + *
16739 + * Parameters:
16740 + *     certificate     - Certificate ojbect.
16741 + *     mask_prompt     - Allow prompt.
16742 + */
16743 +void
16744 +pkcs11h_certificate_setPromptMask (
16745 +   IN const pkcs11h_certificate_t certificate,
16746 +   IN const unsigned ask_prompt
16747 +);
16748 +
16749 +/*
16750 + * pkcs11h_certificate_getUserData - Extract user data out of certificate.
16751 + *
16752 + * Parameters:
16753 + *     certificate     - Certificate ojbect.
16754 + *
16755 + * Returns:
16756 + *     user_data       - Optional user data, to be passed to hooks.
16757 + */
16758 +void *
16759 +pkcs11h_certificate_getUserData (
16760 +   IN const pkcs11h_certificate_t certificate
16761 +);
16762 +
16763 +/*
16764 + * pkcs11h_certificate_setUserData - Extract user data out of certificate.
16765 + *
16766 + * Parameters:
16767 + *     certificate     - Certificate ojbect.
16768 + *     user_data       - Optional user data, to be passed to hooks.
16769 + */
16770 +void
16771 +pkcs11h_certificate_setUserData (
16772 +   IN const pkcs11h_certificate_t certificate,
16773 +   IN void * const user_data
16774 +);
16775 +
16776 +/*
16777 + * pkcs11h_certificate_getCertificateId - Get certifiate id object out of a certifiate
16778 + *
16779 + * Parameters:
16780 + *     certificate     - Certificate object.
16781 + *     p_certificate_id    - Certificate id object pointer.
16782 + *
16783 + * The certificate id must be freed by caller.
16784 + */
16785 +CK_RV
16786 +pkcs11h_certificate_getCertificateId (
16787 +   IN const pkcs11h_certificate_t certificate,
16788 +   OUT pkcs11h_certificate_id_t * const p_certificate_id
16789 +);
16790 +
16791 +/*
16792 + * pkcs11h_certificate_getCertificateBlob - Get the certificate blob out of the certificate object.
16793 + *
16794 + * Parameters:
16795 + *     certificate     - Certificate object.
16796 + *     certificate_blob    - Buffer.
16797 + *     certificate_blob_size   - Buffer size.
16798 + *
16799 + * Buffer may be NULL in order to get size.
16800 + */
16801 +CK_RV
16802 +pkcs11h_certificate_getCertificateBlob (
16803 +   IN const pkcs11h_certificate_t certificate,
16804 +   OUT unsigned char * const certificate_blob,
16805 +   IN OUT size_t * const p_certificate_blob_size
16806 +);
16807 +
16808 +#if defined(ENABLE_PKCS11H_SERIALIZATION)
16809 +
16810 +/*
16811 + * pkcs11h_certificate_serializeCertificateId - Serialize certificate_id into a string
16812 + *
16813 + * Parametrs:
16814 + *     sz          - Output string.
16815 + * max         - Max buffer size.
16816 + * certificate_id      - id to serialize
16817 + *
16818 + * sz may be NULL in order to get size.
16819 + */
16820 +CK_RV
16821 +pkcs11h_certificate_serializeCertificateId (
16822 +   OUT char * const sz,
16823 +   IN OUT size_t *max,
16824 +   IN const pkcs11h_certificate_id_t certificate_id
16825 +);
16826 +
16827 +/*
16828 + * pkcs11h_certificate_deserializeCertificateId - Deserialize certificate_id out of string.
16829 + *
16830 + * Parameters:
16831 + *     p_certificate_id    - id.
16832 + *     sz          - Inut string
16833 + */
16834 +CK_RV
16835 +pkcs11h_certificate_deserializeCertificateId (
16836 +   OUT pkcs11h_certificate_id_t * const p_certificate_id,
16837 +   IN const char * const sz
16838 +);
16839 +
16840 +#endif             /* ENABLE_PKCS11H_SERIALIZATION */
16841 +
16842 +/*
16843 + * pkcs11h_certificate_ensureCertificateAccess - Ensure certificate is accessible.
16844 + *
16845 + * Parameters:
16846 + *     certificate     - Certificate object.
16847 + */
16848 +CK_RV
16849 +pkcs11h_certificate_ensureCertificateAccess (
16850 +   IN const pkcs11h_certificate_t certificate
16851 +);
16852 +
16853 +/*
16854 + * pkcs11h_certificate_ensureKeyAccess - Ensure key is accessible.
16855 + *
16856 + * Parameters:
16857 + *     certificate     - Certificate object.
16858 + */
16859 +CK_RV
16860 +pkcs11h_certificate_ensureKeyAccess (
16861 +   IN const pkcs11h_certificate_t certificate
16862 +);
16863 +
16864 +/*
16865 + * pkcs11h_certificate_lockSession - Lock session for threded environment
16866 + *
16867 + * Parameters:
16868 + *     certificate     - Certificate object.
16869 + *
16870 + * This must be called on threaded environment, so both calls to _sign and
16871 + * _signRecover and _decrypt will be from the same source.
16872 + * Failing to lock session, will result with CKR_OPERATION_ACTIVE if
16873 + * provider is good, or unexpected behaviour for others.
16874 + *
16875 + * It is save to call this also in none threaded environment, it will do nothing.
16876 + * Call this also if you are doing one stage operation, since locking is not
16877 + * done by method.
16878 + */
16879 +CK_RV
16880 +pkcs11h_certificate_lockSession (
16881 +   IN const pkcs11h_certificate_t certificate
16882 +);
16883 +
16884 +/*
16885 + * pkcs11h_certificate_releaseSession - Releases session lock.
16886 + *
16887 + * Parameters:
16888 + *     certificate     - Certificate object.
16889 + *
16890 + * See pkcs11h_certificate_lockSession.
16891 + */
16892 +CK_RV
16893 +pkcs11h_certificate_releaseSession (
16894 +   IN const pkcs11h_certificate_t certificate
16895 +);
16896 +
16897 +/*
16898 + * pkcs11h_certificate_sign - Sign data.
16899 + *
16900 + * Parameters:
16901 + *     certificate     - Certificate object.
16902 + *     mech_type       - PKCS#11 mechanism.
16903 + * source          - Buffer to sign.
16904 + * source_size     - Buffer size.
16905 + * target          - Target buffer, can be NULL to get size.
16906 + * target_size     - Target buffer size.
16907 + */
16908 +CK_RV
16909 +pkcs11h_certificate_sign (
16910 +   IN const pkcs11h_certificate_t certificate,
16911 +   IN const CK_MECHANISM_TYPE mech_type,
16912 +   IN const unsigned char * const source,
16913 +   IN const size_t source_size,
16914 +   OUT unsigned char * const target,
16915 +   IN OUT size_t * const p_target_size
16916 +);
16917 +
16918 +/*
16919 + * pkcs11h_certificate_signRecover - Sign data.
16920 + *
16921 + * Parameters:
16922 + *     certificate     - Certificate object.
16923 + *     mech_type       - PKCS#11 mechanism.
16924 + * source          - Buffer to sign.
16925 + * source_size     - Buffer size.
16926 + * target          - Target buffer, can be NULL to get size.
16927 + * target_size     - Target buffer size.
16928 + */
16929 +CK_RV
16930 +pkcs11h_certificate_signRecover (
16931 +   IN const pkcs11h_certificate_t certificate,
16932 +   IN const CK_MECHANISM_TYPE mech_type,
16933 +   IN const unsigned char * const source,
16934 +   IN const size_t source_size,
16935 +   OUT unsigned char * const target,
16936 +   IN OUT size_t * const p_target_size
16937 +);
16938 +
16939 +/*
16940 + * pkcs11h_certificate_signAny - Sign data mechanism determined by key attributes.
16941 + *
16942 + * Parameters:
16943 + *     certificate     - Certificate object.
16944 + *     mech_type       - PKCS#11 mechanism.
16945 + * source          - Buffer to sign.
16946 + * source_size     - Buffer size.
16947 + * target          - Target buffer, can be NULL to get size.
16948 + * target_size     - Target buffer size.
16949 + */
16950 +CK_RV
16951 +pkcs11h_certificate_signAny (
16952 +   IN const pkcs11h_certificate_t certificate,
16953 +   IN const CK_MECHANISM_TYPE mech_type,
16954 +   IN const unsigned char * const source,
16955 +   IN const size_t source_size,
16956 +   OUT unsigned char * const target,
16957 +   IN OUT size_t * const p_target_size
16958 +);
16959 +
16960 +/*
16961 + * pkcs11h_certificate_decrypt - Decrypt data.
16962 + *
16963 + * Parameters:
16964 + *     certificate     - Certificate object.
16965 + *     mech_type       - PKCS#11 mechanism.
16966 + * source          - Buffer to sign.
16967 + * source_size     - Buffer size.
16968 + * target          - Target buffer, can be NULL to get size.
16969 + * target_size     - Target buffer size.
16970 + */
16971 +CK_RV
16972 +pkcs11h_certificate_decrypt (
16973 +   IN const pkcs11h_certificate_t certificate,
16974 +   IN const CK_MECHANISM_TYPE mech_type,
16975 +   IN const unsigned char * const source,
16976 +   IN const size_t source_size,
16977 +   OUT unsigned char * const target,
16978 +   IN OUT size_t * const p_target_size
16979 +);
16980 +
16981 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
16982 +
16983 +#if defined(ENABLE_PKCS11H_LOCATE)
16984 +/*======================================================================*
16985 + * LOCATE INTERFACE
16986 + *======================================================================*/
16987 +
16988 +#if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE)
16989 +
16990 +/*
16991 + * pkcs11h_locate_token - Locate token based on atributes.
16992 + *
16993 + * Parameters:
16994 + *     slot_type       - How to locate slot.
16995 + *     slot            - Slot name.
16996 + *     user_data       - Optional user data, to be passed to hooks.
16997 + *     mask_prompt     - Allow prompt.
16998 + *     p_token_id      - Token object.
16999 + *
17000 + * Slot:
17001 + *     id  - Slot number.
17002 + *     name    - Slot name.
17003 + *     label   - Available token label.
17004 + *
17005 + * Caller must free token id.
17006 + */
17007 +CK_RV
17008 +pkcs11h_locate_token (
17009 +   IN const char * const slot_type,
17010 +   IN const char * const slot,
17011 +   IN void * const user_data,
17012 +   IN const unsigned mask_prompt,
17013 +   OUT pkcs11h_token_id_t * const p_token_id
17014 +);
17015 +
17016 +#endif             /* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
17017 +
17018 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
17019 +
17020 +/*
17021 + * pkcs11h_locate_certificate - Locate certificate based on atributes.
17022 + *
17023 + * Parameters:
17024 + *     slot_type       - How to locate slot.
17025 + *     slot            - Slot name.
17026 + *     id_type         - How to locate object.
17027 + *     id          - Object name.
17028 + *     user_data       - Optional user data, to be passed to hooks.
17029 + *     mask_prompt     - Allow prompt.
17030 + *     p_certificate_id    - Certificate object.
17031 + *
17032 + * Slot:
17033 + * Same as pkcs11h_locate_token.
17034 + *
17035 + * Object:
17036 + *     id  - Certificate CKA_ID (hex string) (Fastest).
17037 + *     label   - Certificate CKA_LABEL (string).
17038 + *     subject - Certificate subject (OpenSSL or gnutls DN).
17039 + *
17040 + * Caller must free certificate id.
17041 + */
17042 +CK_RV
17043 +pkcs11h_locate_certificate (
17044 +   IN const char * const slot_type,
17045 +   IN const char * const slot,
17046 +   IN const char * const id_type,
17047 +   IN const char * const id,
17048 +   IN void * const user_data,
17049 +   IN const unsigned mask_prompt,
17050 +   OUT pkcs11h_certificate_id_t * const p_certificate_id
17051 +);
17052 +
17053 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
17054 +
17055 +#endif             /* ENABLE_PKCS11H_LOCATE */
17056 +
17057 +#if defined(ENABLE_PKCS11H_ENUM)
17058 +/*======================================================================*
17059 + * ENUM INTERFACE
17060 + *======================================================================*/
17061 +
17062 +#if defined(ENABLE_PKCS11H_TOKEN)
17063 +
17064 +/*
17065 + * pkcs11h_freeTokenIdList - Free certificate_id list.
17066 + */
17067 +CK_RV
17068 +pkcs11h_token_freeTokenIdList (
17069 +   IN const pkcs11h_token_id_list_t token_id_list
17070 +);
17071 +
17072 +/*
17073 + * pkcs11h_token_enumTokenIds - Enumerate available tokens
17074 + *
17075 + * Parameters:
17076 + *     p_token_id_list     - A list of token ids.
17077 + *     
17078 + * Caller must free the list.
17079 + */
17080 +CK_RV
17081 +pkcs11h_token_enumTokenIds (
17082 +   IN const int method,
17083 +   OUT pkcs11h_token_id_list_t * const p_token_id_list
17084 +);
17085 +
17086 +#endif             /* ENABLE_PKCS11H_TOKEN */
17087 +
17088 +#if defined(ENABLE_PKCS11H_DATA)
17089 +
17090 +/*
17091 + * pkcs11h_data_freeDataIdList - free data object list..
17092 + *
17093 + * Parameters:
17094 + *     data_id_list        - list to free.
17095 + */
17096 +CK_RV
17097 +pkcs11h_data_freeDataIdList (
17098 +   IN const pkcs11h_data_id_list_t data_id_list
17099 +);
17100 +
17101 +/*
17102 + * pkcs11h_data_enumDataObjects - get list of data objects.
17103 + *
17104 + * Parameters:
17105 + *     token_id        - token id.
17106 + *     is_public       - Get a list of public objects.
17107 + *     user_data       - Optional user data, to be passed to hooks.
17108 + *     mask_prompt     - Allow prompt.
17109 + *     p_data_id_list      - List location.
17110 + */
17111 +CK_RV
17112 +pkcs11h_data_enumDataObjects (
17113 +   IN const pkcs11h_token_id_t token_id,
17114 +   IN const PKCS11H_BOOL is_public,
17115 +   IN void * const user_data,
17116 +   IN const unsigned mask_prompt,
17117 +   OUT pkcs11h_data_id_list_t * const p_data_id_list
17118 +);
17119 +
17120 +#endif             /* ENABLE_PKCS11H_DATA */
17121 +
17122 +#if defined(ENABLE_PKCS11H_CERTIFICATE)
17123 +
17124 +/*
17125 + * pkcs11h_certificate_freeCertificateIdList - Free certificate_id list.
17126 + */
17127 +CK_RV
17128 +pkcs11h_certificate_freeCertificateIdList (
17129 +   IN const pkcs11h_certificate_id_list_t cert_id_list
17130 +);
17131 +
17132 +/*
17133 + * pkcs11h_certificate_enumTokenCertificateIds - Enumerate available certificates on specific token
17134 + *
17135 + * Parameters:
17136 + *     token_id        - Token id to enum.
17137 + *     method          - How to fetch certificates.
17138 + *     user_data       - Some user specific data.
17139 + *     mask_prompt     - Allow prompt.
17140 + *     p_cert_id_issuers_list  - Receives issues list, can be NULL.
17141 + *     p_cert_id_end_list  - Receives end certificates list.
17142 + *
17143 + * This function will likely take long time.
17144 + *
17145 + * Method can be one of the following:
17146 + * PKCS11H_ENUM_METHOD_CACHE
17147 + *     Return available certificates, even if token was once detected and
17148 + *     was removed.
17149 + * PKCS11H_ENUM_METHOD_CACHE_EXIST
17150 + *     Return available certificates for available tokens only, don't
17151 + *     read the contents of the token if already read, even if this token
17152 + *     removed and inserted.
17153 + * PKCS11H_ENUM_METHOD_RELOAD
17154 + *     Clear all caches and then enum.
17155 + *
17156 + * Caller must free the lists.
17157 + */
17158 +CK_RV
17159 +pkcs11h_certificate_enumTokenCertificateIds (
17160 +   IN const pkcs11h_token_id_t token_id,
17161 +   IN const int method,
17162 +   IN void * const user_data,
17163 +   IN const unsigned mask_prompt,
17164 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
17165 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
17166 +);
17167 +
17168 +/*
17169 + * pkcs11h_enum_getCertificateIds - Enumerate available certificates.
17170 + *
17171 + * Parameters:
17172 + *     method          - How to fetch certificates.
17173 + *     user_data       - Some user specific data.
17174 + *     mask_prompt     - Allow prompt.
17175 + *     p_cert_id_issuers_list  - Receives issues list, can be NULL.
17176 + *     p_cert_id_end_list  - Receives end certificates list.
17177 + *
17178 + * This function will likely take long time.
17179 + *
17180 + * Method can be one of the following:
17181 + * PKCS11H_ENUM_METHOD_CACHE
17182 + *     Return available certificates, even if token was once detected and
17183 + *     was removed.
17184 + * PKCS11H_ENUM_METHOD_CACHE_EXIST
17185 + *     Return available certificates for available tokens only, don't
17186 + *     read the contents of the token if already read, even if this token
17187 + *     removed and inserted.
17188 + * PKCS11H_ENUM_METHOD_RELOAD
17189 + *     Clear all caches and then enum.
17190 + *
17191 + * Caller must free lists.
17192 + */
17193 +CK_RV
17194 +pkcs11h_certificate_enumCertificateIds (
17195 +   IN const int method,
17196 +   IN void * const user_data,
17197 +   IN const unsigned mask_prompt,
17198 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_issuers_list,
17199 +   OUT pkcs11h_certificate_id_list_t * const p_cert_id_end_list
17200 +);
17201 +
17202 +#endif             /* ENABLE_PKCS11H_CERTIFICATE */
17203 +
17204 +#endif             /* ENABLE_PKCS11H_ENUM */
17205 +
17206 +#if defined(ENABLE_PKCS11H_OPENSSL)
17207 +/*======================================================================*
17208 + * OPENSSL INTERFACE
17209 + *======================================================================*/
17210 +
17211 +/*
17212 + * pkcs11h_openssl_getX509 - Returns an X509 object out of the openssl_session object.
17213 + *
17214 + * Parameters:
17215 + *     certificate     - Certificate object.
17216 + */
17217 +X509 *
17218 +pkcs11h_openssl_getX509 (
17219 +   IN const pkcs11h_certificate_t certificate
17220 +);
17221 +
17222 +/*
17223 + * pkcs11h_openssl_createSession - Create OpenSSL session based on a certificate object.
17224 + *
17225 + * Parameters:
17226 + *     certificate     - Certificate object.
17227 + *
17228 + * The certificate object will be freed by the OpenSSL interface on session end.
17229 + */
17230 +pkcs11h_openssl_session_t
17231 +pkcs11h_openssl_createSession (
17232 +   IN const pkcs11h_certificate_t certificate
17233 +);
17234 +
17235 +/*
17236 + * pkcs11h_openssl_getCleanupHook - Sets cleanup hook
17237 + *
17238 + * Parameters:
17239 + *     openssl_session     - session.
17240 + */
17241 +pkcs11h_hook_openssl_cleanup_t
17242 +pkcs11h_openssl_getCleanupHook (
17243 +   IN const pkcs11h_openssl_session_t openssl_session
17244 +);
17245 +
17246 +/*
17247 + * pkcs11h_openssl_setCleanupHook - Sets cleanup hook
17248 + *
17249 + * Parameters:
17250 + *     openssl_session     - session.
17251 + *     cleanup         - hook.
17252 + */
17253 +void
17254 +pkcs11h_openssl_setCleanupHook (
17255 +   IN const pkcs11h_openssl_session_t openssl_session,
17256 +   IN const pkcs11h_hook_openssl_cleanup_t cleanup
17257 +);
17258 +
17259 +/*
17260 + * pkcs11h_openssl_freeSession - Free OpenSSL session.
17261 + *
17262 + * Parameters:
17263 + *     openssl_session     - Session to free.
17264 + *
17265 + * The openssl_session object has a reference count just like other OpenSSL objects.
17266 + */
17267 +void
17268 +pkcs11h_openssl_freeSession (
17269 +   IN const pkcs11h_openssl_session_t openssl_session
17270 +);
17271 +
17272 +/*
17273 + * pkcs11h_openssl_session_getRSA - Returns an RSA object out of the openssl_session object.
17274 + *
17275 + * Parameters:
17276 + *     openssl_session     - Session.
17277 + */
17278 +RSA *
17279 +pkcs11h_openssl_session_getRSA (
17280 +   IN const pkcs11h_openssl_session_t openssl_session
17281 +);
17282 +
17283 +/*
17284 + * pkcs11h_openssl_session_getX509 - Returns an X509 object out of the openssl_session object.
17285 + *
17286 + * Parameters:
17287 + *     openssl_session     - Session.
17288 + */
17289 +X509 *
17290 +pkcs11h_openssl_session_getX509 (
17291 +   IN const pkcs11h_openssl_session_t openssl_session
17292 +);
17293 +
17294 +#endif             /* ENABLE_PKCS11H_OPENSSL */
17295 +
17296 +#if defined(ENABLE_PKCS11H_STANDALONE)
17297 +/*======================================================================*
17298 + * STANDALONE INTERFACE
17299 + *======================================================================*/
17300 +
17301 +void
17302 +pkcs11h_standalone_dump_slots (
17303 +   IN const pkcs11h_output_print_t my_output,
17304 +   IN void * const global_data,
17305 +   IN const char * const provider
17306 +);
17307 +
17308 +void
17309 +pkcs11h_standalone_dump_objects (
17310 +   IN const pkcs11h_output_print_t my_output,
17311 +   IN void * const global_data,
17312 +   IN const char * const provider,
17313 +   IN const char * const slot,
17314 +   IN const char * const pin
17315 +);
17316 +
17317 +#endif             /* ENABLE_PKCS11H_STANDALONE */
17318 +
17319 +#ifdef __cplusplus
17320 +}
17321 +#endif
17322 +
17323 +#endif             /* __PKCS11H_HELPER_H */
17324 diff -urNp openssh-4.4p1/README.pkcs11 openssh-4.4p1+pkcs11-0.17/README.pkcs11
17325 --- openssh-4.4p1/README.pkcs11 1970-01-01 02:00:00.000000000 +0200
17326 +++ openssh-4.4p1+pkcs11-0.17/README.pkcs11 2006-10-18 20:22:08.000000000 +0200
17327 @@ -0,0 +1,49 @@
17328 +The PKCS#11 patch modify ssh-add and ssh-agent to support PKCS#11 private keys
17329 +and certificates (http://alon.barlev.googlepages.com/openssh-pkcs11).
17330 +
17331 +It allows using multiple PKCS#11 providers at the same time, selecting keys by
17332 +id, label or certificate subject, handling card removal and card insert events,
17333 +handling card re-insert to a different slot, supporting session expiration.
17334 +
17335 +A valid X.509 certificate should exist on the token, without X.509 support it is
17336 +exported as regular RSA key. Self-signed certificates are treated as RSA key and
17337 +not as X.509 RSA key.
17338 +
17339 +If you like X.509 (http://roumenpetrov.info/openssh) support apply the X.509
17340 +patch AFTER the PKCS#11 patch. You can use -o PubkeyAlgorithms=ssh-rsa in order to
17341 +authenticate to none X.509 servers.
17342 +
17343 +One significant change is that the ssh-agent prompts for passwords now... So you
17344 +need to configure it with a program that asks for card insert or PIN, a program
17345 +such as x11-ssh-askpass. Current implementation (ssh-add asks for passwords) is
17346 +not valid for dynamic smartcard environment.
17347 +
17348 +Current implementation uses the askpin program also for prompting card insert...
17349 +Don't be confused, it only expects ok or cancel, some simple scripts available
17350 +at http://alon.barlev.googlepages.com/openssh-pkcs11 that uses KDE, Gnome and .NET
17351 +in order to display these dialogs.
17352 +
17353 +You can view full usage by:
17354 +$ ssh-agent /bin/sh
17355 +$ ssh-add -h
17356 +
17357 +A common scenario is the following:
17358 +$ ssh-agent /bin/sh
17359 +$ ssh-add --pkcs11-ask-pin `which openssh-kde-dialogs.sh`
17360 +$ ssh-add --pkcs11-add-provider --pkcs11-provider /usr/lib/pkcs11/MyProvider.so
17361 +$ ssh-add --pkcs11-add-id --pkcs11-id "serialized id"
17362 +$ ssh myhost
17363 +
17364 +In order to see available objects, you can use:
17365 +$ ssh-add --pkcs11-show-ids --pkcs11-provider /usr/lib/pkcs11/MyProvider.so
17366 +
17367 +In order to add id without accessing the token, you must put the certificate in
17368 +a PEM file and use:
17369 +$ ssh-add --pkcs11-add-id --pkcs11-id "serialized id" --pkcs11-cert-file my.pem
17370 +
17371 +In order to debug open two shells:
17372 +1$ rm -fr /tmp/s; ssh-agent -d -d -d -a /tmp/s
17373 +
17374 +2$ SSH_AUTH_SOCK=/tmp/s; export SSH_AUTH_SOCK;
17375 +2$ [ssh-add]...
17376 +
17377 diff -urNp openssh-4.4p1/ssh-add.c openssh-4.4p1+pkcs11-0.17/ssh-add.c
17378 --- openssh-4.4p1/ssh-add.c 2006-09-01 08:38:37.000000000 +0300
17379 +++ openssh-4.4p1+pkcs11-0.17/ssh-add.c 2006-10-12 15:10:42.000000000 +0200
17380 @@ -56,12 +56,15 @@
17381  #include "rsa.h"
17382  #include "log.h"
17383  #include "key.h"
17384 +#include "pkcs11.h"
17385  #include "buffer.h"
17386  #include "authfd.h"
17387  #include "authfile.h"
17388  #include "pathnames.h"
17389  #include "misc.h"
17390  
17391 +static void usage (void);
17392 +
17393  /* argv0 */
17394  extern char *__progname;
17395  
17396 @@ -306,6 +309,261 @@ do_file(AuthenticationConnection *ac, in
17397     return 0;
17398  }
17399  
17400 +#ifndef SSH_PKCS11_DISABLED
17401 +
17402 +static
17403 +int
17404 +do_pkcs11 (AuthenticationConnection *ac, int argc, char *argv[])
17405 +{
17406 +   /*
17407 +    * TEMP TEMP TEMP TEMP
17408 +    *
17409 +    * This should be fixed if another mechanism
17410 +    * will be propsed.
17411 +    */
17412 +   pkcs11_identity *id = NULL;
17413 +   char *szPKCS11Provider = NULL;
17414 +   char *szPKCS11Id = NULL;
17415 +   char *szPKCS11SignMode = NULL;
17416 +   char *szPKCS11AskPIN = NULL;
17417 +   char *szPKCS11SlotId = NULL;
17418 +   char *szPKCS11CertFile = NULL;
17419 +   int fDebug = 0;
17420 +   int fPKCS11AddProvider = 0;
17421 +   int fPKCS11AddId = 0;
17422 +   int fPKCS11RemoveId = 0;
17423 +   int fPKCS11ShowIds = 0;
17424 +   int fPKCS11DumpSlots = 0;
17425 +   int fPKCS11DumpObjects = 0;
17426 +   int fPKCS11ProtectedAuthentication = 0;
17427 +   int fPKCS11CertPrivate = 0;
17428 +   int nPKCS11PINCachePeriod = -1;
17429 +   int fBadUsage = 0;
17430 +   int ret = 0;
17431 +   int nSkipPrmCount;
17432 +   int i;
17433 +
17434 +   for (i=0,nSkipPrmCount=0;i<argc;i++) {
17435 +       if (!strcmp (argv[i], "--pkcs11-provider")) {
17436 +           szPKCS11Provider = argv[i+1];
17437 +           i++;
17438 +       }
17439 +       else if (!strcmp (argv[i], "--pkcs11-id")) {
17440 +           szPKCS11Id = argv[i+1];
17441 +           i++;
17442 +       }
17443 +       else if (!strcmp (argv[i], "--pkcs11-pin-cache")) {
17444 +           nPKCS11PINCachePeriod = atoi (argv[i+1]);
17445 +           i++;
17446 +       }
17447 +       else if (!strcmp (argv[i], "--pkcs11-sign-mode")) {
17448 +           szPKCS11SignMode = argv[i+1];
17449 +           i++;
17450 +       }
17451 +       else if (!strcmp (argv[i], "--pkcs11-ask-pin")) {
17452 +           szPKCS11AskPIN = argv[i+1];
17453 +           i++;
17454 +       }
17455 +       else if (!strcmp (argv[i], "--pkcs11-slot")) {
17456 +           szPKCS11SlotId = argv[i+1];
17457 +           i++;
17458 +       }
17459 +       else if (!strcmp (argv[i], "--pkcs11-cert-file")) {
17460 +           szPKCS11CertFile = argv[i+1];
17461 +           i++;
17462 +       }
17463 +       else if (!strcmp (argv[i], "--pkcs11-add-provider")) {
17464 +           fPKCS11AddProvider = 1;
17465 +       }
17466 +       else if (!strcmp (argv[i], "--pkcs11-remove-id")) {
17467 +           fPKCS11RemoveId = 1;
17468 +       }
17469 +       else if (!strcmp (argv[i], "--pkcs11-add-id")) {
17470 +           fPKCS11AddId = 1;
17471 +       }
17472 +       else if (!strcmp (argv[i], "--pkcs11-show-ids")) {
17473 +           fPKCS11ShowIds = 1;
17474 +       }
17475 +       else if (!strcmp (argv[i], "--pkcs11-dump-slots")) {
17476 +           fPKCS11DumpSlots = 1;
17477 +       }
17478 +       else if (!strcmp (argv[i], "--pkcs11-dump-objects")) {
17479 +           fPKCS11DumpObjects = 1;
17480 +       }
17481 +       else if (!strcmp (argv[i], "--pkcs11-protected-authentication")) {
17482 +           fPKCS11ProtectedAuthentication = 1;
17483 +       }
17484 +       else if (!strcmp (argv[i], "--pkcs11-cert-private")) {
17485 +           fPKCS11CertPrivate = 1;
17486 +       }
17487 +       else if (!strcmp (argv[i], "-d")) {
17488 +           fDebug = 1;
17489 +       }
17490 +       else {
17491 +           nSkipPrmCount++;
17492 +       }
17493 +   }
17494 +
17495 +   if (nSkipPrmCount == argc) {
17496 +       /* no pkcs#11 arguments */
17497 +       ret = -2;
17498 +   }
17499 +
17500 +   if (ret == 0) {
17501 +       if (
17502 +           !fBadUsage &&
17503 +           fPKCS11AddProvider &&
17504 +           szPKCS11Provider == NULL
17505 +       ) {
17506 +           fBadUsage = 1;
17507 +       }
17508 +
17509 +       if (
17510 +           !fBadUsage &&
17511 +           fPKCS11AddId &&
17512 +           (
17513 +               szPKCS11Id == NULL
17514 +           )
17515 +       ) {
17516 +           fBadUsage = 1;
17517 +       }
17518 +
17519 +       if (
17520 +           !fBadUsage &&
17521 +           fPKCS11RemoveId &&
17522 +           (
17523 +               szPKCS11Id == NULL
17524 +           )
17525 +       ) {
17526 +           fBadUsage = 1;
17527 +       }
17528 +
17529 +       if (
17530 +           !fBadUsage &&
17531 +           fPKCS11ShowIds &&
17532 +           szPKCS11Provider == NULL
17533 +       ) {
17534 +           fBadUsage = 1;
17535 +       }
17536 +
17537 +       if (
17538 +           !fBadUsage &&
17539 +           fPKCS11DumpSlots &&
17540 +           szPKCS11Provider == NULL
17541 +       ) {
17542 +           fBadUsage = 1;
17543 +       }
17544 +
17545 +       if (
17546 +           !fBadUsage &&
17547 +           fPKCS11DumpObjects &&
17548 +           (
17549 +               szPKCS11Provider == NULL ||
17550 +               szPKCS11SlotId == NULL
17551 +           )
17552 +       ) {
17553 +           fBadUsage = 1;
17554 +       }
17555 +
17556 +       if (fBadUsage) {
17557 +           usage ();
17558 +           ret = 1;
17559 +       }
17560 +   }
17561 +   
17562 +   if (ret == 0) {
17563 +       if (fPKCS11AddId || fPKCS11RemoveId) {
17564 +           id = pkcs11_identity_new ();
17565 +           if (id == NULL) {
17566 +               ret = 1;
17567 +           }
17568 +           else {
17569 +               id->id = strdup (szPKCS11Id);
17570 +               id->pin_cache_period = nPKCS11PINCachePeriod;
17571 +               id->cert_file = szPKCS11CertFile;
17572 +           }
17573 +       }
17574 +   }
17575 +
17576 +   if (ret == 0) {
17577 +       if (fDebug) {
17578 +           log_init(__progname, SYSLOG_LEVEL_DEBUG3, SYSLOG_FACILITY_AUTH, 1);
17579 +       }
17580 +
17581 +       if (fPKCS11ShowIds) {
17582 +           pkcs11_show_ids (szPKCS11Provider, fPKCS11ProtectedAuthentication, fPKCS11CertPrivate);
17583 +           ret = 0;
17584 +       }
17585 +       else if (fPKCS11DumpSlots) {
17586 +           pkcs11_dump_slots (szPKCS11Provider);
17587 +           ret = 0;
17588 +       }
17589 +       else if (fPKCS11DumpObjects) {
17590 +           char *szPIN = read_passphrase("PIN: ", RP_ALLOW_STDIN);
17591 +           if (szPIN[0] != '\0') {
17592 +               pkcs11_dump_objects (szPKCS11Provider, szPKCS11SlotId, szPIN);
17593 +           }
17594 +           memset (szPIN, 0, strlen (szPIN));
17595 +           xfree (szPIN);
17596 +           ret = 0;
17597 +       }
17598 +       else if (szPKCS11AskPIN != NULL) {
17599 +           ret = !ssh_pkcs11_set_ask_pin (ac, szPKCS11AskPIN);
17600 +
17601 +           if (ret) {
17602 +               fprintf (stderr, "Failed\n");
17603 +           }
17604 +           else {
17605 +               fprintf (stderr, "Success\n");
17606 +           }
17607 +       }
17608 +       else if (fPKCS11AddProvider) {
17609 +           ret = !ssh_pkcs11_add_provider (
17610 +               ac,
17611 +               szPKCS11Provider,
17612 +               fPKCS11ProtectedAuthentication,
17613 +               szPKCS11SignMode,
17614 +               fPKCS11CertPrivate
17615 +           );
17616 +
17617 +           if (ret) {
17618 +               fprintf (stderr, "Cannot add provider %s\n", szPKCS11Provider);
17619 +           }
17620 +           else {
17621 +               fprintf (stderr, "Provider %s added successfully\n", szPKCS11Provider);
17622 +           }
17623 +       }
17624 +       else if (fPKCS11AddId) {
17625 +           ret = !ssh_pkcs11_id (ac, id, 0);
17626 +
17627 +           if (ret) {
17628 +               fprintf (stderr, "Cannot add identity\n");
17629 +           }
17630 +           else {
17631 +               fprintf (stderr, "Identity added successfully\n");
17632 +           }
17633 +       }
17634 +       else if (fPKCS11RemoveId) {
17635 +           ret = !ssh_pkcs11_id (ac, id, 1);
17636 +
17637 +           if (ret) {
17638 +               fprintf (stderr, "Cannot remove identity\n");
17639 +           }
17640 +           else {
17641 +               fprintf (stderr, "Identity removed successfully\n");
17642 +           }
17643 +       }
17644 +   }
17645 +
17646 +   if (id != NULL) {
17647 +       pkcs11_identity_free (id);
17648 +   }
17649 +
17650 +   return ret;
17651 +}
17652 +
17653 +#endif /* SSH_PKCS11_DISABLED */
17654 +
17655  static void
17656  usage(void)
17657  {
17658 @@ -323,6 +581,50 @@ usage(void)
17659     fprintf(stderr, "  -s reader   Add key in smartcard reader.\n");
17660     fprintf(stderr, "  -e reader   Remove key in smartcard reader.\n");
17661  #endif
17662 +#ifndef SSH_PKCS11_DISABLED
17663 +   fprintf(
17664 +       stderr,
17665 +       (
17666 +           "\n"
17667 +               "  PKCS#11 Options:\n"
17668 +           "  --pkcs11-ask-pin prog          Set ask-pin program\n"
17669 +           "\n"
17670 +           "  --pkcs11-add-provider          Add PKCS#11 provider\n"
17671 +           "    --pkcs11-provider provider   PKCS#11 provider library\n"
17672 +           "    [--pkcs11-protected-authentication] Use PKCS#11 protected authentication\n"
17673 +           "    [--pkcs11-sign-mode mode]    Provider signature mode\n"
17674 +           "                                  auto    - determine automatically\n"
17675 +           "                                  sign    - perform sign\n"
17676 +           "                                  recover - perform sign recover\n"
17677 +           "                                  any     - perform sign and then sign recover\n"
17678 +           "    [--pkcs11-cert-private]       Login required in order to access certificate\n"
17679 +           "\n"
17680 +           "  --pkcs11-show-ids              Show available identities\n"
17681 +           "    --pkcs11-provider provider   PKCS#11 provider library\n"
17682 +           "    [--pkcs11-protected-authentication] Use PKCS#11 protected authentication\n"
17683 +           "    [--pkcs11-cert-private]       Login required in order to access certificate\n"
17684 +           "    [-d]                         debug\n"  
17685 +           "\n"
17686 +           "  --pkcs11-add-id                Add PKCS#11 identity\n"
17687 +           "    --pkcs11-id id                Serialized string\n"
17688 +           "    [--pkcs11-cert-file file]     Use this PEM file, don't access token\n"
17689 +           "    [--pkcs11-pin-cache period]   PIN cache period (seconds)\n"
17690 +           "\n"
17691 +           "  --pkcs11-remove-id             Remove PKCS#11 identity\n"
17692 +           "    --pkcs11-id id                Serialized string\n"
17693 +           "    [--pkcs11-cert-file file]     Use this PEM file, don't access token\n"
17694 +           "\n"
17695 +           " PKCS#11 Debugging Options:\n"
17696 +           "  --pkcs11-dump-slots            Dump available PKCS#11 slots\n"
17697 +           "    --pkcs11-provider provider   PKCS#11 provider library\n"
17698 +           "\n"
17699 +           "  --pkcs11-dump-objects          Dump available PKCS#11 objects\n"
17700 +           "    --pkcs11-provider provider   PKCS#11 provider library\n"
17701 +           "    --pkcs11-slot slot           Slot numeric id\n"
17702 +           "\n"
17703 +       )
17704 +   );
17705 +#endif  /* SSH_PKCS11_DISABLED */
17706  }
17707  
17708  int
17709 @@ -350,6 +652,17 @@ main(int argc, char **argv)
17710             "Could not open a connection to your authentication agent.\n");
17711         exit(2);
17712     }
17713 +
17714 +#ifndef SSH_PKCS11_DISABLED
17715 +   {
17716 +       int r = do_pkcs11 (ac, argc, argv);
17717 +       if (r != -2) {
17718 +           ret = r;
17719 +           goto done;
17720 +       }
17721 +   }
17722 +#endif /* SSH_PKCS11_DISABLED */
17723 +
17724     while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
17725         switch (ch) {
17726         case 'l':
17727 diff -urNp openssh-4.4p1/ssh-agent.c openssh-4.4p1+pkcs11-0.17/ssh-agent.c
17728 --- openssh-4.4p1/ssh-agent.c   2006-09-01 08:38:37.000000000 +0300
17729 +++ openssh-4.4p1+pkcs11-0.17/ssh-agent.c   2006-10-12 14:00:53.000000000 +0200
17730 @@ -71,6 +71,7 @@
17731  #include "buffer.h"
17732  #include "key.h"
17733  #include "authfd.h"
17734 +#include "pkcs11.h"
17735  #include "compat.h"
17736  #include "log.h"
17737  #include "misc.h"
17738 @@ -690,6 +691,157 @@ send:
17739  }
17740  #endif /* SMARTCARD */
17741  
17742 +#ifndef SSH_PKCS11_DISABLED
17743 +
17744 +static
17745 +void
17746 +process_pkcs11_set_ask_pin (SocketEntry *e)
17747 +{
17748 +   char *szAskPIN = NULL;
17749 +   int success = 0;
17750 +
17751 +   szAskPIN = buffer_get_string(&e->request, NULL);
17752 +
17753 +   success = pkcs11_setAskPIN (szAskPIN);
17754 +
17755 +   buffer_put_int(&e->output, 1);
17756 +   buffer_put_char(&e->output,
17757 +       success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
17758 +}
17759 +
17760 +static void
17761 +process_pkcs11_add_provider (SocketEntry *e)
17762 +{
17763 +   char *szProvider = NULL;
17764 +   int fProtectedAuthentication = 0;
17765 +   char *szSignMode = NULL;
17766 +   int fCertIsPrivate = 0;
17767 +   int success = 0;
17768 +
17769 +   szProvider = buffer_get_string(&e->request, NULL);
17770 +   fProtectedAuthentication = buffer_get_int (&e->request);
17771 +   szSignMode = buffer_get_string(&e->request, NULL);
17772 +   fCertIsPrivate = buffer_get_int (&e->request);
17773 +
17774 +   success = pkcs11_addProvider (szProvider, fProtectedAuthentication, szSignMode, fCertIsPrivate);
17775 +
17776 +   buffer_put_int(&e->output, 1);
17777 +   buffer_put_char(&e->output,
17778 +       success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
17779 +}
17780 +
17781 +static
17782 +void
17783 +process_pkcs11_add_id (SocketEntry *e)
17784 +{
17785 +   int success = 0;
17786 +   int version = 2;
17787 +   char szComment[1024];
17788 +   Key *k = NULL;
17789 +   pkcs11_identity *pkcs11_id = NULL;
17790 +
17791 +   pkcs11_id = pkcs11_identity_new ();
17792 +   if (pkcs11_id != NULL) {
17793 +       pkcs11_id->id = strdup (buffer_get_string(&e->request, NULL));
17794 +       pkcs11_id->pin_cache_period = buffer_get_int(&e->request);
17795 +       pkcs11_id->cert_file = strdup (buffer_get_string(&e->request, NULL));
17796 +
17797 +       pkcs11_getKey (
17798 +           pkcs11_id,
17799 +           &k,
17800 +           szComment,
17801 +           sizeof (szComment)
17802 +       );
17803 +
17804 +       if (k != NULL) {
17805 +           if (lookup_identity(k, version) == NULL) {
17806 +               Identity *id = xmalloc(sizeof(Identity));
17807 +               Idtab *tab = NULL;
17808 +   
17809 +               id->key = k;
17810 +               k = NULL;
17811 +               id->comment = xstrdup (szComment);
17812 +               id->death = 0;      /* handled by pkcs#11 helper */
17813 +               id->confirm = 0;
17814 +   
17815 +               tab = idtab_lookup(version);
17816 +               TAILQ_INSERT_TAIL(&tab->idlist, id, next);
17817 +               /* Increment the number of identities. */
17818 +               tab->nentries++;
17819 +               success = 1;
17820 +           }
17821 +       }
17822 +   }
17823 +
17824 +   if (k != NULL) {
17825 +       key_free (k);
17826 +   }
17827 +
17828 +   if (pkcs11_id != NULL) {
17829 +       pkcs11_identity_free (pkcs11_id);
17830 +   }
17831 +
17832 +   buffer_put_int(&e->output, 1);
17833 +   buffer_put_char(&e->output,
17834 +       success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
17835 +}
17836 +
17837 +static
17838 +void
17839 +process_pkcs11_remove_id (SocketEntry *e)
17840 +{
17841 +   int success = 0;
17842 +   Identity *id = NULL;
17843 +   int version = 2;
17844 +   char szComment[1024];
17845 +   Key *k = NULL;
17846 +
17847 +   pkcs11_identity *pkcs11_id = NULL;
17848 +
17849 +   pkcs11_id = pkcs11_identity_new ();
17850 +   if (pkcs11_id != NULL) {
17851 +       pkcs11_id->id = strdup (buffer_get_string(&e->request, NULL));
17852 +       pkcs11_id->pin_cache_period = buffer_get_int(&e->request);
17853 +       pkcs11_id->cert_file = strdup (buffer_get_string(&e->request, NULL));
17854 +
17855 +       pkcs11_getKey (
17856 +           pkcs11_id,
17857 +           &k,
17858 +           szComment,
17859 +           sizeof (szComment)
17860 +       );
17861 +
17862 +       if (k != NULL) {
17863 +           id = lookup_identity (k, version);
17864 +       }
17865 +
17866 +       if (id != NULL) {
17867 +           Idtab *tab = NULL;
17868 +
17869 +           tab = idtab_lookup(version);
17870 +           TAILQ_REMOVE(&tab->idlist, id, next);
17871 +           tab->nentries--;
17872 +           free_identity(id);
17873 +           id = NULL;
17874 +           success = 1;
17875 +       }
17876 +   }
17877 +
17878 +   if (k != NULL) {
17879 +       key_free (k);
17880 +   }
17881 +
17882 +   if (pkcs11_id != NULL) {
17883 +       pkcs11_identity_free (pkcs11_id);
17884 +   }
17885 +
17886 +   buffer_put_int(&e->output, 1);
17887 +   buffer_put_char(&e->output,
17888 +       success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
17889 +}
17890 +
17891 +#endif /* SSH_PKCS11_DISABLED */
17892 +
17893  /* dispatch incoming messages */
17894  
17895  static void
17896 @@ -785,6 +937,21 @@ process_message(SocketEntry *e)
17897         process_remove_smartcard_key(e);
17898         break;
17899  #endif /* SMARTCARD */
17900 +
17901 +#ifndef SSH_PKCS11_DISABLED
17902 +   case SSH_AGENTC_PKCS11_SET_ASK_PIN:
17903 +       process_pkcs11_set_ask_pin (e);
17904 +       break;
17905 +   case SSH_AGENTC_PKCS11_ADD_PROVIDER:
17906 +       process_pkcs11_add_provider (e);
17907 +       break;
17908 +   case SSH_AGENTC_PKCS11_ADD_ID:
17909 +       process_pkcs11_add_id (e);
17910 +       break;
17911 +   case SSH_AGENTC_PKCS11_REMOVE_ID:
17912 +       process_pkcs11_remove_id (e);
17913 +       break;
17914 +#endif /* SSH_PKCS11_DISABLED */
17915     default:
17916         /* Unknown message.  Respond with failure. */
17917         error("Unknown message %d", type);
17918 @@ -1064,7 +1231,7 @@ main(int ac, char **av)
17919             s_flag++;
17920             break;
17921         case 'd':
17922 -           if (d_flag)
17923 +           if (d_flag > 3)
17924                 usage();
17925             d_flag++;
17926             break;
17927 @@ -1167,7 +1334,7 @@ main(int ac, char **av)
17928      * the socket data.  The child continues as the authentication agent.
17929      */
17930     if (d_flag) {
17931 -       log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
17932 +       log_init(__progname, SYSLOG_LEVEL_DEBUG1+d_flag-1, SYSLOG_FACILITY_AUTH, 1);
17933         format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
17934         printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
17935             SSH_AUTHSOCKET_ENV_NAME);
17936 @@ -1228,6 +1395,11 @@ main(int ac, char **av)
17937  #endif
17938  
17939  skip:
17940 +
17941 +#ifndef SSH_PKCS11_DISABLED
17942 +   pkcs11_initialize (1, -1);
17943 +#endif /* SSH_PKCS11_DISABLED */
17944 +
17945     new_socket(AUTH_SOCKET, sock);
17946     if (ac > 0) {
17947         mysignal(SIGALRM, check_parent_exists);
17948 @@ -1251,4 +1423,8 @@ skip:
17949         after_select(readsetp, writesetp);
17950     }
17951     /* NOTREACHED */
17952 +
17953 +#ifndef SSH_PKCS11_DISABLED
17954 +   pkcs11_terminate ();
17955 +#endif /* SSH_PKCS11_DISABLED */
17956  }
4577392 [rkeene@sledge /home/rkeene/archive/openssh]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2021-11-13 19:21:37