mirror of https://gerrit.osmocom.org/pysim
pySim/cards: Split legacy classes away from core SIM + UICC
This introduces an internal split between * the code that is shared between pySim-shell and legacy tools, which is now in the new class hierarchy {Card,SimCard,UiccCard}Base * the code that is only used by legacy tools, which is using the old class names inherited from the *Base above All users still go through the legacy {Sim,Usim,Isim}Card classes, they will be adjusted in subsequent patches. Change-Id: Id36140675def5fc44eedce81fc7b09e0adc527e1
This commit is contained in:
parent
02a7f7441f
commit
263fb0871c
149
pySim/cards.py
149
pySim/cards.py
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
|
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
|
||||||
# Copyright (C) 2011 Harald Welte <laforge@gnumonks.org>
|
# Copyright (C) 2011-2023 Harald Welte <laforge@gnumonks.org>
|
||||||
# Copyright (C) 2017 Alexander.Chemeris <Alexander.Chemeris@gmail.com>
|
# Copyright (C) 2017 Alexander.Chemeris <Alexander.Chemeris@gmail.com>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
@ -25,13 +25,81 @@
|
||||||
from typing import Optional, Dict, Tuple
|
from typing import Optional, Dict, Tuple
|
||||||
import abc
|
import abc
|
||||||
|
|
||||||
from pySim.ts_51_011 import EF, DF, EF_AD, EF_SPN
|
|
||||||
from pySim.ts_31_102 import EF_USIM_ADF_map
|
|
||||||
from pySim.ts_31_103 import EF_ISIM_ADF_map
|
|
||||||
from pySim.utils import *
|
from pySim.utils import *
|
||||||
|
|
||||||
|
class CardBase:
|
||||||
|
"""General base class for some kind of telecommunications card."""
|
||||||
|
def __init__(self, scc):
|
||||||
|
self._scc = scc
|
||||||
|
self._aids = []
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
rc = self._scc.reset_card()
|
||||||
|
if rc == 1:
|
||||||
|
return self._scc.get_atr()
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_apdu_parameter(self, cla, sel_ctrl):
|
||||||
|
"""Set apdu parameters (class byte and selection control bytes)"""
|
||||||
|
self._scc.cla_byte = cla
|
||||||
|
self._scc.sel_ctrl = sel_ctrl
|
||||||
|
|
||||||
|
def get_apdu_parameter(self):
|
||||||
|
"""Get apdu parameters (class byte and selection control bytes)"""
|
||||||
|
return (self._scc.cla_byte, self._scc.sel_ctrl)
|
||||||
|
|
||||||
|
def erase(self):
|
||||||
|
print("warning: erasing is not supported for specified card type!")
|
||||||
|
return
|
||||||
|
|
||||||
|
def file_exists(self, fid):
|
||||||
|
res_arr = self._scc.try_select_path(fid)
|
||||||
|
for res in res_arr:
|
||||||
|
if res[1] != '9000':
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def read_aids(self):
|
||||||
|
# a non-UICC doesn't have any applications. Convenience helper to avoid
|
||||||
|
# callers having to do hasattr('read_aids') ahead of every call.
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class SimCardBase(CardBase):
|
||||||
|
|
||||||
|
"""Here we only add methods for commands specified in TS 51.011, without
|
||||||
|
any higher-layer processing."""
|
||||||
|
|
||||||
|
name = 'SIM'
|
||||||
|
|
||||||
|
def read_binary(self, ef, length=None, offset=0):
|
||||||
|
ef_path = ef in EF and EF[ef] or ef
|
||||||
|
return self._scc.read_binary(ef_path, length, offset)
|
||||||
|
|
||||||
|
def read_record(self, ef, rec_no):
|
||||||
|
ef_path = ef in EF and EF[ef] or ef
|
||||||
|
return self._scc.read_record(ef_path, rec_no)
|
||||||
|
|
||||||
|
|
||||||
|
class UiccCardBase(SimCardBase):
|
||||||
|
name = 'UICC'
|
||||||
|
|
||||||
|
def __init__(self, ssc):
|
||||||
|
super(UiccCardBase, self).__init__(ssc)
|
||||||
|
# See also: ETSI TS 102 221, Table 9.3
|
||||||
|
self._adm_chv_num = 0xA0
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# LEGACY
|
||||||
|
################################################################################
|
||||||
|
|
||||||
from smartcard.util import toBytes
|
from smartcard.util import toBytes
|
||||||
from pytlv.TLV import *
|
from pytlv.TLV import *
|
||||||
|
|
||||||
|
from pySim.ts_51_011 import EF, DF, EF_AD, EF_SPN
|
||||||
|
from pySim.ts_31_102 import EF_USIM_ADF_map
|
||||||
|
from pySim.ts_31_103 import EF_ISIM_ADF_map
|
||||||
|
|
||||||
def format_addr(addr: str, addr_type: str) -> str:
|
def format_addr(addr: str, addr_type: str) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -52,32 +120,13 @@ def format_addr(addr: str, addr_type: str) -> str:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
class SimCard:
|
|
||||||
|
|
||||||
name = 'SIM'
|
class SimCard(SimCardBase):
|
||||||
|
"""Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
|
||||||
|
|
||||||
def __init__(self, scc):
|
def __init__(self, scc):
|
||||||
self._scc = scc
|
|
||||||
self._adm_chv_num = 4
|
self._adm_chv_num = 4
|
||||||
self._aids = []
|
super().__init__(scc)
|
||||||
|
|
||||||
def reset(self):
|
|
||||||
rc = self._scc.reset_card()
|
|
||||||
if rc == 1:
|
|
||||||
return self._scc.get_atr()
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
def erase(self):
|
|
||||||
print("warning: erasing is not supported for specified card type!")
|
|
||||||
return
|
|
||||||
|
|
||||||
def file_exists(self, fid):
|
|
||||||
res_arr = self._scc.try_select_path(fid)
|
|
||||||
for res in res_arr:
|
|
||||||
if res[1] != '9000':
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def verify_adm(self, key):
|
def verify_adm(self, key):
|
||||||
"""Authenticate with ADM key"""
|
"""Authenticate with ADM key"""
|
||||||
|
@ -252,14 +301,6 @@ class SimCard:
|
||||||
data, sw = self._scc.update_binary(EF['SPN'], content)
|
data, sw = self._scc.update_binary(EF['SPN'], content)
|
||||||
return sw
|
return sw
|
||||||
|
|
||||||
def read_binary(self, ef, length=None, offset=0):
|
|
||||||
ef_path = ef in EF and EF[ef] or ef
|
|
||||||
return self._scc.read_binary(ef_path, length, offset)
|
|
||||||
|
|
||||||
def read_record(self, ef, rec_no):
|
|
||||||
ef_path = ef in EF and EF[ef] or ef
|
|
||||||
return self._scc.read_record(ef_path, rec_no)
|
|
||||||
|
|
||||||
def read_gid1(self):
|
def read_gid1(self):
|
||||||
(res, sw) = self._scc.read_binary(EF['GID1'])
|
(res, sw) = self._scc.read_binary(EF['GID1'])
|
||||||
if sw == '9000':
|
if sw == '9000':
|
||||||
|
@ -274,6 +315,10 @@ class SimCard:
|
||||||
else:
|
else:
|
||||||
return (None, sw)
|
return (None, sw)
|
||||||
|
|
||||||
|
|
||||||
|
class UsimCard(UiccCardBase, SimCard):
|
||||||
|
"""Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
|
||||||
|
|
||||||
def read_aids(self):
|
def read_aids(self):
|
||||||
"""Fetch all the AIDs present on UICC"""
|
"""Fetch all the AIDs present on UICC"""
|
||||||
self._aids = []
|
self._aids = []
|
||||||
|
@ -335,36 +380,6 @@ class SimCard:
|
||||||
return self._scc.select_adf(aid)
|
return self._scc.select_adf(aid)
|
||||||
return (None, None)
|
return (None, None)
|
||||||
|
|
||||||
def erase_binary(self, ef):
|
|
||||||
"""Erase the contents of a file"""
|
|
||||||
len = self._scc.binary_size(ef)
|
|
||||||
self._scc.update_binary(ef, "ff" * len, offset=0, verify=True)
|
|
||||||
|
|
||||||
def erase_record(self, ef, rec_no):
|
|
||||||
"""Erase the contents of a single record"""
|
|
||||||
len = self._scc.record_size(ef)
|
|
||||||
self._scc.update_record(ef, rec_no, "ff" * len,
|
|
||||||
force_len=False, verify=True)
|
|
||||||
|
|
||||||
def set_apdu_parameter(self, cla, sel_ctrl):
|
|
||||||
"""Set apdu parameters (class byte and selection control bytes)"""
|
|
||||||
self._scc.cla_byte = cla
|
|
||||||
self._scc.sel_ctrl = sel_ctrl
|
|
||||||
|
|
||||||
def get_apdu_parameter(self):
|
|
||||||
"""Get apdu parameters (class byte and selection control bytes)"""
|
|
||||||
return (self._scc.cla_byte, self._scc.sel_ctrl)
|
|
||||||
|
|
||||||
|
|
||||||
class UsimCard(SimCard):
|
|
||||||
|
|
||||||
name = 'USIM'
|
|
||||||
|
|
||||||
def __init__(self, ssc):
|
|
||||||
super(UsimCard, self).__init__(ssc)
|
|
||||||
|
|
||||||
# See also: ETSI TS 102 221, Table 9.3
|
|
||||||
self._adm_chv_num = 0xA0
|
|
||||||
|
|
||||||
def read_ehplmn(self):
|
def read_ehplmn(self):
|
||||||
(res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'])
|
(res, sw) = self._scc.read_binary(EF_USIM_ADF_map['EHPLMN'])
|
||||||
|
@ -469,13 +484,11 @@ class UsimCard(SimCard):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IsimCard(SimCard):
|
class IsimCard(UiccCardBase):
|
||||||
|
"""Higher-layer class that is used *only* by legacy pySim-{prog,read}."""
|
||||||
|
|
||||||
name = 'ISIM'
|
name = 'ISIM'
|
||||||
|
|
||||||
def __init__(self, ssc):
|
|
||||||
super(IsimCard, self).__init__(ssc)
|
|
||||||
|
|
||||||
def read_pcscf(self):
|
def read_pcscf(self):
|
||||||
rec_cnt = self._scc.record_count(EF_ISIM_ADF_map['PCSCF'])
|
rec_cnt = self._scc.record_count(EF_ISIM_ADF_map['PCSCF'])
|
||||||
pcscf_recs = ""
|
pcscf_recs = ""
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
Using PC/SC reader interface
|
Using PC/SC reader interface
|
||||||
Reading ...
|
Reading ...
|
||||||
Autodetected card type: fakemagicsim
|
Autodetected card type: fakemagicsim
|
||||||
Can't read AIDs from SIM -- SW match failed! Expected 9000 and got 9404.
|
|
||||||
ICCID: 1122334455667788990
|
ICCID: 1122334455667788990
|
||||||
IMSI: 001010000000102
|
IMSI: 001010000000102
|
||||||
GID1: Can't read file -- SW match failed! Expected 9000 and got 9404.
|
GID1: Can't read file -- SW match failed! Expected 9000 and got 9404.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
Using PC/SC reader interface
|
Using PC/SC reader interface
|
||||||
Reading ...
|
Reading ...
|
||||||
Autodetected card type: sysmosim-gr1
|
Autodetected card type: sysmosim-gr1
|
||||||
Can't read AIDs from SIM -- SW match failed! Expected 9000 and got 9404.
|
|
||||||
ICCID: 1122334455667788990
|
ICCID: 1122334455667788990
|
||||||
IMSI: 001010000000102
|
IMSI: 001010000000102
|
||||||
GID1: Can't read file -- SW match failed! Expected 9000 and got 9404.
|
GID1: Can't read file -- SW match failed! Expected 9000 and got 9404.
|
||||||
|
|
Loading…
Reference in New Issue