HACK: pinfo->private_data points to smb_info again
[wireshark-wip.git] / epan / dissectors / packet-btsmp.c
blob1acd6a652204fec5612a233798ab3a8a534a670e
1 /* packet-btsmp.c
2 * Routines for Bluetooth Security Manager Protocol dissection
4 * Copyright 2012, Allan M. Madsen <allan.m@madsen.dk>
6 * $Id$
8 * Wireshark - Network traffic analyzer
9 * By Gerald Combs <gerald@wireshark.org>
10 * Copyright 1998 Gerald Combs
12 * Wireshark - Network traffic analyzer
13 * By Gerald Combs <gerald@wireshark.org>
14 * Copyright 1998 Gerald Combs
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include "config.h"
33 #include <epan/packet.h>
34 #include "packet-btl2cap.h"
36 /* Initialize the protocol and registered fields */
37 static int proto_btsmp = -1;
39 static int hf_btsmp_opcode = -1;
40 static int hf_btsmp_io_capabilities = -1;
41 static int hf_btsmp_oob_data_flags = -1;
42 static int hf_btsmp_reason = -1;
43 static int hf_btsmp_cfm_value = -1;
44 static int hf_btsmp_random = -1;
45 static int hf_btsmp_long_term_key = -1;
46 static int hf_btsmp_id_resolving_key = -1;
47 static int hf_btsmp_signature_key = -1;
48 static int hf_btsmp_bonding_flags = -1;
49 static int hf_btsmp_mitm_flag = -1;
50 static int hf_btsmp_max_enc_key_size = -1;
51 static int hf_btsmp_key_dist_enc = -1;
52 static int hf_btsmp_key_dist_id = -1;
53 static int hf_btsmp_key_dist_sign = -1;
54 static int hf_btsmp_ediv = -1;
55 static int hf_btsmp_authreq = -1;
56 static int hf_btsmp_initiator_key_distribution = -1;
57 static int hf_btsmp_responder_key_distribution = -1;
59 /* Initialize the subtree pointers */
60 static gint ett_btsmp = -1;
61 static gint ett_btsmp_auth_req = -1;
62 static gint ett_btsmp_key_dist = -1;
64 /* Opcodes */
65 static const value_string opcode_vals[] = {
66 {0x01, "Pairing Request"},
67 {0x02, "Pairing Response"},
68 {0x03, "Pairing Confirm"},
69 {0x04, "Pairing Random"},
70 {0x05, "Pairing Failed"},
71 {0x06, "Encryption Information"},
72 {0x07, "Master Identification"},
73 {0x08, "Identity Information"},
74 {0x09, "Identity Address Information"},
75 {0x0a, "Signing Information"},
76 {0x0b, "Security Request"},
77 {0x0, NULL}
80 /* IO capabilities */
81 static const value_string io_capability_vals[] = {
82 {0x00, "Display Only"},
83 {0x01, "Display Yes/No"},
84 {0x02, "Keyboard Only"},
85 {0x03, "No Input, No Output"},
86 {0x04, "Keyboard, Display"},
87 {0x0, NULL}
90 /* OOB Data present Flag */
91 static const value_string oob_data_flag_vals[] = {
92 {0x00, "OOB Auth. Data Not Present"},
93 {0x01, "OOB Auth. Data From Remote Device Present"},
94 {0x0, NULL}
97 /* Bonding flags */
98 static const value_string bonding_flag_vals[] = {
99 {0x00, "No Bonding"},
100 {0x01, "Bonding"},
101 {0x0, NULL}
104 /* Reason codes */
105 static const value_string reason_vals[] = {
106 {0x01, "Passkey Entry Failed"},
107 {0x02, "OOB Not Available"},
108 {0x03, "Authentication Requirements"},
109 {0x04, "Confirm Value Failed"},
110 {0x05, "Pairing Not Supported"},
111 {0x06, "Encryption Key Size"},
112 {0x07, "Command Not Supported"},
113 {0x08, "Unspecified Reason"},
114 {0x09, "Repeated Attempts"},
115 {0x0a, "Invalid Parameters"},
116 {0x0, NULL}
119 void proto_register_btsmp(void);
120 void proto_reg_handoff_btsmp(void);
122 static int
123 dissect_btsmp_auth_req(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
125 proto_item *ti_param;
126 proto_tree *st_param;
127 guint8 param;
129 param = tvb_get_guint8(tvb, offset);
130 ti_param = proto_tree_add_item(tree, hf_btsmp_authreq, tvb, offset, 1, ENC_NA);
131 st_param = proto_item_add_subtree(ti_param, ett_btsmp_auth_req);
132 proto_tree_add_item(st_param, hf_btsmp_bonding_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
133 proto_item_append_text(ti_param, "%s, ", val_to_str_const(param & 0x03, bonding_flag_vals, "<unknown>"));
134 proto_tree_add_item(st_param, hf_btsmp_mitm_flag, tvb, offset, 1, ENC_LITTLE_ENDIAN);
135 proto_item_append_text(ti_param, "%s", (param & 0x04) ? "MITM" : "No MITM");
137 col_append_fstr(pinfo->cinfo, COL_INFO, "%s, %s", val_to_str_const(param & 0x03, bonding_flag_vals, "<unknown>"), (param & 0x04) ? "MITM" : "No MITM");
139 return offset + 1;
142 static int
143 dissect_btsmp_key_dist(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree, gboolean initiator)
145 proto_item *ti_param;
146 proto_tree *st_param;
147 guint8 param;
149 param = tvb_get_guint8(tvb, offset);
150 if (initiator) {
151 col_append_str(pinfo->cinfo, COL_INFO, ", Initiator Key(s): ");
152 ti_param = proto_tree_add_item(tree, hf_btsmp_initiator_key_distribution, tvb, offset, 1, ENC_NA);
154 else {
155 col_append_str(pinfo->cinfo, COL_INFO, ", Responder Key(s): ");
156 ti_param = proto_tree_add_item(tree, hf_btsmp_responder_key_distribution, tvb, offset, 1, ENC_NA);
159 st_param = proto_item_add_subtree(ti_param, ett_btsmp_key_dist);
160 proto_tree_add_item(st_param, hf_btsmp_key_dist_enc, tvb, offset, 1, ENC_LITTLE_ENDIAN);
161 proto_tree_add_item(st_param, hf_btsmp_key_dist_id, tvb, offset, 1, ENC_LITTLE_ENDIAN);
162 proto_tree_add_item(st_param, hf_btsmp_key_dist_sign, tvb, offset, 1, ENC_LITTLE_ENDIAN);
163 if (param & 0x01) {
164 proto_item_append_text(ti_param, "LTK ");
165 col_append_str(pinfo->cinfo, COL_INFO, "LTK ");
167 if (param & 0x02) {
168 proto_item_append_text(ti_param, "IRK ");
169 col_append_str(pinfo->cinfo, COL_INFO, "IRK ");
171 if (param & 0x04) {
172 proto_item_append_text(ti_param, "CSRK ");
173 col_append_str(pinfo->cinfo, COL_INFO, "CSRK ");
176 return offset + 1;
179 static int
180 dissect_btsmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
182 int offset = 0;
183 proto_item *ti;
184 proto_tree *st;
185 guint8 opcode;
187 ti = proto_tree_add_item(tree, proto_btsmp, tvb, 0, -1, ENC_NA);
188 st = proto_item_add_subtree(ti, ett_btsmp);
190 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SMP");
192 switch (pinfo->p2p_dir) {
193 case P2P_DIR_SENT:
194 col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
195 break;
196 case P2P_DIR_RECV:
197 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
198 break;
199 default:
200 col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
201 pinfo->p2p_dir);
202 break;
205 if (tvb_length_remaining(tvb, 0) < 1)
206 return FALSE;
208 proto_tree_add_item(st, hf_btsmp_opcode, tvb, 0, 1, ENC_LITTLE_ENDIAN);
209 opcode = tvb_get_guint8(tvb, 0);
210 offset++;
212 col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(opcode, opcode_vals, "<unknown>"));
214 switch (opcode) {
215 case 0x01: /* Pairing Request */
216 case 0x02: /* Pairing Response */
218 col_append_str(pinfo->cinfo, COL_INFO, ": ");
220 proto_tree_add_item(st, hf_btsmp_io_capabilities, tvb, offset, 1, ENC_LITTLE_ENDIAN);
221 offset++;
222 proto_tree_add_item(st, hf_btsmp_oob_data_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
223 offset++;
225 offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st);
227 proto_tree_add_item(st, hf_btsmp_max_enc_key_size, tvb, offset, 1, ENC_LITTLE_ENDIAN);
228 offset++;
230 offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, TRUE);
231 offset = dissect_btsmp_key_dist(tvb, offset, pinfo, st, FALSE);
232 break;
235 case 0x03: /* Pairing Confirm */
236 proto_tree_add_item(st, hf_btsmp_cfm_value, tvb, offset, 16, ENC_NA);
237 offset += 16;
238 break;
240 case 0x04: /* Pairing Random */
241 proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 16, ENC_NA);
242 offset += 16;
243 break;
245 case 0x05: /* Pairing Failed */
246 proto_tree_add_item(st, hf_btsmp_reason, tvb, offset, 1, ENC_LITTLE_ENDIAN);
247 col_append_fstr(pinfo->cinfo, COL_INFO, ": %s", val_to_str_const(tvb_get_guint8(tvb, offset), reason_vals, "<unknown>"));
248 offset++;
249 break;
251 case 0x06: /* Encryption Information */
252 proto_tree_add_item(st, hf_btsmp_long_term_key, tvb, offset, 16, ENC_NA);
253 offset += 16;
254 break;
256 case 0x07: /* Master Identification */
257 proto_tree_add_item(st, hf_btsmp_ediv, tvb, offset, 2, ENC_LITTLE_ENDIAN);
258 offset += 2;
259 proto_tree_add_item(st, hf_btsmp_random, tvb, offset, 8, ENC_NA);
260 offset += 8;
261 break;
263 case 0x08: /* Identity Information */
264 proto_tree_add_item(st, hf_btsmp_id_resolving_key, tvb, offset, 16, ENC_NA);
265 offset += 16;
266 break;
268 case 0x0a: /* Signing Informationn */
269 proto_tree_add_item(st, hf_btsmp_signature_key, tvb, offset, 16, ENC_NA);
270 offset += 16;
271 break;
273 case 0x0b: /* Security Request */
274 col_append_str(pinfo->cinfo, COL_INFO, ": ");
275 offset = dissect_btsmp_auth_req(tvb, offset, pinfo, st);
276 break;
278 default:
279 break;
282 return offset;
285 void
286 proto_register_btsmp(void)
288 static hf_register_info hf[] = {
289 {&hf_btsmp_opcode,
290 {"Opcode", "btsmp.opcode",
291 FT_UINT8, BASE_HEX, VALS(opcode_vals), 0x0,
292 NULL, HFILL}
294 {&hf_btsmp_reason,
295 {"Reason", "btsmp.reason",
296 FT_UINT8, BASE_HEX, VALS(reason_vals), 0x0,
297 NULL, HFILL}
299 {&hf_btsmp_io_capabilities,
300 {"IO Capability", "btsmp.io_capability",
301 FT_UINT8, BASE_HEX, VALS(io_capability_vals), 0x0,
302 NULL, HFILL}
304 {&hf_btsmp_oob_data_flags,
305 {"OOB Data Flags", "btsmp.oob_data_flags",
306 FT_UINT8, BASE_HEX, VALS(oob_data_flag_vals), 0x0,
307 NULL, HFILL}
309 {&hf_btsmp_cfm_value,
310 {"Confirm Value", "btsmp.cfm_value",
311 FT_BYTES, BASE_NONE, NULL, 0x0,
312 NULL, HFILL}
314 {&hf_btsmp_random,
315 {"Random Value", "btsmp.random_value",
316 FT_BYTES, BASE_NONE, NULL, 0x0,
317 NULL, HFILL}
319 {&hf_btsmp_long_term_key,
320 {"Long Term Key", "btsmp.long_term_key",
321 FT_BYTES, BASE_NONE, NULL, 0x0,
322 NULL, HFILL}
324 {&hf_btsmp_id_resolving_key,
325 {"Identity Resolving Key", "btsmp.id_resolving_key",
326 FT_BYTES, BASE_NONE, NULL, 0x0,
327 NULL, HFILL}
329 {&hf_btsmp_signature_key,
330 {"Signature Key", "btsmp.signature_key",
331 FT_BYTES, BASE_NONE, NULL, 0x0,
332 NULL, HFILL}
334 {&hf_btsmp_bonding_flags,
335 {"Bonding Flags", "btsmp.bonding_flags",
336 FT_UINT8, BASE_HEX, VALS(bonding_flag_vals), 0x03,
337 NULL, HFILL}
339 {&hf_btsmp_mitm_flag,
340 {"MITM Flag", "btsmp.mitm_flag",
341 FT_UINT8, BASE_DEC, NULL, 0x04,
342 NULL, HFILL}
344 {&hf_btsmp_max_enc_key_size,
345 {"Max Encryption Key Size", "btsmp.max_enc_key_size",
346 FT_UINT8, BASE_DEC, NULL, 0x00,
347 NULL, HFILL}
349 {&hf_btsmp_key_dist_enc,
350 {"Encryption Key (LTK)", "btsmp.key_dist_enc",
351 FT_UINT8, BASE_DEC, NULL, 0x01,
352 NULL, HFILL}
354 {&hf_btsmp_key_dist_id,
355 {"Id Key (IRK)", "btsmp.key_dist_id",
356 FT_UINT8, BASE_DEC, NULL, 0x02,
357 NULL, HFILL}
359 {&hf_btsmp_key_dist_sign,
360 {"Signature Key (CSRK)", "btsmp.key_dist_sign",
361 FT_UINT8, BASE_DEC, NULL, 0x04,
362 NULL, HFILL}
364 {&hf_btsmp_ediv,
365 {"Encrypted Diversifier (EDIV)", "btsmp.ediv",
366 FT_UINT16, BASE_HEX, NULL, 0x00,
367 NULL, HFILL}
369 {&hf_btsmp_authreq,
370 {"AuthReq", "btsmp.authreq",
371 FT_NONE, BASE_NONE, NULL, 0x00,
372 NULL, HFILL}
374 {&hf_btsmp_initiator_key_distribution,
375 {"Initiator Key Distribution", "btsmp.initiator_key_distribution",
376 FT_NONE, BASE_NONE, NULL, 0x00,
377 NULL, HFILL}
379 {&hf_btsmp_responder_key_distribution,
380 {"Responder Key Distribution", "btsmp.responder_key_distribution",
381 FT_NONE, BASE_NONE, NULL, 0x00,
382 NULL, HFILL}
386 /* Setup protocol subtree array */
387 static gint *ett[] = {
388 &ett_btsmp,
389 &ett_btsmp_auth_req,
390 &ett_btsmp_key_dist
393 /* Register the protocol name and description */
394 proto_btsmp = proto_register_protocol("Bluetooth Security Manager Protocol",
395 "BT SMP", "btsmp");
397 new_register_dissector("btsmp", dissect_btsmp, proto_btsmp);
399 /* Required function calls to register the header fields and subtrees used */
400 proto_register_field_array(proto_btsmp, hf, array_length(hf));
401 proto_register_subtree_array(ett, array_length(ett));
404 void
405 proto_reg_handoff_btsmp(void)
407 dissector_handle_t btsmp_handle;
409 btsmp_handle = find_dissector("btsmp");
410 dissector_add_uint("btl2cap.cid", BTL2CAP_FIXED_CID_SMP, btsmp_handle);
414 * Editor modelines - http://www.wireshark.org/tools/modelines.html
416 * Local variables:
417 * c-basic-offset: 4
418 * tab-width: 8
419 * indent-tabs-mode: nil
420 * End:
422 * vi: set shiftwidth=4 tabstop=8 expandtab:
423 * :indentSize=4:tabSize=8:noTabs=true: