Diff

Differences From Artifact [8c591e3548]:

To Artifact [318588635a]:


1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157

1158
1159


1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170




1171
1172
1173
1174
1175
1176
1177
....
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
....
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
....
1536
1537
1538
1539
1540
1541
1542


1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
....
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874








2875
2876
2877
2878
2879
2880
2881
....
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
....
6369
6370
6371
6372
6373
6374
6375


6376
6377
6378
6379
6380
6381
6382
	CACKEY_DEBUG_PRINTF("Returning.");

	return;
}

/*
 * SYNPOSIS
 *     LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol, LPDWORD selected_protocol);
 *
 * ARGUMENTS
 *     cackey_slot *slot
 *         Slot to send commands to
 *
 *     DWORD default_protocol
 *         Protocol to attempt first
 *
 *     LPDWORD selected_protocol
 *         [OUT] Protocol selected
 *
 * RETURN VALUE
 *     The return value from SCardReconnect()
 *
 * NOTES
 *     This function is a wrapper around SCardReconnect()
 *
 *     The SCardReconnect() function call will be called first with the
 *     dwPreferredProtocols of "default_protocol".  If that call returns
 *     SCARD_E_PROTO_MISMATCH try again with a protocol of T=0, and failing
 *     that T=1.
 *
 */
static LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol, LPDWORD selected_protocol) {

	LONG scard_conn_ret;



	scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, default_protocol, SCARD_RESET_CARD, selected_protocol);

	if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
		CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
		scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, selected_protocol);

		if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
			CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
			scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, selected_protocol);
		}
	}





	return(scard_conn_ret);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_connect_card(struct cackey_slot *slot);
................................................................................

				if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
					CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
					scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
				}
			}

			scard_conn_ret = cackey_reconnect_card(slot, protocol, &protocol);
		}

		if (scard_conn_ret != SCARD_S_SUCCESS) {
			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);

			return(CACKEY_PCSC_E_GENERIC);
		}
................................................................................
 *     goes away.
 *
 */
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) {
	uint8_t major_rc, minor_rc;
	size_t bytes_to_copy, tmp_respdata_len;
	LPCSCARD_IO_REQUEST pioSendPci;
	DWORD protocol;
	DWORD xmit_len, recv_len;
	LONG scard_xmit_ret, scard_reconn_ret;
	BYTE xmit_buf[1024], recv_buf[1024];
	int pcsc_connect_ret, pcsc_getresp_ret;
	int idx;

	CACKEY_DEBUG_PRINTF("Called.");
................................................................................

	if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) {
		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);

		/* Begin Smartcard Transaction */
		cackey_end_transaction(slot);



		return(CACKEY_PCSC_E_RETRY);
	}

	if (scard_xmit_ret != SCARD_S_SUCCESS) {
		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);

		CACKEY_DEBUG_PRINTF("Marking slot as having been reset");
		cackey_mark_slot_reset(slot);

		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
			CACKEY_DEBUG_PRINTF("Reset required, please hold...");

			scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &protocol);

			if (scard_reconn_ret == SCARD_S_SUCCESS) {
				/* Update protocol */
				slot->protocol = protocol;
				switch (slot->protocol) {
					case SCARD_PROTOCOL_T0:
						pioSendPci = SCARD_PCI_T0;

						break;
					case SCARD_PROTOCOL_T1:
						pioSendPci = SCARD_PCI_T1;
................................................................................
				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);
				break;
			case CACKEY_ID_TYPE_CERT_ONLY:
				break;
		}

		if (send_ret != CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");

			if (free_tmpbuf) {
				if (tmpbuf_s) {
					free(tmpbuf_s);
				}
			}

			/* End transaction */
			cackey_end_transaction(slot);









			if (respcode == 0x6982 || respcode == 0x6e00) {
				if (respcode == 0x6E00) {
					CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting");
				} else {
					CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x).  Returning NEEDLOGIN", (int) respcode);
				}

................................................................................

	if (status_ret != SCARD_S_SUCCESS) {
		cackey_mark_slot_reset(slot);

		if (status_ret == SCARD_W_RESET_CARD) {
			CACKEY_DEBUG_PRINTF("Reset required, please hold...");

			scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &protocol);
			if (scard_reconn_ret == SCARD_S_SUCCESS) {
				/* Update protocol */
				slot->protocol = protocol;

				/* Re-establish transaction, if it was present */
				if (slot->transaction_depth > 0) {
					slot->transaction_depth--;
					slot->transaction_need_hw_lock = 1;
					cackey_begin_transaction(slot);
				}

................................................................................
			if (buflen < 0) {
				/* Decryption failed. */
				if (buflen == CACKEY_PCSC_E_NEEDLOGIN) {
					retval = CKR_USER_NOT_LOGGED_IN;
				} else if (buflen == CACKEY_PCSC_E_TOKENABSENT) {
					retval = CKR_DEVICE_REMOVED;
				} else {


					retval = CKR_GENERAL_ERROR;
				}
			} else if (((unsigned long) buflen) > *pulPartLen && pPart) {
				/* Decrypted data too large */
				retval = CKR_BUFFER_TOO_SMALL;
			} else {
				if (pPart) {







|








<
<
<












|
>


>
>
|



|



|


>
>
>
>







 







|







 







<







 







>
>












|


<
<







 







<
<









>
>
>
>
>
>
>
>







 







|

<
<
<







 







>
>







1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141



1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
....
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
....
1445
1446
1447
1448
1449
1450
1451

1452
1453
1454
1455
1456
1457
1458
....
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562


1563
1564
1565
1566
1567
1568
1569
....
2860
2861
2862
2863
2864
2865
2866


2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
....
3189
3190
3191
3192
3193
3194
3195
3196
3197



3198
3199
3200
3201
3202
3203
3204
....
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
	CACKEY_DEBUG_PRINTF("Returning.");

	return;
}

/*
 * SYNPOSIS
 *     LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol);
 *
 * ARGUMENTS
 *     cackey_slot *slot
 *         Slot to send commands to
 *
 *     DWORD default_protocol
 *         Protocol to attempt first
 *



 * RETURN VALUE
 *     The return value from SCardReconnect()
 *
 * NOTES
 *     This function is a wrapper around SCardReconnect()
 *
 *     The SCardReconnect() function call will be called first with the
 *     dwPreferredProtocols of "default_protocol".  If that call returns
 *     SCARD_E_PROTO_MISMATCH try again with a protocol of T=0, and failing
 *     that T=1.
 *
 */
static LONG cackey_reconnect_card(struct cackey_slot *slot, DWORD default_protocol) {
	DWORD selected_protocol;
	LONG scard_conn_ret;

	selected_protocol = 0;

	scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, default_protocol, SCARD_RESET_CARD, &selected_protocol);

	if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
		CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
		scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &selected_protocol);

		if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
			CACKEY_DEBUG_PRINTF("SCardReconnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
			scard_conn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, SCARD_RESET_CARD, &selected_protocol);
		}
	}

	if (scard_conn_ret == SCARD_S_SUCCESS) {
		slot->protocol = selected_protocol;
	}

	return(scard_conn_ret);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_connect_card(struct cackey_slot *slot);
................................................................................

				if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
					CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=1")
					scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
				}
			}

			scard_conn_ret = cackey_reconnect_card(slot, protocol);
		}

		if (scard_conn_ret != SCARD_S_SUCCESS) {
			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);

			return(CACKEY_PCSC_E_GENERIC);
		}
................................................................................
 *     goes away.
 *
 */
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) {
	uint8_t major_rc, minor_rc;
	size_t bytes_to_copy, tmp_respdata_len;
	LPCSCARD_IO_REQUEST pioSendPci;

	DWORD xmit_len, recv_len;
	LONG scard_xmit_ret, scard_reconn_ret;
	BYTE xmit_buf[1024], recv_buf[1024];
	int pcsc_connect_ret, pcsc_getresp_ret;
	int idx;

	CACKEY_DEBUG_PRINTF("Called.");
................................................................................

	if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) {
		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);

		/* Begin Smartcard Transaction */
		cackey_end_transaction(slot);

		cackey_reconnect_card(slot, slot->protocol);

		return(CACKEY_PCSC_E_RETRY);
	}

	if (scard_xmit_ret != SCARD_S_SUCCESS) {
		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);

		CACKEY_DEBUG_PRINTF("Marking slot as having been reset");
		cackey_mark_slot_reset(slot);

		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
			CACKEY_DEBUG_PRINTF("Reset required, please hold...");

			scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1);

			if (scard_reconn_ret == SCARD_S_SUCCESS) {


				switch (slot->protocol) {
					case SCARD_PROTOCOL_T0:
						pioSendPci = SCARD_PCI_T0;

						break;
					case SCARD_PROTOCOL_T1:
						pioSendPci = SCARD_PCI_T1;
................................................................................
				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);
				break;
			case CACKEY_ID_TYPE_CERT_ONLY:
				break;
		}

		if (send_ret != CACKEY_PCSC_S_OK) {


			if (free_tmpbuf) {
				if (tmpbuf_s) {
					free(tmpbuf_s);
				}
			}

			/* End transaction */
			cackey_end_transaction(slot);

			if (send_ret == CACKEY_PCSC_E_RETRY) {
				CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- retrying.");

				return(cackey_signdecrypt(slot, identity, buf, buflen, outbuf, outbuflen, padInput, unpadOutput));
			}

			CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");

			if (respcode == 0x6982 || respcode == 0x6e00) {
				if (respcode == 0x6E00) {
					CACKEY_DEBUG_PRINTF("Got \"WRONG CLASS\", this means we are talking to the wrong object (likely because the card went away) -- resetting");
				} else {
					CACKEY_DEBUG_PRINTF("Security status not satisified (respcode = 0x%04x).  Returning NEEDLOGIN", (int) respcode);
				}

................................................................................

	if (status_ret != SCARD_S_SUCCESS) {
		cackey_mark_slot_reset(slot);

		if (status_ret == SCARD_W_RESET_CARD) {
			CACKEY_DEBUG_PRINTF("Reset required, please hold...");

			scard_reconn_ret = cackey_reconnect_card(slot, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1);
			if (scard_reconn_ret == SCARD_S_SUCCESS) {



				/* Re-establish transaction, if it was present */
				if (slot->transaction_depth > 0) {
					slot->transaction_depth--;
					slot->transaction_need_hw_lock = 1;
					cackey_begin_transaction(slot);
				}

................................................................................
			if (buflen < 0) {
				/* Decryption failed. */
				if (buflen == CACKEY_PCSC_E_NEEDLOGIN) {
					retval = CKR_USER_NOT_LOGGED_IN;
				} else if (buflen == CACKEY_PCSC_E_TOKENABSENT) {
					retval = CKR_DEVICE_REMOVED;
				} else {
					CACKEY_DEBUG_PRINTF("Failed to send APDU, error = %li", (long int) buflen);

					retval = CKR_GENERAL_ERROR;
				}
			} else if (((unsigned long) buflen) > *pulPartLen && pPart) {
				/* Decrypted data too large */
				retval = CKR_BUFFER_TOO_SMALL;
			} else {
				if (pPart) {