Check-in [43170e1dd9]
Overview
Comment:Updated transactional support to recursive transactions
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:43170e1dd99babbfe0a27ad35c71934da6fff560
User & Date: rkeene on 2010-05-14 03:28:41
Other Links: manifest | tags
Context
2010-05-14
03:32
Updated transaction support check-in: c2e40da095 user: rkeene tags: trunk
03:28
Updated transactional support to recursive transactions check-in: 43170e1dd9 user: rkeene tags: trunk
02:34
Put all calls to functions that talk to the smartcard inside the big global mutex check-in: da2b17a36c user: rkeene tags: trunk
Changes

Modified cackey.c from [38178200a5] to [0fee951b43].

   481    481   struct cackey_slot {
   482    482   	int active;
   483    483   
   484    484   	char *pcsc_reader;
   485    485   
   486    486   	int pcsc_card_connected;
   487    487   	SCARDHANDLE pcsc_card;
          488  +
          489  +	int transaction_depth;
   488    490   };
   489    491   
   490    492   typedef enum {
   491    493   	CACKEY_TLV_APP_GENERIC = 0x01,
   492    494   	CACKEY_TLV_APP_SKI     = 0x02,
   493    495   	CACKEY_TLV_APP_PKI     = 0x04
   494    496   } cackey_tlv_apptype;
................................................................................
   738    740   		if (scard_conn_ret != SCARD_S_SUCCESS) {
   739    741   			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    742   
   741    743   			return(CACKEY_PCSC_E_GENERIC);
   742    744   		}
   743    745   
   744    746   		slot->pcsc_card_connected = 1;
          747  +		slot->transaction_depth = 0;
   745    748   	}
   746    749   
   747    750   	return(CACKEY_PCSC_S_OK);
   748    751   }
   749    752   
   750    753   /*
   751    754    * SYNPOSIS
................................................................................
   771    774   
   772    775   	cackey_conn_ret = cackey_connect_card(slot);
   773    776   	if (cackey_conn_ret != CACKEY_PCSC_S_OK) {
   774    777   		CACKEY_DEBUG_PRINTF("Unable to connect to card, returning in error");
   775    778   
   776    779   		return(CACKEY_PCSC_E_GENERIC);
   777    780   	}
          781  +
          782  +	slot->transaction_depth++;
          783  +
          784  +	if (slot->transaction_depth > 1) {
          785  +		CACKEY_DEBUG_PRINTF("Already in a transaction, performing no action (new depth = %i)", slot->transaction_depth);
          786  +
          787  +		return(CACKEY_PCSC_S_OK);
          788  +	}
   778    789   
   779    790   	scard_trans_ret = SCardBeginTransaction(slot->pcsc_card);
   780    791   	if (scard_trans_ret != SCARD_S_SUCCESS) {
   781    792   		CACKEY_DEBUG_PRINTF("Unable to begin transaction, returning in error");
   782    793   
   783    794   		return(CACKEY_PCSC_E_GENERIC);
   784    795   	}
          796  +
          797  +	CACKEY_DEBUG_PRINTF("Sucessfully began transaction on slot (%s)", slot->pcsc_reader);
   785    798   
   786    799   	return(CACKEY_PCSC_S_OK);
   787    800   }
   788    801   
   789    802   /*
   790    803    * SYNPOSIS
   791    804    *     cackey_ret cackey_end_transaction(struct cackey_slot *slot);
................................................................................
   808    821   	CACKEY_DEBUG_PRINTF("Called.");
   809    822   
   810    823   	if (!slot->pcsc_card_connected) {
   811    824   		CACKEY_DEBUG_PRINTF("Card is not connected, unable to end transaction");
   812    825   
   813    826   		return(CACKEY_PCSC_E_GENERIC);
   814    827   	}
          828  +
          829  +	if (slot->transaction_depth == 0) {
          830  +		CACKEY_DEBUG_PRINTF("Terminating a transaction that has not begun!");
          831  +
          832  +		return(CACKEY_PCSC_E_GENERIC);
          833  +	}
          834  +
          835  +	slot->transaction_depth--;
          836  +
          837  +	if (slot->transaction_depth > 0) {
          838  +		CACKEY_DEBUG_PRINTF("Transactions still in progress, not terminating on-card Transaction (current depth = %i)", slot->transaction_depth);
          839  +
          840  +		return(CACKEY_PCSC_E_GENERIC);
          841  +	}
   815    842   
   816    843   	scard_trans_ret = SCardEndTransaction(slot->pcsc_card, SCARD_LEAVE_CARD);
   817    844   	if (scard_trans_ret != SCARD_S_SUCCESS) {
   818    845   		CACKEY_DEBUG_PRINTF("Unable to end transaction, returning in error");
   819    846   
   820    847   		return(CACKEY_PCSC_E_GENERIC);
   821    848   	}
          849  +
          850  +	CACKEY_DEBUG_PRINTF("Sucessfully terminated transaction on slot (%s)", slot->pcsc_reader);
   822    851   
   823    852   	return(CACKEY_PCSC_S_OK);
   824    853   }
   825    854   
   826    855   /* APDU Related Functions */
   827    856   /*
   828    857    * SYNPOSIS
................................................................................
   927    956   			xmit_buf[xmit_len++] = data[idx];
   928    957   		}
   929    958   	}
   930    959   
   931    960   	if (le != 0x00) {
   932    961   		xmit_buf[xmit_len++] = le;
   933    962   	}
          963  +
          964  +	/* Begin Smartcard Transaction */
          965  +	cackey_begin_transaction(slot);
   934    966   
   935    967   	CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);
   936    968   
   937    969   	recv_len = sizeof(recv_buf);
   938    970   	scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T1, recv_buf, &recv_len);
   939    971   	if (scard_xmit_ret != SCARD_S_SUCCESS) {
   940    972   		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);
          973  +
          974  +		slot->transaction_depth = 0;
   941    975   
   942    976   		if (scard_xmit_ret == SCARD_W_RESET_CARD) {
   943    977   			CACKEY_DEBUG_PRINTF("Reset required, please hold...");
   944    978   
   945    979   			scard_reconn_ret = SCardReconnect(slot->pcsc_card, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, SCARD_RESET_CARD, &protocol);
   946    980   			if (scard_reconn_ret == SCARD_S_SUCCESS) {
          981  +				/* Re-establish transaction, if it was present */
          982  +				if (slot->transaction_depth > 0) {
          983  +					slot->transaction_depth--;
          984  +					cackey_begin_transaction(slot);
          985  +				}
          986  +
   947    987   				CACKEY_DEBUG_PRINTF("Reset successful, retransmitting");
   948    988   				scard_xmit_ret = SCardTransmit(slot->pcsc_card, SCARD_PCI_T0, xmit_buf, xmit_len, SCARD_PCI_T0, recv_buf, &recv_len);
   949    989   
   950    990   				if (scard_xmit_ret != SCARD_S_SUCCESS) {
   951    991   					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);
   952    992   
   953    993   					SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
   954    994   					slot->pcsc_card_connected = 0;
          995  +
          996  +					/* End Smartcard Transaction */
          997  +					slot->transaction_depth = 1;
          998  +					cackey_end_transaction(slot);
   955    999   
   956   1000   					return(CACKEY_PCSC_E_GENERIC);
   957   1001   				}
   958   1002   			} else {
   959   1003   				CACKEY_DEBUG_PRINTF("Disconnecting card");
   960   1004   
   961   1005   				SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
   962   1006   				slot->pcsc_card_connected = 0;
         1007  +
         1008  +				/* End Smartcard Transaction */
         1009  +				slot->transaction_depth = 1;
         1010  +				cackey_end_transaction(slot);
   963   1011   
   964   1012   				CACKEY_DEBUG_PRINTF("Returning in failure");
   965   1013   				return(CACKEY_PCSC_E_GENERIC);
   966   1014   			}
   967   1015   		} else {
   968   1016   			CACKEY_DEBUG_PRINTF("Disconnecting card");
   969   1017   
   970   1018   			SCardDisconnect(slot->pcsc_card, SCARD_RESET_CARD);
   971   1019   			slot->pcsc_card_connected = 0;
         1020  +
         1021  +			/* End Smartcard Transaction */
         1022  +			slot->transaction_depth = 1;
         1023  +			cackey_end_transaction(slot);
   972   1024   
   973   1025   			CACKEY_DEBUG_PRINTF("Returning in failure");
   974   1026   			return(CACKEY_PCSC_E_GENERIC);
   975   1027   		}
   976   1028   	}
   977   1029   
   978   1030   	CACKEY_DEBUG_PRINTBUF("Returned Value:", recv_buf, recv_len);
   979   1031   
   980   1032   	if (recv_len < 2) {
   981   1033   		/* Minimal response length is 2 bytes, returning in failure */
   982   1034   		CACKEY_DEBUG_PRINTF("Response too small, returning in failure (recv_len = %lu)", (unsigned long) recv_len);
         1035  +
         1036  +		/* End Smartcard Transaction */
         1037  +		cackey_end_transaction(slot);
   983   1038   
   984   1039   		return(CACKEY_PCSC_E_GENERIC);
   985   1040   	}
   986   1041   
   987   1042   	/* Determine result code */
   988   1043   	major_rc = recv_buf[recv_len - 2];
   989   1044   	minor_rc = recv_buf[recv_len - 1];
................................................................................
  1021   1076   	if (major_rc == 0x61) {
  1022   1077   		/* We need to READ */
  1023   1078   		CACKEY_DEBUG_PRINTF("Buffer read required");
  1024   1079   
  1025   1080   		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);
  1026   1081   		if (pcsc_getresp_ret != CACKEY_PCSC_S_OK) {
  1027   1082   			CACKEY_DEBUG_PRINTF("Buffer read failed!  Returning in failure");
         1083  +
         1084  +			/* End Smartcard Transaction */
         1085  +			cackey_end_transaction(slot);
  1028   1086   
  1029   1087   			return(CACKEY_PCSC_E_GENERIC);
  1030   1088   		}
  1031   1089   
  1032   1090   		if (respdata_len) {
  1033   1091   			*respdata_len += tmp_respdata_len;
  1034   1092   		}
         1093  +
         1094  +		/* End Smartcard Transaction */
         1095  +		cackey_end_transaction(slot);
  1035   1096   
  1036   1097   		CACKEY_DEBUG_PRINTF("Returning in success (buffer read complete)");
  1037   1098   		return(CACKEY_PCSC_S_OK);
  1038   1099   	}
         1100  +
         1101  +	/* End Smartcard Transaction */
         1102  +	cackey_end_transaction(slot);
  1039   1103   
  1040   1104   	if (major_rc == 0x90) {
  1041   1105   		/* Success */
  1042   1106   		CACKEY_DEBUG_PRINTF("Returning in success (major_rc = 0x90)");
  1043   1107   
  1044   1108   		return(CACKEY_PCSC_S_OK);
  1045   1109   	}
................................................................................
  1488   1552    */
  1489   1553   static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
  1490   1554   	struct cackey_pcsc_identity *curr_id;
  1491   1555   	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
  1492   1556   	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
  1493   1557   	unsigned char curr_aid[7];
  1494   1558   	unsigned long outidx = 0;
         1559  +	cackey_ret transaction_ret;
  1495   1560   	int certs_resizable;
  1496   1561   	int send_ret, select_ret;
  1497   1562   
  1498   1563   	CACKEY_DEBUG_PRINTF("Called.");
  1499   1564   
  1500   1565   	if (count == NULL) {
  1501   1566   		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");
................................................................................
  1508   1573   			CACKEY_DEBUG_PRINTF("Requested we return 0 objects, short-circuit");
  1509   1574   
  1510   1575   			return(certs);
  1511   1576   		}
  1512   1577   	}
  1513   1578   
  1514   1579   	/* Begin a SmartCard transaction */
  1515         -	cackey_begin_transaction(slot);
         1580  +	transaction_ret = cackey_begin_transaction(slot);
         1581  +	if (transaction_ret != CACKEY_PCSC_S_OK) {
         1582  +		CACKEY_DEBUG_PRINTF("Unable begin transaction, returning in failure");
         1583  +
         1584  +		return(NULL);
         1585  +	}
  1516   1586   
  1517   1587   	if (certs == NULL) {
  1518   1588   		certs = malloc(sizeof(*certs) * 5);
  1519   1589   		*count = 5;
  1520   1590   		certs_resizable = 1;
  1521   1591   	} else {
  1522   1592   		certs_resizable = 0;