blob: e63b044694bbc510f885bdaed18fafbb26764ad2 [file] [log] [blame]
Harald Weltef8d2e2b2023-07-09 17:58:38 +02001################################################################################
2# LEGACY
3################################################################################
4
5import abc
6from smartcard.util import toBytes
7from pytlv.TLV import *
8
9from pySim.cards import SimCardBase, UiccCardBase
10from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_msisdn, enc_msisdn
11from pySim.utils import dec_addr_tlv, enc_addr_tlv
12from pySim.utils import enc_plmn, get_addr_type
13from pySim.utils import is_hex, h2b, b2h, h2s, s2h, lpad, rpad
14from pySim.legacy.utils import enc_ePDGSelection, format_xplmn_w_act, format_xplmn, dec_st, enc_st
15from pySim.legacy.utils import format_ePDGSelection
16
17from pySim.ts_51_011 import EF, DF, EF_AD, EF_SPN
18from pySim.ts_31_102 import EF_USIM_ADF_map
19from pySim.ts_31_103 import EF_ISIM_ADF_map
20
21def format_addr(addr: str, addr_type: str) -> str:
22 """
23 helper function to format an FQDN (addr_type = '00') or IPv4
24 (addr_type = '01') address string into a printable string that
25 contains the hexadecimal representation and the original address
26 string (addr)
27 """
28 res = ""
29 if addr_type == '00': # FQDN
30 res += "\t%s # %s\n" % (s2h(addr), addr)
31 elif addr_type == '01': # IPv4
32 octets = addr.split(".")
33 addr_hex = ""
34 for o in octets:
35 addr_hex += ("%02x" % int(o))
36 res += "\t%s # %s\n" % (addr_hex, addr)
37 return res
38
39
40
41class SimCard(SimCardBase):
42 """Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
43
44 def __init__(self, scc):
45 self._adm_chv_num = 4
46 super().__init__(scc)
47
48 def read_binary(self, ef, length=None, offset=0):
49 ef_path = ef in EF and EF[ef] or ef
50 return self._scc.read_binary(ef_path, length, offset)
51
52 def read_record(self, ef, rec_no):
53 ef_path = ef in EF and EF[ef] or ef
54 return self._scc.read_record(ef_path, rec_no)
55
56 def verify_adm(self, key):
57 """Authenticate with ADM key"""
58 (res, sw) = self._scc.verify_chv(self._adm_chv_num, key)
59 return sw
60
61 def update_iccid(self, iccid):
62 data, sw = self._scc.update_binary(EF['ICCID'], enc_iccid(iccid))
63 return sw
64
65 def read_imsi(self):
66 (res, sw) = self._scc.read_binary(EF['IMSI'])
67 if sw == '9000':
68 return (dec_imsi(res), sw)
69 else:
70 return (None, sw)
71
72 def update_imsi(self, imsi):
73 data, sw = self._scc.update_binary(EF['IMSI'], enc_imsi(imsi))
74 return sw
75
76 def update_acc(self, acc):
77 data, sw = self._scc.update_binary(EF['ACC'], lpad(acc, 4, c='0'))
78 return sw
79
80 def read_hplmn_act(self):
81 (res, sw) = self._scc.read_binary(EF['HPLMNAcT'])
82 if sw == '9000':
83 return (format_xplmn_w_act(res), sw)
84 else:
85 return (None, sw)
86
87 def update_hplmn_act(self, mcc, mnc, access_tech='FFFF'):
88 """
89 Update Home PLMN with access technology bit-field
90
91 See Section "10.3.37 EFHPLMNwAcT (HPLMN Selector with Access Technology)"
92 in ETSI TS 151 011 for the details of the access_tech field coding.
93 Some common values:
94 access_tech = '0080' # Only GSM is selected
95 access_tech = 'FFFF' # All technologies selected, even Reserved for Future Use ones
96 """
97 # get size and write EF.HPLMNwAcT
98 data = self._scc.read_binary(EF['HPLMNwAcT'], length=None, offset=0)
99 size = len(data[0]) // 2
100 hplmn = enc_plmn(mcc, mnc)
101 content = hplmn + access_tech
102 data, sw = self._scc.update_binary(
103 EF['HPLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
104 return sw
105
106 def read_oplmn_act(self):
107 (res, sw) = self._scc.read_binary(EF['OPLMNwAcT'])
108 if sw == '9000':
109 return (format_xplmn_w_act(res), sw)
110 else:
111 return (None, sw)
112
113 def update_oplmn_act(self, mcc, mnc, access_tech='FFFF'):
114 """get size and write EF.OPLMNwAcT, See note in update_hplmn_act()"""
115 data = self._scc.read_binary(EF['OPLMNwAcT'], length=None, offset=0)
116 size = len(data[0]) // 2
117 hplmn = enc_plmn(mcc, mnc)
118 content = hplmn + access_tech
119 data, sw = self._scc.update_binary(
120 EF['OPLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
121 return sw
122
123 def read_plmn_act(self):
124 (res, sw) = self._scc.read_binary(EF['PLMNwAcT'])
125 if sw == '9000':
126 return (format_xplmn_w_act(res), sw)
127 else:
128 return (None, sw)
129
130 def update_plmn_act(self, mcc, mnc, access_tech='FFFF'):
131 """get size and write EF.PLMNwAcT, See note in update_hplmn_act()"""
132 data = self._scc.read_binary(EF['PLMNwAcT'], length=None, offset=0)
133 size = len(data[0]) // 2
134 hplmn = enc_plmn(mcc, mnc)
135 content = hplmn + access_tech
136 data, sw = self._scc.update_binary(
137 EF['PLMNwAcT'], content + 'ffffff0000' * (size // 5 - 1))
138 return sw
139
140 def update_plmnsel(self, mcc, mnc):
141 data = self._scc.read_binary(EF['PLMNsel'], length=None, offset=0)
142 size = len(data[0]) // 2
143 hplmn = enc_plmn(mcc, mnc)
144 data, sw = self._scc.update_binary(
145 EF['PLMNsel'], hplmn + 'ff' * (size-3))
146 return sw
147
148 def update_smsp(self, smsp):
149 data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 84))
150 return sw
151
152 def update_ad(self, mnc=None, opmode=None, ofm=None, path=EF['AD']):
153 """
154 Update Administrative Data (AD)
155
156 See Sec. "4.2.18 EF_AD (Administrative Data)"
157 in 3GPP TS 31.102 for the details of the EF_AD contents.
158
159 Set any parameter to None to keep old value(s) on card.
160
161 Parameters:
162 mnc (str): MNC of IMSI
163 opmode (Hex-str, 1 Byte): MS Operation Mode
164 ofm (Hex-str, 1 Byte): Operational Feature Monitor (OFM) aka Ciphering Indicator
165 path (optional list with file path e.g. ['3f00', '7f20', '6fad'])
166
167 Returns:
168 str: Return code of write operation
169 """
170
171 ad = EF_AD()
172
173 # read from card
174 raw_hex_data, sw = self._scc.read_binary(
175 path, length=None, offset=0)
176 abstract_data = ad.decode_hex(raw_hex_data)
177
178 # perform updates
179 if mnc and abstract_data['extensions']:
180 # Note: Since we derive the length of the MNC by the string length
181 # of the mnc parameter, the caller must ensure that mnc has the
182 # correct length and is padded with zeros (if necessary).
183 mnclen = len(str(mnc))
184 if mnclen > 3 or mnclen < 2:
185 raise RuntimeError('invalid length of mnc "{}", expecting 2 or 3 digits'.format(mnc))
186 abstract_data['extensions']['mnc_len'] = mnclen
187 if opmode:
188 opmode_num = int(opmode, 16)
189 if opmode_num in [int(v) for v in EF_AD.OP_MODE]:
190 abstract_data['ms_operation_mode'] = opmode_num
191 else:
192 raise RuntimeError('invalid opmode "{}"'.format(opmode))
193 if ofm:
194 abstract_data['ofm'] = bool(int(ofm, 16))
195
196 # write to card
197 raw_hex_data = ad.encode_hex(abstract_data)
198 data, sw = self._scc.update_binary(path, raw_hex_data)
199 return sw
200
201 def read_spn(self):
202 (content, sw) = self._scc.read_binary(EF['SPN'])
203 if sw == '9000':
204 abstract_data = EF_SPN().decode_hex(content)
205 show_in_hplmn = abstract_data['show_in_hplmn']
206 hide_in_oplmn = abstract_data['hide_in_oplmn']
207 name = abstract_data['spn']
208 return ((name, show_in_hplmn, hide_in_oplmn), sw)
209 else:
210 return (None, sw)
211
212 def update_spn(self, name="", show_in_hplmn=False, hide_in_oplmn=False):
213 abstract_data = {
214 'hide_in_oplmn': hide_in_oplmn,
215 'show_in_hplmn': show_in_hplmn,
216 'spn': name,
217 }
218 content = EF_SPN().encode_hex(abstract_data)
219 data, sw = self._scc.update_binary(EF['SPN'], content)
220 return sw
221
222 def read_gid1(self):
223 (res, sw) = self._scc.read_binary(EF['GID1'])
224 if sw == '9000':
225 return (res, sw)
226 else:
227 return (None, sw)
228
229 def read_msisdn(self):
230 (res, sw) = self._scc.read_record(EF['MSISDN'], 1)
231 if sw == '9000':
232 return (dec_msisdn(res), sw)
233 else:
234 return (None, sw)
235
236
237class UsimCard(UiccCardBase, SimCard):
238 """Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
239
240 def read_ehplmn(self):
241 (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'])
242 if sw == '9000':
243 return (format_xplmn(res), sw)
244 else:
245 return (None, sw)
246
247 def update_ehplmn(self, mcc, mnc):
248 data = self._scc.read_binary(
249 EF_USIM_ADF_map['EHPLMN'], length=None, offset=0)
250 size = len(data[0]) // 2
251 ehplmn = enc_plmn(mcc, mnc)
252 data, sw = self._scc.update_binary(EF_USIM_ADF_map['EHPLMN'], ehplmn)
253 return sw
254
255 def read_fplmn(self):
256 res, sw = self._scc.read_binary(EF_USIM_ADF_map['FPLMN'])
257 if sw == '9000':
258 return format_xplmn(res), sw
259 else:
260 return None, sw
261
262 def update_fplmn(self, fplmn):
263 self._scc.select_file('3f00')
264 self.select_adf_by_aid('USIM')
265 size = self._scc.binary_size(EF_USIM_ADF_map['FPLMN'])
266 encoded = ''.join([enc_plmn(plmn[:3], plmn[3:]) for plmn in fplmn])
267 encoded = rpad(encoded, size)
268 data, sw = self._scc.update_binary(EF_USIM_ADF_map['FPLMN'], encoded)
269 return sw
270
271 def read_epdgid(self):
272 (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['ePDGId'])
273 if sw == '9000':
274 try:
275 addr, addr_type = dec_addr_tlv(res)
276 except:
277 addr = None
278 addr_type = None
279 return (format_addr(addr, addr_type), sw)
280 else:
281 return (None, sw)
282
283 def update_epdgid(self, epdgid):
284 size = self._scc.binary_size(EF_USIM_ADF_map['ePDGId']) * 2
285 if len(epdgid) > 0:
286 addr_type = get_addr_type(epdgid)
287 if addr_type == None:
288 raise ValueError(
289 "Unknown ePDG Id address type or invalid address provided")
290 epdgid_tlv = rpad(enc_addr_tlv(epdgid, ('%02x' % addr_type)), size)
291 else:
292 epdgid_tlv = rpad('ff', size)
293 data, sw = self._scc.update_binary(
294 EF_USIM_ADF_map['ePDGId'], epdgid_tlv)
295 return sw
296
297 def read_ePDGSelection(self):
298 (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['ePDGSelection'])
299 if sw == '9000':
300 return (format_ePDGSelection(res), sw)
301 else:
302 return (None, sw)
303
304 def update_ePDGSelection(self, mcc, mnc):
305 (res, sw) = self._scc.read_binary(
306 EF_USIM_ADF_map['ePDGSelection'], length=None, offset=0)
307 if sw == '9000' and (len(mcc) == 0 or len(mnc) == 0):
308 # Reset contents
309 # 80 - Tag value
310 (res, sw) = self._scc.update_binary(
311 EF_USIM_ADF_map['ePDGSelection'], rpad('', len(res)))
312 elif sw == '9000':
313 (res, sw) = self._scc.update_binary(
314 EF_USIM_ADF_map['ePDGSelection'], enc_ePDGSelection(res, mcc, mnc))
315 return sw
316
317 def read_ust(self):
318 (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['UST'])
319 if sw == '9000':
320 # Print those which are available
321 return ([res, dec_st(res, table="usim")], sw)
322 else:
323 return ([None, None], sw)
324
325 def update_ust(self, service, bit=1):
326 (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['UST'])
327 if sw == '9000':
328 content = enc_st(res, service, bit)
329 (res, sw) = self._scc.update_binary(
330 EF_USIM_ADF_map['UST'], content)
331 return sw
332
333 def update_est(self, service, bit=1):
334 (res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EST'])
335 if sw == '9000':
336 content = enc_st(res, service, bit)
337 (res, sw) = self._scc.update_binary(
338 EF_USIM_ADF_map['EST'], content)
339 return sw
340
341
342
343class IsimCard(UiccCardBase):
344 """Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
345
346 name = 'ISIM'
347
348 def read_pcscf(self):
349 rec_cnt = self._scc.record_count(EF_ISIM_ADF_map['PCSCF'])
350 pcscf_recs = ""
351 for i in range(0, rec_cnt):
352 (res, sw) = self._scc.read_record(EF_ISIM_ADF_map['PCSCF'], i + 1)
353 if sw == '9000':
354 try:
355 addr, addr_type = dec_addr_tlv(res)
356 except:
357 addr = None
358 addr_type = None
359 content = format_addr(addr, addr_type)
360 pcscf_recs += "%s" % (len(content)
361 and content or '\tNot available\n')
362 else:
363 pcscf_recs += "\tP-CSCF: Can't read, response code = %s\n" % (
364 sw)
365 return pcscf_recs
366
367 def update_pcscf(self, pcscf):
368 if len(pcscf) > 0:
369 addr_type = get_addr_type(pcscf)
370 if addr_type == None:
371 raise ValueError(
372 "Unknown PCSCF address type or invalid address provided")
373 content = enc_addr_tlv(pcscf, ('%02x' % addr_type))
374 else:
375 # Just the tag value
376 content = '80'
377 rec_size_bytes = self._scc.record_size(EF_ISIM_ADF_map['PCSCF'])
378 pcscf_tlv = rpad(content, rec_size_bytes*2)
379 data, sw = self._scc.update_record(
380 EF_ISIM_ADF_map['PCSCF'], 1, pcscf_tlv)
381 return sw
382
383 def read_domain(self):
384 (res, sw) = self._scc.read_binary(EF_ISIM_ADF_map['DOMAIN'])
385 if sw == '9000':
386 # Skip the initial tag value ('80') byte and get length of contents
387 length = int(res[2:4], 16)
388 content = h2s(res[4:4+(length*2)])
389 return (content, sw)
390 else:
391 return (None, sw)
392
393 def update_domain(self, domain=None, mcc=None, mnc=None):
394 hex_str = ""
395 if domain:
396 hex_str = s2h(domain)
397 elif mcc and mnc:
398 # MCC and MNC always has 3 digits in domain form
399 plmn_str = 'mnc' + lpad(mnc, 3, "0") + '.mcc' + lpad(mcc, 3, "0")
400 hex_str = s2h('ims.' + plmn_str + '.3gppnetwork.org')
401
402 # Build TLV
403 tlv = TLV(['80'])
404 content = tlv.build({'80': hex_str})
405
406 bin_size_bytes = self._scc.binary_size(EF_ISIM_ADF_map['DOMAIN'])
407 data, sw = self._scc.update_binary(
408 EF_ISIM_ADF_map['DOMAIN'], rpad(content, bin_size_bytes*2))
409 return sw
410
411 def read_impi(self):
412 (res, sw) = self._scc.read_binary(EF_ISIM_ADF_map['IMPI'])
413 if sw == '9000':
414 # Skip the initial tag value ('80') byte and get length of contents
415 length = int(res[2:4], 16)
416 content = h2s(res[4:4+(length*2)])
417 return (content, sw)
418 else:
419 return (None, sw)
420
421 def update_impi(self, impi=None):
422 hex_str = ""
423 if impi:
424 hex_str = s2h(impi)
425 # Build TLV
426 tlv = TLV(['80'])
427 content = tlv.build({'80': hex_str})
428
429 bin_size_bytes = self._scc.binary_size(EF_ISIM_ADF_map['IMPI'])
430 data, sw = self._scc.update_binary(
431 EF_ISIM_ADF_map['IMPI'], rpad(content, bin_size_bytes*2))
432 return sw
433
434 def read_impu(self):
435 rec_cnt = self._scc.record_count(EF_ISIM_ADF_map['IMPU'])
436 impu_recs = ""
437 for i in range(0, rec_cnt):
438 (res, sw) = self._scc.read_record(EF_ISIM_ADF_map['IMPU'], i + 1)
439 if sw == '9000':
440 # Skip the initial tag value ('80') byte and get length of contents
441 length = int(res[2:4], 16)
442 content = h2s(res[4:4+(length*2)])
443 impu_recs += "\t%s\n" % (len(content)
444 and content or 'Not available')
445 else:
446 impu_recs += "IMS public user identity: Can't read, response code = %s\n" % (
447 sw)
448 return impu_recs
449
450 def update_impu(self, impu=None):
451 hex_str = ""
452 if impu:
453 hex_str = s2h(impu)
454 # Build TLV
455 tlv = TLV(['80'])
456 content = tlv.build({'80': hex_str})
457
458 rec_size_bytes = self._scc.record_size(EF_ISIM_ADF_map['IMPU'])
459 impu_tlv = rpad(content, rec_size_bytes*2)
460 data, sw = self._scc.update_record(
461 EF_ISIM_ADF_map['IMPU'], 1, impu_tlv)
462 return sw
463
464 def read_iari(self):
465 rec_cnt = self._scc.record_count(EF_ISIM_ADF_map['UICCIARI'])
466 uiari_recs = ""
467 for i in range(0, rec_cnt):
468 (res, sw) = self._scc.read_record(
469 EF_ISIM_ADF_map['UICCIARI'], i + 1)
470 if sw == '9000':
471 # Skip the initial tag value ('80') byte and get length of contents
472 length = int(res[2:4], 16)
473 content = h2s(res[4:4+(length*2)])
474 uiari_recs += "\t%s\n" % (len(content)
475 and content or 'Not available')
476 else:
477 uiari_recs += "UICC IARI: Can't read, response code = %s\n" % (
478 sw)
479 return uiari_recs
480
481 def update_ist(self, service, bit=1):
482 (res, sw) = self._scc.read_binary(EF_ISIM_ADF_map['IST'])
483 if sw == '9000':
484 content = enc_st(res, service, bit)
485 (res, sw) = self._scc.update_binary(
486 EF_ISIM_ADF_map['IST'], content)
487 return sw
488
489
490class MagicSimBase(abc.ABC, SimCard):
491 """
492 Theses cards uses several record based EFs to store the provider infos,
493 each possible provider uses a specific record number in each EF. The
494 indexes used are ( where N is the number of providers supported ) :
495 - [2 .. N+1] for the operator name
496 - [1 .. N] for the programmable EFs
497
498 * 3f00/7f4d/8f0c : Operator Name
499
500 bytes 0-15 : provider name, padded with 0xff
501 byte 16 : length of the provider name
502 byte 17 : 01 for valid records, 00 otherwise
503
504 * 3f00/7f4d/8f0d : Programmable Binary EFs
505
506 * 3f00/7f4d/8f0e : Programmable Record EFs
507
508 """
509
510 _files = {} # type: Dict[str, Tuple[str, int, bool]]
511 _ki_file = None # type: Optional[str]
512
513 @classmethod
514 def autodetect(kls, scc):
515 try:
516 for p, l, t in kls._files.values():
517 if not t:
518 continue
519 if scc.record_size(['3f00', '7f4d', p]) != l:
520 return None
521 except:
522 return None
523
524 return kls(scc)
525
526 def _get_count(self):
527 """
528 Selects the file and returns the total number of entries
529 and entry size
530 """
531 f = self._files['name']
532
533 r = self._scc.select_path(['3f00', '7f4d', f[0]])
534 rec_len = int(r[-1][28:30], 16)
535 tlen = int(r[-1][4:8], 16)
536 rec_cnt = (tlen // rec_len) - 1
537
538 if (rec_cnt < 1) or (rec_len != f[1]):
539 raise RuntimeError('Bad card type')
540
541 return rec_cnt
542
543 def program(self, p):
544 # Go to dir
545 self._scc.select_path(['3f00', '7f4d'])
546
547 # Home PLMN in PLMN_Sel format
548 hplmn = enc_plmn(p['mcc'], p['mnc'])
549
550 # Operator name ( 3f00/7f4d/8f0c )
551 self._scc.update_record(self._files['name'][0], 2,
552 rpad(b2h(p['name']), 32) + ('%02x' %
553 len(p['name'])) + '01'
554 )
555
556 # ICCID/IMSI/Ki/HPLMN ( 3f00/7f4d/8f0d )
557 v = ''
558
559 # inline Ki
560 if self._ki_file is None:
561 v += p['ki']
562
563 # ICCID
564 v += '3f00' + '2fe2' + '0a' + enc_iccid(p['iccid'])
565
566 # IMSI
567 v += '7f20' + '6f07' + '09' + enc_imsi(p['imsi'])
568
569 # Ki
570 if self._ki_file:
571 v += self._ki_file + '10' + p['ki']
572
573 # PLMN_Sel
574 v += '6f30' + '18' + rpad(hplmn, 36)
575
576 # ACC
577 # This doesn't work with "fake" SuperSIM cards,
578 # but will hopefully work with real SuperSIMs.
579 if p.get('acc') is not None:
580 v += '6f78' + '02' + lpad(p['acc'], 4)
581
582 self._scc.update_record(self._files['b_ef'][0], 1,
583 rpad(v, self._files['b_ef'][1]*2)
584 )
585
586 # SMSP ( 3f00/7f4d/8f0e )
587 # FIXME
588
589 # Write PLMN_Sel forcefully as well
590 r = self._scc.select_path(['3f00', '7f20', '6f30'])
591 tl = int(r[-1][4:8], 16)
592
593 hplmn = enc_plmn(p['mcc'], p['mnc'])
594 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
595
596 def erase(self):
597 # Dummy
598 df = {}
599 for k, v in self._files.items():
600 ofs = 1
601 fv = v[1] * 'ff'
602 if k == 'name':
603 ofs = 2
604 fv = fv[0:-4] + '0000'
605 df[v[0]] = (fv, ofs)
606
607 # Write
608 for n in range(0, self._get_count()):
609 for k, (msg, ofs) in df.items():
610 self._scc.update_record(['3f00', '7f4d', k], n + ofs, msg)
611
612
613class SuperSim(MagicSimBase):
614
615 name = 'supersim'
616
617 _files = {
618 'name': ('8f0c', 18, True),
619 'b_ef': ('8f0d', 74, True),
620 'r_ef': ('8f0e', 50, True),
621 }
622
623 _ki_file = None
624
625
626class MagicSim(MagicSimBase):
627
628 name = 'magicsim'
629
630 _files = {
631 'name': ('8f0c', 18, True),
632 'b_ef': ('8f0d', 130, True),
633 'r_ef': ('8f0e', 102, False),
634 }
635
636 _ki_file = '6f1b'
637
638
639class FakeMagicSim(SimCard):
640 """
641 Theses cards have a record based EF 3f00/000c that contains the provider
642 information. See the program method for its format. The records go from
643 1 to N.
644 """
645
646 name = 'fakemagicsim'
647
648 @classmethod
649 def autodetect(kls, scc):
650 try:
651 if scc.record_size(['3f00', '000c']) != 0x5a:
652 return None
653 except:
654 return None
655
656 return kls(scc)
657
658 def _get_infos(self):
659 """
660 Selects the file and returns the total number of entries
661 and entry size
662 """
663
664 r = self._scc.select_path(['3f00', '000c'])
665 rec_len = int(r[-1][28:30], 16)
666 tlen = int(r[-1][4:8], 16)
667 rec_cnt = (tlen // rec_len) - 1
668
669 if (rec_cnt < 1) or (rec_len != 0x5a):
670 raise RuntimeError('Bad card type')
671
672 return rec_cnt, rec_len
673
674 def program(self, p):
675 # Home PLMN
676 r = self._scc.select_path(['3f00', '7f20', '6f30'])
677 tl = int(r[-1][4:8], 16)
678
679 hplmn = enc_plmn(p['mcc'], p['mnc'])
680 self._scc.update_binary('6f30', hplmn + 'ff' * (tl-3))
681
682 # Get total number of entries and entry size
683 rec_cnt, rec_len = self._get_infos()
684
685 # Set first entry
686 entry = (
687 '81' + # 1b Status: Valid & Active
688 rpad(s2h(p['name'][0:14]), 28) + # 14b Entry Name
689 enc_iccid(p['iccid']) + # 10b ICCID
690 enc_imsi(p['imsi']) + # 9b IMSI_len + id_type(9) + IMSI
691 p['ki'] + # 16b Ki
692 lpad(p['smsp'], 80) # 40b SMSP (padded with ff if needed)
693 )
694 self._scc.update_record('000c', 1, entry)
695
696 def erase(self):
697 # Get total number of entries and entry size
698 rec_cnt, rec_len = self._get_infos()
699
700 # Erase all entries
701 entry = 'ff' * rec_len
702 for i in range(0, rec_cnt):
703 self._scc.update_record('000c', 1+i, entry)
704
705
706class GrcardSim(SimCard):
707 """
708 Greencard (grcard.cn) HZCOS GSM SIM
709 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
710 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
711 """
712
713 name = 'grcardsim'
714
715 @classmethod
716 def autodetect(kls, scc):
717 return None
718
719 def program(self, p):
720 # We don't really know yet what ADM PIN 4 is about
721 #self._scc.verify_chv(4, h2b("4444444444444444"))
722
723 # Authenticate using ADM PIN 5
724 if p['pin_adm']:
725 pin = h2b(p['pin_adm'])
726 else:
727 pin = h2b("4444444444444444")
728 self._scc.verify_chv(5, pin)
729
730 # EF.ICCID
731 r = self._scc.select_path(['3f00', '2fe2'])
732 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
733
734 # EF.IMSI
735 r = self._scc.select_path(['3f00', '7f20', '6f07'])
736 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
737
738 # EF.ACC
739 if p.get('acc') is not None:
740 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
741
742 # EF.SMSP
743 if p.get('smsp'):
744 r = self._scc.select_path(['3f00', '7f10', '6f42'])
745 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
746
747 # Set the Ki using proprietary command
748 pdu = '80d4020010' + p['ki']
749 data, sw = self._scc._tp.send_apdu(pdu)
750
751 # EF.HPLMN
752 r = self._scc.select_path(['3f00', '7f20', '6f30'])
753 size = int(r[-1][4:8], 16)
754 hplmn = enc_plmn(p['mcc'], p['mnc'])
755 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
756
757 # EF.SPN (Service Provider Name)
758 r = self._scc.select_path(['3f00', '7f20', '6f30'])
759 size = int(r[-1][4:8], 16)
760 # FIXME
761
762 # FIXME: EF.MSISDN
763
764
765class SysmoSIMgr1(GrcardSim):
766 """
767 sysmocom sysmoSIM-GR1
768 These cards have a much more regular ISO 7816-4 / TS 11.11 structure,
769 and use standard UPDATE RECORD / UPDATE BINARY commands except for Ki.
770 """
771 name = 'sysmosim-gr1'
772
773 @classmethod
774 def autodetect(kls, scc):
775 try:
776 # Look for ATR
777 if scc.get_atr() == toBytes("3B 99 18 00 11 88 22 33 44 55 66 77 60"):
778 return kls(scc)
779 except:
780 return None
781 return None
782
783
784class SysmoUSIMgr1(UsimCard):
785 """
786 sysmocom sysmoUSIM-GR1
787 """
788 name = 'sysmoUSIM-GR1'
789
790 @classmethod
791 def autodetect(kls, scc):
792 # TODO: Access the ATR
793 return None
794
795 def program(self, p):
796 # TODO: check if verify_chv could be used or what it needs
797 # self._scc.verify_chv(0x0A, [0x33,0x32,0x32,0x31,0x33,0x32,0x33,0x32])
798 # Unlock the card..
799 data, sw = self._scc._tp.send_apdu_checksw(
800 "0020000A083332323133323332")
801
802 # TODO: move into SimCardCommands
803 par = (p['ki'] + # 16b K
804 p['opc'] + # 32b OPC
805 enc_iccid(p['iccid']) + # 10b ICCID
806 enc_imsi(p['imsi']) # 9b IMSI_len + id_type(9) + IMSI
807 )
808 data, sw = self._scc._tp.send_apdu_checksw("0099000033" + par)
809
810
811class SysmoSIMgr2(SimCard):
812 """
813 sysmocom sysmoSIM-GR2
814 """
815
816 name = 'sysmoSIM-GR2'
817
818 @classmethod
819 def autodetect(kls, scc):
820 try:
821 # Look for ATR
822 if scc.get_atr() == toBytes("3B 7D 94 00 00 55 55 53 0A 74 86 93 0B 24 7C 4D 54 68"):
823 return kls(scc)
824 except:
825 return None
826 return None
827
828 def program(self, p):
829
830 # select MF
831 r = self._scc.select_path(['3f00'])
832
833 # authenticate as SUPER ADM using default key
834 self._scc.verify_chv(0x0b, h2b("3838383838383838"))
835
836 # set ADM pin using proprietary command
837 # INS: D4
838 # P1: 3A for PIN, 3B for PUK
839 # P2: CHV number, as in VERIFY CHV for PIN, and as in UNBLOCK CHV for PUK
840 # P3: 08, CHV length (curiously the PUK is also 08 length, instead of 10)
841 if p['pin_adm']:
842 pin = h2b(p['pin_adm'])
843 else:
844 pin = h2b("4444444444444444")
845
846 pdu = 'A0D43A0508' + b2h(pin)
847 data, sw = self._scc._tp.send_apdu(pdu)
848
849 # authenticate as ADM (enough to write file, and can set PINs)
850
851 self._scc.verify_chv(0x05, pin)
852
853 # write EF.ICCID
854 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
855
856 # select DF_GSM
857 r = self._scc.select_path(['7f20'])
858
859 # write EF.IMSI
860 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
861
862 # write EF.ACC
863 if p.get('acc') is not None:
864 data, sw = self._scc.update_binary('6f78', lpad(p['acc'], 4))
865
866 # get size and write EF.HPLMN
867 r = self._scc.select_path(['6f30'])
868 size = int(r[-1][4:8], 16)
869 hplmn = enc_plmn(p['mcc'], p['mnc'])
870 self._scc.update_binary('6f30', hplmn + 'ff' * (size-3))
871
872 # set COMP128 version 0 in proprietary file
873 data, sw = self._scc.update_binary('0001', '001000')
874
875 # set Ki in proprietary file
876 data, sw = self._scc.update_binary('0001', p['ki'], 3)
877
878 # select DF_TELECOM
879 r = self._scc.select_path(['3f00', '7f10'])
880
881 # write EF.SMSP
882 if p.get('smsp'):
883 data, sw = self._scc.update_record('6f42', 1, lpad(p['smsp'], 80))
884
885
886class SysmoUSIMSJS1(UsimCard):
887 """
888 sysmocom sysmoUSIM-SJS1
889 """
890
891 name = 'sysmoUSIM-SJS1'
892
893 def __init__(self, ssc):
894 super(SysmoUSIMSJS1, self).__init__(ssc)
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 96 80 1F C7 80 31 A0 73 BE 21 13 67 43 20 07 18 00 00 01 A5"):
903 return kls(scc)
904 except:
905 return None
906 return None
907
908 def verify_adm(self, key):
909 # authenticate as ADM using default key (written on the card..)
910 if not key:
911 raise ValueError(
912 "Please provide a PIN-ADM as there is no default one")
913 (res, sw) = self._scc.verify_chv(0x0A, key)
914 return sw
915
916 def program(self, p):
917 self.verify_adm(h2b(p['pin_adm']))
918
919 # select MF
920 r = self._scc.select_path(['3f00'])
921
922 # write EF.ICCID
923 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
924
925 # select DF_GSM
926 r = self._scc.select_path(['7f20'])
927
928 # set Ki in proprietary file
929 data, sw = self._scc.update_binary('00FF', p['ki'])
930
931 # set OPc in proprietary file
932 if 'opc' in p:
933 content = "01" + p['opc']
934 data, sw = self._scc.update_binary('00F7', content)
935
936 # set Service Provider Name
937 if p.get('name') is not None:
938 self.update_spn(p['name'], True, True)
939
940 if p.get('acc') is not None:
941 self.update_acc(p['acc'])
942
943 # write EF.IMSI
944 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
945
946 # EF.PLMNsel
947 if p.get('mcc') and p.get('mnc'):
948 sw = self.update_plmnsel(p['mcc'], p['mnc'])
949 if sw != '9000':
950 print("Programming PLMNsel failed with code %s" % sw)
951
952 # EF.PLMNwAcT
953 if p.get('mcc') and p.get('mnc'):
954 sw = self.update_plmn_act(p['mcc'], p['mnc'])
955 if sw != '9000':
956 print("Programming PLMNwAcT failed with code %s" % sw)
957
958 # EF.OPLMNwAcT
959 if p.get('mcc') and p.get('mnc'):
960 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
961 if sw != '9000':
962 print("Programming OPLMNwAcT failed with code %s" % sw)
963
964 # EF.HPLMNwAcT
965 if p.get('mcc') and p.get('mnc'):
966 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
967 if sw != '9000':
968 print("Programming HPLMNwAcT failed with code %s" % sw)
969
970 # EF.AD
971 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
972 if p.get('mcc') and p.get('mnc'):
973 mnc = p['mnc']
974 else:
975 mnc = None
976 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
977 if sw != '9000':
978 print("Programming AD failed with code %s" % sw)
979
980 # EF.SMSP
981 if p.get('smsp'):
982 r = self._scc.select_path(['3f00', '7f10'])
983 data, sw = self._scc.update_record(
984 '6f42', 1, lpad(p['smsp'], 104), force_len=True)
985
986 # EF.MSISDN
987 # TODO: Alpha Identifier (currently 'ff'O * 20)
988 # TODO: Capability/Configuration1 Record Identifier
989 # TODO: Extension1 Record Identifier
990 if p.get('msisdn') is not None:
991 msisdn = enc_msisdn(p['msisdn'])
992 data = 'ff' * 20 + msisdn
993
994 r = self._scc.select_path(['3f00', '7f10'])
995 data, sw = self._scc.update_record('6F40', 1, data, force_len=True)
996
997
998class FairwavesSIM(UsimCard):
999 """
1000 FairwavesSIM
1001
1002 The SIM card is operating according to the standard.
1003 For Ki/OP/OPC programming the following files are additionally open for writing:
1004 3F00/7F20/FF01 – OP/OPC:
1005 byte 1 = 0x01, bytes 2-17: OPC;
1006 byte 1 = 0x00, bytes 2-17: OP;
1007 3F00/7F20/FF02: Ki
1008 """
1009
1010 name = 'Fairwaves-SIM'
1011 # Propriatary files
1012 _EF_num = {
1013 'Ki': 'FF02',
1014 'OP/OPC': 'FF01',
1015 }
1016 _EF = {
1017 'Ki': DF['GSM']+[_EF_num['Ki']],
1018 'OP/OPC': DF['GSM']+[_EF_num['OP/OPC']],
1019 }
1020
1021 def __init__(self, ssc):
1022 super(FairwavesSIM, self).__init__(ssc)
1023 self._adm_chv_num = 0x11
1024 self._adm2_chv_num = 0x12
1025
1026 @classmethod
1027 def autodetect(kls, scc):
1028 try:
1029 # Look for ATR
1030 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"):
1031 return kls(scc)
1032 except:
1033 return None
1034 return None
1035
1036 def verify_adm2(self, key):
1037 '''
1038 Authenticate with ADM2 key.
1039
1040 Fairwaves SIM cards support hierarchical key structure and ADM2 key
1041 is a key which has access to proprietary files (Ki and OP/OPC).
1042 That said, ADM key inherits permissions of ADM2 key and thus we rarely
1043 need ADM2 key per se.
1044 '''
1045 (res, sw) = self._scc.verify_chv(self._adm2_chv_num, key)
1046 return sw
1047
1048 def read_ki(self):
1049 """
1050 Read Ki in proprietary file.
1051
1052 Requires ADM1 access level
1053 """
1054 return self._scc.read_binary(self._EF['Ki'])
1055
1056 def update_ki(self, ki):
1057 """
1058 Set Ki in proprietary file.
1059
1060 Requires ADM1 access level
1061 """
1062 data, sw = self._scc.update_binary(self._EF['Ki'], ki)
1063 return sw
1064
1065 def read_op_opc(self):
1066 """
1067 Read Ki in proprietary file.
1068
1069 Requires ADM1 access level
1070 """
1071 (ef, sw) = self._scc.read_binary(self._EF['OP/OPC'])
1072 type = 'OP' if ef[0:2] == '00' else 'OPC'
1073 return ((type, ef[2:]), sw)
1074
1075 def update_op(self, op):
1076 """
1077 Set OP in proprietary file.
1078
1079 Requires ADM1 access level
1080 """
1081 content = '00' + op
1082 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
1083 return sw
1084
1085 def update_opc(self, opc):
1086 """
1087 Set OPC in proprietary file.
1088
1089 Requires ADM1 access level
1090 """
1091 content = '01' + opc
1092 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
1093 return sw
1094
1095 def program(self, p):
1096 # For some reason the card programming only works when the card
1097 # is handled as a classic SIM, even though it is an USIM, so we
1098 # reconfigure the class byte and the select control field on
1099 # the fly. When the programming is done the original values are
1100 # restored.
1101 cla_byte_orig = self._scc.cla_byte
1102 sel_ctrl_orig = self._scc.sel_ctrl
1103 self._scc.cla_byte = "a0"
1104 self._scc.sel_ctrl = "0000"
1105
1106 try:
1107 self._program(p)
1108 finally:
1109 # restore original cla byte and sel ctrl
1110 self._scc.cla_byte = cla_byte_orig
1111 self._scc.sel_ctrl = sel_ctrl_orig
1112
1113 def _program(self, p):
1114 # authenticate as ADM1
1115 if not p['pin_adm']:
1116 raise ValueError(
1117 "Please provide a PIN-ADM as there is no default one")
1118 self.verify_adm(h2b(p['pin_adm']))
1119
1120 # TODO: Set operator name
1121 if p.get('smsp') is not None:
1122 sw = self.update_smsp(p['smsp'])
1123 if sw != '9000':
1124 print("Programming SMSP failed with code %s" % sw)
1125 # This SIM doesn't support changing ICCID
1126 if p.get('mcc') is not None and p.get('mnc') is not None:
1127 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
1128 if sw != '9000':
1129 print("Programming MCC/MNC failed with code %s" % sw)
1130 if p.get('imsi') is not None:
1131 sw = self.update_imsi(p['imsi'])
1132 if sw != '9000':
1133 print("Programming IMSI failed with code %s" % sw)
1134 if p.get('ki') is not None:
1135 sw = self.update_ki(p['ki'])
1136 if sw != '9000':
1137 print("Programming Ki failed with code %s" % sw)
1138 if p.get('opc') is not None:
1139 sw = self.update_opc(p['opc'])
1140 if sw != '9000':
1141 print("Programming OPC failed with code %s" % sw)
1142 if p.get('acc') is not None:
1143 sw = self.update_acc(p['acc'])
1144 if sw != '9000':
1145 print("Programming ACC failed with code %s" % sw)
1146
1147
1148class OpenCellsSim(SimCard):
1149 """
1150 OpenCellsSim
1151
1152 """
1153
1154 name = 'OpenCells-SIM'
1155
1156 def __init__(self, ssc):
1157 super(OpenCellsSim, self).__init__(ssc)
1158 self._adm_chv_num = 0x0A
1159
1160 @classmethod
1161 def autodetect(kls, scc):
1162 try:
1163 # Look for ATR
1164 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"):
1165 return kls(scc)
1166 except:
1167 return None
1168 return None
1169
1170 def program(self, p):
1171 if not p['pin_adm']:
1172 raise ValueError(
1173 "Please provide a PIN-ADM as there is no default one")
1174 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
1175
1176 # select MF
1177 r = self._scc.select_path(['3f00'])
1178
1179 # write EF.ICCID
1180 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
1181
1182 r = self._scc.select_path(['7ff0'])
1183
1184 # set Ki in proprietary file
1185 data, sw = self._scc.update_binary('FF02', p['ki'])
1186
1187 # set OPC in proprietary file
1188 data, sw = self._scc.update_binary('FF01', p['opc'])
1189
1190 # select DF_GSM
1191 r = self._scc.select_path(['7f20'])
1192
1193 # write EF.IMSI
1194 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
1195
1196
1197class WavemobileSim(UsimCard):
1198 """
1199 WavemobileSim
1200
1201 """
1202
1203 name = 'Wavemobile-SIM'
1204
1205 def __init__(self, ssc):
1206 super(WavemobileSim, self).__init__(ssc)
1207 self._adm_chv_num = 0x0A
1208 self._scc.cla_byte = "00"
1209 self._scc.sel_ctrl = "0004" # request an FCP
1210
1211 @classmethod
1212 def autodetect(kls, scc):
1213 try:
1214 # Look for ATR
1215 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"):
1216 return kls(scc)
1217 except:
1218 return None
1219 return None
1220
1221 def program(self, p):
1222 if not p['pin_adm']:
1223 raise ValueError(
1224 "Please provide a PIN-ADM as there is no default one")
1225 self.verify_adm(h2b(p['pin_adm']))
1226
1227 # EF.ICCID
1228 # TODO: Add programming of the ICCID
1229 if p.get('iccid'):
1230 print(
1231 "Warning: Programming of the ICCID is not implemented for this type of card.")
1232
1233 # KI (Presumably a proprietary file)
1234 # TODO: Add programming of KI
1235 if p.get('ki'):
1236 print(
1237 "Warning: Programming of the KI is not implemented for this type of card.")
1238
1239 # OPc (Presumably a proprietary file)
1240 # TODO: Add programming of OPc
1241 if p.get('opc'):
1242 print(
1243 "Warning: Programming of the OPc is not implemented for this type of card.")
1244
1245 # EF.SMSP
1246 if p.get('smsp'):
1247 sw = self.update_smsp(p['smsp'])
1248 if sw != '9000':
1249 print("Programming SMSP failed with code %s" % sw)
1250
1251 # EF.IMSI
1252 if p.get('imsi'):
1253 sw = self.update_imsi(p['imsi'])
1254 if sw != '9000':
1255 print("Programming IMSI failed with code %s" % sw)
1256
1257 # EF.ACC
1258 if p.get('acc'):
1259 sw = self.update_acc(p['acc'])
1260 if sw != '9000':
1261 print("Programming ACC failed with code %s" % sw)
1262
1263 # EF.PLMNsel
1264 if p.get('mcc') and p.get('mnc'):
1265 sw = self.update_plmnsel(p['mcc'], p['mnc'])
1266 if sw != '9000':
1267 print("Programming PLMNsel failed with code %s" % sw)
1268
1269 # EF.PLMNwAcT
1270 if p.get('mcc') and p.get('mnc'):
1271 sw = self.update_plmn_act(p['mcc'], p['mnc'])
1272 if sw != '9000':
1273 print("Programming PLMNwAcT failed with code %s" % sw)
1274
1275 # EF.OPLMNwAcT
1276 if p.get('mcc') and p.get('mnc'):
1277 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
1278 if sw != '9000':
1279 print("Programming OPLMNwAcT failed with code %s" % sw)
1280
1281 # EF.AD
1282 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
1283 if p.get('mcc') and p.get('mnc'):
1284 mnc = p['mnc']
1285 else:
1286 mnc = None
1287 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
1288 if sw != '9000':
1289 print("Programming AD failed with code %s" % sw)
1290
1291 return None
1292
1293
1294class SysmoISIMSJA2(UsimCard, IsimCard):
1295 """
1296 sysmocom sysmoISIM-SJA2
1297 """
1298
1299 name = 'sysmoISIM-SJA2'
1300
1301 def __init__(self, ssc):
1302 super(SysmoISIMSJA2, self).__init__(ssc)
1303 self._scc.cla_byte = "00"
1304 self._scc.sel_ctrl = "0004" # request an FCP
1305
1306 @classmethod
1307 def autodetect(kls, scc):
1308 try:
1309 # Try card model #1
1310 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9"
1311 if scc.get_atr() == toBytes(atr):
1312 return kls(scc)
1313
1314 # Try card model #2
1315 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2"
1316 if scc.get_atr() == toBytes(atr):
1317 return kls(scc)
1318
1319 # Try card model #3
1320 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"
1321 if scc.get_atr() == toBytes(atr):
1322 return kls(scc)
1323 except:
1324 return None
1325 return None
1326
1327 def verify_adm(self, key):
1328 # authenticate as ADM using default key (written on the card..)
1329 if not key:
1330 raise ValueError(
1331 "Please provide a PIN-ADM as there is no default one")
1332 (res, sw) = self._scc.verify_chv(0x0A, key)
1333 return sw
1334
1335 def program(self, p):
1336 self.verify_adm(h2b(p['pin_adm']))
1337
1338 # Populate AIDs
1339 self.read_aids()
1340
1341 # This type of card does not allow to reprogram the ICCID.
1342 # Reprogramming the ICCID would mess up the card os software
1343 # license management, so the ICCID must be kept at its factory
1344 # setting!
1345 if p.get('iccid'):
1346 print(
1347 "Warning: Programming of the ICCID is not implemented for this type of card.")
1348
1349 # select DF_GSM
1350 self._scc.select_path(['7f20'])
1351
1352 # set Service Provider Name
1353 if p.get('name') is not None:
1354 self.update_spn(p['name'], True, True)
1355
1356 # write EF.IMSI
1357 if p.get('imsi'):
1358 self._scc.update_binary('6f07', enc_imsi(p['imsi']))
1359
1360 # EF.PLMNsel
1361 if p.get('mcc') and p.get('mnc'):
1362 sw = self.update_plmnsel(p['mcc'], p['mnc'])
1363 if sw != '9000':
1364 print("Programming PLMNsel failed with code %s" % sw)
1365
1366 # EF.PLMNwAcT
1367 if p.get('mcc') and p.get('mnc'):
1368 sw = self.update_plmn_act(p['mcc'], p['mnc'])
1369 if sw != '9000':
1370 print("Programming PLMNwAcT failed with code %s" % sw)
1371
1372 # EF.OPLMNwAcT
1373 if p.get('mcc') and p.get('mnc'):
1374 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
1375 if sw != '9000':
1376 print("Programming OPLMNwAcT failed with code %s" % sw)
1377
1378 # EF.HPLMNwAcT
1379 if p.get('mcc') and p.get('mnc'):
1380 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
1381 if sw != '9000':
1382 print("Programming HPLMNwAcT failed with code %s" % sw)
1383
1384 # EF.AD
1385 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
1386 if p.get('mcc') and p.get('mnc'):
1387 mnc = p['mnc']
1388 else:
1389 mnc = None
1390 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
1391 if sw != '9000':
1392 print("Programming AD failed with code %s" % sw)
1393
1394 # EF.SMSP
1395 if p.get('smsp'):
1396 r = self._scc.select_path(['3f00', '7f10'])
1397 data, sw = self._scc.update_record(
1398 '6f42', 1, lpad(p['smsp'], 104), force_len=True)
1399
1400 # EF.MSISDN
1401 # TODO: Alpha Identifier (currently 'ff'O * 20)
1402 # TODO: Capability/Configuration1 Record Identifier
1403 # TODO: Extension1 Record Identifier
1404 if p.get('msisdn') is not None:
1405 msisdn = enc_msisdn(p['msisdn'])
1406 content = 'ff' * 20 + msisdn
1407
1408 r = self._scc.select_path(['3f00', '7f10'])
1409 data, sw = self._scc.update_record(
1410 '6F40', 1, content, force_len=True)
1411
1412 # EF.ACC
1413 if p.get('acc'):
1414 sw = self.update_acc(p['acc'])
1415 if sw != '9000':
1416 print("Programming ACC failed with code %s" % sw)
1417
1418 # update EF-SIM_AUTH_KEY (and EF-USIM_AUTH_KEY_2G, which is
1419 # hard linked to EF-USIM_AUTH_KEY)
1420 self._scc.select_path(['3f00'])
1421 self._scc.select_path(['a515'])
1422 if p.get('ki'):
1423 self._scc.update_binary('6f20', p['ki'], 1)
1424 if p.get('opc'):
1425 self._scc.update_binary('6f20', p['opc'], 17)
1426
1427 # update EF-USIM_AUTH_KEY in ADF.ISIM
1428 if self.adf_present("isim"):
1429 self.select_adf_by_aid(adf="isim")
1430
1431 if p.get('ki'):
1432 self._scc.update_binary('af20', p['ki'], 1)
1433 if p.get('opc'):
1434 self._scc.update_binary('af20', p['opc'], 17)
1435
1436 # update EF.P-CSCF in ADF.ISIM
1437 if self.file_exists(EF_ISIM_ADF_map['PCSCF']):
1438 if p.get('pcscf'):
1439 sw = self.update_pcscf(p['pcscf'])
1440 else:
1441 sw = self.update_pcscf("")
1442 if sw != '9000':
1443 print("Programming P-CSCF failed with code %s" % sw)
1444
1445 # update EF.DOMAIN in ADF.ISIM
1446 if self.file_exists(EF_ISIM_ADF_map['DOMAIN']):
1447 if p.get('ims_hdomain'):
1448 sw = self.update_domain(domain=p['ims_hdomain'])
1449 else:
1450 sw = self.update_domain()
1451
1452 if sw != '9000':
1453 print(
1454 "Programming Home Network Domain Name failed with code %s" % sw)
1455
1456 # update EF.IMPI in ADF.ISIM
1457 # TODO: Validate IMPI input
1458 if self.file_exists(EF_ISIM_ADF_map['IMPI']):
1459 if p.get('impi'):
1460 sw = self.update_impi(p['impi'])
1461 else:
1462 sw = self.update_impi()
1463 if sw != '9000':
1464 print("Programming IMPI failed with code %s" % sw)
1465
1466 # update EF.IMPU in ADF.ISIM
1467 # TODO: Validate IMPU input
1468 # Support multiple IMPU if there is enough space
1469 if self.file_exists(EF_ISIM_ADF_map['IMPU']):
1470 if p.get('impu'):
1471 sw = self.update_impu(p['impu'])
1472 else:
1473 sw = self.update_impu()
1474 if sw != '9000':
1475 print("Programming IMPU failed with code %s" % sw)
1476
1477 if self.adf_present("usim"):
1478 self.select_adf_by_aid(adf="usim")
1479
1480 # EF.AD in ADF.USIM
1481 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
1482 if p.get('mcc') and p.get('mnc'):
1483 mnc = p['mnc']
1484 else:
1485 mnc = None
1486 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'),
1487 path=EF_USIM_ADF_map['AD'])
1488 if sw != '9000':
1489 print("Programming AD failed with code %s" % sw)
1490
1491 # update EF-USIM_AUTH_KEY in ADF.USIM
1492 if p.get('ki'):
1493 self._scc.update_binary('af20', p['ki'], 1)
1494 if p.get('opc'):
1495 self._scc.update_binary('af20', p['opc'], 17)
1496
1497 # update EF.EHPLMN in ADF.USIM
1498 if self.file_exists(EF_USIM_ADF_map['EHPLMN']):
1499 if p.get('mcc') and p.get('mnc'):
1500 sw = self.update_ehplmn(p['mcc'], p['mnc'])
1501 if sw != '9000':
1502 print("Programming EHPLMN failed with code %s" % sw)
1503
1504 # update EF.ePDGId in ADF.USIM
1505 if self.file_exists(EF_USIM_ADF_map['ePDGId']):
1506 if p.get('epdgid'):
1507 sw = self.update_epdgid(p['epdgid'])
1508 else:
1509 sw = self.update_epdgid("")
1510 if sw != '9000':
1511 print("Programming ePDGId failed with code %s" % sw)
1512
1513 # update EF.ePDGSelection in ADF.USIM
1514 if self.file_exists(EF_USIM_ADF_map['ePDGSelection']):
1515 if p.get('epdgSelection'):
1516 epdg_plmn = p['epdgSelection']
1517 sw = self.update_ePDGSelection(
1518 epdg_plmn[:3], epdg_plmn[3:])
1519 else:
1520 sw = self.update_ePDGSelection("", "")
1521 if sw != '9000':
1522 print("Programming ePDGSelection failed with code %s" % sw)
1523
1524 # After successfully programming EF.ePDGId and EF.ePDGSelection,
1525 # Set service 106 and 107 as available in EF.UST
1526 # Disable service 95, 99, 115 if ISIM application is present
1527 if self.file_exists(EF_USIM_ADF_map['UST']):
1528 if p.get('epdgSelection') and p.get('epdgid'):
1529 sw = self.update_ust(106, 1)
1530 if sw != '9000':
1531 print("Programming UST failed with code %s" % sw)
1532 sw = self.update_ust(107, 1)
1533 if sw != '9000':
1534 print("Programming UST failed with code %s" % sw)
1535
1536 sw = self.update_ust(95, 0)
1537 if sw != '9000':
1538 print("Programming UST failed with code %s" % sw)
1539 sw = self.update_ust(99, 0)
1540 if sw != '9000':
1541 print("Programming UST failed with code %s" % sw)
1542 sw = self.update_ust(115, 0)
1543 if sw != '9000':
1544 print("Programming UST failed with code %s" % sw)
1545
1546 return
1547
1548class SysmoISIMSJA5(SysmoISIMSJA2):
1549 """
1550 sysmocom sysmoISIM-SJA5
1551 """
1552
1553 name = 'sysmoISIM-SJA5'
1554
1555 @classmethod
1556 def autodetect(kls, scc):
1557 try:
1558 # Try card model #1 (9FJ)
1559 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 51 CC"
1560 if scc.get_atr() == toBytes(atr):
1561 return kls(scc)
1562 # Try card model #2 (SLM17)
1563 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 65 F8"
1564 if scc.get_atr() == toBytes(atr):
1565 return kls(scc)
1566 # Try card model #3 (9FV)
1567 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 59 C4"
1568 if scc.get_atr() == toBytes(atr):
1569 return kls(scc)
1570 except:
1571 return None
1572 return None
1573
1574
1575class GialerSim(UsimCard):
1576 """
1577 Gialer sim cards (www.gialer.com).
1578 """
1579 name = 'gialersim'
1580
1581 def __init__(self, ssc):
1582 super().__init__(ssc)
1583 self._program_handlers = {
1584 'iccid': self.update_iccid,
1585 'imsi': self.update_imsi,
1586 'acc': self.update_acc,
1587 'smsp': self.update_smsp,
1588 'ki': self.update_ki,
1589 'opc': self.update_opc,
1590 'fplmn': self.update_fplmn,
1591 }
1592
1593 @classmethod
1594 def autodetect(cls, scc):
1595 try:
1596 # Look for ATR
1597 if scc.get_atr() == toBytes('3B 9F 95 80 1F C7 80 31 A0 73 B6 A1 00 67 CF 32 15 CA 9C D7 09 20'):
1598 return cls(scc)
1599 except:
1600 return None
1601 return None
1602
1603 def program(self, p):
1604 self.set_apdu_parameter('00', '0004')
1605 # Authenticate
1606 self._scc.verify_chv(0xc, h2b('3834373936313533'))
1607 for handler in self._program_handlers:
1608 if p.get(handler) is not None:
1609 self._program_handlers[handler](p[handler])
1610
1611 mcc = p.get('mcc')
1612 mnc = p.get('mnc')
1613 has_plmn = mcc is not None and mnc is not None
1614 # EF.HPLMN
1615 if has_plmn:
1616 self.update_hplmn_act(mcc, mnc)
1617
1618 # EF.AD
1619 if has_plmn or (p.get('opmode') is not None):
1620 self.update_ad(mnc=mnc, opmode=p.get('opmode'))
1621
1622 def update_smsp(self, smsp):
1623 data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 80))
1624 return sw
1625
1626 def update_ki(self, ki):
1627 self._scc.select_path(['3f00', '0001'])
1628 self._scc.update_binary('0001', ki)
1629
1630 def update_opc(self, opc):
1631 self._scc.select_path(['3f00', '6002'])
1632 # No idea why the '01' is required
1633 self._scc.update_binary('6002', '01' + opc)
1634
1635
1636# In order for autodetection ...
1637_cards_classes = [FakeMagicSim, SuperSim, MagicSim, GrcardSim,
1638 SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1,
1639 FairwavesSIM, OpenCellsSim, WavemobileSim, SysmoISIMSJA2,
1640 SysmoISIMSJA5, GialerSim]
1641
1642
1643def card_detect(ctype, scc):
1644 # Detect type if needed
1645 card = None
1646 ctypes = dict([(kls.name, kls) for kls in _cards_classes])
1647
1648 if ctype == "auto":
1649 for kls in _cards_classes:
1650 card = kls.autodetect(scc)
1651 if card:
1652 print("Autodetected card type: %s" % card.name)
1653 card.reset()
1654 break
1655
1656 if card is None:
1657 print("Autodetection failed")
1658 return None
1659
1660 elif ctype in ctypes:
1661 card = ctypes[ctype](scc)
1662
1663 else:
1664 raise ValueError("Unknown card type: %s" % ctype)
1665
1666 return card