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>
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
40 #include <epan/packet.h>
41 #include <epan/strutil.h>
43 static int proto_felica
= -1;
46 static int hf_felica_opcode
= -1;
49 static int hf_felica_sys_code
= -1;
52 static int hf_felica_timeslot
= -1;
54 /* Manufacture ID/NFCID2 */
55 static int hf_felica_idm
= -1;
58 static int hf_felica_req_code
= -1;
60 /* Manufacture Parameter/PAD */
61 static int hf_felica_pnm
= -1;
63 /* Number of Services */
65 static int hf_felica_nbr_of_svcs
= -1;
67 static int hf_felica_svc_code
= -1;
69 static int hf_felica_nbr_of_blocks
= -1;
70 static int hf_felica_block_nbr
= -1;
73 static int hf_felica_status_flag1
= -1;
76 static int hf_felica_status_flag2
= -1;
79 #define CMD_POLLING 0x00
80 #define CMD_REQ_SVC 0x02
81 #define CMD_REQ_RES 0x04
82 #define CMD_READ_WO_ENCRYPTION 0x06
83 #define CMD_WRITE_WO_ENCRYPTION 0x08
84 #define CMD_SEARCH_SVC_CODE 0x0A
85 #define CMD_REQ_SYS_CODE 0x0C
86 #define CMD_AUTH_1 0x10
87 #define CMD_AUTH_2 0x12
89 #define CMD_WRITE 0x16
90 #define CMD_REQ_SVC_V2 0x32
91 #define CMD_REQ_SYS_STATUS 0x38
92 #define CMD_REQ_SPEC_VER 0x3C
93 #define CMD_RESET_MODE 0x3E
94 #define CMD_AUTH1_V2 0x40
95 #define CMD_AUTH2_V2 0x42
96 #define CMD_READ_V2 0x44
97 #define CMD_WRITE_V2 0x46
98 #define CMD_REQ_UPDATE_RAND_ID 0x4C
101 #define RES_POLLING 0x01
102 #define RES_REQ_SVC 0x03
103 #define RES_REQ_RES 0x05
104 #define RES_READ_WO_ENCRYPTION 0x07
105 #define RES_WRITE_WO_ENCRYPTION 0x09
106 #define RES_SEARCH_SVC_CODE 0x0B
107 #define RES_REQ_SYS_CODE 0x0D
108 #define RES_AUTH_1 0x11
109 #define RES_AUTH_2 0x13
110 #define RES_READ 0x15
111 #define RES_WRITE 0x17
112 #define RES_REQ_SVC_V2 0x33
113 #define RES_REQ_SYS_STATUS 0x39
114 #define RES_REQ_SPEC_VER 0x3D
115 #define RES_RESET_MODE 0x3F
116 #define RES_AUTH1_V2 0x41
117 #define RES_AUTH2_V2 0x43
118 #define RES_READ_V2 0x45
119 #define RES_WRITE_V2 0x47
120 #define RES_REQ_UPDATE_RAND_ID 0x4D
122 /* - Request Codes - */
123 #define RC_NO_REQ 0x00
124 #define RC_SYS_REQ 0x01
125 #define RC_COM_PERF_REQ 0x02
127 /* - System Codes - */
129 /* FeliCa Lite/DFC */
130 #define SC_FELICA_LITE 0x88b4
133 #define SC_NFC_FORUM 0x12fc
135 /* FeliCa Networks' Common Area */
136 #define SC_FELICA_NW_COMMON_AREA 0xfe00
138 /* FeliCa Plug (NFC Dynamic Tag) */
139 #define SC_FELICA_PLUG 0xfee1
141 /* Japanese transit card */
142 #define SC_IRUCA 0xde80
144 /* "...return a response to the Polling command, regardless
145 of its System Code" */
147 #define SC_DOUBLE_WILDCARD 0xffff
149 static const value_string felica_opcodes
[] = {
151 {CMD_POLLING
, "Polling"},
152 {CMD_REQ_SVC
, "Request Service"},
153 {CMD_REQ_RES
, "Request Response"},
154 {CMD_READ_WO_ENCRYPTION
, "Read Without Encryption"},
155 {CMD_WRITE_WO_ENCRYPTION
, "Write Without Encryption"},
156 {CMD_SEARCH_SVC_CODE
, "Search Service Code"},
157 {CMD_REQ_SYS_CODE
, "Request System Code"},
158 {CMD_AUTH_1
, "Authentication1"},
159 {CMD_AUTH_2
, "Authentication2"},
161 {CMD_WRITE
, "Write"},
162 {CMD_REQ_SVC_V2
, "Request Service v2"},
163 {CMD_REQ_SYS_STATUS
, "Get System Status"},
164 {CMD_REQ_SPEC_VER
, "Request Specification Version"},
165 {CMD_RESET_MODE
, "Reset Mode"},
166 {CMD_AUTH1_V2
, "Authentication1 v2"},
167 {CMD_AUTH2_V2
, "Authentication2 v2"},
168 {CMD_READ_V2
, "Read v2"},
169 {CMD_WRITE_V2
, "Write v2"},
170 {CMD_REQ_UPDATE_RAND_ID
, "Update Random ID"},
171 /* End of commands */
174 {RES_POLLING
, "Polling (Response)"},
175 {RES_REQ_SVC
, "Request Service (Response)"},
176 {RES_REQ_RES
, "Request Response (Response)"},
177 {RES_READ_WO_ENCRYPTION
, "Read Without Encryption (Response)"},
178 {RES_WRITE_WO_ENCRYPTION
, "Write Without Encryption (Response)"},
179 {RES_SEARCH_SVC_CODE
, "Search Service Code (Response)"},
180 {RES_REQ_SYS_CODE
, "Request System Code (Response)"},
181 {RES_AUTH_1
, "Authentication1 (Response)"},
182 {RES_AUTH_2
, "Authentication2 (Response)"},
183 {RES_READ
, "Read (Response)"},
184 {RES_WRITE
, "Write (Response)"},
185 {RES_REQ_SVC_V2
, "Request Service v2 (Response)"},
186 {RES_REQ_SYS_STATUS
, "Get System Status (Response)"},
187 {RES_REQ_SPEC_VER
, "Request Specification Version (Response)"},
188 {RES_RESET_MODE
, "Reset Mode (Response)"},
189 {RES_AUTH1_V2
, "Authentication1 v2 (Response)"},
190 {RES_AUTH2_V2
, "Authentication2 v2 (Response)"},
191 {RES_READ_V2
, "Read v2 (Response)"},
192 {RES_WRITE_V2
, "Write v2 (Response)"},
193 {RES_REQ_UPDATE_RAND_ID
, "Update Random ID"},
194 /* End of responses */
199 static const value_string felica_req_codes
[] = {
200 {RC_NO_REQ
, "No Request"},
201 {RC_SYS_REQ
, "System Code Request"},
202 {RC_COM_PERF_REQ
, "Communication Performance Request"},
204 /* Others are reserved for future use */
206 /* End of request codes */
210 static const value_string felica_sys_codes
[] = {
211 {SC_FELICA_LITE
, "FeliCa Lite"},
212 {SC_FELICA_PLUG
, "FeliCa Plug (NFC Dynamic Tag)"},
213 {SC_NFC_FORUM
, "NFC Forum (NDEF)"},
214 {SC_FELICA_NW_COMMON_AREA
, "FeliCa Networks Common Area"},
216 {SC_DOUBLE_WILDCARD
, "Wildcard"},
218 /* End of system codes */
222 static dissector_handle_t data_handle
=NULL
;
224 /* Forward-declare the dissector functions */
225 static void dissect_felica(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
227 /* Subtree handles: set by register_subtree_array */
228 static gint ett_felica
= -1;
230 static void dissect_felica(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
233 proto_tree
*felica_tree
= NULL
;
236 tvbuff_t
*rwe_resp_data_tvb
;
238 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FeliCa");
241 /* Start with a top-level item to add everything else to */
242 item
= proto_tree_add_item(tree
, proto_felica
, tvb
, 0, -1, ENC_NA
);
243 felica_tree
= proto_item_add_subtree(item
, ett_felica
);
245 opcode
= tvb_get_guint8(tvb
, 0);
246 col_set_str(pinfo
->cinfo
, COL_INFO
,
247 val_to_str_const(opcode
, felica_opcodes
, "Unknown"));
250 proto_tree_add_item(felica_tree
, hf_felica_opcode
, tvb
, 0, 1, ENC_NA
);
257 proto_tree_add_item(felica_tree
, hf_felica_sys_code
, tvb
, 1, 2, ENC_BIG_ENDIAN
);
258 proto_tree_add_item(felica_tree
, hf_felica_req_code
, tvb
, 3, 1, ENC_BIG_ENDIAN
);
259 proto_tree_add_item(felica_tree
, hf_felica_timeslot
, tvb
, 4, 1, ENC_BIG_ENDIAN
);
265 proto_tree_add_item(felica_tree
, hf_felica_idm
, tvb
, 1, 8, ENC_BIG_ENDIAN
);
266 proto_tree_add_item(felica_tree
, hf_felica_pnm
, tvb
, 9, 8, ENC_BIG_ENDIAN
);
268 if (tvb_reported_length(tvb
) == 19)
269 proto_tree_add_item(felica_tree
, hf_felica_sys_code
, tvb
, 17, 2, ENC_BIG_ENDIAN
);
272 * Request data - 0 or 2 bytes long; data corresponding to request
273 * code; only if request code of command packet is not 00 and
274 * corresponds to request data
295 case CMD_READ_WO_ENCRYPTION
:
297 proto_tree_add_item(felica_tree
, hf_felica_idm
, tvb
, 1, 8, ENC_BIG_ENDIAN
);
298 proto_tree_add_item(felica_tree
, hf_felica_nbr_of_svcs
, tvb
, 9, 1, ENC_BIG_ENDIAN
);
300 /* Service codes are always 2 bytes in length */
302 /* There can technically be multiple Service Codes - although my traces only contain 1 */
303 proto_tree_add_item(felica_tree
, hf_felica_svc_code
, tvb
, 10, 2, ENC_BIG_ENDIAN
);
305 /* Number of Blocks - 1byte */
306 proto_tree_add_item(felica_tree
, hf_felica_nbr_of_blocks
, tvb
, 12, 1, ENC_BIG_ENDIAN
);
308 /* Iterate through the block list, and update the tree */
309 for (rwe_pos
= 0; rwe_pos
< tvb_get_guint8(tvb
, 12); rwe_pos
++) {
310 proto_tree_add_uint(felica_tree
, hf_felica_block_nbr
, tvb
,
311 13 + 2 * rwe_pos
, 2, tvb_get_guint8(tvb
, 14 + 2 * rwe_pos
));
316 case RES_READ_WO_ENCRYPTION
:
318 proto_tree_add_item(felica_tree
, hf_felica_idm
, tvb
, 1, 8, ENC_BIG_ENDIAN
);
319 proto_tree_add_item(felica_tree
, hf_felica_status_flag1
, tvb
, 9, 1, ENC_BIG_ENDIAN
);
320 proto_tree_add_item(felica_tree
, hf_felica_status_flag2
, tvb
, 10, 1, ENC_BIG_ENDIAN
);
321 proto_tree_add_item(felica_tree
, hf_felica_nbr_of_blocks
, tvb
, 11, 1, ENC_BIG_ENDIAN
);
323 rwe_resp_data_tvb
= tvb_new_subset_remaining(tvb
, 12);
324 call_dissector(data_handle
, rwe_resp_data_tvb
, pinfo
, tree
);
327 case CMD_WRITE_WO_ENCRYPTION
:
331 case RES_WRITE_WO_ENCRYPTION
:
335 case CMD_SEARCH_SVC_CODE
:
339 case RES_SEARCH_SVC_CODE
:
343 case CMD_REQ_SYS_CODE
:
347 case RES_REQ_SYS_CODE
:
391 case CMD_REQ_SYS_STATUS
:
395 case RES_REQ_SYS_STATUS
:
399 case CMD_REQ_SPEC_VER
:
403 case RES_REQ_SPEC_VER
:
447 case CMD_REQ_UPDATE_RAND_ID
:
451 case RES_REQ_UPDATE_RAND_ID
:
461 proto_register_felica(void)
463 static hf_register_info hf
[] = {
466 { "Opcode", "felica.opcode",
467 FT_UINT8
, BASE_HEX
, VALS(felica_opcodes
), 0x0,
472 {&hf_felica_req_code
,
473 { "Request Code", "felica.req.code",
474 FT_UINT8
, BASE_HEX
, VALS(felica_req_codes
), 0x0,
479 { "IDm (Manufacture ID)/NFCID2", "felica.idm",
480 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
485 {&hf_felica_sys_code
,
486 { "System Code", "felica.sys_code",
487 FT_UINT16
, BASE_HEX
, VALS(felica_sys_codes
), 0x0,
492 {&hf_felica_svc_code
,
493 { "Service Code", "felica.svc_code",
494 FT_UINT16
, BASE_HEX
, NULL
, 0x0,
500 { "PNm (Manufacture Parameter)/PAD", "felica.pnm",
501 FT_UINT64
, BASE_HEX
, NULL
, 0x0,
505 /* Number of Services */
506 {&hf_felica_nbr_of_svcs
,
507 { "Number of Services", "felica.svcs",
508 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
512 /* Number of Blocks */
513 {&hf_felica_nbr_of_blocks
,
514 { "Number of Blocks", "felica.blocks",
515 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
520 {&hf_felica_block_nbr
,
521 { "Block Number", "felica.block.nbr",
522 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
527 {&hf_felica_status_flag1
,
528 { "Status Flag 1", "felica.status.flag1",
529 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
534 {&hf_felica_status_flag2
,
535 { "Status Flag 2", "felica.status.flag2",
536 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
541 {&hf_felica_timeslot
,
542 { "Timeslot", "felica.timeslot",
543 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
548 static gint
*ett
[] = {
552 proto_felica
= proto_register_protocol("Sony FeliCa", "FeliCa", "felica");
553 proto_register_field_array(proto_felica
, hf
, array_length(hf
));
554 proto_register_subtree_array(ett
, array_length(ett
));
556 register_dissector("felica", dissect_felica
, proto_felica
);
559 /* Handler registration */
561 proto_reg_handoff_felica(void)
563 data_handle
= find_dissector("data");
566 * Editor modelines - http://www.wireshark.org/tools/modelines.html
571 * indent-tabs-mode: nil
574 * ex: set shiftwidth=4 tabstop=8 expandtab:
575 * :indentSize=4:tabSize=8:noTabs=true: