Diff

Differences From Artifact [3db9c71bd5]:

To Artifact [e326e231e2]:


   152    152   #define GSCIS_TAG_SERNO               0x51
   153    153   #define GSCIS_TAG_ISSUE_DATE          0x52
   154    154   #define GSCIS_TAG_EXPIRE_DATE         0x53
   155    155   #define GSCIS_TAG_CARD_TYPE           0x54
   156    156   #define GSCIS_TAG_SECURITY_CODE       0x57
   157    157   #define GSCIS_TAG_CARDID_AID          0x58
   158    158   
          159  +/*** PIV Codes ***/
          160  +#define NISTSP800_73_3_INSTR_GET_DATA 0xCB
          161  +
   159    162   /*** PKI Information - EF 7000 ***/
   160    163   #define GSCIS_TAG_CERTIFICATE         0x70
   161    164   #define GSCIS_TAG_CERT_ISSUE_DATE     0x71
   162    165   #define GSCIS_TAG_CERT_EXPIRE_DATE    0x72
   163    166   
   164    167   /** Applet IDs **/
   165    168   #define GSCIS_AID_CCC                 0xA0, 0x00, 0x00, 0x01, 0x16, 0xDB, 0x00
          169  +#define NISTSP800_73_3_PIV_AID        0xA0, 0x00, 0x00, 0x03, 0x08, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00
          170  +
          171  +/* PIV IDs */
          172  +/** Key Identifiers (NIST SP 800-78-3, Table 6-1 **/
          173  +#define NISTSP800_78_3_KEY_PIVAUTH   0x9A
          174  +#define NISTSP800_78_3_KEY_SIGNATURE 0x9C
          175  +#define NISTSP800_78_3_KEY_KEYMGT    0x9D
          176  +#define NISTSP800_78_3_KEY_CARDAUTH  0x9E
          177  +
          178  +/** Algorithm Identifiers (NIST SP 800-78-3, Table 6-2 **/
          179  +#define NISTSP800_78_3_ALGO_RSA1024  0x06
          180  +#define NISTSP800_78_3_ALGO_RSA2048  0x07
          181  +
          182  +/** Object Identifiers (NIST SP 800-73-3 Part 1, Table 2) **/
          183  +#define NISTSP800_73_3_OID_PIVAUTH   0x5F, 0xC1, 0x05
          184  +#define NISTSP800_73_3_OID_SIGNATURE 0x5F, 0xC1, 0x0A
          185  +#define NISTSP800_73_3_OID_KEYMGT    0x5F, 0xC1, 0x0B
          186  +#define NISTSP800_73_3_OID_CARDAUTH  0x5F, 0xC1, 0x01
   166    187   
   167    188   /* Maximum size of data portion of APDUs */
   168    189   /** Do not set this above 250 **/
   169    190   #define CACKEY_APDU_MTU               250
   170    191   
   171    192   /* ATR If not available */
   172    193   #ifndef MAX_ATR_SIZE
................................................................................
  1417   1438   	if (le != 0x00) {
  1418   1439   		xmit_buf[xmit_len++] = le;
  1419   1440   	}
  1420   1441   
  1421   1442   	/* Begin Smartcard Transaction */
  1422   1443   	cackey_begin_transaction(slot);
  1423   1444   
  1424         -	if (class == GSCIS_CLASS_ISO7816 && instruction == GSCIS_INSTR_VERIFY && p1 == 0x00 && p2 == 0x00) {
         1445  +	if (class == GSCIS_CLASS_ISO7816 && instruction == GSCIS_INSTR_VERIFY && p1 == 0x00) {
  1425   1446   		CACKEY_DEBUG_PRINTF("Sending APDU: <<censored>>");
  1426   1447   	} else {
  1427   1448   		CACKEY_DEBUG_PRINTBUF("Sending APDU:", xmit_buf, xmit_len);
  1428   1449   	}
  1429   1450   
  1430   1451   	recv_len = sizeof(recv_buf);
  1431   1452   	scard_xmit_ret = SCardTransmit(slot->pcsc_card, pioSendPci, xmit_buf, xmit_len, NULL, recv_buf, &recv_len);
................................................................................
  1611   1632   	}
  1612   1633   
  1613   1634   
  1614   1635   	CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure");
  1615   1636   
  1616   1637   	return(CACKEY_PCSC_E_GENERIC);
  1617   1638   }
         1639  +
         1640  +/*
         1641  + * SYNPOSIS
         1642  + *     ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t count, ....
         1643  + *
         1644  + * ARGUMENTS
         1645  + *     struct cackey_slot *slot
         1646  + *         Slot to send commands to
         1647  + *
         1648  + *     unsigned char *buffer
         1649  + *         [OUT] Buffer
         1650  + *
         1651  + *     size_t count
         1652  + *         Number of bytes to attempt to read
         1653  + *
         1654  + *     size_t initial_offset
         1655  + *         Specify the offset to begin the read from
         1656  + *
         1657  + *
         1658  + * RETURN VALUE
         1659  + *     This function returns the number of bytes actually read, or -1 on error.
         1660  + *
         1661  + * NOTES
         1662  + *     None
         1663  + *
         1664  + */
         1665  +static ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char oid[3]) {
         1666  +	unsigned char *buffer_p;
         1667  +	size_t init_count;
         1668  +
         1669  +	size_t offset = 0, max_offset, max_count, size;
         1670  +	unsigned char cmd[] = {0x5C, 0x03, 0x00, 0x00, 0x00};
         1671  +	uint16_t respcode;
         1672  +	int send_ret;
         1673  +	int idx;
         1674  +
         1675  +	CACKEY_DEBUG_PRINTF("Called.");
         1676  +
         1677  +	init_count = count;
         1678  +
         1679  +	max_offset = count;
         1680  +	max_count = CACKEY_APDU_MTU;
         1681  +
         1682  +	cmd[2] = oid[0];
         1683  +	cmd[3] = oid[1];
         1684  +	cmd[4] = oid[2];
         1685  +
         1686  +	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, NISTSP800_73_3_INSTR_GET_DATA, 0x3F, 0xFF, sizeof(cmd), cmd, count, &respcode, buffer, &count);
         1687  +
         1688  +	if (send_ret == CACKEY_PCSC_E_RETRY) {
         1689  +		CACKEY_DEBUG_PRINTF("ADPU Sending failed, retrying read buffer");
         1690  +
         1691  +		return(cackey_get_data(slot, buffer, init_count, oid));
         1692  +	}
         1693  +
         1694  +	if (send_ret != CACKEY_PCSC_S_OK) {
         1695  +		if (respcode == 0x6A86) {
         1696  +/* XXX TODO PIV */
         1697  +		}
         1698  +
         1699  +		CACKEY_DEBUG_PRINTF("cackey_send_apdu() failed, returning in failure");
         1700  +
         1701  +		return(-1);
         1702  +	}
         1703  +
         1704  +	offset += count;
         1705  +
         1706  +#ifdef CACKEY_PARANOID
         1707  +#  ifdef _POSIX_SSIZE_MAX
         1708  +	if (offset > _POSIX_SSIZE_MAX) {
         1709  +		CACKEY_DEBUG_PRINTF("Offset exceeds maximum value, returning in failure. (max = %li, offset = %lu)", (long) _POSIX_SSIZE_MAX, (unsigned long) offset);
         1710  +
         1711  +		return(-1);
         1712  +	}
         1713  +#  endif
         1714  +#endif
         1715  +
         1716  +	if (offset < 2) {
         1717  +		CACKEY_DEBUG_PRINTF("APDU GET DATA returned %lu bytes, which is too short for a BER-TLV response", (unsigned long) offset);
         1718  +
         1719  +		return(-1);
         1720  +	}
         1721  +
         1722  +	buffer_p = buffer;
         1723  +	if (*buffer_p != 0x53) {
         1724  +		CACKEY_DEBUG_PRINTF("APDU GET DATA did not return a BER-TLV with tag 53.  Tag = %02x", (unsigned int) *buffer_p);
         1725  +
         1726  +		return(-1);
         1727  +	}
         1728  +	buffer_p++;
         1729  +
         1730  +	if ((*buffer_p & 0x80) == 0x80) {
         1731  +		size = 0;
         1732  +		idx = (*buffer_p & 0x7f);
         1733  +
         1734  +		if (((buffer_p - buffer) + idx) >= offset) {
         1735  +			CACKEY_DEBUG_PRINTF("Malformed BER value -- not enough bytes available to read length");
         1736  +
         1737  +			return(-1);
         1738  +		}
         1739  +
         1740  +		for (; idx > 0; idx--) {
         1741  +			buffer_p++;
         1742  +			size <<= 8;
         1743  +			size |= *buffer_p;
         1744  +		}
         1745  +	} else {
         1746  +		size = *buffer_p;
         1747  +	}
         1748  +	buffer_p++;
         1749  +
         1750  +	if (((buffer_p - buffer) + size) != offset) {
         1751  +		CACKEY_DEBUG_PRINTF("Entire buffer is not consumed!");
         1752  +
         1753  +		if (((buffer_p - buffer) + size) > offset) {
         1754  +			CACKEY_DEBUG_PRINTF("Encoded size is greater than the amount of data read, dropping");
         1755  +
         1756  +			return(-1);
         1757  +		}
         1758  +	}
         1759  +
         1760  +	memmove(buffer, buffer_p, size);
         1761  +
         1762  +	CACKEY_DEBUG_PRINTBUF("GET DATA result", buffer, size);
         1763  +
         1764  +	CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) size);
         1765  +
         1766  +	return(size);
         1767  +}
  1618   1768   
  1619   1769   /*
  1620   1770    * SYNPOSIS
  1621   1771    *     ssize_t cackey_read_buffer(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char t_or_v, size_t initial_offset);
  1622   1772    *
  1623   1773    * ARGUMENTS
  1624   1774    *     struct cackey_slot *slot
................................................................................
  2130   2280    * NOTES
  2131   2281    *     ...
  2132   2282    *
  2133   2283    */
  2134   2284   static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
  2135   2285   	struct cackey_pcsc_identity *curr_id;
  2136   2286   	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
  2137         -	unsigned char ccc_aid[] = {GSCIS_AID_CCC};
         2287  +	unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID};
         2288  +	unsigned char piv_oid_pivauth[] = {NISTSP800_73_3_OID_PIVAUTH};
  2138   2289   	unsigned char curr_aid[7];
         2290  +	unsigned char buffer[8192];
  2139   2291   	unsigned long outidx = 0;
  2140   2292   	cackey_ret transaction_ret;
         2293  +	ssize_t read_ret;
  2141   2294   	int certs_resizable;
  2142   2295   	int send_ret, select_ret;
         2296  +	int piv = 0;
  2143   2297   
  2144   2298   	CACKEY_DEBUG_PRINTF("Called.");
  2145   2299   
  2146   2300   	if (count == NULL) {
  2147   2301   		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");
  2148   2302   
  2149   2303   		return(NULL);
................................................................................
  2196   2350   	} else {
  2197   2351   		certs_resizable = 0;
  2198   2352   	}
  2199   2353   
  2200   2354   	/* Select the CCC Applet */
  2201   2355   	send_ret = cackey_select_applet(slot, ccc_aid, sizeof(ccc_aid));
  2202   2356   	if (send_ret != CACKEY_PCSC_S_OK) {
  2203         -		CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");
  2204         -
  2205         -		/* Terminate SmartCard Transaction */
  2206         -		cackey_end_transaction(slot);
  2207         -
  2208         -		return(NULL);
  2209         -	}
  2210         -
  2211         -	/* Read all the applets from the CCC's TLV */
  2212         -	ccc_tlv = cackey_read_tlv(slot);
  2213         -
  2214         -	/* Look for CARDURLs that coorespond to PKI applets */
  2215         -	for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) {
  2216         -		CACKEY_DEBUG_PRINTF("Found tag: %s ... ", CACKEY_DEBUG_FUNC_TAG_TO_STR(ccc_curr->tag));
  2217         -
  2218         -		if (ccc_curr->tag != GSCIS_TAG_CARDURL) {
  2219         -			CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about CARDURLs)");
  2220         -
  2221         -			continue;
  2222         -		}
  2223         -
  2224         -		if ((ccc_curr->value_cardurl->apptype & CACKEY_TLV_APP_PKI) != CACKEY_TLV_APP_PKI) {
  2225         -			CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about PKI applets, this applet supports: %s/%02x)", CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(ccc_curr->value_cardurl->apptype), (unsigned int) ccc_curr->value_cardurl->apptype);
  2226         -
  2227         -			continue;
  2228         -		}
  2229         -
  2230         -		CACKEY_DEBUG_PRINTBUF("RID:", ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
  2231         -		CACKEY_DEBUG_PRINTF("AppID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(ccc_curr->value_cardurl->appid), (unsigned long) ccc_curr->value_cardurl->appid);
  2232         -		CACKEY_DEBUG_PRINTF("ObjectID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(ccc_curr->value_cardurl->objectid), (unsigned long) ccc_curr->value_cardurl->objectid);
  2233         -
  2234         -		memcpy(curr_aid, ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
  2235         -		curr_aid[sizeof(curr_aid) - 2] = (ccc_curr->value_cardurl->appid >> 8) & 0xff;
  2236         -		curr_aid[sizeof(curr_aid) - 1] = ccc_curr->value_cardurl->appid & 0xff;
  2237         -
  2238         -		/* Select found applet ... */
  2239         -		select_ret = cackey_select_applet(slot, curr_aid, sizeof(curr_aid));
  2240         -		if (select_ret != CACKEY_PCSC_S_OK) {
  2241         -			CACKEY_DEBUG_PRINTF("Failed to select applet, skipping processing of this object");
  2242         -
  2243         -			continue;
  2244         -		}
  2245         -
  2246         -		/* ... and object (file) */
  2247         -		select_ret = cackey_select_file(slot, ccc_curr->value_cardurl->objectid);
  2248         -		if (select_ret != CACKEY_PCSC_S_OK) {
  2249         -			CACKEY_DEBUG_PRINTF("Failed to select file, skipping processing of this object");
  2250         -
  2251         -			continue;
  2252         -		}
  2253         -
  2254         -		/* Process this file's TLV looking for certificates */
  2255         -		app_tlv = cackey_read_tlv(slot);
  2256         -
  2257         -		for (app_curr = app_tlv; app_curr; app_curr = app_curr->_next) {
  2258         -			CACKEY_DEBUG_PRINTF("Found tag: %s", CACKEY_DEBUG_FUNC_TAG_TO_STR(app_curr->tag));
  2259         -			if (app_curr->tag != GSCIS_TAG_CERTIFICATE) {
  2260         -				CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about CERTIFICATEs)");
         2357  +		/* Try PIV application */
         2358  +		send_ret = cackey_select_applet(slot, piv_aid, sizeof(piv_aid));
         2359  +		if (send_ret == CACKEY_PCSC_S_OK) {
         2360  +			CACKEY_DEBUG_PRINTF("We have a PIV card, doing the needful");
         2361  +
         2362  +			piv = 1;
         2363  +		} else {
         2364  +
         2365  +			CACKEY_DEBUG_PRINTF("Unable to select CCC Applet, returning in failure");
         2366  +
         2367  +			/* Terminate SmartCard Transaction */
         2368  +			cackey_end_transaction(slot);
         2369  +
         2370  +			return(NULL);
         2371  +		}
         2372  +	}
         2373  +
         2374  +	if (piv) {
         2375  +		read_ret = cackey_get_data(slot, buffer, sizeof(buffer), piv_oid_pivauth);
         2376  +
         2377  +		curr_id = &certs[outidx];
         2378  +		outidx++;
         2379  +
         2380  +		curr_id->keysize = -1;
         2381  +		curr_id->file = 0xFFFF;
         2382  +		curr_id->applet[0] = NISTSP800_78_3_KEY_PIVAUTH;
         2383  +
         2384  +		curr_id->certificate_len = read_ret;
         2385  +		curr_id->certificate = malloc(curr_id->certificate_len);
         2386  +		memcpy(curr_id->certificate, buffer + 4, curr_id->certificate_len - 4); /* XXX TODO PIV */
         2387  +	} else {
         2388  +		/* Read all the applets from the CCC's TLV */
         2389  +		ccc_tlv = cackey_read_tlv(slot);
         2390  +
         2391  +		/* Look for CARDURLs that coorespond to PKI applets */
         2392  +		for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) {
         2393  +			CACKEY_DEBUG_PRINTF("Found tag: %s ... ", CACKEY_DEBUG_FUNC_TAG_TO_STR(ccc_curr->tag));
         2394  +
         2395  +			if (ccc_curr->tag != GSCIS_TAG_CARDURL) {
         2396  +				CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about CARDURLs)");
         2397  +
         2398  +				continue;
         2399  +			}
         2400  +
         2401  +			if ((ccc_curr->value_cardurl->apptype & CACKEY_TLV_APP_PKI) != CACKEY_TLV_APP_PKI) {
         2402  +				CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about PKI applets, this applet supports: %s/%02x)", CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(ccc_curr->value_cardurl->apptype), (unsigned int) ccc_curr->value_cardurl->apptype);
         2403  +
         2404  +				continue;
         2405  +			}
         2406  +
         2407  +			CACKEY_DEBUG_PRINTBUF("RID:", ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
         2408  +			CACKEY_DEBUG_PRINTF("AppID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(ccc_curr->value_cardurl->appid), (unsigned long) ccc_curr->value_cardurl->appid);
         2409  +			CACKEY_DEBUG_PRINTF("ObjectID = %s/%04lx", CACKEY_DEBUG_FUNC_OBJID_TO_STR(ccc_curr->value_cardurl->objectid), (unsigned long) ccc_curr->value_cardurl->objectid);
         2410  +
         2411  +			memcpy(curr_aid, ccc_curr->value_cardurl->rid, sizeof(ccc_curr->value_cardurl->rid));
         2412  +			curr_aid[sizeof(curr_aid) - 2] = (ccc_curr->value_cardurl->appid >> 8) & 0xff;
         2413  +			curr_aid[sizeof(curr_aid) - 1] = ccc_curr->value_cardurl->appid & 0xff;
         2414  +
         2415  +			/* Select found applet ... */
         2416  +			select_ret = cackey_select_applet(slot, curr_aid, sizeof(curr_aid));
         2417  +			if (select_ret != CACKEY_PCSC_S_OK) {
         2418  +				CACKEY_DEBUG_PRINTF("Failed to select applet, skipping processing of this object");
         2419  +
         2420  +				continue;
         2421  +			}
         2422  +
         2423  +			/* ... and object (file) */
         2424  +			select_ret = cackey_select_file(slot, ccc_curr->value_cardurl->objectid);
         2425  +			if (select_ret != CACKEY_PCSC_S_OK) {
         2426  +				CACKEY_DEBUG_PRINTF("Failed to select file, skipping processing of this object");
  2261   2427   
  2262   2428   				continue;
  2263   2429   			}
  2264   2430   
  2265         -			curr_id = &certs[outidx];
  2266         -			outidx++;
  2267         -
  2268         -			memcpy(curr_id->applet, curr_aid, sizeof(curr_id->applet));
  2269         -			curr_id->file = ccc_curr->value_cardurl->objectid;
  2270         -			curr_id->keysize = -1;
  2271         -
  2272         -			CACKEY_DEBUG_PRINTF("Filling curr_id->applet (%p) with %lu bytes:", curr_id->applet, (unsigned long) sizeof(curr_id->applet));
  2273         -			CACKEY_DEBUG_PRINTBUF("VAL:", curr_id->applet, sizeof(curr_id->applet));
  2274         -
  2275         -			curr_id->certificate_len = app_curr->length;
  2276         -
  2277         -			curr_id->certificate = malloc(curr_id->certificate_len);
  2278         -			memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len);
         2431  +			/* Process this file's TLV looking for certificates */
         2432  +			app_tlv = cackey_read_tlv(slot);
         2433  +	
         2434  +			for (app_curr = app_tlv; app_curr; app_curr = app_curr->_next) {
         2435  +				CACKEY_DEBUG_PRINTF("Found tag: %s", CACKEY_DEBUG_FUNC_TAG_TO_STR(app_curr->tag));
         2436  +				if (app_curr->tag != GSCIS_TAG_CERTIFICATE) {
         2437  +					CACKEY_DEBUG_PRINTF("  ... skipping it (we only care about CERTIFICATEs)");
         2438  +
         2439  +					continue;
         2440  +				}
         2441  +
         2442  +				curr_id = &certs[outidx];
         2443  +				outidx++;
         2444  +
         2445  +				memcpy(curr_id->applet, curr_aid, sizeof(curr_id->applet));
         2446  +				curr_id->file = ccc_curr->value_cardurl->objectid;
         2447  +				curr_id->keysize = -1;
         2448  +
         2449  +				CACKEY_DEBUG_PRINTF("Filling curr_id->applet (%p) with %lu bytes:", curr_id->applet, (unsigned long) sizeof(curr_id->applet));
         2450  +				CACKEY_DEBUG_PRINTBUF("VAL:", curr_id->applet, sizeof(curr_id->applet));
         2451  +
         2452  +				curr_id->certificate_len = app_curr->length;
         2453  +
         2454  +				curr_id->certificate = malloc(curr_id->certificate_len);
         2455  +				memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len);
         2456  +
         2457  +				if (outidx >= *count) {
         2458  +					if (certs_resizable) {
         2459  +						*count *= 2;
         2460  +						certs = realloc(certs, sizeof(*certs) * (*count));
         2461  +					} else {
         2462  +						break;
         2463  +					}
         2464  +				}
         2465  +			}
         2466  +
         2467  +			cackey_free_tlv(app_tlv);
  2279   2468   
  2280   2469   			if (outidx >= *count) {
  2281         -				if (certs_resizable) {
  2282         -					*count *= 2;
  2283         -					certs = realloc(certs, sizeof(*certs) * (*count));
  2284         -				} else {
  2285         -					break;
  2286         -				}
         2470  +				break;
  2287   2471   			}
  2288   2472   		}
  2289   2473   
  2290         -		cackey_free_tlv(app_tlv);
  2291         -
  2292         -		if (outidx >= *count) {
  2293         -			break;
  2294         -		}
         2474  +		cackey_free_tlv(ccc_tlv);
  2295   2475   	}
  2296   2476   
  2297         -	cackey_free_tlv(ccc_tlv);
  2298         -
  2299   2477   	*count = outidx;
  2300   2478   
  2301   2479   	if (certs_resizable) {
  2302   2480   		certs = realloc(certs, sizeof(*certs) * (*count));
  2303   2481   	}
  2304   2482   
  2305   2483   	slot->cached_certs = cackey_copy_certs(NULL, certs, *count);
................................................................................
  2331   2509   	unsigned char blocktype;
  2332   2510   	cackey_ret send_ret;
  2333   2511   	uint16_t respcode;
  2334   2512   	ssize_t retval = 0, unpadoffset;
  2335   2513   	size_t tmpbuflen, padlen, tmpoutbuflen;
  2336   2514   	int free_tmpbuf = 0;
  2337   2515   	int le;
         2516  +	int piv;
  2338   2517   
  2339   2518   	CACKEY_DEBUG_PRINTF("Called.");
  2340   2519   
  2341   2520   	if (slot == NULL) {
  2342   2521   		CACKEY_DEBUG_PRINTF("Error.  slot is NULL");
  2343   2522   
  2344   2523   		return(-1);
................................................................................
  2419   2598   		padlen = 0;
  2420   2599   	}
  2421   2600   
  2422   2601   	/* Begin transaction */
  2423   2602   	cackey_begin_transaction(slot);
  2424   2603   
  2425   2604   	/* Select correct applet */
  2426         -	CACKEY_DEBUG_PRINTF("Selecting applet found at %p ...", identity->pcsc_identity->applet);
  2427         -	cackey_select_applet(slot, identity->pcsc_identity->applet, sizeof(identity->pcsc_identity->applet));
  2428         -
  2429         -	/* Select correct file */
  2430         -	cackey_select_file(slot, identity->pcsc_identity->file);
  2431         -
  2432         -	tmpbuf_s = tmpbuf;
  2433         -	outbuf_s = outbuf;
  2434         -	while (tmpbuflen) {
  2435         -		if (tmpbuflen > 245) {
  2436         -			bytes_to_send = 245;
  2437         -			p1 = 0x80;
  2438         -			le = 0x00;
  2439         -		} else {
  2440         -			bytes_to_send = tmpbuflen;
  2441         -			p1 = 0x00;
  2442         -			le = 0x00;
  2443         -		}
  2444         -
  2445         -		tmpoutbuflen = outbuflen;
  2446         -
  2447         -		send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
  2448         -		if (send_ret != CACKEY_PCSC_S_OK) {
  2449         -			CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");
  2450         -
  2451         -			if (free_tmpbuf) {
  2452         -				if (tmpbuf_s) {
  2453         -					free(tmpbuf_s);
  2454         -				}
  2455         -			}
  2456         -
  2457         -			/* End transaction */
  2458         -			cackey_end_transaction(slot);
  2459         -
  2460         -			if (respcode == 0x6982) {
  2461         -				CACKEY_DEBUG_PRINTF("Security status not satisified.  Returning NEEDLOGIN");
  2462         -
  2463         -				cackey_mark_slot_reset(slot);
  2464         -				slot->token_flags = CKF_LOGIN_REQUIRED;
  2465         -
  2466         -				return(CACKEY_PCSC_E_NEEDLOGIN);
  2467         -			}
  2468         -
  2469         -			if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
  2470         -				CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");
  2471         -
  2472         -				cackey_mark_slot_reset(slot);
  2473         -
  2474         -				return(CACKEY_PCSC_E_TOKENABSENT);
  2475         -			}
  2476         -
  2477         -			return(-1);
  2478         -		}
  2479         -
  2480         -		tmpbuf += bytes_to_send;
  2481         -		tmpbuflen -= bytes_to_send;
  2482         -
  2483         -		outbuf += tmpoutbuflen;
  2484         -		outbuflen -= tmpoutbuflen;
  2485         -		retval += tmpoutbuflen;
         2605  +	if (identity->pcsc_identity->file == 0xFFFF) {
         2606  +		piv = 1;
         2607  +	} else {
         2608  +		piv = 0;
         2609  +	}
         2610  +
         2611  +	if (piv) {
         2612  +		CACKEY_DEBUG_PRINTF("Sign/Decrypt not implemented XXX TODO PIV");
         2613  +		cackey_end_transaction(slot);
         2614  +		return(-1);
         2615  +	} else {
         2616  +		CACKEY_DEBUG_PRINTF("Selecting applet found at %p ...", identity->pcsc_identity->applet);
         2617  +		cackey_select_applet(slot, identity->pcsc_identity->applet, sizeof(identity->pcsc_identity->applet));
         2618  +
         2619  +		/* Select correct file */
         2620  +		cackey_select_file(slot, identity->pcsc_identity->file);
         2621  +
         2622  +		tmpbuf_s = tmpbuf;
         2623  +		outbuf_s = outbuf;
         2624  +		while (tmpbuflen) {
         2625  +			if (tmpbuflen > 245) {
         2626  +				bytes_to_send = 245;
         2627  +				p1 = 0x80;
         2628  +				le = 0x00;
         2629  +			} else {
         2630  +				bytes_to_send = tmpbuflen;
         2631  +				p1 = 0x00;
         2632  +				le = 0x00;
         2633  +			}
         2634  +
         2635  +			tmpoutbuflen = outbuflen;
         2636  +
         2637  +			send_ret = cackey_send_apdu(slot, GSCIS_CLASS_GLOBAL_PLATFORM, GSCIS_INSTR_SIGNDECRYPT, p1, 0x00, bytes_to_send, tmpbuf, le, &respcode, outbuf, &tmpoutbuflen);
         2638  +			if (send_ret != CACKEY_PCSC_S_OK) {
         2639  +				CACKEY_DEBUG_PRINTF("ADPU Sending Failed -- returning in error.");
         2640  +
         2641  +				if (free_tmpbuf) {
         2642  +					if (tmpbuf_s) {
         2643  +						free(tmpbuf_s);
         2644  +					}
         2645  +				}
         2646  +
         2647  +				/* End transaction */
         2648  +				cackey_end_transaction(slot);
         2649  +
         2650  +				if (respcode == 0x6982) {
         2651  +					CACKEY_DEBUG_PRINTF("Security status not satisified.  Returning NEEDLOGIN");
         2652  +
         2653  +					cackey_mark_slot_reset(slot);
         2654  +					slot->token_flags = CKF_LOGIN_REQUIRED;
         2655  +
         2656  +					return(CACKEY_PCSC_E_NEEDLOGIN);
         2657  +				}
         2658  +
         2659  +				if (send_ret == CACKEY_PCSC_E_TOKENABSENT) {
         2660  +					CACKEY_DEBUG_PRINTF("Token absent.  Returning TOKENABSENT");
         2661  +
         2662  +					cackey_mark_slot_reset(slot);
         2663  +
         2664  +					return(CACKEY_PCSC_E_TOKENABSENT);
         2665  +				}
         2666  +
         2667  +				return(-1);
         2668  +			}
         2669  +
         2670  +			tmpbuf += bytes_to_send;
         2671  +			tmpbuflen -= bytes_to_send;
         2672  +
         2673  +			outbuf += tmpoutbuflen;
         2674  +			outbuflen -= tmpoutbuflen;
         2675  +			retval += tmpoutbuflen;
         2676  +		}
  2486   2677   	}
  2487   2678   
  2488   2679   	if (free_tmpbuf) {
  2489   2680   		if (tmpbuf_s) {
  2490   2681   			free(tmpbuf_s);
  2491   2682   		}
  2492   2683   	}
................................................................................
  2601   2792    *
  2602   2793    */
  2603   2794   static cackey_ret cackey_login(struct cackey_slot *slot, unsigned char *pin, unsigned long pin_len, int *tries_remaining_p) {
  2604   2795   	unsigned char cac_pin[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
  2605   2796   	uint16_t response_code;
  2606   2797   	int tries_remaining;
  2607   2798   	int send_ret;
         2799  +	int key_reference = 0x00;
  2608   2800   
  2609   2801   	/* Indicate that we do not know about how many tries are remaining */
  2610   2802   	if (tries_remaining_p) {
  2611   2803   		*tries_remaining_p = -1;
  2612   2804   	}
  2613   2805   
  2614   2806   	/* Apparently, CAC PINs are *EXACTLY* 8 bytes long -- pad with 0xFF if too short */
................................................................................
  2615   2807   	if (pin_len >= 8) {
  2616   2808   		memcpy(cac_pin, pin, 8);
  2617   2809   	} else {
  2618   2810   		memcpy(cac_pin, pin, pin_len);
  2619   2811   	}
  2620   2812   
  2621   2813   	/* Issue PIN Verify */
  2622         -	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_VERIFY, 0x00, 0x00, sizeof(cac_pin), cac_pin, 0x00, &response_code, NULL, NULL);
         2814  +	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_VERIFY, 0x00, key_reference, sizeof(cac_pin), cac_pin, 0x00, &response_code, NULL, NULL);
         2815  +	if (send_ret != CACKEY_PCSC_S_OK && response_code == 0x6A88) {
         2816  +		key_reference = 0x80;
         2817  +
         2818  +		send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, GSCIS_INSTR_VERIFY, 0x00, key_reference, sizeof(cac_pin), cac_pin, 0x00, &response_code, NULL, NULL);
         2819  +	}
         2820  +
  2623   2821   	if (send_ret != CACKEY_PCSC_S_OK) {
  2624   2822   		if ((response_code & 0x63C0) == 0x63C0) {
  2625   2823   			tries_remaining = (response_code & 0xF);
  2626   2824   
  2627   2825   			CACKEY_DEBUG_PRINTF("PIN Verification failed, %i tries remaining", tries_remaining);
  2628   2826   
  2629   2827   			if (tries_remaining_p) {