blob: fe7f0fd1bcb32d2bd32138053ec1d355f2ca3e72 [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
Philipp Maierc8ce82a2018-07-04 17:57:20 +020087 def update_oplmn_act(self, mcc, mnc, access_tech='FFFF'):
88 """
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +020089 See note in update_hplmn_act()
Philipp Maierc8ce82a2018-07-04 17:57:20 +020090 """
91 # get size and write EF.OPLMNwAcT
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +020092 data = self._scc.read_binary(EF['OPLMNwAcT'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +070093 size = len(data[0]) // 2
Philipp Maierc8ce82a2018-07-04 17:57:20 +020094 hplmn = enc_plmn(mcc, mnc)
95 content = hplmn + access_tech
Vadim Yanitskiy9664b2e2020-02-27 01:49:51 +070096 data, sw = self._scc.update_binary(EF['OPLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
Philipp Maierc8ce82a2018-07-04 17:57:20 +020097 return sw
98
99 def update_plmn_act(self, mcc, mnc, access_tech='FFFF'):
100 """
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200101 See note in update_hplmn_act()
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200102 """
103 # get size and write EF.PLMNwAcT
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200104 data = self._scc.read_binary(EF['PLMNwAcT'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700105 size = len(data[0]) // 2
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200106 hplmn = enc_plmn(mcc, mnc)
107 content = hplmn + access_tech
Vadim Yanitskiy9664b2e2020-02-27 01:49:51 +0700108 data, sw = self._scc.update_binary(EF['PLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200109 return sw
110
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200111 def update_plmnsel(self, mcc, mnc):
112 data = self._scc.read_binary(EF['PLMNsel'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700113 size = len(data[0]) // 2
Philipp Maier5bf42602018-07-11 23:23:40 +0200114 hplmn = enc_plmn(mcc, mnc)
Philipp Maieraf9ae8b2018-07-13 11:15:49 +0200115 data, sw = self._scc.update_binary(EF['PLMNsel'], hplmn + 'ff' * (size-3))
116 return sw
Philipp Maier5bf42602018-07-11 23:23:40 +0200117
Alexander Chemeriseb6807d2017-07-18 17:04:38 +0300118 def update_smsp(self, smsp):
119 data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 84))
120 return sw
121
Philipp Maieree908ae2019-03-21 16:21:12 +0100122 def update_ad(self, mnc):
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200123 #See also: 3GPP TS 31.102, chapter 4.2.18
124 mnclen = len(str(mnc))
125 if mnclen == 1:
126 mnclen = 2
127 if mnclen > 3:
Philipp Maieree908ae2019-03-21 16:21:12 +0100128 raise RuntimeError('unable to calculate proper mnclen')
129
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200130 data = self._scc.read_binary(EF['AD'], length=None, offset=0)
Vadim Yanitskiy99affe12020-02-15 05:03:09 +0700131 size = len(data[0]) // 2
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200132 content = data[0][0:6] + "%02X" % mnclen
Philipp Maieree908ae2019-03-21 16:21:12 +0100133 data, sw = self._scc.update_binary(EF['AD'], content)
134 return sw
135
Alexander Chemeriseb6807d2017-07-18 17:04:38 +0300136 def read_spn(self):
137 (spn, sw) = self._scc.read_binary(EF['SPN'])
138 if sw == '9000':
139 return (dec_spn(spn), sw)
140 else:
141 return (None, sw)
142
143 def update_spn(self, name, hplmn_disp=False, oplmn_disp=False):
144 content = enc_spn(name, hplmn_disp, oplmn_disp)
145 data, sw = self._scc.update_binary(EF['SPN'], rpad(content, 32))
146 return sw
147
Philipp Maier0ad5bcf2019-12-31 17:55:47 +0100148 # Read the (full) AID for either ISIM or USIM application
149 def read_aid(self, isim = False):
150
151 # First (known) halves of the AID
152 aid_usim = "a0000000871002"
153 aid_isim = "a0000000871004"
154
155 # Select which one to look for
156 if isim:
157 aid = aid_isim
158 else:
159 aid = aid_usim
160
161 # Find out how many records the EF.DIR has, then go through
162 # all records and try to find the AID we are looking for
163 aid_record_count = self._scc.record_count(['2F00'])
164 for i in range(0, aid_record_count):
165 record = self._scc.read_record(['2F00'], i + 1)
166 if aid in record[0]:
167 aid_len = int(record[0][6:8], 16)
168 return record[0][8:8 + aid_len * 2]
169
170 return None
171
Supreeth Herlee4e98312020-03-18 11:33:14 +0100172 # Fetch all the AIDs present on UICC
173 def read_aids(self):
174 try:
175 # Find out how many records the EF.DIR has
176 # and store all the AIDs in the UICC
177 rec_cnt = self._scc.record_count(['3f00', '2f00'])
178 for i in range(0, rec_cnt):
179 rec = self._scc.read_record(['3f00', '2f00'], i + 1)
180 if (rec[0][0:2], rec[0][4:6]) == ('61', '4f') and len(rec[0]) > 12 \
181 and rec[0][8:8 + int(rec[0][6:8], 16) * 2] not in self._aids:
182 self._aids.append(rec[0][8:8 + int(rec[0][6:8], 16) * 2])
183 except Exception as e:
184 print("Can't read AIDs from SIM -- %s" % (str(e),))
185
Sylvain Munaut76504e02010-12-07 00:24:32 +0100186
187class _MagicSimBase(Card):
188 """
189 Theses cards uses several record based EFs to store the provider infos,
190 each possible provider uses a specific record number in each EF. The
191 indexes used are ( where N is the number of providers supported ) :
192 - [2 .. N+1] for the operator name
Supreeth Herle9ca41c12020-01-21 12:50:30 +0100193 - [1 .. N] for the programable EFs
Sylvain Munaut76504e02010-12-07 00:24:32 +0100194
195 * 3f00/7f4d/8f0c : Operator Name
196
197 bytes 0-15 : provider name, padded with 0xff
198 byte 16 : length of the provider name
199 byte 17 : 01 for valid records, 00 otherwise
200
201 * 3f00/7f4d/8f0d : Programmable Binary EFs
202
203 * 3f00/7f4d/8f0e : Programmable Record EFs
204
205 """
206
207 @classmethod
208 def autodetect(kls, scc):
209 try:
210 for p, l, t in kls._files.values():
211 if not t:
212 continue
213 if scc.record_size(['3f00', '7f4d', p]) != l:
214 return None
215 except:
216 return None
217
218 return kls(scc)
219
220 def _get_count(self):
221 """
222 Selects the file and returns the total number of entries
223 and entry size
224 """
225 f = self._files['name']
226
227 r = self._scc.select_file(['3f00', '7f4d', f[0]])
228 rec_len = int(r[-1][28:30], 16)
229 tlen = int(r[-1][4:8],16)
230 rec_cnt = (tlen / rec_len) - 1;
231
232 if (rec_cnt < 1) or (rec_len != f[1]):
233 raise RuntimeError('Bad card type')
234
235 return rec_cnt
236
237 def program(self, p):
238 # Go to dir
239 self._scc.select_file(['3f00', '7f4d'])
240
241 # Home PLMN in PLMN_Sel format
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400242 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100243
244 # Operator name ( 3f00/7f4d/8f0c )
245 self._scc.update_record(self._files['name'][0], 2,
246 rpad(b2h(p['name']), 32) + ('%02x' % len(p['name'])) + '01'
247 )
248
249 # ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
250 v = ''
251
252 # inline Ki
253 if self._ki_file is None:
254 v += p['ki']
255
256 # ICCID
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400257 v += '3f00' + '2fe2' + '0a' + enc_iccid(p['iccid'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100258
259 # IMSI
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400260 v += '7f20' + '6f07' + '09' + enc_imsi(p['imsi'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100261
262 # Ki
263 if self._ki_file:
264 v += self._ki_file + '10' + p['ki']
265
266 # PLMN_Sel
267 v+= '6f30' + '18' + rpad(hplmn, 36)
268
Alexander Chemeris21885242013-07-02 16:56:55 +0400269 # ACC
270 # This doesn't work with "fake" SuperSIM cards,
271 # but will hopefully work with real SuperSIMs.
272 if p.get('acc') is not None:
273 v+= '6f78' + '02' + lpad(p['acc'], 4)
274
Sylvain Munaut76504e02010-12-07 00:24:32 +0100275 self._scc.update_record(self._files['b_ef'][0], 1,
276 rpad(v, self._files['b_ef'][1]*2)
277 )
278
279 # SMSP ( 3f00/7f4d/8f0e )
280 # FIXME
281
282 # Write PLMN_Sel forcefully as well
283 r = self._scc.select_file(['3f00', '7f20', '6f30'])
284 tl = int(r[-1][4:8], 16)
285
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400286 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100287 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
288
289 def erase(self):
290 # Dummy
291 df = {}
292 for k, v in self._files.iteritems():
293 ofs = 1
294 fv = v[1] * 'ff'
295 if k == 'name':
296 ofs = 2
297 fv = fv[0:-4] + '0000'
298 df[v[0]] = (fv, ofs)
299
300 # Write
301 for n in range(0,self._get_count()):
302 for k, (msg, ofs) in df.iteritems():
303 self._scc.update_record(['3f00', '7f4d', k], n + ofs, msg)
304
305
306class SuperSim(_MagicSimBase):
307
308 name = 'supersim'
309
310 _files = {
311 'name' : ('8f0c', 18, True),
312 'b_ef' : ('8f0d', 74, True),
313 'r_ef' : ('8f0e', 50, True),
314 }
315
316 _ki_file = None
317
318
319class MagicSim(_MagicSimBase):
320
321 name = 'magicsim'
322
323 _files = {
324 'name' : ('8f0c', 18, True),
325 'b_ef' : ('8f0d', 130, True),
326 'r_ef' : ('8f0e', 102, False),
327 }
328
329 _ki_file = '6f1b'
330
331
332class FakeMagicSim(Card):
333 """
334 Theses cards have a record based EF 3f00/000c that contains the provider
335 informations. See the program method for its format. The records go from
336 1 to N.
337 """
338
339 name = 'fakemagicsim'
340
341 @classmethod
342 def autodetect(kls, scc):
343 try:
344 if scc.record_size(['3f00', '000c']) != 0x5a:
345 return None
346 except:
347 return None
348
349 return kls(scc)
350
351 def _get_infos(self):
352 """
353 Selects the file and returns the total number of entries
354 and entry size
355 """
356
357 r = self._scc.select_file(['3f00', '000c'])
358 rec_len = int(r[-1][28:30], 16)
359 tlen = int(r[-1][4:8],16)
360 rec_cnt = (tlen / rec_len) - 1;
361
362 if (rec_cnt < 1) or (rec_len != 0x5a):
363 raise RuntimeError('Bad card type')
364
365 return rec_cnt, rec_len
366
367 def program(self, p):
368 # Home PLMN
369 r = self._scc.select_file(['3f00', '7f20', '6f30'])
370 tl = int(r[-1][4:8], 16)
371
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400372 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100373 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
374
375 # Get total number of entries and entry size
376 rec_cnt, rec_len = self._get_infos()
377
378 # Set first entry
379 entry = (
Philipp Maier45daa922019-04-01 15:49:45 +0200380 '81' + # 1b Status: Valid & Active
Sylvain Munaut76504e02010-12-07 00:24:32 +0100381 rpad(b2h(p['name'][0:14]), 28) + # 14b Entry Name
Philipp Maier45daa922019-04-01 15:49:45 +0200382 enc_iccid(p['iccid']) + # 10b ICCID
383 enc_imsi(p['imsi']) + # 9b IMSI_len + id_type(9) + IMSI
384 p['ki'] + # 16b Ki
385 lpad(p['smsp'], 80) # 40b SMSP (padded with ff if needed)
Sylvain Munaut76504e02010-12-07 00:24:32 +0100386 )
387 self._scc.update_record('000c', 1, entry)
388
389 def erase(self):
390 # Get total number of entries and entry size
391 rec_cnt, rec_len = self._get_infos()
392
393 # Erase all entries
394 entry = 'ff' * rec_len
395 for i in range(0, rec_cnt):
396 self._scc.update_record('000c', 1+i, entry)
397
Sylvain Munaut5da8d4e2013-07-02 15:13:24 +0200398
Harald Welte3156d902011-03-22 21:48:19 +0100399class GrcardSim(Card):
400 """
401 Greencard (grcard.cn) HZCOS GSM SIM
402 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
403 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
404 """
405
406 name = 'grcardsim'
407
408 @classmethod
409 def autodetect(kls, scc):
410 return None
411
412 def program(self, p):
413 # We don't really know yet what ADM PIN 4 is about
414 #self._scc.verify_chv(4, h2b("4444444444444444"))
415
416 # Authenticate using ADM PIN 5
Jan Balkec3ebd332015-01-26 12:22:55 +0100417 if p['pin_adm']:
Philipp Maiera3de5a32018-08-23 10:27:04 +0200418 pin = h2b(p['pin_adm'])
Jan Balkec3ebd332015-01-26 12:22:55 +0100419 else:
420 pin = h2b("4444444444444444")
421 self._scc.verify_chv(5, pin)
Harald Welte3156d902011-03-22 21:48:19 +0100422
423 # EF.ICCID
424 r = self._scc.select_file(['3f00', '2fe2'])
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400425 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
Harald Welte3156d902011-03-22 21:48:19 +0100426
427 # EF.IMSI
428 r = self._scc.select_file(['3f00', '7f20', '6f07'])
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400429 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
Harald Welte3156d902011-03-22 21:48:19 +0100430
431 # EF.ACC
Alexander Chemeris21885242013-07-02 16:56:55 +0400432 if p.get('acc') is not None:
433 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
Harald Welte3156d902011-03-22 21:48:19 +0100434
435 # EF.SMSP
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200436 if p.get('smsp'):
Harald Welte23888da2019-08-28 23:19:11 +0200437 r = self._scc.select_file(['3f00', '7f10', '6f42'])
438 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
Harald Welte3156d902011-03-22 21:48:19 +0100439
440 # Set the Ki using proprietary command
441 pdu = '80d4020010' + p['ki']
442 data, sw = self._scc._tp.send_apdu(pdu)
443
444 # EF.HPLMN
445 r = self._scc.select_file(['3f00', '7f20', '6f30'])
446 size = int(r[-1][4:8], 16)
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400447 hplmn = enc_plmn(p['mcc'], p['mnc'])
Harald Welte3156d902011-03-22 21:48:19 +0100448 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
449
450 # EF.SPN (Service Provider Name)
451 r = self._scc.select_file(['3f00', '7f20', '6f30'])
452 size = int(r[-1][4:8], 16)
453 # FIXME
454
455 # FIXME: EF.MSISDN
456
457 def erase(self):
458 return
Sylvain Munaut76504e02010-12-07 00:24:32 +0100459
Harald Weltee10394b2011-12-07 12:34:14 +0100460class SysmoSIMgr1(GrcardSim):
461 """
462 sysmocom sysmoSIM-GR1
463 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
464 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
465 """
466 name = 'sysmosim-gr1'
467
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200468 @classmethod
Philipp Maier087feff2018-08-23 09:41:36 +0200469 def autodetect(kls, scc):
470 try:
471 # Look for ATR
472 if scc.get_atr() == toBytes("3B 99 18 00 11 88 22 33 44 55 66 77 60"):
473 return kls(scc)
474 except:
475 return None
476 return None
Sylvain Munaut5da8d4e2013-07-02 15:13:24 +0200477
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100478class SysmoUSIMgr1(Card):
479 """
480 sysmocom sysmoUSIM-GR1
481 """
482 name = 'sysmoUSIM-GR1'
483
484 @classmethod
485 def autodetect(kls, scc):
486 # TODO: Access the ATR
487 return None
488
489 def program(self, p):
490 # TODO: check if verify_chv could be used or what it needs
491 # self._scc.verify_chv(0x0A, [0x33,0x32,0x32,0x31,0x33,0x32,0x33,0x32])
492 # Unlock the card..
493 data, sw = self._scc._tp.send_apdu_checksw("0020000A083332323133323332")
494
495 # TODO: move into SimCardCommands
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100496 par = ( p['ki'] + # 16b K
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400497 p['opc'] + # 32b OPC
498 enc_iccid(p['iccid']) + # 10b ICCID
499 enc_imsi(p['imsi']) # 9b IMSI_len + id_type(9) + IMSI
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100500 )
501 data, sw = self._scc._tp.send_apdu_checksw("0099000033" + par)
502
503 def erase(self):
504 return
505
Sylvain Munaut053c8952013-07-02 15:12:32 +0200506
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100507class SysmoSIMgr2(Card):
508 """
509 sysmocom sysmoSIM-GR2
510 """
511
512 name = 'sysmoSIM-GR2'
513
514 @classmethod
515 def autodetect(kls, scc):
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900516 try:
517 # Look for ATR
518 if scc.get_atr() == toBytes("3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68"):
519 return kls(scc)
520 except:
521 return None
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100522 return None
523
524 def program(self, p):
525
526 # select MF
527 r = self._scc.select_file(['3f00'])
528
529 # authenticate as SUPER ADM using default key
530 self._scc.verify_chv(0x0b, h2b("3838383838383838"))
531
532 # set ADM pin using proprietary command
533 # INS: D4
534 # P1: 3A for PIN, 3B for PUK
535 # P2: CHV number, as in VERIFY CHV for PIN, and as in UNBLOCK CHV for PUK
536 # P3: 08, CHV length (curiously the PUK is also 08 length, instead of 10)
Jan Balkec3ebd332015-01-26 12:22:55 +0100537 if p['pin_adm']:
Daniel Willmann7d38d742018-06-15 07:31:50 +0200538 pin = h2b(p['pin_adm'])
Jan Balkec3ebd332015-01-26 12:22:55 +0100539 else:
540 pin = h2b("4444444444444444")
541
542 pdu = 'A0D43A0508' + b2h(pin)
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100543 data, sw = self._scc._tp.send_apdu(pdu)
544
545 # authenticate as ADM (enough to write file, and can set PINs)
Jan Balkec3ebd332015-01-26 12:22:55 +0100546
547 self._scc.verify_chv(0x05, pin)
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100548
549 # write EF.ICCID
550 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
551
552 # select DF_GSM
553 r = self._scc.select_file(['7f20'])
554
555 # write EF.IMSI
556 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
557
558 # write EF.ACC
559 if p.get('acc') is not None:
560 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
561
562 # get size and write EF.HPLMN
563 r = self._scc.select_file(['6f30'])
564 size = int(r[-1][4:8], 16)
565 hplmn = enc_plmn(p['mcc'], p['mnc'])
566 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
567
568 # set COMP128 version 0 in proprietary file
569 data, sw = self._scc.update_binary('0001', '001000')
570
571 # set Ki in proprietary file
572 data, sw = self._scc.update_binary('0001', p['ki'], 3)
573
574 # select DF_TELECOM
575 r = self._scc.select_file(['3f00', '7f10'])
576
577 # write EF.SMSP
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200578 if p.get('smsp'):
Harald Welte23888da2019-08-28 23:19:11 +0200579 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100580
581 def erase(self):
582 return
583
Jan Balke3e840672015-01-26 15:36:27 +0100584class SysmoUSIMSJS1(Card):
585 """
586 sysmocom sysmoUSIM-SJS1
587 """
588
589 name = 'sysmoUSIM-SJS1'
590
591 def __init__(self, ssc):
592 super(SysmoUSIMSJS1, self).__init__(ssc)
593 self._scc.cla_byte = "00"
Philipp Maier2d15ea02019-03-20 12:40:36 +0100594 self._scc.sel_ctrl = "0004" #request an FCP
Jan Balke3e840672015-01-26 15:36:27 +0100595
596 @classmethod
597 def autodetect(kls, scc):
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900598 try:
599 # Look for ATR
600 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"):
601 return kls(scc)
602 except:
603 return None
Jan Balke3e840672015-01-26 15:36:27 +0100604 return None
605
606 def program(self, p):
607
Philipp Maiere9604882017-03-21 17:24:31 +0100608 # authenticate as ADM using default key (written on the card..)
609 if not p['pin_adm']:
610 raise ValueError("Please provide a PIN-ADM as there is no default one")
611 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
Jan Balke3e840672015-01-26 15:36:27 +0100612
613 # select MF
614 r = self._scc.select_file(['3f00'])
615
Philipp Maiere9604882017-03-21 17:24:31 +0100616 # write EF.ICCID
617 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
618
Jan Balke3e840672015-01-26 15:36:27 +0100619 # select DF_GSM
620 r = self._scc.select_file(['7f20'])
621
Jan Balke3e840672015-01-26 15:36:27 +0100622 # set Ki in proprietary file
623 data, sw = self._scc.update_binary('00FF', p['ki'])
624
Philipp Maier1be35bf2018-07-13 11:29:03 +0200625 # set OPc in proprietary file
Daniel Willmann67acdbc2018-06-15 07:42:48 +0200626 if 'opc' in p:
627 content = "01" + p['opc']
628 data, sw = self._scc.update_binary('00F7', content)
Jan Balke3e840672015-01-26 15:36:27 +0100629
Supreeth Herle7947d922019-06-08 07:50:53 +0200630 # set Service Provider Name
Supreeth Herle840a9e22020-01-21 13:32:46 +0100631 if p.get('name') is not None:
632 content = enc_spn(p['name'], True, True)
633 data, sw = self._scc.update_binary('6F46', rpad(content, 32))
Supreeth Herle7947d922019-06-08 07:50:53 +0200634
Supreeth Herlec8796a32019-12-23 12:23:42 +0100635 if p.get('acc') is not None:
636 self.update_acc(p['acc'])
637
Jan Balke3e840672015-01-26 15:36:27 +0100638 # write EF.IMSI
639 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
640
Philipp Maier2d15ea02019-03-20 12:40:36 +0100641 # EF.PLMNsel
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200642 if p.get('mcc') and p.get('mnc'):
643 sw = self.update_plmnsel(p['mcc'], p['mnc'])
644 if sw != '9000':
Philipp Maier2d15ea02019-03-20 12:40:36 +0100645 print("Programming PLMNsel failed with code %s"%sw)
646
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200647 # EF.PLMNwAcT
648 if p.get('mcc') and p.get('mnc'):
Philipp Maier2d15ea02019-03-20 12:40:36 +0100649 sw = self.update_plmn_act(p['mcc'], p['mnc'])
650 if sw != '9000':
651 print("Programming PLMNwAcT failed with code %s"%sw)
652
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200653 # EF.OPLMNwAcT
654 if p.get('mcc') and p.get('mnc'):
Philipp Maier2d15ea02019-03-20 12:40:36 +0100655 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
656 if sw != '9000':
657 print("Programming OPLMNwAcT failed with code %s"%sw)
658
Supreeth Herlef442fb42020-01-21 12:47:32 +0100659 # EF.HPLMNwAcT
660 if p.get('mcc') and p.get('mnc'):
661 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
662 if sw != '9000':
663 print("Programming HPLMNwAcT failed with code %s"%sw)
664
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200665 # EF.AD
666 if p.get('mcc') and p.get('mnc'):
Philipp Maieree908ae2019-03-21 16:21:12 +0100667 sw = self.update_ad(p['mnc'])
668 if sw != '9000':
669 print("Programming AD failed with code %s"%sw)
Philipp Maier2d15ea02019-03-20 12:40:36 +0100670
Daniel Willmann1d087ef2017-08-31 10:08:45 +0200671 # EF.SMSP
Harald Welte23888da2019-08-28 23:19:11 +0200672 if p.get('smsp'):
673 r = self._scc.select_file(['3f00', '7f10'])
674 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 104), force_len=True)
Jan Balke3e840672015-01-26 15:36:27 +0100675
Supreeth Herle5a541012019-12-22 08:59:16 +0100676 # EF.MSISDN
677 # TODO: Alpha Identifier (currently 'ff'O * 20)
678 # TODO: Capability/Configuration1 Record Identifier
679 # TODO: Extension1 Record Identifier
680 if p.get('msisdn') is not None:
681 msisdn = enc_msisdn(p['msisdn'])
682 data = 'ff' * 20 + msisdn + 'ff' * 2
683
684 r = self._scc.select_file(['3f00', '7f10'])
685 data, sw = self._scc.update_record('6F40', 1, data, force_len=True)
686
Alexander Chemerise0d9d882018-01-10 14:18:32 +0900687 def erase(self):
688 return
689
690
691class FairwavesSIM(Card):
692 """
693 FairwavesSIM
694
695 The SIM card is operating according to the standard.
696 For Ki/OP/OPC programming the following files are additionally open for writing:
697 3F00/7F20/FF01 – OP/OPC:
698 byte 1 = 0x01, bytes 2-17: OPC;
699 byte 1 = 0x00, bytes 2-17: OP;
700 3F00/7F20/FF02: Ki
701 """
702
Philipp Maier5a876312019-11-11 11:01:46 +0100703 name = 'Fairwaves-SIM'
Alexander Chemerise0d9d882018-01-10 14:18:32 +0900704 # Propriatary files
705 _EF_num = {
706 'Ki': 'FF02',
707 'OP/OPC': 'FF01',
708 }
709 _EF = {
710 'Ki': DF['GSM']+[_EF_num['Ki']],
711 'OP/OPC': DF['GSM']+[_EF_num['OP/OPC']],
712 }
713
714 def __init__(self, ssc):
715 super(FairwavesSIM, self).__init__(ssc)
716 self._adm_chv_num = 0x11
717 self._adm2_chv_num = 0x12
718
719
720 @classmethod
721 def autodetect(kls, scc):
722 try:
723 # Look for ATR
724 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"):
725 return kls(scc)
726 except:
727 return None
728 return None
729
730
731 def verify_adm2(self, key):
732 '''
733 Authenticate with ADM2 key.
734
735 Fairwaves SIM cards support hierarchical key structure and ADM2 key
736 is a key which has access to proprietary files (Ki and OP/OPC).
737 That said, ADM key inherits permissions of ADM2 key and thus we rarely
738 need ADM2 key per se.
739 '''
740 (res, sw) = self._scc.verify_chv(self._adm2_chv_num, key)
741 return sw
742
743
744 def read_ki(self):
745 """
746 Read Ki in proprietary file.
747
748 Requires ADM1 access level
749 """
750 return self._scc.read_binary(self._EF['Ki'])
751
752
753 def update_ki(self, ki):
754 """
755 Set Ki in proprietary file.
756
757 Requires ADM1 access level
758 """
759 data, sw = self._scc.update_binary(self._EF['Ki'], ki)
760 return sw
761
762
763 def read_op_opc(self):
764 """
765 Read Ki in proprietary file.
766
767 Requires ADM1 access level
768 """
769 (ef, sw) = self._scc.read_binary(self._EF['OP/OPC'])
770 type = 'OP' if ef[0:2] == '00' else 'OPC'
771 return ((type, ef[2:]), sw)
772
773
774 def update_op(self, op):
775 """
776 Set OP in proprietary file.
777
778 Requires ADM1 access level
779 """
780 content = '00' + op
781 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
782 return sw
783
784
785 def update_opc(self, opc):
786 """
787 Set OPC in proprietary file.
788
789 Requires ADM1 access level
790 """
791 content = '01' + opc
792 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
793 return sw
794
795
796 def program(self, p):
797 # authenticate as ADM1
798 if not p['pin_adm']:
799 raise ValueError("Please provide a PIN-ADM as there is no default one")
800 sw = self.verify_adm(h2b(p['pin_adm']))
801 if sw != '9000':
802 raise RuntimeError('Failed to authenticate with ADM key %s'%(p['pin_adm'],))
803
804 # TODO: Set operator name
805 if p.get('smsp') is not None:
806 sw = self.update_smsp(p['smsp'])
807 if sw != '9000':
808 print("Programming SMSP failed with code %s"%sw)
809 # This SIM doesn't support changing ICCID
810 if p.get('mcc') is not None and p.get('mnc') is not None:
811 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
812 if sw != '9000':
813 print("Programming MCC/MNC failed with code %s"%sw)
814 if p.get('imsi') is not None:
815 sw = self.update_imsi(p['imsi'])
816 if sw != '9000':
817 print("Programming IMSI failed with code %s"%sw)
818 if p.get('ki') is not None:
819 sw = self.update_ki(p['ki'])
820 if sw != '9000':
821 print("Programming Ki failed with code %s"%sw)
822 if p.get('opc') is not None:
823 sw = self.update_opc(p['opc'])
824 if sw != '9000':
825 print("Programming OPC failed with code %s"%sw)
826 if p.get('acc') is not None:
827 sw = self.update_acc(p['acc'])
828 if sw != '9000':
829 print("Programming ACC failed with code %s"%sw)
Jan Balke3e840672015-01-26 15:36:27 +0100830
831 def erase(self):
832 return
833
834
Todd Neal9eeadfc2018-04-25 15:36:29 -0500835class OpenCellsSim(Card):
836 """
837 OpenCellsSim
838
839 """
840
Philipp Maier5a876312019-11-11 11:01:46 +0100841 name = 'OpenCells-SIM'
Todd Neal9eeadfc2018-04-25 15:36:29 -0500842
843 def __init__(self, ssc):
844 super(OpenCellsSim, self).__init__(ssc)
845 self._adm_chv_num = 0x0A
846
847
848 @classmethod
849 def autodetect(kls, scc):
850 try:
851 # Look for ATR
852 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"):
853 return kls(scc)
854 except:
855 return None
856 return None
857
858
859 def program(self, p):
860 if not p['pin_adm']:
861 raise ValueError("Please provide a PIN-ADM as there is no default one")
862 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
863
864 # select MF
865 r = self._scc.select_file(['3f00'])
866
867 # write EF.ICCID
868 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
869
870 r = self._scc.select_file(['7ff0'])
871
872 # set Ki in proprietary file
873 data, sw = self._scc.update_binary('FF02', p['ki'])
874
875 # set OPC in proprietary file
876 data, sw = self._scc.update_binary('FF01', p['opc'])
877
878 # select DF_GSM
879 r = self._scc.select_file(['7f20'])
880
881 # write EF.IMSI
882 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
883
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200884class WavemobileSim(Card):
885 """
886 WavemobileSim
887
888 """
889
890 name = 'Wavemobile-SIM'
891
892 def __init__(self, ssc):
893 super(WavemobileSim, self).__init__(ssc)
894 self._adm_chv_num = 0x0A
895 self._scc.cla_byte = "00"
896 self._scc.sel_ctrl = "0004" #request an FCP
897
898 @classmethod
899 def autodetect(kls, scc):
900 try:
901 # Look for ATR
902 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"):
903 return kls(scc)
904 except:
905 return None
906 return None
907
908 def program(self, p):
909 if not p['pin_adm']:
910 raise ValueError("Please provide a PIN-ADM as there is no default one")
911 sw = self.verify_adm(h2b(p['pin_adm']))
912 if sw != '9000':
913 raise RuntimeError('Failed to authenticate with ADM key %s'%(p['pin_adm'],))
914
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200915 # EF.ICCID
916 # TODO: Add programming of the ICCID
917 if p.get('iccid'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200918 print("Warning: Programming of the ICCID is not implemented for this type of card.")
919
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200920 # KI (Presumably a propritary file)
921 # TODO: Add programming of KI
922 if p.get('ki'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200923 print("Warning: Programming of the KI is not implemented for this type of card.")
924
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200925 # OPc (Presumably a propritary file)
926 # TODO: Add programming of OPc
927 if p.get('opc'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200928 print("Warning: Programming of the OPc is not implemented for this type of card.")
929
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200930 # EF.SMSP
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200931 if p.get('smsp'):
932 sw = self.update_smsp(p['smsp'])
933 if sw != '9000':
934 print("Programming SMSP failed with code %s"%sw)
935
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200936 # EF.IMSI
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200937 if p.get('imsi'):
938 sw = self.update_imsi(p['imsi'])
939 if sw != '9000':
940 print("Programming IMSI failed with code %s"%sw)
941
942 # EF.ACC
943 if p.get('acc'):
944 sw = self.update_acc(p['acc'])
945 if sw != '9000':
946 print("Programming ACC failed with code %s"%sw)
947
948 # EF.PLMNsel
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200949 if p.get('mcc') and p.get('mnc'):
950 sw = self.update_plmnsel(p['mcc'], p['mnc'])
951 if sw != '9000':
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200952 print("Programming PLMNsel failed with code %s"%sw)
953
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200954 # EF.PLMNwAcT
955 if p.get('mcc') and p.get('mnc'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200956 sw = self.update_plmn_act(p['mcc'], p['mnc'])
957 if sw != '9000':
958 print("Programming PLMNwAcT failed with code %s"%sw)
959
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200960 # EF.OPLMNwAcT
961 if p.get('mcc') and p.get('mnc'):
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200962 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
963 if sw != '9000':
964 print("Programming OPLMNwAcT failed with code %s"%sw)
965
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200966 # EF.AD
967 if p.get('mcc') and p.get('mnc'):
Philipp Maier6e507a72019-04-01 16:33:48 +0200968 sw = self.update_ad(p['mnc'])
969 if sw != '9000':
970 print("Programming AD failed with code %s"%sw)
971
Denis 'GNUtoo' Carikli84d2cb32019-09-12 01:46:25 +0200972 return None
Philipp Maierc8ce82a2018-07-04 17:57:20 +0200973
974 def erase(self):
975 return
976
Todd Neal9eeadfc2018-04-25 15:36:29 -0500977
Philipp Maier0ad5bcf2019-12-31 17:55:47 +0100978class SysmoISIMSJA2(Card):
979 """
980 sysmocom sysmoISIM-SJA2
981 """
982
983 name = 'sysmoISIM-SJA2'
984
985 def __init__(self, ssc):
986 super(SysmoISIMSJA2, self).__init__(ssc)
987 self._scc.cla_byte = "00"
988 self._scc.sel_ctrl = "0004" #request an FCP
989
990 @classmethod
991 def autodetect(kls, scc):
992 try:
993 # Try card model #1
994 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9"
995 if scc.get_atr() == toBytes(atr):
996 return kls(scc)
997
998 # Try card model #2
999 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2"
1000 if scc.get_atr() == toBytes(atr):
1001 return kls(scc)
Philipp Maierb3e11ea2020-03-11 12:32:44 +01001002
1003 # Try card model #3
1004 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"
1005 if scc.get_atr() == toBytes(atr):
1006 return kls(scc)
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001007 except:
1008 return None
1009 return None
1010
1011 def program(self, p):
1012 # authenticate as ADM using default key (written on the card..)
1013 if not p['pin_adm']:
1014 raise ValueError("Please provide a PIN-ADM as there is no default one")
1015 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
1016
1017 # This type of card does not allow to reprogram the ICCID.
1018 # Reprogramming the ICCID would mess up the card os software
1019 # license management, so the ICCID must be kept at its factory
1020 # setting!
1021 if p.get('iccid'):
1022 print("Warning: Programming of the ICCID is not implemented for this type of card.")
1023
1024 # select DF_GSM
1025 self._scc.select_file(['7f20'])
1026
1027 # write EF.IMSI
1028 if p.get('imsi'):
1029 self._scc.update_binary('6f07', enc_imsi(p['imsi']))
1030
1031 # EF.PLMNsel
1032 if p.get('mcc') and p.get('mnc'):
1033 sw = self.update_plmnsel(p['mcc'], p['mnc'])
1034 if sw != '9000':
1035 print("Programming PLMNsel failed with code %s"%sw)
1036
1037 # EF.PLMNwAcT
1038 if p.get('mcc') and p.get('mnc'):
1039 sw = self.update_plmn_act(p['mcc'], p['mnc'])
1040 if sw != '9000':
1041 print("Programming PLMNwAcT failed with code %s"%sw)
1042
1043 # EF.OPLMNwAcT
1044 if p.get('mcc') and p.get('mnc'):
1045 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
1046 if sw != '9000':
1047 print("Programming OPLMNwAcT failed with code %s"%sw)
1048
1049 # EF.AD
1050 if p.get('mcc') and p.get('mnc'):
1051 sw = self.update_ad(p['mnc'])
1052 if sw != '9000':
1053 print("Programming AD failed with code %s"%sw)
1054
1055 # EF.SMSP
1056 if p.get('smsp'):
1057 r = self._scc.select_file(['3f00', '7f10'])
1058 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 104), force_len=True)
1059
1060 # update EF-SIM_AUTH_KEY (and EF-USIM_AUTH_KEY_2G, which is
1061 # hard linked to EF-USIM_AUTH_KEY)
1062 self._scc.select_file(['3f00'])
1063 self._scc.select_file(['a515'])
1064 if p.get('ki'):
1065 self._scc.update_binary('6f20', p['ki'], 1)
1066 if p.get('opc'):
1067 self._scc.update_binary('6f20', p['opc'], 17)
1068
1069 # update EF-USIM_AUTH_KEY in ADF.ISIM
1070 self._scc.select_file(['3f00'])
1071 aid = self.read_aid(isim = True)
Philipp Maierd9507862020-03-11 12:18:29 +01001072 if (aid):
1073 self._scc.select_adf(aid)
1074 if p.get('ki'):
1075 self._scc.update_binary('af20', p['ki'], 1)
1076 if p.get('opc'):
1077 self._scc.update_binary('af20', p['opc'], 17)
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001078
1079 # update EF-USIM_AUTH_KEY in ADF.USIM
1080 self._scc.select_file(['3f00'])
1081 aid = self.read_aid()
Philipp Maierd9507862020-03-11 12:18:29 +01001082 if (aid):
1083 self._scc.select_adf(aid)
1084 if p.get('ki'):
1085 self._scc.update_binary('af20', p['ki'], 1)
1086 if p.get('opc'):
1087 self._scc.update_binary('af20', p['opc'], 17)
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001088
1089 return
1090
1091 def erase(self):
1092 return
1093
1094
Todd Neal9eeadfc2018-04-25 15:36:29 -05001095# In order for autodetection ...
Harald Weltee10394b2011-12-07 12:34:14 +01001096_cards_classes = [ FakeMagicSim, SuperSim, MagicSim, GrcardSim,
Alexander Chemerise0d9d882018-01-10 14:18:32 +09001097 SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1,
Philipp Maier0ad5bcf2019-12-31 17:55:47 +01001098 FairwavesSIM, OpenCellsSim, WavemobileSim, SysmoISIMSJA2 ]
Alexander Chemeris8ad124a2018-01-10 14:17:55 +09001099
1100def card_autodetect(scc):
1101 for kls in _cards_classes:
1102 card = kls.autodetect(scc)
1103 if card is not None:
1104 card.reset()
1105 return card
1106 return None