diff --git a/draft-ietf-tls-rfc8446bis.md b/draft-ietf-tls-rfc8446bis.md index 13c3d331..ac4807c5 100644 --- a/draft-ietf-tls-rfc8446bis.md +++ b/draft-ietf-tls-rfc8446bis.md @@ -1283,13 +1283,57 @@ processed and transmitted as specified by the current active connection state. } Handshake; Protocol messages MUST be sent in the order defined in -{{the-transcript-hash}} and shown in the diagrams in {{protocol-overview}}. +{{the-transcript-hash}} and shown in the diagrams in {{protocol-overview}}, +unless modified by a TLS extension. A peer which receives a handshake message in an unexpected order MUST abort the handshake with an "unexpected_message" alert. New handshake message types are assigned by IANA as described in {{iana-considerations}}. +## 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 (bytes) */ + 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}}). + +When a range of messages is specified with "...", the transcript hash +is taken from the sequence of handshake messages that were sent or received +during the main handshake, starting and ending at the specified messages. +In this document, it is taken from the following sequence of handshake +messages: ClientHello, HelloRetryRequest, ClientHello, ServerHello, +EncryptedExtensions, server CertificateRequest, server Certificate, +server CertificateVerify, server Finished, EndOfEarlyData, client +Certificate, client CertificateVerify, and client Finished. TLS extensions may +add or remove messages, in which case the transcript hash will reflect the +modified sequence. + +In general, implementations can implement the transcript by keeping a +running transcript hash value based on the negotiated hash. Note, +however, that subsequent post-handshake authentications do not include +each other, just the messages through the end of the main handshake, and the +messages contained in that particular post-handshake authentication. +(See {{certificate-verify}} and {{finished}}.) ## Key Exchange Messages @@ -2932,17 +2976,7 @@ sent under certain circumstances, as defined below. The Finished message is always sent as part of the Authentication Block. These messages are encrypted under keys derived from the \[sender]_handshake_traffic_secret, -except for post-handshake authentication. - -The computations for the Authentication messages all uniformly -take the following inputs: - -- The certificate and signing key to be used. -- A Handshake Context consisting of the list 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: +except for post-handshake authentication: Certificate : The certificate to be used for authentication, and any @@ -2951,62 +2985,11 @@ Certificate (including 0-RTT). CertificateVerify: -: A signature over the value Transcript-Hash(Handshake Context, Certificate) +: A signature over the transcript hash up to this point. Finished: -: A MAC over the value Transcript-Hash(Handshake Context, Certificate, CertificateVerify) +: A MAC over the transcript hash up to this point, using a MAC key derived from the Base Key. -{:br} - - -The following table defines the Handshake Context and MAC Base Key -for each scenario: - -| Mode | Handshake Context | Base Key | -|------|-------------------|----------| -| Server | ClientHello ... later of EncryptedExtensions/CertificateRequest | server_handshake_traffic_secret | -| Client | ClientHello ... later of server Finished/EndOfEarlyData | client_handshake_traffic_secret | -| Post-Handshake | ClientHello ... client Finished + CertificateRequest | [sender]_application_traffic_secret_N | -{: #hs-ctx-and-keys title="Authentication Inputs"} - -### 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 (bytes) */ - 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}}). - -For concreteness, the transcript hash is always taken from the -following sequence of handshake messages, starting at the first -ClientHello and including only those messages that were sent: -ClientHello, HelloRetryRequest, ClientHello, ServerHello, -EncryptedExtensions, server CertificateRequest, server Certificate, -server CertificateVerify, server Finished, EndOfEarlyData, client -Certificate, client CertificateVerify, and client Finished. - -In general, implementations can implement the transcript by keeping a -running transcript hash value based on the negotiated hash. Note, -however, that subsequent post-handshake authentications do not include -each other, just the messages through the end of the main handshake. ### Certificate @@ -3246,11 +3229,25 @@ Structure of this message: The algorithm field specifies the signature algorithm used (see {{signature-algorithms}} for the definition of this type). The -signature is a digital signature using that algorithm. The -content that is covered under the signature is the hash output as described in -{{the-transcript-hash}}, namely: +signature is a digital signature using that algorithm. + +During the handshake, the content that is covered under the signature is +the hash output as described in {{the-transcript-hash}}, ending at the +message immediately preceding CertificateVerify. In this document, the +preceding message is always a Certificate: + + Transcript-Hash(ClientHello...Certificate) + +During post-handshake authentication ({{post-handshake-authentication}}), the +transcript instead contains only the messages in the main handshake, followed by +the messages in this particular post-handshake authentication exchange. Other +post-handshake messages are not included: - Transcript-Hash(Handshake Context, Certificate) + Transcript-Hash(ClientHello...server Finished, + CertificateRequest, Certificate) + +If a TLS extension modifies the messages used in post-handshake authentication, +those modifications are reflected in this transcript hash. The digital signature is then computed over the concatenation of: @@ -3342,15 +3339,23 @@ receiving the peer's Finished: of either the peer's identity or its liveness (i.e., the ClientHello might have been replayed). -The key used to compute the Finished message is computed from the -Base Key defined in {{authentication-messages}} using HKDF (see -{{key-schedule}}). Specifically: +The key used to compute the Finished message is computed from a Base Key +using HKDF (see {{key-schedule}}) as follows: ~~~ finished_key = HKDF-Expand-Label(BaseKey, "finished", "", Hash.length) ~~~ +The following table defines the Base Key for each scenario: + +| Mode | Base Key | +|----------------|---------------------------------------| +| Server | server_handshake_traffic_secret | +| Client | client_handshake_traffic_secret | +| Post-Handshake | [sender]_application_traffic_secret_N | +{: #hs-finished-base-keys title="Base Keys for the Finished Message"} + Structure of this message: %%% Authentication Messages @@ -3360,18 +3365,41 @@ Structure of this message: } Finished; -The verify_data value is computed as follows: +During the handshake, the verify_data value is computed using the +transcript hash (see {{the-transcript-hash}}), ending at the message +immediately preceding this Finished message: + + verify_data = + HMAC(finished_key, Transcript-Hash(ClientHello...Previous)) + +In this document, the transcript hash will end at: + +* For server Finished, Previous will be EncryptedExtensions, server + CertificateRequest, server Certificate, or server CertificateVerify, + depending on which is present and comes last. + +* For client Finished, Previous will be server Finished, EndofEarlyData, + client Certificate, or client CertificateVerify, depending on which is + present and comes last. + +If the message sequence is modified by a TLS extension, the transcript +may end at a different message. + +During post-handshake authentication ({{post-handshake-authentication}}), the +transcript instead contains only the messages in the main handshake, followed by +the messages in this particular post-handshake authentication exchange. Other +post-handshake messages are not included: verify_data = HMAC(finished_key, - Transcript-Hash(Handshake Context, - Certificate*, CertificateVerify*)) + Transcript-Hash(ClientHello...server Finished, + CertificateRequest, Certificate, + CertificateVerify)) - * Only included if present. +If a TLS extension modifies the messages used in post-handshake authentication, +those modifications are reflected in this transcript hash. -HMAC {{RFC2104}} uses the Hash algorithm for the handshake. -As noted above, the HMAC input can generally be implemented by a running -hash, i.e., just the handshake hash at this point. +In both cases, HMAC {{RFC2104}} uses the Hash algorithm for the handshake. In previous versions of TLS, the verify_data was always 12 octets long. In TLS 1.3, it is the size of the HMAC output for the Hash used for the handshake.