Overview
Comment: | Began adding PIV support |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | piv |
Files: | files | file ages | folders |
SHA1: | 1494008def42e5f06f88895da0f13fb36e8a741d |
User & Date: | rkeene on 2013-01-10 01:00:39 |
Other Links: | manifest | tags |
Context
2013-01-10
| ||
04:59 | Updated to provide basic (and buggy) PIV functionality check-in: b9b26ebc73 user: rkeene tags: piv | |
01:00 | Began adding PIV support check-in: 1494008def user: rkeene tags: piv | |
2012-07-30
| ||
16:02 | Updated email address in CACKey for OSX Build Script check-in: 003e5de0f0 user: kvanals tags: trunk | |
Changes
Modified cackey.c from [3db9c71bd5] to [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) {