int main(int argc, char **argv) { FILE *f; int i; struct sc *sc; struct emu_fs *fs; if (argc == 1 || !strcmp(argv[1], "-")) f = stdout; else f = fopen(argv[1], "w"); if (!f) { perror("fopen"); return 1; } sc = scard_init(NULL); if (!sc) { printf("Cannot init scard\n"); fclose(f); return 1; } scard_connect(sc, 0); if (scard_is_error(sc)) { printf("%s\n", scard_error(sc)); fclose(f); return 1; } fs = emu_fs_new(); for (i = 0; apps[i].name_len != 0; i++) emu_fs_append(fs, read_df(f, sc, apps[i].name, apps[i].name_len)); emu_fs_dump(fs, f); fclose(f); emu_fs_free(fs); 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, 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 unsigned char *sc_command_t0(struct sc *sc, unsigned char cla, unsigned char ins, unsigned char p1, unsigned char p2, size_t dlen, const unsigned char *data, unsigned short *psw, size_t *olen ) { unsigned char buf[4 + 1 + dlen]; unsigned char cmdbuf[5] = {cla, ins, p1, p2, 0}; unsigned short force_sw = 0; size_t opos = 0; size_t osize = 256 + 2; size_t ret; unsigned char *obuf; memcpy(buf, cmdbuf, 4); buf[4] = dlen; if (data != NULL) { memcpy(buf + 5, data, dlen); } obuf = malloc(osize); ret = scard_transmit(sc, buf, 5 + dlen, obuf + opos, osize - opos); if (scard_is_error(sc)) { free(obuf); if (olen) *olen = 0; return NULL; } if (ret != 2) { scard_raise_error(sc, SCARD_CARD); free(obuf); if (olen) *olen = 0; return NULL; } /* obuf + opos .. obuf + opos + ret - 1 contains last R-APDU with SW on the end */ while (1) { unsigned short sw = (obuf[opos + ret - 2] << 8) | obuf[opos + ret - 1]; ret -= 2; opos += ret; if (sw == 0x9000) { *psw = force_sw ? : sw; if (olen) *olen = opos; if (ret == 0 || !olen) { free(obuf); obuf = NULL; } return obuf; } switch (sw & 0xff00) { case 0x6200: case 0x6300: case 0x9000 ... 0x9f00: force_sw = sw; sw = 0x6100; /* fallthrough */ case 0x6100: cmdbuf[0] = 0x00; cmdbuf[1] = 0xc0; cmdbuf[2] = 0x00; cmdbuf[3] = 0x00; cmdbuf[4] = sw & 0xff; break; case 0x6c00: cmdbuf[4] = sw & 0xff; break; default: if (olen) *olen = 0; *psw = sw; if (opos != 0) { scard_raise_error(sc, SCARD_CARD); } free(obuf); return NULL; } if (opos + cmdbuf[4] + 2 > osize) { scard_raise_error(sc, SCARD_CARD); free(obuf); if (olen) *olen = 0; return NULL; } ret = scard_transmit(sc, cmdbuf, 5, obuf + opos, osize - opos); if (scard_is_error(sc)) { free(obuf); if (olen) *olen = 0; return NULL; } }
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; }