Skip to content

tcti: add pcap tcti#1817

Merged
tstruk merged 1 commit intotpm2-software:masterfrom
joholl:add_pcapng_tcti
Aug 5, 2020
Merged

tcti: add pcap tcti#1817
tstruk merged 1 commit intotpm2-software:masterfrom
joholl:add_pcapng_tcti

Conversation

@joholl
Copy link
Copy Markdown
Contributor

@joholl joholl commented Aug 2, 2020

Although wireshark features a neat TPM traffic dissector, there is no way to log+parse non-simulator TPM traffic. Additionally, to my knowledge, there is no alternative TPM traffic parser for Linux.

Add a TCTI module which prints TPM traffic to a file tpm2_log.pcap in pcap-ng format. Via the env. variableTCTI_PCAP_FILE, the output can be redirected to another path/stream (stdout, -, and stderr are valid values). If tpm2_log.pcap already exists, the logs are appended.

          +-----------+     +-----------+
SAPI ==>  | tcti-pcap | ==> | tcti-...  | ==> ...
          +-----------+     +-----------+
                ||
                \/
          tpm2_log.pcap

To use this TCTI, just prepend the TCTI name:conf string with "pcap", e.g.

"pcap:device:/dev/tpm0"

To inspect traffic in realtime with wireshark, it can be piped directly. Of course, in this example, the program must not output any additional information to stdout.

TCTI_PCAP_FILE=- tpm2_getrandom --tcti "pcap:device:/dev/tpm0" -o rand.bin 5 | wireshark -ki-

Copy link
Copy Markdown
Contributor

@tstruk tstruk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice to see that someone spent some time to work on some new debugging tools. We have this in our backlog for some time already. Thanks Johannes! In general this is great idea. I have added some questions and comments with regards to some implementation details.

configure.ac Outdated
[enable_tcti_pcap=yes])
AM_CONDITIONAL([ENABLE_TCTI_PCAP], [test "x$enable_tcti_pcap" != xno])
AS_IF([test "x$enable_tcti_pcap" = "xyes"],
AC_DEFINE([TCTI_PCAP],[1], [TCTI FOR DEBUGGING]))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see where is the TCTI_PCAP define used

Copy link
Copy Markdown
Contributor Author

@joholl joholl Aug 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not used. That's a copy-paste error, removing it.

#define PCAP_BLOCK_TYPE_EPB 0x00000006
#define PCAP_SHB_BYTE_ORDER_MAGIC 0x1A2B3C4D
#define PCAP_SHB_SECTION_LEN_NOT_SPECIFIED 0xFFFFFFFFFFFFFFFFUL
#define PCAP_IDB_LINKTYPE_ETHERNET 0x0001
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could set the link type to LINKTYPE_IPV4 (0xE4) and skip the whole Ethernet segment creation logic. The dissector only needs TCP (port number) and TPM2 segments.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I overlooked that. Switching to PCAP_IDB_LINKTYPE_IPv4 (0x00E4) and removing the ethernet frame. Now we have a IP packet wrapping a TCP segment wrapping a TPM request/response.

} else if (!strcmp (filename, "stderr")) {
ctx->fd = STDERR_FILENO;
} else {
ctx->fd = open (filename, O_WRONLY | O_APPEND | O_CREAT | O_NONBLOCK, 0644);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this append functionality gonna work?
I thought we can not just "append to file" because the original pcap header will have the same old snapshot length value and the interpreter, which will read the file won't see the new addition. I thought this new data needs to be "merged" in to the old file and the old pcap header updated, similarly to what the mergecap tool does (https://www.wireshark.org/docs/man-pages/mergecap.html)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file header is a Section Header Block (SHB) and an Interface Description Block (IDB). In the SHB, you can use a Section Length of -1 which means unspecified.

The standard:

If the Section Length is -1
(0xFFFFFFFFFFFFFFFF), this means that the size of the section is
not specified, and the only way to skip the section is to parse
the blocks that it contains.

And generally, multiple SHBs are allowed:

However, more than
one Section Header Block can be present in the capture file, each one
covering the data following it until the next one (or the end of
file).

Same for IDBs:

An Interface Description Block is valid only inside the section to
which it belongs.

So appending should (and does) work just fine.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I didn't know that.

return pdu_len;
}

static int pcap_write_ethernet_frame (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we set the PCAP link type to LINKTYPE_IPV4 this won't be needed. We can just do straight pcap_write_ip_packet()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. Removing this.

(uintptr_t)tctiContext, (uintptr_t)size, conf);
}

rc = Tss2_TctiLdr_Initialize (conf, &tcti_pcap->tcti_child);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The user will call, for instance, tpm2_getrandom -T "pcap:device:/dev/tpm0", which will cause the tcti loader to load libtss2-tcti-pcap.so and call Init() on it, passing the configuration string "pcap:device:/dev/tpm0", which again will cause the tcti loader to load
libtss2-tcti-pcap.so and call Init() on it, passing the configuration string "pcap:device:/dev/tpm0" and so on... Don't we need to parse the config here and skip the "pcap" prefix and only call Tss2_TctiLdr_Initialize() with conf = "device:/dev/tpm0"?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost. The string "pcap:device:/dev/tpm0" is name:conf, so the tcti loader will load the tcti-pcap library and pass its conf device:/dev/tpm0 to it.

The tcti-pcap calls then the tcti loader with device:/dev/tpm0 which loads tcti-device.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right. Looks good

Add a TCTI module which prints TPM commands and responses to a file
"tpm2_log.pcap" in pcap-ng format. By setting the TCTI_PCAP_FILE
environment variable, the output can be redirected to another path
("stdout"/"-" and "stderr" are valid values).

To use this TCTI, just prepend the TCTI name:conf string with "pcap",
    e.g. "pcap:device:/dev/tpm0"

To inspect traffic in realtime with wireshark, it can be piped directly.
Of course, in this example, the program must not output any additional
information to stdout.
     e.g. TCTI_PCAP_FILE=- ./program | wireshark -ki-

Signed-off-by: Johannes Holland <joh.ho@gmx.de>
@codecov
Copy link
Copy Markdown

codecov bot commented Aug 4, 2020

Codecov Report

Merging #1817 into master will increase coverage by 0.04%.
The diff coverage is 88.14%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1817      +/-   ##
==========================================
+ Coverage   83.92%   83.97%   +0.04%     
==========================================
  Files         337      339       +2     
  Lines       38987    39257     +270     
==========================================
+ Hits        32720    32966     +246     
- Misses       6267     6291      +24     
Impacted Files Coverage Δ
src/tss2-tcti/tcti-pcap-builder.c 87.16% <87.16%> (ø)
src/tss2-tcti/tcti-pcap.c 89.34% <89.34%> (ø)
src/util/io.c 89.02% <0.00%> (+2.43%) ⬆️
src/tss2-tcti/tcti-common.c 67.64% <0.00%> (+8.82%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2cd03ab...4329839. Read the comment docs.

Copy link
Copy Markdown
Contributor

@tstruk tstruk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Thanks

(uintptr_t)tctiContext, (uintptr_t)size, conf);
}

rc = Tss2_TctiLdr_Initialize (conf, &tcti_pcap->tcti_child);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are right. Looks good

} else if (!strcmp (filename, "stderr")) {
ctx->fd = STDERR_FILENO;
} else {
ctx->fd = open (filename, O_WRONLY | O_APPEND | O_CREAT | O_NONBLOCK, 0644);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I didn't know that.

@tstruk
Copy link
Copy Markdown
Contributor

tstruk commented Aug 5, 2020

Would be good to enable some of the CI to go through pcap and see what it produces. I will play with it a bit and see what we can do. Also I wonder how the partial read captures will look in wireshark.

@tstruk tstruk merged commit 1361aa3 into tpm2-software:master Aug 5, 2020
@joholl
Copy link
Copy Markdown
Contributor Author

joholl commented Aug 5, 2020

Spoiler alert:

With partial read, you will not see any difference. The first read (for the response size) is not logged. only the second complete receive call is logged (similar to what is implemented with the LOGBLOB_DEBUG function). Wireshark would probably not be able to dissect partial reads anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants