blob: 55d1979c65455a0c4a7a486f76a7966cd45754f1 [file] [log] [blame]
Sylvain Munaut76504e02010-12-07 00:24:32 +01001#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4""" pySim: Card programmation logic
5"""
6
7#
8# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
Harald Welte3156d902011-03-22 21:48:19 +01009# Copyright (C) 2011 Harald Welte <laforge@gnumonks.org>
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030010# Copyright (C) 2017 Alexander.Chemeris <Alexander.Chemeris@gmail.com>
Sylvain Munaut76504e02010-12-07 00:24:32 +010011#
12# This program is free software: you can redistribute it and/or modify
13# it under the terms of the GNU General Public License as published by
14# the Free Software Foundation, either version 2 of the License, or
15# (at your option) any later version.
16#
17# This program is distributed in the hope that it will be useful,
18# but WITHOUT ANY WARRANTY; without even the implied warranty of
19# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20# GNU General Public License for more details.
21#
22# You should have received a copy of the GNU General Public License
23# along with this program. If not, see <http://www.gnu.org/licenses/>.
24#
25
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030026from pySim.ts_51_011 import EF, DF
27from pySim.utils import *
Alexander Chemeris8ad124a2018-01-10 14:17:55 +090028from smartcard.util import toBytes
Sylvain Munaut76504e02010-12-07 00:24:32 +010029
30class Card(object):
31
32 def __init__(self, scc):
33 self._scc = scc
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030034 self._adm_chv_num = 4
Supreeth Herlee4e98312020-03-18 11:33:14 +010035 self._aids = []
Sylvain Munaut76504e02010-12-07 00:24:32 +010036
Sylvain Munaut76504e02010-12-07 00:24:32 +010037 def reset(self):
38 self._scc.reset_card()
39
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030040 def verify_adm(self, key):
41 '''
42 Authenticate with ADM key
43 '''
44 (res, sw) = self._scc.verify_chv(self._adm_chv_num, key)
45 return sw
46
47 def read_iccid(self):
48 (res, sw) = self._scc.read_binary(EF['ICCID'])
49 if sw == '9000':
50 return (dec_iccid(res), sw)
51 else:
52 return (None, sw)
53
54 def read_imsi(self):
55 (res, sw) = self._scc.read_binary(EF['IMSI'])
56 if sw == '9000':
57 return (dec_imsi(res), sw)
58 else:
59 return (None, sw)
60
61 def update_imsi(self, imsi):
62 data, sw = self._scc.update_binary(EF['IMSI'], enc_imsi(imsi))
63 return sw
64
65 def update_acc(self, acc):
66 data, sw = self._scc.update_binary(EF['ACC'], lpad(acc, 4))
67 return sw
68
69 def update_hplmn_act(self, mcc, mnc, access_tech='FFFF'):
70 """
71 Update Home PLMN with access technology bit-field
72
73 See Section "10.3.37 EFHPLMNwAcT (HPLMN Selector with Access Technology)"
74 in ETSI TS 151 011 for the details of the access_tech field coding.
75 Some common values:
76 access_tech = '0080' # Only GSM is selected
77 access_tech = 'FFFF' # All technologues selected, even Reserved for Future Use ones
78 """
79 # get size and write EF.HPLMNwAcT
Supreeth Herle2d785972019-11-30 11:00:10 +010080 data = self._scc.read_binary(EF['HPLMNwAcT'], length=None, offset=0)
Vadim Yanitskiy9664b2e2020-02-27 01:49:51 +070081 size = len(data[0]) // 2
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030082 hplmn = enc_plmn(mcc, mnc)
83 content = hplmn + access_tech
Vadim Yanitskiy9664b2e2020-02-27 01:49:51 +070084 data, sw = self._scc.update_binary(EF['HPLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030085 return sw
86
Supreeth Herle1757b262020-03-19 12:43:11 +010087 def read_oplmn_act(self):
88 (res, sw) = self._scc.read_binary(EF['OPLMNwAcT'])
89 if sw == '9000':
90 return (format_xplmn_w_act(res), sw)
91 else:
92 return (None, sw)
93
Philipp Maierc8ce82a2018-07-04 17:57:20 +020094 def update_oplmn_act(self, mcc, mnc, access_tech='FFFF'):
95 """
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +020096 See note in update_hplmn_act()
Philipp Maierc8ce82a2018-07-04 17:57:20 +020097 """
98 # get size and write EF.OPLMNwAcT
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +020099 data = self._scc.read_binary(EF['OPLMNwAcT'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700100 size = len(data[0]) // 2
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200101 hplmn = enc_plmn(mcc, mnc)
102 content = hplmn + access_tech
Vadim Yanitskiy9664b2e2020-02-27 01:49:51 +0700103 data, sw = self._scc.update_binary(EF['OPLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200104 return sw
105
Supreeth Herle14084402020-03-19 12:42:10 +0100106 def read_plmn_act(self):
107 (res, sw) = self._scc.read_binary(EF['PLMNwAcT'])
108 if sw == '9000':
109 return (format_xplmn_w_act(res), sw)
110 else:
111 return (None, sw)
112
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200113 def update_plmn_act(self, mcc, mnc, access_tech='FFFF'):
114 """
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200115 See note in update_hplmn_act()
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200116 """
117 # get size and write EF.PLMNwAcT
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200118 data = self._scc.read_binary(EF['PLMNwAcT'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700119 size = len(data[0]) // 2
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200120 hplmn = enc_plmn(mcc, mnc)
121 content = hplmn + access_tech
Vadim Yanitskiy9664b2e2020-02-27 01:49:51 +0700122 data, sw = self._scc.update_binary(EF['PLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200123 return sw
124
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200125 def update_plmnsel(self, mcc, mnc):
126 data = self._scc.read_binary(EF['PLMNsel'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700127 size = len(data[0]) // 2
Philipp Maier5bf42602018-07-11 23:23:40 +0200128 hplmn = enc_plmn(mcc, mnc)
Philipp Maieraf9ae8b2018-07-13 11:15:49 +0200129 data, sw = self._scc.update_binary(EF['PLMNsel'], hplmn + 'ff' * (size-3))
130 return sw
Philipp Maier5bf42602018-07-11 23:23:40 +0200131
Alexander Chemeriseb6807d2017-07-18 17:04:38 +0300132 def update_smsp(self, smsp):
133 data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 84))
134 return sw
135
Philipp Maieree908ae2019-03-21 16:21:12 +0100136 def update_ad(self, mnc):
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200137 #See also: 3GPP TS 31.102, chapter 4.2.18
138 mnclen = len(str(mnc))
139 if mnclen == 1:
140 mnclen = 2
141 if mnclen > 3:
Philipp Maieree908ae2019-03-21 16:21:12 +0100142 raise RuntimeError('unable to calculate proper mnclen')
143
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200144 data = self._scc.read_binary(EF['AD'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700145 size = len(data[0]) // 2
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200146 content = data[0][0:6] + "%02X" % mnclen
Philipp Maieree908ae2019-03-21 16:21:12 +0100147 data, sw = self._scc.update_binary(EF['AD'], content)
148 return sw
149
Alexander Chemeriseb6807d2017-07-18 17:04:38 +0300150 def read_spn(self):
151 (spn, sw) = self._scc.read_binary(EF['SPN'])
152 if sw == '9000':
153 return (dec_spn(spn), sw)
154 else:
155 return (None, sw)
156
157 def update_spn(self, name, hplmn_disp=False, oplmn_disp=False):
158 content = enc_spn(name, hplmn_disp, oplmn_disp)
159 data, sw = self._scc.update_binary(EF['SPN'], rpad(content, 32))
160 return sw
161
Supreeth Herled21349a2020-04-01 08:37:47 +0200162 def read_binary(self, ef, length=None, offset=0):
163 ef_path = ef in EF and EF[ef] or ef
164 return self._scc.read_binary(ef_path, length, offset)
165
Supreeth Herlead10d662020-04-01 08:43:08 +0200166 def read_record(self, ef, rec_no):
167 ef_path = ef in EF and EF[ef] or ef
168 return self._scc.read_record(ef_path, rec_no)
169
Supreeth Herle98a69272020-03-18 12:14:48 +0100170 def read_gid1(self):
171 (res, sw) = self._scc.read_binary(EF['GID1'])
172 if sw == '9000':
173 return (res, sw)
174 else:
175 return (None, sw)
176
Philipp Maier0ad5bcf2019-12-31 17:55:47 +0100177 # Read the (full) AID for either ISIM or USIM application
178 def read_aid(self, isim = False):
179
180 # First (known) halves of the AID
181 aid_usim = "a0000000871002"
182 aid_isim = "a0000000871004"
183
184 # Select which one to look for
185 if isim:
186 aid = aid_isim
187 else:
188 aid = aid_usim
189
190 # Find out how many records the EF.DIR has, then go through
191 # all records and try to find the AID we are looking for
192 aid_record_count = self._scc.record_count(['2F00'])
193 for i in range(0, aid_record_count):
194 record = self._scc.read_record(['2F00'], i + 1)
195 if aid in record[0]:
196 aid_len = int(record[0][6:8], 16)
197 return record[0][8:8 + aid_len * 2]
198
199 return None
200
Supreeth Herlee4e98312020-03-18 11:33:14 +0100201 # Fetch all the AIDs present on UICC
202 def read_aids(self):
203 try:
204 # Find out how many records the EF.DIR has
205 # and store all the AIDs in the UICC
206 rec_cnt = self._scc.record_count(['3f00', '2f00'])
207 for i in range(0, rec_cnt):
208 rec = self._scc.read_record(['3f00', '2f00'], i + 1)
209 if (rec[0][0:2], rec[0][4:6]) == ('61', '4f') and len(rec[0]) > 12 \
210 and rec[0][8:8 + int(rec[0][6:8], 16) * 2] not in self._aids:
211 self._aids.append(rec[0][8:8 + int(rec[0][6:8], 16) * 2])
212 except Exception as e:
213 print("Can't read AIDs from SIM -- %s" % (str(e),))
214
Sylvain Munaut76504e02010-12-07 00:24:32 +0100215
216class _MagicSimBase(Card):
217 """
218 Theses cards uses several record based EFs to store the provider infos,
219 each possible provider uses a specific record number in each EF. The
220 indexes used are ( where N is the number of providers supported ) :
221 - [2 .. N+1] for the operator name
Supreeth Herle9ca41c12020-01-21 12:50:30 +0100222 - [1 .. N] for the programable EFs
Sylvain Munaut76504e02010-12-07 00:24:32 +0100223
224 * 3f00/7f4d/8f0c : Operator Name
225
226 bytes 0-15 : provider name, padded with 0xff
227 byte 16 : length of the provider name
228 byte 17 : 01 for valid records, 00 otherwise
229
230 * 3f00/7f4d/8f0d : Programmable Binary EFs
231
232 * 3f00/7f4d/8f0e : Programmable Record EFs
233
234 """
235
236 @classmethod
237 def autodetect(kls, scc):
238 try:
239 for p, l, t in kls._files.values():
240 if not t:
241 continue
242 if scc.record_size(['3f00', '7f4d', p]) != l:
243 return None
244 except:
245 return None
246
247 return kls(scc)
248
249 def _get_count(self):
250 """
251 Selects the file and returns the total number of entries
252 and entry size
253 """
254 f = self._files['name']
255
256 r = self._scc.select_file(['3f00', '7f4d', f[0]])
257 rec_len = int(r[-1][28:30], 16)
258 tlen = int(r[-1][4:8],16)
259 rec_cnt = (tlen / rec_len) - 1;
260
261 if (rec_cnt < 1) or (rec_len != f[1]):
262 raise RuntimeError('Bad card type')
263
264 return rec_cnt
265
266 def program(self, p):
267 # Go to dir
268 self._scc.select_file(['3f00', '7f4d'])
269
270 # Home PLMN in PLMN_Sel format
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400271 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100272
273 # Operator name ( 3f00/7f4d/8f0c )
274 self._scc.update_record(self._files['name'][0], 2,
275 rpad(b2h(p['name']), 32) + ('%02x' % len(p['name'])) + '01'
276 )
277
278 # ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
279 v = ''
280
281 # inline Ki
282 if self._ki_file is None:
283 v += p['ki']
284
285 # ICCID
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400286 v += '3f00' + '2fe2' + '0a' + enc_iccid(p['iccid'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100287
288 # IMSI
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400289 v += '7f20' + '6f07' + '09' + enc_imsi(p['imsi'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100290
291 # Ki
292 if self._ki_file:
293 v += self._ki_file + '10' + p['ki']
294
295 # PLMN_Sel
296 v+= '6f30' + '18' + rpad(hplmn, 36)
297
Alexander Chemeris21885242013-07-02 16:56:55 +0400298 # ACC
299 # This doesn't work with "fake" SuperSIM cards,
300 # but will hopefully work with real SuperSIMs.
301 if p.get('acc') is not None:
302 v+= '6f78' + '02' + lpad(p['acc'], 4)
303
Sylvain Munaut76504e02010-12-07 00:24:32 +0100304 self._scc.update_record(self._files['b_ef'][0], 1,
305 rpad(v, self._files['b_ef'][1]*2)
306 )
307
308 # SMSP ( 3f00/7f4d/8f0e )
309 # FIXME
310
311 # Write PLMN_Sel forcefully as well
312 r = self._scc.select_file(['3f00', '7f20', '6f30'])
313 tl = int(r[-1][4:8], 16)
314
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400315 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100316 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
317
318 def erase(self):
319 # Dummy
320 df = {}
321 for k, v in self._files.iteritems():
322 ofs = 1
323 fv = v[1] * 'ff'
324 if k == 'name':
325 ofs = 2
326 fv = fv[0:-4] + '0000'
327 df[v[0]] = (fv, ofs)
328
329 # Write
330 for n in range(0,self._get_count()):
331 for k, (msg, ofs) in df.iteritems():
332 self._scc.update_record(['3f00', '7f4d', k], n + ofs, msg)
333
334
335class SuperSim(_MagicSimBase):
336
337 name = 'supersim'
338
339 _files = {
340 'name' : ('8f0c', 18, True),
341 'b_ef' : ('8f0d', 74, True),
342 'r_ef' : ('8f0e', 50, True),
343 }
344
345 _ki_file = None
346
347
348class MagicSim(_MagicSimBase):
349
350 name = 'magicsim'
351
352 _files = {
353 'name' : ('8f0c', 18, True),
354 'b_ef' : ('8f0d', 130, True),
355 'r_ef' : ('8f0e', 102, False),
356 }
357
358 _ki_file = '6f1b'
359
360
361class FakeMagicSim(Card):
362 """
363 Theses cards have a record based EF 3f00/000c that contains the provider
364 informations. See the program method for its format. The records go from
365 1 to N.
366 """
367
368 name = 'fakemagicsim'
369
370 @classmethod
371 def autodetect(kls, scc):
372 try:
373 if scc.record_size(['3f00', '000c']) != 0x5a:
374 return None
375 except:
376 return None
377
378 return kls(scc)
379
380 def _get_infos(self):
381 """
382 Selects the file and returns the total number of entries
383 and entry size
384 """
385
386 r = self._scc.select_file(['3f00', '000c'])
387 rec_len = int(r[-1][28:30], 16)
388 tlen = int(r[-1][4:8],16)
389 rec_cnt = (tlen / rec_len) - 1;
390
391 if (rec_cnt < 1) or (rec_len != 0x5a):
392 raise RuntimeError('Bad card type')
393
394 return rec_cnt, rec_len
395
396 def program(self, p):
397 # Home PLMN
398 r = self._scc.select_file(['3f00', '7f20', '6f30'])
399 tl = int(r[-1][4:8], 16)
400
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400401 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100402 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
403
404 # Get total number of entries and entry size
405 rec_cnt, rec_len = self._get_infos()
406
407 # Set first entry
408 entry = (
Philipp Maier45daa922019-04-01 15:49:45 +0200409 '81' + # 1b Status: Valid & Active
Sylvain Munaut76504e02010-12-07 00:24:32 +0100410 rpad(b2h(p['name'][0:14]), 28) + # 14b Entry Name
Philipp Maier45daa922019-04-01 15:49:45 +0200411 enc_iccid(p['iccid']) + # 10b ICCID
412 enc_imsi(p['imsi']) + # 9b IMSI_len + id_type(9) + IMSI
413 p['ki'] + # 16b Ki
414 lpad(p['smsp'], 80) # 40b SMSP (padded with ff if needed)
Sylvain Munaut76504e02010-12-07 00:24:32 +0100415 )
416 self._scc.update_record('000c', 1, entry)
417
418 def erase(self):
419 # Get total number of entries and entry size
420 rec_cnt, rec_len = self._get_infos()
421
422 # Erase all entries
423 entry = 'ff' * rec_len
424 for i in range(0, rec_cnt):
425 self._scc.update_record('000c', 1+i, entry)
426
Sylvain Munaut5da8d4e2013-07-02 15:13:24 +0200427
Harald Welte3156d902011-03-22 21:48:19 +0100428class GrcardSim(Card):
429 """
430 Greencard (grcard.cn) HZCOS GSM SIM
431 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
432 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
433 """
434
435 name = 'grcardsim'
436
437 @classmethod
438 def autodetect(kls, scc):
439 return None
440
441 def program(self, p):
442 # We don't really know yet what ADM PIN 4 is about
443 #self._scc.verify_chv(4, h2b("4444444444444444"))
444
445 # Authenticate using ADM PIN 5
Jan Balkec3ebd332015-01-26 12:22:55 +0100446 if p['pin_adm']:
Philipp Maiera3de5a32018-08-23 10:27:04 +0200447 pin = h2b(p['pin_adm'])
Jan Balkec3ebd332015-01-26 12:22:55 +0100448 else:
449 pin = h2b("4444444444444444")
450 self._scc.verify_chv(5, pin)
Harald Welte3156d902011-03-22 21:48:19 +0100451
452 # EF.ICCID
453 r = self._scc.select_file(['3f00', '2fe2'])
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400454 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
Harald Welte3156d902011-03-22 21:48:19 +0100455
456 # EF.IMSI
457 r = self._scc.select_file(['3f00', '7f20', '6f07'])
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400458 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
Harald Welte3156d902011-03-22 21:48:19 +0100459
460 # EF.ACC
Alexander Chemeris21885242013-07-02 16:56:55 +0400461 if p.get('acc') is not None:
462 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
Harald Welte3156d902011-03-22 21:48:19 +0100463
464 # EF.SMSP
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200465 if p.get('smsp'):
Harald Welte23888da2019-08-28 23:19:11 +0200466 r = self._scc.select_file(['3f00', '7f10', '6f42'])
467 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
Harald Welte3156d902011-03-22 21:48:19 +0100468
469 # Set the Ki using proprietary command
470 pdu = '80d4020010' + p['ki']
471 data, sw = self._scc._tp.send_apdu(pdu)
472
473 # EF.HPLMN
474 r = self._scc.select_file(['3f00', '7f20', '6f30'])
475 size = int(r[-1][4:8], 16)
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400476 hplmn = enc_plmn(p['mcc'], p['mnc'])
Harald Welte3156d902011-03-22 21:48:19 +0100477 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
478
479 # EF.SPN (Service Provider Name)
480 r = self._scc.select_file(['3f00', '7f20', '6f30'])
481 size = int(r[-1][4:8], 16)
482 # FIXME
483
484 # FIXME: EF.MSISDN
485
486 def erase(self):
487 return
Sylvain Munaut76504e02010-12-07 00:24:32 +0100488
Harald Weltee10394b2011-12-07 12:34:14 +0100489class SysmoSIMgr1(GrcardSim):
490 """
491 sysmocom sysmoSIM-GR1
492 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
493 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
494 """
495 name = 'sysmosim-gr1'
496
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200497 @classmethod
Philipp Maier087feff2018-08-23 09:41:36 +0200498 def autodetect(kls, scc):
499 try:
500 # Look for ATR
501 if scc.get_atr() == toBytes("3B 99 18 00 11 88 22 33 44 55 66 77 60"):
502 return kls(scc)
503 except:
504 return None
505 return None
Sylvain Munaut5da8d4e2013-07-02 15:13:24 +0200506
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100507class SysmoUSIMgr1(Card):
508 """
509 sysmocom sysmoUSIM-GR1
510 """
511 name = 'sysmoUSIM-GR1'
512
513 @classmethod
514 def autodetect(kls, scc):
515 # TODO: Access the ATR
516 return None
517
518 def program(self, p):
519 # TODO: check if verify_chv could be used or what it needs
520 # self._scc.verify_chv(0x0A, [0x33,0x32,0x32,0x31,0x33,0x32,0x33,0x32])
521 # Unlock the card..
522 data, sw = self._scc._tp.send_apdu_checksw("0020000A083332323133323332")
523
524 # TODO: move into SimCardCommands
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100525 par = ( p['ki'] + # 16b K
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400526 p['opc'] + # 32b OPC
527 enc_iccid(p['iccid']) + # 10b ICCID
528 enc_imsi(p['imsi']) # 9b IMSI_len + id_type(9) + IMSI
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100529 )
530 data, sw = self._scc._tp.send_apdu_checksw("0099000033" + par)
531
532 def erase(self):
533 return
534
Sylvain Munaut053c8952013-07-02 15:12:32 +0200535
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100536class SysmoSIMgr2(Card):
537 """
538 sysmocom sysmoSIM-GR2
539 """
540
541 name = 'sysmoSIM-GR2'
542
543 @classmethod
544 def autodetect(kls, scc):
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900545 try:
546 # Look for ATR
547 if scc.get_atr() == toBytes("3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68"):
548 return kls(scc)
549 except:
550 return None
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100551 return None
552
553 def program(self, p):
554
555 # select MF
556 r = self._scc.select_file(['3f00'])
557
558 # authenticate as SUPER ADM using default key
559 self._scc.verify_chv(0x0b, h2b("3838383838383838"))
560
561 # set ADM pin using proprietary command
562 # INS: D4
563 # P1: 3A for PIN, 3B for PUK
564 # P2: CHV number, as in VERIFY CHV for PIN, and as in UNBLOCK CHV for PUK
565 # P3: 08, CHV length (curiously the PUK is also 08 length, instead of 10)
Jan Balkec3ebd332015-01-26 12:22:55 +0100566 if p['pin_adm']:
Daniel Willmann7d38d742018-06-15 07:31:50 +0200567 pin = h2b(p['pin_adm'])
Jan Balkec3ebd332015-01-26 12:22:55 +0100568 else:
569 pin = h2b("4444444444444444")
570
571 pdu = 'A0D43A0508' + b2h(pin)
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100572 data, sw = self._scc._tp.send_apdu(pdu)
573
574 # authenticate as ADM (enough to write file, and can set PINs)
Jan Balkec3ebd332015-01-26 12:22:55 +0100575
576 self._scc.verify_chv(0x05, pin)
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100577
578 # write EF.ICCID
579 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
580
581 # select DF_GSM
582 r = self._scc.select_file(['7f20'])
583
584 # write EF.IMSI
585 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
586
587 # write EF.ACC
588 if p.get('acc') is not None:
589 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
590
591 # get size and write EF.HPLMN
592 r = self._scc.select_file(['6f30'])
593 size = int(r[-1][4:8], 16)
594 hplmn = enc_plmn(p['mcc'], p['mnc'])
595 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
596
597 # set COMP128 version 0 in proprietary file
598 data, sw = self._scc.update_binary('0001', '001000')
599
600 # set Ki in proprietary file
601 data, sw = self._scc.update_binary('0001', p['ki'], 3)
602
603 # select DF_TELECOM
604 r = self._scc.select_file(['3f00', '7f10'])
605
606 # write EF.SMSP
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200607 if p.get('smsp'):
Harald Welte23888da2019-08-28 23:19:11 +0200608 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100609
610 def erase(self):
611 return
612
Jan Balke3e840672015-01-26 15:36:27 +0100613class SysmoUSIMSJS1(Card):
614 """
615 sysmocom sysmoUSIM-SJS1
616 """
617
618 name = 'sysmoUSIM-SJS1'
619
620 def __init__(self, ssc):
621 super(SysmoUSIMSJS1, self).__init__(ssc)
622 self._scc.cla_byte = "00"
Philipp Maier2d15ea02019-03-20 12:40:36 +0100623 self._scc.sel_ctrl = "0004" #request an FCP
Jan Balke3e840672015-01-26 15:36:27 +0100624
625 @classmethod
626 def autodetect(kls, scc):
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900627 try:
628 # Look for ATR
629 if scc.get_atr() == toBytes("3B 9F 96 80 1F C7 80 31 A0 73 BE 21 13 67 43 20 07 18 00 00 01 A5"):
630 return kls(scc)
631 except:
632 return None
Jan Balke3e840672015-01-26 15:36:27 +0100633 return None
634
635 def program(self, p):
636
Philipp Maiere9604882017-03-21 17:24:31 +0100637 # authenticate as ADM using default key (written on the card..)
638 if not p['pin_adm']:
639 raise ValueError("Please provide a PIN-ADM as there is no default one")
640 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
Jan Balke3e840672015-01-26 15:36:27 +0100641
642 # select MF
643 r = self._scc.select_file(['3f00'])
644
Philipp Maiere9604882017-03-21 17:24:31 +0100645 # write EF.ICCID
646 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
647
Jan Balke3e840672015-01-26 15:36:27 +0100648 # select DF_GSM
649 r = self._scc.select_file(['7f20'])
650
Jan Balke3e840672015-01-26 15:36:27 +0100651 # set Ki in proprietary file
652 data, sw = self._scc.update_binary('00FF', p['ki'])
653
Philipp Maier1be35bf2018-07-13 11:29:03 +0200654 # set OPc in proprietary file
Daniel Willmann67acdbc2018-06-15 07:42:48 +0200655 if 'opc' in p:
656 content = "01" + p['opc']
657 data, sw = self._scc.update_binary('00F7', content)
Jan Balke3e840672015-01-26 15:36:27 +0100658
Supreeth Herle7947d922019-06-08 07:50:53 +0200659 # set Service Provider Name
Supreeth Herle840a9e22020-01-21 13:32:46 +0100660 if p.get('name') is not None:
661 content = enc_spn(p['name'], True, True)
662 data, sw = self._scc.update_binary('6F46', rpad(content, 32))
Supreeth Herle7947d922019-06-08 07:50:53 +0200663
Supreeth Herlec8796a32019-12-23 12:23:42 +0100664 if p.get('acc') is not None:
665 self.update_acc(p['acc'])
666
Jan Balke3e840672015-01-26 15:36:27 +0100667 # write EF.IMSI
668 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
669
Philipp Maier2d15ea02019-03-20 12:40:36 +0100670 # EF.PLMNsel
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200671 if p.get('mcc') and p.get('mnc'):
672 sw = self.update_plmnsel(p['mcc'], p['mnc'])
673 if sw != '9000':
Philipp Maier2d15ea02019-03-20 12:40:36 +0100674 print("Programming PLMNsel failed with code %s"%sw)
675
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200676 # EF.PLMNwAcT
677 if p.get('mcc') and p.get('mnc'):
Philipp Maier2d15ea02019-03-20 12:40:36 +0100678 sw = self.update_plmn_act(p['mcc'], p['mnc'])
679 if sw != '9000':
680 print("Programming PLMNwAcT failed with code %s"%sw)
681
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200682 # EF.OPLMNwAcT
683 if p.get('mcc') and p.get('mnc'):
Philipp Maier2d15ea02019-03-20 12:40:36 +0100684 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
685 if sw != '9000':
686 print("Programming OPLMNwAcT failed with code %s"%sw)
687
Supreeth Herlef442fb42020-01-21 12:47:32 +0100688 # EF.HPLMNwAcT
689 if p.get('mcc') and p.get('mnc'):
690 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
691 if sw != '9000':
692 print("Programming HPLMNwAcT failed with code %s"%sw)
693
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200694 # EF.AD
695 if p.get('mcc') and p.get('mnc'):
Philipp Maieree908ae2019-03-21 16:21:12 +0100696 sw = self.update_ad(p['mnc'])
697 if sw != '9000':
698 print("Programming AD failed with code %s"%sw)
Philipp Maier2d15ea02019-03-20 12:40:36 +0100699
Daniel Willmann1d087ef2017-08-31 10:08:45 +0200700 # EF.SMSP
Harald Welte23888da2019-08-28 23:19:11 +0200701 if p.get('smsp'):
702 r = self._scc.select_file(['3f00', '7f10'])
703 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 104), force_len=True)
Jan Balke3e840672015-01-26 15:36:27 +0100704
Supreeth Herle5a541012019-12-22 08:59:16 +0100705 # EF.MSISDN
706 # TODO: Alpha Identifier (currently 'ff'O * 20)
707 # TODO: Capability/Configuration1 Record Identifier
708 # TODO: Extension1 Record Identifier
709 if p.get('msisdn') is not None:
710 msisdn = enc_msisdn(p['msisdn'])
711 data = 'ff' * 20 + msisdn + 'ff' * 2
712
713 r = self._scc.select_file(['3f00', '7f10'])
714 data, sw = self._scc.update_record('6F40', 1, data, force_len=True)
715
Alexander Chemerise0d9d882018-01-10 14:18:32 +0900716 def erase(self):
717 return
718
719
720class FairwavesSIM(Card):
721 """
722 FairwavesSIM
723
724 The SIM card is operating according to the standard.
725 For Ki/OP/OPC programming the following files are additionally open for writing:
726 3F00/7F20/FF01 – OP/OPC:
727 byte 1 = 0x01, bytes 2-17: OPC;
728 byte 1 = 0x00, bytes 2-17: OP;
729 3F00/7F20/FF02: Ki
730 """
731
Philipp Maier5a876312019-11-11 11:01:46 +0100732 name = 'Fairwaves-SIM'
Alexander Chemerise0d9d882018-01-10 14:18:32 +0900733 # Propriatary files
734 _EF_num = {
735 'Ki': 'FF02',
736 'OP/OPC': 'FF01',
737 }
738 _EF = {
739 'Ki': DF['GSM']+[_EF_num['Ki']],
740 'OP/OPC': DF['GSM']+[_EF_num['OP/OPC']],
741 }
742
743 def __init__(self, ssc):
744 super(FairwavesSIM, self).__init__(ssc)
745 self._adm_chv_num = 0x11
746 self._adm2_chv_num = 0x12
747
748
749 @classmethod
750 def autodetect(kls, scc):
751 try:
752 # Look for ATR
753 if scc.get_atr() == toBytes("3B 9F 96 80 1F C7 80 31 A0 73 BE 21 13 67 44 22 06 10 00 00 01 A9"):
754 return kls(scc)
755 except:
756 return None
757 return None
758
759
760 def verify_adm2(self, key):
761 '''
762 Authenticate with ADM2 key.
763
764 Fairwaves SIM cards support hierarchical key structure and ADM2 key
765 is a key which has access to proprietary files (Ki and OP/OPC).
766 That said, ADM key inherits permissions of ADM2 key and thus we rarely
767 need ADM2 key per se.
768 '''
769 (res, sw) = self._scc.verify_chv(self._adm2_chv_num, key)
770 return sw
771
772
773 def read_ki(self):
774 """
775 Read Ki in proprietary file.
776
777 Requires ADM1 access level
778 """
779 return self._scc.read_binary(self._EF['Ki'])
780
781
782 def update_ki(self, ki):
783 """
784 Set Ki in proprietary file.
785
786 Requires ADM1 access level
787 """
788 data, sw = self._scc.update_binary(self._EF['Ki'], ki)
789 return sw
790
791
792 def read_op_opc(self):
793 """
794 Read Ki in proprietary file.
795
796 Requires ADM1 access level
797 """
798 (ef, sw) = self._scc.read_binary(self._EF['OP/OPC'])
799 type = 'OP' if ef[0:2] == '00' else 'OPC'
800 return ((type, ef[2:]), sw)
801
802
803 def update_op(self, op):
804 """
805 Set OP in proprietary file.
806
807 Requires ADM1 access level
808 """
809 content = '00' + op
810 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
811 return sw
812
813
814 def update_opc(self, opc):
815 """
816 Set OPC in proprietary file.
817
818 Requires ADM1 access level
819 """
820 content = '01' + opc
821 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
822 return sw
823
824
825 def program(self, p):
826 # authenticate as ADM1
827 if not p['pin_adm']:
828 raise ValueError("Please provide a PIN-ADM as there is no default one")
829 sw = self.verify_adm(h2b(p['pin_adm']))
830 if sw != '9000':
831 raise RuntimeError('Failed to authenticate with ADM key %s'%(p['pin_adm'],))
832
833 # TODO: Set operator name
834 if p.get('smsp') is not None:
835 sw = self.update_smsp(p['smsp'])
836 if sw != '9000':
837 print("Programming SMSP failed with code %s"%sw)
838 # This SIM doesn't support changing ICCID
839 if p.get('mcc') is not None and p.get('mnc') is not None:
840 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
841 if sw != '9000':
842 print("Programming MCC/MNC failed with code %s"%sw)
843 if p.get('imsi') is not None:
844 sw = self.update_imsi(p['imsi'])
845 if sw != '9000':
846 print("Programming IMSI failed with code %s"%sw)
847 if p.get('ki') is not None:
848 sw = self.update_ki(p['ki'])
849 if sw != '9000':
850 print("Programming Ki failed with code %s"%sw)
851 if p.get('opc') is not None:
852 sw = self.update_opc(p['opc'])
853 if sw != '9000':
854 print("Programming OPC failed with code %s"%sw)
855 if p.get('acc') is not None:
856 sw = self.update_acc(p['acc'])
857 if sw != '9000':
858 print("Programming ACC failed with code %s"%sw)
Jan Balke3e840672015-01-26 15:36:27 +0100859
860 def erase(self):
861 return
862
863
Todd Neal9eeadfc2018-04-25 15:36:29 -0500864class OpenCellsSim(Card):
865 """
866 OpenCellsSim
867
868 """
869
Philipp Maier5a876312019-11-11 11:01:46 +0100870 name = 'OpenCells-SIM'
Todd Neal9eeadfc2018-04-25 15:36:29 -0500871
872 def __init__(self, ssc):
873 super(OpenCellsSim, self).__init__(ssc)
874 self._adm_chv_num = 0x0A
875
876
877 @classmethod
878 def autodetect(kls, scc):
879 try:
880 # Look for ATR
881 if scc.get_atr() == toBytes("3B 9F 95 80 1F C3 80 31 E0 73 FE 21 13 57 86 81 02 86 98 44 18 A8"):
882 return kls(scc)
883 except:
884 return None
885 return None
886
887
888 def program(self, p):
889 if not p['pin_adm']:
890 raise ValueError("Please provide a PIN-ADM as there is no default one")
891 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
892
893 # select MF
894 r = self._scc.select_file(['3f00'])
895
896 # write EF.ICCID
897 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
898
899 r = self._scc.select_file(['7ff0'])
900
901 # set Ki in proprietary file
902 data, sw = self._scc.update_binary('FF02', p['ki'])
903
904 # set OPC in proprietary file
905 data, sw = self._scc.update_binary('FF01', p['opc'])
906
907 # select DF_GSM
908 r = self._scc.select_file(['7f20'])
909
910 # write EF.IMSI
911 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
912
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200913class WavemobileSim(Card):
914 """
915 WavemobileSim
916
917 """
918
919 name = 'Wavemobile-SIM'
920
921 def __init__(self, ssc):
922 super(WavemobileSim, self).__init__(ssc)
923 self._adm_chv_num = 0x0A
924 self._scc.cla_byte = "00"
925 self._scc.sel_ctrl = "0004" #request an FCP
926
927 @classmethod
928 def autodetect(kls, scc):
929 try:
930 # Look for ATR
931 if scc.get_atr() == toBytes("3B 9F 95 80 1F C7 80 31 E0 73 F6 21 13 67 4D 45 16 00 43 01 00 8F"):
932 return kls(scc)
933 except:
934 return None
935 return None
936
937 def program(self, p):
938 if not p['pin_adm']:
939 raise ValueError("Please provide a PIN-ADM as there is no default one")
940 sw = self.verify_adm(h2b(p['pin_adm']))
941 if sw != '9000':
942 raise RuntimeError('Failed to authenticate with ADM key %s'%(p['pin_adm'],))
943
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200944 # EF.ICCID
945 # TODO: Add programming of the ICCID
946 if p.get('iccid'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200947 print("Warning: Programming of the ICCID is not implemented for this type of card.")
948
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200949 # KI (Presumably a propritary file)
950 # TODO: Add programming of KI
951 if p.get('ki'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200952 print("Warning: Programming of the KI is not implemented for this type of card.")
953
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200954 # OPc (Presumably a propritary file)
955 # TODO: Add programming of OPc
956 if p.get('opc'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200957 print("Warning: Programming of the OPc is not implemented for this type of card.")
958
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200959 # EF.SMSP
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200960 if p.get('smsp'):
961 sw = self.update_smsp(p['smsp'])
962 if sw != '9000':
963 print("Programming SMSP failed with code %s"%sw)
964
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200965 # EF.IMSI
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200966 if p.get('imsi'):
967 sw = self.update_imsi(p['imsi'])
968 if sw != '9000':
969 print("Programming IMSI failed with code %s"%sw)
970
971 # EF.ACC
972 if p.get('acc'):
973 sw = self.update_acc(p['acc'])
974 if sw != '9000':
975 print("Programming ACC failed with code %s"%sw)
976
977 # EF.PLMNsel
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200978 if p.get('mcc') and p.get('mnc'):
979 sw = self.update_plmnsel(p['mcc'], p['mnc'])
980 if sw != '9000':
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200981 print("Programming PLMNsel failed with code %s"%sw)
982
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200983 # EF.PLMNwAcT
984 if p.get('mcc') and p.get('mnc'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200985 sw = self.update_plmn_act(p['mcc'], p['mnc'])
986 if sw != '9000':
987 print("Programming PLMNwAcT failed with code %s"%sw)
988
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200989 # EF.OPLMNwAcT
990 if p.get('mcc') and p.get('mnc'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200991 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
992 if sw != '9000':
993 print("Programming OPLMNwAcT failed with code %s"%sw)
994
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200995 # EF.AD
996 if p.get('mcc') and p.get('mnc'):
Philipp Maier6e507a72019-04-01 16:33:48 +0200997 sw = self.update_ad(p['mnc'])
998 if sw != '9000':
999 print("Programming AD failed with code %s"%sw)
1000
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +02001001 return None
Philipp Maierc8ce82a2018-07-04 17:57:20 +02001002
1003 def erase(self):
1004 return
1005
Todd Neal9eeadfc2018-04-25 15:36:29 -05001006
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001007class SysmoISIMSJA2(Card):
1008 """
1009 sysmocom sysmoISIM-SJA2
1010 """
1011
1012 name = 'sysmoISIM-SJA2'
1013
1014 def __init__(self, ssc):
1015 super(SysmoISIMSJA2, self).__init__(ssc)
1016 self._scc.cla_byte = "00"
1017 self._scc.sel_ctrl = "0004" #request an FCP
1018
1019 @classmethod
1020 def autodetect(kls, scc):
1021 try:
1022 # Try card model #1
1023 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9"
1024 if scc.get_atr() == toBytes(atr):
1025 return kls(scc)
1026
1027 # Try card model #2
1028 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2"
1029 if scc.get_atr() == toBytes(atr):
1030 return kls(scc)
Philipp Maierb3e11ea2020-03-11 12:32:44 +01001031
1032 # Try card model #3
1033 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"
1034 if scc.get_atr() == toBytes(atr):
1035 return kls(scc)
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001036 except:
1037 return None
1038 return None
1039
1040 def program(self, p):
1041 # authenticate as ADM using default key (written on the card..)
1042 if not p['pin_adm']:
1043 raise ValueError("Please provide a PIN-ADM as there is no default one")
1044 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
1045
1046 # This type of card does not allow to reprogram the ICCID.
1047 # Reprogramming the ICCID would mess up the card os software
1048 # license management, so the ICCID must be kept at its factory
1049 # setting!
1050 if p.get('iccid'):
1051 print("Warning: Programming of the ICCID is not implemented for this type of card.")
1052
1053 # select DF_GSM
1054 self._scc.select_file(['7f20'])
1055
1056 # write EF.IMSI
1057 if p.get('imsi'):
1058 self._scc.update_binary('6f07', enc_imsi(p['imsi']))
1059
1060 # EF.PLMNsel
1061 if p.get('mcc') and p.get('mnc'):
1062 sw = self.update_plmnsel(p['mcc'], p['mnc'])
1063 if sw != '9000':
1064 print("Programming PLMNsel failed with code %s"%sw)
1065
1066 # EF.PLMNwAcT
1067 if p.get('mcc') and p.get('mnc'):
1068 sw = self.update_plmn_act(p['mcc'], p['mnc'])
1069 if sw != '9000':
1070 print("Programming PLMNwAcT failed with code %s"%sw)
1071
1072 # EF.OPLMNwAcT
1073 if p.get('mcc') and p.get('mnc'):
1074 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
1075 if sw != '9000':
1076 print("Programming OPLMNwAcT failed with code %s"%sw)
1077
1078 # EF.AD
1079 if p.get('mcc') and p.get('mnc'):
1080 sw = self.update_ad(p['mnc'])
1081 if sw != '9000':
1082 print("Programming AD failed with code %s"%sw)
1083
1084 # EF.SMSP
1085 if p.get('smsp'):
1086 r = self._scc.select_file(['3f00', '7f10'])
1087 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 104), force_len=True)
1088
1089 # update EF-SIM_AUTH_KEY (and EF-USIM_AUTH_KEY_2G, which is
1090 # hard linked to EF-USIM_AUTH_KEY)
1091 self._scc.select_file(['3f00'])
1092 self._scc.select_file(['a515'])
1093 if p.get('ki'):
1094 self._scc.update_binary('6f20', p['ki'], 1)
1095 if p.get('opc'):
1096 self._scc.update_binary('6f20', p['opc'], 17)
1097
1098 # update EF-USIM_AUTH_KEY in ADF.ISIM
1099 self._scc.select_file(['3f00'])
1100 aid = self.read_aid(isim = True)
Philipp Maierd9507862020-03-11 12:18:29 +01001101 if (aid):
1102 self._scc.select_adf(aid)
1103 if p.get('ki'):
1104 self._scc.update_binary('af20', p['ki'], 1)
1105 if p.get('opc'):
1106 self._scc.update_binary('af20', p['opc'], 17)
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001107
1108 # update EF-USIM_AUTH_KEY in ADF.USIM
1109 self._scc.select_file(['3f00'])
1110 aid = self.read_aid()
Philipp Maierd9507862020-03-11 12:18:29 +01001111 if (aid):
1112 self._scc.select_adf(aid)
1113 if p.get('ki'):
1114 self._scc.update_binary('af20', p['ki'], 1)
1115 if p.get('opc'):
1116 self._scc.update_binary('af20', p['opc'], 17)
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001117
1118 return
1119
1120 def erase(self):
1121 return
1122
1123
Todd Neal9eeadfc2018-04-25 15:36:29 -05001124# In order for autodetection ...
Harald Weltee10394b2011-12-07 12:34:14 +01001125_cards_classes = [ FakeMagicSim, SuperSim, MagicSim, GrcardSim,
Alexander Chemerise0d9d882018-01-10 14:18:32 +09001126 SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1,
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001127 FairwavesSIM, OpenCellsSim, WavemobileSim, SysmoISIMSJA2 ]
Alexander Chemeris8ad124a2018-01-10 14:17:55 +09001128
1129def card_autodetect(scc):
1130 for kls in _cards_classes:
1131 card = kls.autodetect(scc)
1132 if card is not None:
1133 card.reset()
1134 return card
1135 return None
Supreeth Herle4c306ab2020-03-18 11:38:00 +01001136
1137def card_detect(ctype, scc):
1138 # Detect type if needed
1139 card = None
1140 ctypes = dict([(kls.name, kls) for kls in _cards_classes])
1141
1142 if ctype in ("auto", "auto_once"):
1143 for kls in _cards_classes:
1144 card = kls.autodetect(scc)
1145 if card:
1146 print("Autodetected card type: %s" % card.name)
1147 card.reset()
1148 break
1149
1150 if card is None:
1151 print("Autodetection failed")
1152 return None
1153
1154 if ctype == "auto_once":
1155 ctype = card.name
1156
1157 elif ctype in ctypes:
1158 card = ctypes[ctype](scc)
1159
1160 else:
1161 raise ValueError("Unknown card type: %s" % ctype)
1162
1163 return card