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
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
...
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
}
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) {
................................................................................
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;
}
|
>
>
>
>
>
>
>
>
>
>
>
|
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
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
|
} 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) { ................................................................................ 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 ... 226 227 228 229 230 231 232 233 234 235 236 237 238 239 ... 718 719 720 721 722 723 724 725 726 727 728 729 730 731 .... 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 .... 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 .... 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 .... 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 .... 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 |
#include "pkcs11.h" #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 */ /** Classes **/ #define GSCIS_CLASS_ISO7816 0x00 ................................................................................ # 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]); \ ................................................................................ # 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 { ................................................................................ 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", slot->pcsc_reader); 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) { ................................................................................ */ 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; char *piv_label; 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."); if (count == NULL) { CACKEY_DEBUG_PRINTF("count is NULL, returning in failure"); return(NULL); ................................................................................ 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) { ................................................................................ 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; certs = realloc(certs, sizeof(*certs) * (*count)); } else { break; } } } cackey_free_tlv(app_tlv); ................................................................................ cackey_free_tlv(ccc_tlv); } *count = outidx; if (certs_resizable) { certs = realloc(certs, sizeof(*certs) * (*count)); } slot->cached_certs = cackey_copy_certs(NULL, certs, *count); slot->cached_certs_count = *count; /* Terminate SmartCard Transaction */ cackey_end_transaction(slot); |
< < < < < < < < > > > > > > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | > > > |
63 64 65 66 67 68 69 70 71 72 73 74 75 76 ... 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 ... 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 .... 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 .... 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 .... 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 .... 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 .... 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 |
#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 ................................................................................ # 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]); \ ................................................................................ # 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 { ................................................................................ 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) { ................................................................................ */ 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); ................................................................................ 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) { ................................................................................ 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); ................................................................................ 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); |