FreeCalypso > hg > freecalypso-hwlab
view uicc/dumpdir.c @ 176:fb2f6497ba53 default tip
doc/Linux-DTR-RTS-flaw: point to new location of this article
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 11 Dec 2023 19:37:20 +0000 |
parents | c331560c15a4 |
children |
line wrap: on
line source
/* * This module implements the dump of EF_DIR. */ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <pcsclite.h> #include <winscard.h> #include "globals.h" #include "file_id.h" static check_all_blank() { u_char *dp, *endp; dp = sim_resp_data; endp = sim_resp_data + sim_resp_data_len; while (dp < endp) if (*dp++ != 0xFF) return(0); return(1); } static void dump_aid(tlv) u_char *tlv; { unsigned reclen, n; reclen = tlv[1]; printf(" AID:"); for (n = 0; n < reclen; n++) printf(" %02X", tlv[n+2]); putchar('\n'); } static void dump_label(tlv) u_char *tlv; { int rc; unsigned textlen; printf(" Label: "); rc = validate_alpha_field(tlv + 2, tlv[1], &textlen); if (rc < 0) { printf("malformed\n"); return; } print_alpha_field(tlv + 2, textlen, stdout); putchar('\n'); } static void dump_unknown_tlv(tlv) u_char *tlv; { unsigned reclen, n; reclen = tlv[1] + 2; printf(" TLV:"); for (n = 0; n < reclen; n++) printf(" %02X", tlv[n]); putchar('\n'); } static void dump_record(recno) unsigned recno; { unsigned totlen, reclen; u_char *dp, *endp; printf("Record #%u:\n", recno); if (sim_resp_data[0] != 0x61) { printf(" bad: first byte != 0x61\n"); return; } totlen = sim_resp_data[1]; if (totlen < 3 || totlen > 0x7F) { printf(" bad: global length byte 0x%02X is invalid\n", totlen); return; } if (totlen + 2 > sim_resp_data_len) { printf(" bad: TLV global length exceeds EF record length\n"); return; } dp = sim_resp_data + 2; endp = sim_resp_data + 2 + totlen; while (dp < endp) { if (endp - dp < 2) { trunc_error: printf(" bad: truncated TLV record\n"); return; } if ((dp[0] & 0x1F) == 0x1F) { printf(" bad: extended tag not supported\n"); return; } if (dp[1] & 0x80) { printf(" bad: extended length not supported\n"); return; } reclen = dp[1] + 2; if (endp - dp < reclen) goto trunc_error; switch (dp[0]) { case 0x4F: dump_aid(dp); break; case 0x50: dump_label(dp); break; default: dump_unknown_tlv(dp); } dp += reclen; } } cmd_dir() { int rc; unsigned record_len, record_count; unsigned recno; rc = select_op(FILEID_MF); if (rc < 0) return(rc); rc = select_op(EF_DIR); if (rc < 0) return(rc); rc = select_resp_get_linear_fixed(&record_len, &record_count); if (rc < 0) return(rc); if (record_len < 5) { fprintf(stderr, "error: EF_DIR record length is too short\n"); return(-1); } for (recno = 1; recno <= record_count; recno++) { rc = readrec_op(recno, 0x04, record_len); if (rc < 0) return(rc); if (check_all_blank()) continue; dump_record(recno); } return(0); }