static void build_cap(struct tlvdb *db) { const struct tlv *ipb = tlvdb_get(db, 0x9f56, NULL); ipb_dol_value[sizeof(ipb_dol_value) - 1] = ipb->len - (1 + 1 + 2 + 8); struct tlv *ipb_data_tlv = dol_process(&ipb_dol, db, 0); if (!ipb_data_tlv) return; dump_buffer(ipb_data_tlv->value, ipb_data_tlv->len, stdout); dump_buffer(ipb->value, ipb->len, stdout); if (ipb_data_tlv->len < ipb->len) { free(ipb_data_tlv); return; } unsigned char buf[ipb->len]; int i, j, k = 0; unsigned char c = 0; for (i = ipb->len; i > 0; i--) { for (j = 0; j < 8; j++) { if ((ipb->value[i-1] & (1 << j)) == 0) continue; c |= ((ipb_data_tlv->value[i-1] >> j) & 1) << (k % 8); k++; if (k % 8 != 0) continue; buf[k / 8 - 1] = c; c = 0; } } free(ipb_data_tlv); if (k % 8 != 0) { k += 8 - (k % 8); buf[k / 8 - 1] = c; } k /= 8; unsigned long data = 0; for (i = 0; i < k; i++) data |= ((unsigned long) buf[i]) << (8 * i); dump_buffer(buf, k, stdout); fprintf(stdout, "CAP data: %lu\n", data); }
static struct emu_df *read_df(FILE *f, struct sc *sc, const unsigned char *name, size_t name_len) { struct emu_df *df; int i, j; struct tlvdb *s; unsigned short sw; size_t outlen; unsigned char *outbuf; struct tlv pdol_data_tlv; size_t pdol_data_len; unsigned char *pdol_data; outbuf = sc_command(sc, 0x00, 0xa4, 0x04, 0x00, name_len, name, &sw, &outlen); if (sw != 0x9000) return NULL; s = tlvdb_parse(outbuf, outlen); if (!s) return NULL; df = emu_df_new(); pdol_data_tlv.tag = 0x83; pdol_data_tlv.value = dol_process(tlvdb_get(s, 0x9f38, NULL), s, &pdol_data_tlv.len); pdol_data = tlv_encode(&pdol_data_tlv, &pdol_data_len); if (!pdol_data) return NULL; free((unsigned char *)pdol_data_tlv.value); tlvdb_free(s); emu_df_append(df, emu_property_new("name", emu_value_new_buf(name, name_len))); emu_df_append(df, emu_property_new("fci", emu_value_new_buf(outbuf, outlen))); free(outbuf); outbuf = sc_command(sc, 0x80, 0xa8, 0x00, 0x00, pdol_data_len, pdol_data, &sw, &outlen); free(pdol_data); if (sw == 0x9000) { emu_df_append(df, emu_property_new("gpo", emu_value_new_buf(outbuf, outlen))); free(outbuf); } for (i = 1; i < 31; i++) { int last = 0; struct emu_value *value = NULL; char buf[7]; snprintf(buf, sizeof(buf), "sfi%d", i); for (j = 1; j < 256; j++) { outbuf = sc_command(sc, 0x00, 0xb2, j, (i << 3) | 4, 0, NULL, &sw, &outlen); if (sw == 0x6985) continue; else if (sw != 0x9000) break; for (; last < j - 1; last++) value = emu_value_append(value, ""); value = emu_value_append_buf(value, outbuf, outlen); last ++; free(outbuf); } if (value) emu_df_append(df, emu_property_new(buf, value)); } for (i = 0; card_data[i]; i++) { char buf[10]; tlv_tag_t tag = card_data[i]; outbuf = sc_command(sc, 0x80, 0xca, tag >> 8, tag & 0xff, 0, NULL, &sw, &outlen); if (sw != 0x9000) continue; snprintf(buf, sizeof(buf), "data%x", tag); emu_df_append(df, emu_property_new(buf, emu_value_new_buf(outbuf, outlen))); free(outbuf); } return df; }
int main(void) { int i; struct sc *sc; sc = scard_init(NULL); if (!sc) { printf("Cannot init scard\n"); return 1; } scard_connect(sc, openemv_config_get_int("scard.reader", 0)); if (scard_is_error(sc)) { printf("%s\n", scard_error(sc)); return 1; } struct tlvdb *s; struct tlvdb *t; for (i = 0, s = NULL; apps[i].name_len != 0; i++) { const struct tlv aid_tlv = { .len = apps[i].name_len, .value = apps[i].name, }; s = emv_select(sc, &aid_tlv); if (s) break; } if (!s) return 1; struct tlv *pdol_data_tlv = dol_process(tlvdb_get(s, 0x9f38, NULL), s, 0x83); if (!pdol_data_tlv) return 1; t = emv_gpo(sc, pdol_data_tlv); free(pdol_data_tlv); if (!t) return 1; tlvdb_add(s, t); struct tlv *sda_tlv = emv_read_records(sc, s); if (!sda_tlv) return 1; /* Only PTC read should happen before VERIFY */ tlvdb_add(s, emv_get_data(sc, 0x9f17)); verify_offline_clear(s, sc); #define TAG(tag, len, value...) tlvdb_add(s, tlvdb_fixed(tag, len, (unsigned char[]){value})) // TAG(0x9f02, 6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); // TAG(0x9f1a, 2, 0x06, 0x43); TAG(0x95, 5, 0x80, 0x00, 0x00, 0x00, 0x00); // TAG(0x5f2a, 2, 0x06, 0x43); // TAG(0x9a, 3, 0x14, 0x09, 0x25); // TAG(0x9c, 1, 0x50); // TAG(0x9f37, 4, 0x12, 0x34, 0x57, 0x79); TAG(0x9f35, 1, 0x34); TAG(0x9f34, 3, 0x01, 0x00, 0x02); #undef TAG /* Generate ARQC */ struct tlv *crm_tlv = dol_process(tlvdb_get(s, 0x8c, NULL), s, 0); if (!crm_tlv) return 1; t = emv_generate_ac(sc, 0x80, crm_tlv); free(crm_tlv); tlvdb_add(s, t); build_cap(s); #define TAG(tag, len, value...) tlvdb_add(s, tlvdb_fixed(tag, len, (unsigned char[]){value})) TAG(0x8a, 2, 'Z', '3'); #undef TAG /* Generate AC asking for AAC */ crm_tlv = dol_process(tlvdb_get(s, 0x8d, NULL), s, 0); if (!crm_tlv) return 1; t = emv_generate_ac(sc, 0x00, crm_tlv); free(crm_tlv); tlvdb_add(s, t); tlvdb_visit(s, print_cb, NULL); tlvdb_free(s); scard_disconnect(sc); if (scard_is_error(sc)) { printf("%s\n", scard_error(sc)); return 1; } scard_shutdown(sc); return 0; }
int main(void) { int i; struct sc *sc; sc = scard_init(NULL); if (!sc) { printf("Cannot init scard\n"); return 1; } scard_connect(sc, 0); if (scard_is_error(sc)) { printf("%s\n", scard_error(sc)); return 1; } struct tlvdb *s; struct tlvdb *t; for (i = 0, s = NULL; apps[i].name_len != 0; i++) { s = emv_select(sc, apps[i].name, apps[i].name_len); if (s) break; } if (!s) return 1; size_t pdol_data_len; unsigned char *pdol_data = dol_process(tlvdb_get(s, 0x9f38, NULL), s, &pdol_data_len); struct tlv pdol_data_tlv = { .tag = 0x83, .len = pdol_data_len, .value = pdol_data }; size_t pdol_data_tlv_data_len; unsigned char *pdol_data_tlv_data = tlv_encode(&pdol_data_tlv, &pdol_data_tlv_data_len); free(pdol_data); if (!pdol_data_tlv_data) return 1; t = emv_gpo(sc, pdol_data_tlv_data, pdol_data_tlv_data_len); free(pdol_data_tlv_data); if (!t) return 1; tlvdb_add(s, t); unsigned char *sda_data = NULL; size_t sda_len = 0; bool ok = emv_read_records(sc, s, &sda_data, &sda_len); if (!ok) return 1; free(sda_data); /* Generate AC asking for AAC */ size_t crm_data_len; unsigned char *crm_data = dol_process(tlvdb_get(s, 0x8c, NULL), s, &crm_data_len); t = emv_generate_ac(sc, 0x00, crm_data, crm_data_len); free(crm_data); tlvdb_add(s, t); tlvdb_add(s, emv_get_data(sc, 0x9f36)); tlvdb_add(s, emv_get_data(sc, 0x9f13)); tlvdb_add(s, emv_get_data(sc, 0x9f17)); tlvdb_add(s, emv_get_data(sc, 0x9f4f)); tlvdb_visit(s, print_cb, NULL); const struct tlv *logent_tlv = tlvdb_get(s, 0x9f4d, NULL); const struct tlv *logent_dol = tlvdb_get(s, 0x9f4f, NULL); if (logent_tlv && logent_tlv->len == 2 && logent_dol) { for (i = 1; i <= logent_tlv->value[1]; i++) { unsigned short sw; size_t log_len; unsigned char *log = emv_read_record(sc, logent_tlv->value[0], i, &sw, &log_len); if (!log) continue; if (sw == 0x9000) { printf("Log #%d\n", i); struct tlvdb *log_db = dol_parse(logent_dol, log, log_len); tlvdb_visit(log_db, print_cb, NULL); tlvdb_free(log_db); } free(log); } } tlvdb_free(s); scard_disconnect(sc); if (scard_is_error(sc)) { printf("%s\n", scard_error(sc)); return 1; } scard_shutdown(sc); return 0; }