view uicc/bfsearch.c @ 58:871281cb0555

doc/Low-level-commands: apdu-checksw documented
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 23 Mar 2021 00:21:02 +0000
parents b70d35f5476f
children
line wrap: on
line source

/*
 * 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);
}