FreeCalypso > hg > fc-pcsc-tools
view simtool/bfsearch.c @ 192:edaccdbac95b
doc/GrcardSIM2-security-model: document ADM11 MF quirk
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 06 Mar 2021 21:41:12 +0000 |
parents | 26d7a8815515 |
children |
line wrap: on
line source
/* * This module implements a brute force search of file ID space at a given * file system directory level. */ #include <sys/types.h> #include <ctype.h> #include <stdio.h> #include <stdlib.h> #include "simresp.h" #include "file_id.h" static parse_skip_ids(argv, array, total) char **argv; unsigned *array, total; { unsigned n; for (n = 0; n < total; n++) { if (!isxdigit(argv[n][0]) || !isxdigit(argv[n][1]) || !isxdigit(argv[n][2]) || !isxdigit(argv[n][3]) || argv[n][4]) { fprintf(stderr, "error: argument is not 4-digit hex\n"); return(-1); } array[n] = strtoul(argv[n], 0, 16); } return(0); } static void report_ef_struct(outf) FILE *outf; { unsigned total_size, record_len; fputs("EF, ", outf); total_size = (sim_resp_data[2] << 8) | sim_resp_data[3]; switch (sim_resp_data[13]) { case 0x00: fprintf(outf, "transparent, length %u\n", total_size); return; case 0x01: fputs("linear fixed, ", outf); break; case 0x03: fputs("cyclic, ", outf); break; default: fprintf(outf, "struct 0x%02X\n", sim_resp_data[13]); return; } if (sim_resp_data_len < 15) { fprintf(outf, "response struct cut off\n"); return; } record_len = sim_resp_data[14]; fprintf(outf, "record length %u", record_len); if (record_len && total_size % record_len == 0) fprintf(outf, ", %u records", total_size / record_len); putc('\n', outf); } cmd_bfsearch(argc, argv, outf) char **argv; FILE *outf; { unsigned skip_ids[8], num_skip_ids; unsigned bfs, n; int rc; num_skip_ids = argc - 1; rc = parse_skip_ids(argv + 1, skip_ids, num_skip_ids); if (rc < 0) return(rc); rc = elem_select_op(skip_ids[0]); if (rc < 0) return(rc); if (!rc) { fprintf(stderr, "error: starting file ID 0x%04X not found\n", skip_ids[0]); return(-1); } for (bfs = 0; bfs <= 0xFFFF; bfs++) { for (n = 0; n < num_skip_ids; n++) { if (bfs == skip_ids[n]) break; } if (n < num_skip_ids) continue; rc = elem_select_op(bfs); if (rc < 0) return(rc); if (!rc) continue; rc = get_response_op(); if (rc < 0) return(rc); fprintf(outf, "%04X: ", bfs); if (sim_resp_data_len < 14) fprintf(outf, "too-short response struct\n"); else { switch (sim_resp_data[6]) { case 0x01: fprintf(outf, "MF\n"); break; case 0x02: fprintf(outf, "DF\n"); break; case 0x04: report_ef_struct(outf); break; default: fprintf(outf, "unknown file type %02X\n", sim_resp_data[6]); } } rc = elem_select_op(skip_ids[0]); if (rc < 0) return(rc); if (!rc) { fprintf(stderr, "reselecting starting file ID 0x%04X not-found error\n", skip_ids[0]); return(-1); } } return(0); } static bfsearch_dir(path, pathlen, siblings, nsiblings, outf) unsigned *path, pathlen, *siblings, nsiblings; FILE *outf; { unsigned bfs, n; unsigned df_children[255], ndfc; unsigned childpath[8]; int rc; for (n = 0; n < pathlen; n++) { rc = elem_select_op(path[n]); if (rc < 0) return(rc); if (!rc) { fprintf(stderr, "error selecting 0x%04X: file not found\n", path[n]); return(-1); } } ndfc = 0; for (bfs = 0; bfs <= 0xFFFF; bfs++) { for (n = 0; n < pathlen; n++) { if (bfs == path[n]) break; } if (n < pathlen) continue; for (n = 0; n < nsiblings; n++) { if (bfs == siblings[n]) break; } if (n < nsiblings) continue; rc = elem_select_op(bfs); if (rc < 0) return(rc); if (!rc) continue; rc = get_response_op(); if (rc < 0) return(rc); for (n = 0; n < pathlen; n++) fprintf(outf, "%04X/", path[n]); fprintf(outf, "%04X: ", bfs); if (sim_resp_data_len < 14) fprintf(outf, "too-short response struct\n"); else { switch (sim_resp_data[6]) { case 0x01: fprintf(outf, "MF\n"); break; case 0x02: fprintf(outf, "DF\n"); if (ndfc < 255) df_children[ndfc++] = bfs; break; case 0x04: report_ef_struct(outf); break; default: fprintf(outf, "unknown file type %02X\n", sim_resp_data[6]); } } rc = elem_select_op(path[pathlen-1]); if (rc < 0) return(rc); if (!rc) { fprintf(stderr, "reselecting starting file ID 0x%04X not-found error\n", path[pathlen-1]); return(-1); } } if (pathlen >= 8) return(0); for (n = 0; n < pathlen; n++) childpath[n] = path[n]; for (n = 0; n < ndfc; n++) { childpath[pathlen] = df_children[n]; rc = bfsearch_dir(childpath, pathlen + 1, df_children, ndfc, outf); if (rc < 0) return(rc); } return(0); } cmd_bfsearch_full(argc, argv, outf) char **argv; FILE *outf; { unsigned initpath; initpath = FILEID_MF; return bfsearch_dir(&initpath, 1, &initpath, 1, outf); }