1 /* packet-rfid-mifare.c
2 * Dissector for the NXP MiFare Protocol
5 * http://code.google.com/p/nfc-tools/source/browse/trunk/libfreefare/libfreefare/mifare_classic.c
6 * http://www.nxp.com/documents/data_sheet/MF1S703x.pdf
7 * http://www.nxp.com/documents/application_note/AN1304.pdf
9 * Copyright 2011, Tyson Key <tyson.key@gmail.com>
11 * Wireshark - Network traffic analyzer
12 * By Gerald Combs <gerald@wireshark.org>
13 * Copyright 1998 Gerald Combs
15 * SPDX-License-Identifier: GPL-2.0-or-later
21 #include <epan/packet.h>
23 void proto_register_mifare(void);
25 static int proto_mifare
;
27 static int hf_mifare_command
;
28 static int hf_mifare_block_address
;
29 static int hf_mifare_key_a
;
30 static int hf_mifare_key_b
;
31 static int hf_mifare_uid
;
32 static int hf_mifare_operand
;
33 static int hf_mifare_payload
;
40 #define DECREMENT 0xC0
41 #define INCREMENT 0xC1
44 static const value_string hf_mifare_commands
[] = {
49 {TRANSFER
, "TRANSFER"},
50 {DECREMENT
, "DECREMENT"},
51 {INCREMENT
, "INCREMENT"},
58 /* Subtree handles: set by register_subtree_array */
59 static int ett_mifare
;
62 dissect_mifare(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
65 proto_tree
*mifare_tree
;
69 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "MiFare");
70 col_clear(pinfo
->cinfo
, COL_INFO
);
72 /* Start with a top-level item to add everything else to */
74 item
= proto_tree_add_item(tree
, proto_mifare
, tvb
, 0, -1, ENC_NA
);
75 mifare_tree
= proto_item_add_subtree(item
, ett_mifare
);
77 proto_tree_add_item(mifare_tree
, hf_mifare_command
, tvb
, 0, 1, ENC_BIG_ENDIAN
);
78 cmd
= tvb_get_uint8(tvb
, 0);
84 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
85 proto_tree_add_item(mifare_tree
, hf_mifare_key_a
, tvb
, 2, 6, ENC_BIG_ENDIAN
);
86 proto_tree_add_item(mifare_tree
, hf_mifare_uid
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
87 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Authenticate with Key A");
91 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
92 proto_tree_add_item(mifare_tree
, hf_mifare_key_b
, tvb
, 2, 6, ENC_BIG_ENDIAN
);
93 proto_tree_add_item(mifare_tree
, hf_mifare_uid
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
94 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Authenticate with Key B");
98 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
99 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Read");
103 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Write");
105 /* LibNFC and the TouchATag-branded reader don't expose the 2-byte CRC
106 or 4-bit NAK, as per MF1S703x, so we pretend that they don't exist.
108 I've never seen traces with those data structures before, either... */
110 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
112 proto_tree_add_item(mifare_tree
, hf_mifare_payload
, tvb
, 2, -1, ENC_NA
);
116 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
117 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Transfer");
121 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
122 proto_tree_add_item(mifare_tree
, hf_mifare_operand
, tvb
, 2, 4, ENC_BIG_ENDIAN
);
123 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Decrement");
127 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
128 proto_tree_add_item(mifare_tree
, hf_mifare_operand
, tvb
, 2, 4, ENC_BIG_ENDIAN
);
129 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Increment");
133 proto_tree_add_item(mifare_tree
, hf_mifare_block_address
, tvb
, 1, 1, ENC_BIG_ENDIAN
);
134 proto_tree_add_item(mifare_tree
, hf_mifare_operand
, tvb
, 2, 4, ENC_BIG_ENDIAN
);
135 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Restore");
139 col_append_sep_str(pinfo
->cinfo
, COL_INFO
, NULL
, "Unknown");
142 return tvb_captured_length(tvb
);
146 proto_register_mifare(void)
148 static hf_register_info hf
[] = {
151 { "Command", "mifare.cmd", FT_UINT8
, BASE_HEX
,
152 VALS(hf_mifare_commands
), 0x0, NULL
, HFILL
}},
153 {&hf_mifare_block_address
,
154 { "Block Address", "mifare.block.addr", FT_UINT8
, BASE_DEC
,
155 NULL
, 0x0, NULL
, HFILL
}},
157 { "Key A", "mifare.key.a", FT_UINT64
, BASE_HEX
,
158 NULL
, 0x0, NULL
, HFILL
}},
160 { "Key B", "mifare.key.b", FT_UINT64
, BASE_HEX
,
161 NULL
, 0x0, NULL
, HFILL
}},
163 { "UID", "mifare.uid", FT_UINT32
, BASE_HEX
,
164 NULL
, 0x0, NULL
, HFILL
}},
166 { "Operand", "mifare.operand", FT_INT32
, BASE_DEC
,
167 NULL
, 0x0, NULL
, HFILL
}},
169 { "Payload", "mifare.payload", FT_BYTES
, BASE_NONE
,
170 NULL
, 0x0, NULL
, HFILL
}}
173 static int *ett
[] = {
177 proto_mifare
= proto_register_protocol("NXP MiFare", "MiFare", "mifare");
178 proto_register_field_array(proto_mifare
, hf
, array_length(hf
));
179 proto_register_subtree_array(ett
, array_length(ett
));
181 register_dissector("mifare", dissect_mifare
, proto_mifare
);
185 * Editor modelines - https://www.wireshark.org/tools/modelines.html
190 * indent-tabs-mode: nil
193 * ex: set shiftwidth=4 tabstop=8 expandtab:
194 * :indentSize=4:tabSize=8:noTabs=true: