changeset 108:6f80cfdc7e05

fc-simtool: CHV commands implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 26 Jan 2021 00:51:59 +0000
parents ba2c796259e9
children 4aaf722ab933
files simtool/Makefile simtool/chv.c simtool/dispatch.c
diffstat 3 files changed, 224 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/simtool/Makefile	Mon Jan 25 21:15:42 2021 +0000
+++ b/simtool/Makefile	Tue Jan 26 00:51:59 2021 +0000
@@ -1,10 +1,10 @@
 CC=	gcc
 CFLAGS=	-O2 -I/usr/include/PCSC
 PROG=	fc-simtool
-OBJS=	alpha_decode.o alpha_valid.o apdu.o atr.o cardconnect.o dispatch.o \
-	globals.o hexdump.o hexread.o hlread.o main.o names.o pbcommon.o \
-	pbdump.o readcmd.o readops.o saverestore.o select.o telsum.o writecmd.o\
-	writeops.o
+OBJS=	alpha_decode.o alpha_valid.o apdu.o atr.o cardconnect.o chv.o \
+	dispatch.o globals.o hexdump.o hexread.o hlread.o main.o names.o \
+	pbcommon.o pbdump.o readcmd.o readops.o saverestore.o select.o telsum.o\
+	writecmd.o writeops.o
 INSTBIN=/opt/freecalypso/bin
 
 all:	${PROG}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simtool/chv.c	Tue Jan 26 00:51:59 2021 +0000
@@ -0,0 +1,199 @@
+/*
+ * This module implements the standard set of CHV commands
+ * for GSM 11.11 SIMs.
+ */
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pcsclite.h>
+#include <winscard.h>
+#include "globals.h"
+
+static
+encode_pin_entry(arg, dest)
+	char *arg;
+	u_char *dest;
+{
+	unsigned n;
+
+	n = 0;
+	while (*arg) {
+		if (!isdigit(*arg)) {
+			fprintf(stderr,
+			"error: PIN argument contains a non-digit character\n");
+			return(-1);
+		}
+		if (n >= 8) {
+			fprintf(stderr, "error: PIN argument is too long\n");
+			return(-1);
+		}
+		*dest++ = *arg++;
+		n++;
+	}
+	for (; n < 8; n++)
+		*dest++ = 0xFF;
+	return(0);
+}
+
+cmd_verify_chv(argc, argv)
+	char **argv;
+{
+	u_char cmd[13];
+	int rc;
+
+	/* VERIFY CHV command APDU */
+	cmd[0] = 0xA0;
+	cmd[1] = 0x20;
+	cmd[2] = 0x00;
+	switch (argv[0][10]) {
+	case '1':
+		cmd[3] = 0x01;
+		break;
+	case '2':
+		cmd[3] = 0x02;
+		break;
+	default:
+		fprintf(stderr, "BUG in verify-chvN command\n");
+		return(-1);
+	}
+	cmd[4] = 8;
+	rc = encode_pin_entry(argv[1], cmd + 5);
+	if (rc < 0)
+		return(rc);
+	rc = apdu_exchange(cmd, 13);
+	if (rc < 0)
+		return(rc);
+	if (sim_resp_sw != 0x9000) {
+		fprintf(stderr, "bad SW response: %04X\n", sim_resp_sw);
+		return(-1);
+	}
+	return(0);
+}
+
+cmd_change_chv(argc, argv)
+	char **argv;
+{
+	u_char cmd[21];
+	int rc;
+
+	/* CHANGE CHV command APDU */
+	cmd[0] = 0xA0;
+	cmd[1] = 0x24;
+	cmd[2] = 0x00;
+	switch (argv[0][10]) {
+	case '1':
+		cmd[3] = 0x01;
+		break;
+	case '2':
+		cmd[3] = 0x02;
+		break;
+	default:
+		fprintf(stderr, "BUG in change-chvN command\n");
+		return(-1);
+	}
+	cmd[4] = 16;
+	rc = encode_pin_entry(argv[1], cmd + 5);
+	if (rc < 0)
+		return(rc);
+	rc = encode_pin_entry(argv[2], cmd + 13);
+	if (rc < 0)
+		return(rc);
+	rc = apdu_exchange(cmd, 21);
+	if (rc < 0)
+		return(rc);
+	if (sim_resp_sw != 0x9000) {
+		fprintf(stderr, "bad SW response: %04X\n", sim_resp_sw);
+		return(-1);
+	}
+	return(0);
+}
+
+cmd_disable_chv(argc, argv)
+	char **argv;
+{
+	u_char cmd[13];
+	int rc;
+
+	/* DISABLE CHV command APDU */
+	cmd[0] = 0xA0;
+	cmd[1] = 0x26;
+	cmd[2] = 0x00;
+	cmd[3] = 0x01;
+	cmd[4] = 8;
+	rc = encode_pin_entry(argv[1], cmd + 5);
+	if (rc < 0)
+		return(rc);
+	rc = apdu_exchange(cmd, 13);
+	if (rc < 0)
+		return(rc);
+	if (sim_resp_sw != 0x9000) {
+		fprintf(stderr, "bad SW response: %04X\n", sim_resp_sw);
+		return(-1);
+	}
+	return(0);
+}
+
+cmd_enable_chv(argc, argv)
+	char **argv;
+{
+	u_char cmd[13];
+	int rc;
+
+	/* ENABLE CHV command APDU */
+	cmd[0] = 0xA0;
+	cmd[1] = 0x28;
+	cmd[2] = 0x00;
+	cmd[3] = 0x01;
+	cmd[4] = 8;
+	rc = encode_pin_entry(argv[1], cmd + 5);
+	if (rc < 0)
+		return(rc);
+	rc = apdu_exchange(cmd, 13);
+	if (rc < 0)
+		return(rc);
+	if (sim_resp_sw != 0x9000) {
+		fprintf(stderr, "bad SW response: %04X\n", sim_resp_sw);
+		return(-1);
+	}
+	return(0);
+}
+
+cmd_unblock_chv(argc, argv)
+	char **argv;
+{
+	u_char cmd[21];
+	int rc;
+
+	/* UNBLOCK CHV command APDU */
+	cmd[0] = 0xA0;
+	cmd[1] = 0x2C;
+	cmd[2] = 0x00;
+	switch (argv[0][11]) {
+	case '1':
+		cmd[3] = 0x00;
+		break;
+	case '2':
+		cmd[3] = 0x02;
+		break;
+	default:
+		fprintf(stderr, "BUG in unblock-chvN command\n");
+		return(-1);
+	}
+	cmd[4] = 16;
+	rc = encode_pin_entry(argv[1], cmd + 5);
+	if (rc < 0)
+		return(rc);
+	rc = encode_pin_entry(argv[2], cmd + 13);
+	if (rc < 0)
+		return(rc);
+	rc = apdu_exchange(cmd, 21);
+	if (rc < 0)
+		return(rc);
+	if (sim_resp_sw != 0x9000) {
+		fprintf(stderr, "bad SW response: %04X\n", sim_resp_sw);
+		return(-1);
+	}
+	return(0);
+}
--- a/simtool/dispatch.c	Mon Jan 25 21:15:42 2021 +0000
+++ b/simtool/dispatch.c	Tue Jan 26 00:51:59 2021 +0000
@@ -12,6 +12,9 @@
 #include <winscard.h>
 #include "globals.h"
 
+extern int cmd_change_chv();
+extern int cmd_disable_chv();
+extern int cmd_enable_chv();
 extern int cmd_iccid();
 extern int cmd_imsi();
 extern int cmd_pb_dump();
@@ -23,8 +26,10 @@
 extern int cmd_select();
 extern int cmd_spn();
 extern int cmd_telecom_sum();
+extern int cmd_unblock_chv();
 extern int cmd_update_bin();
 extern int cmd_update_rec();
+extern int cmd_verify_chv();
 
 extern int display_sim_resp_in_hex();
 
@@ -41,6 +46,14 @@
 	int maxargs;
 	int (*func)();
 } cmdtab[] = {
+	{"change-chv1", 2, 2, cmd_change_chv},
+	{"change-chv2", 2, 2, cmd_change_chv},
+	{"change-pin1", 2, 2, cmd_change_chv},
+	{"change-pin2", 2, 2, cmd_change_chv},
+	{"disable-chv", 1, 1, cmd_disable_chv},
+	{"disable-pin", 1, 1, cmd_disable_chv},
+	{"enable-chv", 1, 1, cmd_enable_chv},
+	{"enable-pin", 1, 1, cmd_enable_chv},
 	{"exit", 0, 0, cmd_exit},
 	{"iccid", 0, 0, cmd_iccid},
 	{"imsi", 0, 0, cmd_imsi},
@@ -55,8 +68,16 @@
 	{"sim-resp", 0, 0, display_sim_resp_in_hex},
 	{"spn", 0, 0, cmd_spn},
 	{"telecom-sum", 0, 0, cmd_telecom_sum},
+	{"unblock-chv1", 2, 2, cmd_unblock_chv},
+	{"unblock-chv2", 2, 2, cmd_unblock_chv},
+	{"unblock-pin1", 2, 2, cmd_unblock_chv},
+	{"unblock-pin2", 2, 2, cmd_unblock_chv},
 	{"update-bin", 2, 2, cmd_update_bin},
 	{"update-rec", 2, 2, cmd_update_rec},
+	{"verify-chv1", 1, 1, cmd_verify_chv},
+	{"verify-chv2", 1, 1, cmd_verify_chv},
+	{"verify-pin1", 1, 1, cmd_verify_chv},
+	{"verify-pin2", 1, 1, cmd_verify_chv},
 	{0, 0, 0, 0}
 };