Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clarify that trailing data in extensions is forbidden. #1220

Merged
merged 2 commits into from Oct 25, 2021

Conversation

davidben
Copy link
Contributor

This was already a compliance requirement, but spell it out more explicitly.

Closes #1219.

This was already a compliance requirement, but spell it out more
explicitly.

Closes tlswg#1219.
@martinduke
Copy link

LGTM

Copy link
Contributor

@martinthomson martinthomson left a comment

Choose a reason for hiding this comment

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

Why is this specific to extension_data? Why not require this for every length-prefixed construct that contains fields that might not extend to the full length?

@kaduk
Copy link
Contributor

kaduk commented Feb 25, 2021

Why is this specific to extension_data? Why not require this for every length-prefixed construct that contains fields that might not extend to the full length?

AFAICT it isn't.

https://tools.ietf.org/html/draft-ietf-quic-http-34#section-10.8 also comes to mind

@martinduke
Copy link

@martinthomson Good catch.

@davidben
Copy link
Contributor Author

Why is this specific to extension_data? Why not require this for every length-prefixed construct that contains fields that might not extend to the full length?

It's already required. Length prefixes typically come from the T field<floor..ceiling> syntax in the presentation language. Not only would a parser that allows trailing data be non-compliant, but it'd be totally incoherent. Vectors don't tell you the number of elements, so the only way to parse it is to loop until empty, peeling off Ts. That means, if there is any trailing data, it'll be immediately interpreted as another instance of T, not trailing data.

Whereas extension_data is a little different because it's an opaque extension_data<0..2^16-1> byte string whose contents happen to be another structure. TBH, I don't think this case needed a clarification either (it's pretty obvious, IMO), but a clarification doesn't hurt so whatever.

@martinthomson
Copy link
Contributor

@davidben, I think that you are right when it comes to lists of things. I was thinking about structs in general. However, in QUIC, we have transport parameters, which would share the need for this exact treatment; that we decided to manage that within QUIC rather than use the TLS grammar means that we don't need to worry about it, but it suggests that nested extension points will hit this problem too.

I was trying to find other such instances, but I can't find any offhand. I was looking at server_name, and that uses a switch statement, which suggests that it is simply impossible to include a non-zero type value (another reason that server name extension is irredeemably busted; and of course, that's not how NSS implements it; from memory, we assume every type has a 1 byte length prefix...).

I thought that handshake messages might need this, but the grammar seems to prevent that in the same way as server_name. An unknown handshake message hits a switch statement and falls out, presumably into an error condition. So even though the format might allow an unknown handshake message to be ignored the grammar suggests that it is always an error (which, to be clear, is a good thing from a protocol perspective).

The encapsulation of handshake messages in records is another place that is interesting. In TLS, that doesn't matter much because the extra bytes roll over and we are back in your "next instance of T" case, but it is a problem in DTLS where each record needs to contain discrete fragments.

So I do think that it would be better to have this be a general statement, even if it there is precisely one instance where we know it definitely applies.

otherwise specified, trailing data is forbidden. That is, senders MUST NOT
include data after the structure in the "extension_data" field, and receivers
MUST abort the handshake with a "decode_error" alert if there is data left
over after parsing the structure.
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please clarify this so that it is clear that if the receiver doesn't parse the extension data, then it doesn't have to check it? The way it is worded now seems to imply that receivers must parse every extension every time, just to comply with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough. Does the new text work?

@tomato42
Copy link
Contributor

the only place where trailing data is allowed is after ClientHello for implementations that don't support extensions

@briansmith
Copy link
Contributor

It's already required. Length prefixes typically come from the T field<floor..ceiling> syntax in the presentation language. Not only would a parser that allows trailing data be non-compliant, but it'd be totally incoherent. Vectors don't tell you the number of elements, so the only way to parse it is to loop until empty, peeling off Ts. That means, if there is any trailing data, it'll be immediately interpreted as another instance of T, not trailing data.

A receiver will not necessarily parse every entry in the vector, if it finds what it's looking for before it gets through the whole vector.

@davidben
Copy link
Contributor Author

So I do think that it would be better to have this be a general statement, even if it there is precisely one instance where we know it definitely applies.

Hmm. Where were you envisioning putting this generally? The definition of various length prefixes are kind of scattered all over the place.

@martinthomson
Copy link
Contributor

Section 3.9?

@ekr ekr merged commit 2cb5b55 into tlswg:main Oct 25, 2021
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.

Self-encoded lengths that don't match
7 participants