2 * Dissector for the Sony FeliCa Protocol
5 * http://www.sony.net/Products/felica/business/tech-support/data/fl_usmnl_1.2.pdf
6 * http://www.sony.net/Products/felica/business/tech-support/data/fp_usmnl_1.11.pdf
7 * http://www.sony.net/Products/felica/business/tech-support/data/format_sequence_guidelines_1.1.pdf
8 * http://www.sony.net/Products/felica/business/tech-support/data/card_usersmanual_2.0.pdf
9 * http://code.google.com/u/101410204121169118393/updates
10 * https://github.com/codebutler/farebot/wiki/Suica
12 * Copyright 2012, Tyson Key <tyson.key@gmail.com>
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * SPDX-License-Identifier: GPL-2.0-or-later
24 #include <epan/packet.h>
26 void proto_register_felica(void);
28 static int proto_felica
;
31 static int hf_felica_opcode
;
34 static int hf_felica_sys_code
;
37 static int hf_felica_timeslot
;
39 /* Manufacture ID/NFCID2 */
40 static int hf_felica_idm
;
43 static int hf_felica_req_code
;
45 /* Manufacture Parameter/PAD */
46 static int hf_felica_pnm
;
48 /* Number of Services */
50 static int hf_felica_nbr_of_svcs
;
52 static int hf_felica_svc_code
;
54 static int hf_felica_nbr_of_blocks
;
55 static int hf_felica_block_nbr
;
58 static int hf_felica_status_flag1
;
61 static int hf_felica_status_flag2
;
64 #define CMD_POLLING 0x00
65 #define CMD_REQ_SVC 0x02
66 #define CMD_REQ_RES 0x04
67 #define CMD_READ_WO_ENCRYPTION 0x06
68 #define CMD_WRITE_WO_ENCRYPTION 0x08
69 #define CMD_SEARCH_SVC_CODE 0x0A
70 #define CMD_REQ_SYS_CODE 0x0C
71 #define CMD_AUTH_1 0x10
72 #define CMD_AUTH_2 0x12
74 #define CMD_WRITE 0x16
75 #define CMD_REQ_SVC_V2 0x32
76 #define CMD_REQ_SYS_STATUS 0x38
77 #define CMD_REQ_SPEC_VER 0x3C
78 #define CMD_RESET_MODE 0x3E
79 #define CMD_AUTH1_V2 0x40
80 #define CMD_AUTH2_V2 0x42
81 #define CMD_READ_V2 0x44
82 #define CMD_WRITE_V2 0x46
83 #define CMD_REQ_UPDATE_RAND_ID 0x4C
86 #define RES_POLLING 0x01
87 #define RES_REQ_SVC 0x03
88 #define RES_REQ_RES 0x05
89 #define RES_READ_WO_ENCRYPTION 0x07
90 #define RES_WRITE_WO_ENCRYPTION 0x09
91 #define RES_SEARCH_SVC_CODE 0x0B
92 #define RES_REQ_SYS_CODE 0x0D
93 #define RES_AUTH_1 0x11
94 #define RES_AUTH_2 0x13
96 #define RES_WRITE 0x17
97 #define RES_REQ_SVC_V2 0x33
98 #define RES_REQ_SYS_STATUS 0x39
99 #define RES_REQ_SPEC_VER 0x3D
100 #define RES_RESET_MODE 0x3F
101 #define RES_AUTH1_V2 0x41
102 #define RES_AUTH2_V2 0x43
103 #define RES_READ_V2 0x45
104 #define RES_WRITE_V2 0x47
105 #define RES_REQ_UPDATE_RAND_ID 0x4D
107 /* - Request Codes - */
108 #define RC_NO_REQ 0x00
109 #define RC_SYS_REQ 0x01
110 #define RC_COM_PERF_REQ 0x02
112 /* - System Codes - */
114 /* FeliCa Lite/DFC */
115 #define SC_FELICA_LITE 0x88b4
118 #define SC_NFC_FORUM 0x12fc
120 /* FeliCa Networks' Common Area */
121 #define SC_FELICA_NW_COMMON_AREA 0xfe00
123 /* FeliCa Plug (NFC Dynamic Tag) */
124 #define SC_FELICA_PLUG 0xfee1
126 /* Japanese transit card */
127 #define SC_IRUCA 0xde80
129 /* "...return a response to the Polling command, regardless
130 of its System Code" */
132 #define SC_DOUBLE_WILDCARD 0xffff
134 static const value_string felica_opcodes
[] = {
136 {CMD_POLLING
, "Polling"},
137 {CMD_REQ_SVC
, "Request Service"},
138 {CMD_REQ_RES
, "Request Response"},
139 {CMD_READ_WO_ENCRYPTION
, "Read Without Encryption"},
140 {CMD_WRITE_WO_ENCRYPTION
, "Write Without Encryption"},
141 {CMD_SEARCH_SVC_CODE
, "Search Service Code"},
142 {CMD_REQ_SYS_CODE
, "Request System Code"},
143 {CMD_AUTH_1
, "Authentication1"},
144 {CMD_AUTH_2
, "Authentication2"},
146 {CMD_WRITE
, "Write"},
147 {CMD_REQ_SVC_V2
, "Request Service v2"},
148 {CMD_REQ_SYS_STATUS
, "Get System Status"},
149 {CMD_REQ_SPEC_VER
, "Request Specification Version"},
150 {CMD_RESET_MODE
, "Reset Mode"},
151 {CMD_AUTH1_V2
, "Authentication1 v2"},
152 {CMD_AUTH2_V2
, "Authentication2 v2"},
153 {CMD_READ_V2
, "Read v2"},
154 {CMD_WRITE_V2
, "Write v2"},
155 {CMD_REQ_UPDATE_RAND_ID
, "Update Random ID"},
156 /* End of commands */
159 {RES_POLLING
, "Polling (Response)"},
160 {RES_REQ_SVC
, "Request Service (Response)"},
161 {RES_REQ_RES
, "Request Response (Response)"},
162 {RES_READ_WO_ENCRYPTION
, "Read Without Encryption (Response)"},
163 {RES_WRITE_WO_ENCRYPTION
, "Write Without Encryption (Response)"},
164 {RES_SEARCH_SVC_CODE
, "Search Service Code (Response)"},
165 {RES_REQ_SYS_CODE
, "Request System Code (Response)"},
166 {RES_AUTH_1
, "Authentication1 (Response)"},
167 {RES_AUTH_2
, "Authentication2 (Response)"},
168 {RES_READ
, "Read (Response)"},
169 {RES_WRITE
, "Write (Response)"},
170 {RES_REQ_SVC_V2
, "Request Service v2 (Response)"},
171 {RES_REQ_SYS_STATUS
, "Get System Status (Response)"},
172 {RES_REQ_SPEC_VER
, "Request Specification Version (Response)"},
173 {RES_RESET_MODE
, "Reset Mode (Response)"},
174 {RES_AUTH1_V2
, "Authentication1 v2 (Response)"},
175 {RES_AUTH2_V2
, "Authentication2 v2 (Response)"},
176 {RES_READ_V2
, "Read v2 (Response)"},
177 {RES_WRITE_V2
, "Write v2 (Response)"},
178 {RES_REQ_UPDATE_RAND_ID
, "Update Random ID"},
179 /* End of responses */
184 static const value_string felica_req_codes
[] = {
185 {RC_NO_REQ
, "No Request"},
186 {RC_SYS_REQ
, "System Code Request"},
187 {RC_COM_PERF_REQ
, "Communication Performance Request"},
189 /* Others are reserved for future use */
191 /* End of request codes */
195 static const value_string felica_sys_codes
[] = {
196 {SC_FELICA_LITE
, "FeliCa Lite"},
197 {SC_FELICA_PLUG
, "FeliCa Plug (NFC Dynamic Tag)"},
198 {SC_NFC_FORUM
, "NFC Forum (NDEF)"},
199 {SC_FELICA_NW_COMMON_AREA
, "FeliCa Networks Common Area"},
201 {SC_DOUBLE_WILDCARD
, "Wildcard"},
203 /* End of system codes */
207 /* Subtree handles: set by register_subtree_array */
208 static int ett_felica
;
210 static int dissect_felica(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
213 proto_tree
*felica_tree
;
216 tvbuff_t
*rwe_resp_data_tvb
;
218 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FeliCa");
220 /* Start with a top-level item to add everything else to */
221 item
= proto_tree_add_item(tree
, proto_felica
, tvb
, 0, -1, ENC_NA
);
222 felica_tree
= proto_item_add_subtree(item
, ett_felica
);
224 opcode
= tvb_get_uint8(tvb
, 0);
225 col_set_str(pinfo
->cinfo
, COL_INFO
,
226 val_to_str_const(opcode
, felica_opcodes
, "Unknown"));
228 proto_tree_add_item(felica_tree
, hf_felica_opcode
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
234 proto_tree_add_item(felica_tree
, hf_felica_sys_code
, tvb
, 1, 2, ENC_BIG_ENDIAN
);
235 proto_tree_add_item(felica_tree
, hf_felica_req_code
, tvb
, 3, 1, ENC_BIG_ENDIAN
);
236 proto_tree_add_item(felica_tree
, hf_felica_timeslot
, tvb
, 4, 1, ENC_BIG_ENDIAN
);
242 proto_tree_add_item(felica_tree
, hf_felica_idm
, tvb
, 1, 8, ENC_BIG_ENDIAN
);
243 proto_tree_add_item(felica_tree
, hf_felica_pnm
, tvb
, 9, 8, ENC_BIG_ENDIAN
);
245 if (tvb_reported_length(tvb
) == 19)
246 proto_tree_add_item(felica_tree
, hf_felica_sys_code
, tvb
, 17, 2, ENC_BIG_ENDIAN
);
249 * Request data - 0 or 2 bytes long; data corresponding to request
250 * code; only if request code of command packet is not 00 and
251 * corresponds to request data
272 case CMD_READ_WO_ENCRYPTION
:
274 proto_tree_add_item(felica_tree
, hf_felica_idm
, tvb
, 1, 8, ENC_BIG_ENDIAN
);
275 proto_tree_add_item(felica_tree
, hf_felica_nbr_of_svcs
, tvb
, 9, 1, ENC_BIG_ENDIAN
);
277 /* Service codes are always 2 bytes in length */
279 /* There can technically be multiple Service Codes - although my traces only contain 1 */
280 proto_tree_add_item(felica_tree
, hf_felica_svc_code
, tvb
, 10, 2, ENC_BIG_ENDIAN
);
282 /* Number of Blocks - 1byte */
283 proto_tree_add_item(felica_tree
, hf_felica_nbr_of_blocks
, tvb
, 12, 1, ENC_BIG_ENDIAN
);
285 /* Iterate through the block list, and update the tree */
286 for (rwe_pos
= 0; rwe_pos
< tvb_get_uint8(tvb
, 12); rwe_pos
++) {
287 proto_tree_add_item(felica_tree
, hf_felica_block_nbr
, tvb
,
288 13 + 2 * rwe_pos
, 2, ENC_NA
);
293 case RES_READ_WO_ENCRYPTION
:
295 proto_tree_add_item(felica_tree
, hf_felica_idm
, tvb
, 1, 8, ENC_BIG_ENDIAN
);
296 proto_tree_add_item(felica_tree
, hf_felica_status_flag1
, tvb
, 9, 1, ENC_BIG_ENDIAN
);
297 proto_tree_add_item(felica_tree
, hf_felica_status_flag2
, tvb
, 10, 1, ENC_BIG_ENDIAN
);
298 proto_tree_add_item(felica_tree
, hf_felica_nbr_of_blocks
, tvb
, 11, 1, ENC_BIG_ENDIAN
);
300 rwe_resp_data_tvb
= tvb_new_subset_remaining(tvb
, 12);
301 call_data_dissector(rwe_resp_data_tvb
, pinfo
, tree
);
304 case CMD_WRITE_WO_ENCRYPTION
:
308 case RES_WRITE_WO_ENCRYPTION
:
312 case CMD_SEARCH_SVC_CODE
:
316 case RES_SEARCH_SVC_CODE
:
320 case CMD_REQ_SYS_CODE
:
324 case RES_REQ_SYS_CODE
:
368 case CMD_REQ_SYS_STATUS
:
372 case RES_REQ_SYS_STATUS
:
376 case CMD_REQ_SPEC_VER
:
380 case RES_REQ_SPEC_VER
:
424 case CMD_REQ_UPDATE_RAND_ID
:
428 case RES_REQ_UPDATE_RAND_ID
:
435 return tvb_captured_length(tvb
);
439 proto_register_felica(void)
441 static hf_register_info hf
[] = {
444 { "Opcode", "felica.opcode",
445 FT_UINT8
, BASE_HEX
, VALS(felica_opcodes
), 0x0,
450 {&hf_felica_req_code
,
451 { "Request Code", "felica.req.code",
452 FT_UINT8
, BASE_HEX
, VALS(felica_req_codes
), 0x0,
457 { "IDm (Manufacture ID)/NFCID2", "felica.idm",
458 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
463 {&hf_felica_sys_code
,
464 { "System Code", "felica.sys_code",
465 FT_UINT16
, BASE_HEX
, VALS(felica_sys_codes
), 0x0,
470 {&hf_felica_svc_code
,
471 { "Service Code", "felica.svc_code",
472 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
478 { "PNm (Manufacture Parameter)/PAD", "felica.pnm",
479 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
483 /* Number of Services */
484 {&hf_felica_nbr_of_svcs
,
485 { "Number of Services", "felica.svcs",
486 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
490 /* Number of Blocks */
491 {&hf_felica_nbr_of_blocks
,
492 { "Number of Blocks", "felica.blocks",
493 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
498 {&hf_felica_block_nbr
,
499 { "Block Number", "felica.block.nbr",
500 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
505 {&hf_felica_status_flag1
,
506 { "Status Flag 1", "felica.status.flag1",
507 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
512 {&hf_felica_status_flag2
,
513 { "Status Flag 2", "felica.status.flag2",
514 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
519 {&hf_felica_timeslot
,
520 { "Timeslot", "felica.timeslot",
521 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
526 static int *ett
[] = {
530 proto_felica
= proto_register_protocol("Sony FeliCa", "FeliCa", "felica");
531 proto_register_field_array(proto_felica
, hf
, array_length(hf
));
532 proto_register_subtree_array(ett
, array_length(ett
));
534 register_dissector("felica", dissect_felica
, proto_felica
);
538 * Editor modelines - https://www.wireshark.org/tools/modelines.html
543 * indent-tabs-mode: nil
546 * ex: set shiftwidth=4 tabstop=8 expandtab:
547 * :indentSize=4:tabSize=8:noTabs=true: