Diff

Differences From Artifact [efb7accc6b]:

To Artifact [c365c15fc9]:


    33     33   #define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name)
    34     34   #define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name)
    35     35   #ifndef NULL_PTR
    36     36   #  define NULL_PTR 0
    37     37   #endif
    38     38   
    39     39   #include "pkcs11.h"
           40  +#include "asn1-x509.h"
    40     41   
    41     42   #ifndef CACKEY_CRYPTOKI_VERSION_CODE
    42     43   #  define CACKEY_CRYPTOKI_VERSION_CODE 0x021e00
    43     44   #endif
    44     45   
           46  +#ifndef CKA_TRUST_SERVER_AUTH
           47  +#  define CKA_TRUST_SERVER_AUTH 0xce536358
           48  +#endif
           49  +#ifndef CKA_TRUST_CLIENT_AUTH
           50  +#  define CKA_TRUST_CLIENT_AUTH 0xce536359
           51  +#endif
           52  +#ifndef CKA_TRUST_CODE_SIGNING
           53  +#  define CKA_TRUST_CODE_SIGNING 0xce53635a
           54  +#endif
           55  +#ifndef CKA_TRUST_EMAIL_PROTECTION
           56  +#  define CKA_TRUST_EMAIL_PROTECTION 0xce53635b
           57  +#endif
           58  +
           59  +/* GSC-IS v2.1 Definitions */
           60  +#define GSCIS_CLASS_ISO7816           0x00
           61  +#define GSCIS_CLASS_GLOBAL_PLATFORM   0x80
           62  +
           63  +#define GSCIS_INSTR_GET_RESPONSE      0xC0
           64  +#define GSCIS_INSTR_READ_BINARY       0xB0
           65  +#define GSCIS_INSTR_UPDATE_BINARY     0xD6
           66  +#define GSCIS_INSTR_SELECT            0xA4
           67  +#define GSCIS_INSTR_EXTERNAL_AUTH     0x82
           68  +#define GSCIS_INSTR_GET_CHALLENGE     0x84
           69  +#define GSCIS_INSTR_INTERNAL_AUTH     0x88
           70  +#define GSCIS_INSTR_VERIFY            0x20
           71  +#define GSCIS_INSTR_SIGN              0x2A
           72  +#define GSCIS_INSTR_GET_PROP          0x56
           73  +#define GSCIS_INSTR_GET_ACR           0x4C
           74  +#define GSCIS_INSTR_READ_BUFFER       0x52
           75  +#define GSCIS_INSTR_SIGNDECRYPT       0x42
           76  +
           77  +#define GSCIS_PARAM_SELECT_APPLET     0x04
           78  +
           79  +/* CCC */
           80  +#define GSCIS_TAG_CARDID              0xF0
           81  +#define GSCIS_TAG_CCC_VER             0xF1
           82  +#define GSCIS_TAG_CCG_VER             0xF2
           83  +#define GSCIS_TAG_CARDURL             0xF3
           84  +#define GSCIS_TAG_PKCS15              0xF4
           85  +#define GSCIS_TAG_REG_DATA_MODEL      0xF5
           86  +#define GSCIS_TAG_ACR_TABLE           0xF6
           87  +#define GSCIS_TAG_CARD_APDU           0xF7
           88  +#define GSCIS_TAG_REDIRECTION         0xFA
           89  +#define GSCIS_TAG_CT                  0xFB
           90  +#define GSCIS_TAG_ST                  0xFC
           91  +#define GSCIS_TAG_NEXTCCC             0xFD
           92  +
           93  +/* General - EF 2200 */
           94  +#define GSCIS_TAG_FNAME               0x01
           95  +#define GSCIS_TAG_MNAME               0x02
           96  +#define GSCIS_TAG_LNAME               0x03
           97  +#define GSCIS_TAG_SUFFIX              0x04
           98  +#define GSCIS_TAG_GOVT_AGENCY         0x05
           99  +#define GSCIS_TAG_BUREAU              0x06
          100  +#define GSCIS_TAG_BUREAU_CODE         0x07
          101  +#define GSCIS_TAG_DEPT_CODE           0x08
          102  +#define GSCIS_TAG_TITLE               0x09
          103  +#define GSCIS_TAG_BUILDING            0x10
          104  +#define GSCIS_TAG_OFFICE_ADDR1        0x11
          105  +#define GSCIS_TAG_OFFICE_ADDR2        0x12
          106  +#define GSCIS_TAG_OFFICE_CITY         0x13
          107  +#define GSCIS_TAG_OFFICE_STATE        0x14
          108  +#define GSCIS_TAG_OFFICE_ZIP          0x15
          109  +#define GSCIS_TAG_OFFICE_COUNTRY      0x16
          110  +#define GSCIS_TAG_OFFICE_PHONE        0x17
          111  +#define GSCIS_TAG_OFFICE_PHONE_EXT    0x18
          112  +#define GSCIS_TAG_OFFICE_FAX          0x19
          113  +#define GSCIS_TAG_OFFICE_EMAIL        0x1A
          114  +#define GSCIS_TAG_OFFICE_ROOM         0x1B
          115  +#define GSCIS_TAG_NONGOV_AGENCY       0x1C
          116  +#define GSCIS_TAG_SSN_DESIGNATOR      0x1D
          117  +
          118  +/* PII - EF 2100 */
          119  +#define GSCIS_TAG_SSN                 0x20
          120  +#define GSCIS_TAG_DOB                 0x21
          121  +#define GSCIS_TAG_GENDER              0x22
          122  +
          123  +/* Login Information - EF 4000 */
          124  +#define GSCIS_TAG_USERID              0x40
          125  +#define GSCIS_TAG_DOMAIN              0x41
          126  +#define GSCIS_TAG_PASSWORD            0x42
          127  +
          128  +/* Card Information - EF 5000 */
          129  +#define GSCIS_TAG_ISSUERID            0x50
          130  +#define GSCIS_TAG_SERNO               0x51
          131  +#define GSCIS_TAG_ISSUE_DATE          0x52
          132  +#define GSCIS_TAG_EXPIRE_DATE         0x53
          133  +#define GSCIS_TAG_CARD_TYPE           0x54
          134  +#define GSCIS_TAG_SECURITY_CODE       0x57
          135  +#define GSCIS_TAG_CARDID_AID          0x58
          136  +
          137  +/* PKI Information - EF 7000 */
          138  +#define GSCIS_TAG_CERTIFICATE         0x70
          139  +#define GSCIS_TAG_CERT_ISSUE_DATE     0x71
          140  +#define GSCIS_TAG_CERT_EXPIRE_DATE    0x72
          141  +
    45    142   #ifdef CACKEY_DEBUG
    46    143   #  ifdef HAVE_STDIO_H
    47    144   #    include <stdio.h>
    48    145   #  endif
    49    146   
    50    147   #  define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); }
    51    148   #  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"); }
................................................................................
    73    170   		fprintf(stderr, "%s(): ", func);
    74    171   		fprintf(stderr, "REALLOC(%p) = %p", ptr, retval);
    75    172   		fprintf(stderr, "\n");
    76    173   	}
    77    174   
    78    175   	return(retval);
    79    176   }
          177  +
          178  +static const char *CACKEY_DEBUG_FUNC_TAG_TO_STR(unsigned char tag) {
          179  +	const char *retval = NULL;
          180  +
          181  +	switch (tag) {
          182  +		case GSCIS_TAG_CARDID:
          183  +			retval = "GSCIS_TAG_CARDID";
          184  +			break;
          185  +		case GSCIS_TAG_CCC_VER:
          186  +			retval = "GSCIS_TAG_CCC_VER";
          187  +			break;
          188  +		case GSCIS_TAG_CCG_VER:
          189  +			retval = "GSCIS_TAG_CCG_VER";
          190  +			break;
          191  +		case GSCIS_TAG_CARDURL:
          192  +			retval = "GSCIS_TAG_CARDURL";
          193  +			break;
          194  +		case GSCIS_TAG_PKCS15:
          195  +			retval = "GSCIS_TAG_PKCS15";
          196  +			break;
          197  +		case GSCIS_TAG_REG_DATA_MODEL:
          198  +			retval = "GSCIS_TAG_REG_DATA_MODEL";
          199  +			break;
          200  +		case GSCIS_TAG_ACR_TABLE:
          201  +			retval = "GSCIS_TAG_ACR_TABLE";
          202  +			break;
          203  +		case GSCIS_TAG_CARD_APDU:
          204  +			retval = "GSCIS_TAG_CARD_APDU";
          205  +			break;
          206  +		case GSCIS_TAG_REDIRECTION:
          207  +			retval = "GSCIS_TAG_REDIRECTION";
          208  +			break;
          209  +		case GSCIS_TAG_CT:
          210  +			retval = "GSCIS_TAG_CT";
          211  +			break;
          212  +		case GSCIS_TAG_ST:
          213  +			retval = "GSCIS_TAG_ST";
          214  +			break;
          215  +		case GSCIS_TAG_NEXTCCC:
          216  +			retval = "GSCIS_TAG_NEXTCCC";
          217  +			break;
          218  +		case GSCIS_TAG_FNAME:
          219  +			retval = "GSCIS_TAG_FNAME";
          220  +			break;
          221  +		case GSCIS_TAG_MNAME:
          222  +			retval = "GSCIS_TAG_MNAME";
          223  +			break;
          224  +		case GSCIS_TAG_LNAME:
          225  +			retval = "GSCIS_TAG_LNAME";
          226  +			break;
          227  +		case GSCIS_TAG_SUFFIX:
          228  +			retval = "GSCIS_TAG_SUFFIX";
          229  +			break;
          230  +		case GSCIS_TAG_GOVT_AGENCY:
          231  +			retval = "GSCIS_TAG_GOVT_AGENCY";
          232  +			break;
          233  +		case GSCIS_TAG_BUREAU:
          234  +			retval = "GSCIS_TAG_BUREAU";
          235  +			break;
          236  +		case GSCIS_TAG_BUREAU_CODE:
          237  +			retval = "GSCIS_TAG_BUREAU_CODE";
          238  +			break;
          239  +		case GSCIS_TAG_DEPT_CODE:
          240  +			retval = "GSCIS_TAG_DEPT_CODE";
          241  +			break;
          242  +		case GSCIS_TAG_TITLE:
          243  +			retval = "GSCIS_TAG_TITLE";
          244  +			break;
          245  +		case GSCIS_TAG_BUILDING:
          246  +			retval = "GSCIS_TAG_BUILDING";
          247  +			break;
          248  +		case GSCIS_TAG_OFFICE_ADDR1:
          249  +			retval = "GSCIS_TAG_OFFICE_ADDR1";
          250  +			break;
          251  +		case GSCIS_TAG_OFFICE_ADDR2:
          252  +			retval = "GSCIS_TAG_OFFICE_ADDR2";
          253  +			break;
          254  +		case GSCIS_TAG_OFFICE_CITY:
          255  +			retval = "GSCIS_TAG_OFFICE_CITY";
          256  +			break;
          257  +		case GSCIS_TAG_OFFICE_STATE:
          258  +			retval = "GSCIS_TAG_OFFICE_STATE";
          259  +			break;
          260  +		case GSCIS_TAG_OFFICE_ZIP:
          261  +			retval = "GSCIS_TAG_OFFICE_ZIP";
          262  +			break;
          263  +		case GSCIS_TAG_OFFICE_COUNTRY:
          264  +			retval = "GSCIS_TAG_OFFICE_COUNTRY";
          265  +			break;
          266  +		case GSCIS_TAG_OFFICE_PHONE:
          267  +			retval = "GSCIS_TAG_OFFICE_PHONE";
          268  +			break;
          269  +		case GSCIS_TAG_OFFICE_PHONE_EXT:
          270  +			retval = "GSCIS_TAG_OFFICE_PHONE_EXT";
          271  +			break;
          272  +		case GSCIS_TAG_OFFICE_FAX:
          273  +			retval = "GSCIS_TAG_OFFICE_FAX";
          274  +			break;
          275  +		case GSCIS_TAG_OFFICE_EMAIL:
          276  +			retval = "GSCIS_TAG_OFFICE_EMAIL";
          277  +			break;
          278  +		case GSCIS_TAG_OFFICE_ROOM:
          279  +			retval = "GSCIS_TAG_OFFICE_ROOM";
          280  +			break;
          281  +		case GSCIS_TAG_NONGOV_AGENCY:
          282  +			retval = "GSCIS_TAG_NONGOV_AGENCY";
          283  +			break;
          284  +		case GSCIS_TAG_SSN_DESIGNATOR:
          285  +			retval = "GSCIS_TAG_SSN_DESIGNATOR";
          286  +			break;
          287  +		case GSCIS_TAG_SSN:
          288  +			retval = "GSCIS_TAG_SSN";
          289  +			break;
          290  +		case GSCIS_TAG_DOB:
          291  +			retval = "GSCIS_TAG_DOB";
          292  +			break;
          293  +		case GSCIS_TAG_GENDER:
          294  +			retval = "GSCIS_TAG_GENDER";
          295  +			break;
          296  +		case GSCIS_TAG_USERID:
          297  +			retval = "GSCIS_TAG_USERID";
          298  +			break;
          299  +		case GSCIS_TAG_DOMAIN:
          300  +			retval = "GSCIS_TAG_DOMAIN";
          301  +			break;
          302  +		case GSCIS_TAG_PASSWORD:
          303  +			retval = "GSCIS_TAG_PASSWORD";
          304  +			break;
          305  +		case GSCIS_TAG_ISSUERID:
          306  +			retval = "GSCIS_TAG_ISSUERID";
          307  +			break;
          308  +		case GSCIS_TAG_SERNO:
          309  +			retval = "GSCIS_TAG_SERNO";
          310  +			break;
          311  +		case GSCIS_TAG_ISSUE_DATE:
          312  +			retval = "GSCIS_TAG_ISSUE_DATE";
          313  +			break;
          314  +		case GSCIS_TAG_EXPIRE_DATE:
          315  +			retval = "GSCIS_TAG_EXPIRE_DATE";
          316  +			break;
          317  +		case GSCIS_TAG_CARD_TYPE:
          318  +			retval = "GSCIS_TAG_CARD_TYPE";
          319  +			break;
          320  +		case GSCIS_TAG_SECURITY_CODE:
          321  +			retval = "GSCIS_TAG_SECURITY_CODE";
          322  +			break;
          323  +		case GSCIS_TAG_CARDID_AID:
          324  +			retval = "GSCIS_TAG_CARDID_AID";
          325  +			break;
          326  +		case GSCIS_TAG_CERTIFICATE:
          327  +			retval = "GSCIS_TAG_CERTIFICATE";
          328  +			break;
          329  +		case GSCIS_TAG_CERT_ISSUE_DATE:
          330  +			retval = "GSCIS_TAG_CERT_ISSUE_DATE";
          331  +			break;
          332  +		case GSCIS_TAG_CERT_EXPIRE_DATE:
          333  +			retval = "GSCIS_TAG_CERT_EXPIRE_DATE";
          334  +			break;
          335  +	}
          336  +
          337  +	if (retval == NULL) {
          338  +		retval = "UNKNOWN";
          339  +	}
          340  +
          341  +	return(retval);
          342  +}
    80    343   
    81    344   #  define malloc(x) CACKEY_DEBUG_FUNC_MALLOC(x, __func__)
    82    345   #  define realloc(x, y) CACKEY_DEBUG_FUNC_REALLOC(x, y, __func__)
    83    346   #else
    84    347   #  define CACKEY_DEBUG_PRINTF(x...) /**/
    85    348   #  define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/
    86    349   #  define CACKEY_DEBUG_PERROR(x) /**/
    87         -#endif
    88         -
    89         -#ifndef CKA_TRUST_SERVER_AUTH
    90         -#  define CKA_TRUST_SERVER_AUTH 0xce536358
    91         -#endif
    92         -#ifndef CKA_TRUST_CLIENT_AUTH
    93         -#  define CKA_TRUST_CLIENT_AUTH 0xce536359
    94         -#endif
    95         -#ifndef CKA_TRUST_CODE_SIGNING
    96         -#  define CKA_TRUST_CODE_SIGNING 0xce53635a
    97         -#endif
    98         -#ifndef CKA_TRUST_EMAIL_PROTECTION
    99         -#  define CKA_TRUST_EMAIL_PROTECTION 0xce53635b
          350  +#  define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED"
   100    351   #endif
   101    352   
   102    353   struct cackey_identity {
   103    354   	CK_ATTRIBUTE *attributes;
   104    355   	CK_ULONG attributes_count;
   105    356   };
   106    357   
   107    358   struct cackey_session {
   108    359   	int active;
   109    360   
   110    361   	CK_SLOT_ID slotID;
          362  +
   111    363   	CK_STATE state;
   112    364   	CK_FLAGS flags;
   113    365   	CK_ULONG ulDeviceError;
   114    366   	CK_VOID_PTR pApplication;
   115    367   	CK_NOTIFY Notify;
   116    368   
   117    369   	struct cackey_identity *identities;
................................................................................
   128    380   	unsigned long sign_buflen;
   129    381   	unsigned long sign_bufused;
   130    382   
   131    383   	int decrypt_active;
   132    384   	CK_MECHANISM_TYPE decrypt_mechanism;
   133    385   	CK_VOID_PTR decrypt_mech_parm;
   134    386   	CK_ULONG decrypt_mech_parmlen;
          387  +
          388  +};
          389  +
          390  +struct cackey_slot {
          391  +	int active;
          392  +
          393  +	char *pcsc_reader;
          394  +
          395  +	int pcsc_card_connected;
          396  +	SCARDHANDLE pcsc_card;
          397  +};
          398  +
          399  +struct cackey_tlv_entity {
          400  +	uint8_t tag;
          401  +	size_t length;
          402  +	unsigned char *value_buf; /* Raw buffer */
   135    403   };
   136    404   
   137    405   /* CACKEY Global Handles */
   138    406   static void *cackey_biglock = NULL;
   139    407   static struct cackey_session cackey_sessions[128];
          408  +static struct cackey_slot cackey_slots[128];
   140    409   static int cackey_initialized = 0;
   141    410   static int cackey_biglock_init = 0;
   142    411   CK_C_INITIALIZE_ARGS cackey_args;
   143    412   
   144    413   /* PCSC Global Handles */
   145    414   static LPSCARDCONTEXT cackey_pcsc_handle = NULL;
   146    415   
................................................................................
   175    444   #endif
   176    445   
   177    446   	CACKEY_DEBUG_PRINTF("Returning 0x%lx", retval);
   178    447   
   179    448   	return(retval);
   180    449   }
   181    450   
   182         -/* APDU Related Functions */
   183         -static int cackey_send_apdu(unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char *resp, unsigned char resplen) {
          451  +/* PC/SC Related Functions */
          452  +static void cackey_slots_disconnect_all(void) {
          453  +	uint32_t idx;
          454  +
          455  +	CACKEY_DEBUG_PRINTF("Called.");
          456  +
          457  +	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
          458  +		if (cackey_slots[idx].pcsc_card_connected) {
          459  +			CACKEY_DEBUG_PRINTF("SCardDisconnect(%lu) called", (unsigned long) idx);
          460  +
          461  +			SCardDisconnect(cackey_slots[idx].pcsc_card, SCARD_LEAVE_CARD);
          462  +		}
          463  +
          464  +		cackey_slots[idx].pcsc_card_connected = 0;
          465  +	}
          466  +
          467  +	CACKEY_DEBUG_PRINTF("Returning");
          468  +
          469  +	return;
          470  +}
          471  +
          472  +static int cackey_pcsc_connect(void) {
   184    473   	LONG scard_est_context_ret;
   185    474   #ifdef HAVE_SCARDISVALIDCONTEXT
   186    475   	LONG scard_isvalid_ret;
   187    476   #endif
   188    477   
   189    478   	CACKEY_DEBUG_PRINTF("Called.");
   190    479   
   191    480   	if (cackey_pcsc_handle == NULL) {
   192    481   		cackey_pcsc_handle = malloc(sizeof(*cackey_pcsc_handle));
   193    482   		if (cackey_pcsc_handle == NULL) {
   194    483   			CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure");
   195    484   
          485  +			cackey_slots_disconnect_all();
          486  +
   196    487   			return(-1);
   197    488   		}
   198    489   
          490  +		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
   199    491   		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
   200    492   		if (scard_est_context_ret != SCARD_S_SUCCESS) {
   201    493   			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %li), returning in failure", (long) scard_est_context_ret);
   202    494   
   203    495   			free(cackey_pcsc_handle);
          496  +
          497  +			cackey_slots_disconnect_all();
   204    498   
   205    499   			return(-1);
   206    500   		}
   207    501   	}
   208    502   
   209    503   #ifdef HAVE_SCARDISVALIDCONTEXT
          504  +	CACKEY_DEBUG_PRINTF("SCardIsValidContext() called");
   210    505   	scard_isvalid_ret = SCardIsValidContext(*cackey_pcsc_handle);
   211    506   	if (scard_isvalid_ret != SCARD_S_SUCCESS) {
   212         -		CACKEY_DEBUG_PRINTF("Handle has become invalid, trying to re-establish...");
          507  +		CACKEY_DEBUG_PRINTF("Handle has become invalid (SCardIsValidContext = %li), trying to re-establish...", (long) scard_isvalid_ret);
   213    508   
          509  +		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
   214    510   		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
   215    511   		if (scard_est_context_ret != SCARD_S_SUCCESS) {
   216    512   			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %li), returning in failure", (long) scard_est_context_ret);
   217    513   
   218    514   			free(cackey_pcsc_handle);
          515  +
          516  +			cackey_slots_disconnect_all();
   219    517   
   220    518   			return(-1);
   221    519   		}
   222    520   
   223    521   		CACKEY_DEBUG_PRINTF("Handle has been re-established");
   224    522   	}
   225    523   #endif
   226    524   
   227         -	/* Connect to a reader, if needed */
          525  +	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");
          526  +
          527  +	return(0);
          528  +}
          529  +
          530  +/* APDU Related Functions */
          531  +/** Le = 0x00 to indicate not to send Le **/
          532  +static int cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) {
          533  +	uint8_t major_rc, minor_rc;
          534  +	size_t bytes_to_copy, tmp_respdata_len;
          535  +	DWORD protocol;
          536  +	DWORD xmit_len, recv_len;
          537  +	LONG scard_conn_ret, scard_xmit_ret, scard_reconn_ret;
          538  +	BYTE xmit_buf[1024], recv_buf[1024];
          539  +	int pcsc_connect_ret, pcsc_getresp_ret;
          540  +	int idx;
          541  +
          542  +	CACKEY_DEBUG_PRINTF("Called.");
          543  +
          544  +	if (!slot) {
          545  +		CACKEY_DEBUG_PRINTF("Invalid slot specified.");
          546  +
          547  +		return(-1);
          548  +	}
          549  +
          550  +	pcsc_connect_ret = cackey_pcsc_connect();
          551  +	if (pcsc_connect_ret < 0) {
          552  +		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");
          553  +
          554  +		return(-1);
          555  +	}
          556  +
          557  +	/* Connect to reader, if needed */
          558  +	if (!slot->pcsc_card_connected) {
          559  +		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader);
          560  +		scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol);
          561  +
          562  +		if (scard_conn_ret != SCARD_S_SUCCESS) {
          563  +			CACKEY_DEBUG_PRINTF("Connection to card failed, returning in failure (SCardConnect() = %li)", (long) scard_conn_ret);
          564  +
          565  +			return(-1);
          566  +		}
          567  +
          568  +		slot->pcsc_card_connected = 1;
          569  +	}
   228    570   
   229    571   	/* Transmit */
          572  +	xmit_len = 0;
          573  +	xmit_buf[xmit_len++] = class;
          574  +	xmit_buf[xmit_len++] = instruction;
          575  +	xmit_buf[xmit_len++] = p1;
          576  +	xmit_buf[xmit_len++] = p2;
          577  +	if (data) {
          578  +		xmit_buf[xmit_len++] = lc;
          579  +		for (idx = 0; idx < lc; idx++) {
          580  +			xmit_buf[xmit_len++] = data[idx];
          581  +		}
          582  +	}
          583  +
          584  +	if (le != 0x00) {
          585  +		xmit_buf[xmit_len++] = le;
          586  +	}
          587  +
          588  +	CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);
          589  +
          590  +	recv_len = sizeof(recv_buf);
          591  +	scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);
          592  +	if (scard_xmit_ret != SCARD_S_SUCCESS) {
          593  +		CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %lx)", (unsigned long) scard_xmit_ret);
          594  +
          595  +		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
          596  +			CACKEY_DEBUG_PRINTF("Reset required, please hold...");
          597  +
          598  +			scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol);
          599  +			if (scard_reconn_ret == SCARD_S_SUCCESS) {
          600  +				CACKEY_DEBUG_PRINTF("Reset successful, retransmitting");
          601  +				scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T0, recv_buf, &recv_len);
          602  +
          603  +				if (scard_xmit_ret != SCARD_S_SUCCESS) {
          604  +					CACKEY_DEBUG_PRINTF("Retransmit failed, returning in failure after disconnecting the card");
          605  +
          606  +					SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
          607  +					slot->pcsc_card_connected = 0;
          608  +
          609  +					return(-1);
          610  +				}
          611  +			} else {
          612  +				CACKEY_DEBUG_PRINTF("Disconnecting card");
          613  +
          614  +				SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
          615  +				slot->pcsc_card_connected = 0;
          616  +
          617  +				CACKEY_DEBUG_PRINTF("Returning in failure");
          618  +				return(-1);
          619  +			}
          620  +		} else {
          621  +			CACKEY_DEBUG_PRINTF("Disconnecting card");
          622  +
          623  +			SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
          624  +			slot->pcsc_card_connected = 0;
          625  +
          626  +			CACKEY_DEBUG_PRINTF("Returning in failure");
          627  +			return(-1);
          628  +		}
          629  +	}
          630  +
          631  +	CACKEY_DEBUG_PRINTBUF("Returned Value:", recv_buf, recv_len);
          632  +
          633  +	if (recv_len < 2) {
          634  +		/* Minimal response length is 2 bytes, returning in failure */
          635  +		CACKEY_DEBUG_PRINTF("Response too small, returning in failure (recv_len = %lu)", (unsigned long) recv_len);
          636  +
          637  +		return(-1);
          638  +	}
          639  +
          640  +	/* Determine result code */
          641  +	major_rc = recv_buf[recv_len - 2];
          642  +	minor_rc = recv_buf[recv_len - 1];
          643  +	if (respcode) {
          644  +		*respcode = (major_rc << 8) | minor_rc;
          645  +	}
          646  +
          647  +	/* Adjust message buffer */
          648  +	recv_len -= 2;
          649  +
          650  +	/* Add bytes to return value */
          651  +	tmp_respdata_len = 0;
          652  +	if (respdata && respdata_len) {
          653  +		tmp_respdata_len = *respdata_len;
          654  +
          655  +		bytes_to_copy = *respdata_len;
          656  +
          657  +		if (recv_len < bytes_to_copy) {
          658  +			bytes_to_copy = recv_len;
          659  +		}
          660  +
          661  +		CACKEY_DEBUG_PRINTF("Copying %lu bytes to the buffer", (unsigned long) bytes_to_copy);
          662  +
          663  +		memcpy(respdata, recv_buf, bytes_to_copy);
          664  +		respdata += bytes_to_copy;
          665  +
          666  +		*respdata_len = bytes_to_copy;
          667  +		tmp_respdata_len -= bytes_to_copy;
          668  +	} else {
          669  +		if (recv_len != 0) {
          670  +			CACKEY_DEBUG_PRINTF("Throwing away %lu bytes, nowhere to put them!", (unsigned long) recv_len);
          671  +		}
          672  +	}
          673  +
          674  +	if (major_rc == 0x61) {
          675  +		/* We need to READ */
          676  +		CACKEY_DEBUG_PRINTF("Buffer read required");
          677  +
          678  +		pcsc_getresp_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_GET_RESPONSE, 0x00, 0x00, 0, NULL, minor_rc, respcode, respdata, &tmp_respdata_len);
          679  +		if (pcsc_getresp_ret < 0) {
          680  +			CACKEY_DEBUG_PRINTF("Buffer read failed!  Returning in failure");
          681  +
          682  +			return(-1);
          683  +		}
          684  +
          685  +		if (respdata_len) {
          686  +			*respdata_len += tmp_respdata_len;
          687  +		}
          688  +
          689  +		CACKEY_DEBUG_PRINTF("Returning in success (buffer read complete)");
          690  +		return(0);
          691  +	}
          692  +
          693  +	if (major_rc == 0x90) {
          694  +		/* Success */
          695  +		CACKEY_DEBUG_PRINTF("Returning in success (major_rc = 0x90)");
          696  +
          697  +		return(0);
          698  +	}
          699  +
          700  +
          701  +	CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure");
          702  +
          703  +	return(-1);
          704  +}
          705  +
          706  +static ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset) {
          707  +	size_t offset = 0, max_offset, max_count;
          708  +	unsigned char cmd[2];
          709  +	uint16_t respcode;
          710  +	int send_ret;
          711  +
          712  +	CACKEY_DEBUG_PRINTF("Called");
          713  +
          714  +	max_offset = count;
          715  +	max_count = 64;
          716  +
          717  +	cmd[0] = t_or_v;
          718  +
          719  +	while (1) {
          720  +		if (offset >= max_offset) {
          721  +			CACKEY_DEBUG_PRINTF("Buffer too small, returning what we got...");
          722  +
          723  +			break;
          724  +		}
          725  +
          726  +		count = max_offset - offset;
          727  +		if (count > max_count) {
          728  +			count = max_count;
          729  +		}
          730  +
          731  +		cmd[1] = count;
          732  +
          733  +		send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_READ_BUFFER, ((initial_offset + offset) >> 8) & 0xff, (initial_offset + offset) & 0xff, sizeof(cmd), cmd, 0x00, &respcode, buffer + offset, &count);
          734  +		if (send_ret < 0) {
          735  +			if (respcode == 0x6A86) {
          736  +				if (max_count == 1) {
          737  +					break;
          738  +				}
          739  +
          740  +				max_count = max_count / 2;
          741  +
          742  +				continue;
          743  +			}
          744  +
          745  +			CACKEY_DEBUG_PRINTF("cackey_send_apdu() failed, returning in failure");
          746  +
          747  +			return(-1);
          748  +		}
          749  +
          750  +		offset += count;
          751  +
          752  +		if (count < max_count) {
          753  +			CACKEY_DEBUG_PRINTF("Short read -- count = %i, cmd[1] = %i", count, cmd[1]);
          754  +
          755  +			break;
          756  +		}
          757  +	}
          758  +
          759  +	CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) offset);
          760  +
          761  +	return(offset);
          762  +}
          763  +
          764  +static int cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) {
          765  +	int send_ret;
          766  +
          767  +	CACKEY_DEBUG_PRINTF("Called");
          768  +
          769  +	CACKEY_DEBUG_PRINTBUF("Selecting applet:", aid, aid_len);
          770  +
          771  +	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, GSCIS_PARAM_SELECT_APPLET, 0x0C, aid_len, aid, 0x00, NULL, NULL, NULL);
          772  +	if (send_ret < 0) {
          773  +		CACKEY_DEBUG_PRINTF("Failed to open applet, returning in failure");
          774  +
          775  +		return(-1);
          776  +	}
          777  +
          778  +	CACKEY_DEBUG_PRINTF("Successfully selected file");
          779  +
          780  +	return(0);
          781  +}
          782  +
          783  +static int cackey_read_tlv(struct cackey_slot *slot, int follow_url) {
          784  +	struct cackey_tlv_entity curr_entity;
          785  +	unsigned char tlen_buf[2], tval_buf[1024], *tval;
          786  +	unsigned char vlen_buf[2], vval_buf[8192], *vval;
          787  +	ssize_t tlen, vlen;
          788  +	ssize_t read_ret;
          789  +	size_t offset_t = 0, offset_v = 0;
          790  +	int select_ret;
          791  +
          792  +	CACKEY_DEBUG_PRINTF("Called");
          793  +
          794  +	read_ret = cackey_read_buffer(slot, tlen_buf, sizeof(tlen_buf), 1, offset_t);
          795  +	if (read_ret != sizeof(tlen_buf)) {
          796  +		CACKEY_DEBUG_PRINTF("Read failed, returning in failure");
          797  +
          798  +		return(0);
          799  +	}
          800  +
          801  +	tlen = (tlen_buf[1] << 8) | tlen_buf[0];
          802  +
          803  +	read_ret = cackey_read_buffer(slot, vlen_buf, sizeof(vlen_buf), 2, offset_v);
          804  +	if (read_ret != sizeof(vlen_buf)) {
          805  +		CACKEY_DEBUG_PRINTF("Read failed, returning in failure");
          806  +
          807  +		return(0);
          808  +	}
          809  +
          810  +	vlen = (vlen_buf[1] << 8) | vlen_buf[0];
          811  +
          812  +	CACKEY_DEBUG_PRINTF("Tag Length = %i, Value Length = %i", tlen, vlen);
          813  +
          814  +	tlen -= 2;
          815  +	offset_t += 2;
          816  +
          817  +	vlen -= 2;
          818  +	offset_v += 2;
          819  +
          820  +	if (tlen > sizeof(tval_buf)) {
          821  +		CACKEY_DEBUG_PRINTF("Tag length is too large, returning in failure");
          822  +
          823  +		return(0);
          824  +	}
          825  +
          826  +	if (vlen > sizeof(vval_buf)) {
          827  +		CACKEY_DEBUG_PRINTF("Value length is too large, returning in failure");
          828  +
          829  +		return(0);
          830  +	}
          831  +
          832  +	read_ret = cackey_read_buffer(slot, tval_buf, tlen, 1, offset_t);
          833  +	if (read_ret != tlen) {
          834  +		CACKEY_DEBUG_PRINTF("Unable to read entire T-buffer, returning in failure");
          835  +
          836  +		return(0);
          837  +	}
          838  +
          839  +	read_ret = cackey_read_buffer(slot, vval_buf, vlen, 2, offset_v);
          840  +	if (read_ret != vlen) {
          841  +		CACKEY_DEBUG_PRINTF("Unable to read entire V-buffer, returning in failure");
          842  +
          843  +		return(0);
          844  +	}
          845  +
          846  +	tval = tval_buf;
          847  +	vval = vval_buf;
          848  +	while (tlen > 0 && vlen > 0) {
          849  +		curr_entity.tag = *tval;
          850  +		tval++;
          851  +		tlen--;
          852  +
          853  +		if (*tval == 0xff) {
          854  +			curr_entity.length = (tval[2] << 8) | tval[1];
          855  +			tval += 3;
          856  +			tlen -= 3;
          857  +		} else {
          858  +			curr_entity.length = *tval;
          859  +			tval++;
          860  +			tlen--;
          861  +		}
          862  +
          863  +		CACKEY_DEBUG_PRINTF("Tag: %s (%02x)", CACKEY_DEBUG_FUNC_TAG_TO_STR(curr_entity.tag), (unsigned int) curr_entity.tag);
          864  +		CACKEY_DEBUG_PRINTBUF("Value:", vval, curr_entity.length);
          865  +		vval += curr_entity.length;
          866  +		vlen -= curr_entity.length;
          867  +
          868  +		switch (curr_entity.tag) {
          869  +			case GSCIS_TAG_CARDURL:
          870  +				if (follow_url) {
          871  +					unsigned char aid[7];
          872  +					memcpy(aid, vval, 5);
          873  +					memcpy(aid + 5, vval + 8, 2);
          874  +
          875  +					select_ret = cackey_select_applet(slot, aid, 7);
          876  +					if (select_ret < 0) {
          877  +						CACKEY_DEBUG_PRINTF("Failed to select applet");
          878  +						break;
          879  +					}
          880  +
          881  +					cackey_read_tlv(slot, 0);
          882  +				}
          883  +				break;
          884  +		}
          885  +	}
          886  +
          887  +	return(0);
          888  +}
          889  +
          890  +static int cackey_select_file(struct cackey_slot *slot, uint16_t ef) {
          891  +	unsigned char fid_buf[2];
          892  +	int send_ret;
          893  +
          894  +	CACKEY_DEBUG_PRINTF("Called");
          895  +
          896  +	/* Open the elementary file */
          897  +	fid_buf[0] = (ef >> 8) & 0xff;
          898  +	fid_buf[1] = ef & 0xff;
          899  +
          900  +	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, 0x02, 0x0C, sizeof(fid_buf), fid_buf, 0x00, NULL, NULL, NULL);
          901  +	if (send_ret < 0) {
          902  +		CACKEY_DEBUG_PRINTF("Failed to open file, returning in failure");
          903  +
          904  +		return(-1);
          905  +	}
          906  +
          907  +	CACKEY_DEBUG_PRINTF("Successfully selected file");
          908  +
          909  +	return(0);
          910  +}
          911  +
          912  +/* Returns 1 if a token is in the specified slot, 0 otherwise */
          913  +static int cackey_token_present(struct cackey_slot *slot) {
          914  +	unsigned char ccc_aid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00};
          915  +	int send_ret;
          916  +
          917  +	/* Select the CCC Applet */
          918  +	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
          919  +	if (send_ret < 0) {
          920  +		return(0);
          921  +	}
          922  +
          923  +	cackey_read_tlv(slot, 1);
          924  +
          925  +	return(1);
   230    926   }
   231    927   
   232    928   /* Returns 0 on success */
   233    929   static int cackey_mutex_create(void **mutex) {
   234    930   	pthread_mutex_t *pthread_mutex;
   235    931   	int pthread_retval;
   236    932   	CK_RV custom_retval;
................................................................................
   699   1395   
   700   1396   		return(CKR_CRYPTOKI_ALREADY_INITIALIZED);
   701   1397   	}
   702   1398   
   703   1399   	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
   704   1400   		cackey_sessions[idx].active = 0;
   705   1401   	}
         1402  +
         1403  +	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
         1404  +		cackey_slots[idx].active = 0;
         1405  +		cackey_slots[idx].pcsc_reader = NULL;
         1406  +	}
   706   1407   
   707   1408   	cackey_initialized = 1;
   708   1409   
   709   1410   	if (!cackey_biglock_init) {
   710   1411   		mutex_init_ret = cackey_mutex_create(&cackey_biglock);
   711   1412   
   712   1413   		if (mutex_init_ret != 0) {
................................................................................
   741   1442   	}
   742   1443   
   743   1444   	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
   744   1445   		if (cackey_sessions[idx].active) {
   745   1446   			C_CloseSession(idx);
   746   1447   		}
   747   1448   	}
         1449  +
         1450  +	cackey_slots_disconnect_all();
         1451  +
         1452  +	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
         1453  +		if (cackey_slots[idx].pcsc_reader) {
         1454  +			free(cackey_slots[idx].pcsc_reader);
         1455  +		}
         1456  +	}
   748   1457   
   749   1458   	cackey_initialized = 0;
   750   1459   
   751   1460   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
   752   1461   
   753   1462   	return(CKR_OK);
   754   1463   }
................................................................................
   786   1495   	pInfo->libraryVersion.minor = (cackey_getversion() >> 8) & 0xff;
   787   1496   
   788   1497   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
   789   1498   
   790   1499   	return(CKR_OK);
   791   1500   }
   792   1501   
   793         -/* We only support 1 slot.  If the slot exists, the token exists. */
         1502  +/*
         1503  + * Process list of readers, and create mapping between reader name and slot ID
         1504  + */
   794   1505   CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) {
   795         -	CK_ULONG count, slot_present = 0, currslot;
         1506  +	int mutex_retval;
         1507  +	int pcsc_connect_ret;
         1508  +	CK_ULONG count, slot_count = 0, currslot;
         1509  +	char *pcsc_readers, *pcsc_readers_s, *pcsc_readers_e;
         1510  +	DWORD pcsc_readers_len;
         1511  +	LONG scard_listreaders_ret;
         1512  +	size_t curr_reader_len;
   796   1513   
   797   1514   	CACKEY_DEBUG_PRINTF("Called.");
   798   1515   
   799   1516   	if (pulCount == NULL) {
   800   1517   		CACKEY_DEBUG_PRINTF("Error. pulCount is NULL.");
   801   1518   
   802   1519   		return(CKR_ARGUMENTS_BAD);
................................................................................
   804   1521   
   805   1522   	if (!cackey_initialized) {
   806   1523   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
   807   1524   
   808   1525   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
   809   1526   	}
   810   1527   
   811         -	/* XXX: Determine if slot is present */
         1528  +	mutex_retval = cackey_mutex_lock(cackey_biglock);
         1529  +	if (mutex_retval != 0) {
         1530  +		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
         1531  +
         1532  +		return(CKR_GENERAL_ERROR);
         1533  +	}
         1534  +
         1535  +	/* Clear list of slots */
         1536  +	if (pSlotList) {
         1537  +		/* Only update the list of slots if we are actually being supply the slot information */
         1538  +		cackey_slots_disconnect_all();
         1539  +
         1540  +		for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
         1541  +			if (cackey_slots[currslot].pcsc_reader) {
         1542  +				free(cackey_slots[currslot].pcsc_reader);
         1543  +
         1544  +				cackey_slots[currslot].pcsc_reader = NULL;
         1545  +			}
         1546  +
         1547  +			cackey_slots[currslot].active = 0;
         1548  +		}
         1549  +	}
         1550  +
         1551  +	/* Determine list of readers */
         1552  +	pcsc_connect_ret = cackey_pcsc_connect();
         1553  +	if (pcsc_connect_ret < 0) {
         1554  +		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, assuming no slots");
         1555  +
         1556  +		slot_count = 0;
         1557  +	} else {
         1558  +		pcsc_readers_len = 0;
         1559  +
         1560  +		scard_listreaders_ret = SCardListReaders(*cackey_pcsc_handle, NULL, NULL, &pcsc_readers_len);
         1561  +		if (scard_listreaders_ret == SCARD_S_SUCCESS && pcsc_readers_len != 0) {
         1562  +			pcsc_readers = malloc(pcsc_readers_len);
         1563  +			pcsc_readers_s = pcsc_readers;
         1564  +
         1565  +			scard_listreaders_ret = SCardListReaders(*cackey_pcsc_handle, NULL, pcsc_readers, &pcsc_readers_len);
         1566  +			if (scard_listreaders_ret == SCARD_S_SUCCESS) {
         1567  +				pcsc_readers_e = pcsc_readers + pcsc_readers_len;
         1568  +
         1569  +				currslot = 0;
         1570  +				while (pcsc_readers < pcsc_readers_e) {
         1571  +					curr_reader_len = strlen(pcsc_readers);
         1572  +
         1573  +					if ((pcsc_readers + curr_reader_len) > pcsc_readers_e) {
         1574  +						break;
         1575  +					}
         1576  +
         1577  +					if (curr_reader_len == 0) {
         1578  +						break;
         1579  +					}
         1580  +
         1581  +					if (currslot >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
         1582  +						CACKEY_DEBUG_PRINTF("Found more readers than slots are available!");
         1583  +
         1584  +						break;
         1585  +					}
         1586  +
         1587  +					CACKEY_DEBUG_PRINTF("Found reader: %s", pcsc_readers);
         1588  +
         1589  +					/* Only update the list of slots if we are actually being supply the slot information */
         1590  +					if (pSlotList) {
         1591  +						cackey_slots[currslot].active = 1;
         1592  +						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
         1593  +						cackey_slots[currslot].pcsc_card_connected = 0;
         1594  +					}
         1595  +					currslot++;
         1596  +
         1597  +					pcsc_readers += curr_reader_len + 1;
         1598  +				}
         1599  +
         1600  +				if (currslot > 0) {
         1601  +					slot_count = currslot;
         1602  +				}
         1603  +			}
         1604  +
         1605  +			free(pcsc_readers_s);
         1606  +		}
         1607  +	}
         1608  +
         1609  +	mutex_retval = cackey_mutex_unlock(cackey_biglock);
         1610  +	if (mutex_retval != 0) {
         1611  +		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");
         1612  +
         1613  +		return(CKR_GENERAL_ERROR);
         1614  +	}
   812   1615   
   813   1616   	if (pSlotList == NULL) {
   814         -		*pulCount = slot_present;
         1617  +		*pulCount = slot_count;
   815   1618   
   816   1619   		CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
   817   1620   
   818   1621   		return(CKR_OK);
   819   1622   	}
   820   1623   
   821   1624   	count = *pulCount;
   822         -	if (count < slot_present) {
   823         -		CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we have %lu entries.", count, slot_present);
         1625  +	if (count < slot_count) {
         1626  +		CACKEY_DEBUG_PRINTF("Error. User allocated %lu entries, but we have %lu entries.", count, slot_count);
   824   1627   
   825   1628   		return(CKR_BUFFER_TOO_SMALL);	
   826   1629   	}
   827   1630   
   828         -	for (currslot = 0; currslot < slot_present; currslot++) {
         1631  +	for (currslot = 0; currslot < slot_count; currslot++) {
   829   1632   		pSlotList[currslot] = currslot;
   830   1633   	}
   831   1634   
   832         -	*pulCount = slot_present;
         1635  +	*pulCount = slot_count;
   833   1636   
   834   1637   	CACKEY_DEBUG_PRINTF("Returning CKR_OK (%i)", CKR_OK);
   835   1638   
   836   1639   	return(CKR_OK);
   837   1640   
   838   1641   	tokenPresent = tokenPresent; /* Supress unused variable warning */
   839   1642   }
   840   1643   
   841   1644   CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) {
   842         -	static CK_UTF8CHAR manufacturerID[] = "U.S. Government";
   843   1645   	static CK_UTF8CHAR slotDescription[] = "CACKey Slot";
         1646  +	int bytes_to_copy;
   844   1647   
   845   1648   	CACKEY_DEBUG_PRINTF("Called.");
   846   1649   
   847   1650   	if (pInfo == NULL) {
   848   1651   		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
   849   1652   
   850   1653   		return(CKR_ARGUMENTS_BAD);
   851   1654   	}
   852   1655   
   853         -	if (slotID != 0) {
   854         -		/* Again, we only support one slot -- slot 0 */
   855         -		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         1656  +	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
         1657  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
         1658  +
         1659  +		return(CKR_SLOT_ID_INVALID);
         1660  +	}
         1661  +
         1662  +	if (cackey_slots[slotID].active == 0) {
         1663  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
   856   1664   
   857   1665   		return(CKR_SLOT_ID_INVALID);
   858   1666   	}
   859   1667   
   860   1668   	if (!cackey_initialized) {
   861   1669   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
   862   1670   
................................................................................
   863   1671   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
   864   1672   	}
   865   1673   
   866   1674   	memset(pInfo->slotDescription, ' ', sizeof(pInfo->slotDescription));
   867   1675   	memcpy(pInfo->slotDescription, slotDescription, sizeof(slotDescription) - 1);
   868   1676   
   869   1677   	memset(pInfo->manufacturerID, ' ', sizeof(pInfo->manufacturerID));
   870         -	memcpy(pInfo->manufacturerID, manufacturerID, sizeof(manufacturerID) - 1);
   871   1678   
   872         -	pInfo->flags = CKF_TOKEN_PRESENT;
         1679  +	bytes_to_copy = strlen(cackey_slots[slotID].pcsc_reader);
         1680  +	if (sizeof(pInfo->manufacturerID) < bytes_to_copy) {
         1681  +		bytes_to_copy = sizeof(pInfo->manufacturerID);
         1682  +	}
         1683  +	memcpy(pInfo->manufacturerID, cackey_slots[slotID].pcsc_reader, bytes_to_copy);
         1684  +
         1685  +	pInfo->flags = 0;
         1686  +
         1687  +	if (cackey_token_present(&cackey_slots[slotID])) {
         1688  +		pInfo->flags |= CKF_TOKEN_PRESENT;
         1689  +	}
   873   1690   
   874   1691   	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
   875   1692   	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;
   876   1693   
   877   1694   	pInfo->firmwareVersion.major = 0x00;
   878   1695   	pInfo->firmwareVersion.minor = 0x00;
   879   1696   
................................................................................
   891   1708   
   892   1709   	if (pInfo == NULL) {
   893   1710   		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
   894   1711   
   895   1712   		return(CKR_ARGUMENTS_BAD);
   896   1713   	}
   897   1714   
   898         -	if (slotID != 0) {
   899         -		/* Again, we only support one slot -- slot 0 */
   900         -		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         1715  +	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
         1716  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
         1717  +
         1718  +		return(CKR_SLOT_ID_INVALID);
         1719  +	}
         1720  +
         1721  +	if (cackey_slots[slotID].active == 0) {
         1722  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
   901   1723   
   902   1724   		return(CKR_SLOT_ID_INVALID);
   903   1725   	}
   904   1726   
   905   1727   	if (!cackey_initialized) {
   906   1728   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
   907   1729   
   908   1730   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
   909   1731   	}
   910   1732   
   911         -	/* XXX: Verify connection is valid */
   912         -	if (0) {
   913         -		CACKEY_DEBUG_PRINTF("Error. Tried to connect to slot, but failed.");
   914         -
   915         -		return(CKR_SLOT_ID_INVALID);
   916         -	}
   917         -
   918         -	/* XXX: Get list of identities */
   919         -	if (0) {
   920         -		CACKEY_DEBUG_PRINTF("Error. No identities found in slot.");
         1733  +	if (!cackey_token_present(&cackey_slots[slotID])) {
         1734  +		CACKEY_DEBUG_PRINTF("No token is present in slotID = %lu", slotID);
   921   1735   
   922   1736   		return(CKR_TOKEN_NOT_PRESENT);
   923   1737   	}
   924   1738   
   925   1739   	memset(pInfo->label, ' ', sizeof(pInfo->label));
   926   1740   	if (1) {
   927   1741   		memcpy(pInfo->label, defaultLabel, sizeof(defaultLabel) - 1);
................................................................................
   940   1754   
   941   1755   	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
   942   1756   	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;
   943   1757   
   944   1758   	pInfo->firmwareVersion.major = 0x00;
   945   1759   	pInfo->firmwareVersion.minor = 0x00;
   946   1760   
   947         -	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_PROTECTED_AUTHENTICATION_PATH | CKF_TOKEN_INITIALIZED;
         1761  +	pInfo->flags = CKF_WRITE_PROTECTED | CKF_USER_PIN_INITIALIZED | CKF_TOKEN_INITIALIZED;
   948   1762   
   949   1763   	pInfo->ulMaxSessionCount = (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])) - 1;
   950   1764   	pInfo->ulSessionCount = CK_UNAVAILABLE_INFORMATION;
   951   1765   	pInfo->ulMaxRwSessionCount = 0;
   952   1766   	pInfo->ulRwSessionCount = CK_UNAVAILABLE_INFORMATION;
   953   1767   	pInfo->ulMaxPinLen = 128;
   954   1768   	pInfo->ulMinPinLen = 0;
................................................................................
  1019   1833   
  1020   1834   	return(CKR_OK);
  1021   1835   }
  1022   1836   
  1023   1837   CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) {
  1024   1838   	CACKEY_DEBUG_PRINTF("Called.");
  1025   1839   
  1026         -	if (slotID != 0) {
  1027         -		/* Again, we only support one slot -- slot 0 */
  1028         -		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         1840  +	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
         1841  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
         1842  +
         1843  +		return(CKR_SLOT_ID_INVALID);
         1844  +	}
         1845  +
         1846  +	if (cackey_slots[slotID].active == 0) {
         1847  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
  1029   1848   
  1030   1849   		return(CKR_SLOT_ID_INVALID);
  1031   1850   	}
  1032   1851   
  1033   1852   	if (pInfo == NULL) {
  1034   1853   		CACKEY_DEBUG_PRINTF("Error. pInfo is NULL.");
  1035   1854   
................................................................................
  1110   1929   
  1111   1930   	return(CKR_FUNCTION_NOT_SUPPORTED);
  1112   1931   }
  1113   1932   
  1114   1933   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) {
  1115   1934   	struct cackey_identity *identities;
  1116   1935   	unsigned long idx, num_ids, id_idx, curr_id_type;
         1936  +#if 0
  1117   1937   	CK_BYTE sigbuf[1024];
  1118   1938   	ssize_t sigbuflen;
         1939  +#endif
  1119   1940   	int mutex_retval;
  1120   1941   	int found_session = 0;
  1121   1942   
  1122   1943   	CACKEY_DEBUG_PRINTF("Called.");
  1123   1944   
  1124         -	if (slotID != 0) {
  1125         -		/* We only support one slot -- slot 0 */
  1126         -		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         1945  +	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
         1946  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
         1947  +
         1948  +		return(CKR_SLOT_ID_INVALID);
         1949  +	}
         1950  +
         1951  +	if (cackey_slots[slotID].active == 0) {
         1952  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
  1127   1953   
  1128   1954   		return(CKR_SLOT_ID_INVALID);
  1129   1955   	}
  1130   1956   
  1131   1957   	if ((flags & CKF_SERIAL_SESSION) != CKF_SERIAL_SESSION) {
  1132   1958   		return(CKR_SESSION_PARALLEL_NOT_SUPPORTED);
  1133   1959   	}
................................................................................
  1295   2121   
  1296   2122   CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(CK_SLOT_ID slotID) {
  1297   2123   	uint32_t idx;
  1298   2124   	int mutex_retval;
  1299   2125   
  1300   2126   	CACKEY_DEBUG_PRINTF("Called.");
  1301   2127   
  1302         -	if (slotID != 0) {
  1303         -		/* Again, we only support one slot -- slot 0 */
  1304         -		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), only one slot available: 0", slotID);
         2128  +	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
         2129  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
         2130  +
         2131  +		return(CKR_SLOT_ID_INVALID);
         2132  +	}
         2133  +
         2134  +	if (cackey_slots[slotID].active == 0) {
         2135  +		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), slot not currently active", slotID);
  1305   2136   
  1306   2137   		return(CKR_SLOT_ID_INVALID);
  1307   2138   	}
  1308   2139   
  1309   2140   	if (!cackey_initialized) {
  1310   2141   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  1311   2142