Overview
Comment: | Updated to use BER-TLV decoding to extract responses rather than hard-coded offsets |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | piv |
Files: | files | file ages | folders |
SHA1: |
ab26dec40100d598ef4cc55901387418 |
User & Date: | rkeene on 2013-01-15 15:59:23 |
Other Links: | branch diff | manifest | tags |
Context
2013-01-15
| ||
18:44 | Updated to build a certificate chain to a root (atleast one) and also not have loops in chains check-in: 1847ef7af2 user: rkeene tags: piv | |
15:59 | Updated to use BER-TLV decoding to extract responses rather than hard-coded offsets check-in: ab26dec401 user: rkeene tags: piv | |
14:12 | Merged in trunk check-in: 8f27214611 user: rkeene tags: piv | |
Changes
Modified cackey.c from [ddd6381c90] to [cc302eaf9b].
︙ | ︙ | |||
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 | } CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } /* * SYNPOSIS | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | > | < < < < | | | < < | | | | < < < < < < < < < | < | < < < < < < | < < < < < < < < < | < < < | | < < < | 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 | } CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } static unsigned char *cackey_read_bertlv_tag(unsigned char *buffer, size_t *buffer_len_p, unsigned char tag, unsigned char *outbuffer, size_t *outbuffer_len_p) { unsigned char *buffer_p; size_t outbuffer_len, buffer_len; size_t size; int idx; CACKEY_DEBUG_PRINTF("Called."); if (buffer_len_p == NULL) { CACKEY_DEBUG_PRINTF("buffer_len_p is NULL. Returning in failure."); return(NULL); } if (outbuffer_len_p == NULL) { CACKEY_DEBUG_PRINTF("outbuffer_len_p is NULL. Returning in failure."); return(NULL); } buffer_len = *outbuffer_len_p; outbuffer_len = *outbuffer_len_p; buffer_p = buffer; if (buffer_p[0] != tag) { CACKEY_DEBUG_PRINTF("Tag found was not tag expected. Tag = %02x, Expected = %02x. Returning in failure.", (unsigned int) buffer_p[0], tag); return(NULL); } buffer_p++; buffer_len--; if ((buffer_p[0] & 0x80) == 0x80) { size = 0; idx = (buffer_p[0] & 0x7f); if (idx > buffer_len) { CACKEY_DEBUG_PRINTF("Malformed BER value -- not enough bytes available to read length (idx = %i, buffer_len = %lu)", idx, (unsigned long) buffer_len); return(NULL); } for (; idx > 0; idx--) { buffer_p++; buffer_len--; size <<= 8; size |= buffer_p[0]; } } else { size = buffer_p[0]; } buffer_p++; buffer_len--; if (size > outbuffer_len) { CACKEY_DEBUG_PRINTF("Unable to copy value buffer to outbuffer, not enough room. Value buffer length = %lu, out buffer length = %lu", (unsigned long) size, (unsigned long) outbuffer_len); return(NULL); } *outbuffer_len_p = size; if (outbuffer) { memcpy(outbuffer, buffer_p, size); buffer_p += size; buffer_len -= size; *buffer_len_p = buffer_len; CACKEY_DEBUG_PRINTBUF("BER-TLV results:", outbuffer, size); } else { memmove(buffer, buffer_p, size); buffer_p = buffer; CACKEY_DEBUG_PRINTBUF("BER-TLV results:", buffer, size); } CACKEY_DEBUG_PRINTF("Returning in success. Size of contents for tag %02x is %lu", (unsigned int) tag, (unsigned long) size); return(buffer_p); } /* * SYNPOSIS * ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t buffer_len, unsigned char oid[3]); * * ARGUMENTS * struct cackey_slot *slot * Slot to send commands to * * unsigned char *buffer * [OUT] Buffer * * size_t buffer_len * Number of bytes to attempt to read * * unsigned char oid[3] * 3-byte OID to read * * * RETURN VALUE * This function returns the number of bytes actually read, or -1 on error. * * NOTES * None * */ static ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t buffer_len, unsigned char oid[3]) { unsigned char cmd[] = {0x5C, 0x03, 0x00, 0x00, 0x00}; unsigned char *buffer_p; size_t init_buffer_len, size; uint16_t respcode; int send_ret; CACKEY_DEBUG_PRINTF("Called."); init_buffer_len = buffer_len; cmd[2] = oid[0]; cmd[3] = oid[1]; cmd[4] = oid[2]; /* 256 to indicate the largest message size -- not clear if this will work with all messages */ send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, NISTSP800_73_3_INSTR_GET_DATA, 0x3F, 0xFF, sizeof(cmd), cmd, 256, &respcode, buffer, &buffer_len); if (send_ret == CACKEY_PCSC_E_RETRY) { CACKEY_DEBUG_PRINTF("ADPU Sending failed, retrying read buffer"); return(cackey_get_data(slot, buffer, init_buffer_len, oid)); } if (send_ret != CACKEY_PCSC_S_OK) { CACKEY_DEBUG_PRINTF("cackey_send_apdu() failed, returning in failure"); return(-1); } #ifdef CACKEY_PARANOID # ifdef _POSIX_SSIZE_MAX if (buffer_len > _POSIX_SSIZE_MAX) { CACKEY_DEBUG_PRINTF("Read bytes (buffer_len) exceeds maximum value, returning in failure. (max = %li, buffer_len = %lu)", (long) _POSIX_SSIZE_MAX, (unsigned long) buffer_len); return(-1); } # endif #endif if (buffer_len < 2) { CACKEY_DEBUG_PRINTF("APDU GET DATA returned %lu bytes, which is too short for a BER-TLV response", (unsigned long) buffer_len); return(-1); } size = buffer_len; buffer_p = cackey_read_bertlv_tag(buffer, &buffer_len, 0x53, NULL, &size); if (buffer_p == NULL) { CACKEY_DEBUG_PRINTF("Tag decoding failed, returning in error."); return(-1); } CACKEY_DEBUG_PRINTBUF("GET DATA result", buffer, size); CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) size); return(size); } |
︙ | ︙ | |||
2353 2354 2355 2356 2357 2358 2359 | */ static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) { struct cackey_pcsc_identity *curr_id; struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr; unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID}; unsigned char *piv_oid, piv_oid_pivauth[] = {NISTSP800_73_3_OID_PIVAUTH}, piv_oid_signature[] = {NISTSP800_73_3_OID_SIGNATURE}, piv_oid_keymgt[] = {NISTSP800_73_3_OID_KEYMGT}; unsigned char curr_aid[7]; | | > | 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 | */ static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) { struct cackey_pcsc_identity *curr_id; struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr; unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID}; unsigned char *piv_oid, piv_oid_pivauth[] = {NISTSP800_73_3_OID_PIVAUTH}, piv_oid_signature[] = {NISTSP800_73_3_OID_SIGNATURE}, piv_oid_keymgt[] = {NISTSP800_73_3_OID_KEYMGT}; unsigned char curr_aid[7]; unsigned char buffer[8192], *buffer_p; unsigned long outidx = 0; cackey_ret transaction_ret; ssize_t read_ret; size_t buffer_len; int certs_resizable; int send_ret, select_ret; int piv_key, piv = 0; int idx; CACKEY_DEBUG_PRINTF("Called."); |
︙ | ︙ | |||
2469 2470 2471 2472 2473 2474 2475 | curr_id->keysize = -1; curr_id->id_type = CACKEY_ID_TYPE_PIV; curr_id->card.piv.key_id = piv_key; curr_id->certificate_len = read_ret; curr_id->certificate = malloc(curr_id->certificate_len); | | | > > > > > > | > > > > > > > | 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 | curr_id->keysize = -1; curr_id->id_type = CACKEY_ID_TYPE_PIV; curr_id->card.piv.key_id = piv_key; curr_id->certificate_len = read_ret; curr_id->certificate = malloc(curr_id->certificate_len); CACKEY_DEBUG_PRINTBUF("Pre-shrink (-4header, -5trailer) == ", buffer, curr_id->certificate_len); buffer_len = sizeof(buffer); buffer_p = cackey_read_bertlv_tag(buffer, &buffer_len, 0x70, curr_id->certificate, &curr_id->certificate_len); if (buffer_p == NULL) { CACKEY_DEBUG_PRINTF("Reading certificate from BER-TLV response failed, skipping key %i", idx); free(curr_id->certificate); outidx--; continue; } CACKEY_DEBUG_PRINTBUF("Post-shrink (-4header, -5trailer) == ", curr_id->certificate, curr_id->certificate_len); } } else { /* Read all the applets from the CCC's TLV */ ccc_tlv = cackey_read_tlv(slot); /* Look for CARDURLs that coorespond to PKI applets */ for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) { |
︙ | ︙ | |||
2596 2597 2598 2599 2600 2601 2602 | * NOTES * ... * */ static ssize_t cackey_signdecrypt(struct cackey_slot *slot, struct cackey_identity *identity, unsigned char *buf, size_t buflen, unsigned char *outbuf, size_t outbuflen, int padInput, int unpadOutput) { cackey_pcsc_id_type id_type; unsigned char dyn_auth_template[10]; | | | | 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 | * NOTES * ... * */ static ssize_t cackey_signdecrypt(struct cackey_slot *slot, struct cackey_identity *identity, unsigned char *buf, size_t buflen, unsigned char *outbuf, size_t outbuflen, int padInput, int unpadOutput) { cackey_pcsc_id_type id_type; unsigned char dyn_auth_template[10]; unsigned char *tmpbuf, *tmpbuf_s, *outbuf_s, *outbuf_p; unsigned char bytes_to_send, p1, class; unsigned char blocktype; cackey_ret send_ret; uint16_t respcode; ssize_t retval = 0, unpadoffset; size_t tmpbuflen, padlen, tmpoutbuflen, outbuf_len; int free_tmpbuf = 0; int le; CACKEY_DEBUG_PRINTF("Called."); if (slot == NULL) { CACKEY_DEBUG_PRINTF("Error. slot is NULL"); |
︙ | ︙ | |||
2839 2840 2841 2842 2843 2844 2845 | } # endif #endif /* We must remove the "7C" tag to get to the signature */ switch (id_type) { case CACKEY_ID_TYPE_PIV: | > > | > | > > > > | > > > | > | 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 | } # endif #endif /* We must remove the "7C" tag to get to the signature */ switch (id_type) { case CACKEY_ID_TYPE_PIV: outbuf_len = retval; outbuf_p = cackey_read_bertlv_tag(outbuf, &outbuf_len, 0x7C, NULL, &outbuf_len); if (outbuf_p == NULL) { CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x7C tag, returning in failure"); return(-1); } retval = outbuf_len; outbuf_len = retval; outbuf_p = cackey_read_bertlv_tag(outbuf, &outbuf_len, 0x82, NULL, &outbuf_len); if (outbuf_p == NULL) { CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x82 with then 0x7C tag, returning in failure"); return(-1); } retval = outbuf_len; break; case CACKEY_ID_TYPE_CAC: case CACKEY_ID_TYPE_CERT_ONLY: break; } /* Unpad reply */ |
︙ | ︙ |