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    689   	}
   690    690   #endif
   691    691   
   692    692   	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");
   693    693   
   694    694   	return(CACKEY_PCSC_S_OK);
   695    695   }
          696  +
          697  +/*
          698  + * SYNPOSIS
          699  + *     cackey_ret cackey_connect_card(struct cackey_slot *slot);
          700  + *
          701  + * ARGUMENTS
          702  + *     cackey_slot *slot
          703  + *         Slot to send commands to
          704  + *
          705  + * RETURN VALUE
          706  + *     CACKEY_PCSC_S_OK         On success
          707  + *     CACKEY_PCSC_E_GENERIC    On error
          708  + *
          709  + * NOTES
          710  + *     None
          711  + *
          712  + */
          713  +static cackey_ret cackey_connect_card(struct cackey_slot *slot) {
          714  +	cackey_ret pcsc_connect_ret;
          715  +	DWORD protocol;
          716  +	LONG scard_conn_ret;
          717  +
          718  +	CACKEY_DEBUG_PRINTF("Called.");
          719  +
          720  +	if (!slot) {
          721  +		CACKEY_DEBUG_PRINTF("Invalid slot specified, returning in failure");
          722  +
          723  +		return(CACKEY_PCSC_E_GENERIC);
          724  +	}
          725  +
          726  +	pcsc_connect_ret = cackey_pcsc_connect();
          727  +	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
          728  +		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");
          729  +
          730  +		return(CACKEY_PCSC_E_GENERIC);
          731  +	}
          732  +
          733  +	/* Connect to reader, if needed */
          734  +	if (!slot->pcsc_card_connected) {
          735  +		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader);
          736  +		scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol);
          737  +
          738  +		if (scard_conn_ret != SCARD_S_SUCCESS) {
          739  +			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);
          740  +
          741  +			return(CACKEY_PCSC_E_GENERIC);
          742  +		}
          743  +
          744  +		slot->pcsc_card_connected = 1;
          745  +	}
          746  +
          747  +	return(CACKEY_PCSC_S_OK);
          748  +}
          749  +
          750  +/*
          751  + * SYNPOSIS
          752  + *     cackey_ret cackey_begin_transaction(struct cackey_slot *slot);
          753  + *
          754  + * ARGUMENTS
          755  + *     cackey_slot *slot
          756  + *         Slot to send commands to
          757  + *
          758  + * RETURN VALUE
          759  + *     CACKEY_PCSC_S_OK         On success
          760  + *     CACKEY_PCSC_E_GENERIC    On error
          761  + *
          762  + * NOTES
          763  + *     The transaction should be terminated using "cackey_end_transaction"
          764  + *
          765  + */
          766  +static cackey_ret cackey_begin_transaction(struct cackey_slot *slot) {
          767  +	cackey_ret cackey_conn_ret;
          768  +	LONG scard_trans_ret;
          769  +
          770  +	CACKEY_DEBUG_PRINTF("Called.");
          771  +
          772  +	cackey_conn_ret = cackey_connect_card(slot);
          773  +	if (cackey_conn_ret != CACKEY_PCSC_S_OK) {
          774  +		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in error");
          775  +
          776  +		return(CACKEY_PCSC_E_GENERIC);
          777  +	}
          778  +
          779  +	scard_trans_ret = SCardBeginTransaction(slot->pcsc_card);
          780  +	if (scard_trans_ret != SCARD_S_SUCCESS) {
          781  +		CACKEY_DEBUG_PRINTF("Unable to begin transaction, returning in error");
          782  +
          783  +		return(CACKEY_PCSC_E_GENERIC);
          784  +	}
          785  +
          786  +	return(CACKEY_PCSC_S_OK);
          787  +}
          788  +
          789  +/*
          790  + * SYNPOSIS
          791  + *     cackey_ret cackey_end_transaction(struct cackey_slot *slot);
          792  + *
          793  + * ARGUMENTS
          794  + *     cackey_slot *slot
          795  + *         Slot to send commands to
          796  + *
          797  + * RETURN VALUE
          798  + *     CACKEY_PCSC_S_OK         On success
          799  + *     CACKEY_PCSC_E_GENERIC    On error
          800  + *
          801  + * NOTES
          802  + *     This function requires "cackey_begin_transaction" to be called first
          803  + *
          804  + */
          805  +static cackey_ret cackey_end_transaction(struct cackey_slot *slot) {
          806  +	LONG scard_trans_ret;
          807  +
          808  +	CACKEY_DEBUG_PRINTF("Called.");
          809  +
          810  +	if (!slot->pcsc_card_connected) {
          811  +		CACKEY_DEBUG_PRINTF("Card is not connected, unable to end transaction");
          812  +
          813  +		return(CACKEY_PCSC_E_GENERIC);
          814  +	}
          815  +
          816  +	scard_trans_ret = SCardEndTransaction(slot->pcsc_card, SCARD_LEAVE_CARD);
          817  +	if (scard_trans_ret != SCARD_S_SUCCESS) {
          818  +		CACKEY_DEBUG_PRINTF("Unable to end transaction, returning in error");
          819  +
          820  +		return(CACKEY_PCSC_E_GENERIC);
          821  +	}
          822  +
          823  +	return(CACKEY_PCSC_S_OK);
          824  +}
   696    825   
   697    826   /* APDU Related Functions */
   698    827   /*
   699    828    * SYNPOSIS
   700    829    *     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);
   701    830    *
   702    831    * ARGUMENTS
................................................................................
   762    891    *
   763    892    */
   764    893   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) {
   765    894   	uint8_t major_rc, minor_rc;
   766    895   	size_t bytes_to_copy, tmp_respdata_len;
   767    896   	DWORD protocol;
   768    897   	DWORD xmit_len, recv_len;
   769         -	LONG scard_conn_ret, scard_xmit_ret, scard_reconn_ret;
          898  +	LONG scard_xmit_ret, scard_reconn_ret;
   770    899   	BYTE xmit_buf[1024], recv_buf[1024];
   771    900   	int pcsc_connect_ret, pcsc_getresp_ret;
   772    901   	int idx;
   773    902   
   774    903   	CACKEY_DEBUG_PRINTF("Called.");
   775    904   
   776    905   	if (!slot) {
   777    906   		CACKEY_DEBUG_PRINTF("Invalid slot specified.");
   778    907   
   779    908   		return(CACKEY_PCSC_E_GENERIC);
   780    909   	}
   781    910   
   782         -	pcsc_connect_ret = cackey_pcsc_connect();
          911  +	pcsc_connect_ret = cackey_connect_card(slot);
   783    912   	if (pcsc_connect_ret != CACKEY_PCSC_S_OK) {
   784         -		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");
          913  +		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in failure");
   785    914   
   786    915   		return(CACKEY_PCSC_E_GENERIC);
   787    916   	}
   788    917   
   789         -	/* Connect to reader, if needed */
   790         -	if (!slot->pcsc_card_connected) {
   791         -		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader);
   792         -		scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol);
   793         -
   794         -		if (scard_conn_ret != SCARD_S_SUCCESS) {
   795         -			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);
   796         -
   797         -			return(CACKEY_PCSC_E_GENERIC);
   798         -		}
   799         -
   800         -		slot->pcsc_card_connected = 1;
   801         -	}
   802         -
   803    918   	/* Transmit */
   804    919   	xmit_len = 0;
   805    920   	xmit_buf[xmit_len++] = class;
   806    921   	xmit_buf[xmit_len++] = instruction;
   807    922   	xmit_buf[xmit_len++] = p1;
   808    923   	xmit_buf[xmit_len++] = p2;
   809    924   	if (data) {
................................................................................
  1392   1507   		if (certs != NULL) {
  1393   1508   			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");
  1394   1509   
  1395   1510   			return(certs);
  1396   1511   		}
  1397   1512   	}
  1398   1513   
         1514  +	/* Begin a SmartCard transaction */
         1515  +	cackey_begin_transaction(slot);
         1516  +
  1399   1517   	if (certs == NULL) {
  1400   1518   		certs = malloc(sizeof(*certs) * 5);
  1401   1519   		*count = 5;
  1402   1520   		certs_resizable = 1;
  1403   1521   	} else {
  1404   1522   		certs_resizable = 0;
  1405   1523   	}
  1406   1524   
  1407   1525   	/* Select the CCC Applet */
  1408   1526   	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
  1409   1527   	if (send_ret != CACKEY_PCSC_S_OK) {
  1410   1528   		CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");
         1529  +
         1530  +		/* Terminate SmartCard Transaction */
         1531  +		cackey_end_transaction(slot);
  1411   1532   
  1412   1533   		return(NULL);
  1413   1534   	}
  1414   1535   
  1415   1536   	/* Read all the applets from the CCC's TLV */
  1416   1537   	ccc_tlv = cackey_read_tlv(slot);
  1417   1538   
................................................................................
  1498   1619   	cackey_free_tlv(ccc_tlv);
  1499   1620   
  1500   1621   	*count = outidx;
  1501   1622   
  1502   1623   	if (certs_resizable) {
  1503   1624   		certs = realloc(certs, sizeof(*certs) * (*count));
  1504   1625   	}
         1626  +
         1627  +	/* Terminate SmartCard Transaction */
         1628  +	cackey_end_transaction(slot);
  1505   1629   
  1506   1630   	return(certs);
  1507   1631   }
  1508   1632   
  1509   1633   /*
  1510   1634    * SYNPOSIS
  1511   1635    *     ...