blob: bb3e8a52d8f8d4f4ee3f611053f2da163ee0464d [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 Weltef8d2e2b2023-07-09 17:58:38 +020017
Harald Welte57ad38e2023-07-09 22:14:09 +020018from pySim.ts_51_011 import EF_AD, EF_SPN
Harald Weltef8d2e2b2023-07-09 17:58:38 +020019from pySim.ts_31_102 import EF_USIM_ADF_map
20from pySim.ts_31_103 import EF_ISIM_ADF_map
21
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)
896 self._scc.cla_byte = "00"
897 self._scc.sel_ctrl = "0004" # request an FCP
898
899 @classmethod
900 def autodetect(kls, scc):
901 try:
902 # Look for ATR
903 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"):
904 return kls(scc)
905 except:
906 return None
907 return None
908
909 def verify_adm(self, key):
910 # authenticate as ADM using default key (written on the card..)
911 if not key:
912 raise ValueError(
913 "Please provide a PIN-ADM as there is no default one")
914 (res, sw) = self._scc.verify_chv(0x0A, key)
915 return sw
916
917 def program(self, p):
918 self.verify_adm(h2b(p['pin_adm']))
919
920 # select MF
921 r = self._scc.select_path(['3f00'])
922
923 # write EF.ICCID
924 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
925
926 # select DF_GSM
927 r = self._scc.select_path(['7f20'])
928
929 # set Ki in proprietary file
930 data, sw = self._scc.update_binary('00FF', p['ki'])
931
932 # set OPc in proprietary file
933 if 'opc' in p:
934 content = "01" + p['opc']
935 data, sw = self._scc.update_binary('00F7', content)
936
937 # set Service Provider Name
938 if p.get('name') is not None:
939 self.update_spn(p['name'], True, True)
940
941 if p.get('acc') is not None:
942 self.update_acc(p['acc'])
943
944 # write EF.IMSI
945 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
946
947 # EF.PLMNsel
948 if p.get('mcc') and p.get('mnc'):
949 sw = self.update_plmnsel(p['mcc'], p['mnc'])
950 if sw != '9000':
951 print("Programming PLMNsel failed with code %s" % sw)
952
953 # EF.PLMNwAcT
954 if p.get('mcc') and p.get('mnc'):
955 sw = self.update_plmn_act(p['mcc'], p['mnc'])
956 if sw != '9000':
957 print("Programming PLMNwAcT failed with code %s" % sw)
958
959 # EF.OPLMNwAcT
960 if p.get('mcc') and p.get('mnc'):
961 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
962 if sw != '9000':
963 print("Programming OPLMNwAcT failed with code %s" % sw)
964
965 # EF.HPLMNwAcT
966 if p.get('mcc') and p.get('mnc'):
967 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
968 if sw != '9000':
969 print("Programming HPLMNwAcT failed with code %s" % sw)
970
971 # EF.AD
972 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
973 if p.get('mcc') and p.get('mnc'):
974 mnc = p['mnc']
975 else:
976 mnc = None
977 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
978 if sw != '9000':
979 print("Programming AD failed with code %s" % sw)
980
981 # EF.SMSP
982 if p.get('smsp'):
983 r = self._scc.select_path(['3f00', '7f10'])
984 data, sw = self._scc.update_record(
985 '6f42', 1, lpad(p['smsp'], 104), force_len=True)
986
987 # EF.MSISDN
988 # TODO: Alpha Identifier (currently 'ff'O * 20)
989 # TODO: Capability/Configuration1 Record Identifier
990 # TODO: Extension1 Record Identifier
991 if p.get('msisdn') is not None:
992 msisdn = enc_msisdn(p['msisdn'])
993 data = 'ff' * 20 + msisdn
994
995 r = self._scc.select_path(['3f00', '7f10'])
996 data, sw = self._scc.update_record('6F40', 1, data, force_len=True)
997
998
999class FairwavesSIM(UsimCard):
1000 """
1001 FairwavesSIM
1002
1003 The SIM card is operating according to the standard.
1004 For Ki/OP/OPC programming the following files are additionally open for writing:
1005 3F00/7F20/FF01 – OP/OPC:
1006 byte 1 = 0x01, bytes 2-17: OPC;
1007 byte 1 = 0x00, bytes 2-17: OP;
1008 3F00/7F20/FF02: Ki
1009 """
1010
1011 name = 'Fairwaves-SIM'
1012 # Propriatary files
1013 _EF_num = {
1014 'Ki': 'FF02',
1015 'OP/OPC': 'FF01',
1016 }
1017 _EF = {
1018 'Ki': DF['GSM']+[_EF_num['Ki']],
1019 'OP/OPC': DF['GSM']+[_EF_num['OP/OPC']],
1020 }
1021
1022 def __init__(self, ssc):
1023 super(FairwavesSIM, self).__init__(ssc)
1024 self._adm_chv_num = 0x11
1025 self._adm2_chv_num = 0x12
1026
1027 @classmethod
1028 def autodetect(kls, scc):
1029 try:
1030 # Look for ATR
1031 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"):
1032 return kls(scc)
1033 except:
1034 return None
1035 return None
1036
1037 def verify_adm2(self, key):
1038 '''
1039 Authenticate with ADM2 key.
1040
1041 Fairwaves SIM cards support hierarchical key structure and ADM2 key
1042 is a key which has access to proprietary files (Ki and OP/OPC).
1043 That said, ADM key inherits permissions of ADM2 key and thus we rarely
1044 need ADM2 key per se.
1045 '''
1046 (res, sw) = self._scc.verify_chv(self._adm2_chv_num, key)
1047 return sw
1048
1049 def read_ki(self):
1050 """
1051 Read Ki in proprietary file.
1052
1053 Requires ADM1 access level
1054 """
1055 return self._scc.read_binary(self._EF['Ki'])
1056
1057 def update_ki(self, ki):
1058 """
1059 Set Ki in proprietary file.
1060
1061 Requires ADM1 access level
1062 """
1063 data, sw = self._scc.update_binary(self._EF['Ki'], ki)
1064 return sw
1065
1066 def read_op_opc(self):
1067 """
1068 Read Ki in proprietary file.
1069
1070 Requires ADM1 access level
1071 """
1072 (ef, sw) = self._scc.read_binary(self._EF['OP/OPC'])
1073 type = 'OP' if ef[0:2] == '00' else 'OPC'
1074 return ((type, ef[2:]), sw)
1075
1076 def update_op(self, op):
1077 """
1078 Set OP in proprietary file.
1079
1080 Requires ADM1 access level
1081 """
1082 content = '00' + op
1083 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
1084 return sw
1085
1086 def update_opc(self, opc):
1087 """
1088 Set OPC in proprietary file.
1089
1090 Requires ADM1 access level
1091 """
1092 content = '01' + opc
1093 data, sw = self._scc.update_binary(self._EF['OP/OPC'], content)
1094 return sw
1095
1096 def program(self, p):
1097 # For some reason the card programming only works when the card
1098 # is handled as a classic SIM, even though it is an USIM, so we
1099 # reconfigure the class byte and the select control field on
1100 # the fly. When the programming is done the original values are
1101 # restored.
1102 cla_byte_orig = self._scc.cla_byte
1103 sel_ctrl_orig = self._scc.sel_ctrl
1104 self._scc.cla_byte = "a0"
1105 self._scc.sel_ctrl = "0000"
1106
1107 try:
1108 self._program(p)
1109 finally:
1110 # restore original cla byte and sel ctrl
1111 self._scc.cla_byte = cla_byte_orig
1112 self._scc.sel_ctrl = sel_ctrl_orig
1113
1114 def _program(self, p):
1115 # authenticate as ADM1
1116 if not p['pin_adm']:
1117 raise ValueError(
1118 "Please provide a PIN-ADM as there is no default one")
1119 self.verify_adm(h2b(p['pin_adm']))
1120
1121 # TODO: Set operator name
1122 if p.get('smsp') is not None:
1123 sw = self.update_smsp(p['smsp'])
1124 if sw != '9000':
1125 print("Programming SMSP failed with code %s" % sw)
1126 # This SIM doesn't support changing ICCID
1127 if p.get('mcc') is not None and p.get('mnc') is not None:
1128 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
1129 if sw != '9000':
1130 print("Programming MCC/MNC failed with code %s" % sw)
1131 if p.get('imsi') is not None:
1132 sw = self.update_imsi(p['imsi'])
1133 if sw != '9000':
1134 print("Programming IMSI failed with code %s" % sw)
1135 if p.get('ki') is not None:
1136 sw = self.update_ki(p['ki'])
1137 if sw != '9000':
1138 print("Programming Ki failed with code %s" % sw)
1139 if p.get('opc') is not None:
1140 sw = self.update_opc(p['opc'])
1141 if sw != '9000':
1142 print("Programming OPC failed with code %s" % sw)
1143 if p.get('acc') is not None:
1144 sw = self.update_acc(p['acc'])
1145 if sw != '9000':
1146 print("Programming ACC failed with code %s" % sw)
1147
1148
1149class OpenCellsSim(SimCard):
1150 """
1151 OpenCellsSim
1152
1153 """
1154
1155 name = 'OpenCells-SIM'
1156
1157 def __init__(self, ssc):
1158 super(OpenCellsSim, self).__init__(ssc)
1159 self._adm_chv_num = 0x0A
1160
1161 @classmethod
1162 def autodetect(kls, scc):
1163 try:
1164 # Look for ATR
1165 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"):
1166 return kls(scc)
1167 except:
1168 return None
1169 return None
1170
1171 def program(self, p):
1172 if not p['pin_adm']:
1173 raise ValueError(
1174 "Please provide a PIN-ADM as there is no default one")
1175 self._scc.verify_chv(0x0A, h2b(p['pin_adm']))
1176
1177 # select MF
1178 r = self._scc.select_path(['3f00'])
1179
1180 # write EF.ICCID
1181 data, sw = self._scc.update_binary('2fe2', enc_iccid(p['iccid']))
1182
1183 r = self._scc.select_path(['7ff0'])
1184
1185 # set Ki in proprietary file
1186 data, sw = self._scc.update_binary('FF02', p['ki'])
1187
1188 # set OPC in proprietary file
1189 data, sw = self._scc.update_binary('FF01', p['opc'])
1190
1191 # select DF_GSM
1192 r = self._scc.select_path(['7f20'])
1193
1194 # write EF.IMSI
1195 data, sw = self._scc.update_binary('6f07', enc_imsi(p['imsi']))
1196
1197
1198class WavemobileSim(UsimCard):
1199 """
1200 WavemobileSim
1201
1202 """
1203
1204 name = 'Wavemobile-SIM'
1205
1206 def __init__(self, ssc):
1207 super(WavemobileSim, self).__init__(ssc)
1208 self._adm_chv_num = 0x0A
1209 self._scc.cla_byte = "00"
1210 self._scc.sel_ctrl = "0004" # request an FCP
1211
1212 @classmethod
1213 def autodetect(kls, scc):
1214 try:
1215 # Look for ATR
1216 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"):
1217 return kls(scc)
1218 except:
1219 return None
1220 return None
1221
1222 def program(self, p):
1223 if not p['pin_adm']:
1224 raise ValueError(
1225 "Please provide a PIN-ADM as there is no default one")
1226 self.verify_adm(h2b(p['pin_adm']))
1227
1228 # EF.ICCID
1229 # TODO: Add programming of the ICCID
1230 if p.get('iccid'):
1231 print(
1232 "Warning: Programming of the ICCID is not implemented for this type of card.")
1233
1234 # KI (Presumably a proprietary file)
1235 # TODO: Add programming of KI
1236 if p.get('ki'):
1237 print(
1238 "Warning: Programming of the KI is not implemented for this type of card.")
1239
1240 # OPc (Presumably a proprietary file)
1241 # TODO: Add programming of OPc
1242 if p.get('opc'):
1243 print(
1244 "Warning: Programming of the OPc is not implemented for this type of card.")
1245
1246 # EF.SMSP
1247 if p.get('smsp'):
1248 sw = self.update_smsp(p['smsp'])
1249 if sw != '9000':
1250 print("Programming SMSP failed with code %s" % sw)
1251
1252 # EF.IMSI
1253 if p.get('imsi'):
1254 sw = self.update_imsi(p['imsi'])
1255 if sw != '9000':
1256 print("Programming IMSI failed with code %s" % sw)
1257
1258 # EF.ACC
1259 if p.get('acc'):
1260 sw = self.update_acc(p['acc'])
1261 if sw != '9000':
1262 print("Programming ACC failed with code %s" % sw)
1263
1264 # EF.PLMNsel
1265 if p.get('mcc') and p.get('mnc'):
1266 sw = self.update_plmnsel(p['mcc'], p['mnc'])
1267 if sw != '9000':
1268 print("Programming PLMNsel failed with code %s" % sw)
1269
1270 # EF.PLMNwAcT
1271 if p.get('mcc') and p.get('mnc'):
1272 sw = self.update_plmn_act(p['mcc'], p['mnc'])
1273 if sw != '9000':
1274 print("Programming PLMNwAcT failed with code %s" % sw)
1275
1276 # EF.OPLMNwAcT
1277 if p.get('mcc') and p.get('mnc'):
1278 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
1279 if sw != '9000':
1280 print("Programming OPLMNwAcT failed with code %s" % sw)
1281
1282 # EF.AD
1283 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
1284 if p.get('mcc') and p.get('mnc'):
1285 mnc = p['mnc']
1286 else:
1287 mnc = None
1288 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
1289 if sw != '9000':
1290 print("Programming AD failed with code %s" % sw)
1291
1292 return None
1293
1294
1295class SysmoISIMSJA2(UsimCard, IsimCard):
1296 """
1297 sysmocom sysmoISIM-SJA2
1298 """
1299
1300 name = 'sysmoISIM-SJA2'
1301
1302 def __init__(self, ssc):
1303 super(SysmoISIMSJA2, self).__init__(ssc)
1304 self._scc.cla_byte = "00"
1305 self._scc.sel_ctrl = "0004" # request an FCP
1306
1307 @classmethod
1308 def autodetect(kls, scc):
1309 try:
1310 # Try card model #1
1311 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9"
1312 if scc.get_atr() == toBytes(atr):
1313 return kls(scc)
1314
1315 # Try card model #2
1316 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2"
1317 if scc.get_atr() == toBytes(atr):
1318 return kls(scc)
1319
1320 # Try card model #3
1321 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"
1322 if scc.get_atr() == toBytes(atr):
1323 return kls(scc)
1324 except:
1325 return None
1326 return None
1327
1328 def verify_adm(self, key):
1329 # authenticate as ADM using default key (written on the card..)
1330 if not key:
1331 raise ValueError(
1332 "Please provide a PIN-ADM as there is no default one")
1333 (res, sw) = self._scc.verify_chv(0x0A, key)
1334 return sw
1335
1336 def program(self, p):
1337 self.verify_adm(h2b(p['pin_adm']))
1338
1339 # Populate AIDs
1340 self.read_aids()
1341
1342 # This type of card does not allow to reprogram the ICCID.
1343 # Reprogramming the ICCID would mess up the card os software
1344 # license management, so the ICCID must be kept at its factory
1345 # setting!
1346 if p.get('iccid'):
1347 print(
1348 "Warning: Programming of the ICCID is not implemented for this type of card.")
1349
1350 # select DF_GSM
1351 self._scc.select_path(['7f20'])
1352
1353 # set Service Provider Name
1354 if p.get('name') is not None:
1355 self.update_spn(p['name'], True, True)
1356
1357 # write EF.IMSI
1358 if p.get('imsi'):
1359 self._scc.update_binary('6f07', enc_imsi(p['imsi']))
1360
1361 # EF.PLMNsel
1362 if p.get('mcc') and p.get('mnc'):
1363 sw = self.update_plmnsel(p['mcc'], p['mnc'])
1364 if sw != '9000':
1365 print("Programming PLMNsel failed with code %s" % sw)
1366
1367 # EF.PLMNwAcT
1368 if p.get('mcc') and p.get('mnc'):
1369 sw = self.update_plmn_act(p['mcc'], p['mnc'])
1370 if sw != '9000':
1371 print("Programming PLMNwAcT failed with code %s" % sw)
1372
1373 # EF.OPLMNwAcT
1374 if p.get('mcc') and p.get('mnc'):
1375 sw = self.update_oplmn_act(p['mcc'], p['mnc'])
1376 if sw != '9000':
1377 print("Programming OPLMNwAcT failed with code %s" % sw)
1378
1379 # EF.HPLMNwAcT
1380 if p.get('mcc') and p.get('mnc'):
1381 sw = self.update_hplmn_act(p['mcc'], p['mnc'])
1382 if sw != '9000':
1383 print("Programming HPLMNwAcT failed with code %s" % sw)
1384
1385 # EF.AD
1386 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
1387 if p.get('mcc') and p.get('mnc'):
1388 mnc = p['mnc']
1389 else:
1390 mnc = None
1391 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'))
1392 if sw != '9000':
1393 print("Programming AD failed with code %s" % sw)
1394
1395 # EF.SMSP
1396 if p.get('smsp'):
1397 r = self._scc.select_path(['3f00', '7f10'])
1398 data, sw = self._scc.update_record(
1399 '6f42', 1, lpad(p['smsp'], 104), force_len=True)
1400
1401 # EF.MSISDN
1402 # TODO: Alpha Identifier (currently 'ff'O * 20)
1403 # TODO: Capability/Configuration1 Record Identifier
1404 # TODO: Extension1 Record Identifier
1405 if p.get('msisdn') is not None:
1406 msisdn = enc_msisdn(p['msisdn'])
1407 content = 'ff' * 20 + msisdn
1408
1409 r = self._scc.select_path(['3f00', '7f10'])
1410 data, sw = self._scc.update_record(
1411 '6F40', 1, content, force_len=True)
1412
1413 # EF.ACC
1414 if p.get('acc'):
1415 sw = self.update_acc(p['acc'])
1416 if sw != '9000':
1417 print("Programming ACC failed with code %s" % sw)
1418
1419 # update EF-SIM_AUTH_KEY (and EF-USIM_AUTH_KEY_2G, which is
1420 # hard linked to EF-USIM_AUTH_KEY)
1421 self._scc.select_path(['3f00'])
1422 self._scc.select_path(['a515'])
1423 if p.get('ki'):
1424 self._scc.update_binary('6f20', p['ki'], 1)
1425 if p.get('opc'):
1426 self._scc.update_binary('6f20', p['opc'], 17)
1427
1428 # update EF-USIM_AUTH_KEY in ADF.ISIM
1429 if self.adf_present("isim"):
1430 self.select_adf_by_aid(adf="isim")
1431
1432 if p.get('ki'):
1433 self._scc.update_binary('af20', p['ki'], 1)
1434 if p.get('opc'):
1435 self._scc.update_binary('af20', p['opc'], 17)
1436
1437 # update EF.P-CSCF in ADF.ISIM
1438 if self.file_exists(EF_ISIM_ADF_map['PCSCF']):
1439 if p.get('pcscf'):
1440 sw = self.update_pcscf(p['pcscf'])
1441 else:
1442 sw = self.update_pcscf("")
1443 if sw != '9000':
1444 print("Programming P-CSCF failed with code %s" % sw)
1445
1446 # update EF.DOMAIN in ADF.ISIM
1447 if self.file_exists(EF_ISIM_ADF_map['DOMAIN']):
1448 if p.get('ims_hdomain'):
1449 sw = self.update_domain(domain=p['ims_hdomain'])
1450 else:
1451 sw = self.update_domain()
1452
1453 if sw != '9000':
1454 print(
1455 "Programming Home Network Domain Name failed with code %s" % sw)
1456
1457 # update EF.IMPI in ADF.ISIM
1458 # TODO: Validate IMPI input
1459 if self.file_exists(EF_ISIM_ADF_map['IMPI']):
1460 if p.get('impi'):
1461 sw = self.update_impi(p['impi'])
1462 else:
1463 sw = self.update_impi()
1464 if sw != '9000':
1465 print("Programming IMPI failed with code %s" % sw)
1466
1467 # update EF.IMPU in ADF.ISIM
1468 # TODO: Validate IMPU input
1469 # Support multiple IMPU if there is enough space
1470 if self.file_exists(EF_ISIM_ADF_map['IMPU']):
1471 if p.get('impu'):
1472 sw = self.update_impu(p['impu'])
1473 else:
1474 sw = self.update_impu()
1475 if sw != '9000':
1476 print("Programming IMPU failed with code %s" % sw)
1477
1478 if self.adf_present("usim"):
1479 self.select_adf_by_aid(adf="usim")
1480
1481 # EF.AD in ADF.USIM
1482 if (p.get('mcc') and p.get('mnc')) or p.get('opmode'):
1483 if p.get('mcc') and p.get('mnc'):
1484 mnc = p['mnc']
1485 else:
1486 mnc = None
1487 sw = self.update_ad(mnc=mnc, opmode=p.get('opmode'),
1488 path=EF_USIM_ADF_map['AD'])
1489 if sw != '9000':
1490 print("Programming AD failed with code %s" % sw)
1491
1492 # update EF-USIM_AUTH_KEY in ADF.USIM
1493 if p.get('ki'):
1494 self._scc.update_binary('af20', p['ki'], 1)
1495 if p.get('opc'):
1496 self._scc.update_binary('af20', p['opc'], 17)
1497
1498 # update EF.EHPLMN in ADF.USIM
1499 if self.file_exists(EF_USIM_ADF_map['EHPLMN']):
1500 if p.get('mcc') and p.get('mnc'):
1501 sw = self.update_ehplmn(p['mcc'], p['mnc'])
1502 if sw != '9000':
1503 print("Programming EHPLMN failed with code %s" % sw)
1504
1505 # update EF.ePDGId in ADF.USIM
1506 if self.file_exists(EF_USIM_ADF_map['ePDGId']):
1507 if p.get('epdgid'):
1508 sw = self.update_epdgid(p['epdgid'])
1509 else:
1510 sw = self.update_epdgid("")
1511 if sw != '9000':
1512 print("Programming ePDGId failed with code %s" % sw)
1513
1514 # update EF.ePDGSelection in ADF.USIM
1515 if self.file_exists(EF_USIM_ADF_map['ePDGSelection']):
1516 if p.get('epdgSelection'):
1517 epdg_plmn = p['epdgSelection']
1518 sw = self.update_ePDGSelection(
1519 epdg_plmn[:3], epdg_plmn[3:])
1520 else:
1521 sw = self.update_ePDGSelection("", "")
1522 if sw != '9000':
1523 print("Programming ePDGSelection failed with code %s" % sw)
1524
1525 # After successfully programming EF.ePDGId and EF.ePDGSelection,
1526 # Set service 106 and 107 as available in EF.UST
1527 # Disable service 95, 99, 115 if ISIM application is present
1528 if self.file_exists(EF_USIM_ADF_map['UST']):
1529 if p.get('epdgSelection') and p.get('epdgid'):
1530 sw = self.update_ust(106, 1)
1531 if sw != '9000':
1532 print("Programming UST failed with code %s" % sw)
1533 sw = self.update_ust(107, 1)
1534 if sw != '9000':
1535 print("Programming UST failed with code %s" % sw)
1536
1537 sw = self.update_ust(95, 0)
1538 if sw != '9000':
1539 print("Programming UST failed with code %s" % sw)
1540 sw = self.update_ust(99, 0)
1541 if sw != '9000':
1542 print("Programming UST failed with code %s" % sw)
1543 sw = self.update_ust(115, 0)
1544 if sw != '9000':
1545 print("Programming UST failed with code %s" % sw)
1546
1547 return
1548
1549class SysmoISIMSJA5(SysmoISIMSJA2):
1550 """
1551 sysmocom sysmoISIM-SJA5
1552 """
1553
1554 name = 'sysmoISIM-SJA5'
1555
1556 @classmethod
1557 def autodetect(kls, scc):
1558 try:
1559 # Try card model #1 (9FJ)
1560 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 51 CC"
1561 if scc.get_atr() == toBytes(atr):
1562 return kls(scc)
1563 # Try card model #2 (SLM17)
1564 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 65 F8"
1565 if scc.get_atr() == toBytes(atr):
1566 return kls(scc)
1567 # Try card model #3 (9FV)
1568 atr = "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 59 C4"
1569 if scc.get_atr() == toBytes(atr):
1570 return kls(scc)
1571 except:
1572 return None
1573 return None
1574
1575
1576class GialerSim(UsimCard):
1577 """
1578 Gialer sim cards (www.gialer.com).
1579 """
1580 name = 'gialersim'
1581
1582 def __init__(self, ssc):
1583 super().__init__(ssc)
1584 self._program_handlers = {
1585 'iccid': self.update_iccid,
1586 'imsi': self.update_imsi,
1587 'acc': self.update_acc,
1588 'smsp': self.update_smsp,
1589 'ki': self.update_ki,
1590 'opc': self.update_opc,
1591 'fplmn': self.update_fplmn,
1592 }
1593
1594 @classmethod
1595 def autodetect(cls, scc):
1596 try:
1597 # Look for ATR
1598 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'):
1599 return cls(scc)
1600 except:
1601 return None
1602 return None
1603
1604 def program(self, p):
1605 self.set_apdu_parameter('00', '0004')
1606 # Authenticate
1607 self._scc.verify_chv(0xc, h2b('3834373936313533'))
1608 for handler in self._program_handlers:
1609 if p.get(handler) is not None:
1610 self._program_handlers[handler](p[handler])
1611
1612 mcc = p.get('mcc')
1613 mnc = p.get('mnc')
1614 has_plmn = mcc is not None and mnc is not None
1615 # EF.HPLMN
1616 if has_plmn:
1617 self.update_hplmn_act(mcc, mnc)
1618
1619 # EF.AD
1620 if has_plmn or (p.get('opmode') is not None):
1621 self.update_ad(mnc=mnc, opmode=p.get('opmode'))
1622
1623 def update_smsp(self, smsp):
1624 data, sw = self._scc.update_record(EF['SMSP'], 1, rpad(smsp, 80))
1625 return sw
1626
1627 def update_ki(self, ki):
1628 self._scc.select_path(['3f00', '0001'])
1629 self._scc.update_binary('0001', ki)
1630
1631 def update_opc(self, opc):
1632 self._scc.select_path(['3f00', '6002'])
1633 # No idea why the '01' is required
1634 self._scc.update_binary('6002', '01' + opc)
1635
1636
1637# In order for autodetection ...
1638_cards_classes = [FakeMagicSim, SuperSim, MagicSim, GrcardSim,
1639 SysmoSIMgr1, SysmoSIMgr2, SysmoUSIMgr1, SysmoUSIMSJS1,
1640 FairwavesSIM, OpenCellsSim, WavemobileSim, SysmoISIMSJA2,
1641 SysmoISIMSJA5, GialerSim]
1642
1643
1644def card_detect(ctype, scc):
1645 # Detect type if needed
1646 card = None
1647 ctypes = dict([(kls.name, kls) for kls in _cards_classes])
1648
1649 if ctype == "auto":
1650 for kls in _cards_classes:
1651 card = kls.autodetect(scc)
1652 if card:
1653 print("Autodetected card type: %s" % card.name)
1654 card.reset()
1655 break
1656
1657 if card is None:
1658 print("Autodetection failed")
1659 return None
1660
1661 elif ctype in ctypes:
1662 card = ctypes[ctype](scc)
1663
1664 else:
1665 raise ValueError("Unknown card type: %s" % ctype)
1666
1667 return card