Check-in [123c71d946]
Overview
Comment:Updated to use unified return codes
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 123c71d9463b9c002d18669f999b4e8a7f9108b6
User & Date: rkeene on 2010-05-13 18:22:56
Other Links: manifest | tags
Context
2010-05-13
18:24
Fixed issues with PIN handling check-in: 780bd59a25 user: rkeene tags: trunk
18:22
Updated to use unified return codes check-in: 123c71d946 user: rkeene tags: trunk
16:19
Updated to determine subject from certificate check-in: 5534d640e4 user: rkeene tags: trunk
Changes

Modified cackey.c from [cf1bec3529] to [65f29eb7d2].

505
506
507
508
509
510
511
512
513
514
515







516
517
518
519
520
521
522
505
506
507
508
509
510
511




512
513
514
515
516
517
518
519
520
521
522
523
524
525







-
-
-
-
+
+
+
+
+
+
+







	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_LOGIN_OK     = 0,
	CACKEY_LOGIN_BADPIN = -1,
	CACKEY_LOGIN_LOCKED = -2
} cackey_login_ret;
	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;
	unsigned char        pinid;
599
600
601
602
603
604
605
606

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621

622
623
624
625
626
627
628
629
630
631
632
633

634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652

653
654
655
656
657
658
659
660
661

662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

682
683
684
685

686
687
688

689
690
691
692
693
694
695
696
697
698
699

700
701
702
703
704
705
706
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635

636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654

655
656
657
658
659
660
661
662
663

664
665
666
667
668

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683

684
685
686
687

688
689
690

691
692
693
694
695
696
697
698
699
700
701

702
703
704
705
706
707
708
709







-
+














-
+











-
+


















-
+








-
+




-
+














-
+



-
+


-
+










-
+







	}

	CACKEY_DEBUG_PRINTF("Returning");

	return;
}

static int cackey_pcsc_connect(void) {
static cackey_ret cackey_pcsc_connect(void) {
	LONG scard_est_context_ret;
#ifdef HAVE_SCARDISVALIDCONTEXT
	LONG scard_isvalid_ret;
#endif

	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(-1);
			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_slots_disconnect_all();

			return(-1);
			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_slots_disconnect_all();

			return(-1);
			return(CACKEY_PCSC_E_GENERIC);
		}

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

	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");

	return(0);
	return(CACKEY_PCSC_S_OK);
}

/* APDU Related Functions */
/** Le = 0x00 to indicate not to send Le **/
static int cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char le, uint16_t *respcode, unsigned char *respdata, size_t *respdata_len) {
static cackey_ret cackey_send_apdu(struct cackey_slot *slot, unsigned char class, unsigned char instruction, unsigned char p1, unsigned char p2, unsigned char lc, unsigned char *data, unsigned char 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;
	DWORD protocol;
	DWORD xmit_len, recv_len;
	LONG scard_conn_ret, 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 (!slot) {
		CACKEY_DEBUG_PRINTF("Invalid slot specified.");

		return(-1);
		return(CACKEY_PCSC_E_GENERIC);
	}

	pcsc_connect_ret = cackey_pcsc_connect();
	if (pcsc_connect_ret < 0) {
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");

		return(-1);
		return(CACKEY_PCSC_E_GENERIC);
	}

	/* Connect to reader, if needed */
	if (!slot->pcsc_card_connected) {
		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader);
		scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &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(-1);
			return(CACKEY_PCSC_E_GENERIC);
		}

		slot->pcsc_card_connected = 1;
	}

	/* Transmit */
	xmit_len = 0;
736
737
738
739
740
741
742
743

744
745
746
747
748
749
750
751
752

753
754
755
756
757
758
759
760
761

762
763
764
765
766
767
768
769
770
771

772
773
774
775
776
777
778
739
740
741
742
743
744
745

746
747
748
749
750
751
752
753
754

755
756
757
758
759
760
761
762
763

764
765
766
767
768
769
770
771
772
773

774
775
776
777
778
779
780
781







-
+








-
+








-
+









-
+








				if (scard_xmit_ret != SCARD_S_SUCCESS) {
					CACKEY_DEBUG_PRINTF("Retransmit failed, returning in failure after disconnecting the card (SCardTransmit = %s/%li)", CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(scard_xmit_ret), (long) scard_xmit_ret);

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

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

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

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

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

			CACKEY_DEBUG_PRINTF("Returning in failure");
			return(-1);
			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 */
		CACKEY_DEBUG_PRINTF("Response too small, returning in failure (recv_len = %lu)", (unsigned long) recv_len);

		return(-1);
		return(CACKEY_PCSC_E_GENERIC);
	}

	/* Determine result code */
	major_rc = recv_buf[recv_len - 2];
	minor_rc = recv_buf[recv_len - 1];
	if (respcode) {
		*respcode = (major_rc << 8) | minor_rc;
806
807
808
809
810
811
812
813

814
815
816

817
818
819
820
821
822
823
824

825
826
827
828
829
830
831

832
833
834
835
836
837

838
839
840
841
842
843
844
809
810
811
812
813
814
815

816
817
818

819
820
821
822
823
824
825
826

827
828
829
830
831
832
833

834
835
836
837
838
839

840
841
842
843
844
845
846
847







-
+


-
+







-
+






-
+





-
+







	}

	if (major_rc == 0x61) {
		/* We need to READ */
		CACKEY_DEBUG_PRINTF("Buffer read required");

		pcsc_getresp_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_GET_RESPONSE, 0x00, 0x00, 0, NULL, minor_rc, respcode, respdata, &tmp_respdata_len);
		if (pcsc_getresp_ret < 0) {
		if (pcsc_getresp_ret != CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("Buffer read failed!  Returning in failure");

			return(-1);
			return(CACKEY_PCSC_E_GENERIC);
		}

		if (respdata_len) {
			*respdata_len += tmp_respdata_len;
		}

		CACKEY_DEBUG_PRINTF("Returning in success (buffer read complete)");
		return(0);
		return(CACKEY_PCSC_S_OK);
	}

	if (major_rc == 0x90) {
		/* Success */
		CACKEY_DEBUG_PRINTF("Returning in success (major_rc = 0x90)");

		return(0);
		return(CACKEY_PCSC_S_OK);
	}


	CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure");

	return(-1);
	return(CACKEY_PCSC_E_GENERIC);
}

static ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset) {
	size_t offset = 0, max_offset, max_count;
	unsigned char cmd[2];
	uint16_t respcode;
	int send_ret;
861
862
863
864
865
866
867
868

869
870
871
872
873
874
875
864
865
866
867
868
869
870

871
872
873
874
875
876
877
878







-
+







		if (count > max_count) {
			count = max_count;
		}

		cmd[1] = count;

		send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_READ_BUFFER, ((initial_offset + offset) >> 8) & 0xff, (initial_offset + offset) & 0xff, sizeof(cmd), cmd, 0x00, &respcode, buffer + offset, &count);
		if (send_ret < 0) {
		if (send_ret != CACKEY_PCSC_S_OK) {
			if (respcode == 0x6A86) {
				if (max_count == 1) {
					break;
				}

				max_count = max_count / 2;

891
892
893
894
895
896
897
898

899
900
901
902
903
904
905
906

907
908
909

910
911
912
913
914

915
916
917

918
919
920
921
922
923
924
925
926
927
928
929
930

931
932
933

934
935
936
937
938

939
940
941
942
943
944
945
894
895
896
897
898
899
900

901
902
903
904
905
906
907
908

909
910
911

912
913
914
915
916

917
918
919

920
921
922
923
924
925
926
927
928
929
930
931
932

933
934
935

936
937
938
939
940

941
942
943
944
945
946
947
948







-
+







-
+


-
+




-
+


-
+












-
+


-
+




-
+







	}

	CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) offset);

	return(offset);
}

static int cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) {
static cackey_ret cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) {
	int send_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	CACKEY_DEBUG_PRINTBUF("Selecting applet:", aid, aid_len);

	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, GSCIS_PARAM_SELECT_APPLET, 0x0C, aid_len, aid, 0x00, NULL, NULL, NULL);
	if (send_ret < 0) {
	if (send_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Failed to open applet, returning in failure");

		return(-1);
		return(CACKEY_PCSC_E_GENERIC);
	}

	CACKEY_DEBUG_PRINTF("Successfully selected file");

	return(0);
	return(CACKEY_PCSC_S_OK);
}

static int cackey_select_file(struct cackey_slot *slot, uint16_t ef) {
static cackey_ret cackey_select_file(struct cackey_slot *slot, uint16_t ef) {
	unsigned char fid_buf[2];
	int send_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	/* Open the elementary file */
	fid_buf[0] = (ef >> 8) & 0xff;
	fid_buf[1] = ef & 0xff;

	CACKEY_DEBUG_PRINTF("Selecting file: %04lx", (unsigned long) ef);

	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_SELECT, 0x02, 0x0C, sizeof(fid_buf), fid_buf, 0x00, NULL, NULL, NULL);
	if (send_ret < 0) {
	if (send_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Failed to open file, returning in failure");

		return(-1);
		return(CACKEY_PCSC_E_GENERIC);
	}

	CACKEY_DEBUG_PRINTF("Successfully selected file");

	return(0);
	return(CACKEY_PCSC_S_OK);
}

static void cackey_free_tlv(struct cackey_tlv_entity *root) {
	struct cackey_tlv_entity *curr, *next;

	if (root == NULL) {
		return;
1167
1168
1169
1170
1171
1172
1173
1174

1175
1176
1177
1178
1179
1180
1181
1170
1171
1172
1173
1174
1175
1176

1177
1178
1179
1180
1181
1182
1183
1184







-
+







		certs_resizable = 1;
	} else {
		certs_resizable = 0;
	}

	/* Select the CCC Applet */
	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
	if (send_ret < 0) {
	if (send_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");

		return(NULL);
	}

	/* Read all the applets from the CCC's TLV */
	ccc_tlv = cackey_read_tlv(slot);
1202
1203
1204
1205
1206
1207
1208
1209

1210
1211
1212
1213
1214
1215
1216
1217

1218
1219
1220
1221
1222
1223
1224
1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
1219

1220
1221
1222
1223
1224
1225
1226
1227







-
+







-
+








		memcpy(curr_aid, ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
		curr_aid[sizeof(curr_aid) - 2] = (ccc_curr->value_cardurl->appid >> 8) & 0xff;
		curr_aid[sizeof(curr_aid) - 1] = ccc_curr->value_cardurl->appid & 0xff;

		/* Select found applet ... */
		select_ret = cackey_select_applet(slot, curr_aid, sizeof(curr_aid));
		if (select_ret < 0) {
		if (select_ret != CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("Failed to select applet, skipping processing of this object");

			continue;
		}

		/* ... and object (file) */
		select_ret = cackey_select_file(slot, ccc_curr->value_cardurl->objectid);
		if (select_ret < 0) {
		if (select_ret != CACKEY_PCSC_S_OK) {
			CACKEY_DEBUG_PRINTF("Failed to select file, skipping processing of this object");

			continue;
		}

		/* Process this file's TLV looking for certificates */
		app_tlv = cackey_read_tlv(slot);
1267
1268
1269
1270
1271
1272
1273
1274

1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286

1287
1288
1289
1290
1291
1292
1293
1294


1295
1296
1297


1298
1299
1300
1301
1302







1303
1304

1305
1306
1307
1308

1309
1310
1311
1312
1313
1314
1315


1316
1317
1318

1319
1320
1321
1322
1323
1324
1325
1270
1271
1272
1273
1274
1275
1276

1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288

1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304





1305
1306
1307
1308
1309
1310
1311
1312

1313
1314
1315
1316

1317
1318
1319
1320
1321
1322


1323
1324
1325
1326

1327
1328
1329
1330
1331
1332
1333
1334







-
+











-
+








+
+



+
+
-
-
-
-
-
+
+
+
+
+
+
+

-
+



-
+





-
-
+
+


-
+







	if (certs_resizable) {
		certs = realloc(certs, sizeof(*certs) * (*count));
	}

	return(certs);
}

static int cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) {
static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) {
	uint16_t response_code;
	int tries_remaining;
	int send_ret;

	/* Indicate that we do not know about how many tries are remaining */
	if (tries_remaining_p) {
		*tries_remaining_p = -1;
	}

	/* Issue PIN Verify */
	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_VERIFY, 0x00, 0x00, pin_len, pin, 0x00, &response_code, NULL, NULL);
	if (send_ret < 0) {
	if (send_ret != CACKEY_PCSC_S_OK) {
		if ((response_code & 0x63C0) == 0x63C0) {
			tries_remaining = (response_code & 0xF);

			CACKEY_DEBUG_PRINTF("PIN Verification failed, %i tries remaining", tries_remaining);

			if (tries_remaining_p) {
				*tries_remaining_p = tries_remaining;
			}

			return(CACKEY_PCSC_E_BADPIN);
		}

		if (response_code == 0x6983) {
			CACKEY_DEBUG_PRINTF("PIN Verification failed, device is locked");

			return(CACKEY_LOGIN_LOCKED);
		} else {
			return(CACKEY_LOGIN_BADPIN);
		}
	}
			return(CACKEY_PCSC_E_LOCKED);
		}

		return(CACKEY_PCSC_E_GENERIC);
	}

	CACKEY_DEBUG_PRINTF("PIN Verification succeeded");

	return(CACKEY_LOGIN_OK);
	return(CACKEY_PCSC_S_OK);
}

/* Returns 1 if a token is in the specified slot, 0 otherwise */
static int cackey_token_present(struct cackey_slot *slot) {
static cackey_ret cackey_token_present(struct cackey_slot *slot) {
	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
	int send_ret;

	/* Select the CCC Applet */
	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
	if (send_ret < 0) {
		return(0);
	if (send_ret != CACKEY_PCSC_S_OK) {
		return(CACKEY_PCSC_S_TOKENABSENT);
	}

	return(1);
	return(CACKEY_PCSC_S_TOKENPRESENT);
}

/* Returns 0 on success */
static int cackey_mutex_create(void **mutex) {
	pthread_mutex_t *pthread_mutex;
	int pthread_retval;
	CK_RV custom_retval;
1961
1962
1963
1964
1965
1966
1967
1968

1969
1970
1971
1972
1973
1974
1975
1970
1971
1972
1973
1974
1975
1976

1977
1978
1979
1980
1981
1982
1983
1984







-
+








			cackey_slots[currslot].active = 0;
		}
	}

	/* Determine list of readers */
	pcsc_connect_ret = cackey_pcsc_connect();
	if (pcsc_connect_ret < 0) {
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, assuming no slots");

		slot_count = 0;
	} else {
		pcsc_readers_len = 0;

		scard_listreaders_ret = SCardListReaders(*cackey_pcsc_handle, NULL, NULL, &pcsc_readers_len);
2099
2100
2101
2102
2103
2104
2105
2106

2107
2108
2109
2110
2111
2112
2113
2108
2109
2110
2111
2112
2113
2114

2115
2116
2117
2118
2119
2120
2121
2122







-
+







	if (sizeof(pInfo->manufacturerID) < bytes_to_copy) {
		bytes_to_copy = sizeof(pInfo->manufacturerID);
	}
	memcpy(pInfo->manufacturerID, cackey_slots[slotID].pcsc_reader, bytes_to_copy);

	pInfo->flags = 0;

	if (cackey_token_present(&cackey_slots[slotID])) {
	if (cackey_token_present(&cackey_slots[slotID]) == CACKEY_PCSC_S_TOKENPRESENT) {
		pInfo->flags |= CKF_TOKEN_PRESENT;
	}

	pInfo->hardwareVersion.major = (cackey_getversion() >> 16) & 0xff;
	pInfo->hardwareVersion.minor = (cackey_getversion() >> 8) & 0xff;

	pInfo->firmwareVersion.major = 0x00;
2145
2146
2147
2148
2149
2150
2151
2152

2153
2154
2155
2156
2157
2158
2159
2154
2155
2156
2157
2158
2159
2160

2161
2162
2163
2164
2165
2166
2167
2168







-
+








	if (!cackey_initialized) {
		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");

		return(CKR_CRYPTOKI_NOT_INITIALIZED);
	}

	if (!cackey_token_present(&cackey_slots[slotID])) {
	if (cackey_token_present(&cackey_slots[slotID]) != CACKEY_PCSC_S_TOKENPRESENT) {
		CACKEY_DEBUG_PRINTF("No token is present in slotID = %lu", slotID);

		return(CKR_TOKEN_NOT_PRESENT);
	}

	memset(pInfo->label, ' ', sizeof(pInfo->label));
	if (1) {
2375
2376
2377
2378
2379
2380
2381
2382

2383
2384
2385
2386
2387
2388
2389
2384
2385
2386
2387
2388
2389
2390

2391
2392
2393
2394
2395
2396
2397
2398







-
+







	if (!cackey_initialized) {
		CACKEY_DEBUG_PRINTF("Error.  Not initialized.");

		return(CKR_CRYPTOKI_NOT_INITIALIZED);
	}

	/* Verify that the card is actually in the slot. */
	if (!cackey_token_present(&cackey_slots[slotID])) {
	if (cackey_token_present(&cackey_slots[slotID]) != CACKEY_PCSC_S_TOKENPRESENT) {
		CACKEY_DEBUG_PRINTF("Error.  Card not present.  Returning CKR_DEVICE_REMOVED");

		return(CKR_DEVICE_REMOVED);
	}

	mutex_retval = cackey_mutex_lock(cackey_biglock);
	if (mutex_retval != 0) {
2676
2677
2678
2679
2680
2681
2682
2683

2684
2685
2686

2687
2688
2689
2690

2691
2692
2693
2694




2695
2696
2697
2698
2699
2700
2701
2685
2686
2687
2688
2689
2690
2691

2692
2693
2694

2695
2696
2697
2698

2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714







-
+


-
+



-
+




+
+
+
+








		CACKEY_DEBUG_PRINTF("Error.  Session not active.");
		
		return(CKR_SESSION_HANDLE_INVALID);
	}

	login_ret = cackey_login(&cackey_slots[cackey_sessions[hSession].slotID], pPin, ulPinLen, NULL);
	if (login_ret != CACKEY_LOGIN_OK) {
	if (login_ret != CACKEY_PCSC_S_OK) {
		cackey_mutex_unlock(cackey_biglock);

		if (login_ret == CACKEY_LOGIN_LOCKED) {
		if (login_ret == CACKEY_PCSC_E_LOCKED) {
			CACKEY_DEBUG_PRINTF("Error.  Token is locked.");

			return(CKR_PIN_LOCKED);
		} else {
		} else if (login_ret == CACKEY_PCSC_E_BADPIN) {
			CACKEY_DEBUG_PRINTF("Error.  Invalid PIN.");

			return(CKR_PIN_INCORRECT);
		}

		CACKEY_DEBUG_PRINTF("Error.  Unknown error returned from cackey_login() (%i)", login_ret);

		return(CKR_GENERAL_ERROR);
	}

	cackey_sessions[hSession].state = CKS_RO_USER_FUNCTIONS;

	mutex_retval = cackey_mutex_unlock(cackey_biglock);
	if (mutex_retval != 0) {
		CACKEY_DEBUG_PRINTF("Error.  Unlocking failed.");