Check-in [e4a2e1c560]
Overview
Comment:Added debugging to ASN.1 X.509 parser, added support for gzip'd certificates, and fixed a possible non-deterministic case with realloc(0)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e4a2e1c560669c0c471c79e1aea995a3f165289c
User & Date: rkeene on 2015-03-05 15:48:58
Other Links: manifest | tags
Context
2015-03-05
16:06
Updated to deal with reading impossibly small TLV buffers sanely check-in: 614742ca67 user: rkeene tags: trunk
15:48
Added debugging to ASN.1 X.509 parser, added support for gzip'd certificates, and fixed a possible non-deterministic case with realloc(0) check-in: e4a2e1c560 user: rkeene tags: trunk
2014-10-21
23:01
Updated email addresses, cleaned up Mac OS X build script, and modified the Mac OS X build script to work on a build host running Mac OS X 10.10 (Yosemite). check-in: f44c5c32ff user: kvanals tags: trunk
Changes

Modified asn1-x509.c from [e21185aa9d] to [f9aa197383].

   131    131   }
   132    132   
   133    133   static int asn1_x509_read_object(unsigned char *buf, size_t buflen, struct x509_object *outbuf) {
   134    134   	int read_ret;
   135    135   
   136    136   	read_ret = asn1_x509_read_asn1_object(buf, buflen, &outbuf->wholething, NULL);
   137    137   	if (read_ret != 0) {
          138  +		CACKEY_DEBUG_PRINTF("Failed at reading the contents from the wrapper")
          139  +
   138    140   		return(-1);
   139    141   	}
   140    142   
   141    143   	read_ret = asn1_x509_read_asn1_object(outbuf->wholething.contents, outbuf->wholething.size, &outbuf->certificate, NULL);
   142    144   	if (read_ret != 0) {
          145  +		CACKEY_DEBUG_PRINTF("Failed at reading the certificate from the contents");
          146  +
   143    147   		return(-1);
   144    148   	}
   145    149   
   146    150   	read_ret = asn1_x509_read_asn1_object(outbuf->certificate.contents, outbuf->certificate.size, &outbuf->version, &outbuf->serial_number, &outbuf->signature_algo, &outbuf->issuer, &outbuf->validity, &outbuf->subject, &outbuf->pubkeyinfo, NULL);
   147    151   	if (read_ret != 0) {
          152  +		CACKEY_DEBUG_PRINTF("Failed at reading the certificate components from the certificate");
          153  +
   148    154   		return(-1);
   149    155   	}
   150    156   
   151    157   	read_ret = asn1_x509_read_asn1_object(outbuf->pubkeyinfo.contents, outbuf->pubkeyinfo.size, &outbuf->pubkey_algoid, &outbuf->pubkey, NULL);
   152    158   	if (read_ret != 0) {
          159  +		CACKEY_DEBUG_PRINTF("Failed at reading the public key from the certificate components");
          160  +
   153    161   		return(-1);
   154    162   	}
   155    163   
   156    164   	return(0);
   157    165   }
   158    166   
   159    167   ssize_t x509_to_issuer(void *x509_der_buf, size_t x509_der_buf_len, void **outbuf) {
................................................................................
   190    198   
   191    199   static ssize_t x509_to_serial(void *x509_der_buf, size_t x509_der_buf_len, void **outbuf) {
   192    200   	struct x509_object x509;
   193    201   	int read_ret;
   194    202   
   195    203   	read_ret = asn1_x509_read_object(x509_der_buf, x509_der_buf_len, &x509);
   196    204   	if (read_ret != 0) {
          205  +		CACKEY_DEBUG_PRINTF("Unable to read serial number from a %lu byte buffer", x509_der_buf_len);
          206  +		CACKEY_DEBUG_PRINTBUF("X.509 DER:", x509_der_buf, x509_der_buf_len);
          207  +
   197    208   		return(-1);
   198    209   	}
   199    210   
   200    211   	if (outbuf) {
   201    212   		*outbuf = x509.serial_number.asn1rep;
   202    213   	}
   203    214   

Modified cackey.c from [fd9c15d1e5] to [7a1e8d322f].

    63     63   
    64     64   #include "pkcs11.h"
    65     65   #include "pkcs11n.h"
    66     66   #include "asn1-x509.h"
    67     67   #include "sha1.h"
    68     68   #include "md5.h"
    69     69   
    70         -/*
    71         - * Include these source files in this translation unit so that we can bind to
    72         - * functions and not include any symbols in the output shared object.
    73         - */
    74         -#include "asn1-x509.c"
    75         -#include "sha1.c"
    76         -#include "md5.c"
    77         -
    78     70   #ifndef CACKEY_CRYPTOKI_VERSION_CODE
    79     71   #  define CACKEY_CRYPTOKI_VERSION_CODE 0x021e00
    80     72   #endif
    81     73   
    82     74   /* GSC-IS v2.1 Definitions */
    83     75   /** Classes **/
    84     76   #define GSCIS_CLASS_ISO7816           0x00
................................................................................
   226    218   #  define CACKEY_DEBUG_PRINTBUF(f, x, y) { \
   227    219   	static char buf_user[4096] = {0}, *buf_user_p; \
   228    220   	unsigned long buf_user_size; \
   229    221   	unsigned char *TMPBUF; \
   230    222   	unsigned long idx; \
   231    223   	int snprintf_ret; \
   232    224   	TMPBUF = (unsigned char *) (x); \
          225  +	buf_user[0] = 0; \
   233    226   	buf_user_p = buf_user; \
   234    227   	buf_user_size = sizeof(buf_user); \
   235    228   	for (idx = 1; idx < (y); idx++) { \
   236    229   		if (buf_user_size <= 0) { \
   237    230   			break; \
   238    231   		}; \
   239    232   		snprintf_ret = snprintf(buf_user_p, buf_user_size, ", %02x", TMPBUF[idx]); \
................................................................................
   718    711   #  define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED"
   719    712   #  define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED"
   720    713   #  define CACKEY_DEBUG_FUNC_OBJID_TO_STR(x) "DEBUG_DISABLED"
   721    714   #  define CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(x) "DEBUG_DISABLED"
   722    715   #  define CACKEY_DEBUG_FUNC_ATTRIBUTE_TO_STR(x) "DEBUG_DISABLED"
   723    716   #endif
   724    717   
          718  +/*
          719  + * Include these source files in this translation unit so that we can bind to
          720  + * functions and not include any symbols in the output shared object.
          721  + */
          722  +#include "asn1-x509.c"
          723  +#include "sha1.c"
          724  +#include "md5.c"
          725  +
   725    726   typedef enum {
   726    727   	CACKEY_ID_TYPE_CAC,
   727    728   	CACKEY_ID_TYPE_PIV,
   728    729   	CACKEY_ID_TYPE_CERT_ONLY
   729    730   } cackey_pcsc_id_type;
   730    731   
   731    732   struct cackey_pcsc_identity {
................................................................................
  1214   1215   		CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure");
  1215   1216   
  1216   1217   		return(CACKEY_PCSC_E_GENERIC);
  1217   1218   	}
  1218   1219   
  1219   1220   	/* Connect to reader, if needed */
  1220   1221   	if (!slot->pcsc_card_connected) {
  1221         -		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader);
         1222  +		CACKEY_DEBUG_PRINTF("SCardConnect(%s) called for slot %p", slot->pcsc_reader, slot);
  1222   1223   		scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol);
  1223   1224   
  1224   1225   		if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
  1225   1226   			CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0")
  1226   1227   			scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol);
  1227   1228   
  1228   1229   			if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) {
................................................................................
  2427   2428    */
  2428   2429   static struct cackey_pcsc_identity *cackey_read_certs(struct cackey_slot *slot, struct cackey_pcsc_identity *certs, unsigned long *count) {
  2429   2430   	struct cackey_pcsc_identity *curr_id;
  2430   2431   	struct cackey_tlv_entity *ccc_tlv, *ccc_curr, *app_tlv, *app_curr;
  2431   2432   	unsigned char ccc_aid[] = {GSCIS_AID_CCC}, piv_aid[] = {NISTSP800_73_3_PIV_AID};
  2432   2433   	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};
  2433   2434   	unsigned char curr_aid[7];
  2434         -	unsigned char buffer[8192], *buffer_p;
         2435  +	unsigned char buffer[8192], *buffer_p, *tmpbuf;
  2435   2436   	unsigned long outidx = 0;
  2436   2437   	char *piv_label;
  2437   2438   	cackey_ret transaction_ret;
  2438   2439   	ssize_t read_ret;
  2439         -	size_t buffer_len;
         2440  +	size_t buffer_len, tmpbuflen;
  2440   2441   	int certs_resizable;
  2441   2442   	int send_ret, select_ret;
  2442   2443   	int piv_key, piv = 0;
  2443   2444   	int idx;
         2445  +#ifdef HAVE_LIBZ
         2446  +	int uncompress_ret;
         2447  +	z_stream gzip_stream;
         2448  +#endif
  2444   2449   
  2445   2450   	CACKEY_DEBUG_PRINTF("Called.");
  2446   2451   
  2447   2452   	if (count == NULL) {
  2448   2453   		CACKEY_DEBUG_PRINTF("count is NULL, returning in failure");
  2449   2454   
  2450   2455   		return(NULL);
................................................................................
  2554   2559   			curr_id->certificate = malloc(curr_id->certificate_len);
  2555   2560   
  2556   2561   			buffer_len = sizeof(buffer);
  2557   2562   			buffer_p = cackey_read_bertlv_tag(buffer, &buffer_len, 0x70, curr_id->certificate, &curr_id->certificate_len);
  2558   2563   
  2559   2564   			if (buffer_p == NULL) {
  2560   2565   				CACKEY_DEBUG_PRINTF("Reading certificate from BER-TLV response failed, skipping key %i", idx);
         2566  +
  2561   2567   				free(curr_id->certificate);
         2568  +
         2569  +				curr_id->certificate = NULL;
  2562   2570   
  2563   2571   				outidx--;
  2564   2572   
  2565   2573   				continue;
  2566   2574   			}
         2575  +
         2576  +#ifdef HAVE_LIBZ
         2577  +			if (curr_id->certificate_len > 4) {
         2578  +				if (memcmp(curr_id->certificate, "\x1f\x8b\x08\x00", 4) == 0) {
         2579  +					tmpbuflen = curr_id->certificate_len * 2;
         2580  +					tmpbuf = malloc(tmpbuflen);
         2581  +
         2582  +					CACKEY_DEBUG_PRINTBUF("Attempting to decompress:", curr_id->certificate, curr_id->certificate_len);
         2583  +
         2584  +					gzip_stream.zalloc = NULL;
         2585  +					gzip_stream.zfree = NULL;
         2586  +					gzip_stream.opaque = NULL;
         2587  +
         2588  +					gzip_stream.next_in  = curr_id->certificate;
         2589  +					gzip_stream.avail_in = curr_id->certificate_len;
         2590  +					gzip_stream.next_out = tmpbuf;
         2591  +					gzip_stream.avail_out = tmpbuflen;
         2592  +
         2593  +					uncompress_ret = inflateInit(&gzip_stream);
         2594  +					if (uncompress_ret == Z_OK) {
         2595  +						uncompress_ret = inflateReset2(&gzip_stream, 31);
         2596  +					}
         2597  +					if (uncompress_ret == Z_OK) {
         2598  +						uncompress_ret = inflate(&gzip_stream, 0);
         2599  +					}
         2600  +					if (uncompress_ret == Z_STREAM_END) {
         2601  +						uncompress_ret = inflateEnd(&gzip_stream);
         2602  +					} else {
         2603  +						uncompress_ret = Z_DATA_ERROR;
         2604  +					}
         2605  +					if (uncompress_ret == Z_OK) {
         2606  +						CACKEY_DEBUG_PRINTBUF("Decompressed to:", tmpbuf, tmpbuflen);
         2607  +
         2608  +						free(curr_id->certificate);
         2609  +
         2610  +						curr_id->certificate = tmpbuf;
         2611  +						curr_id->certificate_len = tmpbuflen;
         2612  +					} else {
         2613  +						CACKEY_DEBUG_PRINTF("Decompressing failed! uncompress() returned %i", uncompress_ret);
         2614  +
         2615  +						free(tmpbuf);
         2616  +					}
         2617  +				}
         2618  +			}
         2619  +#endif
  2567   2620   		}
  2568   2621   	} else {
  2569   2622   		/* Read all the applets from the CCC's TLV */
  2570   2623   		ccc_tlv = cackey_read_tlv(slot);
  2571   2624   
  2572   2625   		/* Look for CARDURLs that coorespond to PKI applets */
  2573   2626   		for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) {
................................................................................
  2635   2688   
  2636   2689   				curr_id->certificate = malloc(curr_id->certificate_len);
  2637   2690   				memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len);
  2638   2691   
  2639   2692   				if (outidx >= *count) {
  2640   2693   					if (certs_resizable) {
  2641   2694   						*count *= 2;
  2642         -						certs = realloc(certs, sizeof(*certs) * (*count));
         2695  +						if (*count != 0) {
         2696  +							certs = realloc(certs, sizeof(*certs) * (*count));
         2697  +						} else {
         2698  +							certs = NULL;
         2699  +						}
  2643   2700   					} else {
  2644   2701   						break;
  2645   2702   					}
  2646   2703   				}
  2647   2704   			}
  2648   2705   
  2649   2706   			cackey_free_tlv(app_tlv);
................................................................................
  2655   2712   
  2656   2713   		cackey_free_tlv(ccc_tlv);
  2657   2714   	}
  2658   2715   
  2659   2716   	*count = outidx;
  2660   2717   
  2661   2718   	if (certs_resizable) {
  2662         -		certs = realloc(certs, sizeof(*certs) * (*count));
         2719  +		if (*count != 0) {
         2720  +			certs = realloc(certs, sizeof(*certs) * (*count));
         2721  +		} else {
         2722  +			certs = NULL;
         2723  +		}
  2663   2724   	}
  2664   2725   
  2665   2726   	slot->cached_certs = cackey_copy_certs(NULL, certs, *count);
  2666   2727   	slot->cached_certs_count = *count;
  2667   2728   
  2668   2729   	/* Terminate SmartCard Transaction */
  2669   2730   	cackey_end_transaction(slot);