view simtool/grcard1.c @ 93:6041c601304d

fcsim1-mkprov: revert OTA key addition It appears that GrcardSIM2 cards (which is what we got for FCSIM1) do not support OTA after all, contrary to what we were previously led to believe by some tech support emails from Grcard - apparently those support emails and OTA descriptions referred to some other card model(s).
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 21 Apr 2021 05:38:39 +0000
parents c8e2a0e89d08
children
line wrap: on
line source

/*
 * This module implements a few special commands for those very few
 * incredibly lucky people on Earth who have no-longer-available
 * sysmoSIM-GR1 cards, or any other branded variant of the same card
 * from Grcard.  All knowledge of proprietary APDUs that appears in
 * this code comes from this Osmocom wiki page:
 *
 * https://osmocom.org/projects/cellular-infrastructure/wiki/GrcardSIM
 */

#include <sys/types.h>
#include <stdio.h>
#include "simresp.h"

/*
 * grcard1-set-pin1 command sets PIN1 and PUK1,
 * grcard1-set-pin2 command sets PIN2 and PUK2.
 *
 * The proprietary APDU structure for these commands is naturally
 * intuitive (agrees with common sense), hence they are expected
 * to be correct despite lack of testing.
 */

cmd_grcard1_set_pin(argc, argv)
	char **argv;
{
	u_char cmd[21];
	int rc;

	/* Grcard1 proprietary command APDU */
	cmd[0] = 0x80;
	cmd[1] = 0xD4;
	cmd[2] = 0x00;
	switch (argv[0][15]) {
	case '1':
		cmd[3] = 0x01;
		break;
	case '2':
		cmd[3] = 0x02;
		break;
	default:
		fprintf(stderr, "BUG in grcard1-set-pinN 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);
}

/*
 * The ADM PIN structure of GrcardSIM1 cards is poorly understood.
 * The Osmocom wiki page describes ADM1 and ADM2 per Grcard's ADMn
 * naming convention (see ../doc/ADM-PIN-numbering), but each of those
 * also has an associated unblock code (called AUK1 and AUK2 in the
 * wiki page), and the command APDUs set ADM+AUK pairs: either
 * ADM1+AUK1 or ADM2+AUK2.  The following blind (untested) code is
 * based on this wiki page description.
 *
 * Because these access control codes are proprietary to Grcard
 * (not standard PIN1/PIN2/PUK1/PUK2), they can be arbitrary 64-bit
 * keys, not restricted to the ASCII-decimal subset used for standard
 * PINs and PUKs.  According to pySim-prog, the canonical ADM2 key
 * on these cards is hex 4444444444444444, which is outside of the
 * ASCII-decimal range (contrast with the situation on GrcardSIM2,
 * where the canonical SUPER ADM is decimal 88888888) - hence our
 * grcard1-set-admN commands take hex strings for ADMn and AUKn,
 * not decimal ones like grcard1-set-pinN.
 */

cmd_grcard1_set_adm(argc, argv)
	char **argv;
{
	u_char cmd[23];
	int rc;

	/* Grcard1 proprietary command APDU */
	cmd[0] = 0x80;
	cmd[1] = 0xD4;
	cmd[2] = 0x01;
	switch (argv[0][15]) {
	case '1':
	case '4':
		cmd[3] = 0x04;
		break;
	case '2':
	case '5':
		cmd[3] = 0x05;
		break;
	default:
		fprintf(stderr, "BUG in grcard1-set-admN command\n");
		return(-1);
	}
	cmd[4] = 18;
	cmd[5] = 0x03;
	cmd[6] = 0x00;
	rc = decode_hex_data_from_string(argv[1], cmd + 7, 8, 8);
	if (rc < 0)
		return(rc);
	rc = decode_hex_data_from_string(argv[2], cmd + 15, 8, 8);
	if (rc < 0)
		return(rc);
	rc = apdu_exchange(cmd, 23);
	if (rc < 0)
		return(rc);
	if (sim_resp_sw != 0x9000) {
		fprintf(stderr, "bad SW response: %04X\n", sim_resp_sw);
		return(-1);
	}
	return(0);
}

/*
 * The command for setting Ki has been extensively exercised
 * by Osmocom people, hence it is assumed to be correct.
 */

cmd_grcard1_set_ki(argc, argv)
	char **argv;
{
	u_char cmd[21];
	int rc;

	/* Grcard1 proprietary command APDU */
	cmd[0] = 0x80;
	cmd[1] = 0xD4;
	cmd[2] = 0x02;
	cmd[3] = 0x00;
	cmd[4] = 16;
	rc = decode_hex_data_from_string(argv[1], cmd + 5, 16, 16);
	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);
}