static int scard_test(void) { struct scard_data *scard; size_t len; char imsi[20]; unsigned char rand[16]; unsigned char sres[4]; unsigned char kc[8]; const int num_triplets = 5; unsigned char rand_[num_triplets][16]; unsigned char sres_[num_triplets][4]; unsigned char kc_[num_triplets][8]; int i, j; scard = scard_init(SCARD_TRY_BOTH, "1234"); if (scard == NULL) return -1; len = sizeof(imsi); if (scard_get_imsi(scard, imsi, &len)) goto failed; wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", imsi, len); /* NOTE: Permanent Username: 1 | IMSI */ memset(rand, 0, sizeof(rand)); if (scard_gsm_auth(scard, rand, sres, kc)) goto failed; memset(rand, 0xff, sizeof(rand)); if (scard_gsm_auth(scard, rand, sres, kc)) goto failed; for (i = 0; i < num_triplets; i++) { memset(rand_[i], i, sizeof(rand_[i])); if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i])) goto failed; } for (i = 0; i < num_triplets; i++) { printf("1"); for (j = 0; j < len; j++) printf("%c", imsi[j]); printf(","); for (j = 0; j < 16; j++) printf("%02X", rand_[i][j]); printf(","); for (j = 0; j < 4; j++) printf("%02X", sres_[i][j]); printf(","); for (j = 0; j < 8; j++) printf("%02X", kc_[i][j]); printf("\n"); } failed: scard_deinit(scard); return 0; }
/** * wpa_supplicant_scard_init - Initialize SIM/USIM access with PC/SC * @wpa_s: pointer to wpa_supplicant data * @ssid: Configuration data for the network * Returns: 0 on success, -1 on failure * * This function is called when starting authentication with a network that is * configured to use PC/SC for SIM/USIM access (EAP-SIM or EAP-AKA). */ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { #ifdef IEEE8021X_EAPOL int aka = 0, sim = 0, type; if (ssid->eap.pcsc == NULL || wpa_s->scard != NULL) return 0; if (ssid->eap.eap_methods == NULL) { sim = 1; aka = 1; } else { struct eap_method_type *eap = ssid->eap.eap_methods; while (eap->vendor != EAP_VENDOR_IETF || eap->method != EAP_TYPE_NONE) { if (eap->vendor == EAP_VENDOR_IETF) { if (eap->method == EAP_TYPE_SIM) sim = 1; else if (eap->method == EAP_TYPE_AKA) aka = 1; } eap++; } } if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_SIM) == NULL) sim = 0; if (eap_peer_get_eap_method(EAP_VENDOR_IETF, EAP_TYPE_AKA) == NULL) aka = 0; if (!sim && !aka) { wpa_printf(MSG_DEBUG, "Selected network is configured to use " "SIM, but neither EAP-SIM nor EAP-AKA are enabled"); return 0; } wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM " "(sim=%d aka=%d) - initialize PCSC", sim, aka); if (sim && aka) type = SCARD_TRY_BOTH; else if (aka) type = SCARD_USIM_ONLY; else type = SCARD_GSM_SIM_ONLY; wpa_s->scard = scard_init(type); if (wpa_s->scard == NULL) { wpa_printf(MSG_WARNING, "Failed to initialize SIM " "(pcsc-lite)"); return -1; } wpa_sm_set_scard_ctx(wpa_s->wpa, wpa_s->scard); eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); #endif /* IEEE8021X_EAPOL */ return 0; }
static int scard_get_triplets(int argc, char *argv[]) { struct scard_data *scard; size_t len; char imsi[20]; unsigned char rand[16]; unsigned char sres[4]; unsigned char kc[8]; int num_triplets; int i, j; if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) { printf("invalid parameters for sim command\n"); return -1; } if (argc <= 2 || strcmp(argv[2], "debug") != 0) { /* disable debug output */ wpa_debug_level = 99; } scard = scard_init(SCARD_GSM_SIM_ONLY, argv[0]); if (scard == NULL) { printf("Failed to open smartcard connection\n"); return -1; } len = sizeof(imsi); if (scard_get_imsi(scard, imsi, &len)) { scard_deinit(scard); return -1; } for (i = 0; i < num_triplets; i++) { memset(rand, i, sizeof(rand)); if (scard_gsm_auth(scard, rand, sres, kc)) break; /* IMSI:Kc:SRES:RAND */ for (j = 0; j < len; j++) printf("%c", imsi[j]); printf(":"); for (j = 0; j < 8; j++) printf("%02X", kc[j]); printf(":"); for (j = 0; j < 4; j++) printf("%02X", sres[j]); printf(":"); for (j = 0; j < 16; j++) printf("%02X", rand[j]); printf("\n"); } scard_deinit(scard); return 0; }
/** * @brief process client's response to our core_capability_req() msg * * @param s stream containing client's response *****************************************************************************/ void dev_redir_proc_client_core_cap_resp(struct stream *s) { int i; tui16 num_caps; tui16 cap_type; tui16 cap_len; tui32 cap_version; char* holdp; xstream_rd_u16_le(s, num_caps); xstream_seek(s, 2); /* padding */ for (i = 0; i < num_caps; i++) { holdp = s->p; xstream_rd_u16_le(s, cap_type); xstream_rd_u16_le(s, cap_len); xstream_rd_u32_le(s, cap_version); switch (cap_type) { case CAP_GENERAL_TYPE: log_debug("got CAP_GENERAL_TYPE"); break; case CAP_PRINTER_TYPE: log_debug("got CAP_PRINTER_TYPE"); g_is_printer_redir_supported = 1; break; case CAP_PORT_TYPE: log_debug("got CAP_PORT_TYPE"); g_is_port_redir_supported = 1; break; case CAP_DRIVE_TYPE: log_debug("got CAP_DRIVE_TYPE"); g_is_drive_redir_supported = 1; if (cap_version == 2) { g_drive_redir_version = 2; } break; case CAP_SMARTCARD_TYPE: log_debug("got CAP_SMARTCARD_TYPE"); g_is_smartcard_redir_supported = 1; scard_init(); break; } s->p = holdp + cap_len; } }
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; }
static void wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { char buf[100]; size_t len; if (ssid->pcsc == NULL) return; if (wpa_s->scard != NULL) { wpa_supplicant_imsi_identity(wpa_s, ssid); return; } wpa_printf(MSG_DEBUG, "Selected network is configured to use SIM - " "initialize PCSC"); wpa_s->scard = scard_init(SCARD_TRY_BOTH, ssid->pin); if (wpa_s->scard == NULL) { wpa_printf(MSG_WARNING, "Failed to initialize SIM " "(pcsc-lite)"); /* TODO: what to do here? */ return; } eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); len = sizeof(buf); if (scard_get_imsi(wpa_s->scard, buf, &len)) { wpa_printf(MSG_WARNING, "Failed to get IMSI from SIM"); /* TODO: what to do here? */ return; } wpa_hexdump(MSG_DEBUG, "IMSI", buf, len); free(wpa_s->imsi); wpa_s->imsi = malloc(len); if (wpa_s->imsi) { wpa_s->imsi = buf; wpa_s->imsi_len = len; wpa_supplicant_imsi_identity(wpa_s, ssid); } }
static int scard_test(void) { struct scard_data *scard; size_t len; char imsi[20]; unsigned char _rand[16]; #ifdef PCSC_FUNCS unsigned char sres[4]; unsigned char kc[8]; #endif /* PCSC_FUNCS */ #define num_triplets 5 unsigned char rand_[num_triplets][16]; unsigned char sres_[num_triplets][4]; unsigned char kc_[num_triplets][8]; int i, res; size_t j; #define AKA_RAND_LEN 16 #define AKA_AUTN_LEN 16 #define AKA_AUTS_LEN 14 #define RES_MAX_LEN 16 #define IK_LEN 16 #define CK_LEN 16 unsigned char aka_rand[AKA_RAND_LEN]; unsigned char aka_autn[AKA_AUTN_LEN]; unsigned char aka_auts[AKA_AUTS_LEN]; unsigned char aka_res[RES_MAX_LEN]; size_t aka_res_len; unsigned char aka_ik[IK_LEN]; unsigned char aka_ck[CK_LEN]; scard = scard_init(SCARD_TRY_BOTH); if (scard == NULL) return -1; if (scard_set_pin(scard, "1234")) { wpa_printf(MSG_WARNING, "PIN validation failed"); scard_deinit(scard); return -1; } len = sizeof(imsi); if (scard_get_imsi(scard, imsi, &len)) goto failed; wpa_hexdump_ascii(MSG_DEBUG, "SCARD: IMSI", (u8 *) imsi, len); /* NOTE: Permanent Username: 1 | IMSI */ os_memset(_rand, 0, sizeof(_rand)); if (scard_gsm_auth(scard, _rand, sres, kc)) goto failed; os_memset(_rand, 0xff, sizeof(_rand)); if (scard_gsm_auth(scard, _rand, sres, kc)) goto failed; for (i = 0; i < num_triplets; i++) { os_memset(rand_[i], i, sizeof(rand_[i])); if (scard_gsm_auth(scard, rand_[i], sres_[i], kc_[i])) goto failed; } for (i = 0; i < num_triplets; i++) { printf("1"); for (j = 0; j < len; j++) printf("%c", imsi[j]); printf(","); for (j = 0; j < 16; j++) printf("%02X", rand_[i][j]); printf(","); for (j = 0; j < 4; j++) printf("%02X", sres_[i][j]); printf(","); for (j = 0; j < 8; j++) printf("%02X", kc_[i][j]); printf("\n"); } wpa_printf(MSG_DEBUG, "Trying to use UMTS authentication"); /* seq 39 (0x28) */ os_memset(aka_rand, 0xaa, 16); os_memcpy(aka_autn, "\x86\x71\x31\xcb\xa2\xfc\x61\xdf" "\xa3\xb3\x97\x9d\x07\x32\xa2\x12", 16); res = scard_umts_auth(scard, aka_rand, aka_autn, aka_res, &aka_res_len, aka_ik, aka_ck, aka_auts); if (res == 0) { wpa_printf(MSG_DEBUG, "UMTS auth completed successfully"); wpa_hexdump(MSG_DEBUG, "RES", aka_res, aka_res_len); wpa_hexdump(MSG_DEBUG, "IK", aka_ik, IK_LEN); wpa_hexdump(MSG_DEBUG, "CK", aka_ck, CK_LEN); } else if (res == -2) { wpa_printf(MSG_DEBUG, "UMTS auth resulted in synchronization " "failure"); wpa_hexdump(MSG_DEBUG, "AUTS", aka_auts, AKA_AUTS_LEN); } else { wpa_printf(MSG_DEBUG, "UMTS auth failed"); } failed: scard_deinit(scard); return 0; #undef num_triplets }
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 int scard_get_triplets(struct eapol_test_data *e, int argc, char *argv[]) { struct scard_data *scard; size_t len; char imsi[20]; unsigned char _rand[16]; unsigned char sres[4]; unsigned char kc[8]; int num_triplets; int i; size_t j; if (argc < 2 || ((num_triplets = atoi(argv[1])) <= 0)) { printf("invalid parameters for sim command\n"); return -1; } if (argc <= 2 || os_strcmp(argv[2], "debug") != 0) { /* disable debug output */ wpa_debug_level = 99; } scard = scard_init(e->pcsc_reader); if (scard == NULL) { printf("Failed to open smartcard connection\n"); return -1; } if (scard_set_pin(scard, argv[0])) { wpa_printf(MSG_WARNING, "PIN validation failed"); scard_deinit(scard); return -1; } len = sizeof(imsi); if (scard_get_imsi(scard, imsi, &len)) { scard_deinit(scard); return -1; } for (i = 0; i < num_triplets; i++) { os_memset(_rand, i, sizeof(_rand)); if (scard_gsm_auth(scard, _rand, sres, kc)) break; /* IMSI:Kc:SRES:RAND */ for (j = 0; j < len; j++) printf("%c", imsi[j]); printf(":"); for (j = 0; j < 8; j++) printf("%02X", kc[j]); printf(":"); for (j = 0; j < 4; j++) printf("%02X", sres[j]); printf(":"); for (j = 0; j < 16; j++) printf("%02X", _rand[j]); printf("\n"); } scard_deinit(scard); 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; }