changeset 132:5af88fa11b54

fc-uicc-tool: SELECT response parsing implemented (basic)
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 04 Feb 2021 01:36:54 +0000
parents d0929cb42e1c
children f3bdefbeae38
files uicc/select.c
diffstat 1 files changed, 80 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/uicc/select.c	Thu Feb 04 00:23:33 2021 +0000
+++ b/uicc/select.c	Thu Feb 04 01:36:54 2021 +0000
@@ -56,10 +56,85 @@
 	return(0);
 }
 
+select_resp_header_check(ret_offset, ret_length)
+	unsigned *ret_offset, *ret_length;
+{
+	unsigned offset, len;
+
+	if (sim_resp_data_len < 2) {
+tooshort:	fprintf(stderr, "error: SELECT response is too short\n");
+		return(-1);
+	}
+	if (sim_resp_data[0] != 0x62) {
+		fprintf(stderr, "error: SELECT response first byte != 0x62\n");
+		return(-1);
+	}
+	len = sim_resp_data[1];
+	if (len <= 0x7F) {
+		offset = 2;
+return_check:	if (offset + len > sim_resp_data_len)
+			goto tooshort;
+		if (ret_offset)
+			*ret_offset = offset;
+		if (ret_length)
+			*ret_length = len;
+		return(0);
+	}
+	if (len != 0x81) {
+		fprintf(stderr, "SELECT response: first length byte is bad\n");
+		return(-1);
+	}
+	if (sim_resp_data_len < 3)
+		goto tooshort;
+	len = sim_resp_data[2];
+	offset = 3;
+	goto return_check;
+}
+
+parse_and_display_select_response()
+{
+	unsigned offset, totlen, reclen, n;
+	u_char *dp, *endp;
+	int rc;
+
+	rc = select_resp_header_check(&offset, &totlen);
+	if (rc < 0)
+		return(rc);
+	dp = sim_resp_data + offset;
+	endp = sim_resp_data + offset + totlen;
+	while (dp < endp) {
+		if (endp - dp < 2) {
+trunc_error:		fprintf(stderr,
+			"error: truncated TLV record in SELECT response\n");
+			return(-1);
+		}
+		if ((dp[0] & 0x1F) == 0x1F) {
+			fprintf(stderr,
+		"error: extended tag not supported in SELECT response\n");
+			return(-1);
+		}
+		if (dp[1] & 0x80) {
+			fprintf(stderr,
+		"error: extended length not supported in SELECT response\n");
+			return(-1);
+		}
+		reclen = dp[1] + 2;
+		if (endp - dp < reclen)
+			goto trunc_error;
+		for (n = 0; n < reclen; n++) {
+			if (n)
+				putchar(' ');
+			printf("%02X", *dp++);
+		}
+		putchar('\n');
+	}
+	return(0);
+}
+
 cmd_select(argc, argv)
 	char **argv;
 {
-	int file_id;
+	int file_id, rc;
 
 	if (isxdigit(argv[1][0]) && isxdigit(argv[1][1]) &&
 	    isxdigit(argv[1][2]) && isxdigit(argv[1][3]) && !argv[1][4])
@@ -71,5 +146,8 @@
 "error: file ID argument is not a hex value or a recognized symbolic name\n");
 		return(-1);
 	}
-	return select_op(file_id);
+	rc = select_op(file_id);
+	if (rc < 0)
+		return(rc);
+	return parse_and_display_select_response();
 }