Check-in [11bf77ef42]
Overview
Comment:Added comments

Updated buffer name in PRINTBUF to avoid aliases

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:11bf77ef42ad6879b630f97454e893b4ccbde387
User & Date: rkeene on 2010-05-14 00:56:32
Other Links: manifest | tags
Context
2010-05-14
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

2010-05-13
19:23
Removed incorrect comment check-in: a52326f02b user: rkeene tags: trunk
Changes

Modified cackey.c from [95e7747218] to [b9a7131d32].

   147    147   
   148    148   #ifdef CACKEY_DEBUG
   149    149   #  ifdef HAVE_STDIO_H
   150    150   #    include <stdio.h>
   151    151   #  endif
   152    152   
   153    153   #  define CACKEY_DEBUG_PRINTF(x...) { fprintf(stderr, "%s(): ", __func__); fprintf(stderr, x); fprintf(stderr, "\n"); }
   154         -#  define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *buf; unsigned long idx; buf = (unsigned char *) (x); fprintf(stderr, "%s(): %s  (%s/%lu = {%02x", __func__, f, #x, (unsigned long) (y), buf[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", buf[idx]); }; fprintf(stderr, "})\n"); }
          154  +#  define CACKEY_DEBUG_PRINTBUF(f, x, y) { unsigned char *TMPBUF; unsigned long idx; TMPBUF = (unsigned char *) (x); fprintf(stderr, "%s(): %s  (%s/%lu = {%02x", __func__, f, #x, (unsigned long) (y), TMPBUF[0]); for (idx = 1; idx < (y); idx++) { fprintf(stderr, ", %02x", TMPBUF[idx]); }; fprintf(stderr, "})\n"); }
   155    155   #  define CACKEY_DEBUG_PERROR(x) { fprintf(stderr, "%s(): ", __func__); perror(x); }
   156    156   #  define free(x) { CACKEY_DEBUG_PRINTF("FREE(%p) (%s)", x, #x); free(x); }
   157    157   
   158    158   static void *CACKEY_DEBUG_FUNC_MALLOC(size_t size, const char *func) {
   159    159   	void *retval;
   160    160   
   161    161   	retval = malloc(size);
................................................................................
   582    582   
   583    583   	CACKEY_DEBUG_PRINTF("Returning 0x%lx", retval);
   584    584   
   585    585   	return(retval);
   586    586   }
   587    587   
   588    588   /* PC/SC Related Functions */
          589  +/*
          590  + * SYNPOSIS
          591  + *     void cackey_slots_disconnect_all(void);
          592  + *
          593  + * ARGUMENTS
          594  + *     None
          595  + *
          596  + * RETURN VALUE
          597  + *     None
          598  + *
          599  + * NOTES
          600  + *     This function disconnects from all cards.
          601  + *
          602  + */
   589    603   static void cackey_slots_disconnect_all(void) {
   590    604   	uint32_t idx;
   591    605   
   592    606   	CACKEY_DEBUG_PRINTF("Called.");
   593    607   
   594    608   	for (idx = 0; idx < (sizeof(cackey_slots) / sizeof(cackey_slots[0])); idx++) {
   595    609   		if (cackey_slots[idx].pcsc_card_connected) {
................................................................................
   602    616   	}
   603    617   
   604    618   	CACKEY_DEBUG_PRINTF("Returning");
   605    619   
   606    620   	return;
   607    621   }
   608    622   
          623  +/*
          624  + * SYNPOSIS
          625  + *     cackey_ret cackey_pcsc_connect(void);
          626  + *
          627  + * ARGUMENTS
          628  + *     None
          629  + *
          630  + * RETURN VALUE
          631  + *     CACKEY_PCSC_S_OK         On success
          632  + *     CACKEY_PCSC_E_GENERIC    On error
          633  + *
          634  + * NOTES
          635  + *     This function connects to the PC/SC Connection Manager and updates the
          636  + *     global handle.
          637  + *
          638  + */
   609    639   static cackey_ret cackey_pcsc_connect(void) {
   610    640   	LONG scard_est_context_ret;
   611    641   #ifdef HAVE_SCARDISVALIDCONTEXT
   612    642   	LONG scard_isvalid_ret;
   613    643   #endif
   614    644   
   615    645   	CACKEY_DEBUG_PRINTF("Called.");
................................................................................
   661    691   
   662    692   	CACKEY_DEBUG_PRINTF("Sucessfully connected to PC/SC, returning in success");
   663    693   
   664    694   	return(CACKEY_PCSC_S_OK);
   665    695   }
   666    696   
   667    697   /* APDU Related Functions */
   668         -/** Le = 0x00 to indicate not to send Le **/
          698  +/*
          699  + * SYNPOSIS
          700  + *     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  + *
          702  + * ARGUMENTS
          703  + *     cackey_slot *slot
          704  + *         Slot to send commands to
          705  + *
          706  + *     unsigned char class
          707  + *         APDU Class (GSCIS_CLASS_ISO7816 or GSCIS_CLASS_GLOBAL_PLATFORM
          708  + *         usually), (CLA)
          709  + *
          710  + *     unsigned char instruction
          711  + *         APDU Instruction (INS)
          712  + *
          713  + *     unsigned char p1
          714  + *         APDU Parameter 1 (P1)
          715  + *
          716  + *     unsigned char p2
          717  + *         APDU Parameter 2 (P2)
          718  + *
          719  + *     unsigned char lc
          720  + *         APDU Length of Content (Lc) -- this is the length of "data"
          721  + *         parameter.  If "data" is specified as NULL, this parameter will
          722  + *         be ignored.
          723  + *
          724  + *     unsigned char *data
          725  + *         Pointer to buffer to send.  It should be "Lc" bytes long.  If
          726  + *         specified as NULL, "Lc" will not be sent, and this buffer will be
          727  + *         ignored.
          728  + *
          729  + *     unsigned char le
          730  + *         APDU Length of Expectation (Le) -- this is the length of the
          731  + *         expected reply.  If this is specified as 0 then it will not
          732  + *         be sent.
          733  + *
          734  + *     uint16_t *respcode
          735  + *         [OUT] Pointer to storage of APDU response code.  If this is
          736  + *         specified as NULL, the response code will be discarded.
          737  + *
          738  + *     unsigned char *respdata
          739  + *         [OUT] Pointer to storage of APDU response data.  If this is
          740  + *         specified as NULL, the response data will be discarded.  If
          741  + *         the "respdata_len" parameter is specified as NULL, this buffer
          742  + *         will not be updated.
          743  + *
          744  + *     size_t *respdata_len
          745  + *         [IN, OUT] Pointer initialing containing the size of the "respdata"
          746  + *         buffer.  Before returning, the pointed to value is updated to the
          747  + *         number of bytes written to the buffer.  If this is specified as
          748  + *         NULL, it will not be updated, and "respdata" will be ignored causing
          749  + *         the response data to be discarded.
          750  + *
          751  + * RETURN VALUE
          752  + *     CACKEY_PCSC_S_OK         On success
          753  + *     CACKEY_PCSC_E_GENERIC    On error
          754  + *
          755  + * NOTES
          756  + *     This function will connect to the PC/SC Connection Manager via
          757  + *     cackey_pcsc_connect() if needed.
          758  + *
          759  + *     It will connect to the card in the reader attached to the slot
          760  + *     specified.  It will reconnect to the card if the connection
          761  + *     goes away.
          762  + *
          763  + */
   669    764   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) {
   670    765   	uint8_t major_rc, minor_rc;
   671    766   	size_t bytes_to_copy, tmp_respdata_len;
   672    767   	DWORD protocol;
   673    768   	DWORD xmit_len, recv_len;
   674    769   	LONG scard_conn_ret, scard_xmit_ret, scard_reconn_ret;
   675    770   	BYTE xmit_buf[1024], recv_buf[1024];
................................................................................
   836    931   
   837    932   
   838    933   	CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure");
   839    934   
   840    935   	return(CACKEY_PCSC_E_GENERIC);
   841    936   }
   842    937   
          938  +/*
          939  + * SYNPOSIS
          940  + *     ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset);
          941  + *
          942  + * ARGUMENTS
          943  + *     struct cackey_slot *slot
          944  + *         Slot to send commands to
          945  + *
          946  + *     unsigned char *buffer
          947  + *         [OUT] Buffer
          948  + *
          949  + *     size_t count
          950  + *         Number of bytes to attempt to read
          951  + *
          952  + *     unsigned char t_or_v
          953  + *         Select the T-buffer (01) or V-buffer (02) to read from.  
          954  + *
          955  + *     size_t initial_offset
          956  + *         Specify the offset to begin the read from
          957  + *
          958  + *
          959  + * RETURN VALUE
          960  + *     This function returns the number of bytes actually read, or -1 on error.
          961  + *
          962  + * NOTES
          963  + *     None
          964  + *
          965  + */
   843    966   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) {
   844    967   	size_t offset = 0, max_offset, max_count;
   845    968   	unsigned char cmd[2];
   846    969   	uint16_t respcode;
   847    970   	int send_ret;
   848    971   
   849    972   	CACKEY_DEBUG_PRINTF("Called.");
   850    973   
   851    974   	max_offset = count;
   852    975   	max_count = 252;
          976  +
          977  +	if (t_or_v != 1 && t_or_v != 2) {
          978  +		CACKEY_DEBUG_PRINTF("Invalid T or V parameter specified, returning in failure");
          979  +
          980  +		return(-1);
          981  +	}
   853    982   
   854    983   	cmd[0] = t_or_v;
   855    984   
   856    985   	while (1) {
   857    986   		if (offset >= max_offset) {
   858    987   			CACKEY_DEBUG_PRINTF("Buffer too small, returning what we got...");
   859    988   
................................................................................
   894   1023   	}
   895   1024   
   896   1025   	CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) offset);
   897   1026   
   898   1027   	return(offset);
   899   1028   }
   900   1029   
         1030  +/*
         1031  + * SYNPOSIS
         1032  + *     cackey_ret cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len);
         1033  + *
         1034  + * ARGUMENTS
         1035  + *     struct cackey_slot *slot
         1036  + *         Slot to send commands to
         1037  + *
         1038  + *     unsigned char *aid
         1039  + *         Buffer containing Applet ID to select
         1040  + *
         1041  + *     size_t aid_len
         1042  + *         Number of bytes in the "aid" (Applet ID) parameter
         1043  + *
         1044  + * RETURN VALUE
         1045  + *     CACKEY_PCSC_S_OK         On success
         1046  + *     CACKEY_PCSC_E_GENERIC    On error
         1047  + *
         1048  + * NOTES
         1049  + *     None
         1050  + *
         1051  + */
   901   1052   static cackey_ret cackey_select_applet(struct cackey_slot *slot, unsigned char *aid, size_t aid_len) {
   902   1053   	int send_ret;
   903   1054   
   904   1055   	CACKEY_DEBUG_PRINTF("Called.");
   905   1056   
   906   1057   	CACKEY_DEBUG_PRINTBUF("Selecting applet:", aid, aid_len);
   907   1058   
................................................................................
   913   1064   	}
   914   1065   
   915   1066   	CACKEY_DEBUG_PRINTF("Successfully selected file");
   916   1067   
   917   1068   	return(CACKEY_PCSC_S_OK);
   918   1069   }
   919   1070   
         1071  +/*
         1072  + * SYNPOSIS
         1073  + *     cackey_ret cackey_select_file(struct cackey_slot *slot, uint16_t ef);
         1074  + *
         1075  + * ARGUMENTS
         1076  + *     struct cackey_slot *slot
         1077  + *         Slot to send commands to
         1078  + *
         1079  + *     uint16_t ef
         1080  + *         Elemental File to select
         1081  + *
         1082  + * RETURN VALUE
         1083  + *     CACKEY_PCSC_S_OK         On success
         1084  + *     CACKEY_PCSC_E_GENERIC    On error
         1085  + *
         1086  + * NOTES
         1087  + *     This selects an Elementary File (EF) under the currently selected
         1088  + *     Dedicated File (DF)
         1089  + *
         1090  + *     Typically this is called after selecting the correct Applet (using
         1091  + *     cackey_select_applet) for VM cards
         1092  + *
         1093  + */
   920   1094   static cackey_ret cackey_select_file(struct cackey_slot *slot, uint16_t ef) {
   921   1095   	unsigned char fid_buf[2];
   922   1096   	int send_ret;
   923   1097   
   924   1098   	CACKEY_DEBUG_PRINTF("Called.");
   925   1099   
   926   1100   	/* Open the elementary file */
................................................................................
   937   1111   	}
   938   1112   
   939   1113   	CACKEY_DEBUG_PRINTF("Successfully selected file");
   940   1114   
   941   1115   	return(CACKEY_PCSC_S_OK);
   942   1116   }
   943   1117   
         1118  +/*
         1119  + * SYNPOSIS
         1120  + *     void cackey_free_tlv(struct cackey_tlv_entity *root);
         1121  + *
         1122  + * ARGUMENTS
         1123  + *     struct cackey_tlv_entity *root
         1124  + *         Root of the TLV list to start freeing
         1125  + *
         1126  + * RETURN VALUE
         1127  + *     None
         1128  + *
         1129  + * NOTES
         1130  + *     This function frees the TLV linked listed returned from
         1131  + *     "cackey_read_tlv"
         1132  + *
         1133  + */
   944   1134   static void cackey_free_tlv(struct cackey_tlv_entity *root) {
   945   1135   	struct cackey_tlv_entity *curr, *next;
   946   1136   
   947   1137   	if (root == NULL) {
   948   1138   		return;
   949   1139   	}
   950   1140   
................................................................................
   967   1157   
   968   1158   		free(curr);
   969   1159   	}
   970   1160   
   971   1161   	return;
   972   1162   }
   973   1163   
         1164  +/*
         1165  + * SYNPOSIS
         1166  + *     ...
         1167  + *
         1168  + * ARGUMENTS
         1169  + *     ...
         1170  + *
         1171  + * RETURN VALUE
         1172  + *     ...
         1173  + *
         1174  + * NOTES
         1175  + *     ...
         1176  + *
         1177  + */
   974   1178   static struct cackey_tlv_entity *cackey_read_tlv(struct cackey_slot *slot) {
   975   1179   	struct cackey_tlv_entity *curr_entity, *root = NULL, *last = NULL;
   976   1180   	unsigned char tlen_buf[2], tval_buf[1024], *tval;
   977   1181   	unsigned char vlen_buf[2], vval_buf[8192], *vval;
   978   1182   	unsigned char *tmpbuf;
   979   1183   	ssize_t tlen, vlen;
   980   1184   	ssize_t read_ret;
................................................................................
  1119   1323   			last = curr_entity;
  1120   1324   		}
  1121   1325   	}
  1122   1326   
  1123   1327   	return(root);
  1124   1328   }
  1125   1329   
         1330  +/*
         1331  + * SYNPOSIS
         1332  + *     ...
         1333  + *
         1334  + * ARGUMENTS
         1335  + *     ...
         1336  + *
         1337  + * RETURN VALUE
         1338  + *     ...
         1339  + *
         1340  + * NOTES
         1341  + *     ...
         1342  + *
         1343  + */
  1126   1344   static void cackey_free_certs(struct cackey_pcsc_identity *start, size_t count, int free_start) {
  1127   1345   	size_t idx;
  1128   1346   
  1129   1347   	for (idx = 0; idx < count; idx++) {
  1130   1348   		if (start[idx].certificate) {
  1131   1349   			free(start[idx].certificate);
  1132   1350   		}
................................................................................
  1135   1353   	if (free_start) {
  1136   1354   		free(start);
  1137   1355   	}
  1138   1356   
  1139   1357   	return;
  1140   1358   }
  1141   1359   
         1360  +/*
         1361  + * SYNPOSIS
         1362  + *     ...
         1363  + *
         1364  + * ARGUMENTS
         1365  + *     ...
         1366  + *
         1367  + * RETURN VALUE
         1368  + *     ...
         1369  + *
         1370  + * NOTES
         1371  + *     ...
         1372  + *
         1373  + */
  1142   1374   static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
  1143   1375   	struct cackey_pcsc_identity *curr_id;
  1144   1376   	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
  1145   1377   	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
  1146   1378   	unsigned char curr_aid[7];
  1147   1379   	unsigned long outidx = 0;
  1148   1380   	int certs_resizable;
................................................................................
  1270   1502   	if (certs_resizable) {
  1271   1503   		certs = realloc(certs, sizeof(*certs) * (*count));
  1272   1504   	}
  1273   1505   
  1274   1506   	return(certs);
  1275   1507   }
  1276   1508   
         1509  +/*
         1510  + * SYNPOSIS
         1511  + *     ...
         1512  + *
         1513  + * ARGUMENTS
         1514  + *     ...
         1515  + *
         1516  + * RETURN VALUE
         1517  + *     ...
         1518  + *
         1519  + * NOTES
         1520  + *     ...
         1521  + *
         1522  + */
  1277   1523   static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) {
  1278   1524   	unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  1279   1525   	uint16_t response_code;
  1280   1526   	int tries_remaining;
  1281   1527   	int send_ret;
  1282   1528   
  1283   1529   	/* Indicate that we do not know about how many tries are remaining */
................................................................................
  1317   1563   	}
  1318   1564   
  1319   1565   	CACKEY_DEBUG_PRINTF("PIN Verification succeeded");
  1320   1566   
  1321   1567   	return(CACKEY_PCSC_S_OK);
  1322   1568   }
  1323   1569   
         1570  +/*
         1571  + * SYNPOSIS
         1572  + *     ...
         1573  + *
         1574  + * ARGUMENTS
         1575  + *     ...
         1576  + *
         1577  + * RETURN VALUE
         1578  + *     ...
         1579  + *
         1580  + * NOTES
         1581  + *     ...
         1582  + *
         1583  + */
  1324   1584   static cackey_ret cackey_token_present(struct cackey_slot *slot) {
  1325   1585   	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
  1326   1586   	int send_ret;
  1327   1587   
  1328   1588   	/* Select the CCC Applet */
  1329   1589   	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
  1330   1590   	if (send_ret != CACKEY_PCSC_S_OK) {