Skip to content

Comments

Remove a spurious TLSProxy byte in TLSv1.3#5370

Closed
mattcaswell wants to merge 1 commit intoopenssl:masterfrom
mattcaswell:remove-spurious-tlsproxy-byte
Closed

Remove a spurious TLSProxy byte in TLSv1.3#5370
mattcaswell wants to merge 1 commit intoopenssl:masterfrom
mattcaswell:remove-spurious-tlsproxy-byte

Conversation

@mattcaswell
Copy link
Member

When the proxy re-encrypted a TLSv1.3 record it was adding a spurious
byte onto the end. This commit removes that.

The "extra" byte was intended to be the inner content type of the record.
However, TLSProxy was actually adding the original encrypted data into the
record (which already has the inner content type in it) and then adding
the spurious additional content type byte on the end (and adjusting the
record length accordingly).

It is interesting to look at why this didn't cause a failure:

The receiving peer first attempts to decrypt the data. Because this is
TLSProxy we always use a GCM based ciphersuite with a 16 byte tag. When
we decrypt this it actually gets diverted to the ossltest engine. All this
does is go through the motions of encrypting/decrypting but just passes
back the original data. Crucially it will never fail because of a bad tag!
The receiving party thinks the spurious additional byte is part of the
tag and the ossltest engine ignores it.

This means the data that gets passed back to the record layer still has
an additional spurious byte on it - but because the 16 byte tag has been
removed, this is actually the first byte of the original tag. Again
because we are using ossltest engine we aren't actually creating "real"
tags - we only ever emit 16, 0 bytes for the tag. So the spurious
additional byte always has the value 0. The TLSv1.3 spec says that records
can have additional 0 bytes on the end of them - this is "padding". So the
record layer interprets this 0 byte as padding and strips it off to end up
with the originally transmitted record data - which it can now process
successfully.

Checklist
  • documentation is added or updated
  • tests are added or updated

@mattcaswell
Copy link
Member Author

I found this based on a comment by @bernd-edlinger in #5067. It was a real case of "how did this ever work" for a while!

@dot-asm
Copy link
Contributor

dot-asm commented Feb 19, 2018

Could you double-check appveryor log and confirm that failure is unrelated.

@bernd-edlinger
Copy link
Member

@levitte I think this looks like we received a fragmented packet here:

[00:07:29] Received server packet
[00:07:29] Packet length = 1167
[00:07:29] Processing flight 2
[00:07:29]  Record 1 (server -> client)
[00:07:29] Use of uninitialized value within %record_type in concatenation (.) or string at C:\projects\openssl\util\perl/TLSProxy/Record.pm line 89.
[00:07:29]   Content type: 
[00:07:29] Use of uninitialized value within %tls_version in concatenation (.) or string at C:\projects\openssl\util\perl/TLSProxy/Record.pm line 90.
[00:07:29]   Version: 
[00:07:29]   Length: 1698 (expected), 1162 (actual)
[00:07:29] 
[00:07:29] Forwarded packet length = 1167

@bernd-edlinger
Copy link
Member

I am pretty sure the test failure is unrelated.
@mattcaswell could you do a re-base to force a new run of the appveyor?

When the proxy re-encrypted a TLSv1.3 record it was adding a spurious
byte onto the end. This commit removes that.

The "extra" byte was intended to be the inner content type of the record.
However, TLSProxy was actually adding the original encrypted data into the
record (which already has the inner content type in it) and then adding
the spurious additional content type byte on the end (and adjusting the
record length accordingly).

It is interesting to look at why this didn't cause a failure:

The receiving peer first attempts to decrypt the data. Because this is
TLSProxy we always use a GCM based ciphersuite with a 16 byte tag. When
we decrypt this it actually gets diverted to the ossltest engine. All this
does is go through the motions of encrypting/decrypting but just passes
back the original data. Crucially it will never fail because of a bad tag!
The receiving party thinks the spurious additional byte is part of the
tag and the ossltest engine ignores it.

This means the data that gets passed back to the record layer still has
an additional spurious byte on it - but because the 16 byte tag has been
removed, this is actually the first byte of the original tag. Again
because we are using ossltest engine we aren't actually creating "real"
tags - we only ever emit 16, 0 bytes for the tag. So the spurious
additional byte always has the value 0. The TLSv1.3 spec says that records
can have additional 0 bytes on the end of them - this is "padding". So the
record layer interprets this 0 byte as padding and strips it off to end up
with the originally transmitted record data - which it can now process
successfully.
@mattcaswell mattcaswell force-pushed the remove-spurious-tlsproxy-byte branch from a4fd6ba to 85d1b19 Compare February 20, 2018 14:23
@mattcaswell
Copy link
Member Author

Rebased as requested.

@mattcaswell
Copy link
Member Author

Pushed. Thanks.

levitte pushed a commit that referenced this pull request Feb 21, 2018
When the proxy re-encrypted a TLSv1.3 record it was adding a spurious
byte onto the end. This commit removes that.

The "extra" byte was intended to be the inner content type of the record.
However, TLSProxy was actually adding the original encrypted data into the
record (which already has the inner content type in it) and then adding
the spurious additional content type byte on the end (and adjusting the
record length accordingly).

It is interesting to look at why this didn't cause a failure:

The receiving peer first attempts to decrypt the data. Because this is
TLSProxy we always use a GCM based ciphersuite with a 16 byte tag. When
we decrypt this it actually gets diverted to the ossltest engine. All this
does is go through the motions of encrypting/decrypting but just passes
back the original data. Crucially it will never fail because of a bad tag!
The receiving party thinks the spurious additional byte is part of the
tag and the ossltest engine ignores it.

This means the data that gets passed back to the record layer still has
an additional spurious byte on it - but because the 16 byte tag has been
removed, this is actually the first byte of the original tag. Again
because we are using ossltest engine we aren't actually creating "real"
tags - we only ever emit 16, 0 bytes for the tag. So the spurious
additional byte always has the value 0. The TLSv1.3 spec says that records
can have additional 0 bytes on the end of them - this is "padding". So the
record layer interprets this 0 byte as padding and strips it off to end up
with the originally transmitted record data - which it can now process
successfully.

Reviewed-by: Bernd Edlinger <[email protected]>
(Merged from #5370)
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.

3 participants