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: |
e4a2e1c560669c0c471c79e1aea995a3 |
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 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | } 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) { return(-1); } read_ret = asn1_x509_read_asn1_object(outbuf->wholething.contents, outbuf->wholething.size, &outbuf->certificate, NULL); if (read_ret != 0) { 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) { 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) { return(-1); } return(0); } ssize_t x509_to_issuer(void *x509_der_buf, size_t x509_der_buf_len, void **outbuf) { | > > > > > > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | } 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); } ssize_t x509_to_issuer(void *x509_der_buf, size_t x509_der_buf_len, void **outbuf) { |
︙ | ︙ | |||
190 191 192 193 194 195 196 197 198 199 200 201 202 203 | static ssize_t x509_to_serial(void *x509_der_buf, size_t x509_der_buf_len, void **outbuf) { 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) { return(-1); } if (outbuf) { *outbuf = x509.serial_number.asn1rep; } | > > > | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | static ssize_t x509_to_serial(void *x509_der_buf, size_t x509_der_buf_len, void **outbuf) { 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; } |
︙ | ︙ |
Modified cackey.c from [fd9c15d1e5] to [7a1e8d322f].
︙ | ︙ | |||
63 64 65 66 67 68 69 | #include "pkcs11.h" #include "pkcs11n.h" #include "asn1-x509.h" #include "sha1.h" #include "md5.h" | < < < < < < < < | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | #include "pkcs11.h" #include "pkcs11n.h" #include "asn1-x509.h" #include "sha1.h" #include "md5.h" #ifndef CACKEY_CRYPTOKI_VERSION_CODE # define CACKEY_CRYPTOKI_VERSION_CODE 0x021e00 #endif /* GSC-IS v2.1 Definitions */ /** Classes **/ #define GSCIS_CLASS_ISO7816 0x00 |
︙ | ︙ | |||
226 227 228 229 230 231 232 233 234 235 236 237 238 239 | # define CACKEY_DEBUG_PRINTBUF(f, x, y) { \ static char buf_user[4096] = {0}, *buf_user_p; \ unsigned long buf_user_size; \ unsigned char *TMPBUF; \ unsigned long idx; \ int snprintf_ret; \ TMPBUF = (unsigned char *) (x); \ buf_user_p = buf_user; \ buf_user_size = sizeof(buf_user); \ for (idx = 1; idx < (y); idx++) { \ if (buf_user_size <= 0) { \ break; \ }; \ snprintf_ret = snprintf(buf_user_p, buf_user_size, ", %02x", TMPBUF[idx]); \ | > | 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | # define CACKEY_DEBUG_PRINTBUF(f, x, y) { \ static char buf_user[4096] = {0}, *buf_user_p; \ 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; \ }; \ snprintf_ret = snprintf(buf_user_p, buf_user_size, ", %02x", TMPBUF[idx]); \ |
︙ | ︙ | |||
718 719 720 721 722 723 724 725 726 727 728 729 730 731 | # define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED" # define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED" # 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 typedef enum { CACKEY_ID_TYPE_CAC, CACKEY_ID_TYPE_PIV, CACKEY_ID_TYPE_CERT_ONLY } cackey_pcsc_id_type; struct cackey_pcsc_identity { | > > > > > > > > | 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 | # define CACKEY_DEBUG_FUNC_TAG_TO_STR(x) "DEBUG_DISABLED" # define CACKEY_DEBUG_FUNC_SCARDERR_TO_STR(x) "DEBUG_DISABLED" # 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; struct cackey_pcsc_identity { |
︙ | ︙ | |||
1214 1215 1216 1217 1218 1219 1220 | CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } /* Connect to reader, if needed */ if (!slot->pcsc_card_connected) { | | | 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 | CACKEY_DEBUG_PRINTF("Connection to PC/SC failed, returning in failure"); return(CACKEY_PCSC_E_GENERIC); } /* Connect to reader, if needed */ if (!slot->pcsc_card_connected) { 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); if (scard_conn_ret == SCARD_E_PROTO_MISMATCH) { |
︙ | ︙ | |||
2427 2428 2429 2430 2431 2432 2433 | */ 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]; | | | > > > > | 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 | */ 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, *tmpbuf; unsigned long outidx = 0; char *piv_label; cackey_ret transaction_ret; ssize_t read_ret; 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"); return(NULL); |
︙ | ︙ | |||
2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 | curr_id->certificate = malloc(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; } } } 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) { | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 | curr_id->certificate = malloc(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); 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); /* Look for CARDURLs that coorespond to PKI applets */ for (ccc_curr = ccc_tlv; ccc_curr; ccc_curr = ccc_curr->_next) { |
︙ | ︙ | |||
2635 2636 2637 2638 2639 2640 2641 | curr_id->certificate = malloc(curr_id->certificate_len); memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len); if (outidx >= *count) { if (certs_resizable) { *count *= 2; | > | > > > > | > > > | 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 | curr_id->certificate = malloc(curr_id->certificate_len); memcpy(curr_id->certificate, app_curr->value, curr_id->certificate_len); if (outidx >= *count) { if (certs_resizable) { *count *= 2; if (*count != 0) { certs = realloc(certs, sizeof(*certs) * (*count)); } else { certs = NULL; } } else { break; } } } cackey_free_tlv(app_tlv); if (outidx >= *count) { break; } } cackey_free_tlv(ccc_tlv); } *count = outidx; if (certs_resizable) { 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; /* Terminate SmartCard Transaction */ cackey_end_transaction(slot); |
︙ | ︙ |