blob: d704500656a91bfaa37031298a2f115d7c43d02e [file] [log] [blame]
Oliver Smith05b13322020-02-24 14:18:20 +01001/* Copyright 2020 sysmocom s.f.m.c. GmbH
2 * SPDX-License-Identifier: Apache-2.0 */
Oliver Smith4e5e5162020-02-21 08:47:36 +01003package org.osmocom.IMSIPseudo;
Neels Hofmeyrd20f93a2020-02-24 22:42:22 +01004import org.osmocom.IMSIPseudo.MobileIdentity;
Oliver Smith4e5e5162020-02-21 08:47:36 +01005
Oliver Smith4eee13d2020-02-24 11:28:39 +01006import sim.access.*;
7import sim.toolkit.*;
8import javacard.framework.*;
Oliver Smith4e5e5162020-02-21 08:47:36 +01009
10public class IMSIPseudo extends Applet implements ToolkitInterface, ToolkitConstants {
11 // DON'T DECLARE USELESS INSTANCE VARIABLES! They get saved to the EEPROM,
12 // which has a limited number of write cycles.
Oliver Smith4e5e5162020-02-21 08:47:36 +010013
Oliver Smithca866fe2020-02-24 09:56:30 +010014 private byte STKServicesMenuId;
Oliver Smith2259cb92020-02-24 11:36:31 +010015 private SIMView gsmFile;
Oliver Smith1e5cc462020-02-21 15:39:14 +010016 static byte[] LUCounter = new byte[] { '0', 'x', ' ', 'L', 'U' };
Oliver Smithca866fe2020-02-24 09:56:30 +010017
18 /* Main menu */
Neels Hofmeyr7d7e33f2020-02-24 21:24:02 +010019 private static final byte[] title = new byte[] { 'I', 'M', 'S', 'I', ' ', 'P', 's', 'e', 'u', 'd', 'o', 'n', 'y', 'm',
Oliver Smith2dcbfab2020-02-21 15:40:21 +010020 'i', 'z', 'a', 't', 'i', 'o', 'n'};
Neels Hofmeyr7d7e33f2020-02-24 21:24:02 +010021 private static final byte[] showLU = new byte[] {'S', 'h', 'o', 'w', ' ', 'L', 'U', ' ', 'c', 'o', 'u', 'n', 't', 'e', 'r'};
22 private static final byte[] showIMSI = new byte[] {'S', 'h', 'o', 'w', ' ', 'I', 'M', 'S', 'I'};
23 private static final byte[] changeIMSI = new byte[] {'C', 'h', 'a', 'n', 'g', 'e', ' ', 'I', 'M', 'S', 'I', ' '};
24 private final Object[] itemListMain = {title, showLU, showIMSI, changeIMSI};
Oliver Smithca866fe2020-02-24 09:56:30 +010025
26 /* Change IMSI menu */
Neels Hofmeyr0866f3a2020-02-24 21:30:42 +010027 private static final byte[] enterIMSI = new byte[] {'E', 'n', 't', 'e', 'r', ' ', 'I', 'M', 'S', 'I' };
Neels Hofmeyr7d7e33f2020-02-24 21:24:02 +010028 private static final byte[] setDigit1 = new byte[] {'S', 'e', 't', ' ', '1', ' ', 'a', 's', ' ', 'l', 'a', 's', 't', ' ',
Oliver Smithca866fe2020-02-24 09:56:30 +010029 'd', 'i', 'g', 'i', 't'};
Neels Hofmeyr7d7e33f2020-02-24 21:24:02 +010030 private static final byte[] setDigit2 = new byte[] {'S', 'e', 't', ' ', '2', ' ', 'a', 's', ' ', 'l', 'a', 's', 't', ' ',
Oliver Smithca866fe2020-02-24 09:56:30 +010031 'd', 'i', 'g', 'i', 't'};
Neels Hofmeyr0866f3a2020-02-24 21:30:42 +010032 private final Object[] itemListChangeIMSI = {changeIMSI, enterIMSI, setDigit1, setDigit2};
Oliver Smith4e5e5162020-02-21 08:47:36 +010033
34 private IMSIPseudo() {
Oliver Smith2259cb92020-02-24 11:36:31 +010035 gsmFile = SIMSystem.getTheSIMView();
36
Oliver Smithca866fe2020-02-24 09:56:30 +010037 /* Register menu and trigger on location updates */
Oliver Smith4e5e5162020-02-21 08:47:36 +010038 ToolkitRegistry reg = ToolkitRegistry.getEntry();
Oliver Smithca866fe2020-02-24 09:56:30 +010039 STKServicesMenuId = reg.initMenuEntry(title, (short)0, (short)title.length, PRO_CMD_SELECT_ITEM, false,
40 (byte)0, (short)0);
Oliver Smithe28705a2020-02-21 10:06:14 +010041 reg.setEvent(EVENT_EVENT_DOWNLOAD_LOCATION_STATUS);
Oliver Smith4e5e5162020-02-21 08:47:36 +010042 }
43
Oliver Smith4e5e5162020-02-21 08:47:36 +010044 public static void install(byte[] bArray, short bOffset, byte bLength) {
45 IMSIPseudo applet = new IMSIPseudo();
46 applet.register();
47 }
48
Oliver Smith4e5e5162020-02-21 08:47:36 +010049 public void process(APDU arg0) throws ISOException {
Oliver Smith4e5e5162020-02-21 08:47:36 +010050 if (selectingApplet())
51 return;
52 }
53
Oliver Smith4e5e5162020-02-21 08:47:36 +010054 public void processToolkit(byte event) throws ToolkitException {
55 EnvelopeHandler envHdlr = EnvelopeHandler.getTheHandler();
56
57 if (event == EVENT_MENU_SELECTION) {
58 byte selectedItemId = envHdlr.getItemIdentifier();
59
Oliver Smithca866fe2020-02-24 09:56:30 +010060 if (selectedItemId == STKServicesMenuId) {
Neels Hofmeyr583bfec2020-02-25 03:10:38 +010061 showMenu(itemListMain);
Oliver Smithca866fe2020-02-24 09:56:30 +010062 handleMenuResponseMain();
Oliver Smith4e5e5162020-02-21 08:47:36 +010063 }
64 }
Oliver Smithe28705a2020-02-21 10:06:14 +010065
66 if (event == EVENT_EVENT_DOWNLOAD_LOCATION_STATUS) {
Oliver Smith1e5cc462020-02-21 15:39:14 +010067 LUCounter[0]++;
Oliver Smith234ab542020-02-24 08:25:43 +010068 showMsg(LUCounter);
Oliver Smithe28705a2020-02-21 10:06:14 +010069 }
Oliver Smith4e5e5162020-02-21 08:47:36 +010070 }
71
Neels Hofmeyr583bfec2020-02-25 03:10:38 +010072 private void showMenu(Object[] itemList) {
Oliver Smithca866fe2020-02-24 09:56:30 +010073 ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
74 proHdlr.init((byte) PRO_CMD_SELECT_ITEM,(byte)0,DEV_ID_ME);
75
Neels Hofmeyr583bfec2020-02-25 03:10:38 +010076 for (byte i=(byte)0; i < itemList.length; i++) {
Oliver Smithca866fe2020-02-24 09:56:30 +010077 if (i == 0) {
78 /* Title */
79 proHdlr.appendTLV((byte)(TAG_ALPHA_IDENTIFIER | TAG_SET_CR), (byte[])itemList[i],
80 (short)0, (short)((byte[])itemList[i]).length);
81
82 } else {
83 /* Menu entry */
84 proHdlr.appendTLV((byte)(TAG_ITEM | TAG_SET_CR), (byte)i, (byte[])itemList[i], (short)0,
85 (short)((byte[])itemList[i]).length);
86 }
87 }
88 proHdlr.send();
89 }
90
Oliver Smithcef081c2020-02-24 10:02:14 +010091 private void showMsg(byte[] msg) {
92 ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
93 proHdlr.initDisplayText((byte)0, DCS_8_BIT_DATA, msg, (short)0, (short)(msg.length));
94 proHdlr.send();
Oliver Smithcef081c2020-02-24 10:02:14 +010095 }
96
Neels Hofmeyrba7a6f22020-02-24 21:26:37 +010097 private byte[] getResponse()
98 {
99 ProactiveResponseHandler rspHdlr = ProactiveResponseHandler.getTheHandler();
100 byte[] resp = new byte[rspHdlr.getTextStringLength()];
101 rspHdlr.copyTextString(resp, (short)0);
102 return resp;
103 }
104
105 private byte[] showMsgAndWaitKey(byte[] msg) {
Neels Hofmeyrcfb476d2020-02-24 19:00:03 +0100106 ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
107 proHdlr.initGetInkey((byte)0, DCS_8_BIT_DATA, msg, (short)0, (short)(msg.length));
108 proHdlr.send();
Neels Hofmeyrba7a6f22020-02-24 21:26:37 +0100109
110 return getResponse();
111 }
112
113 private byte[] prompt(byte[] msg, short minLen, short maxLen) {
114 /* if maxLen < 1, the applet crashes */
115 if (maxLen < 1)
116 maxLen = 1;
117
118 ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
119 proHdlr.initGetInput((byte)0, DCS_8_BIT_DATA, msg, (short)0, (short)(msg.length), minLen, maxLen);
120 proHdlr.send();
121
122 return getResponse();
Neels Hofmeyrcfb476d2020-02-24 19:00:03 +0100123 }
124
Oliver Smithd7f18922020-02-24 12:24:38 +0100125 private void showError(short code) {
126 byte[] msg = new byte[] {'E', '?', '?'};
127 msg[1] = (byte)('0' + code / 10);
128 msg[2] = (byte)('0' + code % 10);
129 showMsg(msg);
130 }
131
Neels Hofmeyrc0c95622020-02-24 21:29:23 +0100132
Oliver Smith2259cb92020-02-24 11:36:31 +0100133 private void showIMSI() {
134 /* 3GPP TS 31.102 4.2.2: IMSI */
Oliver Smith2259cb92020-02-24 11:36:31 +0100135 byte[] msg = {'C', 'u', 'r', 'r', 'e', 'n', 't', ' ', 'I', 'M', 'S', 'I', ':', ' ',
Neels Hofmeyrb7a20e32020-02-24 18:58:56 +0100136 ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
Oliver Smith2259cb92020-02-24 11:36:31 +0100137
Oliver Smithd7f18922020-02-24 12:24:38 +0100138 try {
Neels Hofmeyrc24fdd12020-02-24 21:31:01 +0100139 byte IMSI[] = readIMSI();
Neels Hofmeyrd20f93a2020-02-24 22:42:22 +0100140 MobileIdentity.mi2str(msg, (byte)14, (byte)16, IMSI, false);
Neels Hofmeyrc24fdd12020-02-24 21:31:01 +0100141 showMsgAndWaitKey(msg);
Oliver Smithd7f18922020-02-24 12:24:38 +0100142 } catch (SIMViewException e) {
143 showError(e.getReason());
144 }
Oliver Smith2259cb92020-02-24 11:36:31 +0100145 }
146
Oliver Smithca866fe2020-02-24 09:56:30 +0100147 private void handleMenuResponseMain() {
148 ProactiveResponseHandler rspHdlr = ProactiveResponseHandler.getTheHandler();
149
150 switch (rspHdlr.getItemIdentifier()) {
Neels Hofmeyrc8e96412020-02-24 21:29:46 +0100151 case 1: /* Show LU counter */
152 showMsg(LUCounter);
153 break;
154 case 2: /* Show IMSI */
155 showIMSI();
156 break;
157 case 3: /* Change IMSI */
Neels Hofmeyr583bfec2020-02-25 03:10:38 +0100158 showMenu(itemListChangeIMSI);
Neels Hofmeyrc8e96412020-02-24 21:29:46 +0100159 handleMenuResponseChangeIMSI();
160 break;
Oliver Smithca866fe2020-02-24 09:56:30 +0100161 }
162 }
163
164 private void handleMenuResponseChangeIMSI() {
Neels Hofmeyr0866f3a2020-02-24 21:30:42 +0100165 ProactiveResponseHandler rspHdlr = ProactiveResponseHandler.getTheHandler();
166 switch (rspHdlr.getItemIdentifier()) {
167 case 1: /* enter IMSI */
168 promptIMSI();
169 break;
170 case 2: /* set last digit to 1 */
171 promptIMSI();
172 break;
173 case 3: /* set last digit to 2 */
174 promptIMSI();
175 break;
176 }
177 }
178
179 private void promptIMSI()
180 {
181 byte[] msg = {'N', 'e', 'w', ' ', 'I', 'M', 'S', 'I', '?'};
182 byte imsi[] = prompt(msg, (short)0, (short)15);
Neels Hofmeyrd20f93a2020-02-24 22:42:22 +0100183 /* The IMSI file should be 9 bytes long, even if the IMSI is shorter */
184 byte mi[];
185 try {
186 mi = MobileIdentity.str2mi(imsi, MobileIdentity.MI_IMSI, (byte)9);
Neels Hofmeyr41b6f542020-02-24 23:00:30 +0100187 writeIMSI(mi);
Neels Hofmeyrd20f93a2020-02-24 22:42:22 +0100188 } catch (Exception e) {
189 byte err[] = {'E', 'R', 'R' };
190 showMsgAndWaitKey(err);
191 }
Oliver Smithca866fe2020-02-24 09:56:30 +0100192 }
Neels Hofmeyrc24fdd12020-02-24 21:31:01 +0100193
194 private byte[] readIMSI()
195 {
196 gsmFile.select((short) SIMView.FID_DF_GSM);
197 gsmFile.select((short) SIMView.FID_EF_IMSI);
198 byte[] IMSI = new byte[9];
199 gsmFile.readBinary((short)0, IMSI, (short)0, (short)9);
200 return IMSI;
201 }
202
203 private void writeIMSI(byte mi[])
204 {
205 gsmFile.select((short) SIMView.FID_DF_GSM);
206 gsmFile.select((short) SIMView.FID_EF_IMSI);
207 gsmFile.updateBinary((short)0, mi, (short)0, (short)mi.length);
208 }
Oliver Smith4e5e5162020-02-21 08:47:36 +0100209}