This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
dexter gerrit-no-reply at lists.osmocom.orgdexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/26165 ) Change subject: pySim-shell: add method to match card profile to card ...................................................................... pySim-shell: add method to match card profile to card UICC and old SIM cards can be difficult to tell apart without prior knowledge of the card. The ATR won't tell if the card is UICC or not. The only remaining option is to try out if the card is able to handle UICC APDUs. The same is true for 2G SIM cards. It is not guranteed that every UICC card will have 2G functionality. Lets add functionality to match a profile to the currently plugged card by actively probing it. Lets also add another profile to distinguish between UICC-only cards and UICC cards that include SIM functionality. Change-Id: If090d32551145f75c644657b90085a3ef5bfa691 Related: OS#5274 --- M pySim-shell.py M pySim/filesystem.py A pySim/profile.py M pySim/ts_102_221.py M pySim/ts_51_011.py 5 files changed, 167 insertions(+), 7 deletions(-) git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/65/26165/1 diff --git a/pySim-shell.py b/pySim-shell.py index 0be6f21..7941329 100755 --- a/pySim-shell.py +++ b/pySim-shell.py @@ -47,6 +47,7 @@ from pySim.filesystem import CardMF, RuntimeState, CardDF, CardADF, CardModel from pySim.ts_51_011 import CardProfileSIM, DF_TELECOM, DF_GSM from pySim.ts_102_221 import CardProfileUICC +from pySim.ts_102_221 import CardProfileUICCSIM from pySim.ts_31_102 import CardApplicationUSIM from pySim.ts_31_103 import CardApplicationISIM from pySim.gsm_r import DF_EIRENE @@ -58,6 +59,8 @@ from pySim.card_key_provider import CardKeyProviderCsv, card_key_provider_register, card_key_provider_get_field +from pySim.profile import profile_detect + def init_card(sl): """ Detect card in reader and setup card profile and runtime state. This @@ -79,18 +82,31 @@ card = card_detect("auto", scc) if card is None: - print("Could not detect card type!") + print("Warning: Could not detect card type - assuming a generic card type...") + card = SimCard(scc) + + profile = profile_detect(scc) + if profile is None: + print("Unsupported card type!") return None, None + print("Info: Card is of type: %s" % str(profile)) + + # FIXME: This shouln't be here, the profile should add the applications, + # however, we cannot simply put his into ts_102_221.py since we would + # have to e.g. import CardApplicationUSIM from ts_31_102.py, which already + # imports from ts_102_221.py. This means we will end up with a circular + # import, which needs to be resolved first. + if type(profile) is CardProfileUICC or type(profile) is CardProfileUICCSIM: + profile.add_application(CardApplicationUSIM()) + profile.add_application(CardApplicationISIM()) + # Create runtime state with card profile - profile = CardProfileUICC() - profile.add_application(CardApplicationUSIM()) - profile.add_application(CardApplicationISIM()) rs = RuntimeState(card, profile) - # FIXME: do this dynamically - rs.mf.add_file(DF_TELECOM()) - rs.mf.add_file(DF_GSM()) + # FIXME: This is an GSM-R related file, it needs to be added throught, + # the profile. At the moment we add it for all cards, this won't hurt, + # but regular SIM and UICC will not have it and fail to select it. rs.mf.add_file(DF_EIRENE()) CardModel.apply_matching_models(scc, rs) diff --git a/pySim/filesystem.py b/pySim/filesystem.py index 75cd210..df99bc7 100644 --- a/pySim/filesystem.py +++ b/pySim/filesystem.py @@ -1505,6 +1505,21 @@ """ return data_hex + @staticmethod + def match_witch_card(scc:SimCardCommands) -> bool: + """Check if the specific profile matches the card. This method is a + placeholder that is overloaded by specific dirived classes. 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. + + Args: + scc: SimCardCommands class + Returns: + match = True, no match = False + """ + return False class CardModel(abc.ABC): """A specific card model, typically having some additional vendor-specific files. All diff --git a/pySim/profile.py b/pySim/profile.py new file mode 100644 index 0000000..78f5e23 --- /dev/null +++ b/pySim/profile.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +""" pySim: tell old 2G SIMs apart from UICC +""" + +# +# (C) 2021 by Sysmocom s.f.m.c. GmbH +# All Rights Reserved +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +from pySim.commands import SimCardCommands +from pySim.filesystem import CardProfile +from pySim.ts_102_221 import CardProfileUICC +from pySim.ts_102_221 import CardProfileUICCSIM +from pySim.ts_51_011 import CardProfileSIM + +# In order for autodetection ... +_profile_classes = [ CardProfileUICCSIM, CardProfileUICC, CardProfileSIM ] + +def profile_detect(scc:SimCardCommands): + + for p in _profile_classes: + if p.match_witch_card(scc): + return p() + + return None diff --git a/pySim/ts_102_221.py b/pySim/ts_102_221.py index f86a8b3..b1d5e37 100644 --- a/pySim/ts_102_221.py +++ b/pySim/ts_102_221.py @@ -24,6 +24,10 @@ from pySim.filesystem import * from bidict import bidict +# A UICC will usually also support 2G functionality. If this is the case, we +# need to add DF_GSM and DF_TELECOM along with the UICC related files +from pySim.ts_51_011 import DF_GSM, DF_TELECOM + ts_102_22x_cmdset = CardCommandSet('TS 102 22x', [ # TS 102 221 Section 10.1.2 Table 10.5 "Coding of Instruction Byte" CardCommand('SELECT', 0xA4, ['0X', '4X', '6X']), @@ -454,6 +458,48 @@ addl_info = FlagsEnum(Byte, req_inc_idle_current=1, support_uicc_suspend=2) self._construct = Struct('max_current_mA'/Int8ub, 't_op_s'/Int8ub, 'addl_info'/addl_info) +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. + """ + cla_byte_bak = scc.cla_byte + sel_ctrl_bak = scc.sel_ctrl + scc.reset_card() + + scc.cla_byte = "00" + scc.sel_ctrl = "0004" + rc = True + try: + scc.select_file('3f00') + except: + rc = False + + scc.reset_card() + scc.cla_byte = cla_byte_bak + scc.sel_ctrl = sel_ctrl_bak + return rc + +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. + """ + cla_byte_bak = scc.cla_byte + sel_ctrl_bak = scc.sel_ctrl + scc.reset_card() + + scc.cla_byte = "a0" + scc.sel_ctrl = "0000" + rc = True + try: + scc.select_file('3f00') + except: + rc = False + + scc.reset_card() + scc.cla_byte = cla_byte_bak + scc.sel_ctrl = sel_ctrl_bak + return rc class CardProfileUICC(CardProfile): def __init__(self): @@ -538,3 +584,20 @@ def decode_select_response(self, data_hex:str) -> Any: return pySim.ts_102_221_select.decode_select_response(data_hex) + + @staticmethod + def match_witch_card(scc:SimCardCommands) -> bool: + return _match_uicc(scc) + +class CardProfileUICCSIM(CardProfileUICC): + """Same as above, but including 2G SIM support""" + def __init__(self): + super().__init__() + + # Add GSM specific files + self.files_in_mf.append(DF_TELECOM()) + self.files_in_mf.append(DF_GSM()) + + @staticmethod + def match_witch_card(scc:SimCardCommands) -> bool: + return _match_uicc(scc) and _match_sim(scc) diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index c146a79..c2c1711 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -974,8 +974,35 @@ return ret +def _match_witch_card(scc:SimCardCommands) -> bool: + """ Try to access MF via 2G APDUs (3GPP TS 11.11), if this works, the + card is considered a SIM card. This test will also succeed on UICC + cards that also have SIM card functionality for compatibility with + older MS + """ + cla_byte_bak = scc.cla_byte + sel_ctrl_bak = scc.sel_ctrl + scc.reset_card() + + scc.cla_byte = "a0" + scc.sel_ctrl = "0000" + rc = True + try: + scc.select_file('3f00') + except: + rc = False + + scc.reset_card() + scc.cla_byte = cla_byte_bak + scc.sel_ctrl = sel_ctrl_bak + return rc + class CardProfileSIM(CardProfile): def __init__(self): super().__init__('SIM', desc='GSM SIM Card', cla="a0", sel_ctrl="0000", files_in_mf=[DF_TELECOM(), DF_GSM()]) def decode_select_response(self, data_hex:str) -> Any: return _decode_select_response(data_hex) + + @staticmethod + def match_witch_card(scc:SimCardCommands) -> bool: + return _match_witch_card(scc) -- To view, visit https://gerrit.osmocom.org/c/pysim/+/26165 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: pysim Gerrit-Branch: master Gerrit-Change-Id: If090d32551145f75c644657b90085a3ef5bfa691 Gerrit-Change-Number: 26165 Gerrit-PatchSet: 1 Gerrit-Owner: dexter <pmaier at sysmocom.de> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20211108/8535e95a/attachment.htm>