Check-in [074f157a6a]
Overview
Comment:Copied SSH Agent PKCS11 Provider to CACKey for use as a base
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:074f157a6ae0d5c41e130ad9c225aebfa74a3cc3
User & Date: rkeene on 2010-05-04 19:04:53
Other Links: manifest | tags
Context
2010-05-11
16:49
Removed unused variables

Began work towards talking to the smartcard through PC/SC

Began work on a GSC-IS v2.1 SPM implementation check-in: 40726d3b6c user: rkeene tags: trunk

2010-05-04
19:04
Copied SSH Agent PKCS11 Provider to CACKey for use as a base check-in: 074f157a6a user: rkeene tags: trunk
18:30
Added checks for PCSC Header

Updated ignores check-in: 8a2230f927 user: rkeene tags: trunk

Changes

Modified cackey.c from [02188b8075] to [f34f4e9e63].

     1      1   #ifdef HAVE_CONFIG_H
     2      2   #include "config.h"
     3      3   #endif
     4      4   
     5      5   #ifdef HAVE_PCSCLITE_H
     6         -#include <pcsclite.h>
            6  +#  include <pcsclite.h>
            7  +#endif
            8  +#ifdef HAVE_STDINT_H
            9  +#  include <stdint.h>
           10  +#endif
           11  +#ifdef HAVE_INTTYPES_H
           12  +#  include <inttypes.h>
           13  +#endif
           14  +#ifdef HAVE_STDLIB_H
           15  +#  include <stdlib.h>
           16  +#endif
           17  +#ifdef HAVE_UNISTD_H
           18  +#  include <unistd.h>
           19  +#endif
           20  +#ifdef HAVE_STRING_H
           21  +#  include <string.h>
           22  +#endif
           23  +#ifdef HAVE_PTHREAD_H
           24  +#  include <pthread.h>
           25  +#endif
           26  +
           27  +#define CK_PTR *
           28  +#define CK_DEFINE_FUNCTION(returnType, name) returnType name
           29  +#define CK_DECLARE_FUNCTION(returnType, name) returnType name
           30  +#define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
           31  +#define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
           32  +#ifndef NULL_PTR
           33  +#  define NULL_PTR 0
           34  +#endif
           35  +
           36  +#include "pkcs11.h"
           37  +
           38  +#ifndef CACKEY_CRYPTOKI_VERSION_CODE
           39  +#  define CACKEY_CRYPTOKI_VERSION_CODE 0x021e00
           40  +#endif
           41  +
           42  +#ifdef CACKEY_DEBUG
           43  +#  ifdef HAVE_STDIO_H
           44  +#    include <stdio.h>
           45  +#  endif
           46  +
           47  +#  define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); }
           48  +#  define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *buf; unsigned long idx; buf = (unsigned char *) (x); fprintf(stderr, "%s(): %s  (%s/%lu = {%02x", __func__, f, #x, (unsigned long) (y), buf[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", buf[idx]); }; fprintf(stderr, "})\n"); }
           49  +#  define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s(): ", __func__); perror(x); }
           50  +#  define free(x) { CACKEY_DEBUG_PRINTF("FREE(%p) (%s)", x, #x); free(x); }
           51  +
           52  +static void *CACKEY_DEBUG_FUNC_MALLOC(size_t size, const char *func) {
           53  +	void *retval;
           54  +
           55  +	retval = malloc(size);
           56  +
           57  +	fprintf(stderr, "%s(): ", func);
           58  +	fprintf(stderr, "MALLOC() = %p", retval);
           59  +	fprintf(stderr, "\n");
           60  +
           61  +	return(retval);
           62  +}
           63  +
           64  +static void *CACKEY_DEBUG_FUNC_REALLOC(void *ptr, size_t size, const char *func) {
           65  +	void *retval;
           66  +
           67  +	retval = realloc(ptr, size);
           68  +
           69  +	if (retval != ptr) {
           70  +		fprintf(stderr, "%s(): ", func);
           71  +		fprintf(stderr, "REALLOC(%p) = %p", ptr, retval);
           72  +		fprintf(stderr, "\n");
           73  +	}
           74  +
           75  +	return(retval);
           76  +}
           77  +
           78  +#  define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__)
           79  +#  define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__)
           80  +#else
           81  +#  define CACKEY_DEBUG_PRINTF(x...) /**/
           82  +#  define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/
           83  +#  define CACKEY_DEBUG_PERROR(x) /**/
           84  +#endif
           85  +
           86  +#ifndef CKA_TRUST_SERVER_AUTH
           87  +#  define CKA_TRUST_SERVER_AUTH 0xce536358
           88  +#endif
           89  +#ifndef CKA_TRUST_CLIENT_AUTH
           90  +#  define CKA_TRUST_CLIENT_AUTH 0xce536359
           91  +#endif
           92  +#ifndef CKA_TRUST_CODE_SIGNING
           93  +#  define CKA_TRUST_CODE_SIGNING 0xce53635a
           94  +#endif
           95  +#ifndef CKA_TRUST_EMAIL_PROTECTION
           96  +#  define CKA_TRUST_EMAIL_PROTECTION 0xce53635b
           97  +#endif
           98  +
           99  +struct cackey_identity {
          100  +	CK_ATTRIBUTE *attributes;
          101  +	CK_ULONG attributes_count;
          102  +};
          103  +
          104  +struct cackey_session {
          105  +	int active;
          106  +
          107  +	CK_SLOT_ID slotID;
          108  +	CK_STATE state;
          109  +	CK_FLAGS flags;
          110  +	CK_ULONG ulDeviceError;
          111  +	CK_VOID_PTR pApplication;
          112  +	CK_NOTIFY Notify;
          113  +
          114  +	struct cackey_identity *identities;
          115  +	unsigned long identities_count;
          116  +
          117  +	int search_active;
          118  +	CK_ATTRIBUTE_PTR search_query;
          119  +	CK_ULONG search_query_count;
          120  +	unsigned long search_curr_id;
          121  +
          122  +	int sign_active;
          123  +	CK_MECHANISM_TYPE sign_mechanism;
          124  +	CK_BYTE_PTR sign_buf;
          125  +	unsigned long sign_buflen;
          126  +	unsigned long sign_bufused;
          127  +
          128  +	int decrypt_active;
          129  +	CK_MECHANISM_TYPE decrypt_mechanism;
          130  +	CK_VOID_PTR decrypt_mech_parm;
          131  +	CK_ULONG decrypt_mech_parmlen;
          132  +};
          133  +
          134  +static void *cackey_biglock = NULL;
          135  +static struct cackey_session cackey_sessions[8];
          136  +static int cackey_initialized = 0;
          137  +static int cackey_biglock_init = 0;
          138  +CK_C_INITIALIZE_ARGS cackey_args;
          139  +
          140  +static unsigned long cackey_getversion(void) {
          141  +	static unsigned long retval = 255;
          142  +	unsigned long major = 0;
          143  +	unsigned long minor = 0;
          144  +	char *major_str = NULL;
          145  +	char *minor_str = NULL;
          146  +
          147  +	CACKEY_DEBUG_PRINTF("Called.");
          148  +
          149  +	if (retval != 255) {
          150  +		CACKEY_DEBUG_PRINTF("Returning 0x%lx (cached).", retval);
          151  +
          152  +		return(retval);
          153  +	}
          154  +
          155  +	retval = 0;
          156  +
          157  +#ifdef PACKAGE_VERSION
          158  +        major_str = PACKAGE_VERSION;
          159  +	if (major_str) {
          160  +	        major = strtoul(major_str, &minor_str, 10);
          161  +
          162  +		if (minor_str) {
          163  +			minor = strtoul(minor_str + 1, NULL, 10);
          164  +		}
          165  +	}
          166  +
          167  +	retval = (major << 16) | (minor << 8);
     7    168   #endif
     8    169   
          170  +	CACKEY_DEBUG_PRINTF("Returning 0x%lx", retval);
          171  +
          172  +	return(retval);
          173  +}
          174  +
          175  +/* Returns 0 on success */
          176  +static int cackey_mutex_create(void **mutex) {
          177  +	pthread_mutex_t *pthread_mutex;
          178  +	int pthread_retval;
          179  +	CK_RV custom_retval;
          180  +
          181  +	CACKEY_DEBUG_PRINTF("Called.");
          182  +
          183  +	if ((cackey_args.flags & CKF_OS_LOCKING_OK) == CKF_OS_LOCKING_OK) {
          184  +		pthread_mutex = malloc(sizeof(*pthread_mutex));
          185  +		if (!pthread_mutex) {
          186  +			CACKEY_DEBUG_PRINTF("Failed to allocate memory.");
          187  +
          188  +			return(-1);
          189  +		}
          190  +
          191  +		pthread_retval = pthread_mutex_init(pthread_mutex, NULL);
          192  +		if (pthread_retval != 0) {
          193  +			CACKEY_DEBUG_PRINTF("pthread_mutex_init() returned error (%i).", pthread_retval);
          194  +
          195  +			return(-1);
          196  +		}
          197  +
          198  +		*mutex = pthread_mutex;
          199  +	} else {
          200  +		if (cackey_args.CreateMutex) {
          201  +			custom_retval = cackey_args.CreateMutex(mutex);
          202  +
          203  +			if (custom_retval != CKR_OK) {
          204  +				CACKEY_DEBUG_PRINTF("cackey_args.CreateMutex() returned error (%li).", (long) custom_retval);
          205  +
          206  +				return(-1);
          207  +			}
          208  +		}
          209  +	}
          210  +
          211  +	CACKEY_DEBUG_PRINTF("Returning sucessfully (0)");
          212  +
          213  +	return(0);
          214  +}
          215  +
          216  +/* Returns 0 on success */
          217  +static int cackey_mutex_lock(void *mutex) {
          218  +	pthread_mutex_t *pthread_mutex;
          219  +	int pthread_retval;
          220  +	CK_RV custom_retval;
          221  +
          222  +	CACKEY_DEBUG_PRINTF("Called.");
          223  +
          224  +	if ((cackey_args.flags & CKF_OS_LOCKING_OK) == CKF_OS_LOCKING_OK) {
          225  +		pthread_mutex = mutex;
          226  +
          227  +		pthread_retval = pthread_mutex_lock(pthread_mutex);
          228  +		if (pthread_retval != 0) {
          229  +			CACKEY_DEBUG_PRINTF("pthread_mutex_lock() returned error (%i).", pthread_retval);
          230  +
          231  +			return(-1);
          232  +		}
          233  +	} else {
          234  +		if (cackey_args.LockMutex) {
          235  +			custom_retval = cackey_args.LockMutex(mutex);
          236  +
          237  +			if (custom_retval != CKR_OK) {
          238  +				CACKEY_DEBUG_PRINTF("cackey_args.LockMutex() returned error (%li).", (long) custom_retval);
          239  +
          240  +				return(-1);
          241  +			}
          242  +		}
          243  +	}
          244  +
          245  +	CACKEY_DEBUG_PRINTF("Returning sucessfully (0)");
          246  +
          247  +	return(0);
          248  +}
          249  +
          250  +/* Returns 0 on success */
          251  +static int cackey_mutex_unlock(void *mutex) {
          252  +	pthread_mutex_t *pthread_mutex;
          253  +	int pthread_retval;
          254  +	CK_RV custom_retval;
          255  +
          256  +	CACKEY_DEBUG_PRINTF("Called.");
          257  +
          258  +	if ((cackey_args.flags & CKF_OS_LOCKING_OK) == CKF_OS_LOCKING_OK) {
          259  +		pthread_mutex = mutex;
          260  +
          261  +		pthread_retval = pthread_mutex_unlock(pthread_mutex);
          262  +		if (pthread_retval != 0) {
          263  +			CACKEY_DEBUG_PRINTF("pthread_mutex_unlock() returned error (%i).", pthread_retval);
          264  +
          265  +			return(-1);
          266  +		}
          267  +	} else {
          268  +		if (cackey_args.UnlockMutex) {
          269  +			custom_retval = cackey_args.UnlockMutex(mutex);
          270  +
          271  +			if (custom_retval != CKR_OK) {
          272  +				CACKEY_DEBUG_PRINTF("cackey_args.UnlockMutex() returned error (%li).", (long) custom_retval);
          273  +
          274  +				return(-1);
          275  +			}
          276  +		}
          277  +	}
          278  +
          279  +	CACKEY_DEBUG_PRINTF("Returning sucessfully (0)");
          280  +
          281  +	return(0);
          282  +}
          283  +
          284  +static CK_ATTRIBUTE_PTR cackey_get_attributes(CK_OBJECT_CLASS objectclass, void *identity, unsigned long identity_num, CK_ULONG_PTR pulCount) {
          285  +	static CK_BBOOL ck_true = 1;
          286  +	static CK_BBOOL ck_false = 0;
          287  +	CK_ULONG numattrs = 0, retval_count;
          288  +	CK_ATTRIBUTE_TYPE curr_attr_type;
          289  +	CK_ATTRIBUTE curr_attr, *retval;
          290  +	CK_VOID_PTR pValue;
          291  +	CK_ULONG ulValueLen;
          292  +	CK_OBJECT_CLASS ck_object_class;
          293  +	CK_CERTIFICATE_TYPE ck_certificate_type;
          294  +	CK_KEY_TYPE ck_key_type;
          295  +	CK_UTF8CHAR ucTmpBuf[1024];
          296  +	unsigned char certificate[16384];
          297  +	ssize_t getcert_ret, certificate_len = -1, x509_read_ret;
          298  +	int fd;
          299  +	int pValue_free;
          300  +
          301  +	CACKEY_DEBUG_PRINTF("Called (objectClass = %lu, identity_num = %lu).", (unsigned long) objectclass, identity_num);
          302  +
          303  +	if (objectclass != CKO_CERTIFICATE && objectclass != CKO_PUBLIC_KEY && objectclass != CKO_PRIVATE_KEY) {
          304  +		CACKEY_DEBUG_PRINTF("Returning 0 objects (NULL), invalid object class");
          305  +
          306  +		return(NULL);
          307  +	}
          308  +
          309  +	retval_count = 16;
          310  +	retval = malloc(retval_count * sizeof(*retval));
          311  +
          312  +	/* XXX: Get Cert */
          313  +	certificate_len = -1;
          314  +
          315  +	if (certificate_len == -1) {
          316  +		CACKEY_DEBUG_PRINTF("Returning 0 objects (NULL), this identity does not have an X.509 certificate associated with it and will not work");
          317  +
          318  +		return(NULL);
          319  +	}
          320  +
          321  +	for (curr_attr_type = 0; curr_attr_type < 0xce53635f; curr_attr_type++) {
          322  +		if (curr_attr_type == 0x800) {
          323  +			curr_attr_type = 0xce536300;
          324  +		}
          325  +
          326  +		pValue_free = 0;
          327  +		pValue = NULL;
          328  +		ulValueLen = (CK_LONG) -1;
          329  +
          330  +		switch (curr_attr_type) {
          331  +			case CKA_CLASS:
          332  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_CLASS (0x%08lx) ...", (unsigned long) curr_attr_type);
          333  +
          334  +				ck_object_class = objectclass;
          335  +
          336  +				pValue = &ck_object_class;
          337  +				ulValueLen = sizeof(ck_object_class);
          338  +
          339  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_OBJECT_CLASS *) pValue), pValue, (unsigned long) ulValueLen);
          340  +
          341  +				break;
          342  +			case CKA_TOKEN:
          343  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_TOKEN (0x%08lx) ...", (unsigned long) curr_attr_type);
          344  +
          345  +				pValue = &ck_true;
          346  +				ulValueLen = sizeof(ck_true);
          347  +
          348  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          349  +
          350  +				break;
          351  +			case CKA_MODIFIABLE:
          352  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_MODIFIABLE (0x%08lx) ...", (unsigned long) curr_attr_type);
          353  +
          354  +				pValue = &ck_false;
          355  +				ulValueLen = sizeof(ck_false);
          356  +
          357  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          358  +
          359  +				break;
          360  +			case CKA_LABEL:
          361  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_LABEL (0x%08lx) ...", (unsigned long) curr_attr_type);
          362  +
          363  +				/* XXX: Determine name */
          364  +
          365  +				CACKEY_DEBUG_PRINTF(" ... returning %s (%p/%lu)", (char *) ((CK_UTF8CHAR *) pValue), pValue, (unsigned long) ulValueLen);
          366  +
          367  +				break;
          368  +			case CKA_VALUE:
          369  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_VALUE (0x%08lx) ...", (unsigned long) curr_attr_type);
          370  +
          371  +				switch (objectclass) {
          372  +					case CKO_PRIVATE_KEY:
          373  +						CACKEY_DEBUG_PRINTF(" ... but not getting it because we are a private key.");
          374  +
          375  +						break;
          376  +					case CKO_PUBLIC_KEY:
          377  +						/* XXX: TODO */
          378  +
          379  +						break;
          380  +					case CKO_CERTIFICATE:
          381  +						pValue = certificate;
          382  +						ulValueLen = certificate_len;
          383  +
          384  +						break;
          385  +				}
          386  +
          387  +				CACKEY_DEBUG_PRINTF(" ... returning %p/%lu", pValue, (unsigned long) ulValueLen);
          388  +
          389  +				break;
          390  +			case CKA_ISSUER:
          391  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_ISSUER (0x%08lx) ...", (unsigned long) curr_attr_type);
          392  +
          393  +				if (objectclass != CKO_CERTIFICATE) {
          394  +					CACKEY_DEBUG_PRINTF(" ... but not getting it because we are not a certificate.");
          395  +
          396  +					break;
          397  +				}
          398  +
          399  +				if (certificate_len >= 0) {
          400  +					x509_read_ret = x509_to_issuer(certificate, certificate_len, &pValue);
          401  +					if (x509_read_ret < 0) {
          402  +						pValue = NULL;
          403  +					} else {
          404  +						ulValueLen = x509_read_ret;
          405  +					}
          406  +				}
          407  +
          408  +				CACKEY_DEBUG_PRINTF(" ... returning %p/%lu", pValue, (unsigned long) ulValueLen);
          409  +
          410  +				break;
          411  +			case CKA_SERIAL_NUMBER:
          412  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_SERIAL_NUMBER (0x%08lx) ...", (unsigned long) curr_attr_type);
          413  +
          414  +				if (objectclass != CKO_CERTIFICATE) {
          415  +					CACKEY_DEBUG_PRINTF(" ... but not getting it because we are not a certificate.");
          416  +
          417  +					break;
          418  +				}
          419  +
          420  +				if (certificate_len >= 0) {
          421  +					x509_read_ret = x509_to_serial(certificate, certificate_len, &pValue);
          422  +					if (x509_read_ret < 0) {
          423  +						pValue = NULL;
          424  +					} else {
          425  +						ulValueLen = x509_read_ret;
          426  +					}
          427  +				}
          428  +
          429  +				CACKEY_DEBUG_PRINTF(" ... returning (%p/%lu)", pValue, (unsigned long) ulValueLen);
          430  +
          431  +				break;
          432  +			case CKA_SUBJECT:
          433  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_SUBJECT (0x%08lx) ...", (unsigned long) curr_attr_type);
          434  +
          435  +				if (objectclass != CKO_CERTIFICATE) {
          436  +					CACKEY_DEBUG_PRINTF(" ... but not getting it because we are not a certificate.");
          437  +
          438  +					break;
          439  +				}
          440  +
          441  +				if (certificate_len >= 0) {
          442  +					x509_read_ret = x509_to_subject(certificate, certificate_len, &pValue);
          443  +					if (x509_read_ret < 0) {
          444  +						pValue = NULL;
          445  +					} else {
          446  +						ulValueLen = x509_read_ret;
          447  +					}
          448  +				}
          449  +
          450  +				CACKEY_DEBUG_PRINTF(" ... returning %p/%lu", pValue, (unsigned long) ulValueLen);
          451  +
          452  +				break;
          453  +			case CKA_ID:
          454  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_ID (0x%08lx) ...", (unsigned long) curr_attr_type);
          455  +
          456  +				ucTmpBuf[0] = ((identity_num + 1) >> 8) & 0xff;
          457  +				ucTmpBuf[1] =  (identity_num + 1) & 0xff;
          458  +
          459  +				pValue = &ucTmpBuf;
          460  +				ulValueLen = 2;
          461  +
          462  +				CACKEY_DEBUG_PRINTF(" ... returning %p/%lu", pValue, (unsigned long) ulValueLen);
          463  +
          464  +				break;
          465  +			case CKA_CERTIFICATE_TYPE:
          466  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_CERTIFICATE_TYPE (0x%08lx) ...", (unsigned long) curr_attr_type);
          467  +
          468  +				if (objectclass != CKO_CERTIFICATE) {
          469  +					CACKEY_DEBUG_PRINTF(" ... but not getting it because we are not a certificate.");
          470  +
          471  +					break;
          472  +				}
          473  +
          474  +				/* We only support one certificate type */
          475  +				ck_certificate_type = CKC_X_509;
          476  +
          477  +				pValue = &ck_certificate_type;
          478  +				ulValueLen = sizeof(ck_certificate_type);
          479  +
          480  +				CACKEY_DEBUG_PRINTF(" ... returning CKC_X_509 (%lu) (%p/%lu)", (unsigned long) *((CK_CERTIFICATE_TYPE *) pValue), pValue, (unsigned long) ulValueLen);
          481  +
          482  +				break;
          483  +			case CKA_KEY_TYPE:
          484  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_KEY_TYPE (0x%08lx) ...", (unsigned long) curr_attr_type);
          485  +
          486  +				if (objectclass != CKO_PRIVATE_KEY && objectclass != CKO_PUBLIC_KEY) {
          487  +					CACKEY_DEBUG_PRINTF(" ... but not getting it because we are not a key.");
          488  +
          489  +					break;
          490  +				}
          491  +
          492  +				/* We only support one key type */
          493  +				ck_key_type = CKK_RSA;
          494  +
          495  +				pValue = &ck_key_type;
          496  +				ulValueLen = sizeof(ck_key_type);
          497  +
          498  +				CACKEY_DEBUG_PRINTF(" ... returning CKK_RSA (%lu) (%p/%lu)", (unsigned long) *((CK_CERTIFICATE_TYPE *) pValue), pValue, (unsigned long) ulValueLen);
          499  +
          500  +				break;
          501  +			case CKA_SIGN:
          502  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_SIGN (0x%08lx) ...", (unsigned long) curr_attr_type);
          503  +
          504  +				if (objectclass == CKO_PRIVATE_KEY) {
          505  +					pValue = &ck_true;
          506  +					ulValueLen = sizeof(ck_true);
          507  +				} else {
          508  +					pValue = &ck_false;
          509  +					ulValueLen = sizeof(ck_false);
          510  +				}
          511  +
          512  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          513  +
          514  +				break;
          515  +			case CKA_DECRYPT:
          516  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_DECRYPT (0x%08lx) ...", (unsigned long) curr_attr_type);
          517  +
          518  +				if (objectclass == CKO_PRIVATE_KEY || objectclass == CKO_PUBLIC_KEY) {
          519  +					pValue = &ck_true;
          520  +					ulValueLen = sizeof(ck_true);
          521  +				} else {
          522  +					pValue = &ck_false;
          523  +					ulValueLen = sizeof(ck_false);
          524  +				}
          525  +
          526  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          527  +
          528  +				break;
          529  +			case CKA_TRUST_SERVER_AUTH:
          530  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_TRUST_SERVER_AUTH (0x%08lx) ...", (unsigned long) curr_attr_type);
          531  +
          532  +				pValue = &ck_true;
          533  +				ulValueLen = sizeof(ck_true);
          534  +
          535  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          536  +
          537  +				break;
          538  +			case CKA_TRUST_CLIENT_AUTH:
          539  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_TRUST_CLIENT_AUTH (0x%08lx) ...", (unsigned long) curr_attr_type);
          540  +
          541  +				pValue = &ck_true;
          542  +				ulValueLen = sizeof(ck_true);
          543  +
          544  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          545  +
          546  +				break;
          547  +			case CKA_TRUST_CODE_SIGNING:
          548  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_TRUST_CODE_SIGNING (0x%08lx) ...", (unsigned long) curr_attr_type);
          549  +
          550  +				pValue = &ck_true;
          551  +				ulValueLen = sizeof(ck_true);
          552  +
          553  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          554  +
          555  +				break;
          556  +			case CKA_TRUST_EMAIL_PROTECTION:
          557  +				CACKEY_DEBUG_PRINTF("Requesting attribute CKA_TRUST_EMAIL_PROTECTION (0x%08lx) ...", (unsigned long) curr_attr_type);
          558  +
          559  +				pValue = &ck_true;
          560  +				ulValueLen = sizeof(ck_true);
          561  +
          562  +				CACKEY_DEBUG_PRINTF(" ... returning %lu (%p/%lu)", (unsigned long) *((CK_BBOOL *) pValue), pValue, (unsigned long) ulValueLen);
          563  +
          564  +				break;
          565  +			default:
          566  +				pValue = NULL;
          567  +				ulValueLen = (CK_LONG) -1;
          568  +				break;
          569  +		}
          570  +
          571  +		if (((CK_LONG) ulValueLen) != ((CK_LONG) -1)) {
          572  +			/* Push curr_attr onto the stack */
          573  +			curr_attr.type = curr_attr_type;
          574  +			curr_attr.ulValueLen = ulValueLen;
          575  +
          576  +			curr_attr.pValue = malloc(curr_attr.ulValueLen);
          577  +			memcpy(curr_attr.pValue, pValue, curr_attr.ulValueLen);
          578  +
          579  +			if (pValue_free && pValue) {
          580  +				free(pValue);
          581  +			}
          582  +
          583  +			if (numattrs >= retval_count) {
          584  +				retval_count *= 2;
          585  +				retval = realloc(retval, retval_count * sizeof(*retval));
          586  +			}
          587  +
          588  +			memcpy(&retval[numattrs], &curr_attr, sizeof(curr_attr));
          589  +			numattrs++;
          590  +		}
          591  +	}
          592  +
          593  +	if (numattrs != 0) {
          594  +		retval_count = numattrs;
          595  +		retval = realloc(retval, retval_count * sizeof(*retval));
          596  +	} else {
          597  +		free(retval);
          598  +
          599  +		retval = NULL;
          600  +	}
          601  +
          602  +	*pulCount = numattrs;
          603  +
          604  +	CACKEY_DEBUG_PRINTF("Returning %lu objects (%p).", numattrs, retval);
          605  +
          606  +	return(retval);
          607  +}
          608  +
          609  +CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) {
          610  +	CK_C_INITIALIZE_ARGS CK_PTR args;
          611  +	uint32_t idx;
          612  +	int mutex_init_ret;
          613  +
          614  +	CACKEY_DEBUG_PRINTF("Called.");
          615  +
          616  +	if (pInitArgs != NULL) {
          617  +		args = pInitArgs;
          618  +		memcpy(&cackey_args, args, sizeof(cackey_args));
          619  +
          620  +		if (args->CreateMutex == NULL || args->DestroyMutex == NULL || args->LockMutex == NULL || args->UnlockMutex == NULL) {
          621  +			if (args->CreateMutex != NULL || args->DestroyMutex != NULL || args->LockMutex != NULL || args->UnlockMutex != NULL) {
          622  +				CACKEY_DEBUG_PRINTF("Error. Some, but not All threading primitives provided.");
          623  +
          624  +				return(CKR_ARGUMENTS_BAD);
          625  +			}
          626  +		}
          627  +
          628  +		if (args->pReserved != NULL) {
          629  +			CACKEY_DEBUG_PRINTF("Error. pReserved is not NULL.");
          630  +
          631  +			return(CKR_ARGUMENTS_BAD);
          632  +		}
          633  +	} else {
          634  +		cackey_args.CreateMutex = NULL;
          635  +		cackey_args.DestroyMutex = NULL;
          636  +		cackey_args.LockMutex = NULL;
          637  +		cackey_args.UnlockMutex = NULL;
          638  +		cackey_args.flags = 0;
          639  +	}
          640  +
          641  +	if (cackey_initialized) {
          642  +		CACKEY_DEBUG_PRINTF("Error.  Already initialized.");
          643  +
          644  +		return(CKR_CRYPTOKI_ALREADY_INITIALIZED);
          645  +	}
          646  +
          647  +	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
          648  +		cackey_sessions[idx].active = 0;
          649  +	}
          650  +
          651  +	cackey_initialized = 1;
          652  +
          653  +	if (!cackey_biglock_init) {
          654  +		mutex_init_ret = cackey_mutex_create(&cackey_biglock);
          655  +
          656  +		if (mutex_init_ret != 0) {
          657  +			CACKEY_DEBUG_PRINTF("Error.  Mutex initialization failed.");
          658  +
          659  +			return(CKR_CANT_LOCK);
          660  +		}
          661  +
          662  +		cackey_biglock_init = 1;
          663  +	}
          664  +
          665  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          666  +
          667  +	return(CKR_OK);
          668  +}
          669  +
          670  +CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(CK_VOID_PTR pReserved) {
          671  +	uint32_t idx;
          672  +
          673  +	CACKEY_DEBUG_PRINTF("Called.");
          674  +
          675  +	if (pReserved != NULL) {
          676  +		CACKEY_DEBUG_PRINTF("Error. pReserved is not NULL.");
          677  +
          678  +		return(CKR_ARGUMENTS_BAD);
          679  +	}
          680  +
          681  +	if (!cackey_initialized) {
          682  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          683  +
          684  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          685  +	}
          686  +
          687  +	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
          688  +		if (cackey_sessions[idx].active) {
          689  +			C_CloseSession(idx);
          690  +		}
          691  +	}
          692  +
          693  +	cackey_initialized = 0;
          694  +
          695  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          696  +
          697  +	return(CKR_OK);
          698  +}
          699  +
          700  +CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(CK_INFO_PTR pInfo) {
          701  +	static CK_UTF8CHAR manufacturerID[] = "U.S. Government";
          702  +	static CK_UTF8CHAR libraryDescription[] = "SSH Agent PKCS#11";
          703  +
          704  +	CACKEY_DEBUG_PRINTF("Called.");
          705  +
          706  +	if (pInfo == NULL) {
          707  +		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
          708  +
          709  +		return(CKR_ARGUMENTS_BAD);
          710  +	}
          711  +
          712  +	if (!cackey_initialized) {
          713  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          714  +
          715  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          716  +	}
          717  +
          718  +	pInfo->cryptokiVersion.major = ((CACKEY_CRYPTOKI_VERSION_CODE) >> 16) & 0xff;
          719  +	pInfo->cryptokiVersion.minor = ((CACKEY_CRYPTOKI_VERSION_CODE) >> 8) & 0xff;
          720  +
          721  +	memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
          722  +	memcpy(pInfo->manufacturerID, manufacturerID, sizeof(manufacturerID) - 1);
          723  +
          724  +	pInfo->flags = 0x00;
          725  +
          726  +	memset(pInfo->libraryDescription, ' ', sizeof(pInfo->libraryDescription));
          727  +	memcpy(pInfo->libraryDescription, libraryDescription, sizeof(libraryDescription) - 1);
          728  +
          729  +	pInfo->libraryVersion.major = (cackey_getversion() >> 16) & 0xff;
          730  +	pInfo->libraryVersion.minor = (cackey_getversion() >> 8) & 0xff;
          731  +
          732  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          733  +
          734  +	return(CKR_OK);
          735  +}
          736  +
          737  +/* We only support 1 slot.  If the slot exists, the token exists. */
          738  +CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
          739  +	CK_ULONG count, slot_present = 0, currslot;
          740  +	int fd;
          741  +
          742  +	CACKEY_DEBUG_PRINTF("Called.");
          743  +
          744  +	if (pulCount == NULL) {
          745  +		CACKEY_DEBUG_PRINTF("Error. pulCount is NULL.");
          746  +
          747  +		return(CKR_ARGUMENTS_BAD);
          748  +	}
          749  +
          750  +	if (!cackey_initialized) {
          751  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          752  +
          753  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          754  +	}
          755  +
          756  +	/* XXX: Determine if slot is present */
          757  +
          758  +	if (pSlotList == NULL) {
          759  +		*pulCount = slot_present;
          760  +
          761  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          762  +
          763  +		return(CKR_OK);
          764  +	}
          765  +
          766  +	count = *pulCount;
          767  +	if (count < slot_present) {
          768  +		CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we have %lu entries.", count, slot_present);
          769  +
          770  +		return(CKR_BUFFER_TOO_SMALL);	
          771  +	}
          772  +
          773  +	for (currslot = 0; currslot < slot_present; currslot++) {
          774  +		pSlotList[currslot] = currslot;
          775  +	}
          776  +
          777  +	*pulCount = slot_present;
          778  +
          779  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          780  +
          781  +	return(CKR_OK);
          782  +
          783  +	tokenPresent = tokenPresent; /* Supress unused variable warning */
          784  +}
          785  +
          786  +CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
          787  +	static CK_UTF8CHAR manufacturerID[] = "U.S. Government";
          788  +	static CK_UTF8CHAR slotDescription[] = "SSH Agent Slot";
          789  +
          790  +	CACKEY_DEBUG_PRINTF("Called.");
          791  +
          792  +	if (pInfo == NULL) {
          793  +		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
          794  +
          795  +		return(CKR_ARGUMENTS_BAD);
          796  +	}
          797  +
          798  +	if (slotID != 0) {
          799  +		/* Again, we only support one slot -- slot 0 */
          800  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
          801  +
          802  +		return(CKR_SLOT_ID_INVALID);
          803  +	}
          804  +
          805  +	if (!cackey_initialized) {
          806  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          807  +
          808  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          809  +	}
          810  +
          811  +	memset(pInfo->slotDescription, ' ', sizeof(pInfo->slotDescription));
          812  +	memcpy(pInfo->slotDescription, slotDescription, sizeof(slotDescription) - 1);
          813  +
          814  +	memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
          815  +	memcpy(pInfo->manufacturerID, manufacturerID, sizeof(manufacturerID) - 1);
          816  +
          817  +	pInfo->flags = CKF_TOKEN_PRESENT;
          818  +
          819  +	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
          820  +	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;
          821  +
          822  +	pInfo->firmwareVersion.major = 0x00;
          823  +	pInfo->firmwareVersion.minor = 0x00;
          824  +
          825  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          826  +
          827  +	return(CKR_OK);
          828  +}
          829  +
          830  +CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) {
          831  +	static CK_UTF8CHAR manufacturerID[] = "U.S. Government";
          832  +	static CK_UTF8CHAR defaultLabel[] = "Unknown Token";
          833  +	static CK_UTF8CHAR model[] = "SSH Agent Token";
          834  +	int fd, bytestocopy;
          835  +
          836  +	CACKEY_DEBUG_PRINTF("Called.");
          837  +
          838  +	if (pInfo == NULL) {
          839  +		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
          840  +
          841  +		return(CKR_ARGUMENTS_BAD);
          842  +	}
          843  +
          844  +	if (slotID != 0) {
          845  +		/* Again, we only support one slot -- slot 0 */
          846  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
          847  +
          848  +		return(CKR_SLOT_ID_INVALID);
          849  +	}
          850  +
          851  +	if (!cackey_initialized) {
          852  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          853  +
          854  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          855  +	}
          856  +
          857  +	/* XXX: Verify connection is valid */
          858  +	if (0) {
          859  +		CACKEY_DEBUG_PRINTF("Error. Tried to connect to slot, but failed.  fd = %i", fd);
          860  +
          861  +		return(CKR_SLOT_ID_INVALID);
          862  +	}
          863  +
          864  +	/* XXX: Get list of identities */
          865  +	if (0) {
          866  +		CACKEY_DEBUG_PRINTF("Error. No identities found in slot.");
          867  +
          868  +		return(CKR_TOKEN_NOT_PRESENT);
          869  +	}
          870  +
          871  +	memset(pInfo->label, ' ', sizeof(pInfo->label));
          872  +	if (1) {
          873  +		memcpy(pInfo->label, defaultLabel, sizeof(defaultLabel) - 1);
          874  +	} else {
          875  +	}
          876  +
          877  +	memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
          878  +	memcpy(pInfo->manufacturerID, manufacturerID, sizeof(manufacturerID) - 1);
          879  +
          880  +	memset(pInfo->model, ' ', sizeof(pInfo->model));
          881  +	memcpy(pInfo->model, model, sizeof(model) - 1);
          882  +
          883  +	memset(pInfo->serialNumber, ' ', sizeof(pInfo->serialNumber));
          884  +
          885  +	memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime));
          886  +
          887  +	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
          888  +	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;
          889  +
          890  +	pInfo->firmwareVersion.major = 0x00;
          891  +	pInfo->firmwareVersion.minor = 0x00;
          892  +
          893  +	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_PROTECTED_AUTHENTICATION_PATH | CKF_TOKEN_INITIALIZED;
          894  +
          895  +	pInfo->ulMaxSessionCount = (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])) - 1;
          896  +	pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
          897  +	pInfo->ulMaxRwSessionCount = 0;
          898  +	pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
          899  +	pInfo->ulMaxPinLen = 128;
          900  +	pInfo->ulMinPinLen = 0;
          901  +	pInfo->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
          902  +	pInfo->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
          903  +	pInfo->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
          904  +	pInfo->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
          905  +
          906  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          907  +
          908  +	return(CKR_OK);
          909  +}
          910  +
          911  +CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlotID, CK_VOID_PTR pReserved) {
          912  +	CACKEY_DEBUG_PRINTF("Called.");
          913  +
          914  +	if (pReserved != NULL) {
          915  +		CACKEY_DEBUG_PRINTF("Error. pReserved is not NULL.");
          916  +
          917  +		return(CKR_ARGUMENTS_BAD);
          918  +	}
          919  +
          920  +	if (!cackey_initialized) {
          921  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          922  +
          923  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          924  +	}
          925  +
          926  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
          927  +
          928  +	return(CKR_FUNCTION_NOT_SUPPORTED);
          929  +}
          930  +
          931  +CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) {
          932  +	CACKEY_DEBUG_PRINTF("Called.");
          933  +
          934  +	if (!cackey_initialized) {
          935  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          936  +
          937  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          938  +	}
          939  +
          940  +	if (pulCount == NULL) {
          941  +		CACKEY_DEBUG_PRINTF("Error.  pulCount is NULL.");
          942  +
          943  +		return(CKR_ARGUMENTS_BAD);
          944  +	}
          945  +
          946  +	if (pMechanismList == NULL) {
          947  +		*pulCount = 3;
          948  +
          949  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          950  +
          951  +		return(CKR_OK);
          952  +	}
          953  +
          954  +	if (*pulCount < 3) {
          955  +		CACKEY_DEBUG_PRINTF("Error.  Buffer too small.");
          956  +
          957  +		return(CKR_BUFFER_TOO_SMALL);
          958  +	}
          959  +
          960  +	pMechanismList[0] = CKM_RSA_PKCS;
          961  +	pMechanismList[1] = CKM_SHA1_RSA_PKCS;
          962  +	*pulCount = 2;
          963  +
          964  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
          965  +
          966  +	return(CKR_OK);
          967  +}
          968  +
          969  +CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) {
          970  +	CACKEY_DEBUG_PRINTF("Called.");
          971  +
          972  +	if (slotID != 0) {
          973  +		/* Again, we only support one slot -- slot 0 */
          974  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
          975  +
          976  +		return(CKR_SLOT_ID_INVALID);
          977  +	}
          978  +
          979  +	if (pInfo == NULL) {
          980  +		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
          981  +
          982  +		return(CKR_ARGUMENTS_BAD);
          983  +	}
          984  +
          985  +	if (!cackey_initialized) {
          986  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
          987  +
          988  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
          989  +	}
          990  +
          991  +	/* XXX: This is untested, and further I'm not really sure if this is correct. */
          992  +	switch (type) {
          993  +		case CKM_RSA_PKCS:
          994  +			pInfo->ulMinKeySize = 512;
          995  +			pInfo->ulMaxKeySize = 8192;
          996  +			pInfo->flags = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY;
          997  +			break;
          998  +		case CKM_RSA_X_509:
          999  +			pInfo->ulMinKeySize = 512;
         1000  +			pInfo->ulMaxKeySize = 8192;
         1001  +			pInfo->flags = CKF_HW | CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY;
         1002  +			break;
         1003  +		case CKM_SHA1_RSA_PKCS:
         1004  +			pInfo->ulMinKeySize = 512;
         1005  +			pInfo->ulMaxKeySize = 8192;
         1006  +			pInfo->flags = CKF_HW | CKF_SIGN | CKF_VERIFY;
         1007  +			break;
         1008  +	}
         1009  +
         1010  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1011  +
         1012  +	return(CKR_OK);
         1013  +}
         1014  +
         1015  +/* We don't support this method. */
         1016  +CK_DEFINE_FUNCTION(CK_RV, C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel) {
         1017  +	CACKEY_DEBUG_PRINTF("Called.");
         1018  +
         1019  +	if (!cackey_initialized) {
         1020  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1021  +
         1022  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1023  +	}
         1024  +
         1025  +	CACKEY_DEBUG_PRINTF("Returning CKR_TOKEN_WRITE_PROTECTED (%i)", CKR_TOKEN_WRITE_PROTECTED);
         1026  +
         1027  +	return(CKR_TOKEN_WRITE_PROTECTED);
         1028  +}
         1029  +
         1030  +/* We don't support this method. */
         1031  +CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
         1032  +	CACKEY_DEBUG_PRINTF("Called.");
         1033  +
         1034  +	if (!cackey_initialized) {
         1035  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1036  +
         1037  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1038  +	}
         1039  +
         1040  +	CACKEY_DEBUG_PRINTF("Returning CKR_TOKEN_WRITE_PROTECTED (%i)", CKR_TOKEN_WRITE_PROTECTED);
         1041  +
         1042  +	return(CKR_TOKEN_WRITE_PROTECTED);
         1043  +}
         1044  +
         1045  +/* We don't support this method. */
         1046  +CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldPinLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewPinLen) {
         1047  +	CACKEY_DEBUG_PRINTF("Called.");
         1048  +
         1049  +	if (!cackey_initialized) {
         1050  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1051  +
         1052  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1053  +	}
         1054  +
         1055  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1056  +
         1057  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1058  +}
         1059  +
         1060  +CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession) {
         1061  +	struct cackey_identity *identities;
         1062  +	unsigned long idx, num_ids, id_idx, curr_id_type, curr_ssh_id_idx;
         1063  +	CK_BYTE sigbuf[1024];
         1064  +	ssize_t sigbuflen;
         1065  +	int mutex_retval;
         1066  +	int found_session = 0;
         1067  +	int fd;
         1068  +
         1069  +	CACKEY_DEBUG_PRINTF("Called.");
         1070  +
         1071  +	if (slotID != 0) {
         1072  +		/* We only support one slot -- slot 0 */
         1073  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         1074  +
         1075  +		return(CKR_SLOT_ID_INVALID);
         1076  +	}
         1077  +
         1078  +	if ((flags & CKF_SERIAL_SESSION) != CKF_SERIAL_SESSION) {
         1079  +		return(CKR_SESSION_PARALLEL_NOT_SUPPORTED);
         1080  +	}
         1081  +
         1082  +	if (!cackey_initialized) {
         1083  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1084  +
         1085  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1086  +	}
         1087  +
         1088  +	/* Verify that the card is actually in the slot. */
         1089  +	/* XXX: Talk to card */
         1090  +	if (0) {
         1091  +		if (0) {
         1092  +			CACKEY_DEBUG_PRINTF("Error.  Card not present.  Returning CKR_DEVICE_REMOVED");
         1093  +
         1094  +			return(CKR_DEVICE_REMOVED);
         1095  +		}
         1096  +	}
         1097  +
         1098  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1099  +	if (mutex_retval != 0) {
         1100  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1101  +
         1102  +		return(CKR_GENERAL_ERROR);
         1103  +	}
         1104  +
         1105  +	for (idx = 1; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
         1106  +		if (!cackey_sessions[idx].active) {
         1107  +			found_session = 1;
         1108  +
         1109  +			*phSession = idx;
         1110  +
         1111  +			cackey_sessions[idx].active = 1;
         1112  +			cackey_sessions[idx].slotID = slotID;
         1113  +			cackey_sessions[idx].state = CKS_RO_PUBLIC_SESSION;
         1114  +			cackey_sessions[idx].flags = flags;
         1115  +			cackey_sessions[idx].ulDeviceError = 0;
         1116  +			cackey_sessions[idx].pApplication = pApplication;
         1117  +			cackey_sessions[idx].Notify = notify;
         1118  +
         1119  +			cackey_sessions[idx].identities = NULL;
         1120  +			cackey_sessions[idx].identities_count = 0;
         1121  +
         1122  +			if (0) {
         1123  +				num_ids = 0;
         1124  +				/* XXX: Determine number of IDs */
         1125  +
         1126  +				/* Convert number of IDs to number of objects */
         1127  +				num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_ids;
         1128  +
         1129  +				identities = malloc(num_ids * sizeof(*identities));
         1130  +
         1131  +				id_idx = 0;
         1132  +				for (;;) {
         1133  +					for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
         1134  +						/* XXX: Determine base index */
         1135  +
         1136  +						identities[id_idx].attributes = cackey_get_attributes(curr_id_type, NULL, -1, &identities[id_idx].attributes_count);
         1137  +
         1138  +						if (identities[id_idx].attributes == NULL) {
         1139  +							identities[id_idx].attributes_count = 0;
         1140  +						}
         1141  +
         1142  +						id_idx++;
         1143  +					}
         1144  +				}
         1145  +
         1146  +				cackey_sessions[idx].identities = identities;
         1147  +				cackey_sessions[idx].identities_count = num_ids;
         1148  +			}
         1149  +
         1150  +			cackey_sessions[idx].search_active = 0;
         1151  +
         1152  +			cackey_sessions[idx].sign_active = 0;
         1153  +
         1154  +			cackey_sessions[idx].decrypt_active = 0;
         1155  +
         1156  +			break;
         1157  +		}
         1158  +	}
         1159  +
         1160  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1161  +	if (mutex_retval != 0) {
         1162  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1163  +
         1164  +		return(CKR_GENERAL_ERROR);
         1165  +	}
         1166  +
         1167  +	if (!found_session) {
         1168  +		CACKEY_DEBUG_PRINTF("Returning CKR_SESSION_COUNT (%i)", CKR_SESSION_COUNT);
         1169  +
         1170  +		return(CKR_SESSION_COUNT);
         1171  +	}
         1172  +
         1173  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1174  +
         1175  +	return(CKR_OK);
         1176  +}
         1177  +
         1178  +CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(CK_SESSION_HANDLE hSession) {
         1179  +	CK_ATTRIBUTE *curr_attr;
         1180  +	unsigned long id_idx, attr_idx;
         1181  +	int mutex_retval;
         1182  +
         1183  +	CACKEY_DEBUG_PRINTF("Called.");
         1184  +
         1185  +	if (!cackey_initialized) {
         1186  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1187  +
         1188  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1189  +	}
         1190  +
         1191  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1192  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1193  +		
         1194  +		return(CKR_SESSION_HANDLE_INVALID);
         1195  +	}
         1196  +
         1197  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1198  +	if (mutex_retval != 0) {
         1199  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1200  +
         1201  +		return(CKR_GENERAL_ERROR);
         1202  +	}
         1203  +
         1204  +	if (!cackey_sessions[hSession].active) {
         1205  +		cackey_mutex_unlock(cackey_biglock);
         1206  +
         1207  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1208  +		
         1209  +		return(CKR_SESSION_HANDLE_INVALID);
         1210  +	}
         1211  +
         1212  +	cackey_sessions[hSession].active = 0;
         1213  +	if (cackey_sessions[hSession].identities) {
         1214  +		for (id_idx = 0; id_idx < cackey_sessions[hSession].identities_count; id_idx++) {
         1215  +			if (cackey_sessions[hSession].identities[id_idx].attributes) {
         1216  +				for (attr_idx = 0; attr_idx < cackey_sessions[hSession].identities[id_idx].attributes_count; attr_idx++) {
         1217  +					curr_attr = &cackey_sessions[hSession].identities[id_idx].attributes[attr_idx];
         1218  +
         1219  +					if (curr_attr->pValue) {
         1220  +						free(curr_attr->pValue);
         1221  +					}
         1222  +				}
         1223  +
         1224  +				free(cackey_sessions[hSession].identities[id_idx].attributes);
         1225  +			}
         1226  +		}
         1227  +
         1228  +		free(cackey_sessions[hSession].identities);
         1229  +	}
         1230  +
         1231  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1232  +	if (mutex_retval != 0) {
         1233  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1234  +
         1235  +		return(CKR_GENERAL_ERROR);
         1236  +	}
         1237  +
         1238  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1239  +
         1240  +	return(CKR_OK);
         1241  +}
         1242  +
         1243  +CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(CK_SLOT_ID slotID) {
         1244  +	uint32_t idx;
         1245  +	int mutex_retval;
         1246  +
         1247  +	CACKEY_DEBUG_PRINTF("Called.");
         1248  +
         1249  +	if (slotID != 0) {
         1250  +		/* Again, we only support one slot -- slot 0 */
         1251  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         1252  +
         1253  +		return(CKR_SLOT_ID_INVALID);
         1254  +	}
         1255  +
         1256  +	if (!cackey_initialized) {
         1257  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1258  +
         1259  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1260  +	}
         1261  +
         1262  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1263  +	if (mutex_retval != 0) {
         1264  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1265  +
         1266  +		return(CKR_GENERAL_ERROR);
         1267  +	}
         1268  +
         1269  +	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
         1270  +		if (cackey_sessions[idx].active) {
         1271  +			if (cackey_sessions[idx].slotID != slotID) {
         1272  +				continue;
         1273  +			}
         1274  +
         1275  +			cackey_mutex_unlock(cackey_biglock);
         1276  +			C_CloseSession(idx);
         1277  +			cackey_mutex_lock(cackey_biglock);
         1278  +		}
         1279  +	}
         1280  +
         1281  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1282  +	if (mutex_retval != 0) {
         1283  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1284  +
         1285  +		return(CKR_GENERAL_ERROR);
         1286  +	}
         1287  +
         1288  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1289  +
         1290  +	return(CKR_OK);
         1291  +}
         1292  +
         1293  +CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) {
         1294  +	int mutex_retval;
         1295  +
         1296  +	CACKEY_DEBUG_PRINTF("Called.");
         1297  +
         1298  +	if (pInfo == NULL) {
         1299  +		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
         1300  +
         1301  +		return(CKR_ARGUMENTS_BAD);
         1302  +	}
         1303  +
         1304  +	if (!cackey_initialized) {
         1305  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1306  +
         1307  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1308  +	}
         1309  +
         1310  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1311  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1312  +		
         1313  +		return(CKR_SESSION_HANDLE_INVALID);
         1314  +	}
         1315  +
         1316  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1317  +	if (mutex_retval != 0) {
         1318  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1319  +
         1320  +		return(CKR_GENERAL_ERROR);
         1321  +	}
         1322  +
         1323  +	if (!cackey_sessions[hSession].active) {
         1324  +		cackey_mutex_unlock(cackey_biglock);
         1325  +
         1326  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1327  +		
         1328  +		return(CKR_SESSION_HANDLE_INVALID);
         1329  +	}
         1330  +
         1331  +	pInfo->slotID = cackey_sessions[hSession].slotID;
         1332  +	pInfo->state = cackey_sessions[hSession].state;
         1333  +	pInfo->flags = cackey_sessions[hSession].flags;
         1334  +	pInfo->ulDeviceError = cackey_sessions[hSession].ulDeviceError;
         1335  +
         1336  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1337  +	if (mutex_retval != 0) {
         1338  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1339  +
         1340  +		return(CKR_GENERAL_ERROR);
         1341  +	}
         1342  +
         1343  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1344  +
         1345  +	return(CKR_OK);
         1346  +}
         1347  +
         1348  +CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) {
         1349  +	CACKEY_DEBUG_PRINTF("Called.");
         1350  +
         1351  +	if (!cackey_initialized) {
         1352  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1353  +
         1354  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1355  +	}
         1356  +
         1357  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1358  +
         1359  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1360  +}
         1361  +
         1362  +CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) {
         1363  +	CACKEY_DEBUG_PRINTF("Called.");
         1364  +
         1365  +	if (!cackey_initialized) {
         1366  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1367  +
         1368  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1369  +	}
         1370  +
         1371  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1372  +
         1373  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1374  +}
         1375  +
         1376  +CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) {
         1377  +	int mutex_retval;
         1378  +
         1379  +	CACKEY_DEBUG_PRINTF("Called.");
         1380  +
         1381  +	if (!cackey_initialized) {
         1382  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1383  +
         1384  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1385  +	}
         1386  +
         1387  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1388  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1389  +		
         1390  +		return(CKR_SESSION_HANDLE_INVALID);
         1391  +	}
         1392  +
         1393  +	if (userType != CKU_USER) {
         1394  +		CACKEY_DEBUG_PRINTF("Error.  We only support USER mode, asked for %lu mode.", (unsigned long) userType)
         1395  +
         1396  +		return(CKR_USER_TYPE_INVALID);
         1397  +	}
         1398  +
         1399  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1400  +	if (mutex_retval != 0) {
         1401  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1402  +
         1403  +		return(CKR_GENERAL_ERROR);
         1404  +	}
         1405  +
         1406  +	if (!cackey_sessions[hSession].active) {
         1407  +		cackey_mutex_unlock(cackey_biglock);
         1408  +
         1409  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1410  +		
         1411  +		return(CKR_SESSION_HANDLE_INVALID);
         1412  +	}
         1413  +
         1414  +	cackey_sessions[hSession].state = CKS_RO_USER_FUNCTIONS;
         1415  +
         1416  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1417  +	if (mutex_retval != 0) {
         1418  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1419  +
         1420  +		return(CKR_GENERAL_ERROR);
         1421  +	}
         1422  +
         1423  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1424  +
         1425  +	return(CKR_OK);
         1426  +}
         1427  +
         1428  +CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession) {
         1429  +	int mutex_retval;
         1430  +
         1431  +	CACKEY_DEBUG_PRINTF("Called.");
         1432  +
         1433  +	if (!cackey_initialized) {
         1434  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1435  +
         1436  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1437  +	}
         1438  +
         1439  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1440  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1441  +		
         1442  +		return(CKR_SESSION_HANDLE_INVALID);
         1443  +	}
         1444  +
         1445  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1446  +	if (mutex_retval != 0) {
         1447  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1448  +
         1449  +		return(CKR_GENERAL_ERROR);
         1450  +	}
         1451  +
         1452  +	if (!cackey_sessions[hSession].active) {
         1453  +		cackey_mutex_unlock(cackey_biglock);
         1454  +
         1455  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1456  +		
         1457  +		return(CKR_SESSION_HANDLE_INVALID);
         1458  +	}
         1459  +
         1460  +	cackey_sessions[hSession].state = CKS_RO_PUBLIC_SESSION;
         1461  +
         1462  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1463  +	if (mutex_retval != 0) {
         1464  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1465  +
         1466  +		return(CKR_GENERAL_ERROR);
         1467  +	}
         1468  +
         1469  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1470  +
         1471  +	return(CKR_OK);
         1472  +}
         1473  +
         1474  +CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) {
         1475  +	CACKEY_DEBUG_PRINTF("Called.");
         1476  +
         1477  +	if (!cackey_initialized) {
         1478  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1479  +
         1480  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1481  +	}
         1482  +
         1483  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1484  +
         1485  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1486  +}
         1487  +
         1488  +CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) {
         1489  +	CACKEY_DEBUG_PRINTF("Called.");
         1490  +
         1491  +	if (!cackey_initialized) {
         1492  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1493  +
         1494  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1495  +	}
         1496  +
         1497  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1498  +
         1499  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1500  +}
         1501  +
         1502  +CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) {
         1503  +	CACKEY_DEBUG_PRINTF("Called.");
         1504  +
         1505  +	if (!cackey_initialized) {
         1506  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1507  +
         1508  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1509  +	}
         1510  +
         1511  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1512  +
         1513  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1514  +}
         1515  +
         1516  +CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) {
         1517  +	CACKEY_DEBUG_PRINTF("Called.");
         1518  +
         1519  +	if (!cackey_initialized) {
         1520  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1521  +
         1522  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1523  +	}
         1524  +
         1525  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1526  +
         1527  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1528  +}
         1529  +
         1530  +CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
         1531  +	CK_ATTRIBUTE *curr_attr;
         1532  +	struct cackey_identity *identity;
         1533  +	unsigned long identity_idx, attr_idx, sess_attr_idx, num_ids;
         1534  +	int mutex_retval;
         1535  +	CK_RV retval = CKR_OK;
         1536  +	CK_VOID_PTR pValue;
         1537  +	CK_ULONG ulValueLen;
         1538  +
         1539  +	CACKEY_DEBUG_PRINTF("Called.");
         1540  +
         1541  +	if (!cackey_initialized) {
         1542  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1543  +
         1544  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1545  +	}
         1546  +
         1547  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1548  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1549  +		
         1550  +		return(CKR_SESSION_HANDLE_INVALID);
         1551  +	}
         1552  +
         1553  +	if (hObject == 0) {
         1554  +		CACKEY_DEBUG_PRINTF("Error.  Object handle out of range.");
         1555  +		
         1556  +		return(CKR_OBJECT_HANDLE_INVALID);
         1557  +	}
         1558  +
         1559  +	if (ulCount == 0) {
         1560  +		/* Short circuit, if zero objects were specified return zero items immediately */
         1561  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i) (short circuit)", CKR_OK);
         1562  +
         1563  +		return(CKR_OK);
         1564  +	}
         1565  +
         1566  +	if (pTemplate == NULL) {
         1567  +		CACKEY_DEBUG_PRINTF("Error.  pTemplate is NULL.");
         1568  +
         1569  +		return(CKR_ARGUMENTS_BAD);
         1570  +	}
         1571  +
         1572  +	identity_idx = hObject - 1;
         1573  +
         1574  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1575  +	if (mutex_retval != 0) {
         1576  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1577  +
         1578  +		return(CKR_GENERAL_ERROR);
         1579  +	}
         1580  +
         1581  +	if (!cackey_sessions[hSession].active) {
         1582  +		cackey_mutex_unlock(cackey_biglock);
         1583  +
         1584  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1585  +		
         1586  +		return(CKR_SESSION_HANDLE_INVALID);
         1587  +	}
         1588  +
         1589  +	num_ids = cackey_sessions[hSession].identities_count;
         1590  +
         1591  +	if (identity_idx >= num_ids) {
         1592  +		cackey_mutex_unlock(cackey_biglock);
         1593  +
         1594  +		CACKEY_DEBUG_PRINTF("Error.  Object handle out of range.  identity_idx = %lu, num_ids = %lu.", (unsigned long) identity_idx, (unsigned long) num_ids);
         1595  +
         1596  +		return(CKR_OBJECT_HANDLE_INVALID);
         1597  +	}
         1598  +
         1599  +	identity = &cackey_sessions[hSession].identities[identity_idx];
         1600  +
         1601  +	for (attr_idx = 0; attr_idx < ulCount; attr_idx++) {
         1602  +		curr_attr = &pTemplate[attr_idx];
         1603  +
         1604  +		pValue = NULL;
         1605  +		ulValueLen = (CK_LONG) -1;
         1606  +
         1607  +		CACKEY_DEBUG_PRINTF("Looking for attribute 0x%08lx (identity:%lu) ...", (unsigned long) curr_attr->type, (unsigned long) identity_idx);
         1608  +
         1609  +		for (sess_attr_idx = 0; sess_attr_idx < identity->attributes_count; sess_attr_idx++) {
         1610  +			if (identity->attributes[sess_attr_idx].type == curr_attr->type) {
         1611  +				CACKEY_DEBUG_PRINTF(" ... found it, pValue = %p, ulValueLen = %lu", identity->attributes[sess_attr_idx].pValue, identity->attributes[sess_attr_idx].ulValueLen);
         1612  +				
         1613  +				pValue = identity->attributes[sess_attr_idx].pValue;
         1614  +				ulValueLen = identity->attributes[sess_attr_idx].ulValueLen;
         1615  +			}
         1616  +		}
         1617  +
         1618  +		if (curr_attr->pValue && pValue) {
         1619  +			if (curr_attr->ulValueLen >= ulValueLen) {
         1620  +				memcpy(curr_attr->pValue, pValue, ulValueLen);
         1621  +			} else {
         1622  +				ulValueLen = (CK_LONG) -1;
         1623  +
         1624  +				retval = CKR_BUFFER_TOO_SMALL;
         1625  +			}
         1626  +		}
         1627  +
         1628  +		curr_attr->ulValueLen = ulValueLen;
         1629  +	}
         1630  +
         1631  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1632  +	if (mutex_retval != 0) {
         1633  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1634  +
         1635  +		return(CKR_GENERAL_ERROR);
         1636  +	}
         1637  +
         1638  +	if (retval == CKR_ATTRIBUTE_TYPE_INVALID) {
         1639  +		CACKEY_DEBUG_PRINTF("Returning CKR_ATTRIBUTE_TYPE_INVALID (%i)", (int) retval);
         1640  +	} else if (retval == CKR_BUFFER_TOO_SMALL) {
         1641  +		CACKEY_DEBUG_PRINTF("Returning CKR_BUFFER_TOO_SMALL (%i)", (int) retval);
         1642  +	} else if (retval == CKR_OK) {
         1643  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", (int) retval);
         1644  +	} else {
         1645  +		CACKEY_DEBUG_PRINTF("Returning %i", (int) retval);
         1646  +	}
         1647  +
         1648  +	return(retval);
         1649  +}
         1650  +
         1651  +CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
         1652  +	CACKEY_DEBUG_PRINTF("Called.");
         1653  +
         1654  +	if (!cackey_initialized) {
         1655  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1656  +
         1657  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1658  +	}
         1659  +
         1660  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1661  +
         1662  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1663  +}
         1664  +
         1665  +CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) {
         1666  +	int mutex_retval;
         1667  +
         1668  +	CACKEY_DEBUG_PRINTF("Called.");
         1669  +
         1670  +	if (!cackey_initialized) {
         1671  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1672  +
         1673  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1674  +	}
         1675  +
         1676  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1677  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1678  +		
         1679  +		return(CKR_SESSION_HANDLE_INVALID);
         1680  +	}
         1681  +
         1682  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1683  +	if (mutex_retval != 0) {
         1684  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1685  +
         1686  +		return(CKR_GENERAL_ERROR);
         1687  +	}
         1688  +
         1689  +	if (!cackey_sessions[hSession].active) {
         1690  +		cackey_mutex_unlock(cackey_biglock);
         1691  +
         1692  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1693  +		
         1694  +		return(CKR_SESSION_HANDLE_INVALID);
         1695  +	}
         1696  +
         1697  +	if (cackey_sessions[hSession].search_active) {
         1698  +		cackey_mutex_unlock(cackey_biglock);
         1699  +
         1700  +		CACKEY_DEBUG_PRINTF("Error.  Search already active.");
         1701  +		
         1702  +		return(CKR_OPERATION_ACTIVE);
         1703  +	}
         1704  +
         1705  +	if (pTemplate != NULL) {
         1706  +		if (ulCount != 0) {
         1707  +			cackey_sessions[hSession].search_query_count = ulCount;
         1708  +			cackey_sessions[hSession].search_query = malloc(ulCount * sizeof(*pTemplate));
         1709  +
         1710  +			memcpy(cackey_sessions[hSession].search_query, pTemplate, ulCount * sizeof(*pTemplate));
         1711  +		} else {
         1712  +			cackey_sessions[hSession].search_query_count = 0;
         1713  +			cackey_sessions[hSession].search_query = NULL;
         1714  +		}
         1715  +	} else {
         1716  +		if (ulCount != 0) {
         1717  +			cackey_mutex_unlock(cackey_biglock);
         1718  +
         1719  +			CACKEY_DEBUG_PRINTF("Error.  Search query specified as NULL, but number of query terms not specified as 0.");
         1720  +
         1721  +			return(CKR_ARGUMENTS_BAD);
         1722  +		}
         1723  +
         1724  +		cackey_sessions[hSession].search_query_count = 0;
         1725  +		cackey_sessions[hSession].search_query = NULL;
         1726  +	}
         1727  +
         1728  +	cackey_sessions[hSession].search_active = 1;
         1729  +	cackey_sessions[hSession].search_curr_id = 0;
         1730  +
         1731  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1732  +	if (mutex_retval != 0) {
         1733  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1734  +
         1735  +		return(CKR_GENERAL_ERROR);
         1736  +	}
         1737  +
         1738  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1739  +
         1740  +	return(CKR_OK);
         1741  +}
         1742  +
         1743  +CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) {
         1744  +	struct cackey_identity *curr_id;
         1745  +	CK_ATTRIBUTE *curr_attr;
         1746  +	CK_ULONG curr_id_idx, curr_out_id_idx, curr_attr_idx, sess_attr_idx;
         1747  +	CK_ULONG matched_count, prev_matched_count;
         1748  +	int mutex_retval;
         1749  +
         1750  +	CACKEY_DEBUG_PRINTF("Called.");
         1751  +
         1752  +	if (!cackey_initialized) {
         1753  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1754  +
         1755  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1756  +	}
         1757  +
         1758  +	if (pulObjectCount == NULL) {
         1759  +		CACKEY_DEBUG_PRINTF("Error.  pulObjectCount is NULL.");
         1760  +
         1761  +		return(CKR_ARGUMENTS_BAD);
         1762  +	}
         1763  +
         1764  +	if (phObject == NULL && ulMaxObjectCount == 0) {
         1765  +		/* Short circuit, if zero objects were specified return zero items immediately */
         1766  +		*pulObjectCount = 0;
         1767  +
         1768  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i) (short circuit)", CKR_OK);
         1769  +
         1770  +		return(CKR_OK);
         1771  +	}
         1772  +
         1773  +	if (phObject == NULL) {
         1774  +		CACKEY_DEBUG_PRINTF("Error.  phObject is NULL.");
         1775  +
         1776  +		return(CKR_ARGUMENTS_BAD);
         1777  +	}
         1778  +
         1779  +	if (ulMaxObjectCount == 0) {
         1780  +		CACKEY_DEBUG_PRINTF("Error.  Maximum number of objects specified as zero.");
         1781  +
         1782  +		return(CKR_ARGUMENTS_BAD);
         1783  +	}
         1784  +
         1785  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1786  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1787  +		
         1788  +		return(CKR_SESSION_HANDLE_INVALID);
         1789  +	}
         1790  +
         1791  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1792  +	if (mutex_retval != 0) {
         1793  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1794  +
         1795  +		return(CKR_GENERAL_ERROR);
         1796  +	}
         1797  +
         1798  +	if (!cackey_sessions[hSession].active) {
         1799  +		cackey_mutex_unlock(cackey_biglock);
         1800  +
         1801  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1802  +		
         1803  +		return(CKR_SESSION_HANDLE_INVALID);
         1804  +	}
         1805  +
         1806  +	if (!cackey_sessions[hSession].search_active) {
         1807  +		cackey_mutex_unlock(cackey_biglock);
         1808  +
         1809  +		CACKEY_DEBUG_PRINTF("Error.  Search not active.");
         1810  +		
         1811  +		return(CKR_OPERATION_NOT_INITIALIZED);
         1812  +	}
         1813  +
         1814  +	curr_id_idx = 0;
         1815  +	curr_out_id_idx = 0;
         1816  +	for (curr_id_idx = cackey_sessions[hSession].search_curr_id; curr_id_idx < cackey_sessions[hSession].identities_count && ulMaxObjectCount; curr_id_idx++) {
         1817  +		curr_id = &cackey_sessions[hSession].identities[curr_id_idx];
         1818  +
         1819  +		CACKEY_DEBUG_PRINTF("Processing identity:%lu", (unsigned long) curr_id_idx);
         1820  +
         1821  +		matched_count = 0;
         1822  +
         1823  +		for (curr_attr_idx = 0; curr_attr_idx < cackey_sessions[hSession].search_query_count; curr_attr_idx++) {
         1824  +			prev_matched_count = matched_count;
         1825  +
         1826  +			curr_attr = &cackey_sessions[hSession].search_query[curr_attr_idx];
         1827  +
         1828  +			CACKEY_DEBUG_PRINTF("  Checking for attribute 0x%08lx in identity:%i...", (unsigned long) curr_attr->type, (int) curr_id_idx);
         1829  +			CACKEY_DEBUG_PRINTBUF("    Value looking for:", curr_attr->pValue, curr_attr->ulValueLen);
         1830  +
         1831  +			for (sess_attr_idx = 0; sess_attr_idx < curr_id->attributes_count; sess_attr_idx++) {
         1832  +				if (curr_id->attributes[sess_attr_idx].type == curr_attr->type) {
         1833  +					CACKEY_DEBUG_PRINTF("    ... found matching type ...");
         1834  +					CACKEY_DEBUG_PRINTBUF("    ... our value:", curr_id->attributes[sess_attr_idx].pValue, curr_id->attributes[sess_attr_idx].ulValueLen);
         1835  +
         1836  +					if (curr_attr->pValue == NULL) {
         1837  +						CACKEY_DEBUG_PRINTF("       ... found wildcard match");
         1838  +
         1839  +						matched_count++;
         1840  +
         1841  +						break;
         1842  +					}
         1843  +
         1844  + 					if (curr_attr->ulValueLen == curr_id->attributes[sess_attr_idx].ulValueLen && memcmp(curr_attr->pValue, curr_id->attributes[sess_attr_idx].pValue, curr_id->attributes[sess_attr_idx].ulValueLen) == 0) {
         1845  +						CACKEY_DEBUG_PRINTF("       ... found exact match");
         1846  +
         1847  +						matched_count++;
         1848  +
         1849  +						break;
         1850  +					}
         1851  +				}
         1852  +			}
         1853  +
         1854  +			/* If the attribute could not be matched, do not try to match additional attributes */
         1855  +			if (prev_matched_count == matched_count) {
         1856  +				break;
         1857  +			}
         1858  +		}
         1859  +
         1860  +		if (matched_count == cackey_sessions[hSession].search_query_count) {
         1861  +			CACKEY_DEBUG_PRINTF("  ... All %i attributes checked for found, adding identity:%i to returned list", (int) cackey_sessions[hSession].search_query_count, (int) curr_id_idx);
         1862  +
         1863  +			phObject[curr_out_id_idx] = curr_id_idx + 1;
         1864  +
         1865  +			ulMaxObjectCount--;
         1866  +
         1867  +			curr_out_id_idx++;
         1868  +		} else {
         1869  +			CACKEY_DEBUG_PRINTF("  ... Not all %i (only found %i) attributes checked for found, not adding identity:%i", (int) cackey_sessions[hSession].search_query_count, (int) matched_count, (int) curr_id_idx);
         1870  +		}
         1871  +	}
         1872  +	cackey_sessions[hSession].search_curr_id = curr_id_idx;
         1873  +	*pulObjectCount = curr_out_id_idx;
         1874  +
         1875  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1876  +	if (mutex_retval != 0) {
         1877  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1878  +
         1879  +		return(CKR_GENERAL_ERROR);
         1880  +	}
         1881  +
         1882  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i), num objects = %lu", CKR_OK, *pulObjectCount);
         1883  +
         1884  +	return(CKR_OK);
         1885  +}
         1886  +
         1887  +CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)(CK_SESSION_HANDLE hSession) {
         1888  +	int mutex_retval;
         1889  +
         1890  +	CACKEY_DEBUG_PRINTF("Called.");
         1891  +
         1892  +	if (!cackey_initialized) {
         1893  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1894  +
         1895  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1896  +	}
         1897  +
         1898  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         1899  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         1900  +		
         1901  +		return(CKR_SESSION_HANDLE_INVALID);
         1902  +	}
         1903  +
         1904  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1905  +	if (mutex_retval != 0) {
         1906  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1907  +
         1908  +		return(CKR_GENERAL_ERROR);
         1909  +	}
         1910  +
         1911  +	if (!cackey_sessions[hSession].active) {
         1912  +		cackey_mutex_unlock(cackey_biglock);
         1913  +
         1914  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         1915  +		
         1916  +		return(CKR_SESSION_HANDLE_INVALID);
         1917  +	}
         1918  +
         1919  +	if (!cackey_sessions[hSession].search_active) {
         1920  +		cackey_mutex_unlock(cackey_biglock);
         1921  +
         1922  +		CACKEY_DEBUG_PRINTF("Error.  Search not active.");
         1923  +		
         1924  +		return(CKR_OPERATION_NOT_INITIALIZED);
         1925  +	}
         1926  +
         1927  +	cackey_sessions[hSession].search_active = 0;
         1928  +	if (cackey_sessions[hSession].search_query) {
         1929  +		free(cackey_sessions[hSession].search_query);
         1930  +	}
         1931  +
         1932  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1933  +	if (mutex_retval != 0) {
         1934  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1935  +
         1936  +		return(CKR_GENERAL_ERROR);
         1937  +	}
         1938  +
         1939  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         1940  +
         1941  +	return(CKR_OK);
         1942  +}
         1943  +
         1944  +CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
         1945  +	CACKEY_DEBUG_PRINTF("Called.");
         1946  +
         1947  +	if (!cackey_initialized) {
         1948  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1949  +
         1950  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1951  +	}
         1952  +
         1953  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1954  +
         1955  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1956  +}
         1957  +
         1958  +CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) {
         1959  +	CACKEY_DEBUG_PRINTF("Called.");
         1960  +
         1961  +	if (!cackey_initialized) {
         1962  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1963  +
         1964  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1965  +	}
         1966  +
         1967  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1968  +
         1969  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1970  +}
         1971  +
         1972  +CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) {
         1973  +	CACKEY_DEBUG_PRINTF("Called.");
         1974  +
         1975  +	if (!cackey_initialized) {
         1976  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1977  +
         1978  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1979  +	}
         1980  +
         1981  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1982  +
         1983  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1984  +}
         1985  +
         1986  +CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) {
         1987  +	CACKEY_DEBUG_PRINTF("Called.");
         1988  +
         1989  +	if (!cackey_initialized) {
         1990  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         1991  +
         1992  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         1993  +	}
         1994  +
         1995  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         1996  +
         1997  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         1998  +}
         1999  +
         2000  +CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
         2001  +	int mutex_retval;
         2002  +
         2003  +	hKey--;
         2004  +
         2005  +	CACKEY_DEBUG_PRINTF("Called.");
         2006  +
         2007  +	if (!cackey_initialized) {
         2008  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2009  +
         2010  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2011  +	}
         2012  +
         2013  +	if (pMechanism == NULL) {
         2014  +		CACKEY_DEBUG_PRINTF("Error. pMechanism is NULL.");
         2015  +
         2016  +		return(CKR_ARGUMENTS_BAD);
         2017  +	}
         2018  +
         2019  +	if (pMechanism->mechanism != CKM_RSA_PKCS) {
         2020  +		CACKEY_DEBUG_PRINTF("Error. pMechanism->mechanism not specified as CKM_RSA_PKCS");
         2021  +
         2022  +		return(CKR_MECHANISM_PARAM_INVALID);
         2023  +	}
         2024  +
         2025  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         2026  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         2027  +		
         2028  +		return(CKR_SESSION_HANDLE_INVALID);
         2029  +	}
         2030  +
         2031  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         2032  +	if (mutex_retval != 0) {
         2033  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         2034  +
         2035  +		return(CKR_GENERAL_ERROR);
         2036  +	}
         2037  +
         2038  +	if (!cackey_sessions[hSession].active) {
         2039  +		cackey_mutex_unlock(cackey_biglock);
         2040  +
         2041  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         2042  +		
         2043  +		return(CKR_SESSION_HANDLE_INVALID);
         2044  +	}
         2045  +
         2046  +	if (cackey_sessions[hSession].decrypt_active) {
         2047  +		cackey_mutex_unlock(cackey_biglock);
         2048  +
         2049  +		CACKEY_DEBUG_PRINTF("Error.  Decrypt already in progress.");
         2050  +		
         2051  +		return(CKR_OPERATION_ACTIVE);
         2052  +	}
         2053  +
         2054  +	if (hKey >= cackey_sessions[hSession].identities_count) {
         2055  +		cackey_mutex_unlock(cackey_biglock);
         2056  +
         2057  +		CACKEY_DEBUG_PRINTF("Error.  Key handle out of range.");
         2058  +
         2059  +		return(CKR_KEY_HANDLE_INVALID);
         2060  +	}
         2061  +
         2062  +	cackey_sessions[hSession].decrypt_active = 1;
         2063  +
         2064  +	cackey_sessions[hSession].decrypt_mechanism = pMechanism->mechanism;
         2065  +	cackey_sessions[hSession].decrypt_mech_parm = pMechanism->pParameter;
         2066  +	cackey_sessions[hSession].decrypt_mech_parmlen = pMechanism->ulParameterLen;
         2067  +
         2068  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         2069  +	if (mutex_retval != 0) {
         2070  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         2071  +
         2072  +		return(CKR_GENERAL_ERROR);
         2073  +	}
         2074  +
         2075  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         2076  +
         2077  +	return(CKR_OK);
         2078  +}
         2079  +
         2080  +CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) {
         2081  +	CK_ULONG datalen_update, datalen_final;
         2082  +	CK_RV decrypt_ret;
         2083  +
         2084  +	CACKEY_DEBUG_PRINTF("Called.");
         2085  +
         2086  +	if (!cackey_initialized) {
         2087  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2088  +
         2089  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2090  +	}
         2091  +
         2092  +	if (pulDataLen == NULL) {
         2093  +		CACKEY_DEBUG_PRINTF("Error. pulDataLen is NULL.");
         2094  +
         2095  +		return(CKR_ARGUMENTS_BAD);
         2096  +	}
         2097  +
         2098  +	datalen_update = *pulDataLen;
         2099  +
         2100  +	decrypt_ret = C_DecryptUpdate(hSession, pEncryptedData, ulEncryptedDataLen, pData, &datalen_update);
         2101  +	if (decrypt_ret != CKR_OK) {
         2102  +		CACKEY_DEBUG_PRINTF("Error.  DecryptUpdate() returned failure (rv = %lu).", (unsigned long) decrypt_ret);
         2103  +
         2104  +		return(decrypt_ret);
         2105  +	}
         2106  +
         2107  +	if (pData) {
         2108  +		pData += datalen_update;
         2109  +	}
         2110  +	datalen_final = *pulDataLen - datalen_update;
         2111  +
         2112  +	decrypt_ret = C_DecryptFinal(hSession, pData, &datalen_final);
         2113  +	if (decrypt_ret != CKR_OK) {
         2114  +		CACKEY_DEBUG_PRINTF("Error.  DecryptFinal() returned failure (rv = %lu).", (unsigned long) decrypt_ret);
         2115  +
         2116  +		return(decrypt_ret);
         2117  +	}
         2118  +
         2119  +	*pulDataLen = datalen_update + datalen_final;
         2120  +
         2121  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         2122  +
         2123  +	return(CKR_OK);
         2124  +}
         2125  +
         2126  +CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) {
         2127  +	static CK_BYTE buf[16384];
         2128  +	ssize_t buflen;
         2129  +	CK_RV retval = CKR_GENERAL_ERROR;
         2130  +	int mutex_retval;
         2131  +	int fd;
         2132  +
         2133  +	CACKEY_DEBUG_PRINTF("Called.");
         2134  +
         2135  +	if (!cackey_initialized) {
         2136  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2137  +
         2138  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2139  +	}
         2140  +
         2141  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         2142  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         2143  +		
         2144  +		return(CKR_SESSION_HANDLE_INVALID);
         2145  +	}
         2146  +
         2147  +	if (pEncryptedPart == NULL && ulEncryptedPartLen == 0) {
         2148  +		/* Short circuit if we are asked to decrypt nothing... */
         2149  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i) (short circuit)", CKR_OK);
         2150  +
         2151  +		return(CKR_OK);
         2152  +	}
         2153  +
         2154  +	if (pEncryptedPart == NULL) {
         2155  +		CACKEY_DEBUG_PRINTF("Error. pEncryptedPart is NULL, but ulEncryptedPartLen is not 0.");
         2156  +
         2157  +		return(CKR_ARGUMENTS_BAD);
         2158  +	}
         2159  +
         2160  +	if (ulEncryptedPartLen == 0) {
         2161  +		CACKEY_DEBUG_PRINTF("Error. ulEncryptedPartLen is 0, but pPart is not NULL.");
         2162  +
         2163  +		return(CKR_ARGUMENTS_BAD);
         2164  +	}
         2165  +
         2166  +	if (pulPartLen == NULL) {
         2167  +		CACKEY_DEBUG_PRINTF("Error. pulPartLen is NULL.");
         2168  +
         2169  +		return(CKR_ARGUMENTS_BAD);
         2170  +	}
         2171  +
         2172  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         2173  +	if (mutex_retval != 0) {
         2174  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         2175  +
         2176  +		return(CKR_GENERAL_ERROR);
         2177  +	}
         2178  +
         2179  +	if (!cackey_sessions[hSession].active) {
         2180  +		cackey_mutex_unlock(cackey_biglock);
         2181  +
         2182  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         2183  +		
         2184  +		return(CKR_SESSION_HANDLE_INVALID);
         2185  +	}
         2186  +
         2187  +	if (!cackey_sessions[hSession].decrypt_active) {
         2188  +		cackey_mutex_unlock(cackey_biglock);
         2189  +
         2190  +		CACKEY_DEBUG_PRINTF("Error.  Decrypt not active.");
         2191  +		
         2192  +		return(CKR_OPERATION_NOT_INITIALIZED);
         2193  +	}
         2194  +
         2195  +	switch (cackey_sessions[hSession].decrypt_mechanism) {
         2196  +		case CKM_RSA_PKCS:
         2197  +			buflen = -1;
         2198  +
         2199  +			/* XXX: Ask card to decrypt */
         2200  +
         2201  +			if (buflen < 0) {
         2202  +				/* Decryption failed. */
         2203  +				retval = CKR_GENERAL_ERROR;
         2204  +			} else if (((unsigned long) buflen) > *pulPartLen && pPart) {
         2205  +				/* Decrypted data too large */
         2206  +				retval = CKR_BUFFER_TOO_SMALL;
         2207  +			} else {
         2208  +				if (pPart) {
         2209  +					memcpy(pPart, buf, buflen);
         2210  +				}
         2211  +
         2212  +				*pulPartLen = buflen;
         2213  +
         2214  +				retval = CKR_OK;
         2215  +			}
         2216  +
         2217  +			break;
         2218  +	}
         2219  +
         2220  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         2221  +	if (mutex_retval != 0) {
         2222  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         2223  +
         2224  +		return(CKR_GENERAL_ERROR);
         2225  +	}
         2226  +
         2227  +	CACKEY_DEBUG_PRINTF("Returning %i", (int) retval);
         2228  +
         2229  +	return(retval);
         2230  +}
         2231  +
         2232  +CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) {
         2233  +	int mutex_retval;
         2234  +	int terminate_decrypt = 1;
         2235  +
         2236  +	CACKEY_DEBUG_PRINTF("Called.");
         2237  +
         2238  +	if (!cackey_initialized) {
         2239  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2240  +
         2241  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2242  +	}
         2243  +
         2244  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         2245  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         2246  +		
         2247  +		return(CKR_SESSION_HANDLE_INVALID);
         2248  +	}
         2249  +
         2250  +	if (pulLastPartLen == NULL) {
         2251  +		CACKEY_DEBUG_PRINTF("Error. pulLastPartLen is NULL.");
         2252  +
         2253  +		return(CKR_ARGUMENTS_BAD);
         2254  +	}
         2255  +
         2256  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         2257  +	if (mutex_retval != 0) {
         2258  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         2259  +
         2260  +		return(CKR_GENERAL_ERROR);
         2261  +	}
         2262  +
         2263  +	if (!cackey_sessions[hSession].active) {
         2264  +		cackey_mutex_unlock(cackey_biglock);
         2265  +
         2266  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         2267  +		
         2268  +		return(CKR_SESSION_HANDLE_INVALID);
         2269  +	}
         2270  +
         2271  +	if (!cackey_sessions[hSession].decrypt_active) {
         2272  +		cackey_mutex_unlock(cackey_biglock);
         2273  +
         2274  +		CACKEY_DEBUG_PRINTF("Error.  Decrypt not active.");
         2275  +		
         2276  +		return(CKR_OPERATION_NOT_INITIALIZED);
         2277  +	}
         2278  +
         2279  +	*pulLastPartLen = 0;
         2280  +
         2281  +	if (pLastPart == NULL) {
         2282  +		terminate_decrypt = 0;
         2283  +	}
         2284  +
         2285  +	if (terminate_decrypt) {
         2286  +		cackey_sessions[hSession].decrypt_active = 0;
         2287  +	}
         2288  +
         2289  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         2290  +	if (mutex_retval != 0) {
         2291  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         2292  +
         2293  +		return(CKR_GENERAL_ERROR);
         2294  +	}
         2295  +
         2296  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         2297  +
         2298  +	return(CKR_OK);
         2299  +}
         2300  +
         2301  +CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) {
         2302  +	CACKEY_DEBUG_PRINTF("Called.");
         2303  +
         2304  +	if (!cackey_initialized) {
         2305  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2306  +
         2307  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2308  +	}
         2309  +
         2310  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2311  +
         2312  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2313  +}
         2314  +
         2315  +CK_DEFINE_FUNCTION(CK_RV, C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) {
         2316  +	CACKEY_DEBUG_PRINTF("Called.");
         2317  +
         2318  +	if (!cackey_initialized) {
         2319  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2320  +
         2321  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2322  +	}
         2323  +
         2324  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2325  +
         2326  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2327  +}
         2328  +
         2329  +CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) {
         2330  +	CACKEY_DEBUG_PRINTF("Called.");
         2331  +
         2332  +	if (!cackey_initialized) {
         2333  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2334  +
         2335  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2336  +	}
         2337  +
         2338  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2339  +
         2340  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2341  +}
         2342  +
         2343  +CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) {
         2344  +	CACKEY_DEBUG_PRINTF("Called.");
         2345  +
         2346  +	if (!cackey_initialized) {
         2347  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2348  +
         2349  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2350  +	}
         2351  +
         2352  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2353  +
         2354  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2355  +}
         2356  +
         2357  +CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) {
         2358  +	CACKEY_DEBUG_PRINTF("Called.");
         2359  +
         2360  +	if (!cackey_initialized) {
         2361  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2362  +
         2363  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2364  +	}
         2365  +
         2366  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2367  +
         2368  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2369  +}
         2370  +
         2371  +CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
         2372  +	int mutex_retval;
         2373  +
         2374  +	hKey--;
         2375  +
         2376  +	CACKEY_DEBUG_PRINTF("Called.");
         2377  +
         2378  +	if (!cackey_initialized) {
         2379  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2380  +
         2381  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2382  +	}
         2383  +
         2384  +	if (pMechanism == NULL) {
         2385  +		CACKEY_DEBUG_PRINTF("Error. pMechanism is NULL.");
         2386  +
         2387  +		return(CKR_ARGUMENTS_BAD);
         2388  +	}
         2389  +
         2390  +	if (pMechanism->mechanism != CKM_RSA_PKCS && pMechanism->mechanism != CKM_SHA1_RSA_PKCS) {
         2391  +		CACKEY_DEBUG_PRINTF("Error. pMechanism->mechanism not specified as CKM_RSA_PKCS or CKM_SHA1_RSA_PKCS");
         2392  +
         2393  +		return(CKR_MECHANISM_PARAM_INVALID);
         2394  +	}
         2395  +
         2396  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         2397  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         2398  +		
         2399  +		return(CKR_SESSION_HANDLE_INVALID);
         2400  +	}
         2401  +
         2402  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         2403  +	if (mutex_retval != 0) {
         2404  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         2405  +
         2406  +		return(CKR_GENERAL_ERROR);
         2407  +	}
         2408  +
         2409  +	if (!cackey_sessions[hSession].active) {
         2410  +		cackey_mutex_unlock(cackey_biglock);
         2411  +
         2412  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         2413  +		
         2414  +		return(CKR_SESSION_HANDLE_INVALID);
         2415  +	}
         2416  +
         2417  +	if (cackey_sessions[hSession].sign_active) {
         2418  +		cackey_mutex_unlock(cackey_biglock);
         2419  +
         2420  +		CACKEY_DEBUG_PRINTF("Error.  Sign already in progress.");
         2421  +		
         2422  +		return(CKR_OPERATION_ACTIVE);
         2423  +	}
         2424  +
         2425  +	if (hKey >= cackey_sessions[hSession].identities_count) {
         2426  +		cackey_mutex_unlock(cackey_biglock);
         2427  +
         2428  +		CACKEY_DEBUG_PRINTF("Error.  Key handle out of range.");
         2429  +
         2430  +		return(CKR_KEY_HANDLE_INVALID);
         2431  +	}
         2432  +
         2433  +	cackey_sessions[hSession].sign_active = 1;
         2434  +
         2435  +	cackey_sessions[hSession].sign_mechanism = pMechanism->mechanism;
         2436  +
         2437  +	cackey_sessions[hSession].sign_buflen = 128;
         2438  +	cackey_sessions[hSession].sign_bufused = 0;
         2439  +	cackey_sessions[hSession].sign_buf = malloc(sizeof(*cackey_sessions[hSession].sign_buf) * cackey_sessions[hSession].sign_buflen);
         2440  +
         2441  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         2442  +	if (mutex_retval != 0) {
         2443  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         2444  +
         2445  +		return(CKR_GENERAL_ERROR);
         2446  +	}
         2447  +
         2448  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         2449  +
         2450  +	return(CKR_OK);
         2451  +}
         2452  +
         2453  +CK_DEFINE_FUNCTION(CK_RV, C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) {
         2454  +	CK_RV sign_ret;
         2455  +
         2456  +	CACKEY_DEBUG_PRINTF("Called.");
         2457  +
         2458  +	if (!cackey_initialized) {
         2459  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2460  +
         2461  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2462  +	}
         2463  +
         2464  +	sign_ret = C_SignUpdate(hSession, pData, ulDataLen);
         2465  +	if (sign_ret != CKR_OK) {
         2466  +		CACKEY_DEBUG_PRINTF("Error.  SignUpdate() returned failure (rv = %lu).", (unsigned long) sign_ret);
         2467  +
         2468  +		return(sign_ret);
         2469  +	}
         2470  +
         2471  +	sign_ret = C_SignFinal(hSession, pSignature, pulSignatureLen);
         2472  +	if (sign_ret != CKR_OK) {
         2473  +		CACKEY_DEBUG_PRINTF("Error.  SignFinal() returned failure (rv = %lu).", (unsigned long) sign_ret);
         2474  +
         2475  +		return(sign_ret);
         2476  +	}
         2477  +
         2478  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         2479  +
         2480  +	return(CKR_OK);
         2481  +}
         2482  +
         2483  +CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) {
         2484  +	int mutex_retval;
         2485  +
         2486  +	CACKEY_DEBUG_PRINTF("Called.");
         2487  +
         2488  +	if (!cackey_initialized) {
         2489  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2490  +
         2491  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2492  +	}
         2493  +
         2494  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         2495  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         2496  +		
         2497  +		return(CKR_SESSION_HANDLE_INVALID);
         2498  +	}
         2499  +
         2500  +	if (pPart == NULL && ulPartLen == 0) {
         2501  +		/* Short circuit if we are asked to sign nothing... */
         2502  +		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i) (short circuit)", CKR_OK);
         2503  +
         2504  +		return(CKR_OK);
         2505  +	}
         2506  +
         2507  +	if (pPart == NULL) {
         2508  +		CACKEY_DEBUG_PRINTF("Error. pPart is NULL, but ulPartLen is not 0.");
         2509  +
         2510  +		return(CKR_ARGUMENTS_BAD);
         2511  +	}
         2512  +
         2513  +	if (ulPartLen == 0) {
         2514  +		CACKEY_DEBUG_PRINTF("Error. ulPartLen is 0, but pPart is not NULL.");
         2515  +
         2516  +		return(CKR_ARGUMENTS_BAD);
         2517  +	}
         2518  +
         2519  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         2520  +	if (mutex_retval != 0) {
         2521  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         2522  +
         2523  +		return(CKR_GENERAL_ERROR);
         2524  +	}
         2525  +
         2526  +	if (!cackey_sessions[hSession].active) {
         2527  +		cackey_mutex_unlock(cackey_biglock);
         2528  +
         2529  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         2530  +		
         2531  +		return(CKR_SESSION_HANDLE_INVALID);
         2532  +	}
         2533  +
         2534  +	if (!cackey_sessions[hSession].sign_active) {
         2535  +		cackey_mutex_unlock(cackey_biglock);
         2536  +
         2537  +		CACKEY_DEBUG_PRINTF("Error.  Sign not active.");
         2538  +		
         2539  +		return(CKR_OPERATION_NOT_INITIALIZED);
         2540  +	}
         2541  +
         2542  +	switch (cackey_sessions[hSession].sign_mechanism) {
         2543  +		case CKM_RSA_PKCS:
         2544  +			/* Accumulate directly */
         2545  +			if ((cackey_sessions[hSession].sign_bufused + ulPartLen) > cackey_sessions[hSession].sign_buflen) {
         2546  +				cackey_sessions[hSession].sign_buflen *= 2;
         2547  +
         2548  +				cackey_sessions[hSession].sign_buf = realloc(cackey_sessions[hSession].sign_buf, sizeof(*cackey_sessions[hSession].sign_buf) * cackey_sessions[hSession].sign_buflen);
         2549  +			}
         2550  +
         2551  +			memcpy(cackey_sessions[hSession].sign_buf + cackey_sessions[hSession].sign_bufused, pPart, ulPartLen);
         2552  +
         2553  +			cackey_sessions[hSession].sign_bufused += ulPartLen;
         2554  +
         2555  +			break;
         2556  +		case CKM_SHA1_RSA_PKCS:
         2557  +			/* Accumulate into a SHA1 hash */
         2558  +			cackey_mutex_unlock(cackey_biglock);
         2559  +
         2560  +			CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2561  +
         2562  +			return(CKR_FUNCTION_NOT_SUPPORTED);
         2563  +			break;
         2564  +	}
         2565  +
         2566  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         2567  +	if (mutex_retval != 0) {
         2568  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         2569  +
         2570  +		return(CKR_GENERAL_ERROR);
         2571  +	}
         2572  +
         2573  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         2574  +
         2575  +	return(CKR_OK);
         2576  +}
         2577  +
         2578  +CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) {
         2579  +	static CK_BYTE sigbuf[1024];
         2580  +	ssize_t sigbuflen;
         2581  +	CK_RV retval = CKR_GENERAL_ERROR;
         2582  +	int terminate_sign = 1;
         2583  +	int mutex_retval;
         2584  +	int fd;
         2585  +
         2586  +	CACKEY_DEBUG_PRINTF("Called.");
         2587  +
         2588  +	if (!cackey_initialized) {
         2589  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2590  +
         2591  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2592  +	}
         2593  +
         2594  +	if (pulSignatureLen == NULL) {
         2595  +		CACKEY_DEBUG_PRINTF("Error. pulSignatureLen is NULL.");
         2596  +
         2597  +		return(CKR_ARGUMENTS_BAD);
         2598  +	}
         2599  +
         2600  +	if (hSession == 0 || hSession >= (sizeof(cackey_sessions) / sizeof(cackey_sessions[0]))) {
         2601  +		CACKEY_DEBUG_PRINTF("Error.  Session out of range.");
         2602  +		
         2603  +		return(CKR_SESSION_HANDLE_INVALID);
         2604  +	}
         2605  +
         2606  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         2607  +	if (mutex_retval != 0) {
         2608  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         2609  +
         2610  +		return(CKR_GENERAL_ERROR);
         2611  +	}
         2612  +
         2613  +	if (!cackey_sessions[hSession].active) {
         2614  +		cackey_mutex_unlock(cackey_biglock);
         2615  +
         2616  +		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
         2617  +		
         2618  +		return(CKR_SESSION_HANDLE_INVALID);
         2619  +	}
         2620  +
         2621  +	if (!cackey_sessions[hSession].sign_active) {
         2622  +		cackey_mutex_unlock(cackey_biglock);
         2623  +
         2624  +		CACKEY_DEBUG_PRINTF("Error.  Sign not active.");
         2625  +		
         2626  +		return(CKR_OPERATION_NOT_INITIALIZED);
         2627  +	}
         2628  +
         2629  +	switch (cackey_sessions[hSession].sign_mechanism) {
         2630  +		case CKM_RSA_PKCS:
         2631  +			sigbuflen = -1;
         2632  +
         2633  +			/* XXX: Ask card to sign */
         2634  +
         2635  +			if (sigbuflen < 0) {
         2636  +				/* Signing failed. */
         2637  +				retval = CKR_GENERAL_ERROR;
         2638  +			} else if (((unsigned long) sigbuflen) > *pulSignatureLen && pSignature) {
         2639  +				/* Signed data too large */
         2640  +				retval = CKR_BUFFER_TOO_SMALL;
         2641  +
         2642  +				terminate_sign = 0;
         2643  +			} else {
         2644  +				terminate_sign = 0;
         2645  +
         2646  +				if (pSignature) {
         2647  +					memcpy(pSignature, sigbuf, sigbuflen);
         2648  +
         2649  +					terminate_sign = 1;
         2650  +				}
         2651  +
         2652  +				*pulSignatureLen = sigbuflen;
         2653  +
         2654  +				retval = CKR_OK;
         2655  +			}
         2656  +
         2657  +			break;
         2658  +		case CKM_SHA1_RSA_PKCS:
         2659  +			/* Accumulate into a SHA1 hash */
         2660  +			cackey_mutex_unlock(cackey_biglock);
         2661  +
         2662  +			CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2663  +
         2664  +			return(CKR_FUNCTION_NOT_SUPPORTED);
         2665  +			break;
         2666  +	}
         2667  +
         2668  +	if (terminate_sign) {
         2669  +		if (cackey_sessions[hSession].sign_buf) {
         2670  +			free(cackey_sessions[hSession].sign_buf);
         2671  +		}
         2672  +
         2673  +		cackey_sessions[hSession].sign_active = 0;
         2674  +	}
         2675  +
         2676  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         2677  +	if (mutex_retval != 0) {
         2678  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         2679  +
         2680  +		return(CKR_GENERAL_ERROR);
         2681  +	}
         2682  +
         2683  +	CACKEY_DEBUG_PRINTF("Returning %i", (int) retval);
         2684  +
         2685  +	return(retval);
         2686  +}
         2687  +
         2688  +CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
         2689  +	CACKEY_DEBUG_PRINTF("Called.");
         2690  +
         2691  +	if (!cackey_initialized) {
         2692  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2693  +
         2694  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2695  +	}
         2696  +
         2697  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2698  +
         2699  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2700  +}
         2701  +
         2702  +CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) {
         2703  +	CACKEY_DEBUG_PRINTF("Called.");
         2704  +
         2705  +	if (!cackey_initialized) {
         2706  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2707  +
         2708  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2709  +	}
         2710  +
         2711  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2712  +
         2713  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2714  +}
         2715  +
         2716  +CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
         2717  +	CACKEY_DEBUG_PRINTF("Called.");
         2718  +
         2719  +	if (!cackey_initialized) {
         2720  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2721  +
         2722  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2723  +	}
         2724  +
         2725  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2726  +
         2727  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2728  +}
         2729  +
         2730  +CK_DEFINE_FUNCTION(CK_RV, C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) {
         2731  +	CACKEY_DEBUG_PRINTF("Called.");
         2732  +
         2733  +	if (!cackey_initialized) {
         2734  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2735  +
         2736  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2737  +	}
         2738  +
         2739  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2740  +
         2741  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2742  +}
         2743  +
         2744  +CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) {
         2745  +	CACKEY_DEBUG_PRINTF("Called.");
         2746  +
         2747  +	if (!cackey_initialized) {
         2748  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2749  +
         2750  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2751  +	}
         2752  +
         2753  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2754  +
         2755  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2756  +}
         2757  +
         2758  +CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) {
         2759  +	CACKEY_DEBUG_PRINTF("Called.");
         2760  +
         2761  +	if (!cackey_initialized) {
         2762  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2763  +
         2764  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2765  +	}
         2766  +
         2767  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2768  +
         2769  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2770  +}
         2771  +
         2772  +CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) {
         2773  +	CACKEY_DEBUG_PRINTF("Called.");
         2774  +
         2775  +	if (!cackey_initialized) {
         2776  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2777  +
         2778  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2779  +	}
         2780  +
         2781  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2782  +
         2783  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2784  +}
         2785  +
         2786  +CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) {
         2787  +	CACKEY_DEBUG_PRINTF("Called.");
         2788  +
         2789  +	if (!cackey_initialized) {
         2790  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2791  +
         2792  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2793  +	}
         2794  +
         2795  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2796  +
         2797  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2798  +}
         2799  +
         2800  +CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) {
         2801  +	CACKEY_DEBUG_PRINTF("Called.");
         2802  +
         2803  +	if (!cackey_initialized) {
         2804  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2805  +
         2806  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2807  +	}
         2808  +
         2809  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2810  +
         2811  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2812  +}
         2813  +
         2814  +CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) {
         2815  +	CACKEY_DEBUG_PRINTF("Called.");
         2816  +
         2817  +	if (!cackey_initialized) {
         2818  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2819  +
         2820  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2821  +	}
         2822  +
         2823  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2824  +
         2825  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2826  +}
         2827  +
         2828  +CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) {
         2829  +	CACKEY_DEBUG_PRINTF("Called.");
         2830  +
         2831  +	if (!cackey_initialized) {
         2832  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2833  +
         2834  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2835  +	}
         2836  +
         2837  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2838  +
         2839  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2840  +}
         2841  +
         2842  +CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) {
         2843  +	CACKEY_DEBUG_PRINTF("Called.");
         2844  +
         2845  +	if (!cackey_initialized) {
         2846  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2847  +
         2848  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2849  +	}
         2850  +
         2851  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2852  +
         2853  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2854  +}
         2855  +
         2856  +CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) {
         2857  +	CACKEY_DEBUG_PRINTF("Called.");
         2858  +
         2859  +	if (!cackey_initialized) {
         2860  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2861  +
         2862  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2863  +	}
         2864  +
         2865  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2866  +
         2867  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2868  +}
         2869  +
         2870  +CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) {
         2871  +	CACKEY_DEBUG_PRINTF("Called.");
         2872  +
         2873  +	if (!cackey_initialized) {
         2874  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2875  +
         2876  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2877  +	}
         2878  +
         2879  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2880  +
         2881  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2882  +}
         2883  +
         2884  +CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) {
         2885  +	CACKEY_DEBUG_PRINTF("Called.");
         2886  +
         2887  +	if (!cackey_initialized) {
         2888  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2889  +
         2890  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2891  +	}
         2892  +
         2893  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2894  +
         2895  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2896  +}
         2897  +
         2898  +CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) {
         2899  +	CACKEY_DEBUG_PRINTF("Called.");
         2900  +
         2901  +	if (!cackey_initialized) {
         2902  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2903  +
         2904  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2905  +	}
         2906  +
         2907  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2908  +
         2909  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2910  +}
         2911  +
         2912  +CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) {
         2913  +	CACKEY_DEBUG_PRINTF("Called.");
         2914  +
         2915  +	if (!cackey_initialized) {
         2916  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2917  +
         2918  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2919  +	}
         2920  +
         2921  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2922  +
         2923  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2924  +}
         2925  +
         2926  +CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) {
         2927  +	CACKEY_DEBUG_PRINTF("Called.");
         2928  +
         2929  +	if (!cackey_initialized) {
         2930  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2931  +
         2932  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2933  +	}
         2934  +
         2935  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2936  +
         2937  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2938  +}
         2939  +
         2940  +CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen) {
         2941  +	CACKEY_DEBUG_PRINTF("Called.");
         2942  +
         2943  +	if (!cackey_initialized) {
         2944  +		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
         2945  +
         2946  +		return(CKR_CRYPTOKI_NOT_INITIALIZED);
         2947  +	}
         2948  +
         2949  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
         2950  +
         2951  +	return(CKR_FUNCTION_NOT_SUPPORTED);
         2952  +}
         2953  +
         2954  +/* Deprecated Function */
         2955  +CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)(CK_SESSION_HANDLE hSession) {
         2956  +	CACKEY_DEBUG_PRINTF("Called.");
         2957  +
         2958  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_PARALLEL (%i)", CKR_FUNCTION_NOT_PARALLEL);
         2959  +
         2960  +	return(CKR_FUNCTION_NOT_PARALLEL);
         2961  +
         2962  +	hSession = hSession; /* Supress unused variable warning */
         2963  +}
         2964  +
         2965  +/* Deprecated Function */
         2966  +CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)(CK_SESSION_HANDLE hSession) {
         2967  +	CACKEY_DEBUG_PRINTF("Called.");
         2968  +
         2969  +	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_PARALLEL (%i)", CKR_FUNCTION_NOT_PARALLEL);
         2970  +
         2971  +	return(CKR_FUNCTION_NOT_PARALLEL);
         2972  +
         2973  +	hSession = hSession; /* Supress unused variable warning */
         2974  +}
         2975  +
         2976  +CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) {
         2977  +	CK_FUNCTION_LIST_PTR pFunctionList;
         2978  +
         2979  +	CACKEY_DEBUG_PRINTF("Called.");
         2980  +
         2981  +	if (ppFunctionList == NULL) {
         2982  +		CACKEY_DEBUG_PRINTF("Error. ppFunctionList is NULL.");
         2983  +
         2984  +		return(CKR_ARGUMENTS_BAD);
         2985  +	}
         2986  +
         2987  +	pFunctionList = malloc(sizeof(*pFunctionList));
         2988  +
         2989  +	pFunctionList->version.major = ((CACKEY_CRYPTOKI_VERSION_CODE) >> 16) & 0xff;
         2990  +	pFunctionList->version.minor = ((CACKEY_CRYPTOKI_VERSION_CODE) >> 8) & 0xff;
         2991  +
         2992  +	pFunctionList->C_Initialize = C_Initialize;
         2993  +	pFunctionList->C_Finalize = C_Finalize;
         2994  +	pFunctionList->C_GetInfo = C_GetInfo;
         2995  +	pFunctionList->C_GetSlotList = C_GetSlotList;
         2996  +	pFunctionList->C_GetSlotInfo = C_GetSlotInfo;
         2997  +	pFunctionList->C_GetTokenInfo = C_GetTokenInfo;
         2998  +	pFunctionList->C_WaitForSlotEvent = C_WaitForSlotEvent;
         2999  +	pFunctionList->C_GetMechanismList = C_GetMechanismList;
         3000  +	pFunctionList->C_GetMechanismInfo = C_GetMechanismInfo;
         3001  +	pFunctionList->C_InitToken = C_InitToken;
         3002  +	pFunctionList->C_InitPIN = C_InitPIN;
         3003  +	pFunctionList->C_SetPIN = C_SetPIN;
         3004  +	pFunctionList->C_OpenSession = C_OpenSession;
         3005  +	pFunctionList->C_CloseSession = C_CloseSession;
         3006  +	pFunctionList->C_CloseAllSessions = C_CloseAllSessions;
         3007  +	pFunctionList->C_GetSessionInfo = C_GetSessionInfo;
         3008  +	pFunctionList->C_GetOperationState = C_GetOperationState;
         3009  +	pFunctionList->C_SetOperationState = C_SetOperationState;
         3010  +	pFunctionList->C_Login = C_Login;
         3011  +	pFunctionList->C_Logout = C_Logout;
         3012  +	pFunctionList->C_CreateObject = C_CreateObject;
         3013  +	pFunctionList->C_CopyObject = C_CopyObject;
         3014  +	pFunctionList->C_DestroyObject = C_DestroyObject;
         3015  +	pFunctionList->C_GetObjectSize = C_GetObjectSize;
         3016  +	pFunctionList->C_GetAttributeValue = C_GetAttributeValue;
         3017  +	pFunctionList->C_SetAttributeValue = C_SetAttributeValue;
         3018  +	pFunctionList->C_FindObjectsInit = C_FindObjectsInit;
         3019  +	pFunctionList->C_FindObjects = C_FindObjects;
         3020  +	pFunctionList->C_FindObjectsFinal = C_FindObjectsFinal;
         3021  +	pFunctionList->C_EncryptInit = C_EncryptInit;
         3022  +	pFunctionList->C_Encrypt = C_Encrypt;
         3023  +	pFunctionList->C_EncryptUpdate = C_EncryptUpdate;
         3024  +	pFunctionList->C_EncryptFinal = C_EncryptFinal;
         3025  +	pFunctionList->C_DecryptInit = C_DecryptInit;
         3026  +	pFunctionList->C_Decrypt = C_Decrypt;
         3027  +	pFunctionList->C_DecryptUpdate = C_DecryptUpdate;
         3028  +	pFunctionList->C_DecryptFinal = C_DecryptFinal;
         3029  +	pFunctionList->C_DigestInit = C_DigestInit;
         3030  +	pFunctionList->C_Digest = C_Digest;
         3031  +	pFunctionList->C_DigestUpdate = C_DigestUpdate;
         3032  +	pFunctionList->C_DigestKey = C_DigestKey;
         3033  +	pFunctionList->C_DigestFinal = C_DigestFinal;
         3034  +	pFunctionList->C_SignInit = C_SignInit;
         3035  +	pFunctionList->C_Sign = C_Sign;
         3036  +	pFunctionList->C_SignUpdate = C_SignUpdate;
         3037  +	pFunctionList->C_SignFinal = C_SignFinal;
         3038  +	pFunctionList->C_SignRecoverInit = C_SignRecoverInit;
         3039  +	pFunctionList->C_SignRecover = C_SignRecover;
         3040  +	pFunctionList->C_VerifyInit = C_VerifyInit;
         3041  +	pFunctionList->C_Verify = C_Verify;
         3042  +	pFunctionList->C_VerifyUpdate = C_VerifyUpdate;
         3043  +	pFunctionList->C_VerifyFinal = C_VerifyFinal;
         3044  +	pFunctionList->C_VerifyRecoverInit = C_VerifyRecoverInit;
         3045  +	pFunctionList->C_VerifyRecover = C_VerifyRecover;
         3046  +	pFunctionList->C_DigestEncryptUpdate = C_DigestEncryptUpdate;
         3047  +	pFunctionList->C_DecryptDigestUpdate = C_DecryptDigestUpdate;
         3048  +	pFunctionList->C_SignEncryptUpdate = C_SignEncryptUpdate;
         3049  +	pFunctionList->C_DecryptVerifyUpdate = C_DecryptVerifyUpdate;
         3050  +	pFunctionList->C_GenerateKey = C_GenerateKey;
         3051  +	pFunctionList->C_GenerateKeyPair = C_GenerateKeyPair;
         3052  +	pFunctionList->C_WrapKey = C_WrapKey;
         3053  +	pFunctionList->C_UnwrapKey = C_UnwrapKey;
         3054  +	pFunctionList->C_DeriveKey = C_DeriveKey;
         3055  +	pFunctionList->C_SeedRandom = C_SeedRandom;
         3056  +	pFunctionList->C_GenerateRandom = C_GenerateRandom;
         3057  +	pFunctionList->C_GetFunctionStatus = C_GetFunctionStatus;
         3058  +	pFunctionList->C_CancelFunction = C_CancelFunction;
         3059  +	pFunctionList->C_GetFunctionList = C_GetFunctionList;
         3060  +
         3061  +	*ppFunctionList = pFunctionList;
         3062  +
         3063  +	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
         3064  +
         3065  +	return(CKR_OK);
         3066  +}
     9   3067