Check-in [06e07b8f0d]
Overview
Comment:Added routines for reading certificates

Updated OpenSession to use PC/SC certificates

Comment and debugging update

Updated to read in larger chunks to improve speed

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:06e07b8f0d3c1eeaa1618082d4f00bba6219717d
User & Date: rkeene on 2010-05-12 21:52:55
Other Links: manifest | tags
Context
2010-05-12
23:58
Moved certificate examination to occur during search initialization

Added support for logging in via PC/SC in C_Login() check-in: 0c536f15c1 user: rkeene tags: trunk

21:52
Added routines for reading certificates

Updated OpenSession to use PC/SC certificates

Comment and debugging update

Updated to read in larger chunks to improve speed check-in: 06e07b8f0d user: rkeene tags: trunk

19:35
Updated ignores

Updated read_tlv to return a list

Added a free_tlv function

Updated value->str conversion functions to be more flexible/direct

Added sample code to select all PKI applets/files

Simplified TLV entity check-in: 330efa4f3b user: rkeene tags: trunk

Changes

Modified cackey.c from [e9e3a11241] to [80414011fe].

    53     53   #  define CKA_TRUST_CODE_SIGNING 0xce53635a
    54     54   #endif
    55     55   #ifndef CKA_TRUST_EMAIL_PROTECTION
    56     56   #  define CKA_TRUST_EMAIL_PROTECTION 0xce53635b
    57     57   #endif
    58     58   
    59     59   /* GSC-IS v2.1 Definitions */
           60  +/** Classes **/
    60     61   #define GSCIS_CLASS_ISO7816           0x00
    61     62   #define GSCIS_CLASS_GLOBAL_PLATFORM   0x80
    62     63   
           64  +/** Instructions **/
    63     65   #define GSCIS_INSTR_GET_RESPONSE      0xC0
    64     66   #define GSCIS_INSTR_READ_BINARY       0xB0
    65     67   #define GSCIS_INSTR_UPDATE_BINARY     0xD6
    66     68   #define GSCIS_INSTR_SELECT            0xA4
    67     69   #define GSCIS_INSTR_EXTERNAL_AUTH     0x82
    68     70   #define GSCIS_INSTR_GET_CHALLENGE     0x84
    69     71   #define GSCIS_INSTR_INTERNAL_AUTH     0x88
................................................................................
    72     74   #define GSCIS_INSTR_GET_PROP          0x56
    73     75   #define GSCIS_INSTR_GET_ACR           0x4C
    74     76   #define GSCIS_INSTR_READ_BUFFER       0x52
    75     77   #define GSCIS_INSTR_SIGNDECRYPT       0x42
    76     78   
    77     79   #define GSCIS_PARAM_SELECT_APPLET     0x04
    78     80   
    79         -/* CCC */
           81  +/** Tags **/
           82  +/*** CCC Tags ***/
    80     83   #define GSCIS_TAG_CARDID              0xF0
    81     84   #define GSCIS_TAG_CCC_VER             0xF1
    82     85   #define GSCIS_TAG_CCG_VER             0xF2
    83     86   #define GSCIS_TAG_CARDURL             0xF3
    84     87   #define GSCIS_TAG_PKCS15              0xF4
    85     88   #define GSCIS_TAG_REG_DATA_MODEL      0xF5
    86     89   #define GSCIS_TAG_ACR_TABLE           0xF6
    87     90   #define GSCIS_TAG_CARD_APDU           0xF7
    88     91   #define GSCIS_TAG_REDIRECTION         0xFA
    89     92   #define GSCIS_TAG_CT                  0xFB
    90     93   #define GSCIS_TAG_ST                  0xFC
    91     94   #define GSCIS_TAG_NEXTCCC             0xFD
    92     95   
    93         -/* General - EF 2200 */
           96  +/*** General - EF 2200 ***/
    94     97   #define GSCIS_TAG_FNAME               0x01
    95     98   #define GSCIS_TAG_MNAME               0x02
    96     99   #define GSCIS_TAG_LNAME               0x03
    97    100   #define GSCIS_TAG_SUFFIX              0x04
    98    101   #define GSCIS_TAG_GOVT_AGENCY         0x05
    99    102   #define GSCIS_TAG_BUREAU              0x06
   100    103   #define GSCIS_TAG_BUREAU_CODE         0x07
................................................................................
   111    114   #define GSCIS_TAG_OFFICE_PHONE_EXT    0x18
   112    115   #define GSCIS_TAG_OFFICE_FAX          0x19
   113    116   #define GSCIS_TAG_OFFICE_EMAIL        0x1A
   114    117   #define GSCIS_TAG_OFFICE_ROOM         0x1B
   115    118   #define GSCIS_TAG_NONGOV_AGENCY       0x1C
   116    119   #define GSCIS_TAG_SSN_DESIGNATOR      0x1D
   117    120   
   118         -/* PII - EF 2100 */
          121  +/*** PII - EF 2100 ***/
   119    122   #define GSCIS_TAG_SSN                 0x20
   120    123   #define GSCIS_TAG_DOB                 0x21
   121    124   #define GSCIS_TAG_GENDER              0x22
   122    125   
   123         -/* Login Information - EF 4000 */
          126  +/*** Login Information - EF 4000 ***/
   124    127   #define GSCIS_TAG_USERID              0x40
   125    128   #define GSCIS_TAG_DOMAIN              0x41
   126    129   #define GSCIS_TAG_PASSWORD            0x42
   127    130   
   128         -/* Card Information - EF 5000 */
          131  +/*** Card Information - EF 5000 ***/
   129    132   #define GSCIS_TAG_ISSUERID            0x50
   130    133   #define GSCIS_TAG_SERNO               0x51
   131    134   #define GSCIS_TAG_ISSUE_DATE          0x52
   132    135   #define GSCIS_TAG_EXPIRE_DATE         0x53
   133    136   #define GSCIS_TAG_CARD_TYPE           0x54
   134    137   #define GSCIS_TAG_SECURITY_CODE       0x57
   135    138   #define GSCIS_TAG_CARDID_AID          0x58
   136    139   
   137         -/* PKI Information - EF 7000 */
          140  +/*** PKI Information - EF 7000 ***/
   138    141   #define GSCIS_TAG_CERTIFICATE         0x70
   139    142   #define GSCIS_TAG_CERT_ISSUE_DATE     0x71
   140    143   #define GSCIS_TAG_CERT_EXPIRE_DATE    0x72
   141    144   
          145  +/** Applet IDs **/
          146  +#define GSCIS_AID_CCC                 0xA0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00
          147  +
   142    148   #ifdef CACKEY_DEBUG
   143    149   #  ifdef HAVE_STDIO_H
   144    150   #    include <stdio.h>
   145    151   #  endif
   146    152   
   147    153   #  define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); }
   148    154   #  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"); }
................................................................................
   386    392   	}
   387    393   	
   388    394   	return("UNKNOWN");
   389    395   }
   390    396   
   391    397   static const char *CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(uint8_t apptype) {
   392    398   	switch (apptype) {
          399  +		case 0x00:
          400  +			return("NONE");
   393    401   		case 0x01:
   394    402   			return("CACKEY_TLV_APP_GENERIC");
   395    403   		case 0x02:
   396    404   			return("CACKEY_TLV_APP_SKI");
   397    405   		case 0x03:
   398    406   			return("CACKEY_TLV_APP_GENERIC | CACKEY_TLV_APP_SKI");
   399    407   		case 0x04:
................................................................................
   416    424   #  define CACKEY_DEBUG_PRINTBUF(f, x, y) /**/
   417    425   #  define CACKEY_DEBUG_PERROR(x) /**/
   418    426   #  define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED"
   419    427   #  define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED"
   420    428   #  define CACKEY_DEBUG_FUNC_OBJID_TO_STR(x) "DEBUG_DISABLED"
   421    429   #  define CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(x) "DEBUG_DISABLED"
   422    430   #endif
          431  +
          432  +struct cackey_pcsc_identity {
          433  +	unsigned char applet[7];
          434  +	uint16_t file;
          435  +
          436  +	unsigned char *label;
          437  +
          438  +	size_t certificate_len;
          439  +	unsigned char *certificate;
          440  +};
   423    441   
   424    442   struct cackey_identity {
          443  +	struct cackey_pcsc_identity *identity;
          444  +
   425    445   	CK_ATTRIBUTE *attributes;
   426    446   	CK_ULONG attributes_count;
   427    447   };
   428    448   
   429    449   struct cackey_session {
   430    450   	int active;
   431    451   
................................................................................
   813    833   
   814    834   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) {
   815    835   	size_t offset = 0, max_offset, max_count;
   816    836   	unsigned char cmd[2];
   817    837   	uint16_t respcode;
   818    838   	int send_ret;
   819    839   
   820         -	CACKEY_DEBUG_PRINTF("Called");
          840  +	CACKEY_DEBUG_PRINTF("Called.");
   821    841   
   822    842   	max_offset = count;
   823         -	max_count = 64;
          843  +	max_count = 252;
   824    844   
   825    845   	cmd[0] = t_or_v;
   826    846   
   827    847   	while (1) {
   828    848   		if (offset >= max_offset) {
   829    849   			CACKEY_DEBUG_PRINTF("Buffer too small, returning what we got...");
   830    850   
................................................................................
   868    888   
   869    889   	return(offset);
   870    890   }
   871    891   
   872    892   static int cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) {
   873    893   	int send_ret;
   874    894   
   875         -	CACKEY_DEBUG_PRINTF("Called");
          895  +	CACKEY_DEBUG_PRINTF("Called.");
   876    896   
   877    897   	CACKEY_DEBUG_PRINTBUF("Selecting applet:", aid, aid_len);
   878    898   
   879    899   	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, GSCIS_PARAM_SELECT_APPLET, 0x0C, aid_len, aid, 0x00, NULL, NULL, NULL);
   880    900   	if (send_ret < 0) {
   881    901   		CACKEY_DEBUG_PRINTF("Failed to open applet, returning in failure");
   882    902   
................................................................................
   888    908   	return(0);
   889    909   }
   890    910   
   891    911   static int cackey_select_file(struct cackey_slot *slot, uint16_t ef) {
   892    912   	unsigned char fid_buf[2];
   893    913   	int send_ret;
   894    914   
   895         -	CACKEY_DEBUG_PRINTF("Called");
          915  +	CACKEY_DEBUG_PRINTF("Called.");
   896    916   
   897    917   	/* Open the elementary file */
   898    918   	fid_buf[0] = (ef >> 8) & 0xff;
   899    919   	fid_buf[1] = ef & 0xff;
          920  +
          921  +	CACKEY_DEBUG_PRINTF("Selecting file: %04lx", (unsigned long) ef);
   900    922   
   901    923   	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, 0x02, 0x0C, sizeof(fid_buf), fid_buf, 0x00, NULL, NULL, NULL);
   902    924   	if (send_ret < 0) {
   903    925   		CACKEY_DEBUG_PRINTF("Failed to open file, returning in failure");
   904    926   
   905    927   		return(-1);
   906    928   	}
................................................................................
   908    930   	CACKEY_DEBUG_PRINTF("Successfully selected file");
   909    931   
   910    932   	return(0);
   911    933   }
   912    934   
   913    935   static void cackey_free_tlv(struct cackey_tlv_entity *root) {
   914    936   	struct cackey_tlv_entity *curr, *next;
          937  +
          938  +	if (root == NULL) {
          939  +		return;
          940  +	}
   915    941   
   916    942   	for (curr = root; curr; curr = next) {
   917    943   		next = curr->_next;
   918    944   
   919    945   		switch (curr->tag) {
   920    946   			case GSCIS_TAG_ACR_TABLE:
          947  +			case GSCIS_TAG_CERTIFICATE:
   921    948   				if (curr->value) {
   922    949   					free(curr->value);
   923    950   				}
   924    951   				break;
   925    952   			case GSCIS_TAG_CARDURL:
   926    953   				if (curr->value_cardurl) {
   927    954   					free(curr->value_cardurl);
................................................................................
   942    969   	unsigned char *tmpbuf;
   943    970   	ssize_t tlen, vlen;
   944    971   	ssize_t read_ret;
   945    972   	size_t offset_t = 0, offset_v = 0;
   946    973   	unsigned char tag;
   947    974   	size_t length;
   948    975   
   949         -	CACKEY_DEBUG_PRINTF("Called");
          976  +	CACKEY_DEBUG_PRINTF("Called.");
   950    977   
   951    978   	read_ret = cackey_read_buffer(slot, tlen_buf, sizeof(tlen_buf), 1, offset_t);
   952    979   	if (read_ret != sizeof(tlen_buf)) {
   953    980   		CACKEY_DEBUG_PRINTF("Read failed, returning in failure");
   954    981   
   955    982   		return(NULL);
   956    983   	}
................................................................................
  1044   1071   				memcpy(tmpbuf, vval, length);
  1045   1072   
  1046   1073   				curr_entity->tag = tag;
  1047   1074   				curr_entity->length = length;
  1048   1075   				curr_entity->value = tmpbuf;
  1049   1076   				curr_entity->_next = NULL;
  1050   1077   
         1078  +				break;
         1079  +			case GSCIS_TAG_CERTIFICATE:
         1080  +				curr_entity = malloc(sizeof(*curr_entity));
         1081  +				tmpbuf = malloc(length);
         1082  +
         1083  +				memcpy(tmpbuf, vval, length);
         1084  +
         1085  +				curr_entity->tag = tag;
         1086  +				curr_entity->length = length;
         1087  +				curr_entity->value = tmpbuf;
         1088  +				curr_entity->_next = NULL;
         1089  +
  1051   1090   				break;
  1052   1091   			case GSCIS_TAG_PKCS15:
  1053   1092   				curr_entity = malloc(sizeof(*curr_entity));
  1054   1093   
  1055   1094   				curr_entity->tag = tag;
  1056   1095   				curr_entity->value_byte = vval[0];
  1057   1096   				curr_entity->_next = NULL;
................................................................................
  1070   1109   
  1071   1110   			last = curr_entity;
  1072   1111   		}
  1073   1112   	}
  1074   1113   
  1075   1114   	return(root);
  1076   1115   }
         1116  +
         1117  +static void cackey_free_certs(struct cackey_pcsc_identity *start, size_t count, int free_start) {
         1118  +	size_t idx;
         1119  +
         1120  +	for (idx = 0; idx < count; idx++) {
         1121  +		if (start[idx].certificate) {
         1122  +			free(start[idx].certificate);
         1123  +		}
         1124  +	}
         1125  +
         1126  +	if (free_start) {
         1127  +		free(start);
         1128  +	}
         1129  +
         1130  +	return;
         1131  +}
         1132  +
         1133  +static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
         1134  +	struct cackey_pcsc_identity *curr_id;
         1135  +	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
         1136  +	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
         1137  +	unsigned char curr_aid[7];
         1138  +	unsigned long outidx = 0;
         1139  +	int certs_resizable;
         1140  +	int send_ret, select_ret;
         1141  +
         1142  +	CACKEY_DEBUG_PRINTF("Called.");
         1143  +
         1144  +	if (count == NULL) {
         1145  +		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");
         1146  +
         1147  +		return(NULL);
         1148  +	}
         1149  +
         1150  +	if (*count == 0) {
         1151  +		if (certs != NULL) {
         1152  +			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");
         1153  +
         1154  +			return(certs);
         1155  +		}
         1156  +	}
         1157  +
         1158  +	if (certs == NULL) {
         1159  +		certs = malloc(sizeof(*certs) * 5);
         1160  +		*count = 5;
         1161  +		certs_resizable = 1;
         1162  +	} else {
         1163  +		certs_resizable = 0;
         1164  +	}
         1165  +
         1166  +	/* Select the CCC Applet */
         1167  +	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
         1168  +	if (send_ret < 0) {
         1169  +		CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");
         1170  +
         1171  +		return(NULL);
         1172  +	}
         1173  +
         1174  +	/* Read all the applets from the CCC's TLV */
         1175  +	ccc_tlv = cackey_read_tlv(slot);
         1176  +
         1177  +	/* Look for CARDURLs that coorespond to PKI applets */
         1178  +	for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) {
         1179  +		CACKEY_DEBUG_PRINTF("Found tag: %s ... ", CACKEY_DEBUG_FUNC_TAG_TO_STR(ccc_curr->tag));
         1180  +
         1181  +		if (ccc_curr->tag != GSCIS_TAG_CARDURL) {
         1182  +			CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about CARDURLs)");
         1183  +
         1184  +			continue;
         1185  +		}
         1186  +
         1187  +		if ((ccc_curr->value_cardurl->apptype & CACKEY_TLV_APP_PKI) != CACKEY_TLV_APP_PKI) {
         1188  +			CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about PKI applets, this applet supports: %s/%02x)", CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(ccc_curr->value_cardurl->apptype), (unsigned int) ccc_curr->value_cardurl->apptype);
         1189  +
         1190  +			continue;
         1191  +		}
         1192  +
         1193  +		CACKEY_DEBUG_PRINTBUF("RID:", ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
         1194  +		CACKEY_DEBUG_PRINTF("AppID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(ccc_curr->value_cardurl->appid), (unsigned long) ccc_curr->value_cardurl->appid);
         1195  +		CACKEY_DEBUG_PRINTF("ObjectID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(ccc_curr->value_cardurl->objectid), (unsigned long) ccc_curr->value_cardurl->objectid);
         1196  +
         1197  +		memcpy(curr_aid, ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
         1198  +		curr_aid[sizeof(curr_aid) - 2] = (ccc_curr->value_cardurl->appid >> 8) & 0xff;
         1199  +		curr_aid[sizeof(curr_aid) - 1] = ccc_curr->value_cardurl->appid & 0xff;
         1200  +
         1201  +		/* Select found applet ... */
         1202  +		select_ret = cackey_select_applet(slot, curr_aid, sizeof(curr_aid));
         1203  +		if (select_ret < 0) {
         1204  +			CACKEY_DEBUG_PRINTF("Failed to select applet, skipping processing of this object");
         1205  +
         1206  +			continue;
         1207  +		}
         1208  +
         1209  +		/* ... and object (file) */
         1210  +		select_ret = cackey_select_file(slot, ccc_curr->value_cardurl->objectid);
         1211  +		if (select_ret < 0) {
         1212  +			CACKEY_DEBUG_PRINTF("Failed to select file, skipping processing of this object");
         1213  +
         1214  +			continue;
         1215  +		}
         1216  +
         1217  +		/* Process this file's TLV looking for certificates */
         1218  +		app_tlv = cackey_read_tlv(slot);
         1219  +
         1220  +		for (app_curr = app_tlv; app_curr; app_curr = app_curr->_next) {
         1221  +			CACKEY_DEBUG_PRINTF("Found tag: %s", CACKEY_DEBUG_FUNC_TAG_TO_STR(app_curr->tag));
         1222  +			if (app_curr->tag != GSCIS_TAG_CERTIFICATE) {
         1223  +				CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about CERTIFICATEs)");
         1224  +
         1225  +				continue;
         1226  +			}
         1227  +
         1228  +			curr_id = &certs[outidx];
         1229  +			outidx++;
         1230  +
         1231  +			memcpy(curr_id->applet, curr_aid, sizeof(curr_id->applet));
         1232  +			curr_id->file = ccc_curr->value_cardurl->objectid;
         1233  +			curr_id->label = NULL;
         1234  +
         1235  +			curr_id->certificate_len = app_curr->length;
         1236  +
         1237  +			curr_id->certificate = malloc(curr_id->certificate_len);
         1238  +			memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len);
         1239  +
         1240  +			if (outidx >= *count) {
         1241  +				if (certs_resizable) {
         1242  +					*count *= 2;
         1243  +					certs = realloc(certs, sizeof(*certs) * (*count));
         1244  +				} else {
         1245  +					break;
         1246  +				}
         1247  +			}
         1248  +		}
         1249  +
         1250  +		cackey_free_tlv(app_tlv);
         1251  +
         1252  +		if (outidx >= *count) {
         1253  +			break;
         1254  +		}
         1255  +	}
         1256  +
         1257  +	cackey_free_tlv(ccc_tlv);
         1258  +
         1259  +	*count = outidx;
         1260  +
         1261  +	if (certs_resizable) {
         1262  +		certs = realloc(certs, sizeof(*certs) * (*count));
         1263  +	}
         1264  +
         1265  +	return(certs);
         1266  +}
  1077   1267   
  1078   1268   /* Returns 1 if a token is in the specified slot, 0 otherwise */
  1079   1269   static int cackey_token_present(struct cackey_slot *slot) {
  1080         -	struct cackey_tlv_entity *tlvs, *curr;
  1081         -	unsigned char ccc_aid[] = {0xa0, 0x00, 0x00, 0x01, 0x16, 0xdb, 0x00};
  1082         -	unsigned char curr_aid[7];
         1270  +	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
  1083   1271   	int send_ret;
  1084   1272   
  1085   1273   	/* Select the CCC Applet */
  1086   1274   	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
  1087   1275   	if (send_ret < 0) {
  1088   1276   		return(0);
  1089   1277   	}
  1090   1278   
  1091         -	tlvs = cackey_read_tlv(slot);
  1092         -
  1093         -	for (curr = tlvs; curr; curr = curr->_next) {
  1094         -		CACKEY_DEBUG_PRINTF("Found tag: %s", CACKEY_DEBUG_FUNC_TAG_TO_STR(curr->tag));
  1095         -		switch (curr->tag) {
  1096         -			case GSCIS_TAG_CARDURL:
  1097         -				if ((curr->value_cardurl->apptype & CACKEY_TLV_APP_PKI) == CACKEY_TLV_APP_PKI) {
  1098         -					CACKEY_DEBUG_PRINTBUF("RID:", curr->value_cardurl->rid, sizeof(curr->value_cardurl->rid));
  1099         -					CACKEY_DEBUG_PRINTF("AppID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(curr->value_cardurl->appid), (unsigned long) curr->value_cardurl->appid);
  1100         -					CACKEY_DEBUG_PRINTF("ObjectID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(curr->value_cardurl->objectid), (unsigned long) curr->value_cardurl->objectid);
  1101         -
  1102         -					memcpy(curr_aid, curr->value_cardurl->rid, sizeof(curr->value_cardurl->rid));
  1103         -					curr_aid[sizeof(curr_aid) - 2] = (curr->value_cardurl->appid >> 8) & 0xff;
  1104         -					curr_aid[sizeof(curr_aid) - 1] = curr->value_cardurl->appid & 0xff;
  1105         -
  1106         -					cackey_select_applet(slot, curr_aid, sizeof(curr_aid));
  1107         -					cackey_select_file(slot, curr->value_cardurl->objectid);
  1108         -				}
  1109         -				break;
  1110         -		}
  1111         -	}
  1112         -
  1113         -	cackey_free_tlv(tlvs);
  1114         -
  1115   1279   	return(1);
  1116   1280   }
  1117   1281   
  1118   1282   /* Returns 0 on success */
  1119   1283   static int cackey_mutex_create(void **mutex) {
  1120   1284   	pthread_mutex_t *pthread_mutex;
  1121   1285   	int pthread_retval;
................................................................................
  1220   1384   	}
  1221   1385   
  1222   1386   	CACKEY_DEBUG_PRINTF("Returning sucessfully (0)");
  1223   1387   
  1224   1388   	return(0);
  1225   1389   }
  1226   1390   
  1227         -static CK_ATTRIBUTE_PTR cackey_get_attributes(CK_OBJECT_CLASS objectclass, void *identity, unsigned long identity_num, CK_ULONG_PTR pulCount) {
         1391  +static CK_ATTRIBUTE_PTR cackey_get_attributes(CK_OBJECT_CLASS objectclass, struct cackey_pcsc_identity *identity, unsigned long identity_num, CK_ULONG_PTR pulCount) {
  1228   1392   	static CK_BBOOL ck_true = 1;
  1229   1393   	static CK_BBOOL ck_false = 0;
  1230   1394   	CK_ULONG numattrs = 0, retval_count;
  1231   1395   	CK_ATTRIBUTE_TYPE curr_attr_type;
  1232   1396   	CK_ATTRIBUTE curr_attr, *retval;
  1233   1397   	CK_VOID_PTR pValue;
  1234   1398   	CK_ULONG ulValueLen;
................................................................................
  2121   2285   
  2122   2286   	CACKEY_DEBUG_PRINTF("Returning CKR_FUNCTION_NOT_SUPPORTED (%i)", CKR_FUNCTION_NOT_SUPPORTED);
  2123   2287   
  2124   2288   	return(CKR_FUNCTION_NOT_SUPPORTED);
  2125   2289   }
  2126   2290   
  2127   2291   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) {
         2292  +	struct cackey_pcsc_identity *pcsc_identities;
  2128   2293   	struct cackey_identity *identities;
  2129   2294   	unsigned long idx, num_ids, id_idx, curr_id_type;
  2130         -#if 0
  2131         -	CK_BYTE sigbuf[1024];
  2132         -	ssize_t sigbuflen;
  2133         -#endif
         2295  +	unsigned long num_certs, cert_idx;
  2134   2296   	int mutex_retval;
  2135   2297   	int found_session = 0;
  2136   2298   
  2137   2299   	CACKEY_DEBUG_PRINTF("Called.");
  2138   2300   
  2139   2301   	if (slotID < 0 || slotID >= (sizeof(cackey_slots) / sizeof(cackey_slots[0]))) {
  2140   2302   		CACKEY_DEBUG_PRINTF("Error. Invalid slot requested (%lu), outside of valid range", slotID);
................................................................................
  2155   2317   	if (!cackey_initialized) {
  2156   2318   		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");
  2157   2319   
  2158   2320   		return(CKR_CRYPTOKI_NOT_INITIALIZED);
  2159   2321   	}
  2160   2322   
  2161   2323   	/* Verify that the card is actually in the slot. */
  2162         -	/* XXX: Talk to card */
  2163         -	if (0) {
  2164         -		if (0) {
         2324  +	if (!cackey_token_present(&cackey_slots[slotID])) {
  2165   2325   			CACKEY_DEBUG_PRINTF("Error.  Card not present.  Returning CKR_DEVICE_REMOVED");
  2166   2326   
  2167   2327   			return(CKR_DEVICE_REMOVED);
  2168   2328   		}
  2169         -	}
  2170   2329   
  2171   2330   	mutex_retval = cackey_mutex_lock(cackey_biglock);
  2172   2331   	if (mutex_retval != 0) {
  2173   2332   		CACKEY_DEBUG_PRINTF("Error.  Locking failed.");
  2174   2333   
  2175   2334   		return(CKR_GENERAL_ERROR);
  2176   2335   	}
................................................................................
  2188   2347   			cackey_sessions[idx].ulDeviceError = 0;
  2189   2348   			cackey_sessions[idx].pApplication = pApplication;
  2190   2349   			cackey_sessions[idx].Notify = notify;
  2191   2350   
  2192   2351   			cackey_sessions[idx].identities = NULL;
  2193   2352   			cackey_sessions[idx].identities_count = 0;
  2194   2353   
  2195         -			if (0) {
  2196         -				num_ids = 0;
  2197         -				/* XXX: Determine number of IDs */
  2198         -
         2354  +			pcsc_identities = cackey_read_certs(&cackey_slots[slotID], NULL, &num_certs);
         2355  +			if (pcsc_identities != NULL) {
  2199   2356   				/* Convert number of IDs to number of objects */
  2200         -				num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_ids;
         2357  +				num_ids = (CKO_PRIVATE_KEY - CKO_CERTIFICATE + 1) * num_certs;
  2201   2358   
  2202   2359   				identities = malloc(num_ids * sizeof(*identities));
  2203   2360   
  2204   2361   				id_idx = 0;
  2205         -				for (;;) {
         2362  +				for (cert_idx = 0; cert_idx < num_certs; cert_idx++) {
  2206   2363   					for (curr_id_type = CKO_CERTIFICATE; curr_id_type <= CKO_PRIVATE_KEY; curr_id_type++) {
  2207         -						/* XXX: Determine base index */
  2208         -
  2209         -						identities[id_idx].attributes = cackey_get_attributes(curr_id_type, NULL, -1, &identities[id_idx].attributes_count);
         2364  +						identities[id_idx].attributes = cackey_get_attributes(curr_id_type, &pcsc_identities[cert_idx], -1, &identities[id_idx].attributes_count);
  2210   2365   
  2211   2366   						if (identities[id_idx].attributes == NULL) {
  2212   2367   							identities[id_idx].attributes_count = 0;
  2213   2368   						}
  2214   2369   
  2215   2370   						id_idx++;
  2216   2371   					}
  2217   2372   				}
  2218   2373   
  2219   2374   				cackey_sessions[idx].identities = identities;
  2220   2375   				cackey_sessions[idx].identities_count = num_ids;
         2376  +
         2377  +				cackey_free_certs(pcsc_identities, num_certs, 1);
  2221   2378   			}
  2222   2379   
  2223   2380   			cackey_sessions[idx].search_active = 0;
  2224   2381   
  2225   2382   			cackey_sessions[idx].sign_active = 0;
  2226   2383   
  2227   2384   			cackey_sessions[idx].decrypt_active = 0;