blob: 0c9c2b88250f8d9e01dcc04fca64441cd28d25ff [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
Sylvain Munaut76504e02010-12-07 00:24:32 +010035
Sylvain Munaut76504e02010-12-07 00:24:32 +010036 def reset(self):
37 self._scc.reset_card()
38
Alexander Chemeriseb6807d2017-07-18 17:04:38 +030039 def verify_adm(self, key):
40 '''
41 Authenticate with ADM key
42 '''
43 (res, sw) = self._scc.verify_chv(self._adm_chv_num, key)
44 return sw
45
46 def read_iccid(self):
47 (res, sw) = self._scc.read_binary(EF['ICCID'])
48 if sw == '9000':
49 return (dec_iccid(res), sw)
50 else:
51 return (None, sw)
52
53 def read_imsi(self):
54 (res, sw) = self._scc.read_binary(EF['IMSI'])
55 if sw == '9000':
56 return (dec_imsi(res), sw)
57 else:
58 return (None, sw)
59
60 def update_imsi(self, imsi):
61 data, sw = self._scc.update_binary(EF['IMSI'], enc_imsi(imsi))
62 return sw
63
64 def update_acc(self, acc):
65 data, sw = self._scc.update_binary(EF['ACC'], lpad(acc, 4))
66 return sw
67
68 def update_hplmn_act(self, mcc, mnc, access_tech='FFFF'):
69 """
70 Update Home PLMN with access technology bit-field
71
72 See Section "10.3.37 EFHPLMNwAcT (HPLMN Selector with Access Technology)"
73 in ETSI TS 151 011 for the details of the access_tech field coding.
74 Some common values:
75 access_tech = '0080' # Only GSM is selected
76 access_tech = 'FFFF' # All technologues selected, even Reserved for Future Use ones
77 """
78 # get size and write EF.HPLMNwAcT
79 r = self._scc.select_file(EF['HPLMNwAcT'])
80 size = int(r[-1][4:8], 16)
81 hplmn = enc_plmn(mcc, mnc)
82 content = hplmn + access_tech
83 data, sw = self._scc.update_binary(EF['HPLMNwAcT'], content + 'ffffff0000' * (size/5-1))
84 return sw
85
86 def update_smsp(self, smsp):
87 data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 84))
88 return sw
89
90 def read_spn(self):
91 (spn, sw) = self._scc.read_binary(EF['SPN'])
92 if sw == '9000':
93 return (dec_spn(spn), sw)
94 else:
95 return (None, sw)
96
97 def update_spn(self, name, hplmn_disp=False, oplmn_disp=False):
98 content = enc_spn(name, hplmn_disp, oplmn_disp)
99 data, sw = self._scc.update_binary(EF['SPN'], rpad(content, 32))
100 return sw
101
Sylvain Munaut76504e02010-12-07 00:24:32 +0100102
103class _MagicSimBase(Card):
104 """
105 Theses cards uses several record based EFs to store the provider infos,
106 each possible provider uses a specific record number in each EF. The
107 indexes used are ( where N is the number of providers supported ) :
108 - [2 .. N+1] for the operator name
109 - [1 .. N] for the programable EFs
110
111 * 3f00/7f4d/8f0c : Operator Name
112
113 bytes 0-15 : provider name, padded with 0xff
114 byte 16 : length of the provider name
115 byte 17 : 01 for valid records, 00 otherwise
116
117 * 3f00/7f4d/8f0d : Programmable Binary EFs
118
119 * 3f00/7f4d/8f0e : Programmable Record EFs
120
121 """
122
123 @classmethod
124 def autodetect(kls, scc):
125 try:
126 for p, l, t in kls._files.values():
127 if not t:
128 continue
129 if scc.record_size(['3f00', '7f4d', p]) != l:
130 return None
131 except:
132 return None
133
134 return kls(scc)
135
136 def _get_count(self):
137 """
138 Selects the file and returns the total number of entries
139 and entry size
140 """
141 f = self._files['name']
142
143 r = self._scc.select_file(['3f00', '7f4d', f[0]])
144 rec_len = int(r[-1][28:30], 16)
145 tlen = int(r[-1][4:8],16)
146 rec_cnt = (tlen / rec_len) - 1;
147
148 if (rec_cnt < 1) or (rec_len != f[1]):
149 raise RuntimeError('Bad card type')
150
151 return rec_cnt
152
153 def program(self, p):
154 # Go to dir
155 self._scc.select_file(['3f00', '7f4d'])
156
157 # Home PLMN in PLMN_Sel format
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400158 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100159
160 # Operator name ( 3f00/7f4d/8f0c )
161 self._scc.update_record(self._files['name'][0], 2,
162 rpad(b2h(p['name']), 32) + ('%02x' % len(p['name'])) + '01'
163 )
164
165 # ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
166 v = ''
167
168 # inline Ki
169 if self._ki_file is None:
170 v += p['ki']
171
172 # ICCID
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400173 v += '3f00' + '2fe2' + '0a' + enc_iccid(p['iccid'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100174
175 # IMSI
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400176 v += '7f20' + '6f07' + '09' + enc_imsi(p['imsi'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100177
178 # Ki
179 if self._ki_file:
180 v += self._ki_file + '10' + p['ki']
181
182 # PLMN_Sel
183 v+= '6f30' + '18' + rpad(hplmn, 36)
184
Alexander Chemeris21885242013-07-02 16:56:55 +0400185 # ACC
186 # This doesn't work with "fake" SuperSIM cards,
187 # but will hopefully work with real SuperSIMs.
188 if p.get('acc') is not None:
189 v+= '6f78' + '02' + lpad(p['acc'], 4)
190
Sylvain Munaut76504e02010-12-07 00:24:32 +0100191 self._scc.update_record(self._files['b_ef'][0], 1,
192 rpad(v, self._files['b_ef'][1]*2)
193 )
194
195 # SMSP ( 3f00/7f4d/8f0e )
196 # FIXME
197
198 # Write PLMN_Sel forcefully as well
199 r = self._scc.select_file(['3f00', '7f20', '6f30'])
200 tl = int(r[-1][4:8], 16)
201
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400202 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100203 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
204
205 def erase(self):
206 # Dummy
207 df = {}
208 for k, v in self._files.iteritems():
209 ofs = 1
210 fv = v[1] * 'ff'
211 if k == 'name':
212 ofs = 2
213 fv = fv[0:-4] + '0000'
214 df[v[0]] = (fv, ofs)
215
216 # Write
217 for n in range(0,self._get_count()):
218 for k, (msg, ofs) in df.iteritems():
219 self._scc.update_record(['3f00', '7f4d', k], n + ofs, msg)
220
221
222class SuperSim(_MagicSimBase):
223
224 name = 'supersim'
225
226 _files = {
227 'name' : ('8f0c', 18, True),
228 'b_ef' : ('8f0d', 74, True),
229 'r_ef' : ('8f0e', 50, True),
230 }
231
232 _ki_file = None
233
234
235class MagicSim(_MagicSimBase):
236
237 name = 'magicsim'
238
239 _files = {
240 'name' : ('8f0c', 18, True),
241 'b_ef' : ('8f0d', 130, True),
242 'r_ef' : ('8f0e', 102, False),
243 }
244
245 _ki_file = '6f1b'
246
247
248class FakeMagicSim(Card):
249 """
250 Theses cards have a record based EF 3f00/000c that contains the provider
251 informations. See the program method for its format. The records go from
252 1 to N.
253 """
254
255 name = 'fakemagicsim'
256
257 @classmethod
258 def autodetect(kls, scc):
259 try:
260 if scc.record_size(['3f00', '000c']) != 0x5a:
261 return None
262 except:
263 return None
264
265 return kls(scc)
266
267 def _get_infos(self):
268 """
269 Selects the file and returns the total number of entries
270 and entry size
271 """
272
273 r = self._scc.select_file(['3f00', '000c'])
274 rec_len = int(r[-1][28:30], 16)
275 tlen = int(r[-1][4:8],16)
276 rec_cnt = (tlen / rec_len) - 1;
277
278 if (rec_cnt < 1) or (rec_len != 0x5a):
279 raise RuntimeError('Bad card type')
280
281 return rec_cnt, rec_len
282
283 def program(self, p):
284 # Home PLMN
285 r = self._scc.select_file(['3f00', '7f20', '6f30'])
286 tl = int(r[-1][4:8], 16)
287
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400288 hplmn = enc_plmn(p['mcc'], p['mnc'])
Sylvain Munaut76504e02010-12-07 00:24:32 +0100289 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
290
291 # Get total number of entries and entry size
292 rec_cnt, rec_len = self._get_infos()
293
294 # Set first entry
295 entry = (
296 '81' + # 1b Status: Valid & Active
297 rpad(b2h(p['name'][0:14]), 28) + # 14b Entry Name
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400298 enc_iccid(p['iccid']) + # 10b ICCID
299 enc_imsi(p['imsi']) + # 9b IMSI_len + id_type(9) + IMSI
Sylvain Munaut76504e02010-12-07 00:24:32 +0100300 p['ki'] + # 16b Ki
Sylvain Munaut8ca49e92011-12-10 09:57:50 +0100301 lpad(p['smsp'], 80) # 40b SMSP (padded with ff if needed)
Sylvain Munaut76504e02010-12-07 00:24:32 +0100302 )
303 self._scc.update_record('000c', 1, entry)
304
305 def erase(self):
306 # Get total number of entries and entry size
307 rec_cnt, rec_len = self._get_infos()
308
309 # Erase all entries
310 entry = 'ff' * rec_len
311 for i in range(0, rec_cnt):
312 self._scc.update_record('000c', 1+i, entry)
313
Sylvain Munaut5da8d4e2013-07-02 15:13:24 +0200314
Harald Welte3156d902011-03-22 21:48:19 +0100315class GrcardSim(Card):
316 """
317 Greencard (grcard.cn) HZCOS GSM SIM
318 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
319 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
320 """
321
322 name = 'grcardsim'
323
324 @classmethod
325 def autodetect(kls, scc):
326 return None
327
328 def program(self, p):
329 # We don't really know yet what ADM PIN 4 is about
330 #self._scc.verify_chv(4, h2b("4444444444444444"))
331
332 # Authenticate using ADM PIN 5
Jan Balkec3ebd332015-01-26 12:22:55 +0100333 if p['pin_adm']:
334 pin = p['pin_adm']
335 else:
336 pin = h2b("4444444444444444")
337 self._scc.verify_chv(5, pin)
Harald Welte3156d902011-03-22 21:48:19 +0100338
339 # EF.ICCID
340 r = self._scc.select_file(['3f00', '2fe2'])
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400341 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
Harald Welte3156d902011-03-22 21:48:19 +0100342
343 # EF.IMSI
344 r = self._scc.select_file(['3f00', '7f20', '6f07'])
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400345 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
Harald Welte3156d902011-03-22 21:48:19 +0100346
347 # EF.ACC
Alexander Chemeris21885242013-07-02 16:56:55 +0400348 if p.get('acc') is not None:
349 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
Harald Welte3156d902011-03-22 21:48:19 +0100350
351 # EF.SMSP
352 r = self._scc.select_file(['3f00', '7f10', '6f42'])
Sylvain Munaut8ca49e92011-12-10 09:57:50 +0100353 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
Harald Welte3156d902011-03-22 21:48:19 +0100354
355 # Set the Ki using proprietary command
356 pdu = '80d4020010' + p['ki']
357 data, sw = self._scc._tp.send_apdu(pdu)
358
359 # EF.HPLMN
360 r = self._scc.select_file(['3f00', '7f20', '6f30'])
361 size = int(r[-1][4:8], 16)
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400362 hplmn = enc_plmn(p['mcc'], p['mnc'])
Harald Welte3156d902011-03-22 21:48:19 +0100363 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
364
365 # EF.SPN (Service Provider Name)
366 r = self._scc.select_file(['3f00', '7f20', '6f30'])
367 size = int(r[-1][4:8], 16)
368 # FIXME
369
370 # FIXME: EF.MSISDN
371
372 def erase(self):
373 return
Sylvain Munaut76504e02010-12-07 00:24:32 +0100374
Harald Weltee10394b2011-12-07 12:34:14 +0100375class SysmoSIMgr1(GrcardSim):
376 """
377 sysmocom sysmoSIM-GR1
378 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
379 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
380 """
381 name = 'sysmosim-gr1'
382
Sylvain Munaut5da8d4e2013-07-02 15:13:24 +0200383
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100384class SysmoUSIMgr1(Card):
385 """
386 sysmocom sysmoUSIM-GR1
387 """
388 name = 'sysmoUSIM-GR1'
389
390 @classmethod
391 def autodetect(kls, scc):
392 # TODO: Access the ATR
393 return None
394
395 def program(self, p):
396 # TODO: check if verify_chv could be used or what it needs
397 # self._scc.verify_chv(0x0A, [0x33,0x32,0x32,0x31,0x33,0x32,0x33,0x32])
398 # Unlock the card..
399 data, sw = self._scc._tp.send_apdu_checksw("0020000A083332323133323332")
400
401 # TODO: move into SimCardCommands
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100402 par = ( p['ki'] + # 16b K
Alexander Chemeris7be92ff2013-07-10 11:18:06 +0400403 p['opc'] + # 32b OPC
404 enc_iccid(p['iccid']) + # 10b ICCID
405 enc_imsi(p['imsi']) # 9b IMSI_len + id_type(9) + IMSI
Holger Hans Peter Freyther4d91bf42012-03-22 14:28:38 +0100406 )
407 data, sw = self._scc._tp.send_apdu_checksw("0099000033" + par)
408
409 def erase(self):
410 return
411
Sylvain Munaut053c8952013-07-02 15:12:32 +0200412
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100413class SysmoSIMgr2(Card):
414 """
415 sysmocom sysmoSIM-GR2
416 """
417
418 name = 'sysmoSIM-GR2'
419
420 @classmethod
421 def autodetect(kls, scc):
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900422 try:
423 # Look for ATR
424 if scc.get_atr() == toBytes("3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68"):
425 return kls(scc)
426 except:
427 return None
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100428 return None
429
430 def program(self, p):
431
432 # select MF
433 r = self._scc.select_file(['3f00'])
434
435 # authenticate as SUPER ADM using default key
436 self._scc.verify_chv(0x0b, h2b("3838383838383838"))
437
438 # set ADM pin using proprietary command
439 # INS: D4
440 # P1: 3A for PIN, 3B for PUK
441 # P2: CHV number, as in VERIFY CHV for PIN, and as in UNBLOCK CHV for PUK
442 # P3: 08, CHV length (curiously the PUK is also 08 length, instead of 10)
Jan Balkec3ebd332015-01-26 12:22:55 +0100443 if p['pin_adm']:
444 pin = p['pin_adm']
445 else:
446 pin = h2b("4444444444444444")
447
448 pdu = 'A0D43A0508' + b2h(pin)
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100449 data, sw = self._scc._tp.send_apdu(pdu)
450
451 # authenticate as ADM (enough to write file, and can set PINs)
Jan Balkec3ebd332015-01-26 12:22:55 +0100452
453 self._scc.verify_chv(0x05, pin)
Sylvain Munaut2fc205c2013-12-23 17:22:56 +0100454
455 # write EF.ICCID
456 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
457
458 # select DF_GSM
459 r = self._scc.select_file(['7f20'])
460
461 # write EF.IMSI
462 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
463
464 # write EF.ACC
465 if p.get('acc') is not None:
466 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
467
468 # get size and write EF.HPLMN
469 r = self._scc.select_file(['6f30'])
470 size = int(r[-1][4:8], 16)
471 hplmn = enc_plmn(p['mcc'], p['mnc'])
472 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
473
474 # set COMP128 version 0 in proprietary file
475 data, sw = self._scc.update_binary('0001', '001000')
476
477 # set Ki in proprietary file
478 data, sw = self._scc.update_binary('0001', p['ki'], 3)
479
480 # select DF_TELECOM
481 r = self._scc.select_file(['3f00', '7f10'])
482
483 # write EF.SMSP
484 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
485
486 def erase(self):
487 return
488
Jan Balke3e840672015-01-26 15:36:27 +0100489class SysmoUSIMSJS1(Card):
490 """
491 sysmocom sysmoUSIM-SJS1
492 """
493
494 name = 'sysmoUSIM-SJS1'
495
496 def __init__(self, ssc):
497 super(SysmoUSIMSJS1, self).__init__(ssc)
498 self._scc.cla_byte = "00"
Philipp Maier41460862017-03-21 12:05:30 +0100499 self._scc.sel_ctrl = "000C"
Jan Balke3e840672015-01-26 15:36:27 +0100500
501 @classmethod
502 def autodetect(kls, scc):
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900503 try:
504 # Look for ATR
505 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"):
506 return kls(scc)
507 except:
508 return None
Jan Balke3e840672015-01-26 15:36:27 +0100509 return None
510
511 def program(self, p):
512
Philipp Maiere9604882017-03-21 17:24:31 +0100513 # authenticate as ADM using default key (written on the card..)
514 if not p['pin_adm']:
515 raise ValueError("Please provide a PIN-ADM as there is no default one")
516 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
Jan Balke3e840672015-01-26 15:36:27 +0100517
518 # select MF
519 r = self._scc.select_file(['3f00'])
520
Philipp Maiere9604882017-03-21 17:24:31 +0100521 # write EF.ICCID
522 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
523
Jan Balke3e840672015-01-26 15:36:27 +0100524 # select DF_GSM
525 r = self._scc.select_file(['7f20'])
526
Jan Balke3e840672015-01-26 15:36:27 +0100527 # set Ki in proprietary file
528 data, sw = self._scc.update_binary('00FF', p['ki'])
529
530 # set Ki in proprietary file
531 content = "01" + p['opc']
532 data, sw = self._scc.update_binary('00F7', content)
533
534
535 # write EF.IMSI
536 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
537
Daniel Willmann1d087ef2017-08-31 10:08:45 +0200538 # EF.SMSP
539 r = self._scc.select_file(['3f00', '7f10'])
540 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 104), force_len=True)
Jan Balke3e840672015-01-26 15:36:27 +0100541
Alexander Chemerise0d9d882018-01-10 14:18:32 +0900542 def erase(self):
543 return
544
545
546class FairwavesSIM(Card):
547 """
548 FairwavesSIM
549
550 The SIM card is operating according to the standard.
551 For Ki/OP/OPC programming the following files are additionally open for writing:
552 3F00/7F20/FF01 – OP/OPC:
553 byte 1 = 0x01, bytes 2-17: OPC;
554 byte 1 = 0x00, bytes 2-17: OP;
555 3F00/7F20/FF02: Ki
556 """
557
558 name = 'Fairwaves SIM'
559 # Propriatary files
560 _EF_num = {
561 'Ki': 'FF02',
562 'OP/OPC': 'FF01',
563 }
564 _EF = {
565 'Ki': DF['GSM']+[_EF_num['Ki']],
566 'OP/OPC': DF['GSM']+[_EF_num['OP/OPC']],
567 }
568
569 def __init__(self, ssc):
570 super(FairwavesSIM, self).__init__(ssc)
571 self._adm_chv_num = 0x11
572 self._adm2_chv_num = 0x12
573
574
575 @classmethod
576 def autodetect(kls, scc):
577 try:
578 # Look for ATR
579 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"):
580 return kls(scc)
581 except:
582 return None
583 return None
584
585
586 def verify_adm2(self, key):
587 '''
588 Authenticate with ADM2 key.
589
590 Fairwaves SIM cards support hierarchical key structure and ADM2 key
591 is a key which has access to proprietary files (Ki and OP/OPC).
592 That said, ADM key inherits permissions of ADM2 key and thus we rarely
593 need ADM2 key per se.
594 '''
595 (res, sw) = self._scc.verify_chv(self._adm2_chv_num, key)
596 return sw
597
598
599 def read_ki(self):
600 """
601 Read Ki in proprietary file.
602
603 Requires ADM1 access level
604 """
605 return self._scc.read_binary(self._EF['Ki'])
606
607
608 def update_ki(self, ki):
609 """
610 Set Ki in proprietary file.
611
612 Requires ADM1 access level
613 """
614 data, sw = self._scc.update_binary(self._EF['Ki'], ki)
615 return sw
616
617
618 def read_op_opc(self):
619 """
620 Read Ki in proprietary file.
621
622 Requires ADM1 access level
623 """
624 (ef, sw) = self._scc.read_binary(self._EF['OP/OPC'])
625 type = 'OP' if ef[0:2] == '00' else 'OPC'
626 return ((type, ef[2:]), sw)
627
628
629 def update_op(self, op):
630 """
631 Set OP in proprietary file.
632
633 Requires ADM1 access level
634 """
635 content = '00' + op
636 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
637 return sw
638
639
640 def update_opc(self, opc):
641 """
642 Set OPC in proprietary file.
643
644 Requires ADM1 access level
645 """
646 content = '01' + opc
647 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
648 return sw
649
650
651 def program(self, p):
652 # authenticate as ADM1
653 if not p['pin_adm']:
654 raise ValueError("Please provide a PIN-ADM as there is no default one")
655 sw = self.verify_adm(h2b(p['pin_adm']))
656 if sw != '9000':
657 raise RuntimeError('Failed to authenticate with ADM key %s'%(p['pin_adm'],))
658
659 # TODO: Set operator name
660 if p.get('smsp') is not None:
661 sw = self.update_smsp(p['smsp'])
662 if sw != '9000':
663 print("Programming SMSP failed with code %s"%sw)
664 # This SIM doesn't support changing ICCID
665 if p.get('mcc') is not None and p.get('mnc') is not None:
666 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
667 if sw != '9000':
668 print("Programming MCC/MNC failed with code %s"%sw)
669 if p.get('imsi') is not None:
670 sw = self.update_imsi(p['imsi'])
671 if sw != '9000':
672 print("Programming IMSI failed with code %s"%sw)
673 if p.get('ki') is not None:
674 sw = self.update_ki(p['ki'])
675 if sw != '9000':
676 print("Programming Ki failed with code %s"%sw)
677 if p.get('opc') is not None:
678 sw = self.update_opc(p['opc'])
679 if sw != '9000':
680 print("Programming OPC failed with code %s"%sw)
681 if p.get('acc') is not None:
682 sw = self.update_acc(p['acc'])
683 if sw != '9000':
684 print("Programming ACC failed with code %s"%sw)
Jan Balke3e840672015-01-26 15:36:27 +0100685
686 def erase(self):
687 return
688
689
Todd Neal9eeadfc2018-04-25 15:36:29 -0500690class OpenCellsSim(Card):
691 """
692 OpenCellsSim
693
694 """
695
696 name = 'OpenCells SIM'
697
698 def __init__(self, ssc):
699 super(OpenCellsSim, self).__init__(ssc)
700 self._adm_chv_num = 0x0A
701
702
703 @classmethod
704 def autodetect(kls, scc):
705 try:
706 # Look for ATR
707 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"):
708 return kls(scc)
709 except:
710 return None
711 return None
712
713
714 def program(self, p):
715 if not p['pin_adm']:
716 raise ValueError("Please provide a PIN-ADM as there is no default one")
717 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
718
719 # select MF
720 r = self._scc.select_file(['3f00'])
721
722 # write EF.ICCID
723 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
724
725 r = self._scc.select_file(['7ff0'])
726
727 # set Ki in proprietary file
728 data, sw = self._scc.update_binary('FF02', p['ki'])
729
730 # set OPC in proprietary file
731 data, sw = self._scc.update_binary('FF01', p['opc'])
732
733 # select DF_GSM
734 r = self._scc.select_file(['7f20'])
735
736 # write EF.IMSI
737 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
738
739
740# In order for autodetection ...
Harald Weltee10394b2011-12-07 12:34:14 +0100741_cards_classes = [ FakeMagicSim, SuperSim, MagicSim, GrcardSim,
Alexander Chemerise0d9d882018-01-10 14:18:32 +0900742 SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1,
Todd Neal9eeadfc2018-04-25 15:36:29 -0500743 FairwavesSIM, OpenCellsSim ]
Alexander Chemeris8ad124a2018-01-10 14:17:55 +0900744
745def card_autodetect(scc):
746 for kls in _cards_classes:
747 card = kls.autodetect(scc)
748 if card is not None:
749 card.reset()
750 return card
751 return None