diff uicc/bfsearch.c @ 15:b70d35f5476f

fc-uicc-tool ported over
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 14 Mar 2021 07:41:09 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uicc/bfsearch.c	Sun Mar 14 07:41:09 2021 +0000
@@ -0,0 +1,136 @@
+/*
+ * This module implements a brute force search of file ID space,
+ * both MF and ADF trees.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include "simresp.h"
+#include "file_id.h"
+
+extern u_char *extract_select_resp_tag();
+
+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];
+	u_char *tlv_file_desc, *tlv_file_size;
+	int rc;
+
+	for (n = 0; n < pathlen; n++) {
+		rc = elem_select_op(path[n]);
+		if (rc < 0)
+			return(rc);
+		if ((sim_resp_sw & 0xFF00) != 0x6100) {
+			fprintf(stderr,
+				"error selecting 0x%04X: SW resp 0x%04X\n",
+				path[n], sim_resp_sw);
+			return(-1);
+		}
+	}
+	ndfc = 0;
+	for (bfs = 0; bfs <= 0xFFFF; bfs++) {
+		if (bfs == FILEID_MF || bfs == FILEID_ADF)
+			continue;
+		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 (sim_resp_sw == 0x6A82)
+			continue;
+		if ((sim_resp_sw & 0xFF00) != 0x6100) {
+			for (n = 0; n < pathlen; n++)
+				fprintf(outf, "%04X/", path[n]);
+			fprintf(outf, "%04X: SW response 0x%04X\n", bfs,
+				sim_resp_sw);
+			continue;
+		}
+		rc = get_response_op();
+		if (rc < 0)
+			return(rc);
+		tlv_file_desc = extract_select_resp_tag(0x82);
+		if (!tlv_file_desc)
+			return(-1);
+		if (tlv_file_desc[1] < 1) {
+			fprintf(stderr,
+				"error: file desc TLV object is too short\n");
+			return(-1);
+		}
+		for (n = 0; n < pathlen; n++)
+			fprintf(outf, "%04X/", path[n]);
+		fprintf(outf, "%04X: file desc 0x%02X", bfs, tlv_file_desc[2]);
+		if ((tlv_file_desc[2] & 0xBF) == 0x38) {
+			fprintf(outf, ", DF\n");
+			if (ndfc < 255)
+				df_children[ndfc++] = bfs;
+		} else {
+			tlv_file_size = extract_select_resp_tag(0x80);
+			if (tlv_file_size && tlv_file_size[1] == 2)
+				fprintf(outf, ", total size %u",
+					(tlv_file_size[2] << 8) |
+					tlv_file_size[3]);
+			if (tlv_file_desc[1] == 5)
+				fprintf(outf, ", %u records of %u bytes",
+					tlv_file_desc[6],
+					(tlv_file_desc[4] << 8) |
+					tlv_file_desc[5]);
+			putc('\n', outf);
+		}
+		rc = elem_select_op(path[pathlen-1]);
+		if (rc < 0)
+			return(rc);
+		if ((sim_resp_sw & 0xFF00) != 0x6100) {
+			fprintf(stderr,
+			"reselecting starting file ID 0x%04X: SW resp 0x%04X\n",
+				path[pathlen-1], sim_resp_sw);
+			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_mf(argc, argv, outf)
+	char **argv;
+	FILE *outf;
+{
+	unsigned initpath;
+
+	initpath = FILEID_MF;
+	return bfsearch_dir(&initpath, 1, &initpath, 1, outf);
+}
+
+cmd_bfsearch_adf(argc, argv, outf)
+	char **argv;
+	FILE *outf;
+{
+	unsigned initpath;
+
+	initpath = FILEID_ADF;
+	return bfsearch_dir(&initpath, 1, &initpath, 1, outf);
+}