Skip to content

Commit

Permalink
Require 0.5RTT server data to be explicitly enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
ctz committed Feb 5, 2022
1 parent 837ccd7 commit 184b509
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 7 deletions.
1 change: 1 addition & 0 deletions rustls/examples/internal/bogo_shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ fn make_server_cfg(opts: &Options) -> Arc<rustls::ServerConfig> {
if opts.enable_early_data {
// see kMaxEarlyDataAccepted in boringssl, which bogo validates
cfg.max_early_data_size = 14336;
cfg.send_half_rtt_data = true;
}

Arc::new(cfg)
Expand Down
1 change: 1 addition & 0 deletions rustls/src/server/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ impl ConfigBuilder<ServerConfig, WantsServerCert> {
versions: self.state.versions,
key_log: Arc::new(NoKeyLog {}),
max_early_data_size: 0,
send_half_rtt_data: false,
}
}
}
21 changes: 21 additions & 0 deletions rustls/src/server/server_conn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,27 @@ pub struct ServerConfig {
/// this value to account for the unknown amount of ciphertext
/// expansion in the latter case.
pub max_early_data_size: u32,

/// Whether the server should send "0.5RTT" data. This means the server
/// sends data after its first flight of handshake messages, without
/// waiting for the client to complete the handshake.
///
/// This can improve TTFB latency for either server-speaks-first protocols,
/// or client-speaks-first protocols when paired with "0RTT" data. This
/// comes at the cost of a subtle weakening of the normal handshake
/// integrity guarantees that TLS provides. Note that the initial
/// `ClientHello` is indirectly authenticated because it is included
/// in the transcript used to derive the keys used to encrypt the data.
///
/// This only applies to TLS1.3 connections. TLS1.2 connections cannot
/// do this optimisation and this setting is ignored for them. It is
/// also ignored for TLS1.3 connections that even attempt client
/// authentication.
///
/// This defaults to false. This means the first application data
/// sent by the server comes after receiving and validating the client's
/// handshake up to the `Finished` message. This is the safest option.
pub send_half_rtt_data: bool,
}

impl ServerConfig {
Expand Down
2 changes: 1 addition & 1 deletion rustls/src/server/tls13.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ mod client_hello {
&self.config,
);

if !doing_client_auth {
if !doing_client_auth && self.config.send_half_rtt_data {
// Application data can be sent immediately after Finished, in one
// flight. However, if client auth is enabled, we don't want to send
// application data to an unauthenticated peer.
Expand Down
27 changes: 21 additions & 6 deletions rustls/tests/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2334,8 +2334,11 @@ fn vectored_write_for_client_appdata() {
}

#[test]
fn vectored_write_for_server_handshake_without_client_auth() {
let (mut client, mut server) = make_pair(KeyType::Rsa);
fn vectored_write_for_server_handshake_with_half_rtt_data() {
let mut server_config = make_server_config(KeyType::Rsa);
server_config.send_half_rtt_data = true;
let (mut client, mut server) =
make_pair_for_configs(make_client_config_with_auth(KeyType::Rsa), server_config);

server
.writer()
Expand Down Expand Up @@ -2372,9 +2375,7 @@ fn vectored_write_for_server_handshake_without_client_auth() {
check_read(&mut client.reader(), b"012345678901234567890123456789");
}

#[test]
fn vectored_write_for_server_handshake_with_client_auth() {
let server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa);
fn check_half_rtt_does_not_work(server_config: ServerConfig) {
let (mut client, mut server) =
make_pair_for_configs(make_client_config_with_auth(KeyType::Rsa), server_config);

Expand All @@ -2395,7 +2396,7 @@ fn vectored_write_for_server_handshake_with_client_auth() {
// don't assert exact sizes here, to avoid a brittle test
assert!(wrlen > 4000); // its pretty big (contains cert chain)
assert_eq!(pipe.writevs.len(), 1); // only one writev
assert_eq!(pipe.writevs[0].len(), 7); // at least a server hello/ccs/cert/serverkx data
assert!(pipe.writevs[0].len() >= 6); // at least a server hello/ccs/cert/serverkx data
}

// client second flight
Expand All @@ -2418,6 +2419,20 @@ fn vectored_write_for_server_handshake_with_client_auth() {
check_read(&mut client.reader(), b"012345678901234567890123456789");
}

#[test]
fn vectored_write_for_server_handshake_no_half_rtt_with_client_auth() {
let mut server_config = make_server_config_with_mandatory_client_auth(KeyType::Rsa);
server_config.send_half_rtt_data = true; // ask even though it will be ignored
check_half_rtt_does_not_work(server_config);
}

#[test]
fn vectored_write_for_server_handshake_no_half_rtt_by_default() {
let server_config = make_server_config(KeyType::Rsa);
assert_eq!(server_config.send_half_rtt_data, false);
check_half_rtt_does_not_work(server_config);
}

#[test]
fn vectored_write_for_client_handshake() {
let (mut client, mut server) = make_pair(KeyType::Rsa);
Expand Down

0 comments on commit 184b509

Please sign in to comment.