<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/pysim/+/26160">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">ts_102_221: put select response decoder into separate file<br><br>The decoder function that decodes the select response has become more<br>and more complex over time, so it makes sense to put the code into a<br>separate file, lets also mark the functions we only call from inside the<br>decoder as private. This makes the code more readable and also helps to<br>prevent circular dependencies.<br><br>Change-Id: If5fae46bb40d0f285236a6ab287070125c69ed70<br>---<br>M pySim/ts_102_221.py<br>A pySim/ts_102_221_select.py<br>M pySim/ts_31_102.py<br>M pySim/ts_31_103.py<br>M pySim/ts_51_011.py<br>5 files changed, 182 insertions(+), 155 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/60/26160/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/pySim/ts_102_221.py b/pySim/ts_102_221.py</span><br><span>index 3665939..8b1f7da 100644</span><br><span>--- a/pySim/ts_102_221.py</span><br><span>+++ b/pySim/ts_102_221.py</span><br><span>@@ -17,7 +17,7 @@</span><br><span> along with this program. If not, see <http://www.gnu.org/licenses/>.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from pytlv.TLV import *</span><br><span style="color: hsl(120, 100%, 40%);">+#from pytlv.TLV import *</span><br><span> from construct import *</span><br><span> from pySim.construct import *</span><br><span> from pySim.utils import *</span><br><span>@@ -70,138 +70,11 @@</span><br><span> ])</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-FCP_TLV_MAP = {</span><br><span style="color: hsl(0, 100%, 40%);">- '82': 'file_descriptor',</span><br><span style="color: hsl(0, 100%, 40%);">- '83': 'file_identifier',</span><br><span style="color: hsl(0, 100%, 40%);">- '84': 'df_name',</span><br><span style="color: hsl(0, 100%, 40%);">- 'A5': 'proprietary_info',</span><br><span style="color: hsl(0, 100%, 40%);">- '8A': 'life_cycle_status_int',</span><br><span style="color: hsl(0, 100%, 40%);">- '8B': 'security_attrib_ref_expanded',</span><br><span style="color: hsl(0, 100%, 40%);">- '8C': 'security_attrib_compact',</span><br><span style="color: hsl(0, 100%, 40%);">- 'AB': 'security_attrib_espanded',</span><br><span style="color: hsl(0, 100%, 40%);">- 'C6': 'pin_status_template_do',</span><br><span style="color: hsl(0, 100%, 40%);">- '80': 'file_size',</span><br><span style="color: hsl(0, 100%, 40%);">- '81': 'total_file_size',</span><br><span style="color: hsl(0, 100%, 40%);">- '88': 'short_file_id',</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# ETSI TS 102 221 11.1.1.4.6</span><br><span style="color: hsl(0, 100%, 40%);">-FCP_Proprietary_TLV_MAP = {</span><br><span style="color: hsl(0, 100%, 40%);">- '80': 'uicc_characteristics',</span><br><span style="color: hsl(0, 100%, 40%);">- '81': 'application_power_consumption',</span><br><span style="color: hsl(0, 100%, 40%);">- '82': 'minimum_app_clock_freq',</span><br><span style="color: hsl(0, 100%, 40%);">- '83': 'available_memory',</span><br><span style="color: hsl(0, 100%, 40%);">- '84': 'file_details',</span><br><span style="color: hsl(0, 100%, 40%);">- '85': 'reserved_file_size',</span><br><span style="color: hsl(0, 100%, 40%);">- '86': 'maximum_file_size',</span><br><span style="color: hsl(0, 100%, 40%);">- '87': 'suported_system_commands',</span><br><span style="color: hsl(0, 100%, 40%);">- '88': 'specific_uicc_env_cond',</span><br><span style="color: hsl(0, 100%, 40%);">- '89': 'p2p_cat_secured_apdu',</span><br><span style="color: hsl(0, 100%, 40%);">- # Additional private TLV objects (bits b7 and b8 of the first byte of the tag set to '1')</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# ETSI TS 102 221 11.1.1.4.3</span><br><span style="color: hsl(0, 100%, 40%);">-def interpret_file_descriptor(in_hex):</span><br><span style="color: hsl(0, 100%, 40%);">- in_bin = h2b(in_hex)</span><br><span style="color: hsl(0, 100%, 40%);">- out = {}</span><br><span style="color: hsl(0, 100%, 40%);">- ft_dict = {</span><br><span style="color: hsl(0, 100%, 40%);">- 0: 'working_ef',</span><br><span style="color: hsl(0, 100%, 40%);">- 1: 'internal_ef',</span><br><span style="color: hsl(0, 100%, 40%);">- 7: 'df'</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- fs_dict = {</span><br><span style="color: hsl(0, 100%, 40%);">- 0: 'no_info_given',</span><br><span style="color: hsl(0, 100%, 40%);">- 1: 'transparent',</span><br><span style="color: hsl(0, 100%, 40%);">- 2: 'linear_fixed',</span><br><span style="color: hsl(0, 100%, 40%);">- 6: 'cyclic',</span><br><span style="color: hsl(0, 100%, 40%);">- 0x39: 'ber_tlv',</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- fdb = in_bin[0]</span><br><span style="color: hsl(0, 100%, 40%);">- ftype = (fdb >> 3) & 7</span><br><span style="color: hsl(0, 100%, 40%);">- if fdb & 0xbf == 0x39:</span><br><span style="color: hsl(0, 100%, 40%);">- fstruct = 0x39</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- fstruct = fdb & 7</span><br><span style="color: hsl(0, 100%, 40%);">- out['shareable'] = True if fdb & 0x40 else False</span><br><span style="color: hsl(0, 100%, 40%);">- out['file_type'] = ft_dict[ftype] if ftype in ft_dict else ftype</span><br><span style="color: hsl(0, 100%, 40%);">- out['structure'] = fs_dict[fstruct] if fstruct in fs_dict else fstruct</span><br><span style="color: hsl(0, 100%, 40%);">- if len(in_bin) >= 5:</span><br><span style="color: hsl(0, 100%, 40%);">- out['record_len'] = int.from_bytes(in_bin[2:4], 'big')</span><br><span style="color: hsl(0, 100%, 40%);">- out['num_of_rec'] = int.from_bytes(in_bin[4:5], 'big')</span><br><span style="color: hsl(0, 100%, 40%);">- return out</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# ETSI TS 102 221 11.1.1.4.9</span><br><span style="color: hsl(0, 100%, 40%);">-def interpret_life_cycle_sts_int(in_hex):</span><br><span style="color: hsl(0, 100%, 40%);">- lcsi = int(in_hex, 16)</span><br><span style="color: hsl(0, 100%, 40%);">- if lcsi == 0x00:</span><br><span style="color: hsl(0, 100%, 40%);">- return 'no_information'</span><br><span style="color: hsl(0, 100%, 40%);">- elif lcsi == 0x01:</span><br><span style="color: hsl(0, 100%, 40%);">- return 'creation'</span><br><span style="color: hsl(0, 100%, 40%);">- elif lcsi == 0x03:</span><br><span style="color: hsl(0, 100%, 40%);">- return 'initialization'</span><br><span style="color: hsl(0, 100%, 40%);">- elif lcsi & 0x05 == 0x05:</span><br><span style="color: hsl(0, 100%, 40%);">- return 'operational_activated'</span><br><span style="color: hsl(0, 100%, 40%);">- elif lcsi & 0x05 == 0x04:</span><br><span style="color: hsl(0, 100%, 40%);">- return 'operational_deactivated'</span><br><span style="color: hsl(0, 100%, 40%);">- elif lcsi & 0xc0 == 0xc0:</span><br><span style="color: hsl(0, 100%, 40%);">- return 'termination'</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- return in_hex</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# ETSI TS 102 221 11.1.1.4.10</span><br><span style="color: hsl(0, 100%, 40%);">-FCP_Pin_Status_TLV_MAP = {</span><br><span style="color: hsl(0, 100%, 40%);">- '90': 'ps_do',</span><br><span style="color: hsl(0, 100%, 40%);">- '95': 'usage_qualifier',</span><br><span style="color: hsl(0, 100%, 40%);">- '83': 'key_reference',</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def interpret_ps_templ_do(in_hex):</span><br><span style="color: hsl(0, 100%, 40%);">- # cannot use the 'TLV' parser due to repeating tags</span><br><span style="color: hsl(0, 100%, 40%);">- #psdo_tlv = TLV(FCP_Pin_Status_TLV_MAP)</span><br><span style="color: hsl(0, 100%, 40%);">- #return psdo_tlv.parse(in_hex)</span><br><span style="color: hsl(0, 100%, 40%);">- return in_hex</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# 'interpreter' functions for each tag</span><br><span style="color: hsl(0, 100%, 40%);">-FCP_interpreter_map = {</span><br><span style="color: hsl(0, 100%, 40%);">- '80': lambda x: int(x, 16),</span><br><span style="color: hsl(0, 100%, 40%);">- '82': interpret_file_descriptor,</span><br><span style="color: hsl(0, 100%, 40%);">- '8A': interpret_life_cycle_sts_int,</span><br><span style="color: hsl(0, 100%, 40%);">- 'C6': interpret_ps_templ_do,</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-FCP_prorietary_interpreter_map = {</span><br><span style="color: hsl(0, 100%, 40%);">- '83': lambda x: int(x, 16),</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# pytlv unfortunately doesn't have a setting using which we can make it</span><br><span style="color: hsl(0, 100%, 40%);">-# accept unknown tags. It also doesn't raise a specific exception type but</span><br><span style="color: hsl(0, 100%, 40%);">-# just the generic ValueError, so we cannot ignore those either. Instead,</span><br><span style="color: hsl(0, 100%, 40%);">-# we insert a dict entry for every possible proprietary tag permitted</span><br><span style="color: hsl(0, 100%, 40%);">-def fixup_fcp_proprietary_tlv_map(tlv_map):</span><br><span style="color: hsl(0, 100%, 40%);">- if 'D0' in tlv_map:</span><br><span style="color: hsl(0, 100%, 40%);">- return</span><br><span style="color: hsl(0, 100%, 40%);">- for i in range(0xc0, 0xff):</span><br><span style="color: hsl(0, 100%, 40%);">- i_hex = i2h([i]).upper()</span><br><span style="color: hsl(0, 100%, 40%);">- tlv_map[i_hex] = 'proprietary_' + i_hex</span><br><span style="color: hsl(0, 100%, 40%);">- # Other non-standard TLV objects found on some cards</span><br><span style="color: hsl(0, 100%, 40%);">- tlv_map['9B'] = 'target_ef' # for sysmoUSIM-SJS1</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-def tlv_key_replace(inmap, indata):</span><br><span style="color: hsl(0, 100%, 40%);">- def newkey(inmap, key):</span><br><span style="color: hsl(0, 100%, 40%);">- if key in inmap:</span><br><span style="color: hsl(0, 100%, 40%);">- return inmap[key]</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- return key</span><br><span style="color: hsl(0, 100%, 40%);">- return {newkey(inmap, d[0]): d[1] for d in indata.items()}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-def tlv_val_interpret(inmap, indata):</span><br><span style="color: hsl(0, 100%, 40%);">- def newval(inmap, key, val):</span><br><span style="color: hsl(0, 100%, 40%);">- if key in inmap:</span><br><span style="color: hsl(0, 100%, 40%);">- return inmap[key](val)</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- return val</span><br><span style="color: hsl(0, 100%, 40%);">- return {d[0]: newval(inmap, d[0], d[1]) for d in indata.items()}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> # ETSI TS 102 221 Section 9.2.7 + ISO7816-4 9.3.3/9.3.4</span><br><span> </span><br><span>@@ -466,28 +339,6 @@</span><br><span> SC_DO = DataObjectChoice('security_condition', 'Security Condition',</span><br><span> members=[Always_DO, Never_DO, SecCondByte_DO(), SecCondByte_DO(0x9e), CRT_DO()])</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# ETSI TS 102 221 Section 11.1.1.3</span><br><span style="color: hsl(0, 100%, 40%);">-def decode_select_response(resp_hex):</span><br><span style="color: hsl(0, 100%, 40%);">- fixup_fcp_proprietary_tlv_map(FCP_Proprietary_TLV_MAP)</span><br><span style="color: hsl(0, 100%, 40%);">- resp_hex = resp_hex.upper()</span><br><span style="color: hsl(0, 100%, 40%);">- # outer layer</span><br><span style="color: hsl(0, 100%, 40%);">- fcp_base_tlv = TLV(['62'])</span><br><span style="color: hsl(0, 100%, 40%);">- fcp_base = fcp_base_tlv.parse(resp_hex)</span><br><span style="color: hsl(0, 100%, 40%);">- # actual FCP</span><br><span style="color: hsl(0, 100%, 40%);">- fcp_tlv = TLV(FCP_TLV_MAP)</span><br><span style="color: hsl(0, 100%, 40%);">- fcp = fcp_tlv.parse(fcp_base['62'])</span><br><span style="color: hsl(0, 100%, 40%);">- # further decode the proprietary information</span><br><span style="color: hsl(0, 100%, 40%);">- if fcp['A5']:</span><br><span style="color: hsl(0, 100%, 40%);">- prop_tlv = TLV(FCP_Proprietary_TLV_MAP)</span><br><span style="color: hsl(0, 100%, 40%);">- prop = prop_tlv.parse(fcp['A5'])</span><br><span style="color: hsl(0, 100%, 40%);">- fcp['A5'] = tlv_val_interpret(FCP_prorietary_interpreter_map, prop)</span><br><span style="color: hsl(0, 100%, 40%);">- fcp['A5'] = tlv_key_replace(FCP_Proprietary_TLV_MAP, fcp['A5'])</span><br><span style="color: hsl(0, 100%, 40%);">- # finally make sure we get human-readable keys in the output dict</span><br><span style="color: hsl(0, 100%, 40%);">- r = tlv_val_interpret(FCP_interpreter_map, fcp)</span><br><span style="color: hsl(0, 100%, 40%);">- return tlv_key_replace(FCP_TLV_MAP, r)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> # TS 102 221 Section 13.1</span><br><span> class EF_DIR(LinFixedEF):</span><br><span> def __init__(self, fid='2f00', sfid=0x1e, name='EF.DIR', desc='Application Directory'):</span><br><span>diff --git a/pySim/ts_102_221_select.py b/pySim/ts_102_221_select.py</span><br><span>new file mode 100644</span><br><span>index 0000000..74ede38</span><br><span>--- /dev/null</span><br><span>+++ b/pySim/ts_102_221_select.py</span><br><span>@@ -0,0 +1,173 @@</span><br><span style="color: hsl(120, 100%, 40%);">+# coding=utf-8</span><br><span style="color: hsl(120, 100%, 40%);">+"""Utilities / Functions related to ETSI TS 102 221, section 11.1.1 SELECT.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+(C) 2021 by Harald Welte <laforge@osmocom.org></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This program is free software: you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+the Free Software Foundation, either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+(at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span><br><span style="color: hsl(120, 100%, 40%);">+GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+You should have received a copy of the GNU General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+along with this program. If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.utils import i2h, h2b, bertlv_parse_one</span><br><span style="color: hsl(120, 100%, 40%);">+from pytlv.TLV import *</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+FCP_TLV_MAP = {</span><br><span style="color: hsl(120, 100%, 40%);">+ '82': 'file_descriptor',</span><br><span style="color: hsl(120, 100%, 40%);">+ '83': 'file_identifier',</span><br><span style="color: hsl(120, 100%, 40%);">+ '84': 'df_name',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'A5': 'proprietary_info',</span><br><span style="color: hsl(120, 100%, 40%);">+ '8A': 'life_cycle_status_int',</span><br><span style="color: hsl(120, 100%, 40%);">+ '8B': 'security_attrib_ref_expanded',</span><br><span style="color: hsl(120, 100%, 40%);">+ '8C': 'security_attrib_compact',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'AB': 'security_attrib_espanded',</span><br><span style="color: hsl(120, 100%, 40%);">+ 'C6': 'pin_status_template_do',</span><br><span style="color: hsl(120, 100%, 40%);">+ '80': 'file_size',</span><br><span style="color: hsl(120, 100%, 40%);">+ '81': 'total_file_size',</span><br><span style="color: hsl(120, 100%, 40%);">+ '88': 'short_file_id',</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# ETSI TS 102 221 11.1.1.4.6</span><br><span style="color: hsl(120, 100%, 40%);">+FCP_Proprietary_TLV_MAP = {</span><br><span style="color: hsl(120, 100%, 40%);">+ '80': 'uicc_characteristics',</span><br><span style="color: hsl(120, 100%, 40%);">+ '81': 'application_power_consumption',</span><br><span style="color: hsl(120, 100%, 40%);">+ '82': 'minimum_app_clock_freq',</span><br><span style="color: hsl(120, 100%, 40%);">+ '83': 'available_memory',</span><br><span style="color: hsl(120, 100%, 40%);">+ '84': 'file_details',</span><br><span style="color: hsl(120, 100%, 40%);">+ '85': 'reserved_file_size',</span><br><span style="color: hsl(120, 100%, 40%);">+ '86': 'maximum_file_size',</span><br><span style="color: hsl(120, 100%, 40%);">+ '87': 'suported_system_commands',</span><br><span style="color: hsl(120, 100%, 40%);">+ '88': 'specific_uicc_env_cond',</span><br><span style="color: hsl(120, 100%, 40%);">+ '89': 'p2p_cat_secured_apdu',</span><br><span style="color: hsl(120, 100%, 40%);">+ # Additional private TLV objects (bits b7 and b8 of the first byte of the tag set to '1')</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# ETSI TS 102 221 11.1.1.4.3</span><br><span style="color: hsl(120, 100%, 40%);">+def _interpret_file_descriptor(in_hex):</span><br><span style="color: hsl(120, 100%, 40%);">+ in_bin = h2b(in_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+ out = {}</span><br><span style="color: hsl(120, 100%, 40%);">+ ft_dict = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 0: 'working_ef',</span><br><span style="color: hsl(120, 100%, 40%);">+ 1: 'internal_ef',</span><br><span style="color: hsl(120, 100%, 40%);">+ 7: 'df'</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ fs_dict = {</span><br><span style="color: hsl(120, 100%, 40%);">+ 0: 'no_info_given',</span><br><span style="color: hsl(120, 100%, 40%);">+ 1: 'transparent',</span><br><span style="color: hsl(120, 100%, 40%);">+ 2: 'linear_fixed',</span><br><span style="color: hsl(120, 100%, 40%);">+ 6: 'cyclic',</span><br><span style="color: hsl(120, 100%, 40%);">+ 0x39: 'ber_tlv',</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ fdb = in_bin[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ ftype = (fdb >> 3) & 7</span><br><span style="color: hsl(120, 100%, 40%);">+ if fdb & 0xbf == 0x39:</span><br><span style="color: hsl(120, 100%, 40%);">+ fstruct = 0x39</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ fstruct = fdb & 7</span><br><span style="color: hsl(120, 100%, 40%);">+ out['shareable'] = True if fdb & 0x40 else False</span><br><span style="color: hsl(120, 100%, 40%);">+ out['file_type'] = ft_dict[ftype] if ftype in ft_dict else ftype</span><br><span style="color: hsl(120, 100%, 40%);">+ out['structure'] = fs_dict[fstruct] if fstruct in fs_dict else fstruct</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(in_bin) >= 5:</span><br><span style="color: hsl(120, 100%, 40%);">+ out['record_len'] = int.from_bytes(in_bin[2:4], 'big')</span><br><span style="color: hsl(120, 100%, 40%);">+ out['num_of_rec'] = int.from_bytes(in_bin[4:5], 'big')</span><br><span style="color: hsl(120, 100%, 40%);">+ return out</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# ETSI TS 102 221 11.1.1.4.9</span><br><span style="color: hsl(120, 100%, 40%);">+def _interpret_life_cycle_sts_int(in_hex):</span><br><span style="color: hsl(120, 100%, 40%);">+ lcsi = int(in_hex, 16)</span><br><span style="color: hsl(120, 100%, 40%);">+ if lcsi == 0x00:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'no_information'</span><br><span style="color: hsl(120, 100%, 40%);">+ elif lcsi == 0x01:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'creation'</span><br><span style="color: hsl(120, 100%, 40%);">+ elif lcsi == 0x03:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'initialization'</span><br><span style="color: hsl(120, 100%, 40%);">+ elif lcsi & 0x05 == 0x05:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'operational_activated'</span><br><span style="color: hsl(120, 100%, 40%);">+ elif lcsi & 0x05 == 0x04:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'operational_deactivated'</span><br><span style="color: hsl(120, 100%, 40%);">+ elif lcsi & 0xc0 == 0xc0:</span><br><span style="color: hsl(120, 100%, 40%);">+ return 'termination'</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ return in_hex</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# ETSI TS 102 221 11.1.1.4.10</span><br><span style="color: hsl(120, 100%, 40%);">+FCP_Pin_Status_TLV_MAP = {</span><br><span style="color: hsl(120, 100%, 40%);">+ '90': 'ps_do',</span><br><span style="color: hsl(120, 100%, 40%);">+ '95': 'usage_qualifier',</span><br><span style="color: hsl(120, 100%, 40%);">+ '83': 'key_reference',</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def _interpret_ps_templ_do(in_hex):</span><br><span style="color: hsl(120, 100%, 40%);">+ # cannot use the 'TLV' parser due to repeating tags</span><br><span style="color: hsl(120, 100%, 40%);">+ #psdo_tlv = TLV(FCP_Pin_Status_TLV_MAP)</span><br><span style="color: hsl(120, 100%, 40%);">+ #return psdo_tlv.parse(in_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+ return in_hex</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# 'interpreter' functions for each tag</span><br><span style="color: hsl(120, 100%, 40%);">+FCP_interpreter_map = {</span><br><span style="color: hsl(120, 100%, 40%);">+ '80': lambda x: int(x, 16),</span><br><span style="color: hsl(120, 100%, 40%);">+ '82': _interpret_file_descriptor,</span><br><span style="color: hsl(120, 100%, 40%);">+ '8A': _interpret_life_cycle_sts_int,</span><br><span style="color: hsl(120, 100%, 40%);">+ 'C6': _interpret_ps_templ_do,</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+FCP_prorietary_interpreter_map = {</span><br><span style="color: hsl(120, 100%, 40%);">+ '83': lambda x: int(x, 16),</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# pytlv unfortunately doesn't have a setting using which we can make it</span><br><span style="color: hsl(120, 100%, 40%);">+# accept unknown tags. It also doesn't raise a specific exception type but</span><br><span style="color: hsl(120, 100%, 40%);">+# just the generic ValueError, so we cannot ignore those either. Instead,</span><br><span style="color: hsl(120, 100%, 40%);">+# we insert a dict entry for every possible proprietary tag permitted</span><br><span style="color: hsl(120, 100%, 40%);">+def _fixup_fcp_proprietary_tlv_map(tlv_map):</span><br><span style="color: hsl(120, 100%, 40%);">+ if 'D0' in tlv_map:</span><br><span style="color: hsl(120, 100%, 40%);">+ return</span><br><span style="color: hsl(120, 100%, 40%);">+ for i in range(0xc0, 0xff):</span><br><span style="color: hsl(120, 100%, 40%);">+ i_hex = i2h([i]).upper()</span><br><span style="color: hsl(120, 100%, 40%);">+ tlv_map[i_hex] = 'proprietary_' + i_hex</span><br><span style="color: hsl(120, 100%, 40%);">+ # Other non-standard TLV objects found on some cards</span><br><span style="color: hsl(120, 100%, 40%);">+ tlv_map['9B'] = 'target_ef' # for sysmoUSIM-SJS1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def _tlv_key_replace(inmap, indata):</span><br><span style="color: hsl(120, 100%, 40%);">+ def newkey(inmap, key):</span><br><span style="color: hsl(120, 100%, 40%);">+ if key in inmap:</span><br><span style="color: hsl(120, 100%, 40%);">+ return inmap[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ return key</span><br><span style="color: hsl(120, 100%, 40%);">+ return {newkey(inmap, d[0]): d[1] for d in indata.items()}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def _tlv_val_interpret(inmap, indata):</span><br><span style="color: hsl(120, 100%, 40%);">+ def newval(inmap, key, val):</span><br><span style="color: hsl(120, 100%, 40%);">+ if key in inmap:</span><br><span style="color: hsl(120, 100%, 40%);">+ return inmap[key](val)</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ return val</span><br><span style="color: hsl(120, 100%, 40%);">+ return {d[0]: newval(inmap, d[0], d[1]) for d in indata.items()}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# ETSI TS 102 221 Section 11.1.1.3</span><br><span style="color: hsl(120, 100%, 40%);">+def decode_select_response(resp_hex):</span><br><span style="color: hsl(120, 100%, 40%);">+ _fixup_fcp_proprietary_tlv_map(FCP_Proprietary_TLV_MAP)</span><br><span style="color: hsl(120, 100%, 40%);">+ resp_hex = resp_hex.upper()</span><br><span style="color: hsl(120, 100%, 40%);">+ # outer layer</span><br><span style="color: hsl(120, 100%, 40%);">+ fcp_base_tlv = TLV(['62'])</span><br><span style="color: hsl(120, 100%, 40%);">+ fcp_base = fcp_base_tlv.parse(resp_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+ # actual FCP</span><br><span style="color: hsl(120, 100%, 40%);">+ fcp_tlv = TLV(FCP_TLV_MAP)</span><br><span style="color: hsl(120, 100%, 40%);">+ fcp = fcp_tlv.parse(fcp_base['62'])</span><br><span style="color: hsl(120, 100%, 40%);">+ # further decode the proprietary information</span><br><span style="color: hsl(120, 100%, 40%);">+ if fcp['A5']:</span><br><span style="color: hsl(120, 100%, 40%);">+ prop_tlv = TLV(FCP_Proprietary_TLV_MAP)</span><br><span style="color: hsl(120, 100%, 40%);">+ prop = prop_tlv.parse(fcp['A5'])</span><br><span style="color: hsl(120, 100%, 40%);">+ fcp['A5'] = _tlv_val_interpret(FCP_prorietary_interpreter_map, prop)</span><br><span style="color: hsl(120, 100%, 40%);">+ fcp['A5'] = _tlv_key_replace(FCP_Proprietary_TLV_MAP, fcp['A5'])</span><br><span style="color: hsl(120, 100%, 40%);">+ # finally make sure we get human-readable keys in the output dict</span><br><span style="color: hsl(120, 100%, 40%);">+ r = _tlv_val_interpret(FCP_interpreter_map, fcp)</span><br><span style="color: hsl(120, 100%, 40%);">+ return _tlv_key_replace(FCP_TLV_MAP, r)</span><br><span>diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py</span><br><span>index 14d7ec1..83c281c 100644</span><br><span>--- a/pySim/ts_31_102.py</span><br><span>+++ b/pySim/ts_31_102.py</span><br><span>@@ -294,6 +294,7 @@</span><br><span> from pySim.ts_51_011 import EF_MMSN, EF_MMSICP, EF_MMSUP, EF_MMSUCP, EF_VGCS, EF_VGCSS, EF_NIA</span><br><span> from pySim.ts_51_011 import EF_ACMmax, EF_AAeM, EF_eMLPP, EF_CMI</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+import pySim.ts_51_011</span><br><span> import pySim.ts_102_221</span><br><span> </span><br><span> # 3GPP TS 31.102 Section 4.4.11.4 (EF_5GS3GPPNSC)</span><br><span>@@ -1067,7 +1068,7 @@</span><br><span> self.add_files(files)</span><br><span> </span><br><span> def decode_select_response(self, data_hex):</span><br><span style="color: hsl(0, 100%, 40%);">- return pySim.ts_102_221.decode_select_response(data_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+ return pySim.ts_102_221_select.decode_select_response(data_hex)</span><br><span> </span><br><span> @with_default_category('Application-Specific Commands')</span><br><span> class AddlShellCommands(CommandSet):</span><br><span>diff --git a/pySim/ts_31_103.py b/pySim/ts_31_103.py</span><br><span>index 63ef99e..3fd6629 100644</span><br><span>--- a/pySim/ts_31_103.py</span><br><span>+++ b/pySim/ts_31_103.py</span><br><span>@@ -28,6 +28,7 @@</span><br><span> from pySim.ts_51_011 import EF_AD, EF_SMS, EF_SMSS, EF_SMSR, EF_SMSP</span><br><span> from pySim.ts_31_102 import ADF_USIM, EF_FromPreferred</span><br><span> import pySim.ts_102_221</span><br><span style="color: hsl(120, 100%, 40%);">+import pySim.ts_102_221_select</span><br><span> from pySim.ts_102_221 import EF_ARR</span><br><span> </span><br><span> # Mapping between ISIM Service Number and its description</span><br><span>@@ -213,7 +214,7 @@</span><br><span> self.shell_commands += [ADF_USIM.AddlShellCommands()]</span><br><span> </span><br><span> def decode_select_response(self, data_hex):</span><br><span style="color: hsl(0, 100%, 40%);">- return pySim.ts_102_221.decode_select_response(data_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+ return pySim.ts_102_221_select.decode_select_response(data_hex)</span><br><span> </span><br><span> # TS 31.103 Section 7.1</span><br><span> sw_isim = {</span><br><span>diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py</span><br><span>index 743c14b..c7168e8 100644</span><br><span>--- a/pySim/ts_51_011.py</span><br><span>+++ b/pySim/ts_51_011.py</span><br><span>@@ -333,6 +333,7 @@</span><br><span> </span><br><span> from pySim.filesystem import *</span><br><span> import pySim.ts_102_221</span><br><span style="color: hsl(120, 100%, 40%);">+import pySim.ts_102_221_select</span><br><span> </span><br><span> ######################################################################</span><br><span> # DF.TELECOM</span><br><span>@@ -942,7 +943,7 @@</span><br><span> def decode_select_response(resp_hex):</span><br><span> resp_bin = h2b(resp_hex)</span><br><span> if resp_bin[0] == 0x62:</span><br><span style="color: hsl(0, 100%, 40%);">- return pySim.ts_102_221.decode_select_response(resp_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+ return pySim.ts_102_221_select.decode_select_response(resp_hex)</span><br><span> struct_of_file_map = {</span><br><span> 0: 'transparent',</span><br><span> 1: 'linear_fixed',</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/pysim/+/26160">change 26160</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/pysim/+/26160"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: pysim </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: If5fae46bb40d0f285236a6ab287070125c69ed70 </div>
<div style="display:none"> Gerrit-Change-Number: 26160 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>