Check-in [fdd66a54cd]
Overview
Comment:Simplified some slot disconnect logic and updated to store an ID type hint on the slot itself so that if we reinitialize we treat it as the same type of device
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fdd66a54cd37656c39bdcdb06e698840f89d4a02
User & Date: rkeene on 2016-02-16 23:24:33
Other Links: manifest | tags
Context
2016-02-19
13:30
ChromeOS: Added package icon check-in: e1dc965e9b user: rkeene tags: trunk
2016-02-16
23:24
Simplified some slot disconnect logic and updated to store an ID type hint on the slot itself so that if we reinitialize we treat it as the same type of device check-in: fdd66a54cd user: rkeene tags: trunk
17:04
Added workaround for Google's PCSC where we cannot determine the amount of space required to hold the reader list automatically check-in: 6218cc54fc user: rkeene tags: trunk
Changes

Modified cackey.c from [ebe379d38c] to [6db8eb96eb].

813
814
815
816
817
818
819


820
821
822
823
824
825
826

	unsigned char *label;

	DWORD protocol;

	unsigned int cached_certs_count;
	struct cackey_pcsc_identity *cached_certs;


};

typedef enum {
	CACKEY_TLV_APP_GENERIC = 0x01,
	CACKEY_TLV_APP_SKI     = 0x02,
	CACKEY_TLV_APP_PKI     = 0x04
} cackey_tlv_apptype;







>
>







813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828

	unsigned char *label;

	DWORD protocol;

	unsigned int cached_certs_count;
	struct cackey_pcsc_identity *cached_certs;

	cackey_pcsc_id_type id_type_hint;
};

typedef enum {
	CACKEY_TLV_APP_GENERIC = 0x01,
	CACKEY_TLV_APP_SKI     = 0x02,
	CACKEY_TLV_APP_PKI     = 0x04
} cackey_tlv_apptype;
934
935
936
937
938
939
940
941
942
943

944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960

	return(retval);
}

/* PC/SC Related Functions */
/*
 * SYNPOSIS
 *     void cackey_slots_disconnect_all(void);
 *
 * ARGUMENTS

 *     None
 *
 * RETURN VALUE
 *     None
 *
 * NOTES
 *     This function disconnects from all cards.
 *
 */
static void cackey_slots_disconnect_all(void) {
	uint32_t idx;

	CACKEY_DEBUG_PRINTF("Called.");

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].internal) {
			/* Skip internal slots */







|


>
|








|







936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963

	return(retval);
}

/* PC/SC Related Functions */
/*
 * SYNPOSIS
 *     void cackey_slots_disconnect_all(int unitialize_all_readers);
 *
 * ARGUMENTS
 *     int unitialize_all_readers      Free the "pcsc_reader" object associated with
 *                           each slot (boolean)
 *
 * RETURN VALUE
 *     None
 *
 * NOTES
 *     This function disconnects from all cards.
 *
 */
static void cackey_slots_disconnect_all(int unitialize_all_readers) {
	uint32_t idx;

	CACKEY_DEBUG_PRINTF("Called.");

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].internal) {
			/* Skip internal slots */
968
969
970
971
972
973
974
975




976



977



978




979
980
981
982
983
984

985
986
987
988
989
990
991
		}

		if (cackey_slots[idx].label) {
			free(cackey_slots[idx].label);

			cackey_slots[idx].label = NULL;
		}





		cackey_slots[idx].pcsc_card_connected = 0;



		cackey_slots[idx].transaction_depth = 0;



		cackey_slots[idx].transaction_need_hw_lock = 0;





		if (cackey_slots[idx].active) {
			CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx);
		}

		cackey_slots[idx].slot_reset = 1;

	}

	CACKEY_DEBUG_PRINTF("Returning");

	return;
}









>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>



|
<
|
>







971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999

1000
1001
1002
1003
1004
1005
1006
1007
1008
		}

		if (cackey_slots[idx].label) {
			free(cackey_slots[idx].label);

			cackey_slots[idx].label = NULL;
		}

		if (unitialize_all_readers || !cackey_slots[idx].active) {
			if (cackey_slots[idx].pcsc_reader) {
				free(cackey_slots[idx].pcsc_reader);

				cackey_slots[idx].pcsc_reader = NULL;
			}

			cackey_slots[idx].transaction_need_hw_lock = 0;
			cackey_slots[idx].transaction_depth = 0;
			cackey_slots[idx].id_type_hint = CACKEY_ID_TYPE_UNKNOWN;
		} else {
			if (cackey_slots[idx].transaction_depth > 0) {
				cackey_slots[idx].transaction_need_hw_lock = 1;
			}
		}

		cackey_slots[idx].pcsc_card_connected = 0;

		if (cackey_slots[idx].active) {
			CACKEY_DEBUG_PRINTF("Marking active slot %lu as being reset", (unsigned long) idx);


			cackey_slots[idx].slot_reset = 1;
		}
	}

	CACKEY_DEBUG_PRINTF("Returning");

	return;
}

1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
	CACKEY_DEBUG_PRINTF("Called.");

	if (cackey_pcsc_handle == NULL) {
		cackey_pcsc_handle = malloc(sizeof(*cackey_pcsc_handle));
		if (cackey_pcsc_handle == NULL) {
			CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure");

			cackey_slots_disconnect_all();

			return(CACKEY_PCSC_E_GENERIC);
		}

		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
		if (scard_est_context_ret != SCARD_S_SUCCESS) {
			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret);

			free(cackey_pcsc_handle);
			cackey_pcsc_handle = NULL;

			cackey_slots_disconnect_all();

			return(CACKEY_PCSC_E_GENERIC);
		}
	}

#ifdef HAVE_SCARDISVALIDCONTEXT
	CACKEY_DEBUG_PRINTF("SCardIsValidContext() called");
	scard_isvalid_ret = SCardIsValidContext(*cackey_pcsc_handle);
	if (scard_isvalid_ret != SCARD_S_SUCCESS) {
		CACKEY_DEBUG_PRINTF("Handle has become invalid (SCardIsValidContext = %s/%li), trying to re-establish...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_isvalid_ret), (long) scard_isvalid_ret);

		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
		if (scard_est_context_ret != SCARD_S_SUCCESS) {
			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret);

			free(cackey_pcsc_handle);
			cackey_pcsc_handle = NULL;

			cackey_slots_disconnect_all();

			return(CACKEY_PCSC_E_GENERIC);
		}

		CACKEY_DEBUG_PRINTF("Handle has been re-established");
	}
#endif







|












|



















|







1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
	CACKEY_DEBUG_PRINTF("Called.");

	if (cackey_pcsc_handle == NULL) {
		cackey_pcsc_handle = malloc(sizeof(*cackey_pcsc_handle));
		if (cackey_pcsc_handle == NULL) {
			CACKEY_DEBUG_PRINTF("Call to malloc() failed, returning in failure");

			cackey_slots_disconnect_all(0);

			return(CACKEY_PCSC_E_GENERIC);
		}

		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
		if (scard_est_context_ret != SCARD_S_SUCCESS) {
			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret);

			free(cackey_pcsc_handle);
			cackey_pcsc_handle = NULL;

			cackey_slots_disconnect_all(0);

			return(CACKEY_PCSC_E_GENERIC);
		}
	}

#ifdef HAVE_SCARDISVALIDCONTEXT
	CACKEY_DEBUG_PRINTF("SCardIsValidContext() called");
	scard_isvalid_ret = SCardIsValidContext(*cackey_pcsc_handle);
	if (scard_isvalid_ret != SCARD_S_SUCCESS) {
		CACKEY_DEBUG_PRINTF("Handle has become invalid (SCardIsValidContext = %s/%li), trying to re-establish...", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_isvalid_ret), (long) scard_isvalid_ret);

		CACKEY_DEBUG_PRINTF("SCardEstablishContext() called");
		scard_est_context_ret = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, cackey_pcsc_handle);
		if (scard_est_context_ret != SCARD_S_SUCCESS) {
			CACKEY_DEBUG_PRINTF("Call to SCardEstablishContext failed (returned %s/%li), returning in failure", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_est_context_ret), (long) scard_est_context_ret);

			free(cackey_pcsc_handle);
			cackey_pcsc_handle = NULL;

			cackey_slots_disconnect_all(0);

			return(CACKEY_PCSC_E_GENERIC);
		}

		CACKEY_DEBUG_PRINTF("Handle has been re-established");
	}
#endif
1097
1098
1099
1100
1101
1102
1103


1104
1105
1106
1107
1108
1109
1110
	
		cackey_pcsc_handle = NULL;
	}

	if (scard_rel_context_ret != SCARD_S_SUCCESS) {
		return(CACKEY_PCSC_E_GENERIC);
	}



	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     void cackey_mark_slot_reset(struct cackey_slot *slot);







>
>







1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
	
		cackey_pcsc_handle = NULL;
	}

	if (scard_rel_context_ret != SCARD_S_SUCCESS) {
		return(CACKEY_PCSC_E_GENERIC);
	}

	cackey_slots_disconnect_all(0);

	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     void cackey_mark_slot_reset(struct cackey_slot *slot);
1490
1491
1492
1493
1494
1495
1496




1497
1498
1499
1500
1501
1502
1503
	CACKEY_DEBUG_PRINTF("Called.");

	if (!slot) {
		CACKEY_DEBUG_PRINTF("Invalid slot specified.");

		return(CACKEY_PCSC_E_GENERIC);
	}





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

		return(CACKEY_PCSC_E_GENERIC);
	}







>
>
>
>







1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
	CACKEY_DEBUG_PRINTF("Called.");

	if (!slot) {
		CACKEY_DEBUG_PRINTF("Invalid slot specified.");

		return(CACKEY_PCSC_E_GENERIC);
	}

	if (respcode) {
		*respcode = 0xffff;
	}

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

		return(CACKEY_PCSC_E_GENERIC);
	}
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
	cackey_pcsc_id_type try_types[2], try_type;
	int send_ret;
	int idx;

	CACKEY_DEBUG_PRINTF("Reselecting the root applet");

	if (type_hint == CACKEY_ID_TYPE_UNKNOWN) {
		if (slot->cached_certs && slot->cached_certs_count > 0) {
			type_hint = slot->cached_certs[0].id_type;
		}
	}


	switch (type_hint) {
		case CACKEY_ID_TYPE_PIV:
			CACKEY_DEBUG_PRINTF("Trying to reselect the PIV root applet first");

			try_types[0] = CACKEY_ID_TYPE_PIV;
			try_types[1] = CACKEY_ID_TYPE_CAC;







<
|
|
|
>







2161
2162
2163
2164
2165
2166
2167

2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
	cackey_pcsc_id_type try_types[2], try_type;
	int send_ret;
	int idx;

	CACKEY_DEBUG_PRINTF("Reselecting the root applet");

	if (type_hint == CACKEY_ID_TYPE_UNKNOWN) {

		type_hint = slot->id_type_hint;
	}

	slot->id_type_hint = CACKEY_ID_TYPE_UNKNOWN;

	switch (type_hint) {
		case CACKEY_ID_TYPE_PIV:
			CACKEY_DEBUG_PRINTF("Trying to reselect the PIV root applet first");

			try_types[0] = CACKEY_ID_TYPE_PIV;
			try_types[1] = CACKEY_ID_TYPE_CAC;
2184
2185
2186
2187
2188
2189
2190


2191
2192
2193
2194
2195
2196
2197

		if (send_ret == CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("Successfully selected the %s applet -- setting the \"LOGIN REQUIRED\" flag on the token",
				try_type == CACKEY_ID_TYPE_CAC ? "CAC" : "PIV"
			);

			slot->token_flags = CKF_LOGIN_REQUIRED;



			return(try_type);
		}
	}

	CACKEY_DEBUG_PRINTF("Unable to select any applet, returning in failure");








>
>







2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222

		if (send_ret == CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("Successfully selected the %s applet -- setting the \"LOGIN REQUIRED\" flag on the token",
				try_type == CACKEY_ID_TYPE_CAC ? "CAC" : "PIV"
			);

			slot->token_flags = CKF_LOGIN_REQUIRED;

			slot->id_type_hint = try_type;

			return(try_type);
		}
	}

	CACKEY_DEBUG_PRINTF("Unable to select any applet, returning in failure");

3158
3159
3160
3161
3162
3163
3164

3165


3166
3167
3168
3169
3170
3171
3172

				return(CACKEY_PCSC_E_TOKENABSENT);
			}

			CACKEY_DEBUG_PRINTF("Something went wrong during signing, resetting the slot and hoping for the best.");

			cackey_pcsc_disconnect();

			cackey_pcsc_connect();



			return(CACKEY_PCSC_E_GENERIC);
		}

		tmpbuf += bytes_to_send;
		tmpbuflen -= bytes_to_send;








>

>
>







3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200

				return(CACKEY_PCSC_E_TOKENABSENT);
			}

			CACKEY_DEBUG_PRINTF("Something went wrong during signing, resetting the slot and hoping for the best.");

			cackey_pcsc_disconnect();

			cackey_pcsc_connect();

			cackey_detect_and_select_root_applet(slot, CACKEY_ID_TYPE_UNKNOWN);

			return(CACKEY_PCSC_E_GENERIC);
		}

		tmpbuf += bytes_to_send;
		tmpbuflen -= bytes_to_send;

4583
4584
4585
4586
4587
4588
4589

4590
4591
4592
4593
4594
4595
4596
		cackey_slots[idx].pcsc_reader = NULL;
		cackey_slots[idx].transaction_depth = 0;
		cackey_slots[idx].transaction_need_hw_lock = 0;
		cackey_slots[idx].slot_reset = 0;
		cackey_slots[idx].token_flags = 0;
		cackey_slots[idx].label = NULL;
		cackey_slots[idx].internal = 0;

	}

#ifdef CACKEY_NO_EXTRA_CERTS
	if (getenv("CACKEY_EXTRA_CERTS") != NULL) {
		include_dod_certs = 1;
	} else {
		include_dod_certs = 0;







>







4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
		cackey_slots[idx].pcsc_reader = NULL;
		cackey_slots[idx].transaction_depth = 0;
		cackey_slots[idx].transaction_need_hw_lock = 0;
		cackey_slots[idx].slot_reset = 0;
		cackey_slots[idx].token_flags = 0;
		cackey_slots[idx].label = NULL;
		cackey_slots[idx].internal = 0;
		cackey_slots[idx].id_type_hint = CACKEY_ID_TYPE_UNKNOWN;
	}

#ifdef CACKEY_NO_EXTRA_CERTS
	if (getenv("CACKEY_EXTRA_CERTS") != NULL) {
		include_dod_certs = 1;
	} else {
		include_dod_certs = 0;
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726

	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
		if (cackey_sessions[idx].active) {
			C_CloseSession(idx);
		}
	}

	cackey_slots_disconnect_all();

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].internal) {
			continue;
		}

		if (cackey_slots[idx].pcsc_reader) {
			free(cackey_slots[idx].pcsc_reader);
		}

		if (cackey_slots[idx].cached_certs) {
			cackey_free_certs(cackey_slots[idx].cached_certs, cackey_slots[idx].cached_certs_count, 1);

			cackey_slots[idx].cached_certs = NULL;
		}
	}








|






<
<
<
<







4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744




4745
4746
4747
4748
4749
4750
4751

	for (idx = 0; idx < (sizeof(cackey_sessions) / sizeof(cackey_sessions[0])); idx++) {
		if (cackey_sessions[idx].active) {
			C_CloseSession(idx);
		}
	}

	cackey_slots_disconnect_all(1);

	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
		if (cackey_slots[idx].internal) {
			continue;
		}





		if (cackey_slots[idx].cached_certs) {
			cackey_free_certs(cackey_slots[idx].cached_certs, cackey_slots[idx].cached_certs_count, 1);

			cackey_slots[idx].cached_certs = NULL;
		}
	}

4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
			}
		}

		if (slot_reset) {
			CACKEY_DEBUG_PRINTF("Purging all slot information.");

			/* Only update the list of slots if we are actually being supply the slot information */
			cackey_slots_disconnect_all();

			for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
				if (cackey_slots[currslot].internal) {
					continue;
				}

				if (cackey_slots[currslot].pcsc_reader) {
					free(cackey_slots[currslot].pcsc_reader);

					cackey_slots[currslot].pcsc_reader = NULL;
				}

				if (cackey_slots[currslot].label) {
					free(cackey_slots[currslot].label);

					cackey_slots[currslot].label = NULL;
				}

				cackey_slots[currslot].active = 0;
			}
		}
	}

	/* Determine list of readers */
	pcsc_connect_ret = cackey_pcsc_connect();







|






<
<
<
<
<
<
<
<
<
<
<
<







4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889












4890
4891
4892
4893
4894
4895
4896
			}
		}

		if (slot_reset) {
			CACKEY_DEBUG_PRINTF("Purging all slot information.");

			/* Only update the list of slots if we are actually being supply the slot information */
			cackey_slots_disconnect_all(1);

			for (currslot = 0; currslot < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); currslot++) {
				if (cackey_slots[currslot].internal) {
					continue;
				}













				cackey_slots[currslot].active = 0;
			}
		}
	}

	/* Determine list of readers */
	pcsc_connect_ret = cackey_pcsc_connect();