<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/pysim/+/25784">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">pysim-Shell: Add sysmocom SJA2 card specific bits<br><br>Depending on the ATR, we register the various sysmocom SJA2 card<br>model specific files [or not].<br><br>Change-Id: Id410489841bb9020ddbf74de9114d808b1d5adb6<br>---<br>M pySim-shell.py<br>M pySim/filesystem.py<br>A pySim/sysmocom_sja2.py<br>3 files changed, 278 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/pySim-shell.py b/pySim-shell.py</span><br><span>index f821e41..871c45e 100755</span><br><span>--- a/pySim-shell.py</span><br><span>+++ b/pySim-shell.py</span><br><span>@@ -42,12 +42,14 @@</span><br><span> from pySim.utils import dec_st, sanitize_pin_adm, tabulate_str_list, is_hex, boxed_heading_str</span><br><span> from pySim.card_handler import CardHandler</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from pySim.filesystem import CardMF, RuntimeState, CardDF, CardADF</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.filesystem import CardMF, RuntimeState, CardDF, CardADF, CardModel</span><br><span> from pySim.ts_51_011 import CardProfileSIM, DF_TELECOM, DF_GSM</span><br><span> from pySim.ts_102_221 import CardProfileUICC</span><br><span> from pySim.ts_31_102 import CardApplicationUSIM</span><br><span> from pySim.ts_31_103 import CardApplicationISIM</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+import pySim.sysmocom_sja2</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> from pySim.card_key_provider import CardKeyProviderCsv, card_key_provider_register, card_key_provider_get_field</span><br><span> </span><br><span> def init_card(sl):</span><br><span>@@ -84,6 +86,8 @@</span><br><span>         rs.mf.add_file(DF_TELECOM())</span><br><span>         rs.mf.add_file(DF_GSM())</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  CardModel.apply_matching_models(scc, rs)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   # inform the transport that we can do context-specific SW interpretation</span><br><span>     sl.set_sw_interpreter(rs)</span><br><span> </span><br><span>diff --git a/pySim/filesystem.py b/pySim/filesystem.py</span><br><span>index 170429b..5cdac56 100644</span><br><span>--- a/pySim/filesystem.py</span><br><span>+++ b/pySim/filesystem.py</span><br><span>@@ -27,6 +27,8 @@</span><br><span> import code</span><br><span> import tempfile</span><br><span> import json</span><br><span style="color: hsl(120, 100%, 40%);">+import abc</span><br><span style="color: hsl(120, 100%, 40%);">+import inspect</span><br><span> </span><br><span> import cmd2</span><br><span> from cmd2 import CommandSet, with_default_category, with_argparser</span><br><span>@@ -34,10 +36,13 @@</span><br><span> </span><br><span> from typing import cast, Optional, Iterable, List, Any, Dict, Tuple</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+from smartcard.util import toBytes</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> from pySim.utils import sw_match, h2b, b2h, i2h, is_hex, auto_int, bertlv_parse_one, Hexstr</span><br><span> from pySim.construct import filter_dict, parse_construct</span><br><span> from pySim.exceptions import *</span><br><span> from pySim.jsonpath import js_path_find, js_path_modify</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.commands import SimCardCommands</span><br><span> </span><br><span> class CardFile(object):</span><br><span>     """Base class for all objects in the smart card filesystem.</span><br><span>@@ -1427,3 +1432,30 @@</span><br><span>             Tuple of two strings</span><br><span>         """</span><br><span>         return interpret_sw(self.sw, sw)</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%);">+class CardModel(abc.ABC):</span><br><span style="color: hsl(120, 100%, 40%);">+    """A specific card model, typically having some additional vendor-specific files"""</span><br><span style="color: hsl(120, 100%, 40%);">+    _atrs = []</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @classmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    @abc.abstractmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def add_files(cls, rs:RuntimeState):</span><br><span style="color: hsl(120, 100%, 40%);">+        """Add model specific files to given RuntimeState."""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @classmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def match(cls, scc:SimCardCommands) -> bool:</span><br><span style="color: hsl(120, 100%, 40%);">+        """Test if given card matches this model."""</span><br><span style="color: hsl(120, 100%, 40%);">+        card_atr = scc.get_atr()</span><br><span style="color: hsl(120, 100%, 40%);">+        for atr in cls._atrs:</span><br><span style="color: hsl(120, 100%, 40%);">+            atr_bin = toBytes(atr)</span><br><span style="color: hsl(120, 100%, 40%);">+            if atr_bin == card_atr:</span><br><span style="color: hsl(120, 100%, 40%);">+                print("Detected CardModel:", cls.__name__)</span><br><span style="color: hsl(120, 100%, 40%);">+                return True</span><br><span style="color: hsl(120, 100%, 40%);">+        return False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    @staticmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def apply_matching_models(scc:SimCardCommands, rs:RuntimeState):</span><br><span style="color: hsl(120, 100%, 40%);">+        for m in CardModel.__subclasses__():</span><br><span style="color: hsl(120, 100%, 40%);">+            if m.match(scc):</span><br><span style="color: hsl(120, 100%, 40%);">+                m.add_files(rs)</span><br><span>diff --git a/pySim/sysmocom_sja2.py b/pySim/sysmocom_sja2.py</span><br><span>new file mode 100644</span><br><span>index 0000000..337eca7</span><br><span>--- /dev/null</span><br><span>+++ b/pySim/sysmocom_sja2.py</span><br><span>@@ -0,0 +1,241 @@</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 sysmocom SJA2 cards</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 pytlv.TLV import *</span><br><span style="color: hsl(120, 100%, 40%);">+from struct import pack, unpack</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.utils import *</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.filesystem import *</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.ts_102_221 import CardProfileUICC</span><br><span style="color: hsl(120, 100%, 40%);">+from pySim.construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+from construct import *</span><br><span style="color: hsl(120, 100%, 40%);">+import pySim</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+key_type2str = {</span><br><span style="color: hsl(120, 100%, 40%);">+    0: 'kic',</span><br><span style="color: hsl(120, 100%, 40%);">+    1: 'kid',</span><br><span style="color: hsl(120, 100%, 40%);">+    2: 'kik',</span><br><span style="color: hsl(120, 100%, 40%);">+    3: 'any',</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%);">+key_algo2str = {</span><br><span style="color: hsl(120, 100%, 40%);">+    0: 'des',</span><br><span style="color: hsl(120, 100%, 40%);">+    1: 'aes'</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%);">+mac_length = {</span><br><span style="color: hsl(120, 100%, 40%);">+    0: 8,</span><br><span style="color: hsl(120, 100%, 40%);">+    1: 4</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%);">+class EF_PIN(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid, name):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='%s PIN file' % name)</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode_bin(self, raw_bin_data):</span><br><span style="color: hsl(120, 100%, 40%);">+        u = unpack('!BBB8s', raw_bin_data[:11])</span><br><span style="color: hsl(120, 100%, 40%);">+        res =  {'enabled': (True, False)[u[0] & 0x01],</span><br><span style="color: hsl(120, 100%, 40%);">+                'initialized': (True, False)[u[0] & 0x02],</span><br><span style="color: hsl(120, 100%, 40%);">+                'disable_able': (False, True)[u[0] & 0x10],</span><br><span style="color: hsl(120, 100%, 40%);">+                'unblock_able': (False, True)[u[0] & 0x20],</span><br><span style="color: hsl(120, 100%, 40%);">+                'change_able': (False, True)[u[0] & 0x40],</span><br><span style="color: hsl(120, 100%, 40%);">+                'valid': (False, True)[u[0] & 0x80],</span><br><span style="color: hsl(120, 100%, 40%);">+                'attempts_remaining': u[1],</span><br><span style="color: hsl(120, 100%, 40%);">+                'maximum_attempts': u[2],</span><br><span style="color: hsl(120, 100%, 40%);">+                'pin': u[3].hex(),</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+        if len(raw_bin_data) == 21:</span><br><span style="color: hsl(120, 100%, 40%);">+            u2 = unpack('!BB8s', raw_bin_data[11:10])</span><br><span style="color: hsl(120, 100%, 40%);">+            res['attempts_remaining_puk'] = u2[0]</span><br><span style="color: hsl(120, 100%, 40%);">+            res['maximum_attempts_puk'] = u2[1]</span><br><span style="color: hsl(120, 100%, 40%);">+            res['puk'] = u2[2].hex()</span><br><span style="color: hsl(120, 100%, 40%);">+        return res</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_MILENAGE_CFG(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='6f21', name='EF.MILENAGE_CFG', desc='Milenage connfiguration'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc=desc)</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode_bin(self, raw_bin_data):</span><br><span style="color: hsl(120, 100%, 40%);">+        u = unpack('!BBBBB16s16s16s16s16s', raw_bin_data)</span><br><span style="color: hsl(120, 100%, 40%);">+        return {'r1': u[0], 'r2': u[1], 'r3': u[2], 'r4': u[3], 'r5': u[4],</span><br><span style="color: hsl(120, 100%, 40%);">+                'c1': u[5].hex(),</span><br><span style="color: hsl(120, 100%, 40%);">+                'c2': u[6].hex(),</span><br><span style="color: hsl(120, 100%, 40%);">+                'c3': u[7].hex(),</span><br><span style="color: hsl(120, 100%, 40%);">+                'c4': u[8].hex(),</span><br><span style="color: hsl(120, 100%, 40%);">+                'c5': u[9].hex(),</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%);">+class EF_0348_KEY(LinFixedEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='6f22', name='EF.0348_KEY', desc='TS 03.48 OTA Keys'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc=desc, rec_len={27,35})</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode_record_bin(self, raw_bin_data):</span><br><span style="color: hsl(120, 100%, 40%);">+        u = unpack('!BBB', raw_bin_data[0:3])</span><br><span style="color: hsl(120, 100%, 40%);">+        key_algo = (u[2] >> 6) & 1</span><br><span style="color: hsl(120, 100%, 40%);">+        key_length = ((u[2] >> 3) & 3) * 8</span><br><span style="color: hsl(120, 100%, 40%);">+        return {'sec_domain': u[0],</span><br><span style="color: hsl(120, 100%, 40%);">+                'key_set_version': u[1],</span><br><span style="color: hsl(120, 100%, 40%);">+                'key_type': key_type2str[u[2] & 3],</span><br><span style="color: hsl(120, 100%, 40%);">+                'key_length': key_length,</span><br><span style="color: hsl(120, 100%, 40%);">+                'algorithm': key_algo2str[key_algo],</span><br><span style="color: hsl(120, 100%, 40%);">+                'mac_length': mac_length[(u[2] >> 7)],</span><br><span style="color: hsl(120, 100%, 40%);">+                'key': raw_bin_data[3:key_length].hex()</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%);">+class EF_0348_COUNT(LinFixedEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='6f23', name='EF.0348_COUNT', desc='TS 03.48 OTA Counters'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc=desc, rec_len={7,7})</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode_record_bin(self, raw_bin_data):</span><br><span style="color: hsl(120, 100%, 40%);">+        u = unpack('!BB5s', raw_bin_data)</span><br><span style="color: hsl(120, 100%, 40%);">+        return {'sec_domain': u[0], 'key_set_version': u[1], 'counter': u[2]}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_SIM_AUTH_COUNTER(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af24', name='EF.SIM_AUTH_COUNTER'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='Number of remaining RUN GSM ALGORITHM executions')</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = Struct('num_run_gsm_algo_remain'/Int32ub)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_GP_COUNT(LinFixedEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='6f26', name='EF.GP_COUNT', desc='GP SCP02 Counters'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc=desc, rec_len={5,5})</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode_record_bin(self, raw_bin_data):</span><br><span style="color: hsl(120, 100%, 40%);">+        u = unpack('!BBHB', raw_bin_data)</span><br><span style="color: hsl(120, 100%, 40%);">+        return {'sec_domain': u[0], 'key_set_version': u[1], 'counter': u[2], 'rfu': u[3]}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_GP_DIV_DATA(LinFixedEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='6f27', name='EF.GP_DIV_DATA', desc='GP SCP02 key diversification data'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc=desc, rec_len={12,12})</span><br><span style="color: hsl(120, 100%, 40%);">+    def _decode_record_bin(self, raw_bin_data):</span><br><span style="color: hsl(120, 100%, 40%);">+        u = unpack('!BB8s', raw_bin_data)</span><br><span style="color: hsl(120, 100%, 40%);">+        return {'sec_domain': u[0], 'key_set_version': u[1], 'key_div_data': u[2].hex()}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_SIM_AUTH_KEY(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='6f20', name='EF.SIM_AUTH_KEY'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='USIM authentication key')</span><br><span style="color: hsl(120, 100%, 40%);">+        CfgByte = BitStruct(Bit[2],</span><br><span style="color: hsl(120, 100%, 40%);">+                            'use_sres_deriv_func_2'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'use_opc_instead_of_op'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'algorithm'/Enum(Nibble, milenage=4, comp128v1=1, comp128v2=2, comp128v3=3))</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = Struct('cfg'/CfgByte,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'key'/Bytes(16),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'op'/If(this.cfg.algorithm=='milenage' and not this.cfg.use_opc_instead_of_op, Bytes(16)),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'opc'/If(this.cfg.algorithm=='milenage' and this.cfg.use_opc_instead_of_op, Bytes(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%);">+class DF_SYSTEM(CardDF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid='a515', name='DF.SYSTEM', desc='CardOS specifics')</span><br><span style="color: hsl(120, 100%, 40%);">+        files = [</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_PIN('6f01', 'EF.CHV1'),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_PIN('6f81', 'EF.CHV2'),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_PIN('6f0a', 'EF.ADM1'),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_PIN('6f0b', 'EF.ADM2'),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_PIN('6f0c', 'EF.ADM3'),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_PIN('6f0d', 'EF.ADM4'),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_MILENAGE_CFG(),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_0348_KEY(),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_SIM_AUTH_COUNTER(),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_SIM_AUTH_KEY(),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_0348_COUNT(),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_GP_COUNT(),</span><br><span style="color: hsl(120, 100%, 40%);">+            EF_GP_DIV_DATA(),</span><br><span style="color: hsl(120, 100%, 40%);">+            ]</span><br><span style="color: hsl(120, 100%, 40%);">+        self.add_files(files)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def decode_select_response(self, resp_hex):</span><br><span style="color: hsl(120, 100%, 40%);">+        return pySim.ts_102_221.decode_select_response(resp_hex)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_USIM_SQN(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af30', name='EF.USIM_SQN'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='SQN parameters for AKA')</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag1 = BitStruct('skip_next_sqn_check'/Bit, 'delta_max_check'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                          'age_limit_check'/Bit, 'sqn_check'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                          'ind_len'/BitsInteger(4))</span><br><span style="color: hsl(120, 100%, 40%);">+        Flag2 = BitStruct('rfu'/BitsRFU(5), 'dont_clear_amf_for_macs'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                          'aus_concealed'/Bit, 'autn_concealed'/Bit)</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = Struct('flag1'/Flag1, 'flag2'/Flag2,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'delta_max'/BytesInteger(6), 'age_limit'/BytesInteger(6),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'freshness'/HexAdapter(GreedyBytes))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_USIM_AUTH_KEY(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af20', name='EF.USIM_AUTH_KEY'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='USIM authentication key')</span><br><span style="color: hsl(120, 100%, 40%);">+        CfgByte = BitStruct(Bit, 'only_4bytes_res_in_3g'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'use_sres_deriv_func_2_in_3g'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'use_opc_instead_of_op'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'algorithm'/Enum(Nibble, milenage=4, sha1_aka=5, xor=15))</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = Struct('cfg'/CfgByte,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'key'/Bytes(16),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'op'/If(this.cfg.algorithm=='milenage' and not this.cfg.use_opc_instead_of_op, Bytes(16)),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'opc'/If(this.cfg.algorithm=='milenage' and this.cfg.use_opc_instead_of_op, Bytes(16))</span><br><span style="color: hsl(120, 100%, 40%);">+                                 )</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_USIM_AUTH_KEY_2G(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af22', name='EF.USIM_AUTH_KEY_2G'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='USIM authentication key in 2G context')</span><br><span style="color: hsl(120, 100%, 40%);">+        CfgByte = BitStruct(Bit, 'only_4bytes_res_in_3g'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'use_sres_deriv_func_2_in_3g'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'use_opc_instead_of_op'/Bit,</span><br><span style="color: hsl(120, 100%, 40%);">+                            'algorithm'/Enum(Nibble, milenage=4, comp128v1=1, comp128v2=2, comp128v3=3))</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = Struct('cfg'/CfgByte,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'key'/Bytes(16),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'op'/If(this.cfg.algorithm=='milenage' and not this.cfg.use_opc_instead_of_op, Bytes(16)),</span><br><span style="color: hsl(120, 100%, 40%);">+                                 'opc'/If(this.cfg.algorithm=='milenage' and this.cfg.use_opc_instead_of_op, Bytes(16))</span><br><span style="color: hsl(120, 100%, 40%);">+                                 )</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_GBA_SK(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af31', name='EF.GBA_SK'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='Secret key for GBA key derivation')</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = GreedyBytes</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_GBA_REC_LIST(TransparentEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af32', name='EF.GBA_REC_LIST'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='Secret key for GBA key derivation')</span><br><span style="color: hsl(120, 100%, 40%);">+        # integers representing record numbers in EF-GBANL</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = GreedyRange(Int8ub)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class EF_GBA_INT_KEY(LinFixedEF):</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, fid='af33', name='EF.GBA_INT_KEY'):</span><br><span style="color: hsl(120, 100%, 40%);">+        super().__init__(fid, name=name, desc='Secret key for GBA key derivation', rec_len={32,32})</span><br><span style="color: hsl(120, 100%, 40%);">+        self._construct = GreedyBytes</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class SysmocomSJA2(CardModel):</span><br><span style="color: hsl(120, 100%, 40%);">+    _atrs = [ "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9",</span><br><span style="color: hsl(120, 100%, 40%);">+              "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2",</span><br><span style="color: hsl(120, 100%, 40%);">+              "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5" ]</span><br><span style="color: hsl(120, 100%, 40%);">+    @classmethod</span><br><span style="color: hsl(120, 100%, 40%);">+    def add_files(cls, rs:RuntimeState):</span><br><span style="color: hsl(120, 100%, 40%);">+        """Add sysmocom SJA2 specific files to given RuntimeState."""</span><br><span style="color: hsl(120, 100%, 40%);">+        rs.mf.add_file(DF_SYSTEM())</span><br><span style="color: hsl(120, 100%, 40%);">+        # optional USIM application</span><br><span style="color: hsl(120, 100%, 40%);">+        if 'a0000000871002' in rs.mf.applications:</span><br><span style="color: hsl(120, 100%, 40%);">+            usim_adf = rs.mf.applications['a0000000871002']</span><br><span style="color: hsl(120, 100%, 40%);">+            files_adf_usim = [</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_USIM_AUTH_KEY(),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_USIM_AUTH_KEY_2G(),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_GBA_SK(),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_GBA_REC_LIST(),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_GBA_INT_KEY(),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_USIM_SQN(),</span><br><span style="color: hsl(120, 100%, 40%);">+                ]</span><br><span style="color: hsl(120, 100%, 40%);">+            usim_adf.add_files(files_adf_usim)</span><br><span style="color: hsl(120, 100%, 40%);">+        # optional ISIM application</span><br><span style="color: hsl(120, 100%, 40%);">+        if 'a0000000871004' in rs.mf.applications:</span><br><span style="color: hsl(120, 100%, 40%);">+            isim_adf = rs.mf.applications['a0000000871004']</span><br><span style="color: hsl(120, 100%, 40%);">+            files_adf_isim = [</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_USIM_AUTH_KEY(name='EF.ISIM_AUTH_KEY'),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_USIM_AUTH_KEY_2G(name='EF.ISIM_AUTH_KEY_2G'),</span><br><span style="color: hsl(120, 100%, 40%);">+                EF_USIM_SQN(name='EF.ISIM_SQN'),</span><br><span style="color: hsl(120, 100%, 40%);">+                ]</span><br><span style="color: hsl(120, 100%, 40%);">+            isim_adf.add_files(files_adf_isim)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/pysim/+/25784">change 25784</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/+/25784"/><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: Id410489841bb9020ddbf74de9114d808b1d5adb6 </div>
<div style="display:none"> Gerrit-Change-Number: 25784 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-CC: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>