Wireshark-dev: Re: [Wireshark-dev] working with header data

From: Ed Beroset <beroset@xxxxxxxxxxxxxx>
Date: Fri, 14 Oct 2011 16:16:00 -0400
Guy Harris wrote:

On Oct 14, 2011, at 6:03 AM, Ed Beroset wrote:

There is a portion of the code called
canonify_unencrypted_header().  In order to cryptographically
process the ASN.1 components of the header, the data must be
canonified.  To do this, the dissector must process the pieces of
the header in a particular order no matter what order these were
actually sent.  Additionally, the entire BER encoding must be
processed, and not just the data with a [tag, length, value]
triplet.

I.e., what gets run through the CMAC algorithm is a bunch of
BER-encoded data, in a different order than the order in which the
data appears in the header?

It could be, yes. The specification for the standard doesn't prescribe a particular data order for header information, but of course the CMAC algorithm is designed to be sensitive to data order. That leads to the requirement for being able to rearrange the data.

I can think of two ways to do this (and indeed, have done it both
ways).  First, I can rely on the ASN.1 parser to break things into
their respective fields and then process the components.  This
approach has two problems.  The first problem is that because the
entire encoding must be processed, the tag and length must be
reconstructed which is a bit messy and complex.

Could you use #.FN_BODY for each of the fields in question?  It looks
as if, in the code in question, "offset" would be the offset of the
BER tag for the field; once you've called the appropriate code to
dissect the field - %(DEFAULT_BODY) might expand to the function body
that would have been there without #.FN_BODY, which might be
sufficient - "offset" will point past it, so you'd have the offset
and length of the entire BER-encoded field, and could, for example,
copy it with tvb_memcpy().

I did two earlier versions of the code that did something like that. One version used knowledge of what the tags are and recalculated the length based on the length of the tvb. The other one looked attempted to verify that the expected tag really was the expected number of bytes ahead of the data. Both versions seemed messy and complex to me.

If you need to wrap BER encodings for sequences, etc. around the
individual fields to make a canonicalized "composite" field, that
sounds as if you have to construct a tag in any case.

The BER encodings (with tag and length) are already part of the incoming data, so they wouldn't need to be constructed for any other purpose.

The more serious problem is that to enable filtering based on
crypto results (e.g. "c1222.crypto_good == true"), the code must
also work on packets that haven't yet been parsed.

Why is that the case?  "c1222.crypto_good" is part of the protocol
tree, and gets put there as part of the parsing process.  You can put
it into the protocol tree at any point in the parsing process,
including after all the other parsing has been done.

I don't know why that is, but it's what I observe. When I replace this if statement which is in the working code:

  if (PNODE_FINFO(tree)->hfinfo->id == hf_c1222_user_information)
    pkt_tree = proto_item_get_parent_nth(tree, 2);
  else
    pkt_tree = tree;

with this one:

  if (PNODE_FINFO(tree)->hfinfo->id == hf_c1222_user_information)
    pkt_tree = proto_item_get_parent_nth(tree, 2);
  else
    return FALSE;

The *displayed* values for parsed packets are all correct, but the *filter* does not work. That is, I get a blank screen (no packets selected) no matter what particular value I use in the filter. Maybe you can tell me why this is?

Ed