Check-in [9b8b8e3b4a]
Overview
Comment:Updated to retry APDU in some cases

Updated to recognize when a card is logged out without being switched

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9b8b8e3b4ad44774d04ca207013ae14af26833dc
User & Date: rkeene on 2010-05-23 02:59:54
Other Links: manifest | tags
Context
2010-05-23
03:42
Updated to retry if got NOT_TRANSACTED

Fixed issue with retry in APDU transmit check-in: 7cc9fb64cc user: rkeene tags: trunk

02:59
Updated to retry APDU in some cases

Updated to recognize when a card is logged out without being switched check-in: 9b8b8e3b4a user: rkeene tags: trunk

2010-05-22
21:31
Updated to set LOGIN_REQUIRED flag when C_Logout is called

Updated to check all references to a session's slot check-in: a08de24384 user: rkeene tags: trunk

Changes

Modified cackey.c from [26bb9837f1] to [6811fa6136].

549
550
551
552
553
554
555
556
557
558
559
560
561


562
563
564
565
566
567
568
	CACKEY_TLV_OBJID_CAC_BENEFITS      = 0x0202,
	CACKEY_TLV_OBJID_CAC_OTHERBENEFITS = 0x0203,
	CACKEY_TLV_OBJID_CAC_PERSONNEL     = 0x0201,
	CACKEY_TLV_OBJID_CAC_PKICERT       = 0x02FE
} cackey_tlv_objectid;

typedef enum {
	CACKEY_PCSC_S_TOKENPRESENT    = 2,
	CACKEY_PCSC_S_TOKENABSENT     = 1,
	CACKEY_PCSC_S_OK              = 0,
	CACKEY_PCSC_E_GENERIC         = -1,
	CACKEY_PCSC_E_BADPIN          = -2,
	CACKEY_PCSC_E_LOCKED          = -3,


} cackey_ret;

struct cackey_tlv_cardurl {
	unsigned char        rid[5];
	cackey_tlv_apptype   apptype;
	cackey_tlv_objectid  objectid;
	cackey_tlv_objectid  appid;







|
<




>
>







549
550
551
552
553
554
555
556

557
558
559
560
561
562
563
564
565
566
567
568
569
	CACKEY_TLV_OBJID_CAC_BENEFITS      = 0x0202,
	CACKEY_TLV_OBJID_CAC_OTHERBENEFITS = 0x0203,
	CACKEY_TLV_OBJID_CAC_PERSONNEL     = 0x0201,
	CACKEY_TLV_OBJID_CAC_PKICERT       = 0x02FE
} cackey_tlv_objectid;

typedef enum {
	CACKEY_PCSC_S_TOKENPRESENT    = 1,

	CACKEY_PCSC_S_OK              = 0,
	CACKEY_PCSC_E_GENERIC         = -1,
	CACKEY_PCSC_E_BADPIN          = -2,
	CACKEY_PCSC_E_LOCKED          = -3,
	CACKEY_PCSC_E_NEEDLOGIN       = -4,
	CACKEY_PCSC_E_TOKENABSENT     = -6,
} cackey_ret;

struct cackey_tlv_cardurl {
	unsigned char        rid[5];
	cackey_tlv_apptype   apptype;
	cackey_tlv_objectid  objectid;
	cackey_tlv_objectid  appid;
1065
1066
1067
1068
1069
1070
1071





1072
1073
1074
1075
1076
1077
1078
		CACKEY_DEBUG_PRINTF("Sending APDU: <<censored>>");
	} else {
		CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);
	}

	recv_len = sizeof(recv_buf);
	scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);





	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");

		slot->transaction_depth = 0;
		slot->slot_reset = 1;








>
>
>
>
>







1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
		CACKEY_DEBUG_PRINTF("Sending APDU: <<censored>>");
	} else {
		CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);
	}

	recv_len = sizeof(recv_buf);
	scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);
	if (scard_xmit_ret == SCARD_E_NOT_TRANSACTED) {
		CACKEY_DEBUG_PRINTF("Failed to send APDU to card (SCardTransmit() = SCARD_E_NOT_TRANSACTED), retrying...");

		scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);
	}
	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");

		slot->transaction_depth = 0;
		slot->slot_reset = 1;

1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
					SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
					slot->pcsc_card_connected = 0;

					/* End Smartcard Transaction */
					slot->transaction_depth = 1;
					cackey_end_transaction(slot);

					return(CACKEY_PCSC_E_GENERIC);
				}
			} else {
				CACKEY_DEBUG_PRINTF("Disconnecting card");

				SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
				slot->pcsc_card_connected = 0;

				/* End Smartcard Transaction */
				slot->transaction_depth = 1;
				cackey_end_transaction(slot);

				CACKEY_DEBUG_PRINTF("Returning in failure");
				return(CACKEY_PCSC_E_GENERIC);
			}
		} else {
			CACKEY_DEBUG_PRINTF("Disconnecting card");

			SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
			slot->pcsc_card_connected = 0;

			/* End Smartcard Transaction */
			slot->transaction_depth = 1;
			cackey_end_transaction(slot);

			CACKEY_DEBUG_PRINTF("Returning in failure");
			return(CACKEY_PCSC_E_GENERIC);
		}
	}

	CACKEY_DEBUG_PRINTBUF("Returned Value:", recv_buf, recv_len);

	if (recv_len < 2) {
		/* Minimal response length is 2 bytes, returning in failure */







|












|












|







1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
					SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
					slot->pcsc_card_connected = 0;

					/* End Smartcard Transaction */
					slot->transaction_depth = 1;
					cackey_end_transaction(slot);

					return(CACKEY_PCSC_E_TOKENABSENT);
				}
			} else {
				CACKEY_DEBUG_PRINTF("Disconnecting card");

				SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
				slot->pcsc_card_connected = 0;

				/* End Smartcard Transaction */
				slot->transaction_depth = 1;
				cackey_end_transaction(slot);

				CACKEY_DEBUG_PRINTF("Returning in failure");
				return(CACKEY_PCSC_E_TOKENABSENT);
			}
		} else {
			CACKEY_DEBUG_PRINTF("Disconnecting card");

			SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
			slot->pcsc_card_connected = 0;

			/* End Smartcard Transaction */
			slot->transaction_depth = 1;
			cackey_end_transaction(slot);

			CACKEY_DEBUG_PRINTF("Returning in failure");
			return(CACKEY_PCSC_E_TOKENABSENT);
		}
	}

	CACKEY_DEBUG_PRINTBUF("Returned Value:", recv_buf, recv_len);

	if (recv_len < 2) {
		/* Minimal response length is 2 bytes, returning in failure */
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990


















1991
1992
1993
1994
1995
1996
1997

		tmpoutbuflen = outbuflen;

		send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
		if (send_ret != CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");

			if (respcode == 0x6982) {
				CACKEY_DEBUG_PRINTF("Security status not satisified.");
			}

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

			/* End transaction */
			cackey_end_transaction(slot);



















			return(-1);
		}

		tmpbuf += bytes_to_send;
		tmpbuflen -= bytes_to_send;








<
<
<
<








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1978
1979
1980
1981
1982
1983
1984




1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017

		tmpoutbuflen = outbuflen;

		send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
		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) {
				CACKEY_DEBUG_PRINTF("Security status not satisified.  Returning NEEDLOGIN");

				slot->slot_reset = 1;
				slot->token_flags = CKF_LOGIN_REQUIRED;

				return(CACKEY_PCSC_E_NEEDLOGIN);
			}

			if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
				CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");

				slot->slot_reset = 1;
				slot->token_flags = CKF_LOGIN_REQUIRED;

				return(CACKEY_PCSC_E_TOKENABSENT);
			}

			return(-1);
		}

		tmpbuf += bytes_to_send;
		tmpbuflen -= bytes_to_send;

2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198

	CACKEY_DEBUG_PRINTF("Called.");

	pcsc_connect_ret = cackey_connect_card(slot);
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");

		return(CACKEY_PCSC_S_TOKENABSENT);
	}

	atr_len = sizeof(atr);
	status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
	if (status_ret != SCARD_S_SUCCESS) {
		slot->slot_reset = 1;
		slot->token_flags = CKF_LOGIN_REQUIRED;







|







2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218

	CACKEY_DEBUG_PRINTF("Called.");

	pcsc_connect_ret = cackey_connect_card(slot);
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning token absent");

		return(CACKEY_PCSC_E_TOKENABSENT);
	}

	atr_len = sizeof(atr);
	status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
	if (status_ret != SCARD_S_SUCCESS) {
		slot->slot_reset = 1;
		slot->token_flags = CKF_LOGIN_REQUIRED;
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
				}

				CACKEY_DEBUG_PRINTF("Reset successful, requerying");
				status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
				if (status_ret != SCARD_S_SUCCESS) {
					CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));

					return(CACKEY_PCSC_S_TOKENABSENT);
				}
			} else {
				CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent.  SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret));

				return(CACKEY_PCSC_S_TOKENABSENT);
			}
		} else {
			CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));

			return(CACKEY_PCSC_S_TOKENABSENT);
		}
	}

	if ((state & SCARD_ABSENT) == SCARD_ABSENT) {
		CACKEY_DEBUG_PRINTF("Card is absent, returning token absent");

		return(CACKEY_PCSC_S_TOKENABSENT);
	}

	CACKEY_DEBUG_PRINTF("Returning token present.");

	return(CACKEY_PCSC_S_TOKENPRESENT);
}








|




|




|






|







2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
				}

				CACKEY_DEBUG_PRINTF("Reset successful, requerying");
				status_ret = SCardStatus(slot->pcsc_card, NULL, &reader_len, &state, &protocol, atr, &atr_len);
				if (status_ret != SCARD_S_SUCCESS) {
					CACKEY_DEBUG_PRINTF("Still unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));

					return(CACKEY_PCSC_E_TOKENABSENT);
				}
			} else {
				CACKEY_DEBUG_PRINTF("Unable to reconnect to card, returning token absent.  SCardReconnect() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_reconn_ret));

				return(CACKEY_PCSC_E_TOKENABSENT);
			}
		} else {
			CACKEY_DEBUG_PRINTF("Unable to query card status, returning token absent.  SCardStatus() = %s", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(status_ret));

			return(CACKEY_PCSC_E_TOKENABSENT);
		}
	}

	if ((state & SCARD_ABSENT) == SCARD_ABSENT) {
		CACKEY_DEBUG_PRINTF("Card is absent, returning token absent");

		return(CACKEY_PCSC_E_TOKENABSENT);
	}

	CACKEY_DEBUG_PRINTF("Returning token present.");

	return(CACKEY_PCSC_S_TOKENPRESENT);
}

4804
4805
4806
4807
4808
4809
4810





4811

4812
4813
4814
4815
4816
4817
4818
	switch (cackey_sessions[hSession].decrypt_mechanism) {
		case CKM_RSA_PKCS:
			/* Ask card to decrypt */
			buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1);

			if (buflen < 0) {
				/* Decryption failed. */





				retval = CKR_GENERAL_ERROR;

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







>
>
>
>
>
|
>







4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
	switch (cackey_sessions[hSession].decrypt_mechanism) {
		case CKM_RSA_PKCS:
			/* Ask card to decrypt */
			buflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].decrypt_identity, pEncryptedPart, ulEncryptedPartLen, buf, sizeof(buf), 0, 1);

			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) {
					memcpy(pPart, buf, buflen);
				}
5274
5275
5276
5277
5278
5279
5280





5281

5282
5283
5284
5285
5286
5287
5288
		case CKM_RSA_PKCS:
			/* Ask card to sign */
			CACKEY_DEBUG_PRINTF("Asking to sign from identity %p in session %lu", cackey_sessions[hSession].sign_identity, (unsigned long) hSession);
			sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0);

			if (sigbuflen < 0) {
				/* Signing failed. */





				retval = CKR_GENERAL_ERROR;

			} else if (((unsigned long) sigbuflen) > *pulSignatureLen && pSignature) {
				/* Signed data too large */
				CACKEY_DEBUG_PRINTF("retval = CKR_BUFFER_TOO_SMALL;  sigbuflen = %lu, pulSignatureLen = %lu", (unsigned long) sigbuflen, (unsigned long) *pulSignatureLen);

				retval = CKR_BUFFER_TOO_SMALL;

				terminate_sign = 0;







>
>
>
>
>
|
>







5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
		case CKM_RSA_PKCS:
			/* Ask card to sign */
			CACKEY_DEBUG_PRINTF("Asking to sign from identity %p in session %lu", cackey_sessions[hSession].sign_identity, (unsigned long) hSession);
			sigbuflen = cackey_signdecrypt(&cackey_slots[slotID], cackey_sessions[hSession].sign_identity, cackey_sessions[hSession].sign_buf, cackey_sessions[hSession].sign_bufused, sigbuf, sizeof(sigbuf), 1, 0);

			if (sigbuflen < 0) {
				/* Signing failed. */
				if (sigbuflen == CACKEY_PCSC_E_NEEDLOGIN) {
					retval = CKR_USER_NOT_LOGGED_IN;
				} else if (sigbuflen == CACKEY_PCSC_E_TOKENABSENT) {
					retval = CKR_DEVICE_REMOVED;
				} else {
					retval = CKR_GENERAL_ERROR;
				}
			} else if (((unsigned long) sigbuflen) > *pulSignatureLen && pSignature) {
				/* Signed data too large */
				CACKEY_DEBUG_PRINTF("retval = CKR_BUFFER_TOO_SMALL;  sigbuflen = %lu, pulSignatureLen = %lu", (unsigned long) sigbuflen, (unsigned long) *pulSignatureLen);

				retval = CKR_BUFFER_TOO_SMALL;

				terminate_sign = 0;