Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ jobs:
# reliably matched to CI. There can be non-semantic differences in
# output between point releases of cbindgen that will fail this check
# otherwise.
run: cargo install cbindgen --force --version 0.28.0
run: cargo install cbindgen --force --version 0.29.4

- name: Configure CMake
run: cmake -S librustls -B build
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion librustls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ prefer-post-quantum = ["aws-lc-rs", "rustls/prefer-post-quantum"]

[dependencies]
# Keep in sync with RUSTLS_CRATE_VERSION in build.rs
rustls = { version = "=0.23.41", default-features = false, features = ["std", "tls12"] }
rustls = { version = "=0.23.42", default-features = false, features = ["std", "tls12"] }
webpki = { workspace = true }
libc = { workspace = true }
log = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion librustls/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ fn main() {
// because doing so would require a heavy-weight deserialization lib dependency
// (and it couldn't be a _dev_ dep for use in a build script) or doing brittle
// by-hand parsing.
const RUSTLS_CRATE_VERSION: &str = "0.23.41";
const RUSTLS_CRATE_VERSION: &str = "0.23.42";
86 changes: 85 additions & 1 deletion librustls/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::sync::Arc;

use libc::{c_char, size_t};
use rustls::client::danger::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
use rustls::client::{EchConfig, EchGreaseConfig, EchMode, ResolvesClientCert};
use rustls::client::{EchConfig, EchGreaseConfig, EchMode, ResolvesClientCert, TicketRequest};
use rustls::crypto::{CryptoProvider, verify_tls12_signature, verify_tls13_signature};
use rustls::pki_types::{CertificateDer, EchConfigListBytes, ServerName, UnixTime};
use rustls::{
Expand Down Expand Up @@ -60,6 +60,7 @@ pub(crate) struct ClientConfigBuilder {
cert_resolver: Option<Arc<dyn ResolvesClientCert>>,
key_log: Option<Arc<dyn KeyLog>>,
ech_mode: Option<EchMode>,
send_ticket_request: Option<TicketRequest>,
}

impl Default for ClientConfigBuilder {
Expand All @@ -79,6 +80,7 @@ impl Default for ClientConfigBuilder {
cert_resolver: None,
key_log: None,
ech_mode: None,
send_ticket_request: None,
}
}
}
Expand Down Expand Up @@ -287,6 +289,34 @@ impl rustls_client_config_builder {
}
}

/// Request a specific number of TLS 1.3 session tickets.
///
/// This is done via the RFC 9149 `ticket_request` extension.
///
/// `new_session_count` is the number of tickets desired when the server
/// negotiates a new connection, and `resumption_count` the number desired
/// when the server resumes using a presented ticket.
///
/// By default the extension is not sent. Note that servers are free to
/// ignore the request, it is only a hint.
///
/// <https://docs.rs/rustls/latest/rustls/struct.ClientConfig.html#structfield.send_ticket_request>
#[no_mangle]
pub extern "C" fn rustls_client_config_builder_set_send_ticket_request(
builder: *mut rustls_client_config_builder,
new_session_count: u8,
resumption_count: u8,
) -> rustls_result {
ffi_panic_boundary! {
let config = try_mut_from_ptr!(builder);
config.send_ticket_request = Some(TicketRequest {
new_session_count,
resumption_count,
});
rustls_result::Ok
}
}

/// Enable or disable SNI.
/// <https://docs.rs/rustls/latest/rustls/struct.ClientConfig.html#structfield.enable_sni>
#[no_mangle]
Expand Down Expand Up @@ -556,7 +586,9 @@ impl rustls_client_config_builder {
None => config.with_no_client_auth(),
};
config.alpn_protocols = builder.alpn_protocols;
config.check_selected_alpn = builder.check_selected_alpn;
config.enable_sni = builder.enable_sni;
config.send_ticket_request = builder.send_ticket_request;

if let Some(key_log) = builder.key_log {
config.key_log = key_log;
Expand Down Expand Up @@ -912,6 +944,9 @@ mod tests {
alpn.len(),
);
rustls_client_config_builder::rustls_client_config_builder_set_enable_sni(builder, false);
rustls_client_config_builder::rustls_client_config_builder_set_check_selected_alpn(
builder, false,
);
let mut config = null();
let result =
rustls_client_config_builder::rustls_client_config_builder_build(builder, &mut config);
Expand All @@ -921,6 +956,55 @@ mod tests {
let config2 = try_ref_from_ptr!(config);
assert!(!config2.enable_sni);
assert_eq!(config2.alpn_protocols, vec![h1, h2]);
assert!(!config2.check_selected_alpn);
}
rustls_client_config::rustls_client_config_free(config);
rustls_server_cert_verifier::rustls_server_cert_verifier_free(verifier);
}

#[test]
#[cfg_attr(miri, ignore)]
fn test_config_builder_set_send_ticket_request() {
// The default is to not send the ticket_request extension.
let builder = rustls_client_config_builder::rustls_client_config_builder_new();
let mut verifier = null_mut();
let result =
rustls_server_cert_verifier::rustls_platform_server_cert_verifier(&mut verifier);
assert_eq!(result, rustls_result::Ok);
rustls_client_config_builder::rustls_client_config_builder_set_server_verifier(
builder, verifier,
);
let mut config = null();
let result =
rustls_client_config_builder::rustls_client_config_builder_build(builder, &mut config);
assert_eq!(result, rustls_result::Ok);
{
let config2 = try_ref_from_ptr!(config);
assert_eq!(config2.send_ticket_request, None);
}
rustls_client_config::rustls_client_config_free(config);

// Configured counts flow through to the config.
let builder = rustls_client_config_builder::rustls_client_config_builder_new();
rustls_client_config_builder::rustls_client_config_builder_set_server_verifier(
builder, verifier,
);
rustls_client_config_builder::rustls_client_config_builder_set_send_ticket_request(
builder, 6, 3,
);
let mut config = null();
let result =
rustls_client_config_builder::rustls_client_config_builder_build(builder, &mut config);
assert_eq!(result, rustls_result::Ok);
{
let config2 = try_ref_from_ptr!(config);
assert_eq!(
config2.send_ticket_request,
Some(TicketRequest {
new_session_count: 6,
resumption_count: 3,
})
);
}
rustls_client_config::rustls_client_config_free(config);
rustls_server_cert_verifier::rustls_server_cert_verifier_free(verifier);
Expand Down
112 changes: 76 additions & 36 deletions librustls/src/rustls.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,14 @@
#endif


/**
* Describes which sort of handshake happened.
*/
typedef enum rustls_handshake_kind {
/**
* The type of handshake could not be determined.
*
* This variant should not be used.
*/
RUSTLS_HANDSHAKE_KIND_UNKNOWN = 0,
/**
* A full TLS handshake.
*
* This is the typical TLS connection initiation process when resumption is
* not yet unavailable, and the initial client hello was accepted by the server.
*/
RUSTLS_HANDSHAKE_KIND_FULL = 1,
/**
* A full TLS handshake, with an extra round-trip for a hello retry request.
*
* The server can respond with a hello retry request (HRR) if the initial client
* hello is unacceptable for several reasons, the most likely if no supported key
* shares were offered by the client.
*/
RUSTLS_HANDSHAKE_KIND_FULL_WITH_HELLO_RETRY_REQUEST = 2,
/**
* A resumed TLS handshake.
*
* Resumed handshakes involve fewer round trips and less cryptography than
* full ones, but can only happen when the peers have previously done a full
* handshake together, and then remember data about it.
*/
RUSTLS_HANDSHAKE_KIND_RESUMED = 3,
} rustls_handshake_kind;

/**
* Numeric error codes returned from rustls-ffi API functions.
*/
enum rustls_result {
enum rustls_result
#if __STDC_VERSION__ >= 202311L
: uint32_t
#endif // __STDC_VERSION__ >= 202311L
{
RUSTLS_RESULT_OK = 7000,
RUSTLS_RESULT_IO = 7001,
RUSTLS_RESULT_NULL_PARAMETER = 7002,
Expand Down Expand Up @@ -193,7 +162,11 @@ enum rustls_result {
RUSTLS_RESULT_INVALID_ENCRYPTED_CLIENT_HELLO_NO_COMPATIBLE_CONFIG = 7701,
RUSTLS_RESULT_INVALID_ENCRYPTED_CLIENT_HELLO_SNI_REQUIRED = 7702,
};
#if __STDC_VERSION__ >= 202311L
typedef enum rustls_result rustls_result;
#else
typedef uint32_t rustls_result;
#endif // __STDC_VERSION__ >= 202311L

/**
* Definitions of known TLS protocol versions.
Expand All @@ -208,6 +181,41 @@ typedef enum rustls_tls_version {
RUSTLS_TLS_VERSION_TLSV1_3 = 772,
} rustls_tls_version;

/**
* Describes which sort of handshake happened.
*/
typedef enum rustls_handshake_kind {
/**
* The type of handshake could not be determined.
*
* This variant should not be used.
*/
RUSTLS_HANDSHAKE_KIND_UNKNOWN = 0,
/**
* A full TLS handshake.
*
* This is the typical TLS connection initiation process when resumption is
* not yet unavailable, and the initial client hello was accepted by the server.
*/
RUSTLS_HANDSHAKE_KIND_FULL = 1,
/**
* A full TLS handshake, with an extra round-trip for a hello retry request.
*
* The server can respond with a hello retry request (HRR) if the initial client
* hello is unacceptable for several reasons, the most likely if no supported key
* shares were offered by the client.
*/
RUSTLS_HANDSHAKE_KIND_FULL_WITH_HELLO_RETRY_REQUEST = 2,
/**
* A resumed TLS handshake.
*
* Resumed handshakes involve fewer round trips and less cryptography than
* full ones, but can only happen when the peers have previously done a full
* handshake together, and then remember data about it.
*/
RUSTLS_HANDSHAKE_KIND_RESUMED = 3,
} rustls_handshake_kind;

/**
* A parsed ClientHello produced by a rustls_acceptor.
*
Expand Down Expand Up @@ -1458,6 +1466,24 @@ rustls_result rustls_client_config_builder_set_alpn_protocols(struct rustls_clie
void rustls_client_config_builder_set_check_selected_alpn(struct rustls_client_config_builder *config,
bool enable);

/**
* Request a specific number of TLS 1.3 session tickets.
*
* This is done via the RFC 9149 `ticket_request` extension.
*
* `new_session_count` is the number of tickets desired when the server
* negotiates a new connection, and `resumption_count` the number desired
* when the server resumes using a presented ticket.
*
* By default the extension is not sent. Note that servers are free to
* ignore the request, it is only a hint.
*
* <https://docs.rs/rustls/latest/rustls/struct.ClientConfig.html#structfield.send_ticket_request>
*/
rustls_result rustls_client_config_builder_set_send_ticket_request(struct rustls_client_config_builder *builder,
uint8_t new_session_count,
uint8_t resumption_count);

/**
* Enable or disable SNI.
* <https://docs.rs/rustls/latest/rustls/struct.ClientConfig.html#structfield.enable_sni>
Expand Down Expand Up @@ -2401,6 +2427,20 @@ rustls_result rustls_server_config_builder_set_ignore_client_order(struct rustls
rustls_result rustls_server_config_builder_set_send_tls13_tickets(struct rustls_server_config_builder *builder,
size_t n);

/**
* Set the upper bound on the number of TLS 1.3 tickets sent in response to a client.
*
* This modifies the server's response to a client's RFC 9149 `ticket_request` extension.
*
* A client requesting `n` tickets receives `min(n, max)`. Setting this to
* 0 (the default) ignores client requests entirely, clients get the configured
* `send_tls13_tickets` count regardless.
*
* <https://docs.rs/rustls/latest/rustls/server/struct.ServerConfig.html#structfield.max_tls13_tickets>
*/
rustls_result rustls_server_config_builder_set_max_tls13_tickets(struct rustls_server_config_builder *builder,
size_t max);

/**
* Set the ALPN protocol list to the given protocols.
*
Expand Down
Loading
Loading