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