blob: 49677011cb63d6422738e296a3d8839a19422f30 [file] [log] [blame]
Harald Weltef44256c2021-10-14 15:53:39 +02001# coding=utf-8
2"""Utilities / Functions related to sysmocom SJA2 cards
3
4(C) 2021 by Harald Welte <laforge@osmocom.org>
5
6This program is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18"""
19
20from pytlv.TLV import *
21from struct import pack, unpack
22from pySim.utils import *
23from pySim.filesystem import *
24from pySim.ts_102_221 import CardProfileUICC
25from pySim.construct import *
26from construct import *
27import pySim
28
29key_type2str = {
30 0: 'kic',
31 1: 'kid',
32 2: 'kik',
33 3: 'any',
34}
35
36key_algo2str = {
37 0: 'des',
38 1: 'aes'
39}
40
41mac_length = {
42 0: 8,
43 1: 4
44}
45
Harald Weltec91085e2022-02-10 18:05:45 +010046
Harald Weltef44256c2021-10-14 15:53:39 +020047class EF_PIN(TransparentEF):
48 def __init__(self, fid, name):
49 super().__init__(fid, name=name, desc='%s PIN file' % name)
Harald Weltec91085e2022-02-10 18:05:45 +010050
Harald Weltef44256c2021-10-14 15:53:39 +020051 def _decode_bin(self, raw_bin_data):
52 u = unpack('!BBB8s', raw_bin_data[:11])
Harald Weltec91085e2022-02-10 18:05:45 +010053 res = {'enabled': (True, False)[u[0] & 0x01],
54 'initialized': (True, False)[u[0] & 0x02],
55 'disable_able': (False, True)[u[0] & 0x10],
56 'unblock_able': (False, True)[u[0] & 0x20],
57 'change_able': (False, True)[u[0] & 0x40],
58 'valid': (False, True)[u[0] & 0x80],
59 'attempts_remaining': u[1],
60 'maximum_attempts': u[2],
61 'pin': u[3].hex(),
62 }
Harald Weltef44256c2021-10-14 15:53:39 +020063 if len(raw_bin_data) == 21:
64 u2 = unpack('!BB8s', raw_bin_data[11:10])
65 res['attempts_remaining_puk'] = u2[0]
66 res['maximum_attempts_puk'] = u2[1]
67 res['puk'] = u2[2].hex()
68 return res
69
Harald Weltec91085e2022-02-10 18:05:45 +010070
Harald Weltef44256c2021-10-14 15:53:39 +020071class EF_MILENAGE_CFG(TransparentEF):
72 def __init__(self, fid='6f21', name='EF.MILENAGE_CFG', desc='Milenage connfiguration'):
73 super().__init__(fid, name=name, desc=desc)
Harald Weltec91085e2022-02-10 18:05:45 +010074
Harald Weltef44256c2021-10-14 15:53:39 +020075 def _decode_bin(self, raw_bin_data):
76 u = unpack('!BBBBB16s16s16s16s16s', raw_bin_data)
77 return {'r1': u[0], 'r2': u[1], 'r3': u[2], 'r4': u[3], 'r5': u[4],
78 'c1': u[5].hex(),
79 'c2': u[6].hex(),
80 'c3': u[7].hex(),
81 'c4': u[8].hex(),
82 'c5': u[9].hex(),
Harald Weltec91085e2022-02-10 18:05:45 +010083 }
84
Harald Weltef44256c2021-10-14 15:53:39 +020085
86class EF_0348_KEY(LinFixedEF):
87 def __init__(self, fid='6f22', name='EF.0348_KEY', desc='TS 03.48 OTA Keys'):
Harald Welte99e4cc02022-07-21 15:25:47 +020088 super().__init__(fid, name=name, desc=desc, rec_len=(27, 35))
Harald Weltec91085e2022-02-10 18:05:45 +010089
Harald Weltef6b37af2023-01-24 15:42:26 +010090 def _decode_record_bin(self, raw_bin_data, **kwargs):
Harald Weltef44256c2021-10-14 15:53:39 +020091 u = unpack('!BBB', raw_bin_data[0:3])
92 key_algo = (u[2] >> 6) & 1
93 key_length = ((u[2] >> 3) & 3) * 8
94 return {'sec_domain': u[0],
95 'key_set_version': u[1],
96 'key_type': key_type2str[u[2] & 3],
97 'key_length': key_length,
98 'algorithm': key_algo2str[key_algo],
99 'mac_length': mac_length[(u[2] >> 7)],
100 'key': raw_bin_data[3:key_length].hex()
Harald Weltec91085e2022-02-10 18:05:45 +0100101 }
102
Harald Weltef44256c2021-10-14 15:53:39 +0200103
104class EF_0348_COUNT(LinFixedEF):
105 def __init__(self, fid='6f23', name='EF.0348_COUNT', desc='TS 03.48 OTA Counters'):
Harald Welte99e4cc02022-07-21 15:25:47 +0200106 super().__init__(fid, name=name, desc=desc, rec_len=(7, 7))
Harald Weltec91085e2022-02-10 18:05:45 +0100107
Harald Weltef6b37af2023-01-24 15:42:26 +0100108 def _decode_record_bin(self, raw_bin_data, **kwargs):
Harald Weltef44256c2021-10-14 15:53:39 +0200109 u = unpack('!BB5s', raw_bin_data)
110 return {'sec_domain': u[0], 'key_set_version': u[1], 'counter': u[2]}
111
Harald Weltec91085e2022-02-10 18:05:45 +0100112
Harald Weltef44256c2021-10-14 15:53:39 +0200113class EF_SIM_AUTH_COUNTER(TransparentEF):
114 def __init__(self, fid='af24', name='EF.SIM_AUTH_COUNTER'):
115 super().__init__(fid, name=name, desc='Number of remaining RUN GSM ALGORITHM executions')
116 self._construct = Struct('num_run_gsm_algo_remain'/Int32ub)
117
Harald Weltec91085e2022-02-10 18:05:45 +0100118
Harald Weltef44256c2021-10-14 15:53:39 +0200119class EF_GP_COUNT(LinFixedEF):
120 def __init__(self, fid='6f26', name='EF.GP_COUNT', desc='GP SCP02 Counters'):
Harald Welte99e4cc02022-07-21 15:25:47 +0200121 super().__init__(fid, name=name, desc=desc, rec_len=(5, 5))
Harald Weltec91085e2022-02-10 18:05:45 +0100122
Harald Weltef6b37af2023-01-24 15:42:26 +0100123 def _decode_record_bin(self, raw_bin_data, **kwargs):
Harald Weltef44256c2021-10-14 15:53:39 +0200124 u = unpack('!BBHB', raw_bin_data)
125 return {'sec_domain': u[0], 'key_set_version': u[1], 'counter': u[2], 'rfu': u[3]}
126
Harald Weltec91085e2022-02-10 18:05:45 +0100127
Harald Weltef44256c2021-10-14 15:53:39 +0200128class EF_GP_DIV_DATA(LinFixedEF):
129 def __init__(self, fid='6f27', name='EF.GP_DIV_DATA', desc='GP SCP02 key diversification data'):
Harald Welte99e4cc02022-07-21 15:25:47 +0200130 super().__init__(fid, name=name, desc=desc, rec_len=(12, 12))
Harald Weltec91085e2022-02-10 18:05:45 +0100131
Harald Weltef6b37af2023-01-24 15:42:26 +0100132 def _decode_record_bin(self, raw_bin_data, **kwargs):
Harald Weltef44256c2021-10-14 15:53:39 +0200133 u = unpack('!BB8s', raw_bin_data)
134 return {'sec_domain': u[0], 'key_set_version': u[1], 'key_div_data': u[2].hex()}
135
Harald Weltec91085e2022-02-10 18:05:45 +0100136
Harald Weltef44256c2021-10-14 15:53:39 +0200137class EF_SIM_AUTH_KEY(TransparentEF):
138 def __init__(self, fid='6f20', name='EF.SIM_AUTH_KEY'):
139 super().__init__(fid, name=name, desc='USIM authentication key')
Harald Weltecfa30152022-07-22 17:12:27 +0200140 CfgByte = BitStruct(Padding(2),
Harald Weltef44256c2021-10-14 15:53:39 +0200141 'use_sres_deriv_func_2'/Bit,
142 'use_opc_instead_of_op'/Bit,
143 'algorithm'/Enum(Nibble, milenage=4, comp128v1=1, comp128v2=2, comp128v3=3))
144 self._construct = Struct('cfg'/CfgByte,
Harald Welte3c98d5e2022-07-20 07:40:05 +0200145 'key'/HexAdapter(Bytes(16)),
Philipp Maier4f888a02022-12-02 12:30:12 +0100146 'op_opc' /HexAdapter(Bytes(16)))
Harald Weltef44256c2021-10-14 15:53:39 +0200147
Harald Weltec91085e2022-02-10 18:05:45 +0100148
Harald Weltef44256c2021-10-14 15:53:39 +0200149class DF_SYSTEM(CardDF):
150 def __init__(self):
151 super().__init__(fid='a515', name='DF.SYSTEM', desc='CardOS specifics')
152 files = [
153 EF_PIN('6f01', 'EF.CHV1'),
154 EF_PIN('6f81', 'EF.CHV2'),
155 EF_PIN('6f0a', 'EF.ADM1'),
156 EF_PIN('6f0b', 'EF.ADM2'),
157 EF_PIN('6f0c', 'EF.ADM3'),
158 EF_PIN('6f0d', 'EF.ADM4'),
159 EF_MILENAGE_CFG(),
160 EF_0348_KEY(),
161 EF_SIM_AUTH_COUNTER(),
162 EF_SIM_AUTH_KEY(),
163 EF_0348_COUNT(),
164 EF_GP_COUNT(),
165 EF_GP_DIV_DATA(),
Harald Weltec91085e2022-02-10 18:05:45 +0100166 ]
Harald Weltef44256c2021-10-14 15:53:39 +0200167 self.add_files(files)
168
169 def decode_select_response(self, resp_hex):
Philipp Maier5998a3a2021-11-16 15:16:39 +0100170 return pySim.ts_102_221.CardProfileUICC.decode_select_response(resp_hex)
Harald Weltef44256c2021-10-14 15:53:39 +0200171
Harald Weltec91085e2022-02-10 18:05:45 +0100172
Harald Weltef44256c2021-10-14 15:53:39 +0200173class EF_USIM_SQN(TransparentEF):
174 def __init__(self, fid='af30', name='EF.USIM_SQN'):
175 super().__init__(fid, name=name, desc='SQN parameters for AKA')
176 Flag1 = BitStruct('skip_next_sqn_check'/Bit, 'delta_max_check'/Bit,
177 'age_limit_check'/Bit, 'sqn_check'/Bit,
178 'ind_len'/BitsInteger(4))
179 Flag2 = BitStruct('rfu'/BitsRFU(5), 'dont_clear_amf_for_macs'/Bit,
180 'aus_concealed'/Bit, 'autn_concealed'/Bit)
181 self._construct = Struct('flag1'/Flag1, 'flag2'/Flag2,
Harald Weltec91085e2022-02-10 18:05:45 +0100182 'delta_max' /
183 BytesInteger(6), 'age_limit'/BytesInteger(6),
Harald Welteeb458382021-10-16 10:44:23 +0200184 'freshness'/GreedyRange(BytesInteger(6)))
Harald Weltef44256c2021-10-14 15:53:39 +0200185
Harald Weltec91085e2022-02-10 18:05:45 +0100186
Harald Weltef44256c2021-10-14 15:53:39 +0200187class EF_USIM_AUTH_KEY(TransparentEF):
188 def __init__(self, fid='af20', name='EF.USIM_AUTH_KEY'):
189 super().__init__(fid, name=name, desc='USIM authentication key')
Harald Weltecfa30152022-07-22 17:12:27 +0200190 CfgByte = BitStruct(Padding(1), 'only_4bytes_res_in_3g'/Bit,
Harald Weltef44256c2021-10-14 15:53:39 +0200191 'use_sres_deriv_func_2_in_3g'/Bit,
192 'use_opc_instead_of_op'/Bit,
193 'algorithm'/Enum(Nibble, milenage=4, sha1_aka=5, xor=15))
194 self._construct = Struct('cfg'/CfgByte,
Harald Welte3c98d5e2022-07-20 07:40:05 +0200195 'key'/HexAdapter(Bytes(16)),
Philipp Maier4f888a02022-12-02 12:30:12 +0100196 'op_opc' /HexAdapter(Bytes(16)))
Harald Weltec91085e2022-02-10 18:05:45 +0100197
198
Harald Weltef44256c2021-10-14 15:53:39 +0200199class EF_USIM_AUTH_KEY_2G(TransparentEF):
200 def __init__(self, fid='af22', name='EF.USIM_AUTH_KEY_2G'):
201 super().__init__(fid, name=name, desc='USIM authentication key in 2G context')
Harald Weltecfa30152022-07-22 17:12:27 +0200202 CfgByte = BitStruct(Padding(1), 'only_4bytes_res_in_3g'/Bit,
Harald Weltef44256c2021-10-14 15:53:39 +0200203 'use_sres_deriv_func_2_in_3g'/Bit,
204 'use_opc_instead_of_op'/Bit,
205 'algorithm'/Enum(Nibble, milenage=4, comp128v1=1, comp128v2=2, comp128v3=3))
206 self._construct = Struct('cfg'/CfgByte,
Harald Welte3c98d5e2022-07-20 07:40:05 +0200207 'key'/HexAdapter(Bytes(16)),
Philipp Maier4f888a02022-12-02 12:30:12 +0100208 'op_opc' /HexAdapter(Bytes(16)))
Harald Weltec91085e2022-02-10 18:05:45 +0100209
210
Harald Weltef44256c2021-10-14 15:53:39 +0200211class EF_GBA_SK(TransparentEF):
212 def __init__(self, fid='af31', name='EF.GBA_SK'):
213 super().__init__(fid, name=name, desc='Secret key for GBA key derivation')
214 self._construct = GreedyBytes
215
Harald Weltec91085e2022-02-10 18:05:45 +0100216
Harald Weltef44256c2021-10-14 15:53:39 +0200217class EF_GBA_REC_LIST(TransparentEF):
218 def __init__(self, fid='af32', name='EF.GBA_REC_LIST'):
219 super().__init__(fid, name=name, desc='Secret key for GBA key derivation')
220 # integers representing record numbers in EF-GBANL
221 self._construct = GreedyRange(Int8ub)
222
Harald Weltec91085e2022-02-10 18:05:45 +0100223
Harald Weltef44256c2021-10-14 15:53:39 +0200224class EF_GBA_INT_KEY(LinFixedEF):
225 def __init__(self, fid='af33', name='EF.GBA_INT_KEY'):
Harald Weltec91085e2022-02-10 18:05:45 +0100226 super().__init__(fid, name=name,
Harald Welte99e4cc02022-07-21 15:25:47 +0200227 desc='Secret key for GBA key derivation', rec_len=(32, 32))
Harald Weltef44256c2021-10-14 15:53:39 +0200228 self._construct = GreedyBytes
229
230
Harald Weltef44256c2021-10-14 15:53:39 +0200231class SysmocomSJA2(CardModel):
Harald Weltec91085e2022-02-10 18:05:45 +0100232 _atrs = ["3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 30 34 05 4B A9",
233 "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 75 31 33 02 51 B2",
234 "3B 9F 96 80 1F 87 80 31 E0 73 FE 21 1B 67 4A 4C 52 75 31 04 51 D5"]
235
Harald Weltef44256c2021-10-14 15:53:39 +0200236 @classmethod
Harald Weltec91085e2022-02-10 18:05:45 +0100237 def add_files(cls, rs: RuntimeState):
Harald Weltef44256c2021-10-14 15:53:39 +0200238 """Add sysmocom SJA2 specific files to given RuntimeState."""
239 rs.mf.add_file(DF_SYSTEM())
240 # optional USIM application
241 if 'a0000000871002' in rs.mf.applications:
242 usim_adf = rs.mf.applications['a0000000871002']
243 files_adf_usim = [
244 EF_USIM_AUTH_KEY(),
245 EF_USIM_AUTH_KEY_2G(),
246 EF_GBA_SK(),
247 EF_GBA_REC_LIST(),
248 EF_GBA_INT_KEY(),
249 EF_USIM_SQN(),
Harald Weltec91085e2022-02-10 18:05:45 +0100250 ]
Harald Weltef44256c2021-10-14 15:53:39 +0200251 usim_adf.add_files(files_adf_usim)
252 # optional ISIM application
253 if 'a0000000871004' in rs.mf.applications:
254 isim_adf = rs.mf.applications['a0000000871004']
255 files_adf_isim = [
256 EF_USIM_AUTH_KEY(name='EF.ISIM_AUTH_KEY'),
257 EF_USIM_AUTH_KEY_2G(name='EF.ISIM_AUTH_KEY_2G'),
258 EF_USIM_SQN(name='EF.ISIM_SQN'),
Harald Weltec91085e2022-02-10 18:05:45 +0100259 ]
Harald Weltef44256c2021-10-14 15:53:39 +0200260 isim_adf.add_files(files_adf_isim)