Merge client and server key shares into a single extension.  draft-09 Change to RSA-PSS signatures for handshake messages.

Starts in this thread: URL spt
It's the nonce after all. On Monday, October 19, 2015, Martin Thomson wrote: I don't believe that there's any reason to include the sequence number in the AD input of an AEAD. I think that an empty AD for TLS would be fine now that the content type is encrypted. (Not that I deeply care either way.) Cheers AGL Adam Langley EMAIL URL

Merge client and server key shares into a single extension. <ins> Remove sequence number and version from additional_data, which is now empty. </ins> draft-09 Change to RSA-PSS signatures for handshake messages.


The digest used in the mask generation function MUST be the same as the digest which is being signed (i.e., what appears in algorithm.signature).  The length of the salt MUST be equal to the <del> octet length of the digest output.  Note that previous versions of TLS used RSASSA-PKCS1-v1_5, not RSASSA-PSS. </del>  All ECDSA computations MUST be performed according to ANSI X9.62 X962 or its successors.  Data to be signed/verified is hashed, and the

This addresses Brian's comment from . We don't use "octet length" anywhere else in the document.

The digest used in the mask generation function MUST be the same as the digest which is being signed (i.e., what appears in algorithm.signature).  The length of the salt MUST be equal to the  <ins> length of the digest output.  Note that previous versions of TLS used RSASSA-PKCS1-v1_5, not RSASSA-PSS. </ins> All ECDSA computations MUST be performed according to ANSI X9.62 X962 or its successors.  Data to be signed/verified is hashed, and the


zero-rtt-exchange) it also authenticates the handshake using the the Static Secret. [server-finished] <del> Upon receiving the server's messages, the client responds with his </del>  final flight of messages:

The spec always uses the gender-neutral possessive pronoun "its" for "client", so I think we should definitely fix that occurrence. Also, it seems that throughout the document we try to not use gender-specific pronouns for "attacker". I'm not sure about "their" though, as it looks like we usually try to avoid that by restructuring sentences, but I may be mistaken. We could also refer to multiple attackers?
In technical writing, we should generally use "they" and "their" everywhere when (potentially) referring to a person or persons. ("it" is best for denoting clients/servers) The word "they" gives both gender & quantity neutral language; no assumptions. (this use is older than Shakespeare; it's just underused)

zero-rtt-exchange) it also authenticates the handshake using the the Static Secret. [server-finished]  <ins> Upon receiving the server's messages, the client responds with its </ins> final flight of messages:


between the ServerHello and the EncryptedExtensions encrypted- extensions message.  The ServerHello MUST only include extensions which are required to establish the cryptographic context. <del> Currently the only such extensions are "key_share" and "pre_shared_key".  Clients MUST check the ServerHello for the presence of any forbidden extensions and if any are found MUST terminate the handshake with a "illegal_parameter" alert. </del>  6.3.1.3.

The early_data extension should be listed as one of the few that can't go into EncryptedExtensions but must be sent with ServerHello.

between the ServerHello and the EncryptedExtensions encrypted- extensions message.  The ServerHello MUST only include extensions which are required to establish the cryptographic context.  <ins> Currently the only such extensions are "key_share", "pre_shared_key", and "early_data".  Clients MUST check the ServerHello for the presence of any forbidden extensions and if any are found MUST terminate the handshake with a "illegal_parameter" alert. </ins> 6.3.1.3.


MUST NOT offer any KeyShareEntry values for groups not listed in the client's "supported_groups" extension.  Servers MUST NOT offer a KeyShareEntry value for a group not offered by the client in its <del> corresponding KeyShare. </del>  If no mutually supported group is available between the two endpoints' KeyShare offers, yet there is a mutually supported group

The current text is a mix of omitting and sending empty, as pointed out by Ilari on the mailing list. This fixes things and switches to an always-send model.
This looks good to me modulo the issue noted above
NAME Ok, I've pushed a second commit here which clarifies that point and also reconciles the fact that the two extensions here both claim to determine group priority. Suggestions to reduce verbosity without reducing clarity would be appreciated. (this commit fixes issue )
Typo fixed & rebased.
Since the list is in favor of "forward secrecy" over "forward security", I've changed my use of the term in this PR to the former (a commit just landed to change the existing uses elsewhere). Not rebased again; still merges cleanly (for the moment, at least).

MUST NOT offer any KeyShareEntry values for groups not listed in the client's "supported_groups" extension.  Servers MUST NOT offer a KeyShareEntry value for a group not offered by the client in its  <ins> corresponding KeyShare.  Implementations receiving any KeyShare containing any of these prohibited values MUST abort the connection with a fatal "illegal_parameter" alert. </ins> If no mutually supported group is available between the two endpoints' KeyShare offers, yet there is a mutually supported group


server_key_exchange_RESERVED(12), certificate_request(13), server_hello_done_RESERVED(14), certificate_verify(15), client_key_exchange_RESERVED(16), server_configuration(17), <del> finished(20), (255) } HandshakeType; </del>  The TLS Handshake Protocol messages are presented below in the order they MUST be sent; sending handshake messages in an unexpected order to receive an arbitrary number of such messages before receiving the Authentication messages.  7. In order to begin connection protection, the TLS Record Protocol the underlying hash function for HKDF RFC5869.  SS and ES denote the sources from the table above. <del> The traffic keys are computed from xSS, xES, and the master_secret as described in traffic-key-calculation below. </del>  Note: although the steps above are phrased as individual HKDF-Extract and HKDF-Expand operations, because each HKDF-Expand operation is 7.2.  The traffic keying material is generated from the following input values: The following table indicates the purpose values for each type of key: <del> 7.2.1. </del>  The handshake hash is defined as the hash of all handshake messages sent or received, starting at ClientHello up to the present time, hash" because it contains all the handshake messages involved in establishing the session, up to and including the client's Finished. <del> 7.2.2. </del>  A conventional Diffie-Hellman computation is performed.  The negotiated key (Z) is used as the shared secret, and is used in the key schedule as specified above.  Leading bytes of Z that contain all zero bits are stripped before it is used as the input to HKDF. <del> 7.2.3. </del>  For secp256r1, secp384r1 and secp521r1, ECDH calculations (including parameter and key generation as well as the shared secret

Is good.
The counter has a size of (2^64-1).The records are max (2^14 + 2048). So, my bold calculation would come to (2^64-1) / (2^14 + 2048) / 2^40 = 910.22 TiB of data. In Big Data, video streaming and other mass data cases 910TB data can be a limitation. I would like to propose the counter to go to 2^128-1, which would result in a connection that can reach (2^128-1) / (2^14 + 2048) / 2^80 = 1.52 * 10^10 YiB. If byte preservation is an issue, I'm willing to accept 2^96-1 as the counter max, resulting in (2^96-1) / (2^14 + 2048) / 2^80 = 3.55 YiB as maximum connection.
On a 40Gibit line this will take less time than one might expect: URL (let's say 2.5-3 days with overhead).
Why do you divide by (2^14 + 2048)? Shouldn't it be a multiplication with the minimum record size?
I don't see much support for this. Please take it to the list if you want to pursue it.
Consensus at interim: No protocol action needed. Add calculations to security considerations.
Also, consensus is that the math above is wrong.
NAME would you be willing to contribute a PR with a paragraph or two of guidance on the limits for AES-GCM and ChaCha20
Yes. What happened to the Key Update message? I can't find it in the text, and that would be a logical place to mention the limitations as well as in the security considerations section.
URL If you want to just send a PR against that branch that would be fine. Or really, whatever form you want and I can manually merge.
If we ditch renegotiation (), then we will need a way to rekey sessions to extend their lifetime. Nico suggests that sending ChangeCipherSpec and then using an increasing counter to extract new keys (i.e., add a counter to the key expansion PRF input), which would seem to be sufficient.
We have asked David McGrew about the theoretical limits on AES-GCM, we can find the same info for ChaCha+Poly1305. When we have that info, we will make an assessment as to how urgent this is. That will determine how soon we define this mechanism. NAME noted that you don't even have to negotiate to enable rekeying: if you send the rekey message and rekey, your connection will either be rekeyed, or killed by the peer.

server_key_exchange_RESERVED(12), certificate_request(13), server_hello_done_RESERVED(14), certificate_verify(15), client_key_exchange_RESERVED(16), server_configuration(17),  <ins> finished(20), key_update(24), (255) } HandshakeType; </ins> The TLS Handshake Protocol messages are presented below in the order they MUST be sent; sending handshake messages in an unexpected order to receive an arbitrary number of such messages before receiving the Authentication messages. <ins> 6.3.5.3. struct {} KeyUpdate; The KeyUpdate handshake message is used to indicate that the sender is updating its sending cryptographic keys.  This message can be sent by the server after sending its first flight and the client after sending its second flight.  Implementations that receive a KeyUpdate message prior to receiving a Finished message as part of the 1-RTT handshake MUST generate a fatal "unexpected_message" alert.  After sending a KeyUpdate message, the sender SHALL send all its traffic using the next generation of keys, computed as described in updating- traffic-keys.  Upon receiving a KeyUpdate, the receiver MUST update their receiving keys and if they have not already updated their sending state up to or past the then current receiving generation MUST send their own KeyUpdate prior to sending any other messages. This mechanism allows either side to force an update to the entire connection.  Note that implementations may receive an arbitrary number of messages between sending a KeyUpdate and receiving the peer's KeyUpdate because those messages may already be in flight. Note that if implementations independently send their own KeyUpdates and they cross in flight, this only results in an update of one generation; when each side receives the other side's update it just updates its receive keys and notes that the generations match and thus no send update is needed. Note that the side which sends its KeyUpdate first needs to retain the traffic keys (though not the traffic secret) for the previous generation of keys until it receives the KeyUpdate from the other side. </ins> 7. In order to begin connection protection, the TLS Record Protocol the underlying hash function for HKDF RFC5869.  SS and ES denote the sources from the table above.  <ins> The traffic keys are computed from xSS, xES, and the traffic_secret as described in traffic-key-calculation below.  The traffic_secret may be updated throughout the connection as described in updating- traffic-keys. </ins> Note: although the steps above are phrased as individual HKDF-Extract and HKDF-Expand operations, because each HKDF-Expand operation is 7.2. <ins> Once the handshake is complete, it is possible for either side to update its sending traffic keys using the KeyUpdate handshake message key-update.  The next generation of traffic keys is computed by generating traffic_secret_N+1 from traffic_secret_N as described in this section then re-deriving the traffic keys as described in traffic-key-calculation. The next-generation traffic_secret is computed as: traffic_secret_N+1 = HKDF-Expand-Label(traffic_secret_N, "traffic secret", "", L) Once traffic_secret_N+1 and its associated traffic keys have been computed, implementations SHOULD delete traffic_secret_N.  Once the directional keys are no longer needed, they SHOULD be deleted as well. 7.3. </ins> The traffic keying material is generated from the following input values: The following table indicates the purpose values for each type of key:  <ins> 7.3.1. </ins> The handshake hash is defined as the hash of all handshake messages sent or received, starting at ClientHello up to the present time, hash" because it contains all the handshake messages involved in establishing the session, up to and including the client's Finished.  <ins> 7.3.2. </ins> A conventional Diffie-Hellman computation is performed.  The negotiated key (Z) is used as the shared secret, and is used in the key schedule as specified above.  Leading bytes of Z that contain all zero bits are stripped before it is used as the input to HKDF.  <ins> 7.3.3. </ins> For secp256r1, secp384r1 and secp521r1, ECDH calculations (including parameter and key generation as well as the shared secret


zero, which corresponds to the "null" compression method in prior versions of TLS.  If a TLS 1.3 ClientHello is received with any other value in this field, the server MUST generate a fatal <del> "illegal_parameter" alert.  Note that TLS 1.3 servers may receive TLS 1.2 or prior ClientHellos which contain other compression methods and MUST follow the procedures for the appropriate prior version of TLS. </del>  Clients MAY request extended functionality from servers by sending that is not advertised as being supported in the signature_algorithms extension. <del> Note: TLS 1.3 servers MAY receive TLS 1.2 ClientHellos which do not </del>  contain this extension.  If those servers are willing to negotiate TLS 1.2, they MUST behave in accordance with the requirements of RFC5246 when negotiating that version.

When talking about handling downlevel clients, the spec variously says a server "MAY" receive such messages, or "may" receive such messages. Since this is discussing a possibility (not a permitted behavior), the normative language isn't correct; lower-case versions of the RFC2119 terms have the potential to confuse readers. Suggest changing all of these to "might" to denote a possible occurrence server implementers will need to handle.
Yes, this looks like an improvement.
LGTM

zero, which corresponds to the "null" compression method in prior versions of TLS.  If a TLS 1.3 ClientHello is received with any other value in this field, the server MUST generate a fatal  <ins> "illegal_parameter" alert.  Note that TLS 1.3 servers might receive TLS 1.2 or prior ClientHellos which contain other compression methods and MUST follow the procedures for the appropriate prior version of TLS. </ins> Clients MAY request extended functionality from servers by sending that is not advertised as being supported in the signature_algorithms extension.  <ins> Note: TLS 1.3 servers might receive TLS 1.2 ClientHellos which do not </ins> contain this extension.  If those servers are willing to negotiate TLS 1.2, they MUST behave in accordance with the requirements of RFC5246 when negotiating that version.


The certificate MUST allow the key to be used for signing (i.e., the digitalSignature bit MUST be set if the key usage extension is present) with the signature scheme and hash algorithm that will be <del> employed in the server's KeyShare extension. </del>  An ECDSA or EdDSA public key MUST use a curve and point format supported by the client, as described in RFC4492.

This section has a strange table that looked a little messy. So I cleaned that up. However, I noticed that it used to say this: Which doesn't make any sense. Should this be signature_algorithms extension instead?

The certificate MUST allow the key to be used for signing (i.e., the digitalSignature bit MUST be set if the key usage extension is present) with the signature scheme and hash algorithm that will be  <ins> employed in the server's signature_algorithms extension. </ins> An ECDSA or EdDSA public key MUST use a curve and point format supported by the client, as described in RFC4492.


application_data, and alert respectively) but are protected under different keys.  After all the 0-RTT application data messages (if any) have been sent, a "end_of_early_data" alert of type "warning" is <del> sent to indicate the end of the flight. </del>  A server which receives an "early_data" extension can behave in one of two ways: The type of 0-RTT handshake that this configuration is to be used for (see early-data-indication).  If "client_authentication" or <del> "client_authentication_and_data", then the client should select the certificate for future handshakes based on the CertificateRequest parameters supplied in this handshake.  The server MUST NOT send either of these two options unless it also requested a certificate on this handshake.  [[OPEN ISSUE: Should we relax this?]] </del>  This field is a placeholder for future extensions to the The client MUST send a Certificate message whenever the server has requested client authentication via a CertificateRequest message <del> (certificate-request) or when the EarlyDataIndication indicates client authentication.  This message is only sent if the server requests a certificate.  If no suitable certificate is available, </del>  the client MUST send a Certificate message containing no certificates (i.e., with the "certificate_list" field having length 0).

This cleans up some of the text around EarlyDataIndication that was introduced previously.
The early data indication parameters are defined as clientauthentication(1), earlydata(2), and clientauthenticationanddata(3). A few paragraph after that, some text refers to them by what was probably an old name: If TLS client authentication is being used, then either "earlyhandshake" or "earlyhandshakeand_data" MUST be indicated in order to send the client authentication data on the first flight. Easy fix...
See URL
This should now be fixed.

application_data, and alert respectively) but are protected under different keys.  After all the 0-RTT application data messages (if any) have been sent, a "end_of_early_data" alert of type "warning" is  <ins> sent to indicate the end of the flight.  Clients which do 0-RTT MUST always send "end_of_early_data" even if the ServerConfiguration indicates that no application data is allowed (EarlyDataType of "client_authentication"), though in that case it MUST NOT send any non-empty data records (i.e., those which consist of anything other than padding). </ins> A server which receives an "early_data" extension can behave in one of two ways: The type of 0-RTT handshake that this configuration is to be used for (see early-data-indication).  If "client_authentication" or  <ins> "client_authentication_and_data", then the client MUST select the certificate for future handshakes based on the CertificateRequest parameters supplied in this handshake.  The server MUST NOT send either of these two options unless it also requested a certificate on this handshake.  [[OPEN ISSUE: Should we relax this?]] </ins> This field is a placeholder for future extensions to the The client MUST send a Certificate message whenever the server has requested client authentication via a CertificateRequest message  <ins> (certificate-request) or when the EarlyDataType provided with the server configuration indicates a need for client authentication. This message is only sent if the server requests a certificate via one of these mechanisms.  If no suitable certificate is available, </ins> the client MUST send a Certificate message containing no certificates (i.e., with the "certificate_list" field having length 0).


1-RTT handshake keys until it finds one that decrypts properly, and then pick up the handshake from that point.  [[TODO: How does the client behave if the indication is rejected.]] [[OPEN ISSUE: This just specifies the signaling for 0-RTT but not the

Proposed clarification based on mailing list discussion. Explicitly state that 0-RTT records MUST NOT get special treatment and 1-RTT fallback on decryption errors is prohibited. This may technically already be the intended situation, however any ambiguity here will undoubtedly lead to some implementations falling back to avoid breakage in this scenario, which risks 0-RTT data stripping attacks. As I agree with the expected behavior stated by NAME on-list, this is just a matter of adding some clarification here (even if it might be redundant; someone interpreting the text the way I initially did could do something dangerous if they don't also notice the risk).

1-RTT handshake keys until it finds one that decrypts properly, and then pick up the handshake from that point. <ins> Servers MUST comply with the same error handling requirements specified for all records when processing early data records and MUST NOT fall back to 1-RTT on any such errors.  Specifically, decryption failure of any 0-RTT record following an accepted "early_data" extension MUST produce a fatal "bad_record_mac" alert as per record- payload-protection. </ins> [[TODO: How does the client behave if the indication is rejected.]] [[OPEN ISSUE: This just specifies the signaling for 0-RTT but not the


1-RTT handshake keys until it finds one that decrypts properly, and then pick up the handshake from that point. <del> If the server choosed to accept the "early_data" extension, then it </del>  MUST comply with the same error handling requirements specified for all records when processing early data records.  Specifically, decryption failure of any 0-RTT record following an accepted The cipher suite identifier. <del> If (EC)DHE is being used, the server's version of "key_share". </del>  If PSK is being used, the server's version of the "pre_shared_key" <del> (indicating the PSK the client is using). </del>  6.3.2.5.2. exception of the end-entity certificate which MUST be first. The server's certificate list MUST always be non-empty.  A client <del> will MAY send an empty certificate list if it does not have an </del>  appropriate certificate to send in response to the server's authentication request.

This should be "chose" not "choosed", which isn't really an accepted word.
Added another commit here for a minor wording fix that snuck in with changing all extensions to be referred to by type ID name.
Ok, I switched it to "chooses" instead & squashed my little fixes together here. There's also a fix for the "will MAY" bit that I think we discussed at some point but its fix didn't get in.

1-RTT handshake keys until it finds one that decrypts properly, and then pick up the handshake from that point.  <ins> If the server chooses to accept the "early_data" extension, then it </ins> MUST comply with the same error handling requirements specified for all records when processing early data records.  Specifically, decryption failure of any 0-RTT record following an accepted The cipher suite identifier.  <ins> If (EC)DHE is being used, the server's version of the "key_share" extension. </ins> If PSK is being used, the server's version of the "pre_shared_key"  <ins> extension (indicating the PSK the client is using). </ins> 6.3.2.5.2. exception of the end-entity certificate which MUST be first. The server's certificate list MUST always be non-empty.  A client  <ins> will send an empty certificate list if it does not have an </ins> appropriate certificate to send in response to the server's authentication request.


in CertificateVerify, regardless of whether SHA-1 appears in "signature_algorithms". <del> Note: when used with non-certificate-based handshakes (e.g., PSK), </del>  the client's signature does not cover the server's certificate directly, although it does cover the server's Finished message, which transitively includes the server's certificate when the PSK derives may be updated throughout the connection as described in updating- traffic-keys. <del> Note: although the steps above are phrased as individual HKDF-Extract </del>  and HKDF-Expand operations, because each HKDF-Expand operation is paired with an HKDF-Extract, it is possible to implement this key schedule with a black-box HKDF API, albeit at some loss of efficiency

One more minor fix I just noticed when diffing the latest draft. Just capitalization fixes to match the other notes.

in CertificateVerify, regardless of whether SHA-1 appears in "signature_algorithms".  <ins> Note: When used with non-certificate-based handshakes (e.g., PSK), </ins> the client's signature does not cover the server's certificate directly, although it does cover the server's Finished message, which transitively includes the server's certificate when the PSK derives may be updated throughout the connection as described in updating- traffic-keys.  <ins> Note: Although the steps above are phrased as individual HKDF-Extract </ins> and HKDF-Expand operations, because each HKDF-Expand operation is paired with an HKDF-Extract, it is possible to implement this key schedule with a black-box HKDF API, albeit at some loss of efficiency


at the end of the ClientHello.  Note that this method of detecting optional data differs from the normal TLS method of having a variable-length field, but it is used for compatibility with TLS <del> before extensions were defined. </del>  The version of the TLS protocol by which the client wishes to appropriate prior version of TLS. <del> Clients MAY request extended functionality from servers by sending </del>  data in the extensions field.  The actual "Extension" format is defined in hello-extensions. Structure of this message: %%% Key Exchange Messages struct { ProtocolVersion server_version; <del> Random random; CipherSuite cipher_suite; select (extensions_present) { case false: struct {}; case true: Extension extensions<0..2^16-1>; }; } ServerHello; </del>  <del> The presence of extensions can be detected by determining whether there are bytes following the cipher_suite field at the end of the ServerHello. </del>  This field will contain the lower of that suggested by the client

Small simplification & clarification. Now that the server key share is in an extension, all TLS 1.3 endpoints will have at least one extension in their hello, either "keyshare" or "preshared_key", at minimum. This changeset simplifies the ServerHello struct in the same manner as was previously done for ClientHello and adds short notes explicitly stating this.

at the end of the ClientHello.  Note that this method of detecting optional data differs from the normal TLS method of having a variable-length field, but it is used for compatibility with TLS  <ins> before extensions were defined.  As of TLS 1.3, all clients and servers will send at least one extension (at least "key_share" or "pre_shared_key"). </ins> The version of the TLS protocol by which the client wishes to appropriate prior version of TLS.  <ins> Clients request extended functionality from servers by sending </ins> data in the extensions field.  The actual "Extension" format is defined in hello-extensions. Structure of this message: %%% Key Exchange Messages struct { ProtocolVersion server_version;  <ins> Random random; CipherSuite cipher_suite; Extension extensions<0..2^16-1>; } ServerHello; </ins>  <ins> In prior versions of TLS, the extensions field could be omitted entirely if not needed, similar to ClientHello.  As of TLS 1.3, all clients and servers will send at least one extension (at least "key_share" or "pre_shared_key"). </ins> This field will contain the lower of that suggested by the client


including it in the "pre_shared_key" extension in its ClientHello (pre-shared-key-extension) and supplying a suitable PSK cipher suite. <del> %%% Ticket Establishment struct { uint32 ticket_lifetime_hint; opaque </del>  ticket<0..2^16-1>; } NewSessionTicket; Indicates the lifetime in seconds as a 32-bit unsigned integer in <del> network byte order from the time of ticket issuance.  A value of zero is reserved to indicate that the lifetime of the ticket is unspecified. </del>  The value of the ticket to be used as the PSK identifier. <del> The ticket lifetime hint is informative only.  A client SHOULD delete the ticket and associated state when the time expires.  It MAY delete the ticket earlier based on local policy.  A server MAY treat a ticket as valid for a shorter or longer period of time than what is stated in the ticket_lifetime_hint. </del> The ticket itself is an opaque label.  It MAY either be a database lookup key or a self-encrypted and self-authenticated value. Section 4 of RFC5077 describes a recommended ticket construction

Change ticketlifetimehint to ticket_lifetime and add stricter requirements.
lgtm Please send an email to EMAIL pointing to the change and making a case for it.
Sent, thanks. , Martin Thomson EMAIL wrote:
Mailing list discussion here: URL
+1
Merging per WG discussion. NAME please send me a PR adding yourself to acknowledgements :) Draft 11 currently supports both ServerConfiguration and PSK + Session Ticket for session resumption (0RTT or otherwise). Both mechanisms have the same properties in terms of forward secrecy: a compromise of the server's private data (whether PSK, session ticket key, or DH exponent) lets an attacker retroactively decrypt data from all sessions established with the PSK or Session Ticket. However, both mechanisms contain different language around how the lifetimes of the resumption data is managed. After some discussion with Facebook and others, I'd like to suggest a change in the wording of the draft to make the Session Ticket lifetime more closely resemble the lifetime of the ServerConfiguration. Here is the current language for session ticket lifetimes: ticketlifetimehint Indicates the lifetime in seconds as a 32-bit unsigned integer in network byte order from the time of ticket issuance. A value of zero is reserved to indicate that the lifetime of the ticket is unspecified. The ticket lifetime hint is informative only. A client SHOULD delete the ticket and associated state when the time expires. It MAY delete the ticket earlier based on local policy. A server MAY treat a ticket as valid for a shorter or longer period of time than what is stated in the ticketlifetimehint. And for SeverConfigurations: struct { opaque configurationid; uint32 expirationdate; KeyShareEntry statickeyshare; EarlyDataType earlydatatype; ConfigurationExtension extensions; } ServerConfiguration; expirationdate The last time when this configuration is expected to be valid (in seconds since the Unix epoch). Servers MUST NOT use any value more than 604800 seconds (7 days) in the future. Clients MUST NOT cache configurations for longer than 7 days, regardless of the expirationdate. [[OPEN ISSUE: Is this the right value? The idea is just to minimize exposure.]] My proposed change is to change the session ticket lifetime hint to a strict lifetime along the lines of the ServerConfiguration: ticketlifetime Indicates the lifetime in seconds as a 32-bit unsigned integer in network byte order from the time of ticket issuance. Servers MUST NOT use any value more than 604800 seconds (7 days). The value of zero indicates that the ticket should be discarded immediately. Clients MUST NOT cache session tickets for longer than 7 days, regardless of the ticketlifetime. It MAY delete the ticket earlier based on local policy. A server MAY treat a ticket as valid for a shorter period of time than what is stated in the ticket_lifetime. The full change is on Github as a pull request: URL Note that this new wording is more strict than that of RFC 5077, which does not specify a maximum lifetime for session tickets or dictate that the hint be followed in any way by either client or server. The introduction of the resumption master secret strengthened the forward secrecy story in TLS by requiring resumed connections to use new session keys. The proposed logic strengthens the forward secrecy story of TLS even further by creating a hard limit on the lifetime of unused resumption master secrets. Nick

including it in the "pre_shared_key" extension in its ClientHello (pre-shared-key-extension) and supplying a suitable PSK cipher suite.  <ins> %%% Ticket Establishment struct { uint32 ticket_lifetime; opaque </ins> ticket<0..2^16-1>; } NewSessionTicket; Indicates the lifetime in seconds as a 32-bit unsigned integer in  <ins> network byte order from the time of ticket issuance.  Servers MUST NOT use any value more than 604800 seconds (7 days).  The value of zero indicates that the ticket should be discarded immediately. Clients MUST NOT cache session tickets for longer than 7 days, regardless of the ticket_lifetime.  It MAY delete the ticket earlier based on local policy.  A server MAY treat a ticket as valid for a shorter period of time than what is stated in the ticket_lifetime. </ins> The value of the ticket to be used as the PSK identifier.  The ticket itself is an opaque label.  It MAY either be a database lookup key or a self-encrypted and self-authenticated value. Section 4 of RFC5077 describes a recommended ticket construction


NAME sanity check?
This isn't going to change a great deal, but we need to identify how exporters are constructed with the change to a HKDF-based PRF and the new key schedule.

For X25519 and X448, see RFC7748. <ins> 7.3.4. RFC5705 defines keying material exporters for TLS in terms of the TLS PRF.  This document replaces the PRF with HKDF, thus requiring a new construction.  The exporter interface remains the same, however the value is computed as: Note: the inner HKDF-Extract is strictly unnecessary, but it maintains the invariant that HKDF Extract and Expand calls are paired. </ins> 8. 8.1.


generation of keys until it receives the KeyUpdate from the other side.  7. In order to begin connection protection, the TLS Record Protocol

The current wording of KeyUpdate a bit ambiguous, and leaves out certain areas needed for enforcement and might result in a security issue if not implemented correctly A sender of the keyupdate has no choice of which key to encrypt the keyupdate with, however the recipient does. It has 2 choices: a. Use old key and reset the sequence number after acking the keyupdate b. Use the new key for the key update and reset the sequence number before acking the keyupdate. This distinction is very important for security. If a client uses option b), this causes a security vuln. Because the sequence numbers are reset after a key update, an attacker could truncate (application data) records from the old stream, wait for the key update from the client, and then let new packets through. The client or server has no way of figuring out this has happened. If a receiver verifies that the KeyUpdate is received with the old key before accepting messages encrypted with the new key, then this attack is prevented.
Excellent point. I will merge this. Please also file a PR adding yourself to acknowledgements.

generation of keys until it receives the KeyUpdate from the other side. <ins> Both sender and receiver must encrypt their KeyUpdate messages with the old keys.  Additionally, both sides MUST enforce that a KeyUpdate with the old key is received before accepting any messages encrypted with the new key.  Failure to do so may allow message truncation attacks. </ins> 7. In order to begin connection protection, the TLS Record Protocol


Conceptually, the handshake establishes three secrets which are used to derive all the keys. <del> Ephemeral Secret (ES): A secret which is derived from fresh (EC)DHE shares for this connection.  Keying material derived from ES is intended to be forward secret (with the exception of pre-shared key only modes). Static Secret (SS): A secret which may be derived from static or semi-static keying material, such as a pre-shared key or the server's semi-static (EC)DH share. Master Secret (MS): A secret derived from both the static and the ephemeral secret. There are three basic cases: In a pure (EC)DHE cipher suite, ES and SS will both be the (EC)DHE shared secret. In a pure PSK cipher suite, ES and SS will both be the PSK. In an (EC)DHE-PSK cipher suite, ES will be the (EC)DHE shared secret and SS will be the PSK. </del> tls-full below shows the basic full TLS handshake. The handshake can be thought of as having three phases, indicated in Recipients of Finished messages MUST verify that the contents are correct.  Once a side has sent its Finished message and received and validated the Finished message from its peer, it may begin to <del> send and receive application data over the connection.  This data will be protected under keys derived from the ephemeral secret (see cryptographic-computations). </del>  The key used to compute the finished message is computed from the Base key defined in authentication-messages using HKDF (see key- 7.1. <del> The TLS handshake establishes secret keying material which is then used to protect traffic.  This keying material is derived from the two input secret values: Static Secret (SS) and Ephemeral Secret (ES). </del>  <del> The exact source of each of these secrets depends on the operational mode (DHE, ECDHE, PSK, etc.) and is summarized in the table below: </del>  <del> These shared secret values are used to generate cryptographic keys as shown below. </del>  <del> The derivation process is as follows, where L denotes the length of the underlying hash function for HKDF RFC5869.  SS and ES denote the sources from the table above. </del>  <del> The traffic keys are computed from xSS, xES, and the traffic_secret as described in traffic-key-calculation below.  The traffic_secret may be updated throughout the connection as described in updating- traffic-keys. </del>  <del> Note: Although the steps above are phrased as individual HKDF-Extract and HKDF-Expand operations, because each HKDF-Expand operation is paired with an HKDF-Extract, it is possible to implement this key schedule with a black-box HKDF API, albeit at some loss of efficiency as some HKDF-Extract operations will be repeated. </del>  7.2. The next-generation traffic_secret is computed as: <del> traffic_secret_N+1 = HKDF-Expand-Label(traffic_secret_N, "traffic secret", "", L) </del>  Once traffic_secret_N+1 and its associated traffic keys have been computed, implementations SHOULD delete traffic_secret_N.  Once the The length of the key. <del> The handshake context which is used to generate the keys. </del> The keying material is computed using: The following table describes the inputs to the key calculation for construction.  The exporter interface remains the same, however the value is computed as: <del> Note: the inner HKDF-Extract is strictly unnecessary, but it maintains the invariant that HKDF Extract and Expand calls are paired. </del> 8. 8.1.

First cut at a new, more linear key schedule. WIP so possible I missed something serious. NAME NAME comments, please? Does this seem more straightforward
After this change, the keys used to encrypt the handshake traffic are derived from both ES and SS. (As before, they were derived only from ES) Does this bring any advantages security-wise? In the current version, the Finished keys contain the handshake context up to CertificateVeryServer, by being transitively derived from mES and mSS. Now these keys don't contain handshake context any more. What is the reasoning behind this change?
, svince EMAIL wrote: In the current version, the Finished keys contain the handshake context up
This is pretty good. The simplification is dramatic, which is the number one thing. Well, the number two thing, given that number one is sign-off from the cryptographers; my limited knowledge of this says that we are using the same basic source of keying material for all the important decisions. Critically, exporters and resumption branch after the client Finished. I think that you can revert the bracketing changes by changing the description of each instead. The fact that there are different keys for different phases is quite important to have in people's faces, I think.
Note that I had some concerns with clarity of the PR: formatting, the description of and a few things. I think that those are pretty important and probably need a little attention before landing this.
I'm currently modeling the handshake using the Tamarin Prover. Now i need to decide how to model key generation. Should I rather already use the new key generation, or use the current one? How likely will this pull request be merged in the next time?
I expect to have this resolved and in (though perhaps not identical to this) by this time next week. , svince EMAIL wrote:
The traffic key is derived by applying HKDF-Extract to the traffic_secret, which in turn is derived by applying HKDF-Extract to the master secret. There is no intermediate HKDF-Extract stage. Is this intended? Should there be an intermediate Extract stage? Could the traffic key maybe be derived directly from the master secret, of course together with the correct handshake hash?
Sorry, which line are talking about? The traffic keys are derived by applying HKDF-Expand-Label to the current traffic secret: URL key = HKDF-Expand-Label(Secret, phase + ", " + purpose, handshakecontext, keylength)
According to [URL], the traffic key is computed like this: key = HKDF-Expand-Label(Secret, phase + ", " + purpose, handshakecontext, keylength), where Secret = trafficsecret According to [URL], the trafficsecret is computed as follows: trafficsecret0 = HKDF-Expand-Label(mastersecret, "traffic secret", handshakehash, L) The note at the end of 7.1 declares "each HKDF-Expand operation is paired with an HKDF-Extract". But this is not the case for the traffic key, as there is no HKDF-Extract operation performed on trafficsecret. Is this intended? If so, why? Wouldn't it be the same (security wise) as directly using the mastersecret to derive the traffic key?
Yes, that's an oversight. We are currently reworking the key schedule a bit (see URL) and that will have parity between extract and expand. We could derive the traffic keys from MS, but then we would have to either precompute trafficsecret1 (which is a bit odd) or keep MS around (which threatens PFS for resumed connections). So we did it this way.
Okay thank you for the information. This helped.

Conceptually, the handshake establishes three secrets which are used to derive all the keys.  tls-full below shows the basic full TLS handshake. The handshake can be thought of as having three phases, indicated in Recipients of Finished messages MUST verify that the contents are correct.  Once a side has sent its Finished message and received and validated the Finished message from its peer, it may begin to  <ins> send and receive application data over the connection. </ins> The key used to compute the finished message is computed from the Base key defined in authentication-messages using HKDF (see key- 7.1.  <ins> The TLS handshake establishes one or more input secrets which are combined to create the actual working keying material, as detailed below.  The key derivation process makes use of the following functions, based on HKDF RFC5869: Given a set of n InputSecrets, the final "master secret" is computed by iteratively invoking Add-Secret with InputSecret_1, InputSecret_2, etc.  The initial secret is simply a string of 0s as long as the size of the Hash that is the basis for the HKDF.  Concretely, for the present version of TLS 1.3, secrets are added in the following order: PSK </ins>  <ins> (EC)DHE shared secret </ins>  <ins> This produces a full key derivation schedule shown in the diagram below.  In this diagram, the following formatting conventions apply: </ins>  <ins> HKDF-Extract is drawn as taking the Salt argument from the top and the IKM argument from the left. </ins>  <ins> HKDF's PRK argument is indicated by the arrow coming in from the left.  For instance, the Early Secret is the PRK for generating the early_traffic-secret. </ins>  <ins> The general pattern here is that the secrets shown down the left side of the diagram are just raw entropy without context, whereas the secrets down the right side include handshake context and therefore can be used to derive working keys without additional context.  Note that the different calls to HKDF-Expand-Label may take different Context arguments, even with the same secret.  In a 0-RTT exchange, HKDF-Expand-Label is called with four distinct transcripts; in a 1-RTT only exchange with three distinct transcripts. If a given secret is not available, then the 0-value consisting of a string of L 0s is used. </ins> 7.2. The next-generation traffic_secret is computed as:  <ins> traffic_secret_N+1 = HKDF-Expand-Label(traffic_secret_N, "application traffic secret", "", L) </ins> Once traffic_secret_N+1 and its associated traffic keys have been computed, implementations SHOULD delete traffic_secret_N.  Once the The length of the key.  The keying material is computed using: The following table describes the inputs to the key calculation for construction.  The exporter interface remains the same, however the value is computed as:  8. 8.1.


Diffie-Hellman DH parameters for both clients and servers are encoded in the opaque key_exchange field of a KeyShareEntry in a KeyShare structure.  The opaque value contains the Diffie-Hellman public value <del> (dh_Y = g^X mod p), encoded as a big-endian integer. </del>  %%% Key Exchange Messages opaque dh_Y<1..2^16-1>;

TLS 1.2 did not specify this and some implementations have sporadic interoperability issues as a result. Specify that, in TLS 1.3, public keys should be zero-padded. This is believed to be the more compatible TLS 1.2 variant, and having cryptographic messages be fixed-width fields where possible (not that it matters for public keys) seems preferable to saving one byte 1/256 of the time.
(Er, that should say "DHE public keys". I'll go do a force-push to fix the commit description.)
We seem to have reached consensus that the record layer will use the AEAD form only. The stream and CBC forms will be removed.
Fixed.

Diffie-Hellman DH parameters for both clients and servers are encoded in the opaque key_exchange field of a KeyShareEntry in a KeyShare structure.  The opaque value contains the Diffie-Hellman public value  <ins> (dh_Y = g^X mod p), encoded as a big-endian integer, padded with zeros to the size of p. Note: For a given Diffie-Hellman group, the padding results in all public keys having the same length. </ins> %%% Key Exchange Messages opaque dh_Y<1..2^16-1>;


7.3.1. A conventional Diffie-Hellman computation is performed.  The <del> negotiated key (Z) is used as the shared secret, and is used in the key schedule as specified above.  Leading bytes of Z that contain all zero bits are stripped before it is used as the input to HKDF. </del>  7.3.2.

Every other use of Diffie-Hellman preserves leading zeros. See PKCS section , RFC 2631 section 2.1.2, and SP 800-56A section C.1. I assume X9.42 says something similar to RFC 2631, but I do not have a copy of it. This discrepancy has caused sporadic interoperability issues in TLS 1.2's DHE construction, so clearly it's confusing. Moreover, having variable-length secrets is generally dubious. It exposes an unnecessary side channel. Since TLS 1.2's server-fiat DHE and TLS 1.3's negotiated DHE are already very different animals (1.3 DHE is more like 1.2 ECDHE than anything else), change it to the more reasonable scheme going forward. This is not compatible with 1.2 and does risk a different set of sporadic interop issues if implementations do not realize this changed, but we already have those with 1.2 implementations today.
Edited: Karthik pointed out to me that only the inner length, which was clearly redundant, was dropped in Draft 13. So there is no need for a fix, but there is an opportunity for some savings by changing the encoding of shares. PR changed the text to require padding DH shares to the length of the group, making communicating the length redundant. We could save 2 bytes per share and some processing for parsing and checking the length by specifying as a fixed-length vector with a length dependent on the field. This could also be done for ECDH shares since their length is determined by the curve (because any given curve must specify a single point format). I don't know exactly what is the proper syntax to use, but what I mean is something like this:
The problem with this is that a new named group will have an indeterminate length. The current design is fine.
Concur with MT's analysis.
A new named group will have an indeterminate but fixed length, so the 2-byte length will still be redundant. The struct can be extended as needed for new named groups. The problem I see with redundancy is that implementations will have to check that the length field is consistent with the expected length determined by the group. Implementations will be tempted to omit parsing the length and doing this check. I haven't found any security concern with ignoring the 2-byte length, but being free to choose 2 arbitrary bytes sounds like a bad design. In brief, what I'm suggesting is to either make a MUST for implementations to check that the length bytes encode the expected length
This proposal doesn't work. An old implementation that encounters an unknown new group needs to know the length of data it needs to skip.
Fair enough, you're right. Then, would it be ok for an implementation that encounters a share from a known group and uses it to ignore the 2-byte length?
Failing to check values leads to bugs. c.f. Heartbleed for an extreme example. Implementations that encounter a 37 octet P-256 share should probably reject that message, but they are not obligated to do so if they aren't using the share.
We need to decide whether renegotiation is a part of the protocol. If not, then suitable replacements for the following features may be needed (thanks Nico for the list): rekeying authenticate the client when needed rather than always at handshake time privacy protection for the client's identity privacy protection for the server's identity privacy protection for the server identity desired by the client I'll raise separate issues for tracking these.

7.3.1. A conventional Diffie-Hellman computation is performed.  The  <ins> negotiated key (Z) is converted to byte string by encoding in big- endian, padded with zeros up to the size of the prime.  This byte string is used as the shared secret, and is used in the key schedule as specified above. Note that this construction differs from previous versions of TLS which remove leading zeros. </ins> 7.3.2.


Indicates support of the corresponding named curve.  Note that some curves are also recommended in ANSI X9.62 X962 and FIPS 186-4 <del> DSS.  Others are recommended in I-D.irtf-cfrg-curves.  Values 0xFE00 through 0xFEFF are reserved for private use. </del>  Indicates support of the corresponding finite field group, defined Diffie-Hellman DH parameters for both clients and servers are encoded in the opaque key_exchange field of a KeyShareEntry in a KeyShare structure.  The opaque value contains the Diffie-Hellman public value <del> (dh_Y = g^X mod p), encoded as a big-endian integer, padded with zeros to the size of p. </del>  Note: For a given Diffie-Hellman group, the padding results in all public keys having the same length. <del> %%% Key Exchange Messages opaque dh_Y<1..2^16-1>; </del> 6.3.2.3.2. ECDHE parameters for both clients and servers are encoded in the the opaque key_exchange field of a KeyShareEntry in a KeyShare structure. <del> The opaque value conveys the Elliptic Curve Diffie-Hellman public value (ecdh_Y) represented as a byte string ECPoint.point. %%% Key Exchange Messages opaque point <1..2^8-1>; For secp256r1, secp384r1 and secp521r1, this is the byte string representation of an elliptic curve point following the conversion routine in Section 4.3.6 of ANSI X9.62 X962.  For x25519 and x448, this is raw opaque octet-string representation of point (in the format those functions use), 32 octets for x25519 and 56 octets for x448. </del>  Although X9.62 supports multiple point formats, any given curve MUST specify only a single point format.  All curves currently specified in this document MUST only be used with the uncompressed point format (the format for all ECDH functions is considered uncompressed).  Note: Versions of TLS prior to 1.3 permitted point negotiation; TLS 1.3 removes this feature in favor of a single point format for each curve. ECDH functions are used as follows: <del> The public key to put into ECPoint.point structure is the result of applying the ECDH function to the secret key of appropriate length (into scalar input) and the standard public basepoint (into u-coordinate point input). </del>  The ECDH shared secret is the result of applying ECDH function to the secret key (into scalar input) and the peer's public key (into

(Let me know if you think this is sufficiently non-trivial that it deserves a mailing list posting. It is a wire format change, but I think a fairly boring one.) Only the outer length prefix is necessary, not the inner one. Named groups can just as easily take a byte string with known length rather than need to parse fields out. This is consistent with the definition of DigitallySigned.signature; the signature is an opaque field which is passed as a byte string into the corresponding signature algorithm. The definition of rsapsssha256 does not define an inner u16 length prefix. It simply takes the opaque byte string and passes it into the rsapsssha256 function. (In fact, this change means KeyShareEntry and DigitallySigned structures exactly parallel.) This also fixes some references to non-existent structures like ECPoint and dh_Yc. (Those seem to be remnants of TLS 1.2.)

Indicates support of the corresponding named curve.  Note that some curves are also recommended in ANSI X9.62 X962 and FIPS 186-4  <ins> DSS.  Others are recommended in RFC7748.  Values 0xFE00 through 0xFEFF are reserved for private use. </ins> Indicates support of the corresponding finite field group, defined Diffie-Hellman DH parameters for both clients and servers are encoded in the opaque key_exchange field of a KeyShareEntry in a KeyShare structure.  The opaque value contains the Diffie-Hellman public value  <ins> (Y = g^X mod p), encoded as a big-endian integer, padded with zeros to the size of p. </ins> Note: For a given Diffie-Hellman group, the padding results in all public keys having the same length.  6.3.2.3.2. ECDHE parameters for both clients and servers are encoded in the the opaque key_exchange field of a KeyShareEntry in a KeyShare structure.  <ins> For secp256r1, secp384r1 and secp521r1, the contents are the byte string representation of an elliptic curve public value following the conversion routine in Section 4.3.6 of ANSI X9.62 X962. </ins> Although X9.62 supports multiple point formats, any given curve MUST specify only a single point format.  All curves currently specified in this document MUST only be used with the uncompressed point format (the format for all ECDH functions is considered uncompressed). <ins> For x25519 and x448, the contents are the byte string inputs and outputs of the corresponding functions defined in RFC7748, 32 bytes for x25519 and 56 bytes for x448. </ins> Note: Versions of TLS prior to 1.3 permitted point negotiation; TLS 1.3 removes this feature in favor of a single point format for each curve. ECDH functions are used as follows:  <ins> The public key to put into the KeyShareEntry.key_exchange structure is the result of applying the ECDH function to the secret key of appropriate length (into scalar input) and the standard public basepoint (into u-coordinate point input). </ins> The ECDH shared secret is the result of applying ECDH function to the secret key (into scalar input) and the peer's public key (into


takes as input an arbitrary-length message, rather than a digest. Algorithms which traditionally act on a digest should be defined in TLS to first hash the input with a specified hash function and then <del> proceed as usual. </del>  Indicates a signature algorithm using RSASSA-PKCS1-v1_5 RFC3447

The definition is all "etcetera" currently. We should not assume that readers can parse out the hash algorithm from the enum label.

takes as input an arbitrary-length message, rather than a digest. Algorithms which traditionally act on a digest should be defined in TLS to first hash the input with a specified hash function and then  <ins> proceed as usual.  The code point groups listed above have the following meanings: </ins> Indicates a signature algorithm using RSASSA-PKCS1-v1_5 RFC3447


a client might offer shares for several elliptic curves or multiple integer DH groups.  The key_exchange values for each KeyShareEntry MUST by generated independently.  Clients MUST NOT offer multiple <del> KeyShareEntry values for the same parameters.  Clients and servers MUST NOT offer any KeyShareEntry values for groups not listed in the client's "supported_groups" extension.  Servers MUST NOT offer a KeyShareEntry value for a group not offered by the client in its corresponding KeyShare.  Implementations receiving any KeyShare containing any of these prohibited values MUST abort the connection with a fatal "illegal_parameter" alert. </del>  If the server selects an (EC)DHE cipher suite and no mutually supported group is available between the two endpoints' KeyShare

For issue . This relaxes the requirement to check for and error on lack of inclusion in both extensions and focuses the explicit error requirement on the case of multiple keys for the same group.
Clients MUST NOT offer multiple KeyShareEntry values for the same parameters. Clients and servers MUST NOT offer any KeyShareEntry values for groups not listed in the client's "supportedgroups" extension. Servers MUST NOT offer a KeyShareEntry value for a group not offered by the client in its corresponding KeyShare. Implementations receiving any KeyShare containing any of these prohibited values MUST abort the connection with a fatal "illegalparameter" alert. It's a pain in the ass to check for KeyShareEntry values that are not in the NamedGroups and NSS doesn't presently do it. I think the requirement should be relaxed to just be that you don't select one of them.
NAME I think you wrote this text. Objections?
Relaxing this a bit should be fine. Letting redundant keys slide sounds a bit risky for interop, though. PR with new text submitted.
The "MUST" for what error to throw could be reduced to a "SHOULD", if you'd like to make this even less strict. Not likely to come up that often, though, and I don't see it being more than an interop & waste issue (at least at the moment).
I think that MUST NOT send and MAY generate a fatal error is the right balance here. As an implementation, it's annoying to do this sort of validation because you have to cross validate two extensions, and most of the code for extensions is in the extension handler. Note that even the check for duplicate groups is not something that NSS does. (Did you want to close this now?)

a client might offer shares for several elliptic curves or multiple integer DH groups.  The key_exchange values for each KeyShareEntry MUST by generated independently.  Clients MUST NOT offer multiple  <ins> KeyShareEntry values for the same group and servers recieving multiple KeyShareEntry values for the same group MUST abort the connection with a fatal "illegal_parameter" alert.  Clients and servers MUST NOT offer or accept any KeyShareEntry values for groups not listed in the client's "supported_groups" extension.  Servers MUST NOT offer a KeyShareEntry value for a group not offered by the client in its corresponding KeyShare. </ins> If the server selects an (EC)DHE cipher suite and no mutually supported group is available between the two endpoints' KeyShare


cipher suite adds additional constraints on signature algorithms. server-certificate-selection describes the appropriate rules. <del> rsa_pkcs1_sha1 and dsa_sha1 SHOULD NOT be offered.  Clients offering these values for backwards compatibility MUST list them as the lowest priority (listed after all other algorithms in the </del>  supported_signature_algorithms vector).  TLS 1.3 servers MUST NOT offer a SHA-1 signed certificate unless no valid certificate chain can be produced without it (see server-certificate-selection). key in the sender's end-entity certificate.  RSA signatures MUST use an RSASSA-PSS algorithm, regardless of whether RSASSA- PKCS1-v1_5 algorithms appear in "signature_algorithms".  SHA-1 <del> MUST NOT be used in any signatures in CertificateVerify.  (Note that rsa_pkcs1_sha1 and dsa_sha1, the only defined SHA-1 signature algorithms, are undefined for CertificateVerify signatures.) </del>  Note: When used with non-certificate-based handshakes (e.g., PSK), the client's signature does not cover the server's certificate

I'm going to see about getting rid of it anyway, but I think, for the spec, this is probably the better text, as sad as it makes me. The revised signature algorithm mechanism left the {sha1, ecdsa} SignatureAndHashAlgorithm without a corresponding SignatureScheme defined at all. SHA-1 does not have a corresponding curve, so defining it alongside ecdsap256sha256 and friends was a nuisance. But omitting it, combined with other text, implicitly means it "MUST NOT be offered or negotiated by any implementation". Clients (ideally) send only one ClientHello, so this implies a constraint on TLS 1.2 as well. SHA-1 needs to go, but I think I was a tad overzealous here. I wouldn't be surprised {sha1, ecdsa} can be removed from TLS 1.2 right now. Certainly it will be much much easier to remove than {sha1, rsa}. But this is probably better a SHOULD NOT rather than a MUST NOT. We wouldn't like to discover after the fact that a MUST NOT in TLS 1.3 is untenable due to some ecosystem problem. Notably, old versions of some popular server software ignore signature algorithms and only sign SHA-1. This mostly affects RSA since ECDSA isn't that common, but any such ECDSA deployments would be affected. This is also a little odd for servers as TLS 1.2 says missing sigalgs means the client is assumed to support {sha1, X}. (Although, strictly speaking, the spec does not say the server must do anything useful with that advertisement.) In contrast, dsasha1 is already not offered by many major browsers but is merely a SHOULD NOT. Define ecdsasha1RESERVED as a companion to dsa*RESERVED to bring it out of the implicit MUST NOT. Then include it in the SHOULD NOT lists alongside rsapkcs1sha1 and dsasha1.

cipher suite adds additional constraints on signature algorithms. server-certificate-selection describes the appropriate rules.  <ins> rsa_pkcs1_sha1, dsa_sha1, and ecdsa_sha1 SHOULD NOT be offered. Clients offering these values for backwards compatibility MUST list them as the lowest priority (listed after all other algorithms in the </ins> supported_signature_algorithms vector).  TLS 1.3 servers MUST NOT offer a SHA-1 signed certificate unless no valid certificate chain can be produced without it (see server-certificate-selection). key in the sender's end-entity certificate.  RSA signatures MUST use an RSASSA-PSS algorithm, regardless of whether RSASSA- PKCS1-v1_5 algorithms appear in "signature_algorithms".  SHA-1  <ins> MUST NOT be used in any signatures in CertificateVerify.  All SHA-1 signature algorithms in this specification are defined solely for use in legacy certificates, and are not valid for CertificateVerify signatures. </ins> Note: When used with non-certificate-based handshakes (e.g., PSK), the client's signature does not cover the server's certificate


transmitted as specified by the current active session state. %%% Handshake Protocol enum { hello_request_RESERVED(0), <del> client_hello(1), server_hello(2), session_ticket(4), </del>  hello_retry_request(6), encrypted_extensions(8), certificate(11), server_key_exchange_RESERVED(12), certificate_request(13), server_hello_done_RESERVED(14), certificate_verify(15), Action RFC2434. TLS HandshakeType Registry: Future values are allocated via <del> Standards Action RFC2434. </del>  This document also uses a registry originally created in RFC4366. IANA has updated it to reference this document.  The registry and its

This is purely aesthetic, but apparently no one realizes the name is different, not even IANA, so we may as well go fix it. (I don't know how to write IANA considerations, so I've left it a TODO. But if you give me text, I'll update this PR to include it.) For consistency. At a glance, it seems most TLS implementations did not realize the HandshakeType value was actually named sessionticket and assumed it was named newsession_ticket anyway. Moreover, the IANA entry was named neither and actually named NewSessionTicket since RFC 4507's IANA considerations used the wrong name.

transmitted as specified by the current active session state. %%% Handshake Protocol enum { hello_request_RESERVED(0),  <ins> client_hello(1), server_hello(2), new_session_ticket(4), </ins> hello_retry_request(6), encrypted_extensions(8), certificate(11), server_key_exchange_RESERVED(12), certificate_request(13), server_hello_done_RESERVED(14), certificate_verify(15), Action RFC2434. TLS HandshakeType Registry: Future values are allocated via  <ins> Standards Action RFC2434.  IANA [SHALL update/has updated] this registry to rename item 4 from "NewSessionTicket" to "new_session_ticket". </ins> This document also uses a registry originally created in RFC4366. IANA has updated it to reference this document.  The registry and its


"key_share" or "pre_shared_key"). <del> This field will contain the lower of that suggested by the client in the ClientHello and the highest supported by the server. Servers MUST accept ClientHello versions higher than those supported.  For this version of the specification, the version is { 3, 4 }.  (See backward-compatibility for details about backward compatibility.) </del>  This structure is generated by the server and MUST be generated

People will continue getting this wrong until the end of time, but add an extra MUST in the serverversion half on the off chance someone reads it. Also clarify that clientversion is a maximum version. ("The version of the TLS protocol by which the client wishes to communicate during this session" suggests it should be an exact match.)

"key_share" or "pre_shared_key").  <ins> This field contains the version of TLS negotiated for this session.  Servers MUST select the lower of the highest supported version and the version offered by the client in the ClientHello. In particular, servers MUST accept ClientHello messages with versions higher than those supported and negotiate the highest mutually supported version.  For this version of the specification, the version is { 3, 4 }.  (See backward- compatibility for details about backward compatibility.) </ins> This structure is generated by the server and MUST be generated


The connection is reliable.  Messages include an authentication tag which protects them against modification. <del> Note: The TLS Record Protocol can operate in an insecure mode but is generally only used in this mode while another protocol is using the TLS Record Protocol as a transport for negotiating security parameters. </del> The TLS Record Protocol is used for encapsulation of various higher- level protocols.  One such encapsulated protocol, the TLS Handshake Protocol, allows the server and client to authenticate each other and

and arguably should never be used in that fashion. I know that this stuff badly needs a rewrite, but this is just egregious.

The connection is reliable.  Messages include an authentication tag which protects them against modification.  The TLS Record Protocol is used for encapsulation of various higher- level protocols.  One such encapsulated protocol, the TLS Handshake Protocol, allows the server and client to authenticate each other and


designated digitally-signed, and aead-ciphered, respectively.  A field's cryptographic processing is specified by prepending an appropriate key word designation before the field's type <del> specification.  Cryptographic keys are implied by the current session state (see connection-states). </del>  4.8.1. Specifies the authentication and key establishment algorithms, the hash for use with HKDF to generate keying material, and the record <del> protection algorithm (See the-security-parameters for formal definition.) </del>  a secret shared between the client and server that can be used as a pre-shared symmetric key (PSK) in future connections.

The section on connection states was almost all cruft. I made a new section for nonce construction and moved the piece on sequence numbers there. The only text I modified was the first three paragraphs of the nonce section, which needed to be scrubbed for references to "connection state", and the lead-in section on the AEAD, which I moved to where the other AEAD stuff was and expanded a little to include some forward references.
LGTM NAME Did you still want to replace any of this? The stuff being cut here is very obsolete and must confuse anyone who attempts to read through the whole spec.
Yes, I'm working on it this week. , Dave Garrett EMAIL wrote:

designated digitally-signed, and aead-ciphered, respectively.  A field's cryptographic processing is specified by prepending an appropriate key word designation before the field's type  <ins> specification. </ins> 4.8.1. Specifies the authentication and key establishment algorithms, the hash for use with HKDF to generate keying material, and the record  <ins> protection algorithm </ins> a secret shared between the client and server that can be used as a pre-shared symmetric key (PSK) in future connections.


When resuming via a PSK with an appropriate ticket (i.e., one with the "allow_early_data" flag), clients can also send data on their first flight ("early data").  This data is encrypted solely under <del> keys derived using the PSK as the static secret.  As shown in tls- 0-rtt, the Zero-RTT data is just added to the 1-RTT handshake in the first flight, the rest of the handshake uses the same messages. </del>  [[OPEN ISSUE: Should it be possible to combine 0-RTT with the server authenticating via a signature https://github.com/tlswg/tls13-spec/ A list of the identities (labels for keys) that the client is <del> willing to negotiate with the server. </del>  The server's chosen identity expressed as a (0-based) index into If the server selects a PSK cipher suite, it MUST send a "pre_shared_key" extension with the identity that it selected.  The client MUST verify that the server's selected_identity is within the <del> range supplied by the client.  If any other value is returned, the client MUST generate a fatal "unknown_psk_identity" alert and close the connection. </del>  6.3.2.6. [[OPEN ISSUE: are the rules below correct? https://github.com/tlswg/ tls13-spec/issues/451]] Prior to accepting the "early_data" <del> extension, the server MUST validate that the session ticket parameters are consistent with its current configuration.  It MUST also validate that the extensions negotiated in the previous </del>  connection are identical to those being negotiated in the ServerHello, with the exception of the following extensions:

I would actually much rather we only offer one PSK identity since TLS 1.2 was perfectly fine offering just one and resumption has no use for offering multiple, but I suspect I will lose that fight. Absent that, at least make the protocol well-defined. Unlike both TLS 1.2 resumption and TLS 1.2 PSK, TLS 1.3 increases the state space and allows clients to offer multiple PSK identities. This mostly works, but 0-RTT presumes that only one is offered. Define 0-RTT to presume the first identity is selected and clarify that other shapes are possible due to the increased state space.

When resuming via a PSK with an appropriate ticket (i.e., one with the "allow_early_data" flag), clients can also send data on their first flight ("early data").  This data is encrypted solely under  <ins> keys derived using the first offered PSK as the static secret.  As shown in tls-0-rtt, the Zero-RTT data is just added to the 1-RTT handshake in the first flight, the rest of the handshake uses the same messages. </ins> [[OPEN ISSUE: Should it be possible to combine 0-RTT with the server authenticating via a signature https://github.com/tlswg/tls13-spec/ A list of the identities (labels for keys) that the client is  <ins> willing to negotiate with the server.  If sent alongside the "early_data" extension (see early-data-indication), the first identity is the one used for 0-RTT data. </ins> The server's chosen identity expressed as a (0-based) index into If the server selects a PSK cipher suite, it MUST send a "pre_shared_key" extension with the identity that it selected.  The client MUST verify that the server's selected_identity is within the  <ins> range supplied by the client.  If the server supplies an "early_data" extension, the client MUST verify that the server selected the first offered identity.  If any other value is returned, the client MUST generate a fatal "unknown_psk_identity" alert and close the connection. Note that, although 0-RTT data is encrypted with the first PSK identity, the server may fall back to 1-RTT and select a different PSK identity if multiple are offered. </ins> 6.3.2.6. [[OPEN ISSUE: are the rules below correct? https://github.com/tlswg/ tls13-spec/issues/451]] Prior to accepting the "early_data"  <ins> extension, the server MUST check the first PSK identity (see pre- shared-key-extension) corresponds to a valid ticket and validate that the session parameters are consistent with its current configuration. It MUST also validate that the extensions negotiated in the previous </ins> connection are identical to those being negotiated in the ServerHello, with the exception of the following extensions:


The "extension_data" field of this extension contains a "supported_signature_algorithms" value: <del> %%% Signature Algorithm Extension enum { /* RSASSA-PKCS-v1_5 </del>  algorithms */ rsa_pkcs1_sha1 (0x0201), rsa_pkcs1_sha256 (0x0401), rsa_pkcs1_sha384 (0x0501), rsa_pkcs1_sha512 (0x0601), In addition, the signature algorithm MUST be compatible with the key in the sender's end-entity certificate.  RSA signatures MUST <del> use an RSASSA-PSS algorithm, regardless of whether RSASSA-PKCS- v1_5 algorithms appear in "signature_algorithms".  SHA-1 MUST NOT be used in any signatures in CertificateVerify.  (Note that rsa_pkcs1_sha1 and dsa_sha1, the only defined SHA-1 signature </del>  algorithms, are undefined for CertificateVerify signatures.) Note: When used with non-certificate-based handshakes (e.g., PSK),

RFC 3447 refers to it as RSASSA-PKCS1-v15, not RSASSA-PKCS-v15.

The "extension_data" field of this extension contains a "supported_signature_algorithms" value:  <ins> %%% Signature Algorithm Extension enum { /* RSASSA-PKCS1-v1_5 </ins> algorithms */ rsa_pkcs1_sha1 (0x0201), rsa_pkcs1_sha256 (0x0401), rsa_pkcs1_sha384 (0x0501), rsa_pkcs1_sha512 (0x0601), In addition, the signature algorithm MUST be compatible with the key in the sender's end-entity certificate.  RSA signatures MUST  <ins> use an RSASSA-PSS algorithm, regardless of whether RSASSA- PKCS1-v1_5 algorithms appear in "signature_algorithms".  SHA-1 MUST NOT be used in any signatures in CertificateVerify.  (Note that rsa_pkcs1_sha1 and dsa_sha1, the only defined SHA-1 signature </ins> algorithms, are undefined for CertificateVerify signatures.) Note: When used with non-certificate-based handshakes (e.g., PSK),


"illegal_parameter" alert. TLS 1.3 server implementations which respond to a ClientHello with a <del> client_version indicating TLS 1.2 or below MUST set the first eight </del>  bytes of their Random value to the bytes: TLS 1.2 server implementations which respond to a ClientHello with a <del> client_version indicating TLS 1.1 or below SHOULD set the first eight </del>  bytes of their Random value to the bytes: TLS 1.3 clients receiving a TLS 1.2 or below ServerHello MUST check <del> that the top eight octets are not equal to either of these values. </del>  TLS 1.2 clients SHOULD also perform this check if the ServerHello indicates TLS 1.1 or below.  If a match is found, the client MUST abort the handshake with a fatal "illegal_parameter" alert.  This Note: This is an update to TLS 1.2 so in practice many TLS 1.2 clients and servers will not behave as specified above. <del> Note: Versions of TLS prior to TLS 1.3 used the top 32 bits of the Random value to encode the time since the UNIX epoch.  The sentinel value above was selected to avoid conflicting with any valid TLS 1.2 Random value and to have a low (2^{-64}) probability of colliding with randomly selected Random values. </del> 6.3.1.3. When this message will be sent:

The sentinel value was chosen to avoid conflicting with any valid TLS 1.2 value, but this is not actually desirable. We need to avoid conflicting with any non-TLS-1.3 server but still be a valid TLS 1.2 value. A TLS 1.3 server must still correctly implement TLS 1.2 to interoperate with existing TLS 1.2 clients. In particular, placing it at the front clobbers TLS 1.2's server timestamp. Putting this in the random was silly and 1.3 rightfully removes it, but some software depends on servers sending a timestamp. The tlsdate program uses this as a secure-ish time synchronization protocol. Silly as it is, it exists and it arguably was following the letter of the TLS 1.2 spec, even if we don't like that timestamp very much... Move the sentinel to the end so servers may implement this downgrade protection (which will be needed in the short term given the current version negotiation as it forces browsers to implement the version fallback again) without breaking any tlsdate instances which may still exist.

"illegal_parameter" alert. TLS 1.3 server implementations which respond to a ClientHello with a  <ins> client_version indicating TLS 1.2 or below MUST set the last eight </ins> bytes of their Random value to the bytes: TLS 1.2 server implementations which respond to a ClientHello with a  <ins> client_version indicating TLS 1.1 or below SHOULD set the last eight </ins> bytes of their Random value to the bytes: TLS 1.3 clients receiving a TLS 1.2 or below ServerHello MUST check  <ins> that the last eight octets are not equal to either of these values. </ins> TLS 1.2 clients SHOULD also perform this check if the ServerHello indicates TLS 1.1 or below.  If a match is found, the client MUST abort the handshake with a fatal "illegal_parameter" alert.  This Note: This is an update to TLS 1.2 so in practice many TLS 1.2 clients and servers will not behave as specified above.  6.3.1.3. When this message will be sent:


properties TLS does and does not provide and cannot safely rely on the latter. <del> Note in particular that type and length of a record are not protected by encryption.  If this information is itself sensitive, application </del>  designers may wish to take steps (e.g., padding, cover traffic) to minimize information leakage. described in Section 2.1 of RFC5116.  The key is either the client_write_key or the server_write_key. <del> %%% Record Layer struct { ContentType type; ProtocolVersion record_version = { 3, 1 }; /* TLS v1.x */ uint16 length; aead- ciphered struct { opaque content[TLSPlaintext.length]; } fragment; } TLSCiphertext; </del>  <del> The type field is identical to TLSPlaintext.type. </del>  The record_version field is identical to "record_overflow" alert. <del> The AEAD encrypted form of TLSPlaintext.fragment. </del>  The length of the per-record nonce (iv_length) is set to max(8 bytes, N_MIN) for the AEAD algorithm (see RFC5116 Section 4).  An AEAD Note: This is a different construction from that in TLS 1.2, which specified a partially explicit nonce. <del> The plaintext is the TLSPlaintext.fragment. </del>  The additional authenticated data, which we denote as additional_data, is defined as follows: length of the data. The AEAD output consists of the ciphertext output by the AEAD <del> encryption operation.  The length will generally be larger than TLSPlaintext.length, but by an amount that varies with the AEAD cipher.  Since the ciphers might incorporate padding, the amount of overhead could vary with different TLSPlaintext.length values. Symbolically, </del>  In order to decrypt and verify, the cipher takes as input the key, nonce, the "additional_data", and the AEADEncrypted value.  The If the decryption fails, a fatal "bad_record_mac" alert MUST be generated. <del> An AEAD cipher MUST NOT produce an expansion of greater than 256 bytes.  An endpoint that receives a record that is larger than 2^14 + 256 octets MUST generate a fatal "record_overflow" alert. </del>  <del> As a special case, we define the NULL_NULL AEAD cipher which is simply the identity operation and thus provides no security.  This cipher MUST ONLY be used with the initial TLS_NULL_WITH_NULL_NULL cipher suite. </del>  6.

This pull request has been updated to the current master
Consensus at meeting to merge this PR with updates and with the dummy type byte restored. NAME has action item to actually measure whether we can strip off the now fixed type, record.version bytes.
I've updated this with the expected changes: dummy external ContentType octet is restored, and URL is after fragment.content instead of the other way around (to make it easier to encrypt without having to shuffle buffers).
I agree with davegarrett's suggestion about field naming here, and have supplied a change implementing it.
TLSCiphertext.recordversion provides no useful information, encourages implementations to check it unnecessarily, and wastes two bytes per record. It should be removed entirely. This is effectively dependent on PR or similar changes. Filing this as a specific issue rather than just bringing it up in backwards compatibility discussion. Edited to add: Note that this value is called TLSCiphertext.version in TLS 1.2 and TLSCiphertext.recordversion as of TLS 1.3 draft 06. The TLSPlaintext equivalent of this version field cannot be removed as it is required for backwards compatibility, however it's only used with ClientHello at this point.
Defer pending measurements. Note that this fate shares with removing the cleartext content type
sgtm Amending issue title.
Mozilla is working on measurements.

properties TLS does and does not provide and cannot safely rely on the latter.  <ins> Note in particular that the length of a record is not protected by encryption.  If this information is itself sensitive, application </ins> designers may wish to take steps (e.g., padding, cover traffic) to minimize information leakage. described in Section 2.1 of RFC5116.  The key is either the client_write_key or the server_write_key.  <ins> %%% Record Layer struct { ContentType opaque_type = application_data(23); /* see fragment.type _/ ProtocolVersion record_version = { 3, 1 }; /_ TLS v1.x */ uint16 length; aead- ciphered struct { opaque content[TLSPlaintext.length]; ContentType type; } fragment; } TLSCiphertext; </ins>  <ins> The outer opaque_type field of a TLSCiphertext record is always set to the value 23 (application_data) for outward compatibility with middleboxes used to parsing previous versions of TLS.  The actual content type of the record is found in fragment.type after decryption. </ins> The record_version field is identical to "record_overflow" alert.  <ins> The cleartext of TLSPlaintext.fragment. The actual content type of the record. The AEAD encrypted form of TLSPlaintext.fragment + TLSPlaintext.type, where "+" denotes concatenation. </ins> The length of the per-record nonce (iv_length) is set to max(8 bytes, N_MIN) for the AEAD algorithm (see RFC5116 Section 4).  An AEAD Note: This is a different construction from that in TLS 1.2, which specified a partially explicit nonce.  <ins> The plaintext is the concatenation of TLSPlaintext.fragment and TLSPlaintext.type. </ins> The additional authenticated data, which we denote as additional_data, is defined as follows: length of the data. The AEAD output consists of the ciphertext output by the AEAD  <ins> encryption operation.  The length of the plaintext is one greater than TLSPlaintext.length due to the inclusion of TLSPlaintext.type. The length of aead_output will generally be larger than the plaintext, but by an amount that varies with the AEAD cipher.  Since the ciphers might incorporate padding, the amount of overhead could vary with different TLSPlaintext.length values.  Symbolically, </ins> In order to decrypt and verify, the cipher takes as input the key, nonce, the "additional_data", and the AEADEncrypted value.  The If the decryption fails, a fatal "bad_record_mac" alert MUST be generated.  <ins> An AEAD cipher MUST NOT produce an expansion of greater than 255 bytes.  An endpoint that receives a record from its peer with TLSCipherText.length larger than 2^14 + 256 octets MUST generate a fatal "record_overflow" alert.  This limit is derived from the maximum TLSPlaintext length of 2^14 octets + 1 octet for ContentType + the maximum AEAD expansion of 255 octets. </ins>  <ins> TODO: explain how TLS_NULL_WITH_NULL_NULL is not actually a cipher at all, and that in that state we should send raw TLSPlaintext instead of sending a phony TLSCiphertext </ins> 6.


Note: This is a different construction from that in TLS 1.2, which specified a partially explicit nonce. <del> The plaintext is the concatenation of TLSPlaintext.fragment and TLSPlaintext.type. </del>  The AEAD output consists of the ciphertext output by the AEAD encryption operation.  The length of the plaintext is greater than

This sentence in general seems redundant, but if it's going to be included it should be correct.

Note: This is a different construction from that in TLS 1.2, which specified a partially explicit nonce.  <ins> The plaintext is the concatenation of TLSPlaintext.fragment, TLSPlaintext.type, and any padding bytes (zeros). </ins> The AEAD output consists of the ciphertext output by the AEAD encryption operation.  The length of the plaintext is greater than


A server MUST validate that the ticket_age is within a small tolerance of the time since the ticket was issued (see replay-time). <del> All of the parameters for the 0-RTT data (symmetric cipher suite, ALPN, etc.)  MUST be those which were negotiated in the connection </del>  which established the PSK.  The PSK used to encrypt the early data MUST be the first PSK listed in the client's "pre_shared_key" extension. the early data.  It is not possible for the server to accept only a subset of the early data messages. <del> [[OPEN ISSUE: are the rules below correct? https://github.com/tlswg/ tls13-spec/issues/451]] It MUST also validate that the extensions negotiated in the previous connection are identical to those being negotiated in the ServerHello, with the exception of the following extensions: </del>  <del> The use of "signed_certificate_timestamp" RFC6962 MUST be identical but the server's SCT extension value may differ. </del>  <del> The "padding" extension RFC7685 MUST be ignored for this purpose. </del>  <del> The server MUST have accepted a PSK cipher suite and selected the first key offered in the client's "pre_shared_key" extension. </del>  <del> The values of "key_share", and "early_data", which MUST be as defined in this document. </del>  If any of these checks fail, the server MUST NOT respond with the extension and must discard all the remaining first flight data (thus "early_data" extension MUST produce a fatal "bad_record_mac" alert as per record-payload-protection. <del> [[TODO: How does the client behave if the indication is rejected.]] </del>  4.2.7.1.

We currently have "identical" but Ilari argues we should have more specific rules
From Ilari: "Here is what I think should match (going through all currently known values and excetions): Version Ciphersuite Protection+PRF, key exchange in allowed values. What to do with servername??? Statusrequest presence (but not contents)??? Statusrequestv2 presence (but not contents)??? Signedcertificatetimestamp presence (but not contents)??? ALP can not be negotiated by any means. 0-RTT Protection+PRF+ALP can not be negotiated. (I think statusrequest and statusrequestv2 should mirror whatever signedcertificatetimestamp does). Also, that servername is just its own kind of mess, where what is the proper thing isn't at all obvious. And here is the list of extensions that are allowed to be negotiated with 0-RTT (parenthesis denotes extensions where things depend on exact handling discussed above). (servername) maxframgmentlength (statusrequest) supportedgroups usesrtp heartbeat (statusrequestv2) (signedcertificatetimestamp) tokenbinding [I-D stage] cachedinfo? keyshare presharedkey earlydata (required for obvious reasons) (Note: applicationlayerprotocol_negotiation is not on this list, very much intentionally, since negotiation of ALP is not possible in presence of 0-RTT. Don't even try)."
More from Ilari: Thinking about it some more, including statusrequest/statusrequestv2/ signedcertificatetimestamp is only useful if one wants to tie the ticket lifetime to parent certificate lifetime. Also, list of things saved for 0-RTT-capable context would be useful. I presume: The context name The PSK key The PSK context Timestamp Expiry time (not needed for 0-RTT) On server side: RTT estimate Allowed key exchanges Negotiated protection Negotiated PRF Negotiated ALP (negotiated via any means, or absence thereof) (Implementation-defined peer identity, not needed for 0-RTT) (Implementation-defined self identity, not needed for 0-RTT) What to do with servername??? (On server side, one can save the rest encrypted into context name).

A server MUST validate that the ticket_age is within a small tolerance of the time since the ticket was issued (see replay-time).  <ins> The parameters for the 0-RTT data (symmetric cipher suite, ALPN, etc.) are the same as those which were negotiated in the connection </ins> which established the PSK.  The PSK used to encrypt the early data MUST be the first PSK listed in the client's "pre_shared_key" extension. the early data.  It is not possible for the server to accept only a subset of the early data messages.  <ins> In order to accept early data, the server server MUST have accepted a PSK cipher suite and selected the the first key offered in the client's "pre_shared_key" extension.  In addition, it MUST verify that the following values are consistent with those negotiated in the connection during which the ticket was established. </ins>  <ins> The TLS version number, symmetric ciphersuite, and the hash for HKDF. </ins>  <ins> The selected ALPN RFC7443 value, if any. </ins>  <ins> The server_name RFC6066 value provided by the client, if any. </ins>  <ins> Future extensions MUST define their interaction with 0-RTT. </ins> If any of these checks fail, the server MUST NOT respond with the extension and must discard all the remaining first flight data (thus "early_data" extension MUST produce a fatal "bad_record_mac" alert as per record-payload-protection.  <ins> If the server rejects the "early_data" extension, the client application MAY opt to retransmit the data once the handshake has been completed.  TLS stacks SHOULD not do this automatically and client applications MUST take care that the negotiated parameters are consistent with those it expected.  For example, if the ALPN value has changed, it is likely unsafe to retransmit the original application layer data. </ins> 4.2.7.1.


Note: Alerts and any other record types are not handshake messages and are not included in the hash computations.  4.4. TLS also allows other messages to be sent after the main handshake.

(My impression from the list is that we're not doing post-handshake key separation. If I'm wrong and we are, this will need to be slightly tweaked. Anyway, the current state of the world is we don't do it, so I've worded it accordingly.) As the Finished message is an implicit ChangeCipherSpec, it's worth clarifying that this is the point at which the cipher state changes. Should an implementation not send half-RTT data, it may defer switching traffic keys until both Finished messages have been exchanged. This will not work well, as alerts sent in response to a bad client certificate will be unreadable. The outgoing traffic keys must be switched early.

Note: Alerts and any other record types are not handshake messages and are not included in the hash computations. <ins> Any records following a 1-RTT Finished message MUST be encrypted under the application traffic key.  In particular, this includes any alerts sent by the server in response to client Certificate and CertificateVerify messages. </ins> 4.4. TLS also allows other messages to be sent after the main handshake.


which will be echoed in the client's Certificate message.  The certificate_request_context MUST be unique within the scope of this connection (thus preventing replay of client <del> CertificateVerify messages). </del>  A list of the signature algorithms that the server is able to verify, listed in descending order of preference.  Any

It's only useful during the handshake, so avoid forcing the client save that field for the in-handshake version.
I went back and forth on this, but on balance I think you're right.

which will be echoed in the client's Certificate message.  The certificate_request_context MUST be unique within the scope of this connection (thus preventing replay of client  <ins> CertificateVerify messages).  Within the handshake, this field MUST be empty. </ins> A list of the signature algorithms that the server is able to verify, listed in descending order of preference.  Any


Remove support for non-AEAD ciphers.  2. The cryptographic parameters of the session state are produced by the digest being signed are both the corresponding hash algorithm as defined in SHS.  When used in signed TLS handshake messages, the length of the salt MUST be equal to the length of the digest <del> output. </del>  Indicates a signature algorithm using EdDSA as defined in I- D.irtf-cfrg-eddsa or its successors.  Note that these correspond <del> to the "PureEdDSA" algorithms and not the "prehash" variants. </del>  rsa_pkcs1_sha1, dsa_sha1, and ecdsa_sha1 SHOULD NOT be offered. Clients offering these values for backwards compatibility MUST list accordance with the requirements of RFC5246 when negotiating that version.  In particular: <del> TLS 1.2 ClientHellos may omit this extension. </del>  In TLS 1.2, the extension contained hash/signature pairs.  The pairs are encoded in two octets, so SignatureScheme values have implementation.  In particular, MD5 SLOTH and SHA-224 MUST NOT be used. <del> ecdsa_secp256r1_sha256, etc., align with TLS 1.2's ECDSA hash/ signature pairs.  However, the old semantics did not constrain the signing curve. </del>  4.2.3.

The document was pretty crisp about the version downgrade protections, but was less good about the changes to signature schemes. I have made a few changes to the description of signature_algorithms that should improve that. In particular, I have made it clear that the RSASSA-PSS codepoints are also defined for TLS 1.2 and that they can be used there. That means that TLS implementations need to be prepared to accept PSS signatures. This also adds a section that points to the pieces that 1.2 implementations need to consider.
(Well, I think, strictly speaking, we need only lock down HashAlgorithm.) The SignatureScheme change assumes that we will never again allocate new values in the TLS 1.2 HashAlgorithm and SignatureAlgorithm ranges. I'm not sure how to write that kind of IANA consideration or I'd put together a PR. The end result should probably be something like s/Unassigned/Reserved for TLS 1.3 compatibility/. From TLS 1.3 onwards, all new signature algorithms that apply to TLS 1.2 must go through a backported SignatureScheme. (If we're not happy with that strong of a restriction, we could perhaps only burn HashAlgorithms 0x80 and up. Then TLS 1.3 SignatureSchemes live in the 0x8000 to 0xfdff range. Though 's PSS text already implies we'll be backporting SignatureSchemes, so the division probably isn't necessary? I dunno. I don't really care either way.)
Let's just lock down HAshAlgorithm. Can you submit a PR?

Remove support for non-AEAD ciphers. <ins> 1.3. This document defines several changes that optionally affect implementations of TLS 1.2: A version downgrade protection mechanism is described in server- hello. RSASSA-PSS signature schemes are defined in signature-algorithms. An implementation of TLS 1.3 that also supports TLS 1.2 might need to include changes to support these changes even when TLS 1.3 is not in use.  See the referenced sections for more details. </ins> 2. The cryptographic parameters of the session state are produced by the digest being signed are both the corresponding hash algorithm as defined in SHS.  When used in signed TLS handshake messages, the length of the salt MUST be equal to the length of the digest  <ins> output.  This codepoint is defined for use with TLS 1.2 as well as TLS 1.3.  A server uses RSASSA-PSS signatures with RSA cipher suites. </ins> Indicates a signature algorithm using EdDSA as defined in I- D.irtf-cfrg-eddsa or its successors.  Note that these correspond  <ins> to the "PureEdDSA" algorithms and not the "prehash" variants.  A server uses EdDSA signatures with ECDSA cipher suites. </ins> rsa_pkcs1_sha1, dsa_sha1, and ecdsa_sha1 SHOULD NOT be offered. Clients offering these values for backwards compatibility MUST list accordance with the requirements of RFC5246 when negotiating that version.  In particular:  <ins> TLS 1.2 ClientHellos MAY omit this extension. </ins> In TLS 1.2, the extension contained hash/signature pairs.  The pairs are encoded in two octets, so SignatureScheme values have implementation.  In particular, MD5 SLOTH and SHA-224 MUST NOT be used.  <ins> ECDSA signature schemes align with TLS 1.2's ECDSA hash/signature pairs.  However, the old semantics did not constrain the signing curve.  If TLS 1.2 is negotiated, implementations MUST be prepared to accept a signature that uses any curve that they advertised in the "supported_groups" extension. Implementations that advertise support for RSASSA-PSS (which is mandatory in TLS 1.3), MUST be prepared to accept a signature using that scheme even when TLS 1.2 is negotiated. </ins> 4.2.3.