Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 1 | # coding=utf-8 |
Harald Welte | 0489ae6 | 2023-05-24 10:28:34 +0200 | [diff] [blame] | 2 | """Utilities / Functions related to sysmocom SJA2/SJA5 cards |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 3 | |
Harald Welte | 0489ae6 | 2023-05-24 10:28:34 +0200 | [diff] [blame] | 4 | (C) 2021-2023 by Harald Welte <laforge@osmocom.org> |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 5 | |
| 6 | This program is free software: you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation, either version 2 of the License, or |
| 9 | (at your option) any later version. |
| 10 | |
| 11 | This program is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | """ |
| 19 | |
| 20 | from pytlv.TLV import * |
| 21 | from struct import pack, unpack |
| 22 | from pySim.utils import * |
| 23 | from pySim.filesystem import * |
Harald Welte | 531894d | 2023-07-11 19:11:11 +0200 | [diff] [blame] | 24 | from pySim.runtime import RuntimeState |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 25 | from pySim.ts_102_221 import CardProfileUICC |
| 26 | from pySim.construct import * |
| 27 | from construct import * |
| 28 | import pySim |
| 29 | |
| 30 | key_type2str = { |
| 31 | 0: 'kic', |
| 32 | 1: 'kid', |
| 33 | 2: 'kik', |
| 34 | 3: 'any', |
| 35 | } |
| 36 | |
| 37 | key_algo2str = { |
| 38 | 0: 'des', |
| 39 | 1: 'aes' |
| 40 | } |
| 41 | |
| 42 | mac_length = { |
| 43 | 0: 8, |
| 44 | 1: 4 |
| 45 | } |
| 46 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 47 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 48 | class EF_PIN(TransparentEF): |
Harald Welte | db1684d | 2023-12-28 15:06:11 +0100 | [diff] [blame] | 49 | _test_de_encode = [ |
| 50 | ( 'f1030331323334ffffffff0a0a3132333435363738', |
| 51 | { 'state': { 'valid': True, 'change_able': True, 'unblock_able': True, 'disable_able': True, |
| 52 | 'not_initialized': False, 'disabled': True }, |
| 53 | 'attempts_remaining': 3, 'maximum_attempts': 3, 'pin': '31323334', |
| 54 | 'puk': { 'attempts_remaining': 10, 'maximum_attempts': 10, 'puk': '3132333435363738' } |
| 55 | } ), |
| 56 | ( 'f003039999999999999999', |
| 57 | { 'state': { 'valid': True, 'change_able': True, 'unblock_able': True, 'disable_able': True, |
| 58 | 'not_initialized': False, 'disabled': False }, |
| 59 | 'attempts_remaining': 3, 'maximum_attempts': 3, 'pin': '9999999999999999', |
| 60 | 'puk': None } ), |
| 61 | ] |
| 62 | def __init__(self, fid='6f01', name='EF.CHV1'): |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 63 | super().__init__(fid, name=name, desc='%s PIN file' % name) |
Harald Welte | db1684d | 2023-12-28 15:06:11 +0100 | [diff] [blame] | 64 | StateByte = FlagsEnum(Byte, disabled=1, not_initialized=2, disable_able=0x10, unblock_able=0x20, |
| 65 | change_able=0x40, valid=0x80) |
| 66 | PukStruct = Struct('attempts_remaining'/Int8ub, |
| 67 | 'maximum_attempts'/Int8ub, |
| 68 | 'puk'/HexAdapter(Rpad(Bytes(8)))) |
| 69 | self._construct = Struct('state'/StateByte, |
| 70 | 'attempts_remaining'/Int8ub, |
| 71 | 'maximum_attempts'/Int8ub, |
| 72 | 'pin'/HexAdapter(Rpad(Bytes(8))), |
| 73 | 'puk'/Optional(PukStruct)) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 74 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 75 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 76 | class EF_MILENAGE_CFG(TransparentEF): |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 77 | _test_de_encode = [ |
| 78 | ( '40002040600000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000020000000000000000000000000000000400000000000000000000000000000008', |
| 79 | {"r1": 64, "r2": 0, "r3": 32, "r4": 64, "r5": 96, "c1": "00000000000000000000000000000000", "c2": |
| 80 | "00000000000000000000000000000001", "c3": "00000000000000000000000000000002", "c4": |
| 81 | "00000000000000000000000000000004", "c5": "00000000000000000000000000000008"} ), |
| 82 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 83 | def __init__(self, fid='6f21', name='EF.MILENAGE_CFG', desc='Milenage connfiguration'): |
| 84 | super().__init__(fid, name=name, desc=desc) |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 85 | self._construct = Struct('r1'/Int8ub, 'r2'/Int8ub, 'r3'/Int8ub, 'r4'/Int8ub, 'r5'/Int8ub, |
| 86 | 'c1'/HexAdapter(Bytes(16)), |
| 87 | 'c2'/HexAdapter(Bytes(16)), |
| 88 | 'c3'/HexAdapter(Bytes(16)), |
| 89 | 'c4'/HexAdapter(Bytes(16)), |
| 90 | 'c5'/HexAdapter(Bytes(16))) |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 91 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 92 | |
| 93 | class EF_0348_KEY(LinFixedEF): |
| 94 | def __init__(self, fid='6f22', name='EF.0348_KEY', desc='TS 03.48 OTA Keys'): |
Harald Welte | 99e4cc0 | 2022-07-21 15:25:47 +0200 | [diff] [blame] | 95 | super().__init__(fid, name=name, desc=desc, rec_len=(27, 35)) |
Harald Welte | 954ce95 | 2023-05-27 20:08:09 +0200 | [diff] [blame] | 96 | KeyLenAndType = BitStruct('mac_length'/Mapping(Bit, {8:0, 4:1}), |
| 97 | 'algorithm'/Enum(Bit, des=0, aes=1), |
| 98 | 'key_length'/MultiplyAdapter(BitsInteger(3), 8), |
| 99 | '_rfu'/BitsRFU(1), |
| 100 | 'key_type'/Enum(BitsInteger(2), kic=0, kid=1, kik=2, any=3)) |
| 101 | self._construct = Struct('security_domain'/Int8ub, |
| 102 | 'key_set_version'/Int8ub, |
| 103 | 'key_len_and_type'/KeyLenAndType, |
| 104 | 'key'/HexAdapter(Bytes(this.key_len_and_type.key_length))) |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 105 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 106 | |
| 107 | class EF_0348_COUNT(LinFixedEF): |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 108 | _test_de_encode = [ |
| 109 | ( 'fe010000000000', {"sec_domain": 254, "key_set_version": 1, "counter": "0000000000"} ), |
| 110 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 111 | def __init__(self, fid='6f23', name='EF.0348_COUNT', desc='TS 03.48 OTA Counters'): |
Harald Welte | 99e4cc0 | 2022-07-21 15:25:47 +0200 | [diff] [blame] | 112 | super().__init__(fid, name=name, desc=desc, rec_len=(7, 7)) |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 113 | self._construct = Struct('sec_domain'/Int8ub, |
| 114 | 'key_set_version'/Int8ub, |
| 115 | 'counter'/HexAdapter(Bytes(5))) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 116 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 117 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 118 | class EF_SIM_AUTH_COUNTER(TransparentEF): |
| 119 | def __init__(self, fid='af24', name='EF.SIM_AUTH_COUNTER'): |
| 120 | super().__init__(fid, name=name, desc='Number of remaining RUN GSM ALGORITHM executions') |
| 121 | self._construct = Struct('num_run_gsm_algo_remain'/Int32ub) |
| 122 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 123 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 124 | class EF_GP_COUNT(LinFixedEF): |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 125 | _test_de_encode = [ |
| 126 | ( '0070000000', {"sec_domain": 0, "key_set_version": 112, "counter": 0, "rfu": 0} ), |
| 127 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 128 | def __init__(self, fid='6f26', name='EF.GP_COUNT', desc='GP SCP02 Counters'): |
Harald Welte | 99e4cc0 | 2022-07-21 15:25:47 +0200 | [diff] [blame] | 129 | super().__init__(fid, name=name, desc=desc, rec_len=(5, 5)) |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 130 | self._construct = Struct('sec_domain'/Int8ub, |
| 131 | 'key_set_version'/Int8ub, |
| 132 | 'counter'/Int16ub, |
| 133 | 'rfu'/Int8ub) |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 134 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 135 | class EF_GP_DIV_DATA(LinFixedEF): |
| 136 | def __init__(self, fid='6f27', name='EF.GP_DIV_DATA', desc='GP SCP02 key diversification data'): |
Harald Welte | 99e4cc0 | 2022-07-21 15:25:47 +0200 | [diff] [blame] | 137 | super().__init__(fid, name=name, desc=desc, rec_len=(12, 12)) |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 138 | |
Harald Welte | f6b37af | 2023-01-24 15:42:26 +0100 | [diff] [blame] | 139 | def _decode_record_bin(self, raw_bin_data, **kwargs): |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 140 | u = unpack('!BB8s', raw_bin_data) |
| 141 | return {'sec_domain': u[0], 'key_set_version': u[1], 'key_div_data': u[2].hex()} |
| 142 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 143 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 144 | class EF_SIM_AUTH_KEY(TransparentEF): |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 145 | _test_de_encode = [ |
| 146 | ( '14000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 147 | {"cfg": {"sres_deriv_func": 1, "use_opc_instead_of_op": True, "algorithm": "milenage"}, "key": |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 148 | "000102030405060708090a0b0c0d0e0f", "op_opc": "101112131415161718191a1b1c1d1e1f"} ), |
| 149 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 150 | def __init__(self, fid='6f20', name='EF.SIM_AUTH_KEY'): |
| 151 | super().__init__(fid, name=name, desc='USIM authentication key') |
Harald Welte | cfa3015 | 2022-07-22 17:12:27 +0200 | [diff] [blame] | 152 | CfgByte = BitStruct(Padding(2), |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 153 | 'sres_deriv_func'/Mapping(Bit, {1:0, 2:1}), |
| 154 | 'use_opc_instead_of_op'/Flag, |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 155 | 'algorithm'/Enum(Nibble, milenage=4, comp128v1=1, comp128v2=2, comp128v3=3)) |
| 156 | self._construct = Struct('cfg'/CfgByte, |
Harald Welte | 3c98d5e | 2022-07-20 07:40:05 +0200 | [diff] [blame] | 157 | 'key'/HexAdapter(Bytes(16)), |
Philipp Maier | 4f888a0 | 2022-12-02 12:30:12 +0100 | [diff] [blame] | 158 | 'op_opc' /HexAdapter(Bytes(16))) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 159 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 160 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 161 | class DF_SYSTEM(CardDF): |
| 162 | def __init__(self): |
| 163 | super().__init__(fid='a515', name='DF.SYSTEM', desc='CardOS specifics') |
| 164 | files = [ |
| 165 | EF_PIN('6f01', 'EF.CHV1'), |
| 166 | EF_PIN('6f81', 'EF.CHV2'), |
| 167 | EF_PIN('6f0a', 'EF.ADM1'), |
| 168 | EF_PIN('6f0b', 'EF.ADM2'), |
| 169 | EF_PIN('6f0c', 'EF.ADM3'), |
| 170 | EF_PIN('6f0d', 'EF.ADM4'), |
| 171 | EF_MILENAGE_CFG(), |
| 172 | EF_0348_KEY(), |
| 173 | EF_SIM_AUTH_COUNTER(), |
| 174 | EF_SIM_AUTH_KEY(), |
| 175 | EF_0348_COUNT(), |
| 176 | EF_GP_COUNT(), |
| 177 | EF_GP_DIV_DATA(), |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 178 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 179 | self.add_files(files) |
| 180 | |
| 181 | def decode_select_response(self, resp_hex): |
Philipp Maier | 5998a3a | 2021-11-16 15:16:39 +0100 | [diff] [blame] | 182 | return pySim.ts_102_221.CardProfileUICC.decode_select_response(resp_hex) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 183 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 184 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 185 | class EF_USIM_SQN(TransparentEF): |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 186 | _test_de_encode = [ |
| 187 | ( 'd503000200000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 188 | {"flag1": {"skip_next_sqn_check": True, "delta_max_check": True, "age_limit_check": False, "sqn_check": True, |
| 189 | "ind_len": 5}, "flag2": {"rfu": 0, "dont_clear_amf_for_macs": False, "aus_concealed": True, |
| 190 | "autn_concealed": True}, "delta_max": 8589934592, "age_limit": |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 191 | 8589934592, "freshness": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 192 | 0, 0, 0, 0, 0, 0, 0, 0]} ), |
| 193 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 194 | def __init__(self, fid='af30', name='EF.USIM_SQN'): |
| 195 | super().__init__(fid, name=name, desc='SQN parameters for AKA') |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 196 | Flag1 = BitStruct('skip_next_sqn_check'/Flag, 'delta_max_check'/Flag, |
| 197 | 'age_limit_check'/Flag, 'sqn_check'/Flag, |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 198 | 'ind_len'/BitsInteger(4)) |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 199 | Flag2 = BitStruct('rfu'/BitsRFU(5), 'dont_clear_amf_for_macs'/Flag, |
| 200 | 'aus_concealed'/Flag, 'autn_concealed'/Flag) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 201 | self._construct = Struct('flag1'/Flag1, 'flag2'/Flag2, |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 202 | 'delta_max' / |
| 203 | BytesInteger(6), 'age_limit'/BytesInteger(6), |
Harald Welte | eb45838 | 2021-10-16 10:44:23 +0200 | [diff] [blame] | 204 | 'freshness'/GreedyRange(BytesInteger(6))) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 205 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 206 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 207 | class EF_USIM_AUTH_KEY(TransparentEF): |
| 208 | def __init__(self, fid='af20', name='EF.USIM_AUTH_KEY'): |
| 209 | super().__init__(fid, name=name, desc='USIM authentication key') |
Harald Welte | 0365058 | 2023-05-29 21:07:24 +0200 | [diff] [blame] | 210 | Algorithm = Enum(Nibble, milenage=4, sha1_aka=5, tuak=6, xor=15) |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 211 | CfgByte = BitStruct(Padding(1), 'only_4bytes_res_in_3g'/Flag, |
| 212 | 'sres_deriv_func_in_2g'/Mapping(Bit, {1:0, 2:1}), |
Harald Welte | 0365058 | 2023-05-29 21:07:24 +0200 | [diff] [blame] | 213 | 'use_opc_instead_of_op'/Mapping(Bit, {False:0, True:1}), |
| 214 | 'algorithm'/Algorithm) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 215 | self._construct = Struct('cfg'/CfgByte, |
Harald Welte | 3c98d5e | 2022-07-20 07:40:05 +0200 | [diff] [blame] | 216 | 'key'/HexAdapter(Bytes(16)), |
Philipp Maier | 4f888a0 | 2022-12-02 12:30:12 +0100 | [diff] [blame] | 217 | 'op_opc' /HexAdapter(Bytes(16))) |
Harald Welte | 0365058 | 2023-05-29 21:07:24 +0200 | [diff] [blame] | 218 | # TUAK has a rather different layout for the data, so we define a different |
| 219 | # construct below and use explicit _{decode,encode}_bin() methods for separating |
| 220 | # the TUAK and non-TUAK situation |
| 221 | CfgByteTuak = BitStruct(Padding(1), |
| 222 | 'key_length'/Mapping(Bit, {128:0, 256:1}), |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 223 | 'sres_deriv_func_in_2g'/Mapping(Bit, {1:0, 2:1}), |
Harald Welte | 0365058 | 2023-05-29 21:07:24 +0200 | [diff] [blame] | 224 | 'use_opc_instead_of_op'/Mapping(Bit, {False:0, True:1}), |
| 225 | 'algorithm'/Algorithm) |
| 226 | TuakCfgByte = BitStruct(Padding(1), |
| 227 | 'ck_and_ik_size'/Mapping(Bit, {128:0, 256:1}), |
| 228 | 'mac_size'/Mapping(BitsInteger(3), {64:0, 128:1, 256:2}), |
| 229 | 'res_size'/Mapping(BitsInteger(3), {32:0, 64:1, 128:2, 256:3})) |
| 230 | self._constr_tuak = Struct('cfg'/CfgByteTuak, |
| 231 | 'tuak_cfg'/TuakCfgByte, |
| 232 | 'num_of_keccak_iterations'/Int8ub, |
| 233 | 'op_opc'/HexAdapter(Bytes(32)), |
Harald Welte | 19b4a97 | 2023-06-08 17:18:31 +0200 | [diff] [blame] | 234 | 'k'/HexAdapter(Bytes(this.cfg.key_length//8))) |
Harald Welte | 0365058 | 2023-05-29 21:07:24 +0200 | [diff] [blame] | 235 | |
| 236 | def _decode_bin(self, raw_bin_data: bytearray) -> dict: |
| 237 | if raw_bin_data[0] & 0x0F == 0x06: |
| 238 | return parse_construct(self._constr_tuak, raw_bin_data) |
| 239 | else: |
| 240 | return parse_construct(self._construct, raw_bin_data) |
| 241 | |
| 242 | def _encode_bin(self, abstract_data: dict) -> bytearray: |
| 243 | if abstract_data['cfg']['algorithm'] == 'tuak': |
Harald Welte | a5eb924 | 2023-12-23 10:20:20 +0100 | [diff] [blame] | 244 | return build_construct(self._constr_tuak, abstract_data) |
Harald Welte | 0365058 | 2023-05-29 21:07:24 +0200 | [diff] [blame] | 245 | else: |
Harald Welte | a5eb924 | 2023-12-23 10:20:20 +0100 | [diff] [blame] | 246 | return build_construct(self._construct, abstract_data) |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 247 | |
| 248 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 249 | class EF_USIM_AUTH_KEY_2G(TransparentEF): |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 250 | _test_de_encode = [ |
| 251 | ( '14000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f', |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 252 | {"cfg": {"only_4bytes_res_in_3g": False, "sres_deriv_func_in_2g": 1, "use_opc_instead_of_op": True, |
Harald Welte | 7be68b2 | 2023-11-02 00:19:53 +0100 | [diff] [blame] | 253 | "algorithm": "milenage"}, "key": "000102030405060708090a0b0c0d0e0f", "op_opc": |
| 254 | "101112131415161718191a1b1c1d1e1f"} ), |
| 255 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 256 | def __init__(self, fid='af22', name='EF.USIM_AUTH_KEY_2G'): |
| 257 | super().__init__(fid, name=name, desc='USIM authentication key in 2G context') |
Harald Welte | 45477a7 | 2023-11-03 01:33:06 +0100 | [diff] [blame] | 258 | CfgByte = BitStruct(Padding(1), 'only_4bytes_res_in_3g'/Flag, |
| 259 | 'sres_deriv_func_in_2g'/Mapping(Bit, {1:0, 2:1}), |
| 260 | 'use_opc_instead_of_op'/Flag, |
Harald Welte | 557c136 | 2023-05-29 15:26:22 +0200 | [diff] [blame] | 261 | 'algorithm'/Enum(Nibble, milenage=4, comp128v1=1, comp128v2=2, comp128v3=3, xor=14)) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 262 | self._construct = Struct('cfg'/CfgByte, |
Harald Welte | 3c98d5e | 2022-07-20 07:40:05 +0200 | [diff] [blame] | 263 | 'key'/HexAdapter(Bytes(16)), |
Philipp Maier | 4f888a0 | 2022-12-02 12:30:12 +0100 | [diff] [blame] | 264 | 'op_opc' /HexAdapter(Bytes(16))) |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 265 | |
| 266 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 267 | class EF_GBA_SK(TransparentEF): |
| 268 | def __init__(self, fid='af31', name='EF.GBA_SK'): |
| 269 | super().__init__(fid, name=name, desc='Secret key for GBA key derivation') |
| 270 | self._construct = GreedyBytes |
| 271 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 272 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 273 | class EF_GBA_REC_LIST(TransparentEF): |
| 274 | def __init__(self, fid='af32', name='EF.GBA_REC_LIST'): |
| 275 | super().__init__(fid, name=name, desc='Secret key for GBA key derivation') |
| 276 | # integers representing record numbers in EF-GBANL |
| 277 | self._construct = GreedyRange(Int8ub) |
| 278 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 279 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 280 | class EF_GBA_INT_KEY(LinFixedEF): |
| 281 | def __init__(self, fid='af33', name='EF.GBA_INT_KEY'): |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 282 | super().__init__(fid, name=name, |
Harald Welte | 99e4cc0 | 2022-07-21 15:25:47 +0200 | [diff] [blame] | 283 | desc='Secret key for GBA key derivation', rec_len=(32, 32)) |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 284 | self._construct = GreedyBytes |
| 285 | |
| 286 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 287 | class SysmocomSJA2(CardModel): |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 288 | _atrs = ["3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9", |
| 289 | "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2", |
| 290 | "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"] |
| 291 | |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 292 | @classmethod |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 293 | def add_files(cls, rs: RuntimeState): |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 294 | """Add sysmocom SJA2 specific files to given RuntimeState.""" |
| 295 | rs.mf.add_file(DF_SYSTEM()) |
| 296 | # optional USIM application |
| 297 | if 'a0000000871002' in rs.mf.applications: |
| 298 | usim_adf = rs.mf.applications['a0000000871002'] |
| 299 | files_adf_usim = [ |
| 300 | EF_USIM_AUTH_KEY(), |
| 301 | EF_USIM_AUTH_KEY_2G(), |
| 302 | EF_GBA_SK(), |
| 303 | EF_GBA_REC_LIST(), |
| 304 | EF_GBA_INT_KEY(), |
| 305 | EF_USIM_SQN(), |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 306 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 307 | usim_adf.add_files(files_adf_usim) |
| 308 | # optional ISIM application |
| 309 | if 'a0000000871004' in rs.mf.applications: |
| 310 | isim_adf = rs.mf.applications['a0000000871004'] |
| 311 | files_adf_isim = [ |
| 312 | EF_USIM_AUTH_KEY(name='EF.ISIM_AUTH_KEY'), |
| 313 | EF_USIM_AUTH_KEY_2G(name='EF.ISIM_AUTH_KEY_2G'), |
| 314 | EF_USIM_SQN(name='EF.ISIM_SQN'), |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 315 | ] |
Harald Welte | f44256c | 2021-10-14 15:53:39 +0200 | [diff] [blame] | 316 | isim_adf.add_files(files_adf_isim) |
Harald Welte | 0489ae6 | 2023-05-24 10:28:34 +0200 | [diff] [blame] | 317 | |
| 318 | class SysmocomSJA5(CardModel): |
| 319 | _atrs = ["3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 51 CC", |
| 320 | "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 65 F8", |
| 321 | "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 35 75 30 35 02 59 C4"] |
| 322 | |
| 323 | @classmethod |
| 324 | def add_files(cls, rs: RuntimeState): |
| 325 | """Add sysmocom SJA2 specific files to given RuntimeState.""" |
| 326 | rs.mf.add_file(DF_SYSTEM()) |
| 327 | # optional USIM application |
| 328 | if 'a0000000871002' in rs.mf.applications: |
| 329 | usim_adf = rs.mf.applications['a0000000871002'] |
| 330 | files_adf_usim = [ |
| 331 | EF_USIM_AUTH_KEY(), |
| 332 | EF_USIM_AUTH_KEY_2G(), |
| 333 | EF_GBA_SK(), |
| 334 | EF_GBA_REC_LIST(), |
| 335 | EF_GBA_INT_KEY(), |
| 336 | EF_USIM_SQN(), |
| 337 | ] |
| 338 | usim_adf.add_files(files_adf_usim) |
| 339 | # optional ISIM application |
| 340 | if 'a0000000871004' in rs.mf.applications: |
| 341 | isim_adf = rs.mf.applications['a0000000871004'] |
| 342 | files_adf_isim = [ |
| 343 | EF_USIM_AUTH_KEY(name='EF.ISIM_AUTH_KEY'), |
| 344 | EF_USIM_AUTH_KEY_2G(name='EF.ISIM_AUTH_KEY_2G'), |
| 345 | EF_USIM_SQN(name='EF.ISIM_SQN'), |
| 346 | ] |
| 347 | isim_adf.add_files(files_adf_isim) |