diff options
author | Peter Wu <peter@lekensteyn.nl> | 2019-07-16 01:45:14 +0100 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2019-07-16 06:40:10 +0000 |
commit | 3967f60e45e5d17bc8232fed9be7d5fadf5e82a7 (patch) | |
tree | f6802d1831b5f97c312a40d70671f85e2394f7c2 | |
parent | bafe354fbd9920dee0b87a70fb45a2585677ba58 (diff) |
QUIC: update for new Connection ID Lengths (draft -22)
Fixes decryption and decoding of draft -22 traces.
Bug: 13881
Change-Id: Id5bdee1e6cf2b6f91ec06d7745d2939640802c31
Reviewed-on: https://code.wireshark.org/review/33961
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r-- | epan/dissectors/packet-quic.c | 112 |
1 files changed, 44 insertions, 68 deletions
diff --git a/epan/dissectors/packet-quic.c b/epan/dissectors/packet-quic.c index 29cf4a5c17..ae3b719881 100644 --- a/epan/dissectors/packet-quic.c +++ b/epan/dissectors/packet-quic.c @@ -177,9 +177,15 @@ typedef struct quic_decrypt_result { guint data_len; /**< Size of decrypted data. */ } quic_decrypt_result_t; +/* + * Although the QUIC SCID/DCID length field can store at most 255, v1 limits the + * CID length to 20. + */ +#define QUIC_MAX_CID_LENGTH 20 + typedef struct quic_cid { guint8 len; - guint8 cid[18]; + guint8 cid[QUIC_MAX_CID_LENGTH]; } quic_cid_t; /** QUIC decryption context. */ @@ -306,6 +312,7 @@ const value_string quic_version_vals[] = { { 0xff000013, "draft-19" }, { 0xff000014, "draft-20" }, { 0xff000015, "draft-21" }, + { 0xff000016, "draft-22" }, { 0, NULL } }; @@ -317,26 +324,6 @@ static const value_string quic_short_long_header_vals[] = { #define SH_KP 0x04 -static const value_string quic_cid_len_vals[] = { - { 0, "0 octets" }, - { 1, "4 octets" }, - { 2, "5 octets" }, - { 3, "6 octets" }, - { 4, "7 octets" }, - { 5, "8 octets" }, - { 6, "9 octets" }, - { 7, "10 octets" }, - { 8, "11 octets" }, - { 9, "12 octets" }, - { 10, "13 octets" }, - { 11, "14 octets" }, - { 12, "15 octets" }, - { 13, "16 octets" }, - { 14, "17 octets" }, - { 15, "18 octets" }, - { 0, NULL } -}; - #define QUIC_LPT_INITIAL 0x0 #define QUIC_LPT_0RTT 0x1 #define QUIC_LPT_HANDSHAKE 0x2 @@ -634,13 +621,14 @@ quic_cids_insert(quic_cid_t *cid, quic_info_data_t *conn, gboolean from_server) // Replace any previous CID key with the new one. wmem_map_remove(connections, cid); wmem_map_insert(connections, cid, conn); - quic_cid_lengths |= (1 << cid->len); + G_STATIC_ASSERT(QUIC_MAX_CID_LENGTH <= 8 * sizeof(quic_cid_lengths)); + quic_cid_lengths |= (1ULL << cid->len); } static inline gboolean quic_cids_is_known_length(const quic_cid_t *cid) { - return (quic_cid_lengths & (1 << cid->len)) != 0; + return (quic_cid_lengths & (1ULL << cid->len)) != 0; } /** @@ -1161,10 +1149,10 @@ dissect_quic_frame_type(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree ti = proto_tree_add_item_ret_uint(ft_tree, hf_quic_nci_connection_id_length, tvb, offset, 1, ENC_BIG_ENDIAN, &nci_length); offset++; - valid_cid = nci_length >= 4 && nci_length <= 18; + valid_cid = nci_length >= 1 && nci_length <= QUIC_MAX_CID_LENGTH; if (!valid_cid) { expert_add_info_format(pinfo, ti, &ei_quic_protocol_violation, - "Connection ID Length must be between 4 and 18 bytes"); + "Connection ID Length must be between 1 and %d bytes", QUIC_MAX_CID_LENGTH); } proto_tree_add_item(ft_tree, hf_quic_nci_connection_id, tvb, offset, nci_length, ENC_NA); @@ -1800,11 +1788,8 @@ dissect_quic_long_header_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *q offset += 4; proto_tree_add_item_ret_uint(quic_tree, hf_quic_dcil, tvb, offset, 1, ENC_BIG_ENDIAN, &dcil); - proto_tree_add_item_ret_uint(quic_tree, hf_quic_scil, tvb, offset, 1, ENC_BIG_ENDIAN, &scil); offset++; - if (dcil) { - dcil += 3; proto_tree_add_item(quic_tree, hf_quic_dcid, tvb, offset, dcil, ENC_NA); // TODO expert info on CID mismatch with connection tvb_memcpy(tvb, dcid->cid, offset, dcil); @@ -1812,8 +1797,9 @@ dissect_quic_long_header_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *q offset += dcil; } + proto_tree_add_item_ret_uint(quic_tree, hf_quic_scil, tvb, offset, 1, ENC_BIG_ENDIAN, &scil); + offset++; if (scil) { - scil += 3; proto_tree_add_item(quic_tree, hf_quic_scid, tvb, offset, scil, ENC_NA); // TODO expert info on CID mismatch with connection tvb_memcpy(tvb, scid->cid, offset, scil); @@ -1842,15 +1828,13 @@ dissect_quic_retry_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tr guint retry_token_len; proto_tree_add_item(quic_tree, hf_quic_long_packet_type, tvb, offset, 1, ENC_NA); - proto_tree_add_item_ret_uint(quic_tree, hf_quic_odcil, tvb, offset, 1, ENC_NA, &odcil); - if (odcil) { - odcil += 3; - } offset += 1; col_set_str(pinfo->cinfo, COL_INFO, "Retry"); offset = dissect_quic_long_header_common(tvb, pinfo, quic_tree, offset, quic_packet, &version, &dcid, &scid); + proto_tree_add_item_ret_uint(quic_tree, hf_quic_odcil, tvb, offset, 1, ENC_NA, &odcil); + offset++; proto_tree_add_item(quic_tree, hf_quic_odcid, tvb, offset, odcil, ENC_NA); offset += odcil; retry_token_len = tvb_reported_length_remaining(tvb, offset); @@ -1913,7 +1897,8 @@ dissect_quic_long_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tre if (!error) { guint32 pkn32 = 0; int hp_cipher_algo = long_packet_type != QUIC_LPT_INITIAL && conn ? conn->cipher_algo : GCRY_CIPHER_AES128; - guint pn_offset = 6 + dcid.len + scid.len; + // PKN is after type(1) + version(4) + DCIL+DCID + SCIL+SCID + guint pn_offset = 1 + 4 + 1 + dcid.len + 1 + scid.len; if (long_packet_type == QUIC_LPT_INITIAL) { pn_offset += tvb_get_varint(tvb, pn_offset, 8, &token_length, ENC_VARINT_QUIC); pn_offset += (guint)token_length; @@ -2127,16 +2112,9 @@ quic_get_message_tvb(tvbuff_t *tvb, const guint offset) // If this is not a VN packet but a valid long form, extract a subset. // TODO check for valid QUIC versions as future versions might change the format. if (version != 0) { - guint8 cid_lengths = tvb_get_guint8(tvb, offset + 5); - guint8 dcil = cid_lengths >> 4; - guint8 scil = cid_lengths & 0xf; - guint length = 6; - if (dcil) { - length += 3 + dcil; - } - if (scil) { - length += 3 + scil; - } + guint length = 5; // flag (1 byte) + version (4 bytes) + length += 1 + tvb_get_guint8(tvb, offset + length); // DCID + length += 1 + tvb_get_guint8(tvb, offset + length); // SCID if (long_packet_type == QUIC_LPT_INITIAL) { length += tvb_get_varint(tvb, offset + length, 8, &token_length, ENC_VARINT_QUIC); length += (guint)token_length; @@ -2182,21 +2160,19 @@ quic_extract_header(tvbuff_t *tvb, guint8 *long_packet_type, guint32 *version, // skip version offset += 4; - // read DCIL/SCIL (Connection ID Lengths). - guint8 cid_lengths = tvb_get_guint8(tvb, offset); - guint8 dcil = cid_lengths >> 4; - guint8 scil = cid_lengths & 0xf; + // read DCID and SCID (both are prefixed by a length byte). + guint8 dcil = tvb_get_guint8(tvb, offset); offset++; if (dcil) { - dcil += 3; tvb_memcpy(tvb, dcid->cid, offset, dcil); dcid->len = dcil; offset += dcil; } + guint8 scil = tvb_get_guint8(tvb, offset); + offset++; if (scil) { - scil += 3; tvb_memcpy(tvb, scid->cid, offset, scil); scid->len = scil; } @@ -2204,10 +2180,10 @@ quic_extract_header(tvbuff_t *tvb, guint8 *long_packet_type, guint32 *version, // Definitely not draft -10, set version to dummy value. *version = 0; // For short headers, the DCID length is unknown and could be 0 or - // anything from 4 to 18 bytes. Copy the maximum possible and let the + // anything from 1 to 20 bytes. Copy the maximum possible and let the // consumer truncate it as necessary. - tvb_memcpy(tvb, dcid->cid, offset, 18); - dcid->len = 18; + tvb_memcpy(tvb, dcid->cid, offset, QUIC_MAX_CID_LENGTH); + dcid->len = QUIC_MAX_CID_LENGTH; } } @@ -2310,15 +2286,15 @@ dissect_quic_short_header_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr return FALSE; } - // Is this a SH packet after connection migration? SH (draft -14): - // Flag (1) + DCID (4-18) + PKN (1/2/4) + encrypted payload (>= 16). - if (tvb_captured_length(tvb) < 1 + 4 + 1 + 16) { + // Is this a SH packet after connection migration? SH (since draft -22): + // Flag (1) + DCID (1-20) + PKN (1/2/4) + encrypted payload (>= 16). + if (tvb_captured_length(tvb) < 1 + 1 + 1 + 16) { return FALSE; } // DCID length is unknown, so extract the maximum and look for a match. - quic_cid_t dcid = {.len=18}; - tvb_memcpy(tvb, dcid.cid, 1, 18); + quic_cid_t dcid = {.len=QUIC_MAX_CID_LENGTH}; + tvb_memcpy(tvb, dcid.cid, 1, QUIC_MAX_CID_LENGTH); gboolean from_server; if (!quic_connection_find(pinfo, QUIC_SHORT_PACKET, &dcid, &from_server)) { return FALSE; @@ -2333,12 +2309,12 @@ dissect_quic_short_header_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tr static gboolean dissect_quic_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) { /* - * Since draft -12: - * Flag (1 byte) + Version (4 bytes) + DCIL/SCIL (1 byte) + - * Destination Connection ID (0/4..18 based on DCIL) + - * Source Connection ID (0/4..18 based on SCIL) + + * Since draft -22: + * Flag (1 byte) + Version (4 bytes) + + * Length (1 byte) + Destination Connection ID (0..255) + + * Length (1 byte) + Source Connection ID (0..255) + * Payload length (1/2/4/8) + Packet number (1/2/4 bytes) + Payload. - * (absolute minimum: 8 + payload) + * (absolute minimum: 9 + payload) * (for Version Negotiation, payload len + PKN + payload is replaced by * Supported Version (multiple of 4 bytes.) */ @@ -2442,13 +2418,13 @@ proto_register_quic(void) }, { &hf_quic_dcil, { "Destination Connection ID Length", "quic.dcil", - FT_UINT8, BASE_DEC, VALS(quic_cid_len_vals), 0xf0, - "Destination Connection ID Length (for non-zero lengths, add 3 for actual length)", HFILL } + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, { &hf_quic_scil, { "Source Connection ID Length", "quic.scil", - FT_UINT8, BASE_DEC, VALS(quic_cid_len_vals), 0x0f, - "Source Connection ID Length (for non-zero lengths, add 3 for actual length)", HFILL } + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } }, { &hf_quic_token_length, { "Token Length", "quic.token_length", @@ -2525,7 +2501,7 @@ proto_register_quic(void) { &hf_quic_odcil, { "Original Destination Connection ID Length", "quic.odcil", - FT_UINT8, BASE_DEC, VALS(quic_cid_len_vals), 0x0f, + FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } }, { &hf_quic_odcid, |