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