mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-31 11:27:41 +03:00
pySim.profile: Further refactor card <-> profile matching
The new architecture avoids sim/ruim/uicc specific methods in pySim.profile and instead moves the profile-specific code into the profile; it also solves everything within the class hierarchy, no need for global methods. Change-Id: I3b6c44d2f5cce2513c3ec8a3ce939a242f3e4901
This commit is contained in:
@@ -24,7 +24,6 @@ from osmocom.utils import *
|
|||||||
from osmocom.construct import *
|
from osmocom.construct import *
|
||||||
|
|
||||||
from pySim.filesystem import *
|
from pySim.filesystem import *
|
||||||
from pySim.profile import match_ruim
|
|
||||||
from pySim.profile import CardProfile, CardProfileAddon
|
from pySim.profile import CardProfile, CardProfileAddon
|
||||||
from pySim.ts_51_011 import CardProfileSIM
|
from pySim.ts_51_011 import CardProfileSIM
|
||||||
from pySim.ts_51_011 import DF_TELECOM, DF_GSM
|
from pySim.ts_51_011 import DF_TELECOM, DF_GSM
|
||||||
@@ -191,8 +190,11 @@ class CardProfileRUIM(CardProfile):
|
|||||||
return CardProfileSIM.decode_select_response(data_hex)
|
return CardProfileSIM.decode_select_response(data_hex)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def match_with_card(cls, scc: SimCardCommands) -> bool:
|
def _try_match_card(cls, scc: SimCardCommands) -> None:
|
||||||
return match_ruim(scc)
|
""" Try to access MF/DF.CDMA via 2G APDUs (3GPP TS 11.11), if this works,
|
||||||
|
the card is considered an R-UIM card for CDMA."""
|
||||||
|
cls._mf_select_test(scc, "a0", "0000", ["3f00", "7f25"])
|
||||||
|
|
||||||
|
|
||||||
class AddonRUIM(CardProfileAddon):
|
class AddonRUIM(CardProfileAddon):
|
||||||
"""An Addon that can be found on on a combined SIM + RUIM or UICC + RUIM to support CDMA."""
|
"""An Addon that can be found on on a combined SIM + RUIM or UICC + RUIM to support CDMA."""
|
||||||
|
|||||||
@@ -25,54 +25,11 @@ import abc
|
|||||||
import operator
|
import operator
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from pySim.exceptions import SwMatchError
|
||||||
from pySim.commands import SimCardCommands
|
from pySim.commands import SimCardCommands
|
||||||
from pySim.filesystem import CardApplication, interpret_sw
|
from pySim.filesystem import CardApplication, interpret_sw
|
||||||
from pySim.utils import all_subclasses
|
from pySim.utils import all_subclasses
|
||||||
|
|
||||||
def _mf_select_test(scc: SimCardCommands,
|
|
||||||
cla_byte: str, sel_ctrl: str,
|
|
||||||
fids: List[str]) -> bool:
|
|
||||||
cla_byte_bak = scc.cla_byte
|
|
||||||
sel_ctrl_bak = scc.sel_ctrl
|
|
||||||
scc.reset_card()
|
|
||||||
|
|
||||||
scc.cla_byte = cla_byte
|
|
||||||
scc.sel_ctrl = sel_ctrl
|
|
||||||
rc = True
|
|
||||||
try:
|
|
||||||
for fid in fids:
|
|
||||||
scc.select_file(fid)
|
|
||||||
except:
|
|
||||||
rc = False
|
|
||||||
|
|
||||||
scc.reset_card()
|
|
||||||
scc.cla_byte = cla_byte_bak
|
|
||||||
scc.sel_ctrl = sel_ctrl_bak
|
|
||||||
return rc
|
|
||||||
|
|
||||||
|
|
||||||
def match_uicc(scc: SimCardCommands) -> bool:
|
|
||||||
""" Try to access MF via UICC APDUs (3GPP TS 102.221), if this works, the
|
|
||||||
card is considered a UICC card.
|
|
||||||
"""
|
|
||||||
return _mf_select_test(scc, "00", "0004", ["3f00"])
|
|
||||||
|
|
||||||
|
|
||||||
def match_sim(scc: SimCardCommands) -> bool:
|
|
||||||
""" Try to access MF via 2G APDUs (3GPP TS 11.11), if this works, the card
|
|
||||||
is also a simcard. This will be the case for most UICC cards, but there may
|
|
||||||
also be plain UICC cards without 2G support as well.
|
|
||||||
"""
|
|
||||||
return _mf_select_test(scc, "a0", "0000", ["3f00"])
|
|
||||||
|
|
||||||
|
|
||||||
def match_ruim(scc: SimCardCommands) -> bool:
|
|
||||||
""" Try to access MF/DF.CDMA via 2G APDUs (3GPP TS 11.11), if this works,
|
|
||||||
the card is considered an R-UIM card for CDMA.
|
|
||||||
"""
|
|
||||||
return _mf_select_test(scc, "a0", "0000", ["3f00", "7f25"])
|
|
||||||
|
|
||||||
|
|
||||||
class CardProfile:
|
class CardProfile:
|
||||||
"""A Card Profile describes a card, it's filesystem hierarchy, an [initial] list of
|
"""A Card Profile describes a card, it's filesystem hierarchy, an [initial] list of
|
||||||
applications as well as profile-specific SW and shell commands. Every card has
|
applications as well as profile-specific SW and shell commands. Every card has
|
||||||
@@ -137,14 +94,40 @@ class CardProfile:
|
|||||||
"""
|
"""
|
||||||
return data_hex
|
return data_hex
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _mf_select_test(scc: SimCardCommands,
|
||||||
|
cla_byte: str, sel_ctrl: str,
|
||||||
|
fids: List[str]) -> bool:
|
||||||
|
"""Helper function used by some derived _try_match_card() methods."""
|
||||||
|
scc.reset_card()
|
||||||
|
|
||||||
|
scc.cla_byte = cla_byte
|
||||||
|
scc.sel_ctrl = sel_ctrl
|
||||||
|
for fid in fids:
|
||||||
|
scc.select_file(fid)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def match_with_card(cls, scc: SimCardCommands) -> bool:
|
def _try_match_card(cls, scc: SimCardCommands) -> None:
|
||||||
"""Check if the specific profile matches the card. This method is a
|
"""Try to see if the specific profile matches the card. This method is a
|
||||||
placeholder that is overloaded by specific dirived classes. The method
|
placeholder that is overloaded by specific dirived classes. The method
|
||||||
actively probes the card to make sure the profile class matches the
|
actively probes the card to make sure the profile class matches the
|
||||||
physical card. This usually also means that the card is reset during
|
physical card. This usually also means that the card is reset during
|
||||||
the process, so this method must not be called at random times. It may
|
the process, so this method must not be called at random times. It may
|
||||||
|
only be called on startup. If there is no exception raised, we assume
|
||||||
|
the card matches the profile.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
scc: SimCardCommands class
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def match_with_card(cls, scc: SimCardCommands) -> bool:
|
||||||
|
"""Check if the specific profile matches the card. The method
|
||||||
|
actively probes the card to make sure the profile class matches the
|
||||||
|
physical card. This usually also means that the card is reset during
|
||||||
|
the process, so this method must not be called at random times. It may
|
||||||
only be called on startup.
|
only be called on startup.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -152,7 +135,17 @@ class CardProfile:
|
|||||||
Returns:
|
Returns:
|
||||||
match = True, no match = False
|
match = True, no match = False
|
||||||
"""
|
"""
|
||||||
return False
|
sel_backup = scc.sel_ctrl
|
||||||
|
cla_backup = scc.cla_byte
|
||||||
|
try:
|
||||||
|
cls._try_match_card(scc)
|
||||||
|
return True
|
||||||
|
except SwMatchError:
|
||||||
|
return False
|
||||||
|
finally:
|
||||||
|
scc.sel_ctrl = sel_backup
|
||||||
|
scc.cla_byte = cla_backup
|
||||||
|
scc.reset_card()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pick(scc: SimCardCommands):
|
def pick(scc: SimCardCommands):
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ from osmocom.tlv import *
|
|||||||
from pySim.utils import *
|
from pySim.utils import *
|
||||||
from pySim.filesystem import *
|
from pySim.filesystem import *
|
||||||
from pySim.profile import CardProfile
|
from pySim.profile import CardProfile
|
||||||
from pySim.profile import match_uicc
|
|
||||||
from pySim import iso7816_4
|
from pySim import iso7816_4
|
||||||
|
|
||||||
# A UICC will usually also support 2G functionality. If this is the case, we
|
# A UICC will usually also support 2G functionality. If this is the case, we
|
||||||
@@ -885,8 +884,10 @@ class CardProfileUICC(CardProfile):
|
|||||||
return flatten_dict_lists(d['fcp_template'])
|
return flatten_dict_lists(d['fcp_template'])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def match_with_card(cls, scc: SimCardCommands) -> bool:
|
def _try_match_card(cls, scc: SimCardCommands) -> None:
|
||||||
return match_uicc(scc)
|
""" Try to access MF via UICC APDUs (3GPP TS 102.221), if this works, the
|
||||||
|
card is considered a UICC card."""
|
||||||
|
cls._mf_select_test(scc, "00", "0004", ["3f00"])
|
||||||
|
|
||||||
@with_default_category('TS 102 221 Specific Commands')
|
@with_default_category('TS 102 221 Specific Commands')
|
||||||
class AddlShellCommands(CommandSet):
|
class AddlShellCommands(CommandSet):
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ from osmocom.construct import *
|
|||||||
|
|
||||||
from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_plmn, enc_plmn, dec_xplmn_w_act
|
from pySim.utils import dec_iccid, enc_iccid, dec_imsi, enc_imsi, dec_plmn, enc_plmn, dec_xplmn_w_act
|
||||||
from pySim.utils import dec_msisdn, enc_msisdn
|
from pySim.utils import dec_msisdn, enc_msisdn
|
||||||
from pySim.profile import match_sim
|
|
||||||
from pySim.profile import CardProfile, CardProfileAddon
|
from pySim.profile import CardProfile, CardProfileAddon
|
||||||
from pySim.filesystem import *
|
from pySim.filesystem import *
|
||||||
from pySim.ts_31_102_telecom import DF_PHONEBOOK, DF_MULTIMEDIA, DF_MCS, DF_V2X
|
from pySim.ts_31_102_telecom import DF_PHONEBOOK, DF_MULTIMEDIA, DF_MCS, DF_V2X
|
||||||
@@ -1193,8 +1192,8 @@ class CardProfileSIM(CardProfile):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def match_with_card(cls, scc: SimCardCommands) -> bool:
|
def _try_match_card(cls, scc: SimCardCommands) -> None:
|
||||||
return match_sim(scc)
|
cls._mf_select_test(scc, "a0", "0000", ["3f00"])
|
||||||
|
|
||||||
|
|
||||||
class AddonSIM(CardProfileAddon):
|
class AddonSIM(CardProfileAddon):
|
||||||
|
|||||||
Reference in New Issue
Block a user