Change in pysim[master]: pySim-shell: add method to probe for UICC

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.org
Fri Oct 29 17:24:00 UTC 2021


dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/26043 )


Change subject: pySim-shell: add method to probe for UICC
......................................................................

pySim-shell: add method to probe for UICC

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 that probes the card type and then decide which
profile is suitable.

Change-Id: I535bef35847140e611d4fa95ed2859ee81cce605
Related: OS#5274
---
M pySim-shell.py
M pySim/filesystem.py
A pySim/probe.py
M pySim/ts_102_221.py
M pySim/ts_51_011.py
5 files changed, 119 insertions(+), 12 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/43/26043/1

diff --git a/pySim-shell.py b/pySim-shell.py
index 3fc5859..555ddac 100755
--- a/pySim-shell.py
+++ b/pySim-shell.py
@@ -58,6 +58,8 @@
 
 from pySim.card_key_provider import CardKeyProviderCsv, card_key_provider_register, card_key_provider_get_field
 
+from pySim.probe import probe_card
+
 def init_card(sl):
 	"""
 	Detect card in reader and setup card profile and runtime state. This
@@ -79,19 +81,36 @@
 
 	card = card_detect("auto", scc)
 	if card is None:
-		print("Could not detect card type!")
-		return None, None;
+		print("Warning: Could not detect card type - assuming a generic card type...")
+		card = SimCard(scc);
+
+	card_is_uicc = probe_card(card, ['UICC'])
+	card_is_sim = probe_card(card, ['SIM'])
+
+	if card_is_uicc:
+		if card_is_sim:
+			print("Info: Card is of type SIM and UICC")
+		else:
+			print("Info: Card is of type UICC")
+		profile = CardProfileUICC()
+		profile.add_application(CardApplicationUSIM())
+		profile.add_application(CardApplicationISIM())
+	elif card_is_sim:
+		print("Info: Card is of type SIM")
+		profile = CardProfileSIM()
+	else:
+		print("Unsupported card type!")
+		return None, None
 
 	# 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())
-	rs.mf.add_file(DF_EIRENE())
+	# The card is an UICC, but can also be used a 2G SIM, so we must add the SIM
+	# SIM related bits manaully because they are not part of the UICC profile
+	if card_is_uicc and card_is_sim:
+		rs.mf.add_file(DF_TELECOM())
+		rs.mf.add_file(DF_GSM())
+		rs.mf.add_file(DF_EIRENE())
 
 	CardModel.apply_matching_models(scc, rs)
 
diff --git a/pySim/filesystem.py b/pySim/filesystem.py
index dcc2608..bf4025c 100644
--- a/pySim/filesystem.py
+++ b/pySim/filesystem.py
@@ -1033,6 +1033,11 @@
         self.card = card
         self.selected_file = self.mf # type: CardDF
         self.profile = profile
+
+        # make sure the class and selection control bytes, which are specified
+        # by the card profile are used
+        self.card.set_apdu_parameter(cla=self.profile.cla, sel_ctrl=self.profile.sel_ctrl)
+
         # add application ADFs + MF-files from profile
         apps = self._match_applications()
         for a in apps:
@@ -1042,11 +1047,22 @@
             self.mf.add_file(f)
         self.conserve_write = True
 
+        # make sure that when the runtime state is created, the card is also
+        # in a defined state.
+        self.reset()
+
     def _match_applications(self):
         """match the applications from the profile with applications on the card"""
         apps_profile = self.profile.applications
-        aids_card = self.card.read_aids()
         apps_taken = []
+
+        # When the profile does not feature any applications, then we are done already
+        if not apps_profile:
+            return []
+
+        # Read AIDs from card and match them against the applications defined by the
+        # card profile
+        aids_card = self.card.read_aids()
         if aids_card:
             aids_taken = []
             print("AIDs on card:")
@@ -1407,6 +1423,8 @@
             applications : List of CardApplications present on card
             sw : List of status word definitions
             shell_cmdsets : List of cmd2 shell command sets of profile-specific commands
+            cla : class byte that should be used with cards of this profile
+            sel_ctrl : selection control bytes class byte that should be used with cards of this profile
         """
         self.name = name
         self.desc = kw.get("desc", None)
@@ -1414,6 +1432,8 @@
         self.sw = kw.get("sw", [])
         self.applications = kw.get("applications", [])
         self.shell_cmdsets = kw.get("shell_cmdsets", [])
+        self.cla = kw.get("cla", "00")
+        self.sel_ctrl = kw.get("sel_ctrl", "0004")
 
     def __str__(self):
         return self.name
diff --git a/pySim/probe.py b/pySim/probe.py
new file mode 100644
index 0000000..4348c21
--- /dev/null
+++ b/pySim/probe.py
@@ -0,0 +1,68 @@
+# -*- 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.cards import SimCard
+
+def _test_ts_11_11_apdu(card:SimCard) -> bool:
+	""" Try to access MF via 2G APDUs (3GPP TS 11.11) """
+	card.set_apdu_parameter(cla="a0", sel_ctrl="0000")
+	card.reset()
+	try:
+		card._scc.select_file('3f00')
+	except:
+		return False
+
+	return True
+
+def _test_uicc_apdu(card:SimCard) -> bool:
+	""" Try to access MF via UICC APDUs """
+	card.set_apdu_parameter(cla="00", sel_ctrl="0004")
+	card.reset()
+	try:
+		card._scc.select_file('3f00')
+	except:
+		return False
+
+	return True
+
+def probe_card(card:SimCard, card_is:list=['SIM','UICC']) -> bool:
+	""" Find out whether the card is of type UICC """
+
+	rc = []
+
+	# back up CLA byte and SEL control bytes
+	cla_byte_bak, sel_ctrl_bak = card.get_apdu_parameter()
+
+	if 'SIM' in card_is:
+		rc.append(_test_ts_11_11_apdu(card))
+	if 'UICC' in card_is:
+		rc.append(_test_uicc_apdu(card))
+
+	# Leave with a defined state
+	card.reset()
+	card.set_apdu_parameter(cla=cla_byte_bak, sel_ctrl=sel_ctrl_bak)
+
+	if False in rc:
+		return False
+
+	return True
diff --git a/pySim/ts_102_221.py b/pySim/ts_102_221.py
index 3665939..403daec 100644
--- a/pySim/ts_102_221.py
+++ b/pySim/ts_102_221.py
@@ -683,4 +683,4 @@
             },
           }
 
-        super().__init__('UICC', desc='ETSI TS 102 221', files_in_mf=files, sw=sw)
+        super().__init__('UICC', desc='ETSI TS 102 221', cla="00", sel_ctrl="0004", files_in_mf=files, sw=sw)
diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py
index 743c14b..fa70661 100644
--- a/pySim/ts_51_011.py
+++ b/pySim/ts_51_011.py
@@ -982,4 +982,4 @@
 
 class CardProfileSIM(CardProfile):
     def __init__(self):
-        super().__init__('SIM', desc='GSM SIM Card', files_in_mf=[DF_TELECOM(), DF_GSM()])
+        super().__init__('SIM', desc='GSM SIM Card', cla="a0", sel_ctrl="0000", files_in_mf=[DF_TELECOM(), DF_GSM()])

-- 
To view, visit https://gerrit.osmocom.org/c/pysim/+/26043
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I535bef35847140e611d4fa95ed2859ee81cce605
Gerrit-Change-Number: 26043
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/20211029/3ecf9b6e/attachment.htm>


More information about the gerrit-log mailing list