Change in pysim[master]: commands: get file/record length from FCP (USIM)

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
Wed Jun 13 11:04:04 UTC 2018


dexter has uploaded this change for review. ( https://gerrit.osmocom.org/9597


Change subject: commands: get file/record length from FCP (USIM)
......................................................................

commands: get file/record length from FCP (USIM)

Some of the methods SimCardCommands() have ways to determaine length
information from the card response. Regular sims use a format where
the length field is on a fixed position. USIMs use FCP templates
(format control parameters), which is a TLV encodecs string. So lets
distingish if we deal with an USIM (We can easily do this by looking
at the select control parameters) and extract the length info from
the FCP.

- If we deal with USIMs, use the FCP to determine length
  information

Change-Id: I068cf8a532e1c79a2d208e9d275c155ddb72713c
Related: SYS#4245
---
M pySim/commands.py
1 file changed, 56 insertions(+), 6 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/97/9597/1

diff --git a/pySim/commands.py b/pySim/commands.py
index eba915c..9e16b0e 100644
--- a/pySim/commands.py
+++ b/pySim/commands.py
@@ -23,7 +23,7 @@
 #
 
 from pySim.utils import rpad, b2h
-
+from pytlv.TLV import *
 
 class SimCardCommands(object):
 	def __init__(self, transport):
@@ -31,6 +31,56 @@
 		self._cla_byte = "a0"
 		self.sel_ctrl = "0000"
 
+	# Get file size from FCP
+	def __get_len_from_tlv(self, fcp):
+		# see also: ETSI TS 102 221, chapter 11.1.1.3.1 Response for MF,
+		# DF or ADF
+		tlvparser = TLV(['82', '83', '84', 'A5', '8a', '8b', '8c', '80', 'ab', 'c6', '81', '88'])
+
+		# pytlv is case sensitive!
+		fcp = fcp.lower()
+
+		if fcp[0:2] != '62':
+			raise ValueError('Tag of the FCP template does not match, expected 62 but got %s'%fcp[0:2])
+
+		# Unfortunately the spec is not very clear if the FCP length is
+		# coded as one or two byte vale, so we have to try it out by
+		# checking if the length of the remaining TLV string matches
+		# what we get in the length field.
+		# See also ETSI TS 102 221, chapter 11.1.1.3.0 Base coding.
+		exp_tlv_len = int(fcp[2:4], 16)
+		if len(fcp[4:])/2 == exp_tlv_len:
+			skip = 4
+		else:
+			exp_tlv_len = int(fcp[2:6], 16)
+			if len(fcp[4:])/2 == exp_tlv_len:
+				skip = 6
+
+		# Skip FCP tag and length
+		tlv = fcp[skip:]
+		tlv_parsed = tlvparser.parse(tlv)
+
+		return int(tlv_parsed['80'], 16)
+
+        # Tell the length of a record by the card response
+        # USIMs respond with an FCP template, which is different
+        # from what SIMs responds. See also:
+        # USIM: ETSI TS 102 221, chapter 11.1.1.3 Response Data
+        # SIM: GSM 11.11, chapter 9.2.1 SELECT
+	def __record_len(self, r):
+                if self.sel_ctrl == "0004":
+                        return self.__get_len_from_tlv(r[-1])
+                else:
+                        return int(r[-1][28:30], 16)
+
+        # Tell the length of a binary file. See also comment
+        # above.
+	def __len(self, r):
+                if self.sel_ctrl == "0004":
+                        return self.__get_len_from_tlv(r[-1])
+                else:
+                        return int(r[-1][4:8], 16)
+
 	def get_atr(self):
 		return self._tp.get_atr()
 
@@ -60,7 +110,7 @@
 			ef = [ef]
 		r = self.select_file(ef)
 		if length is None:
-			length = int(r[-1][4:8], 16) - offset
+			length = self.__len(r) - offset
 		pdu = self.cla_byte + 'b0%04x%02x' % (offset, (min(256, length) & 0xff))
 		return self._tp.send_apdu(pdu)
 
@@ -75,7 +125,7 @@
 		if not hasattr(type(ef), '__iter__'):
 			ef = [ef]
 		r = self.select_file(ef)
-		rec_length = int(r[-1][28:30], 16)
+		rec_length = self.__record_len(r)
 		pdu = self.cla_byte + 'b2%02x04%02x' % (rec_no, rec_length)
 		return self._tp.send_apdu(pdu)
 
@@ -84,7 +134,7 @@
 			ef = [ef]
 		r = self.select_file(ef)
 		if not force_len:
-			rec_length = int(r[-1][28:30], 16)
+			rec_length = self.__record_len(r)
 			if (len(data)/2 != rec_length):
 				raise ValueError('Invalid data length (expected %d, got %d)' % (rec_length, len(data)/2))
 		else:
@@ -94,11 +144,11 @@
 
 	def record_size(self, ef):
 		r = self.select_file(ef)
-		return int(r[-1][28:30], 16)
+		return self.__record_len(r)
 
 	def record_count(self, ef):
 		r = self.select_file(ef)
-		return int(r[-1][4:8], 16) // int(r[-1][28:30], 16)
+		return self.__len(r) // self.__record_len(r)
 
 	def run_gsm(self, rand):
 		if len(rand) != 32:

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

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I068cf8a532e1c79a2d208e9d275c155ddb72713c
Gerrit-Change-Number: 9597
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier at sysmocom.de>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180613/69aa09b3/attachment.htm>


More information about the gerrit-log mailing list