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

Special-case the hash for CH1 when HRR is used. This allows the #901

Merged
merged 2 commits into from
Mar 9, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 53 additions & 24 deletions draft-ietf-tls-tls13.md
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,7 @@ processed and transmitted as specified by the current active connection state.
client_key_exchange_RESERVED(16),
finished(20),
key_update(24),
message_hash(254),
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there an IANA section that needs updating?

(255)
} HandshakeType;

Expand Down Expand Up @@ -1986,8 +1987,8 @@ Cookies serve two primary purposes:

- Allowing the server to offload state to the client, thus allowing it to send
a HelloRetryRequest without storing any state. The server does this by
storing the serialized hash state in the cookie (protected
with some suitable integrity algorithm).
storing the hash of the ClientHello in the HelloRetryRequest cookie
(protected with some suitable integrity algorithm).

When sending a HelloRetryRequest, the server MAY provide a "cookie" extension to the
client (this is an exception to the usual rule that the only extensions that
Expand Down Expand Up @@ -2621,7 +2622,7 @@ The PSK binder value forms a binding between a PSK and the current
handshake, as well as between the handshake in which the PSK was
generated (if via a NewSessionTicket message) and the handshake where
it was used. Each entry in the binders list is computed as an HMAC
over the portion of the ClientHello (including the handshake header)
over a transcript hash (see {{the-transcript-hash}}) containing a partial ClientHello
up to and including the PreSharedKeyExtension.identities field. That
is, it includes all of the ClientHello but not the binders list
itself. The length fields for the message (including the overall
Expand All @@ -2639,14 +2640,19 @@ and HelloRetryRequest are included in the transcript along with the
new ClientHello. For instance, if the client sends ClientHello1, its
binder will be computed over:

ClientHello1[truncated]
Transcript-Hash(ClientHello1[truncated])
Copy link
Contributor

Choose a reason for hiding this comment

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

You need to explicitly call out that because this is a partial ClientHello1, it doesn't need to be turned into the special message_hash form.


If the server responds with HelloRetryRequest, and the client then sends
ClientHello2, its binder will be computed over:

ClientHello1 + HelloRetryRequest + ClientHello2[truncated]
Transcript-Hash(ClientHello1,
HelloRetryRequest,
ClientHello2[truncated])

The full ClientHello is included in all other handshake hash computations.
Note that in the first flight, ClientHello1[truncated] is hashed directly,
but in the second flight, it is hashed and then reinjected as a
"handshake_hash" message, as described in {{the-transcript-hash}}.

#### Processing Order

Expand Down Expand Up @@ -2855,7 +2861,8 @@ The computations for the Authentication messages all uniformly
take the following inputs:

- The certificate and signing key to be used.
- A Handshake Context based on the transcript of the handshake messages
- A Handshake Context consisting of the set of messages to be
included in the transcript hash.
- A base key to be used to compute a MAC key.

Based on these inputs, the messages then contain:
Expand All @@ -2866,19 +2873,13 @@ supporting certificates in the chain. Note that certificate-based
client authentication is not available in the 0-RTT case.

CertificateVerify
: A signature over the value Hash(Handshake Context + Certificate)
: A signature over the value Transcript-Hash(Handshake Context, Certificate)

Finished
: A MAC over the value Hash(Handshake Context + Certificate + CertificateVerify)
: A MAC over the value Transcript-Hash(Handshake Context, Certificate, CertificateVerify)
using a MAC key derived from the base key.
{:br}

Because the CertificateVerify signs the Handshake Context +
Certificate and the Finished MACs the Handshake Context + Certificate
+ CertificateVerify, this is mostly equivalent to keeping a running hash
of the handshake messages (exactly so in the pure 1-RTT cases). Note,
however, that subsequent post-handshake authentications do not include
each other, just the messages through the end of the main handshake.

The following table defines the Handshake Context and MAC Base Key
for each scenario:
Expand All @@ -2889,9 +2890,37 @@ for each scenario:
| Client | ClientHello ... ServerFinished | client_handshake_traffic_secret |
| Post-Handshake | ClientHello ... ClientFinished + CertificateRequest | client_traffic_secret_N |

In all cases, the handshake context is formed by concatenating the
indicated handshake messages, including the handshake message type
and length fields, but not including record layer headers.

### The Transcript Hash

Many of the cryptographic computations in TLS make use of a transcript
hash. This value is computed by hashing the concatenation of
each included handshake message, including the handshake
message header carrying the handshake message type and length fields,
but not including record layer headers. I.e.,

Transcript-Hash(M1, M2, ... MN) = Hash(M1 || M2 ... MN)

As an exception to this general rule, when the server responds to a
ClientHello with a HelloRetryRequest, the value of ClientHello1 is
replaced with a special synthetic handshake message of handshake
type "message_hash" containing Hash(ClientHello1). I.e.,

Transcript-Hash(ClientHello1, HelloRetryRequest, ... MN) =
Hash(message_hash || // Handshake Type
00 00 Hash.length || // Handshake message length
Hash(ClientHello1) || // Hash of ClientHello1
HelloRetryRequest ... MN)

The reason for this construction is to allow the server to do a
stateless HelloRetryRequest by storing just the hash of ClientHello1
in the cookie, rather than requiring it to export the entire intermediate
hash state (see {{cookie}}).

In general, implementations can implement the transcript by keeping a
running transcript hash value based on the negotiated hash. Note,
Copy link
Contributor

Choose a reason for hiding this comment

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

[This is not entirely true for the client due to the PSK binder issue, but we can defer that.]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"in general" covers a lot of sins

however, that subsequent post-handshake authentications do not include
each other, just the messages through the end of the main handshake.

### Certificate

Expand Down Expand Up @@ -3111,7 +3140,7 @@ signature is a digital signature using that algorithm. The content
to be signed is the hash output as described in
{{authentication-messages}} namely:

Hash(Handshake Context + Certificate)
Transcript-Hash(Handshake Context, Certificate)

The digital signature is then computed over the concatenation of:

Expand All @@ -3132,7 +3161,7 @@ and for a client signature is "TLS 1.3, client
CertificateVerify". It is used to provide separation between signatures
made in different contexts, helping against potential cross-protocol attacks.

For example, if Hash(Handshake Context + Certificate) was 32 bytes of
For example, if the transcript hash was 32 bytes of
01 (this length would make sense for SHA-256), the content covered by
the digital signature for a server CertificateVerify would be:

Expand Down Expand Up @@ -3227,9 +3256,9 @@ Structure of this message:
The verify_data value is computed as follows:

verify_data =
HMAC(finished_key, Hash(Handshake Context +
Certificate* +
CertificateVerify*))
HMAC(finished_key,
Transcript-Hash(Handshake Context,
Certificate*, CertificateVerify*))

* Only included if present.

Expand Down Expand Up @@ -4045,7 +4074,7 @@ defined below:

Derive-Secret(Secret, Label, Messages) =
HKDF-Expand-Label(Secret, Label,
Hash(Messages), Hash.length)
Transcript-Hash(Messages), Hash.length)
~~~~

The Hash function and the HKDF hash are the cipher suite hash algorithm.
Expand Down Expand Up @@ -4381,7 +4410,7 @@ and their allocation policies are below:
Standards Action {{RFC5226}}. IANA \[SHALL update/has updated] this registry
to rename item 4 from "NewSessionTicket" to "new_session_ticket"
and to add the "hello_retry_request", "encrypted_extensions",
"end_of_early_data", and "key_update" values.
"end_of_early_data", "key_update", and "handshake_hash" values.

This document also uses a registry originally created in {{RFC4366}}. IANA has
updated it to reference this document. The registry and its allocation policy
Expand Down