Diff

Differences From Artifact [5676179bd7]:

To Artifact [4c31fc86bf]:


   532    532   
   533    533   	char *pcsc_reader;
   534    534   
   535    535   	int pcsc_card_connected;
   536    536   	SCARDHANDLE pcsc_card;
   537    537   
   538    538   	int transaction_depth;
          539  +	int transaction_need_hw_lock;
   539    540   
   540    541   	int slot_reset;
   541    542   
   542    543   	CK_FLAGS token_flags;
   543    544   
   544    545   	unsigned char *label;
   545    546   
................................................................................
   676    677   			free(cackey_slots[idx].label);
   677    678   
   678    679   			cackey_slots[idx].label = NULL;
   679    680   		}
   680    681   
   681    682   		cackey_slots[idx].pcsc_card_connected = 0;
   682    683   		cackey_slots[idx].transaction_depth = 0;
          684  +		cackey_slots[idx].transaction_need_hw_lock = 0;
   683    685   
   684    686   		if (cackey_slots[idx].active) {
   685    687   			CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx);
   686    688   		}
   687    689   
   688    690   		cackey_slots[idx].slot_reset = 1;
   689    691   	}
................................................................................
   847    849   
   848    850   	/* Connect to reader, if needed */
   849    851   	if (!slot->pcsc_card_connected) {
   850    852   		slot->protocol = 0;
   851    853   
   852    854   		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader);
   853    855   		scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
          856  +
          857  +		if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
          858  +			CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
          859  +			scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol);
          860  +
          861  +			if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
          862  +				CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
          863  +				scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
          864  +			}
          865  +		}
   854    866   
   855    867   		if (scard_conn_ret == SCARD_W_UNPOWERED_CARD) {
          868  +			CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_W_UNPOWERED_CARD, trying to re-connect...");
          869  +
   856    870   			scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
          871  +
          872  +			if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
          873  +				CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
          874  +				scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol);
          875  +
          876  +				if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
          877  +					CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
          878  +					scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
          879  +				}
          880  +			}
          881  +
   857    882   			scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, protocol, SCARD_RESET_CARD, &protocol);
          883  +
          884  +			if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
          885  +				CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
          886  +				scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol);
          887  +
          888  +				if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
          889  +					CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
          890  +					scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &protocol);
          891  +				}
          892  +			}
          893  +
   858    894   		}
   859    895   
   860    896   		if (scard_conn_ret != SCARD_S_SUCCESS) {
   861    897   			CACKEY_DEBUG_PRINTF("Connection to card failed, returning in failure (SCardConnect() = %s/%li)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_conn_ret), (long) scard_conn_ret);
   862    898   
   863    899   			return(CACKEY_PCSC_E_GENERIC);
   864    900   		}
   865    901   
   866    902   		slot->pcsc_card_connected = 1;
   867    903   		slot->transaction_depth = 0;
          904  +		slot->transaction_need_hw_lock = 0;
   868    905   		slot->protocol = protocol;
   869    906   	}
   870    907   
   871    908   	return(CACKEY_PCSC_S_OK);
   872    909   }
   873    910   
   874    911   /*
................................................................................
   898    935   		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in error");
   899    936   
   900    937   		return(CACKEY_PCSC_E_GENERIC);
   901    938   	}
   902    939   
   903    940   	slot->transaction_depth++;
   904    941   
   905         -	if (slot->transaction_depth > 1) {
          942  +	if (slot->transaction_depth > 1 && !slot->transaction_need_hw_lock) {
   906    943   		CACKEY_DEBUG_PRINTF("Already in a transaction, performing no action (new depth = %i)", slot->transaction_depth);
   907    944   
   908    945   		return(CACKEY_PCSC_S_OK);
   909    946   	}
          947  +
          948  +	slot->transaction_need_hw_lock = 0;
   910    949   
   911    950   	scard_trans_ret = SCardBeginTransaction(slot->pcsc_card);
   912    951   	if (scard_trans_ret != SCARD_S_SUCCESS) {
   913    952   		CACKEY_DEBUG_PRINTF("Unable to begin transaction, returning in error");
   914    953   
   915    954   		return(CACKEY_PCSC_E_GENERIC);
   916    955   	}
................................................................................
   938    977    */
   939    978   static cackey_ret cackey_end_transaction(struct cackey_slot *slot) {
   940    979   	LONG scard_trans_ret;
   941    980   
   942    981   	CACKEY_DEBUG_PRINTF("Called.");
   943    982   
   944    983   	if (!slot->pcsc_card_connected) {
   945         -		CACKEY_DEBUG_PRINTF("Card is not connected, unable to end transaction");
          984  +		CACKEY_DEBUG_PRINTF("Card is not connected, unable to end transaction on card");
          985  +
          986  +		if (slot->transaction_depth > 0) {
          987  +			CACKEY_DEBUG_PRINTF("Decreasing transaction depth and asking for a hardware lock on the next begin transaction (current depth = %i)", slot->transaction_depth);
          988  +
          989  +			slot->transaction_depth--;
          990  +
          991  +			if (slot->transaction_depth > 0) {
          992  +				slot->transaction_need_hw_lock = 1;
          993  +			}
          994  +		}
   946    995   
   947    996   		return(CACKEY_PCSC_E_GENERIC);
   948    997   	}
   949    998   
   950    999   	if (slot->transaction_depth == 0) {
   951   1000   		CACKEY_DEBUG_PRINTF("Terminating a transaction that has not begun!");
   952   1001   
................................................................................
   954   1003   	}
   955   1004   
   956   1005   	slot->transaction_depth--;
   957   1006   
   958   1007   	if (slot->transaction_depth > 0) {
   959   1008   		CACKEY_DEBUG_PRINTF("Transactions still in progress, not terminating on-card Transaction (current depth = %i)", slot->transaction_depth);
   960   1009   
   961         -		return(CACKEY_PCSC_E_GENERIC);
         1010  +		return(CACKEY_PCSC_S_OK);
   962   1011   	}
   963   1012   
   964   1013   	scard_trans_ret = SCardEndTransaction(slot->pcsc_card, SCARD_LEAVE_CARD);
   965   1014   	if (scard_trans_ret != SCARD_S_SUCCESS) {
   966   1015   		CACKEY_DEBUG_PRINTF("Unable to end transaction, returning in error");
   967   1016   
   968   1017   		return(CACKEY_PCSC_E_GENERIC);
................................................................................
  1047   1096   	size_t bytes_to_copy, tmp_respdata_len;
  1048   1097   	LPCSCARD_IO_REQUEST pioSendPci;
  1049   1098   	DWORD protocol;
  1050   1099   	DWORD xmit_len, recv_len;
  1051   1100   	LONG scard_xmit_ret, scard_reconn_ret;
  1052   1101   	BYTE xmit_buf[1024], recv_buf[1024];
  1053   1102   	int pcsc_connect_ret, pcsc_getresp_ret;
  1054         -	int idx;
         1103  +	int idx, retry;
  1055   1104   
  1056   1105   	CACKEY_DEBUG_PRINTF("Called.");
  1057   1106   
  1058   1107   	if (!slot) {
  1059   1108   		CACKEY_DEBUG_PRINTF("Invalid slot specified.");
  1060   1109   
  1061   1110   		return(CACKEY_PCSC_E_GENERIC);
................................................................................
  1107   1156   	if (class == GSCIS_CLASS_ISO7816 && instruction == GSCIS_INSTR_VERIFY && p1 == 0x00 && p2 == 0x00) {
  1108   1157   		CACKEY_DEBUG_PRINTF("Sending APDU: <<censored>>");
  1109   1158   	} else {
  1110   1159   		CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);
  1111   1160   	}
  1112   1161   
  1113   1162   	recv_len = sizeof(recv_buf);
  1114         -	scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len);
         1163  +	for (retry = 0; retry < 10; retry++) {
         1164  +		CACKEY_DEBUG_PRINTF("Calling SCardTransmit()");
         1165  +		scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len);
         1166  +
         1167  +		if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) {
         1168  +			CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx), will retry...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret);
         1169  +		} else {
         1170  +			break;
         1171  +		}
         1172  +	}
         1173  +
  1115   1174   	if (scard_xmit_ret != SCARD_S_SUCCESS) {
  1116   1175   		CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret);
         1176  +
  1117   1177   		CACKEY_DEBUG_PRINTF("Marking slot as having been reset");
  1118         -
  1119         -		slot->transaction_depth = 0;
  1120   1178   		slot->slot_reset = 1;
  1121   1179   
  1122   1180   		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
  1123   1181   			CACKEY_DEBUG_PRINTF("Reset required, please hold...");
  1124   1182   
  1125   1183   			scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &protocol);
  1126   1184   			if (scard_reconn_ret == SCARD_S_SUCCESS) {
................................................................................
  1140   1198   
  1141   1199   						break;
  1142   1200   				}
  1143   1201   
  1144   1202   				/* Re-establish transaction, if it was present */
  1145   1203   				if (slot->transaction_depth > 0) {
  1146   1204   					slot->transaction_depth--;
         1205  +					slot->transaction_need_hw_lock = 1;
  1147   1206   					cackey_begin_transaction(slot);
  1148   1207   				}
  1149   1208   
  1150   1209   				CACKEY_DEBUG_PRINTF("Reset successful, retransmitting");
  1151   1210   
  1152   1211   				recv_len = sizeof(recv_buf);
  1153   1212   				scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len);
................................................................................
  2280   2339   			if (scard_reconn_ret == SCARD_S_SUCCESS) {
  2281   2340   				/* Update protocol */
  2282   2341   				slot->protocol = protocol;
  2283   2342   
  2284   2343   				/* Re-establish transaction, if it was present */
  2285   2344   				if (slot->transaction_depth > 0) {
  2286   2345   					slot->transaction_depth--;
         2346  +					slot->transaction_need_hw_lock = 1;
  2287   2347   					cackey_begin_transaction(slot);
  2288   2348   				}
  2289   2349   
  2290   2350   				CACKEY_DEBUG_PRINTF("Reset successful, requerying");
  2291   2351   				status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
  2292   2352   				if (status_ret != SCARD_S_SUCCESS) {
  2293   2353   					CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));
................................................................................
  3023   3083   		cackey_sessions[idx].active = 0;
  3024   3084   	}
  3025   3085   
  3026   3086   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
  3027   3087   		cackey_slots[idx].active = 0;
  3028   3088   		cackey_slots[idx].pcsc_reader = NULL;
  3029   3089   		cackey_slots[idx].transaction_depth = 0;
         3090  +		cackey_slots[idx].transaction_need_hw_lock = 0;
  3030   3091   		cackey_slots[idx].slot_reset = 0;
  3031   3092   		cackey_slots[idx].token_flags = 0;
  3032   3093   		cackey_slots[idx].label = NULL;
  3033   3094   	}
  3034   3095   
  3035   3096   	cackey_initialized = 1;
  3036   3097   
................................................................................
  3238   3299   
  3239   3300   					/* Only update the list of slots if we are actually being asked supply the slot information */
  3240   3301   					if (pSlotList) {
  3241   3302   						cackey_slots[currslot].active = 1;
  3242   3303   						cackey_slots[currslot].pcsc_reader = strdup(pcsc_readers);
  3243   3304   						cackey_slots[currslot].pcsc_card_connected = 0;
  3244   3305   						cackey_slots[currslot].transaction_depth = 0;
         3306  +						cackey_slots[currslot].transaction_need_hw_lock = 0;
  3245   3307   						cackey_slots[currslot].slot_reset = 1;
  3246   3308   						cackey_slots[currslot].token_flags = CKF_LOGIN_REQUIRED;
  3247   3309   						cackey_slots[currslot].label = NULL;
  3248   3310   					}
  3249   3311   					currslot++;
  3250   3312   
  3251   3313   					pcsc_readers += curr_reader_len + 1;