Check-in [fab9cf1772]
Overview
Comment:Added transaction support

Updated reading certs to be transactional

Added function to connect to card

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fab9cf1772ff4212316ff46ec9bf9f86c7efd762
User & Date: rkeene on 2010-05-14 02:16:14
Other Links: manifest | tags
Context
2010-05-14
02:34
Put all calls to functions that talk to the smartcard inside the big global mutex check-in: da2b17a36c user: rkeene tags: trunk
02:16
Added transaction support

Updated reading certs to be transactional

Added function to connect to card check-in: fab9cf1772 user: rkeene tags: trunk

00:56
Added comments

Updated buffer name in PRINTBUF to avoid aliases check-in: 11bf77ef42 user: rkeene tags: trunk

Changes

Modified cackey.c from [b9a7131d32] to [4f1f703fd4].

689
690
691
692
693
694
695

































































































































696
697
698
699
700
701
702
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
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
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
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







+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+







	}
#endif

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

	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_connect_card(struct cackey_slot *slot);
 *
 * ARGUMENTS
 *     cackey_slot *slot
 *         Slot to send commands to
 *
 * RETURN VALUE
 *     CACKEY_PCSC_S_OK         On success
 *     CACKEY_PCSC_E_GENERIC    On error
 *
 * NOTES
 *     None
 *
 */
static cackey_ret cackey_connect_card(struct cackey_slot *slot) {
	cackey_ret pcsc_connect_ret;
	DWORD protocol;
	LONG scard_conn_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (!slot) {
		CACKEY_DEBUG_PRINTF("Invalid slot specified, returning in failure");

		return(CACKEY_PCSC_E_GENERIC);
	}

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

		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(CACKEY_PCSC_E_GENERIC);
		}

		slot->pcsc_card_connected = 1;
	}

	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_begin_transaction(struct cackey_slot *slot);
 *
 * ARGUMENTS
 *     cackey_slot *slot
 *         Slot to send commands to
 *
 * RETURN VALUE
 *     CACKEY_PCSC_S_OK         On success
 *     CACKEY_PCSC_E_GENERIC    On error
 *
 * NOTES
 *     The transaction should be terminated using "cackey_end_transaction"
 *
 */
static cackey_ret cackey_begin_transaction(struct cackey_slot *slot) {
	cackey_ret cackey_conn_ret;
	LONG scard_trans_ret;

	CACKEY_DEBUG_PRINTF("Called.");

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

		return(CACKEY_PCSC_E_GENERIC);
	}

	scard_trans_ret = SCardBeginTransaction(slot->pcsc_card);
	if (scard_trans_ret != SCARD_S_SUCCESS) {
		CACKEY_DEBUG_PRINTF("Unable to begin transaction, returning in error");

		return(CACKEY_PCSC_E_GENERIC);
	}

	return(CACKEY_PCSC_S_OK);
}

/*
 * SYNPOSIS
 *     cackey_ret cackey_end_transaction(struct cackey_slot *slot);
 *
 * ARGUMENTS
 *     cackey_slot *slot
 *         Slot to send commands to
 *
 * RETURN VALUE
 *     CACKEY_PCSC_S_OK         On success
 *     CACKEY_PCSC_E_GENERIC    On error
 *
 * NOTES
 *     This function requires "cackey_begin_transaction" to be called first
 *
 */
static cackey_ret cackey_end_transaction(struct cackey_slot *slot) {
	LONG scard_trans_ret;

	CACKEY_DEBUG_PRINTF("Called.");

	if (!slot->pcsc_card_connected) {
		CACKEY_DEBUG_PRINTF("Card is not connected, unable to end transaction");

		return(CACKEY_PCSC_E_GENERIC);
	}

	scard_trans_ret = SCardEndTransaction(slot->pcsc_card, SCARD_LEAVE_CARD);
	if (scard_trans_ret != SCARD_S_SUCCESS) {
		CACKEY_DEBUG_PRINTF("Unable to end transaction, returning in error");

		return(CACKEY_PCSC_E_GENERIC);
	}

	return(CACKEY_PCSC_S_OK);
}

/* APDU Related Functions */
/*
 * SYNPOSIS
 *     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);
 *
 * ARGUMENTS
762
763
764
765
766
767
768
769

770
771
772
773
774
775
776
777
778
779
780
781
782

783
784

785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
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







-
+












-
+

-
+


-
-
-
-
-
-
-
-
-
-
-
-
-
-







 *
 */
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;
	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 (!slot) {
		CACKEY_DEBUG_PRINTF("Invalid slot specified.");

		return(CACKEY_PCSC_E_GENERIC);
	}

	pcsc_connect_ret = cackey_pcsc_connect();
	pcsc_connect_ret = cackey_connect_card(slot);
	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");
		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in failure");

		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(CACKEY_PCSC_E_GENERIC);
		}

		slot->pcsc_card_connected = 1;
	}

	/* Transmit */
	xmit_len = 0;
	xmit_buf[xmit_len++] = class;
	xmit_buf[xmit_len++] = instruction;
	xmit_buf[xmit_len++] = p1;
1392
1393
1394
1395
1396
1397
1398



1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410



1411
1412
1413
1414
1415
1416
1417
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538







+
+
+












+
+
+







		if (certs != NULL) {
			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");

			return(certs);
		}
	}

	/* Begin a SmartCard transaction */
	cackey_begin_transaction(slot);

	if (certs == NULL) {
		certs = malloc(sizeof(*certs) * 5);
		*count = 5;
		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 != CACKEY_PCSC_S_OK) {
		CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");

		/* Terminate SmartCard Transaction */
		cackey_end_transaction(slot);

		return(NULL);
	}

	/* Read all the applets from the CCC's TLV */
	ccc_tlv = cackey_read_tlv(slot);

1498
1499
1500
1501
1502
1503
1504



1505
1506
1507
1508
1509
1510
1511
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635







+
+
+







	cackey_free_tlv(ccc_tlv);

	*count = outidx;

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

	/* Terminate SmartCard Transaction */
	cackey_end_transaction(slot);

	return(certs);
}

/*
 * SYNPOSIS
 *     ...