From 53ecc16079ee518e3b83df352a389d04543fcac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mo=C5=84?= Date: Tue, 23 Jul 2019 16:15:51 +0200 Subject: [PATCH] USBLL: Verify Token/Split packets CRC-5 Ping-Bug: 15908 Change-Id: I25aaf772d3d0af2f459a1ad78d8253344ed13f05 Reviewed-on: https://code.wireshark.org/review/34025 Petri-Dish: Peter Wu Tested-by: Petri Dish Buildbot Reviewed-by: Peter Wu --- debian/libwsutil0.symbols | 2 + epan/dissectors/packet-usbll.c | 43 +++++++++++++++------ wsutil/CMakeLists.txt | 2 + wsutil/crc5.c | 68 ++++++++++++++++++++++++++++++++++ wsutil/crc5.h | 40 ++++++++++++++++++++ 5 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 wsutil/crc5.c create mode 100644 wsutil/crc5.h diff --git a/debian/libwsutil0.symbols b/debian/libwsutil0.symbols index 1acbf5e929..036cc872dc 100644 --- a/debian/libwsutil0.symbols +++ b/debian/libwsutil0.symbols @@ -40,6 +40,8 @@ libwsutil.so.0 libwsutil0 #MINVER# crc32c_calculate@Base 1.10.0 crc32c_calculate_no_swap@Base 1.10.0 crc32c_table_lookup@Base 1.10.0 + crc5_usb_11bit_input@Base 3.1.1 + crc5_usb_19bit_input@Base 3.1.1 crc6_0X6F@Base 1.12.0~rc1 crc7update@Base 1.10.0 crc8_0x2F@Base 1.10.0 diff --git a/epan/dissectors/packet-usbll.c b/epan/dissectors/packet-usbll.c index ce99b983c9..8ff29d8ff7 100644 --- a/epan/dissectors/packet-usbll.c +++ b/epan/dissectors/packet-usbll.c @@ -17,6 +17,7 @@ #include #include #include +#include static int proto_usbll = -1; @@ -25,6 +26,7 @@ static int hf_usbll_pid = -1; static int hf_usbll_addr = -1; static int hf_usbll_endp = -1; static int hf_usbll_crc5 = -1; +static int hf_usbll_crc5_status = -1; static int hf_usbll_data = -1; static int hf_usbll_data_crc = -1; static int hf_usbll_data_crc_status = -1; @@ -37,11 +39,14 @@ static int hf_usbll_split_e = -1; static int hf_usbll_split_iso_se = -1; static int hf_usbll_split_et = -1; static int hf_usbll_split_crc5 = -1; +static int hf_usbll_split_crc5_status = -1; static int ett_usbll = -1; static expert_field ei_invalid_pid = EI_INIT; static expert_field ei_undecoded = EI_INIT; +static expert_field ei_wrong_crc5 = EI_INIT; +static expert_field ei_wrong_split_crc5 = EI_INIT; static expert_field ei_wrong_crc16 = EI_INIT; static dissector_handle_t usbll_handle; @@ -154,14 +159,19 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, case USB_PID_TOKEN_IN: case USB_PID_SPECIAL_PING: { + guint16 address_bits; static const int *address_fields[] = { &hf_usbll_addr, &hf_usbll_endp, - &hf_usbll_crc5, NULL }; - proto_tree_add_bitmask_list(tree, tvb, offset, 2, address_fields, ENC_LITTLE_ENDIAN); + address_bits = tvb_get_letohs(tvb, offset); + proto_tree_add_bitmask_list_value(tree, tvb, offset, 2, address_fields, address_bits); + proto_tree_add_checksum(tree, tvb, offset, + hf_usbll_crc5, hf_usbll_crc5_status, &ei_wrong_crc5, pinfo, + crc5_usb_11bit_input(address_bits), + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); offset += 2; break; } @@ -191,13 +201,12 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, break; case USB_PID_TOKEN_SOF: { - static const int *sof_fields[] = { - &hf_usbll_sof_framenum, - &hf_usbll_crc5, - NULL - }; - - proto_tree_add_bitmask_list(tree, tvb, offset, 2, sof_fields, ENC_LITTLE_ENDIAN); + guint32 frame; + proto_tree_add_item_ret_uint(tree, hf_usbll_sof_framenum, tvb, offset, 2, ENC_LITTLE_ENDIAN, &frame); + proto_tree_add_checksum(tree, tvb, offset, + hf_usbll_crc5, hf_usbll_crc5_status, &ei_wrong_crc5, pinfo, + crc5_usb_11bit_input(frame), + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); offset += 2; break; } @@ -212,7 +221,6 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, &hf_usbll_split_s, &hf_usbll_split_e, &hf_usbll_split_et, - &hf_usbll_split_crc5, NULL }; static const int *split_iso_fields[] = { @@ -221,7 +229,6 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, &hf_usbll_split_port, &hf_usbll_split_iso_se, &hf_usbll_split_et, - &hf_usbll_split_crc5, NULL }; @@ -233,6 +240,10 @@ dissect_usbll_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, { proto_tree_add_bitmask_list(tree, tvb, offset, 3, split_fields, ENC_LITTLE_ENDIAN); } + proto_tree_add_checksum(tree, tvb, offset, + hf_usbll_split_crc5, hf_usbll_split_crc5_status, &ei_wrong_split_crc5, pinfo, + crc5_usb_19bit_input(tmp), + ENC_LITTLE_ENDIAN, PROTO_CHECKSUM_VERIFY); offset += 3; break; } @@ -276,6 +287,10 @@ proto_register_usbll(void) { "CRC5", "usbll.crc5", FT_UINT16, BASE_HEX, NULL, 0xF800, NULL, HFILL }}, + { &hf_usbll_crc5_status, + { "CRC5 Status", "usbll.crc5.status", + FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, + NULL, HFILL }}, { &hf_usbll_data, { "Data", "usbll.data", FT_BYTES, BASE_NONE, NULL, 0, @@ -325,11 +340,17 @@ proto_register_usbll(void) { "CRC5", "usbll.split_crc5", FT_UINT24, BASE_HEX, NULL, 0xF80000, NULL, HFILL }}, + { &hf_usbll_split_crc5_status, + { "CRC5 Status", "usbll.split_crc5.status", + FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0, + NULL, HFILL }}, }; static ei_register_info ei[] = { { &ei_invalid_pid, { "usbll.invalid_pid", PI_MALFORMED, PI_ERROR, "Invalid USB Packet ID", EXPFILL }}, { &ei_undecoded, { "usbll.undecoded", PI_UNDECODED, PI_WARN, "Not dissected yet (report to wireshark.org)", EXPFILL }}, + { &ei_wrong_crc5, { "usbll.crc5.wrong", PI_PROTOCOL, PI_WARN, "Wrong CRC", EXPFILL }}, + { &ei_wrong_split_crc5, { "usbll.split_crc5.wrong", PI_PROTOCOL, PI_WARN, "Wrong CRC", EXPFILL }}, { &ei_wrong_crc16, { "usbll.crc16.wrong", PI_PROTOCOL, PI_WARN, "Wrong CRC", EXPFILL }}, }; diff --git a/wsutil/CMakeLists.txt b/wsutil/CMakeLists.txt index 799f9e8f40..e0d256f37e 100644 --- a/wsutil/CMakeLists.txt +++ b/wsutil/CMakeLists.txt @@ -23,6 +23,7 @@ set(WSUTIL_PUBLIC_HEADERS copyright_info.h cpu_info.h crash_info.h + crc5.h crc6.h crc7.h crc8.h @@ -85,6 +86,7 @@ set(WSUTIL_COMMON_FILES crc16.c crc16-plain.c crc32.c + crc5.c crc6.c crc7.c crc8.c diff --git a/wsutil/crc5.c b/wsutil/crc5.c new file mode 100644 index 0000000000..2fc56a2fad --- /dev/null +++ b/wsutil/crc5.c @@ -0,0 +1,68 @@ +/* crc5.c + * CRC-5 routine + * + * 2019 Tomasz Mon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "config.h" + +#include +#include + +static guint8 crc5_usb_bits(guint32 v, int vl, guint8 ival) +{ + /* This function is based on code posted by John Sullivan to Wireshark-dev + * mailing list on Jul 21, 2019. + * + * "One of the properties of LFSRs is that a 1 bit in the input toggles a + * completely predictable set of register bits *at any point in the + * future*. This isn't often useful for most CRC caculations on variable + * sized input, as the cost of working out which those bits are vastly + * outweighs most other methods." + * + * In USB 2.0, the CRC5 is calculated on either 11 or 19 bits inputs, + * and thus this approach is viable. + */ + guint8 rv = ival; + static const guint8 bvals[19] = { + 0x1e, 0x15, 0x03, 0x06, 0x0c, 0x18, 0x19, 0x1b, + 0x1f, 0x17, 0x07, 0x0e, 0x1c, 0x11, 0x0b, 0x16, + 0x05, 0x0a, 0x14 + }; + + for (int i = 0; i < vl; i++) { + if (v & (1 << i)) { + rv ^= bvals[19 - vl + i]; + } + } + return rv; +} + +guint8 crc5_usb_11bit_input(guint16 input) +{ + return crc5_usb_bits(input, 11, 0x02); +} + +guint8 crc5_usb_19bit_input(guint32 input) +{ + return crc5_usb_bits(input, 19, 0x1d); +} + +/* + * Editor modelines - https://www.wireshark.org/tools/modelines.html + * + * Local variables: + * c-basic-offset: 4 + * tab-width: 8 + * indent-tabs-mode: nil + * End: + * + * vi: set shiftwidth=4 tabstop=8 expandtab: + * :indentSize=4:tabSize=8:noTabs=true: + */ diff --git a/wsutil/crc5.h b/wsutil/crc5.h new file mode 100644 index 0000000000..da3fde41fd --- /dev/null +++ b/wsutil/crc5.h @@ -0,0 +1,40 @@ +/* crc5.h + * Declaration of CRC-5 routines and table + * + * 2019 Tomasz Mon + * + * Wireshark - Network traffic analyzer + * By Gerald Combs + * Copyright 1998 Gerald Combs + * + * SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#ifndef __CRC5_H__ +#define __CRC5_H__ + +#include "ws_symbol_export.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** Compute the 5-bit CRC value of a input value matching the CRC-5 + defined in USB 2.0 Specification. This function calculates the CRC + on low 11 bits of the input value. High bits are ignored. + @param input Source data for which the CRC-5 should be calculated. + @return the CRC5 checksum for input value */ +WS_DLL_PUBLIC guint8 crc5_usb_11bit_input(guint16 input); + +/** Compute the 5-bit CRC value of a input value matching the CRC-5 + defined in USB 2.0 Specification. This function calculates the CRC + on low 19 bits of the input value. High bits are ignored. + @param input Source data for which the CRC-5 should be calculated. + @return the CRC5 checksum for input value */ +WS_DLL_PUBLIC guint8 crc5_usb_19bit_input(guint32 input); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __CRC5_H__ */