Stuffer Debug Option to print bytes Read/Written by s2n
Idea I had to make debugging s2n easier.
Phase 1:
Require users to pass in the name of the value that they are reading/writing from a stuffer.
As an example, we could change code from:
GUARD(s2n_stuffer_write_uint8(out, session_id_len));
to
GUARD(s2n_stuffer_write_uint8(out, "Session ID Length", session_id_len));
Phase 2:
Add a new s2n_connection_enable_debug and s2n_stuffer_enable_debug API's. Each conn/stuffer would pointer to a debug output stuffer, and would write out the actions being taken on the parent stuffer.
Example: s2n_connection_enable_debug(conn, flags, stderr); or s2n_connection_enable_debug(conn, flags, debug_stuffer);
This would allow the parent stuffer to automatically generate output similar to what I did manually wrote in this comment: https://github.com/aws/s2n-tls/issues/418#issuecomment-286600640
Use Cases
This type of debug option can have several different uses:
- Be able to add a single line to a unit/integration test if you want to debug a test
- Make it easier to generate Corpus Inputs for Fuzz Tests by enabling this flag and running Unit/Integration Tests
- Can be used by Unit/Integration Tests to verify that expected state transitions occur and that unexpected state transitions did not occur
I had an idea about this last night, it's more complex and requires more work, but I think it may be worth it.
The easy way to go about this is to add a little bit more logic to s2n_handshake_io.c that will print state machine transitions and a hexdump of all bytes received/sent for each state in the state machine, and while that may be good enough for some cases, it still leaves developers flipping back and forth to the RFC to see what TLS parameters are sent, in which order, which bytes mean what, and will be hard for newcomers to use. It would likely look something along the lines of:
Client Hello Send:
0x3, 0x3, 0x58, 0xc8, 0x7e, 0x1b, 0x31, 0xa4, 0xa5, 0xb3, 0x6d, 0x49, 0x48, 0x4a, 0xac, 0xba, 0x5, 0x8a, 0xdb, 0x81, 0x37, 0xfe, 0xb5, 0xc2, 0x74, 0x11, 0x61, 0xae, 0x9e, 0x21, 0xb0, 0x93, 0x33, 0x65, 0x0, 0x0, 0x10, 0xc0, 0x2f, 0xc0, 0x30, 0xc0, 0x13, 0xc0, 0x27, 0xc0, 0x14, 0x0, 0x9c,0x0, 0x3c, 0x0, 0x2f, 0x1, 0x0, 0x0, 0x36, 0x0, 0x0, 0x0, 0x13, 0x0, 0x11, 0x0, 0x0, 0xe, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x0, 0x10, 0x0, 0xb, 0x0, 0x9, 0x8, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x0, 0xa, 0x0, 0x6, 0x0, 0x4, 0x0, 0x17, 0x0, 0x18, 0x0, 0xb, 0x0, 0x2, 0x1, 0x0
This is better than what we have now, but still hard to use for debugging. The idea I had was to instead add logic at the point of use where the data is read/written when using the s2n_stuffer API's.
Eg If we added new s2n_stuffer API's that allowed strings to be passed in, we could change code from:
GUARD(s2n_stuffer_write_uint8(out, session_id_len));
to
GUARD(s2n_stuffer_write_uint8(out, "Session Id Length", session_id_len));
Then we could have logic within s2n_stuffer that checks a debug flag, and writes to a 2nd debug-only stuffer if debugging is enabled that would be pretty printed and be pretty close to what I manually edited and put in this comment: https://github.com/awslabs/s2n/issues/418#issuecomment-286600640
This would require a lot more code changes to the code base, but I think this has the side effect of improving the readability and documentation where we are already using stuffers.
Wow, annotating via the stuffer is an incredibly good idea. It makes me excited to write say a TCP/IP parser using the stuffer. It would be so much easier to work with.