static int cda_test_pk(void) { const struct emv_pk *pk = &mchip_05; struct tlvdb *db; db = tlvdb_external(0x90, sizeof(issuer_cert), issuer_cert); tlvdb_add(db, tlvdb_external(0x9f32, sizeof(issuer_exp), issuer_exp)); tlvdb_add(db, tlvdb_external(0x92, sizeof(issuer_rem), issuer_rem)); tlvdb_add(db, tlvdb_external(0x5a, sizeof(pan), pan)); struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db); if (!ipk) { fprintf(stderr, "Could not recover Issuer certificate!\n"); tlvdb_free(db); return 2; } tlvdb_add(db, tlvdb_external(0x9f46, sizeof(icc_cert), icc_cert)); tlvdb_add(db, tlvdb_external(0x9f47, sizeof(icc_exp), icc_exp)); /*tlvdb_add(db, tlvdb_external(0x9f48, sizeof(issuer_rem), issuer_rem));*/ struct emv_pk *iccpk = emv_pki_recover_icc_cert(ipk, db, &ssd1_tlv); if (!iccpk) { fprintf(stderr, "Could not recover ICC certificate!\n"); emv_pk_free(ipk); tlvdb_free(db); return 2; } tlvdb_add(db, tlvdb_fixed(0x9f37, sizeof(dd1), dd1)); struct tlvdb *cda_db; cda_db = tlvdb_fixed(0x9f27, 1, (unsigned char[]){ 0x40 });
struct tlvdb *dol_parse(const struct tlv *tlv, const unsigned char *data, size_t data_len) { if (!tlv) return NULL; const unsigned char *buf = tlv->value; size_t left = tlv->len; size_t res_len = dol_calculate_len(tlv, data_len); size_t pos = 0; struct tlvdb *db = NULL; if (res_len != data_len) return NULL; while (left) { struct tlv cur_tlv; if (!tlv_parse_tl(&buf, &left, &cur_tlv) || pos + cur_tlv.len > res_len) { tlvdb_free(db); return NULL; } /* Last tag can be of variable length */ if (cur_tlv.len == 0 && left == 0) cur_tlv.len = res_len - pos; struct tlvdb *tag_db = tlvdb_fixed(cur_tlv.tag, cur_tlv.len, data + pos); if (!db) db = tag_db; else tlvdb_add(db, tag_db); pos += cur_tlv.len; } return db; }
static int sda_test_pk(void) { const struct emv_pk *pk = &vsdc_01; struct tlvdb *db; db = tlvdb_external(0x90, sizeof(issuer_cert), issuer_cert); tlvdb_add(db, tlvdb_external(0x9f32, sizeof(issuer_exp), issuer_exp)); tlvdb_add(db, tlvdb_external(0x92, sizeof(issuer_rem), issuer_rem)); struct emv_pk *ipk = emv_pki_recover_issuer_cert(pk, db); if (!ipk) { fprintf(stderr, "Could not recover Issuer certificate!\n"); tlvdb_free(db); return 2; } tlvdb_add(db, tlvdb_external(0x93, sizeof(ssad_cr), ssad_cr)); struct tlvdb *dacdb = emv_pki_recover_dac(ipk, db, ssd1, sizeof(ssd1)); if (!dacdb) { fprintf(stderr, "Could not recover DAC!\n"); emv_pk_free(ipk); tlvdb_free(db); return 2; } const struct tlv *dac = tlvdb_get(dacdb, 0x9f45, NULL); if (!dac) { fprintf(stderr, "DAC not found!\n"); tlvdb_free(dacdb); emv_pk_free(ipk); tlvdb_free(db); return 2; } dump_buffer(dac->value, dac->len, stdout); tlvdb_free(dacdb); emv_pk_free(ipk); tlvdb_free(db); 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, 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; }
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, 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; }