Diff

Differences From Artifact [ddd6381c90]:

To Artifact [cc302eaf9b]:


  1697   1697   	}
  1698   1698   
  1699   1699   
  1700   1700   	CACKEY_DEBUG_PRINTF("APDU Returned an error, returning in failure");
  1701   1701   
  1702   1702   	return(CACKEY_PCSC_E_GENERIC);
  1703   1703   }
         1704  +
         1705  +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) {
         1706  +	unsigned char *buffer_p;
         1707  +	size_t outbuffer_len, buffer_len;
         1708  +	size_t size;
         1709  +	int idx;
         1710  +
         1711  +	CACKEY_DEBUG_PRINTF("Called.");
         1712  +
         1713  +	if (buffer_len_p == NULL) {
         1714  +		CACKEY_DEBUG_PRINTF("buffer_len_p is NULL.  Returning in failure.");
         1715  +
         1716  +		return(NULL);
         1717  +	}
         1718  +
         1719  +	if (outbuffer_len_p == NULL) {
         1720  +		CACKEY_DEBUG_PRINTF("outbuffer_len_p is NULL.  Returning in failure.");
         1721  +
         1722  +		return(NULL);
         1723  +	}
         1724  +
         1725  +	buffer_len = *outbuffer_len_p;
         1726  +	outbuffer_len = *outbuffer_len_p;
         1727  +
         1728  +	buffer_p = buffer;
         1729  +	if (buffer_p[0] != tag) {
         1730  +		CACKEY_DEBUG_PRINTF("Tag found was not tag expected.  Tag = %02x, Expected = %02x.  Returning in failure.", (unsigned int) buffer_p[0], tag);
         1731  +
         1732  +		return(NULL);
         1733  +	}
         1734  +
         1735  +	buffer_p++;
         1736  +	buffer_len--;
         1737  +
         1738  +	if ((buffer_p[0] & 0x80) == 0x80) {
         1739  +		size = 0;
         1740  +		idx = (buffer_p[0] & 0x7f);
         1741  +
         1742  +		if (idx > buffer_len) {
         1743  +			CACKEY_DEBUG_PRINTF("Malformed BER value -- not enough bytes available to read length (idx = %i, buffer_len = %lu)", idx, (unsigned long) buffer_len);
         1744  +
         1745  +			return(NULL);
         1746  +		}
         1747  +
         1748  +		for (; idx > 0; idx--) {
         1749  +			buffer_p++;
         1750  +			buffer_len--;
         1751  +
         1752  +			size <<= 8;
         1753  +			size |= buffer_p[0];
         1754  +		}
         1755  +	} else {
         1756  +		size = buffer_p[0];
         1757  +	}
         1758  +
         1759  +	buffer_p++;
         1760  +	buffer_len--;
         1761  +
         1762  +	if (size > outbuffer_len) {
         1763  +		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);
         1764  +
         1765  +		return(NULL);
         1766  +	}
         1767  +
         1768  +	*outbuffer_len_p = size;
         1769  +	if (outbuffer) {
         1770  +		memcpy(outbuffer, buffer_p, size);
         1771  +		buffer_p += size;
         1772  +		buffer_len -= size;
         1773  +
         1774  +		*buffer_len_p = buffer_len;
         1775  +
         1776  +		CACKEY_DEBUG_PRINTBUF("BER-TLV results:", outbuffer, size);
         1777  +	} else {
         1778  +		memmove(buffer, buffer_p, size);
         1779  +		buffer_p = buffer;
         1780  +
         1781  +		CACKEY_DEBUG_PRINTBUF("BER-TLV results:", buffer, size);
         1782  +	}
         1783  +
         1784  +	CACKEY_DEBUG_PRINTF("Returning in success.  Size of contents for tag %02x is %lu", (unsigned int) tag, (unsigned long) size);
         1785  +
         1786  +	return(buffer_p);
         1787  +}
  1704   1788   
  1705   1789   /*
  1706   1790    * SYNPOSIS
  1707         - *     ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char oid[3]);
         1791  + *     ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t buffer_len, unsigned char oid[3]);
  1708   1792    *
  1709   1793    * ARGUMENTS
  1710   1794    *     struct cackey_slot *slot
  1711   1795    *         Slot to send commands to
  1712   1796    *
  1713   1797    *     unsigned char *buffer
  1714   1798    *         [OUT] Buffer
  1715   1799    *
  1716         - *     size_t count
         1800  + *     size_t buffer_len
  1717   1801    *         Number of bytes to attempt to read
  1718   1802    *
  1719   1803    *     unsigned char oid[3]
  1720   1804    *         3-byte OID to read
  1721   1805    *
  1722   1806    *
  1723   1807    * RETURN VALUE
  1724   1808    *     This function returns the number of bytes actually read, or -1 on error.
  1725   1809    *
  1726   1810    * NOTES
  1727   1811    *     None
  1728   1812    *
  1729   1813    */
  1730         -static ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t count, unsigned char oid[3]) {
         1814  +static ssize_t cackey_get_data(struct cackey_slot *slot, unsigned char *buffer, size_t buffer_len, unsigned char oid[3]) {
         1815  +	unsigned char cmd[] = {0x5C, 0x03, 0x00, 0x00, 0x00};
  1731   1816   	unsigned char *buffer_p;
  1732         -	size_t init_count;
  1733         -
  1734         -	size_t offset = 0, size;
  1735         -	unsigned char cmd[] = {0x5C, 0x03, 0x00, 0x00, 0x00};
         1817  +	size_t init_buffer_len, size;
  1736   1818   	uint16_t respcode;
  1737   1819   	int send_ret;
  1738         -	int idx;
  1739   1820   
  1740   1821   	CACKEY_DEBUG_PRINTF("Called.");
  1741   1822   
  1742         -	init_count = count;
         1823  +	init_buffer_len = buffer_len;
  1743   1824   
  1744   1825   	cmd[2] = oid[0];
  1745   1826   	cmd[3] = oid[1];
  1746   1827   	cmd[4] = oid[2];
  1747   1828   
  1748   1829   	/* 256 to indicate the largest message size -- not clear if this will work with all messages */
  1749         -	send_ret = cackey_send_apdu(slot, GSCIS_CLASS_ISO7816, NISTSP800_73_3_INSTR_GET_DATA, 0x3F, 0xFF, sizeof(cmd), cmd, 256, &respcode, buffer, &count);
         1830  +	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);
  1750   1831   
  1751   1832   	if (send_ret == CACKEY_PCSC_E_RETRY) {
  1752   1833   		CACKEY_DEBUG_PRINTF("ADPU Sending failed, retrying read buffer");
  1753   1834   
  1754         -		return(cackey_get_data(slot, buffer, init_count, oid));
         1835  +		return(cackey_get_data(slot, buffer, init_buffer_len, oid));
  1755   1836   	}
  1756   1837   
  1757   1838   	if (send_ret != CACKEY_PCSC_S_OK) {
  1758   1839   		CACKEY_DEBUG_PRINTF("cackey_send_apdu() failed, returning in failure");
  1759   1840   
  1760   1841   		return(-1);
  1761   1842   	}
  1762   1843   
  1763         -	offset += count;
  1764         -
  1765   1844   #ifdef CACKEY_PARANOID
  1766   1845   #  ifdef _POSIX_SSIZE_MAX
  1767         -	if (offset > _POSIX_SSIZE_MAX) {
  1768         -		CACKEY_DEBUG_PRINTF("Offset exceeds maximum value, returning in failure. (max = %li, offset = %lu)", (long) _POSIX_SSIZE_MAX, (unsigned long) offset);
         1846  +	if (buffer_len > _POSIX_SSIZE_MAX) {
         1847  +		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);
  1769   1848   
  1770   1849   		return(-1);
  1771   1850   	}
  1772   1851   #  endif
  1773   1852   #endif
  1774   1853   
  1775         -	if (offset < 2) {
  1776         -		CACKEY_DEBUG_PRINTF("APDU GET DATA returned %lu bytes, which is too short for a BER-TLV response", (unsigned long) offset);
  1777         -
  1778         -		return(-1);
  1779         -	}
  1780         -
  1781         -	buffer_p = buffer;
  1782         -	if (*buffer_p != 0x53) {
  1783         -		CACKEY_DEBUG_PRINTF("APDU GET DATA did not return a BER-TLV with tag 53.  Tag = %02x", (unsigned int) *buffer_p);
  1784         -
  1785         -		return(-1);
  1786         -	}
  1787         -	buffer_p++;
  1788         -
  1789         -	if ((*buffer_p & 0x80) == 0x80) {
  1790         -		size = 0;
  1791         -		idx = (*buffer_p & 0x7f);
  1792         -
  1793         -		if (((buffer_p - buffer) + idx) >= offset) {
  1794         -			CACKEY_DEBUG_PRINTF("Malformed BER value -- not enough bytes available to read length");
  1795         -
  1796         -			return(-1);
  1797         -		}
  1798         -
  1799         -		for (; idx > 0; idx--) {
  1800         -			buffer_p++;
  1801         -			size <<= 8;
  1802         -			size |= *buffer_p;
  1803         -		}
  1804         -	} else {
  1805         -		size = *buffer_p;
  1806         -	}
  1807         -	buffer_p++;
  1808         -
  1809         -	if (((buffer_p - buffer) + size) != offset) {
  1810         -		CACKEY_DEBUG_PRINTF("Entire buffer is not consumed!");
  1811         -
  1812         -		if (((buffer_p - buffer) + size) > offset) {
  1813         -			CACKEY_DEBUG_PRINTF("Encoded size is greater than the amount of data read, dropping");
  1814         -
  1815         -			return(-1);
  1816         -		}
  1817         -	}
  1818         -
  1819         -	memmove(buffer, buffer_p, size);
         1854  +	if (buffer_len < 2) {
         1855  +		CACKEY_DEBUG_PRINTF("APDU GET DATA returned %lu bytes, which is too short for a BER-TLV response", (unsigned long) buffer_len);
         1856  +
         1857  +		return(-1);
         1858  +	}
         1859  +
         1860  +	size = buffer_len;
         1861  +	buffer_p = cackey_read_bertlv_tag(buffer, &buffer_len, 0x53, NULL, &size);
         1862  +
         1863  +	if (buffer_p == NULL) {
         1864  +		CACKEY_DEBUG_PRINTF("Tag decoding failed, returning in error.");
         1865  +
         1866  +		return(-1);
         1867  +	}
  1820   1868   
  1821   1869   	CACKEY_DEBUG_PRINTBUF("GET DATA result", buffer, size);
  1822   1870   
  1823   1871   	CACKEY_DEBUG_PRINTF("Returning in success, read %lu bytes", (unsigned long) size);
  1824   1872   
  1825   1873   	return(size);
  1826   1874   }
................................................................................
  2353   2401    */
  2354   2402   static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
  2355   2403   	struct cackey_pcsc_identity *curr_id;
  2356   2404   	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
  2357   2405   	unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID};
  2358   2406   	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};
  2359   2407   	unsigned char curr_aid[7];
  2360         -	unsigned char buffer[8192];
         2408  +	unsigned char buffer[8192], *buffer_p;
  2361   2409   	unsigned long outidx = 0;
  2362   2410   	cackey_ret transaction_ret;
  2363   2411   	ssize_t read_ret;
         2412  +	size_t buffer_len;
  2364   2413   	int certs_resizable;
  2365   2414   	int send_ret, select_ret;
  2366   2415   	int piv_key, piv = 0;
  2367   2416   	int idx;
  2368   2417   
  2369   2418   	CACKEY_DEBUG_PRINTF("Called.");
  2370   2419   
................................................................................
  2469   2518   
  2470   2519   			curr_id->keysize = -1;
  2471   2520   			curr_id->id_type = CACKEY_ID_TYPE_PIV;
  2472   2521   			curr_id->card.piv.key_id = piv_key;
  2473   2522   
  2474   2523   			curr_id->certificate_len = read_ret;
  2475   2524   			curr_id->certificate = malloc(curr_id->certificate_len);
  2476         -			memcpy(curr_id->certificate, buffer + 4, curr_id->certificate_len - 4); /* XXX TODO PIV (-4 header, -5 trailer == why ?) */
  2477         -			curr_id->certificate_len -= 4;
  2478         -			curr_id->certificate_len -= 5;
         2525  +
         2526  +			CACKEY_DEBUG_PRINTBUF("Pre-shrink (-4header, -5trailer) == ", buffer, curr_id->certificate_len);
         2527  +
         2528  +			buffer_len = sizeof(buffer);
         2529  +			buffer_p = cackey_read_bertlv_tag(buffer, &buffer_len, 0x70, curr_id->certificate, &curr_id->certificate_len);
         2530  +
         2531  +			if (buffer_p == NULL) {
         2532  +				CACKEY_DEBUG_PRINTF("Reading certificate from BER-TLV response failed, skipping key %i", idx);
         2533  +				free(curr_id->certificate);
         2534  +
         2535  +				outidx--;
         2536  +
         2537  +				continue;
         2538  +			}
         2539  +
         2540  +			CACKEY_DEBUG_PRINTBUF("Post-shrink (-4header, -5trailer) == ", curr_id->certificate, curr_id->certificate_len);
  2479   2541   		}
  2480   2542   	} else {
  2481   2543   		/* Read all the applets from the CCC's TLV */
  2482   2544   		ccc_tlv = cackey_read_tlv(slot);
  2483   2545   
  2484   2546   		/* Look for CARDURLs that coorespond to PKI applets */
  2485   2547   		for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) {
................................................................................
  2596   2658    * NOTES
  2597   2659    *     ...
  2598   2660    *
  2599   2661    */
  2600   2662   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) {
  2601   2663   	cackey_pcsc_id_type id_type;
  2602   2664   	unsigned char dyn_auth_template[10];
  2603         -	unsigned char *tmpbuf, *tmpbuf_s, *outbuf_s;
         2665  +	unsigned char *tmpbuf, *tmpbuf_s, *outbuf_s, *outbuf_p;
  2604   2666   	unsigned char bytes_to_send, p1, class;
  2605   2667   	unsigned char blocktype;
  2606   2668   	cackey_ret send_ret;
  2607   2669   	uint16_t respcode;
  2608   2670   	ssize_t retval = 0, unpadoffset;
  2609         -	size_t tmpbuflen, padlen, tmpoutbuflen;
         2671  +	size_t tmpbuflen, padlen, tmpoutbuflen, outbuf_len;
  2610   2672   	int free_tmpbuf = 0;
  2611   2673   	int le;
  2612   2674   
  2613   2675   	CACKEY_DEBUG_PRINTF("Called.");
  2614   2676   
  2615   2677   	if (slot == NULL) {
  2616   2678   		CACKEY_DEBUG_PRINTF("Error.  slot is NULL");
................................................................................
  2839   2901   	}
  2840   2902   #  endif
  2841   2903   #endif
  2842   2904   
  2843   2905   	/* We must remove the "7C" tag to get to the signature */
  2844   2906   	switch (id_type) {
  2845   2907   		case CACKEY_ID_TYPE_PIV:
  2846         -			if (outbuf[0] != 0x7C) {
         2908  +			outbuf_len = retval;
         2909  +			outbuf_p = cackey_read_bertlv_tag(outbuf, &outbuf_len, 0x7C, NULL,  &outbuf_len);
         2910  +			if (outbuf_p == NULL) {
  2847   2911   				CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x7C tag, returning in failure");
  2848   2912   
  2849   2913   				return(-1);
  2850   2914   			}
  2851   2915   
  2852         -			/* XXX TODO PIV */
  2853         -			memmove(outbuf, outbuf + 8, retval - 8);
  2854         -			retval -= 8;
         2916  +			retval = outbuf_len;
         2917  +
         2918  +			outbuf_len = retval;
         2919  +			outbuf_p = cackey_read_bertlv_tag(outbuf, &outbuf_len, 0x82, NULL,  &outbuf_len);
         2920  +			if (outbuf_p == NULL) {
         2921  +				CACKEY_DEBUG_PRINTF("Response from PIV for GENERATE AUTHENTICATION was not a 0x82 with then 0x7C tag, returning in failure");
         2922  +
         2923  +				return(-1);
         2924  +			}
         2925  +
         2926  +			retval = outbuf_len;
         2927  +
  2855   2928   			break;
  2856   2929   		case CACKEY_ID_TYPE_CAC:
  2857   2930   		case CACKEY_ID_TYPE_CERT_ONLY:
  2858   2931   			break;
  2859   2932   	}
  2860   2933   
  2861   2934   	/* Unpad reply */