Index: asn1-x509.c ================================================================== --- asn1-x509.c +++ asn1-x509.c @@ -133,25 +133,33 @@ static int asn1_x509_read_object(unsigned char *buf, size_t buflen, struct x509_object *outbuf) { int read_ret; read_ret = asn1_x509_read_asn1_object(buf, buflen, &outbuf->wholething, NULL); if (read_ret != 0) { + CACKEY_DEBUG_PRINTF("Failed at reading the contents from the wrapper") + return(-1); } read_ret = asn1_x509_read_asn1_object(outbuf->wholething.contents, outbuf->wholething.size, &outbuf->certificate, NULL); if (read_ret != 0) { + CACKEY_DEBUG_PRINTF("Failed at reading the certificate from the contents"); + return(-1); } 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); if (read_ret != 0) { + CACKEY_DEBUG_PRINTF("Failed at reading the certificate components from the certificate"); + return(-1); } read_ret = asn1_x509_read_asn1_object(outbuf->pubkeyinfo.contents, outbuf->pubkeyinfo.size, &outbuf->pubkey_algoid, &outbuf->pubkey, NULL); if (read_ret != 0) { + CACKEY_DEBUG_PRINTF("Failed at reading the public key from the certificate components"); + return(-1); } return(0); } @@ -192,10 +200,13 @@ struct x509_object x509; int read_ret; read_ret = asn1_x509_read_object(x509_der_buf, x509_der_buf_len, &x509); if (read_ret != 0) { + CACKEY_DEBUG_PRINTF("Unable to read serial number from a %lu byte buffer", x509_der_buf_len); + CACKEY_DEBUG_PRINTBUF("X.509 DER:", x509_der_buf, x509_der_buf_len); + return(-1); } if (outbuf) { *outbuf = x509.serial_number.asn1rep; Index: cackey.c ================================================================== --- cackey.c +++ cackey.c @@ -65,18 +65,10 @@ #include "pkcs11n.h" #include "asn1-x509.h" #include "sha1.h" #include "md5.h" -/* - * Include these source files in this translation unit so that we can bind to - * functions and not include any symbols in the output shared object. - */ -#include "asn1-x509.c" -#include "sha1.c" -#include "md5.c" - #ifndef CACKEY_CRYPTOKI_VERSION_CODE # define CACKEY_CRYPTOKI_VERSION_CODE 0x021e00 #endif /* GSC-IS v2.1 Definitions */ @@ -228,10 +220,11 @@ unsigned long buf_user_size; \ unsigned char *TMPBUF; \ unsigned long idx; \ int snprintf_ret; \ TMPBUF = (unsigned char *) (x); \ + buf_user[0] = 0; \ buf_user_p = buf_user; \ buf_user_size = sizeof(buf_user); \ for (idx = 1; idx < (y); idx++) { \ if (buf_user_size <= 0) { \ break; \ @@ -720,10 +713,18 @@ # define CACKEY_DEBUG_FUNC_OBJID_TO_STR(x) "DEBUG_DISABLED" # define CACKEY_DEBUG_FUNC_APPTYPE_TO_STR(x) "DEBUG_DISABLED" # define CACKEY_DEBUG_FUNC_ATTRIBUTE_TO_STR(x) "DEBUG_DISABLED" #endif +/* + * Include these source files in this translation unit so that we can bind to + * functions and not include any symbols in the output shared object. + */ +#include "asn1-x509.c" +#include "sha1.c" +#include "md5.c" + typedef enum { CACKEY_ID_TYPE_CAC, CACKEY_ID_TYPE_PIV, CACKEY_ID_TYPE_CERT_ONLY } cackey_pcsc_id_type; @@ -1216,11 +1217,11 @@ return(CACKEY_PCSC_E_GENERIC); } /* Connect to reader, if needed */ if (!slot->pcsc_card_connected) { - CACKEY_DEBUG_PRINTF("SCardConnect(%s) called", slot->pcsc_reader); + CACKEY_DEBUG_PRINTF("SCardConnect(%s) called for slot %p", slot->pcsc_reader, slot); scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &slot->pcsc_card, &protocol); if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) { CACKEY_DEBUG_PRINTF("SCardConnect() returned SCARD_E_PROTO_MISMATCH, trying with just T=0") scard_conn_ret = SCardConnect(*cackey_pcsc_handle, slot->pcsc_reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &slot->pcsc_card, &protocol); @@ -2429,20 +2430,24 @@ 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 char buffer[8192], *buffer_p, *tmpbuf; unsigned long outidx = 0; char *piv_label; cackey_ret transaction_ret; ssize_t read_ret; - size_t buffer_len; + size_t buffer_len, tmpbuflen; int certs_resizable; int send_ret, select_ret; int piv_key, piv = 0; int idx; +#ifdef HAVE_LIBZ + int uncompress_ret; + z_stream gzip_stream; +#endif CACKEY_DEBUG_PRINTF("Called."); if (count == NULL) { CACKEY_DEBUG_PRINTF("count is NULL, returning in failure"); @@ -2556,16 +2561,64 @@ 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); + + curr_id->certificate = NULL; outidx--; continue; } + +#ifdef HAVE_LIBZ + if (curr_id->certificate_len > 4) { + if (memcmp(curr_id->certificate, "\x1f\x8b\x08\x00", 4) == 0) { + tmpbuflen = curr_id->certificate_len * 2; + tmpbuf = malloc(tmpbuflen); + + CACKEY_DEBUG_PRINTBUF("Attempting to decompress:", curr_id->certificate, curr_id->certificate_len); + + gzip_stream.zalloc = NULL; + gzip_stream.zfree = NULL; + gzip_stream.opaque = NULL; + + gzip_stream.next_in = curr_id->certificate; + gzip_stream.avail_in = curr_id->certificate_len; + gzip_stream.next_out = tmpbuf; + gzip_stream.avail_out = tmpbuflen; + + uncompress_ret = inflateInit(&gzip_stream); + if (uncompress_ret == Z_OK) { + uncompress_ret = inflateReset2(&gzip_stream, 31); + } + if (uncompress_ret == Z_OK) { + uncompress_ret = inflate(&gzip_stream, 0); + } + if (uncompress_ret == Z_STREAM_END) { + uncompress_ret = inflateEnd(&gzip_stream); + } else { + uncompress_ret = Z_DATA_ERROR; + } + if (uncompress_ret == Z_OK) { + CACKEY_DEBUG_PRINTBUF("Decompressed to:", tmpbuf, tmpbuflen); + + free(curr_id->certificate); + + curr_id->certificate = tmpbuf; + curr_id->certificate_len = tmpbuflen; + } else { + CACKEY_DEBUG_PRINTF("Decompressing failed! uncompress() returned %i", uncompress_ret); + + free(tmpbuf); + } + } + } +#endif } } else { /* Read all the applets from the CCC's TLV */ ccc_tlv = cackey_read_tlv(slot); @@ -2637,11 +2690,15 @@ memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len); if (outidx >= *count) { if (certs_resizable) { *count *= 2; - certs = realloc(certs, sizeof(*certs) * (*count)); + if (*count != 0) { + certs = realloc(certs, sizeof(*certs) * (*count)); + } else { + certs = NULL; + } } else { break; } } } @@ -2657,11 +2714,15 @@ } *count = outidx; if (certs_resizable) { - certs = realloc(certs, sizeof(*certs) * (*count)); + if (*count != 0) { + certs = realloc(certs, sizeof(*certs) * (*count)); + } else { + certs = NULL; + } } slot->cached_certs = cackey_copy_certs(NULL, certs, *count); slot->cached_certs_count = *count;