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