Differences From
Artifact [8c591e3548]:
1126 1126 CACKEY_DEBUG_PRINTF("Returning.");
1127 1127
1128 1128 return;
1129 1129 }
1130 1130
1131 1131 /*
1132 1132 * SYNPOSIS
1133 - * LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol, LPDWORD selected_protocol);
1133 + * LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol);
1134 1134 *
1135 1135 * ARGUMENTS
1136 1136 * cackey_slot *slot
1137 1137 * Slot to send commands to
1138 1138 *
1139 1139 * DWORD default_protocol
1140 1140 * Protocol to attempt first
1141 1141 *
1142 - * LPDWORD selected_protocol
1143 - * [OUT] Protocol selected
1144 - *
1145 1142 * RETURN VALUE
1146 1143 * The return value from SCardReconnect()
1147 1144 *
1148 1145 * NOTES
1149 1146 * This function is a wrapper around SCardReconnect()
1150 1147 *
1151 1148 * The SCardReconnect() function call will be called first with the
1152 1149 * dwPreferredProtocols of "default_protocol". If that call returns
1153 1150 * SCARD_E_PROTO_MISMATCH try again with a protocol of T=0, and failing
1154 1151 * that T=1.
1155 1152 *
1156 1153 */
1157 -static LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol, LPDWORD selected_protocol) {
1154 +static LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol) {
1155 + DWORD selected_protocol;
1158 1156 LONG scard_conn_ret;
1159 1157
1160 - scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, default_protocol, SCARD_RESET_CARD, selected_protocol);
1158 + selected_protocol = 0;
1159 +
1160 + scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, default_protocol, SCARD_RESET_CARD, &selected_protocol);
1161 1161
1162 1162 if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
1163 1163 CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
1164 - scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, selected_protocol);
1164 + scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &selected_protocol);
1165 1165
1166 1166 if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
1167 1167 CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
1168 - scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, selected_protocol);
1168 + scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &selected_protocol);
1169 1169 }
1170 1170 }
1171 +
1172 + if (scard_conn_ret == SCARD_S_SUCCESS) {
1173 + slot->protocol = selected_protocol;
1174 + }
1171 1175
1172 1176 return(scard_conn_ret);
1173 1177 }
1174 1178
1175 1179 /*
1176 1180 * SYNPOSIS
1177 1181 * cackey_ret cackey_connect_card(struct cackey_slot *slot);
................................................................................
1234 1238
1235 1239 if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
1236 1240 CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
1237 1241 scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
1238 1242 }
1239 1243 }
1240 1244
1241 - scard_conn_ret = cackey_reconnect_card(slot, protocol, &protocol);
1245 + scard_conn_ret = cackey_reconnect_card(slot, protocol);
1242 1246 }
1243 1247
1244 1248 if (scard_conn_ret != SCARD_S_SUCCESS) {
1245 1249 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);
1246 1250
1247 1251 return(CACKEY_PCSC_E_GENERIC);
1248 1252 }
................................................................................
1441 1445 * goes away.
1442 1446 *
1443 1447 */
1444 1448 static cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned int lc, unsigned char *data, unsigned int le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) {
1445 1449 uint8_t major_rc, minor_rc;
1446 1450 size_t bytes_to_copy, tmp_respdata_len;
1447 1451 LPCSCARD_IO_REQUEST pioSendPci;
1448 - DWORD protocol;
1449 1452 DWORD xmit_len, recv_len;
1450 1453 LONG scard_xmit_ret, scard_reconn_ret;
1451 1454 BYTE xmit_buf[1024], recv_buf[1024];
1452 1455 int pcsc_connect_ret, pcsc_getresp_ret;
1453 1456 int idx;
1454 1457
1455 1458 CACKEY_DEBUG_PRINTF("Called.");
................................................................................
1536 1539
1537 1540 if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) {
1538 1541 CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = %s/%lx), will ask calling function to retry (not resetting card)...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (unsigned long) scard_xmit_ret);
1539 1542
1540 1543 /* Begin Smartcard Transaction */
1541 1544 cackey_end_transaction(slot);
1542 1545
1546 + cackey_reconnect_card(slot, slot->protocol);
1547 +
1543 1548 return(CACKEY_PCSC_E_RETRY);
1544 1549 }
1545 1550
1546 1551 if (scard_xmit_ret != SCARD_S_SUCCESS) {
1547 1552 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);
1548 1553
1549 1554 CACKEY_DEBUG_PRINTF("Marking slot as having been reset");
1550 1555 cackey_mark_slot_reset(slot);
1551 1556
1552 1557 if (scard_xmit_ret == SCARD_W_RESET_CARD) {
1553 1558 CACKEY_DEBUG_PRINTF("Reset required, please hold...");
1554 1559
1555 - scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &protocol);
1560 + scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1);
1556 1561
1557 1562 if (scard_reconn_ret == SCARD_S_SUCCESS) {
1558 - /* Update protocol */
1559 - slot->protocol = protocol;
1560 1563 switch (slot->protocol) {
1561 1564 case SCARD_PROTOCOL_T0:
1562 1565 pioSendPci = SCARD_PCI_T0;
1563 1566
1564 1567 break;
1565 1568 case SCARD_PROTOCOL_T1:
1566 1569 pioSendPci = SCARD_PCI_T1;
................................................................................
2857 2860 send_ret = cackey_send_apdu(slot, class, NISTSP800_73_3_INSTR_GENAUTH, NISTSP800_78_3_ALGO_RSA2048, identity->pcsc_identity->card.piv.key_id, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
2858 2861 break;
2859 2862 case CACKEY_ID_TYPE_CERT_ONLY:
2860 2863 break;
2861 2864 }
2862 2865
2863 2866 if (send_ret != CACKEY_PCSC_S_OK) {
2864 - CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");
2865 -
2866 2867 if (free_tmpbuf) {
2867 2868 if (tmpbuf_s) {
2868 2869 free(tmpbuf_s);
2869 2870 }
2870 2871 }
2871 2872
2872 2873 /* End transaction */
2873 2874 cackey_end_transaction(slot);
2874 2875
2876 + if (send_ret == CACKEY_PCSC_E_RETRY) {
2877 + CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- retrying.");
2878 +
2879 + return(cackey_signdecrypt(slot, identity, buf, buflen, outbuf, outbuflen, padInput, unpadOutput));
2880 + }
2881 +
2882 + CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");
2883 +
2875 2884 if (respcode == 0x6982 || respcode == 0x6e00) {
2876 2885 if (respcode == 0x6E00) {
2877 2886 CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting");
2878 2887 } else {
2879 2888 CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x). Returning NEEDLOGIN", (int) respcode);
2880 2889 }
2881 2890
................................................................................
3180 3189
3181 3190 if (status_ret != SCARD_S_SUCCESS) {
3182 3191 cackey_mark_slot_reset(slot);
3183 3192
3184 3193 if (status_ret == SCARD_W_RESET_CARD) {
3185 3194 CACKEY_DEBUG_PRINTF("Reset required, please hold...");
3186 3195
3187 - scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &protocol);
3196 + scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1);
3188 3197 if (scard_reconn_ret == SCARD_S_SUCCESS) {
3189 - /* Update protocol */
3190 - slot->protocol = protocol;
3191 -
3192 3198 /* Re-establish transaction, if it was present */
3193 3199 if (slot->transaction_depth > 0) {
3194 3200 slot->transaction_depth--;
3195 3201 slot->transaction_need_hw_lock = 1;
3196 3202 cackey_begin_transaction(slot);
3197 3203 }
3198 3204
................................................................................
6369 6375 if (buflen < 0) {
6370 6376 /* Decryption failed. */
6371 6377 if (buflen == CACKEY_PCSC_E_NEEDLOGIN) {
6372 6378 retval = CKR_USER_NOT_LOGGED_IN;
6373 6379 } else if (buflen == CACKEY_PCSC_E_TOKENABSENT) {
6374 6380 retval = CKR_DEVICE_REMOVED;
6375 6381 } else {
6382 + CACKEY_DEBUG_PRINTF("Failed to send APDU, error = %li", (long int) buflen);
6383 +
6376 6384 retval = CKR_GENERAL_ERROR;
6377 6385 }
6378 6386 } else if (((unsigned long) buflen) > *pulPartLen && pPart) {
6379 6387 /* Decrypted data too large */
6380 6388 retval = CKR_BUFFER_TOO_SMALL;
6381 6389 } else {
6382 6390 if (pPart) {