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 <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
Tomasz Moń 2019-07-23 16:15:51 +02:00 committed by Peter Wu
parent d89eb91eaf
commit 53ecc16079
5 changed files with 144 additions and 11 deletions

View File

@ -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

View File

@ -17,6 +17,7 @@
#include <epan/packet.h>
#include <epan/expert.h>
#include <epan/crc16-tvb.h>
#include <wsutil/crc5.h>
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 }},
};

View File

@ -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

68
wsutil/crc5.c Normal file
View File

@ -0,0 +1,68 @@
/* crc5.c
* CRC-5 routine
*
* 2019 Tomasz Mon <desowin@gmail.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include <glib.h>
#include <wsutil/crc5.h>
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:
*/

40
wsutil/crc5.h Normal file
View File

@ -0,0 +1,40 @@
/* crc5.h
* Declaration of CRC-5 routines and table
*
* 2019 Tomasz Mon <desowin@gmail.com>
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* 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__ */