Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1 | """Code related to the Card Application Toolkit (CAT) as described in |
| 2 | mainly) ETSI TS 102 223, ETSI TS 101 220 and 3GPP TS 31.111.""" |
| 3 | |
| 4 | # (C) 2021 by Harald Welte <laforge@osmocom.org> |
| 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 pySim.tlv import * |
| 21 | from pySim.construct import * |
| 22 | from construct import * |
| 23 | |
| 24 | # Tag values as per TS 101 220 Table 7.23 |
| 25 | |
| 26 | # TS 102 223 Section 8.1 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 27 | |
| 28 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 29 | class Address(COMPR_TLV_IE, tag=0x06): |
| 30 | _construct = Struct('ton_npi'/Int8ub, |
| 31 | 'call_number'/BcdAdapter(Bytes(this._.total_len-1))) |
| 32 | |
| 33 | # TS 102 223 Section 8.2 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 34 | |
| 35 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 36 | class AlphaIdentifier(COMPR_TLV_IE, tag=0x05): |
| 37 | # FIXME: like EF.ADN |
| 38 | pass |
| 39 | |
| 40 | # TS 102 223 Section 8.3 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 41 | |
| 42 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 43 | class Subaddress(COMPR_TLV_IE, tag=0x08): |
| 44 | pass |
| 45 | |
| 46 | # TS 102 223 Section 8.4 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 47 | |
| 48 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 49 | class CapabilityConfigParams(COMPR_TLV_IE, tag=0x07): |
| 50 | pass |
| 51 | |
| 52 | # TS 31.111 Section 8.5 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 53 | |
| 54 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 55 | class CBSPage(COMPR_TLV_IE, tag=0x0C): |
| 56 | pass |
| 57 | |
| 58 | # TS 102 223 Section 8.6 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 59 | |
| 60 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 61 | class CommandDetails(COMPR_TLV_IE, tag=0x01): |
| 62 | _construct = Struct('command_number'/Int8ub, |
| 63 | 'type_of_command'/Int8ub, |
| 64 | 'command_qualifier'/Int8ub) |
| 65 | |
| 66 | # TS 102 223 Section 8.7 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 67 | |
| 68 | |
Harald Welte | 9edbdb9 | 2021-10-08 15:46:42 +0200 | [diff] [blame] | 69 | class DeviceIdentities(COMPR_TLV_IE, tag=0x82): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 70 | DEV_IDS = bidict({ |
| 71 | 0x01: 'keypad', |
| 72 | 0x02: 'display', |
| 73 | 0x03: 'earpiece', |
| 74 | 0x10: 'addl_card_reader_0', |
| 75 | 0x11: 'addl_card_reader_1', |
| 76 | 0x12: 'addl_card_reader_2', |
| 77 | 0x13: 'addl_card_reader_3', |
| 78 | 0x14: 'addl_card_reader_4', |
| 79 | 0x15: 'addl_card_reader_5', |
| 80 | 0x16: 'addl_card_reader_6', |
| 81 | 0x17: 'addl_card_reader_7', |
| 82 | 0x21: 'channel_1', |
| 83 | 0x22: 'channel_2', |
| 84 | 0x23: 'channel_3', |
| 85 | 0x24: 'channel_4', |
| 86 | 0x25: 'channel_5', |
| 87 | 0x26: 'channel_6', |
| 88 | 0x27: 'channel_7', |
| 89 | 0x31: 'ecat_client_1', |
| 90 | 0x32: 'ecat_client_2', |
| 91 | 0x33: 'ecat_client_3', |
| 92 | 0x34: 'ecat_client_4', |
| 93 | 0x35: 'ecat_client_5', |
| 94 | 0x36: 'ecat_client_6', |
| 95 | 0x37: 'ecat_client_7', |
| 96 | 0x38: 'ecat_client_8', |
| 97 | 0x39: 'ecat_client_9', |
| 98 | 0x3a: 'ecat_client_a', |
| 99 | 0x3b: 'ecat_client_b', |
| 100 | 0x3c: 'ecat_client_c', |
| 101 | 0x3d: 'ecat_client_d', |
| 102 | 0x3e: 'ecat_client_e', |
| 103 | 0x3f: 'ecat_client_f', |
| 104 | 0x81: 'uicc', |
| 105 | 0x82: 'terminal', |
| 106 | 0x83: 'network', |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 107 | }) |
| 108 | |
| 109 | def _from_bytes(self, do: bytes): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 110 | return {'source_dev_id': self.DEV_IDS[do[0]], 'dest_dev_id': self.DEV_IDS[do[1]]} |
| 111 | |
| 112 | def _to_bytes(self): |
| 113 | src = self.DEV_IDS.inverse[self.decoded['source_dev_id']] |
| 114 | dst = self.DEV_IDS.inverse[self.decoded['dest_dev_id']] |
| 115 | return bytes([src, dst]) |
| 116 | |
| 117 | # TS 102 223 Section 8.8 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 118 | |
| 119 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 120 | class Duration(COMPR_TLV_IE, tag=0x04): |
| 121 | _construct = Struct('time_unit'/Int8ub, |
| 122 | 'time_interval'/Int8ub) |
| 123 | |
| 124 | # TS 102 223 Section 8.9 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 125 | |
| 126 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 127 | class Item(COMPR_TLV_IE, tag=0x0f): |
| 128 | _construct = Struct('identifier'/Int8ub, |
| 129 | 'text_string'/GsmStringAdapter(GreedyBytes)) |
| 130 | |
| 131 | # TS 102 223 Section 8.10 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 132 | |
| 133 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 134 | class ItemIdentifier(COMPR_TLV_IE, tag=0x10): |
| 135 | _construct = Struct('identifier'/Int8ub) |
| 136 | |
| 137 | # TS 102 223 Section 8.11 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 138 | |
| 139 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 140 | class ResponseLength(COMPR_TLV_IE, tag=0x11): |
| 141 | _construct = Struct('minimum_length'/Int8ub, |
| 142 | 'maximum_length'/Int8ub) |
| 143 | |
| 144 | # TS 102 223 Section 8.12 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 145 | |
| 146 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 147 | class Result(COMPR_TLV_IE, tag=0x03): |
| 148 | _construct = Struct('general_result'/Int8ub, |
| 149 | 'additional_information'/HexAdapter(GreedyBytes)) |
| 150 | |
| 151 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 152 | # TS 102 223 Section 8.13 + TS 31.111 Section 8.13 |
Harald Welte | 9edbdb9 | 2021-10-08 15:46:42 +0200 | [diff] [blame] | 153 | class SMS_TPDU(COMPR_TLV_IE, tag=0x8B): |
| 154 | _construct = Struct('tpdu'/HexAdapter(GreedyBytes)) |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 155 | |
| 156 | # TS 102 223 Section 8.15 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 157 | |
| 158 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 159 | class TextString(COMPR_TLV_IE, tag=0x0d): |
| 160 | _construct = Struct('dcs'/Int8ub, |
| 161 | 'text_string'/HexAdapter(GreedyBytes)) |
| 162 | |
| 163 | # TS 102 223 Section 8.16 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 164 | |
| 165 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 166 | class Tone(COMPR_TLV_IE, tag=0x0e): |
| 167 | _construct = Struct('tone'/Int8ub) |
| 168 | |
| 169 | # TS 31 111 Section 8.17 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 170 | |
| 171 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 172 | class USSDString(COMPR_TLV_IE, tag=0x0a): |
| 173 | _construct = Struct('dcs'/Int8ub, |
| 174 | 'ussd_string'/HexAdapter(GreedyBytes)) |
| 175 | |
| 176 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 177 | # TS 101 220 Table 7.17 |
| 178 | class ProactiveCommand(BER_TLV_IE, tag=0xD0): |
| 179 | pass |
| 180 | |
| 181 | # TS 101 220 Table 7.17 + 31.111 7.1.1.2 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 182 | |
| 183 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 184 | class SMSPPDownload(BER_TLV_IE, tag=0xD1, |
| 185 | nested=[DeviceIdentities, Address, SMS_TPDU]): |
| 186 | pass |
| 187 | |
| 188 | # TS 101 220 Table 7.17 + 31.111 7.1.1.3 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 189 | |
| 190 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 191 | class SMSCBDownload(BER_TLV_IE, tag=0xD2, |
| 192 | nested=[DeviceIdentities, CBSPage]): |
| 193 | pass |
| 194 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 195 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 196 | class USSDDownload(BER_TLV_IE, tag=0xD9, |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 197 | nested=[DeviceIdentities, USSDString]): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 198 | pass |
| 199 | |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 200 | |
| 201 | # reasonable default for playing with OTA |
| 202 | # 010203040506070809101112131415161718192021222324252627282930313233 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 203 | # '7fe1e10e000000000000001f43000000ff00000000000000000000000000000000' |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 204 | |
| 205 | # TS 102 223 Section 5.2 |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 206 | term_prof_bits = { |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 207 | # first byte |
| 208 | 1: 'Profile download', |
| 209 | 2: 'SMS-PP data download', |
| 210 | 3: 'Cell Broadcast data download', |
| 211 | 4: 'Menu selection', |
| 212 | 5: 'SMS-PP data download', |
| 213 | 6: 'Timer expiration', |
| 214 | 7: 'USSD string DO support in CC by USIM', |
| 215 | 8: 'Call Control by NAA', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 216 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 217 | # first byte |
| 218 | 9: 'Command result', |
| 219 | 10: 'Call Control by NAA', |
| 220 | 11: 'Call Control by NAA', |
| 221 | 12: 'MO short message control support', |
| 222 | 13: 'Call Control by NAA', |
| 223 | 14: 'UCS2 Entry supported', |
| 224 | 15: 'UCS2 Display supported', |
| 225 | 16: 'Display Text', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 226 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 227 | # third byte |
| 228 | 17: 'Proactive UICC: DISPLAY TEXT', |
| 229 | 18: 'Proactive UICC: GET INKEY', |
| 230 | 19: 'Proactive UICC: GET INPUT', |
| 231 | 20: 'Proactive UICC: MORE TIME', |
| 232 | 21: 'Proactive UICC: PLAY TONE', |
| 233 | 22: 'Proactive UICC: POLL INTERVAL', |
| 234 | 23: 'Proactive UICC: POLLING OFF', |
| 235 | 24: 'Proactive UICC: REFRESH', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 236 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 237 | # fourth byte |
| 238 | 25: 'Proactive UICC: SELECT ITEM', |
| 239 | 26: 'Proactive UICC: SEND SHORT MESSAGE with 3GPP-SMS-TPDU', |
| 240 | 27: 'Proactive UICC: SEND SS', |
| 241 | 28: 'Proactive UICC: SEND USSD', |
| 242 | 29: 'Proactive UICC: SET UP CALL', |
| 243 | 30: 'Proactive UICC: SET UP MENU', |
| 244 | 31: 'Proactive UICC: PROVIDE LOCAL INFORMATION (MCC, MNC, LAC, Cell ID & IMEI)', |
| 245 | 32: 'Proactive UICC: PROVIDE LOCAL INFORMATION (NMR)', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 246 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 247 | # fifth byte |
| 248 | 33: 'Proactive UICC: SET UP EVENT LIST', |
| 249 | 34: 'Event: MT call', |
| 250 | 35: 'Event: Call connected', |
| 251 | 36: 'Event: Call disconnected', |
| 252 | 37: 'Event: Location status', |
| 253 | 38: 'Event: User activity', |
| 254 | 39: 'Event: Idle screen available', |
| 255 | 40: 'Event: Card reader status', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 256 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 257 | # sixth byte |
| 258 | 41: 'Event: Language selection', |
| 259 | 42: 'Event: Browser Termination', |
| 260 | 43: 'Event: Data aailable', |
| 261 | 44: 'Event: Channel status', |
| 262 | 45: 'Event: Access Technology Change', |
| 263 | 46: 'Event: Display parameters changed', |
| 264 | 47: 'Event: Local Connection', |
| 265 | 48: 'Event: Network Search Mode Change', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 266 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 267 | # seventh byte |
| 268 | 49: 'Proactive UICC: POWER ON CARD', |
| 269 | 50: 'Proactive UICC: POWER OFF CARD', |
| 270 | 51: 'Proactive UICC: PERFORM CARD RESET', |
| 271 | 52: 'Proactive UICC: GET READER STATUS (Card reader status)', |
| 272 | 53: 'Proactive UICC: GET READER STATUS (Card reader identifier)', |
| 273 | # RFU: 3 bit (54,55,56) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 274 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 275 | # eighth byte |
| 276 | 57: 'Proactive UICC: TIMER MANAGEMENT (start, stop)', |
| 277 | 58: 'Proactive UICC: TIMER MANAGEMENT (get current value)', |
| 278 | 59: 'Proactive UICC: PROVIDE LOCAL INFORMATION (date, time and time zone)', |
| 279 | 60: 'GET INKEY', |
| 280 | 61: 'SET UP IDLE MODE TEXT', |
| 281 | 62: 'RUN AT COMMAND', |
| 282 | 63: 'SETUP CALL', |
| 283 | 64: 'Call Control by NAA', |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 284 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 285 | # ninth byte |
| 286 | 65: 'DISPLAY TEXT', |
| 287 | 66: 'SEND DTMF command', |
| 288 | 67: 'Proactive UICC: PROVIDE LOCAL INFORMATION (NMR)', |
| 289 | 68: 'Proactive UICC: PROVIDE LOCAL INFORMATION (language)', |
| 290 | 69: 'Proactive UICC: PROVIDE LOCAL INFORMATION (Timing Advance)', |
| 291 | 70: 'Proactive UICC: LANGUAGE NOTIFICATION', |
| 292 | 71: 'Proactive UICC: LAUNCH BROWSER', |
| 293 | 72: 'Proactive UICC: PROVIDE LOCAL INFORMATION (Access Technology)', |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 294 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 295 | # tenth byte |
| 296 | 73: 'Soft keys support for SELECT ITEM', |
| 297 | 74: 'Soft keys support for SET UP MENU ITEM', |
| 298 | # RFU: 6 bit (75-80) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 299 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 300 | # eleventh byte: max number of soft keys as 8bit value (81..88) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 301 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 302 | # twelfth byte |
| 303 | 89: 'Proactive UICC: OPEN CHANNEL', |
| 304 | 90: 'Proactive UICC: CLOSE CHANNEL', |
| 305 | 91: 'Proactive UICC: RECEIVE DATA', |
| 306 | 92: 'Proactive UICC: SEND DATA', |
| 307 | 93: 'Proactive UICC: GET CHANNEL STATUS', |
| 308 | 94: 'Proactive UICC: SERVICE SEARCH', |
| 309 | 95: 'Proactive UICC: GET SERVICE INFORMATION', |
| 310 | 96: 'Proactive UICC: DECLARE SERVICE', |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 311 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 312 | # thirteenth byte |
| 313 | 97: 'BIP supported Bearer: CSD', |
| 314 | 98: 'BIP supported Bearer: GPRS', |
| 315 | 99: 'BIP supported Bearer: Bluetooth', |
| 316 | 100: 'BIP supported Bearer: IrDA', |
| 317 | 101: 'BIP supported Bearer: RS232', |
| 318 | # 3 bits: number of channels supported (102..104) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 319 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 320 | # fourtheenth byte (screen height) |
| 321 | # fifteenth byte (screen width) |
| 322 | # sixeenth byte (screen effects) |
| 323 | # seventeenth byte (BIP supported bearers) |
| 324 | 129: 'BIP: TCP, UICC in client mode, remote connection', |
| 325 | 130: 'BIP: UDP, UICC in client mode, remote connection', |
| 326 | 131: 'BIP: TCP, UICC in server mode', |
| 327 | 132: 'BIP: TCP, UICC in client mode, local connection', |
| 328 | 133: 'BIP: UDP, UICC in client mode, local connection', |
| 329 | 134: 'BIP: direct communication channel', |
| 330 | # 2 bits reserved: 135, 136 |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 331 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame^] | 332 | # FIXME: remainder |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 333 | } |