Skip to content

Commit 53eb412

Browse files
add a more comprehensive test method
1 parent 1a03061 commit 53eb412

File tree

8 files changed

+456
-229
lines changed

8 files changed

+456
-229
lines changed

Cargo.lock

Lines changed: 5 additions & 32 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,21 @@ rand_core = { version = "0.6.4", default-features = false, features = [
5454
rustls = { version = "0.23.19", default-features = false }
5555
webpki = { package = "rustls-webpki", version = "0.102.8", default-features = false, optional = true }
5656

57-
5857
[dev-dependencies]
58+
# workaround to build on no_std targets
5959
getrandom = { version = "0.2", features = [
6060
"custom",
61-
] } # workaround to build on no_std targets
61+
] }
62+
itertools = "0.13.0"
63+
sha2 = { version = "0.10.8", default-features = false, features = ["oid"] }
64+
x509-cert = { version = "0.2.5", default-features = false, features = [
65+
"builder",
66+
"pem"
67+
] }
68+
rsa = { version = "0.9.7", default-features = false, features = [
69+
"sha2",
70+
] }
71+
bytes = { version = "1.9.0", default-features = false }
6272

6373
[features]
6474
default = ["std", "tls12", "zeroize", "full"]

tests/builder.rs

Lines changed: 140 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,165 @@
1-
use std::sync::Arc;
1+
use std::io::{Read, Write};
2+
use std::sync::{Arc, OnceLock};
23

3-
use rustls::ClientConfig as RusTlsClientConfig;
4-
use rustls::ServerConfig as RusTlsServerConfig;
5-
6-
use rustls_rustcrypto::provider as rustcrypto_provider;
7-
8-
mod fake_time;
4+
use fake_cert_server_resolver::FakeServerCertResolver;
95
use fake_time::FakeTime;
10-
11-
mod fake_cert_server_verifier;
12-
use fake_cert_server_verifier::FakeServerCertVerifier;
13-
14-
mod fake_cert_client_verifier;
15-
use fake_cert_client_verifier::FakeClientCertVerifier;
6+
use itertools::iproduct;
7+
use mem_socket::MemorySocket;
8+
use rand_core::{OsRng, RngCore};
9+
use rustls::crypto::CryptoProvider;
10+
use rustls::{
11+
ClientConfig as RusTlsClientConfig, RootCertStore, ServerConfig as RusTlsServerConfig,
12+
};
13+
use rustls_rustcrypto::{provider as rustcrypto_provider, verify, Provider};
1614

1715
mod fake_cert_server_resolver;
18-
use fake_cert_server_resolver::FakeServerCertResolver;
16+
mod fake_time;
1917

20-
// Test integration between rustls and rustls in Client builder context
21-
#[test]
22-
fn integrate_client_builder_with_details_fake() {
23-
let provider = rustcrypto_provider();
24-
let time_provider = FakeTime {};
18+
static SERVER_RESOLVER: OnceLock<Arc<FakeServerCertResolver>> = OnceLock::new();
2519

26-
let fake_server_cert_verifier = FakeServerCertVerifier {};
20+
fn make_client_config(provider: CryptoProvider) -> RusTlsClientConfig {
21+
let resolver = SERVER_RESOLVER.get_or_init(|| Arc::new(FakeServerCertResolver::new()));
22+
let mut store = RootCertStore::empty();
2723

28-
let builder_init =
29-
RusTlsClientConfig::builder_with_details(Arc::new(provider), Arc::new(time_provider));
24+
store.add(resolver.rsa_root_cert()).unwrap();
25+
store.add(resolver.ecdsa_root_cert()).unwrap();
3026

31-
let builder_default_versions = builder_init
27+
RusTlsClientConfig::builder_with_details(Arc::new(provider), Arc::new(FakeTime {}))
3228
.with_safe_default_protocol_versions()
33-
.expect("Default protocol versions error?");
29+
.expect("Default protocol versions error?")
30+
.with_root_certificates(store)
31+
// .dangerous()
32+
// .with_custom_certificate_verifier(Arc::new(FakeServerCertVerifier {}))
33+
.with_no_client_auth()
34+
}
3435

35-
let dangerous_verifier = builder_default_versions
36-
.dangerous()
37-
.with_custom_certificate_verifier(Arc::new(fake_server_cert_verifier));
36+
fn make_server_config(provider: CryptoProvider) -> RusTlsServerConfig {
37+
let resolver = SERVER_RESOLVER
38+
.get_or_init(|| Arc::new(FakeServerCertResolver::new()))
39+
.clone();
40+
RusTlsServerConfig::builder_with_details(Arc::new(provider), Arc::new(FakeTime {}))
41+
.with_safe_default_protocol_versions()
42+
.expect("Default protocol versions error?")
43+
.with_no_client_auth()
44+
.with_cert_resolver(resolver)
45+
}
3846

47+
// Test integration between rustls and rustls in Client builder context
48+
#[test]
49+
fn integrate_client_builder_with_details_fake() {
3950
// Out of scope
40-
let rustls_client_config = dangerous_verifier.with_no_client_auth();
51+
let rustls_client_config = make_client_config(rustcrypto_provider());
4152

4253
// RustCrypto is not fips
4354
assert!(!rustls_client_config.fips());
4455
}
4556

46-
use rustls::DistinguishedName;
47-
4857
// Test integration between rustls and rustls in Server builder context
4958
#[test]
5059
fn integrate_server_builder_with_details_fake() {
51-
let provider = rustcrypto_provider();
52-
let time_provider = FakeTime {};
53-
54-
let builder_init =
55-
RusTlsServerConfig::builder_with_details(Arc::new(provider), Arc::new(time_provider));
56-
57-
let builder_default_versions = builder_init
58-
.with_safe_default_protocol_versions()
59-
.expect("Default protocol versions error?");
60-
61-
// A DistinguishedName is a Vec<u8> wrapped in internal types.
62-
// DER or BER encoded Subject field from RFC 5280 for a single certificate.
63-
// The Subject field is encoded as an RFC 5280 Name
64-
//let b_wrap_in: &[u8] = b""; // TODO: should have constant somewhere
65-
66-
let dummy_entry: &[u8] = b"";
67-
68-
let client_dn = [DistinguishedName::in_sequence(dummy_entry)];
69-
70-
let client_cert_verifier = FakeClientCertVerifier { dn: client_dn };
60+
let rustls_server_config = make_server_config(rustcrypto_provider());
7161

72-
let dangerous_verifier =
73-
builder_default_versions.with_client_cert_verifier(Arc::new(client_cert_verifier));
62+
// RustCrypto is not fips
63+
assert!(!rustls_server_config.fips());
64+
}
7465

75-
let server_cert_resolver = FakeServerCertResolver {};
66+
const CLIENT_MAGIC: &[u8; 18] = b"Hello from Client!";
67+
const SERVER_MAGIC: &[u8; 18] = b"Hello from Server!";
7668

77-
// Out of scope
78-
let rustls_client_config =
79-
dangerous_verifier.with_cert_resolver(Arc::new(server_cert_resolver));
69+
// Test integration
70+
#[test]
71+
fn test_basic_round_trip() {
72+
std::thread::scope(move |s| {
73+
for provider in generate_providers() {
74+
// Creates a pair of sockets that interconnect from client to server, and server to client
75+
let (socket_c2s, socket_s2c) = MemorySocket::new_pair();
76+
77+
let mut random_data: [u8; 8192] = [0; 8192];
78+
OsRng.fill_bytes(&mut random_data);
79+
80+
std::thread::Builder::new()
81+
.name(format!(
82+
"{:?}-{:?}-server",
83+
provider.cipher_suites[0], provider.kx_groups[0]
84+
))
85+
.spawn_scoped(s, {
86+
let provider: CryptoProvider = provider.clone();
87+
move || {
88+
let config = Arc::new(make_server_config(provider));
89+
let mut stream = socket_s2c;
90+
let mut conn = rustls::ServerConnection::new(config.clone())
91+
.expect("failed to create server config");
92+
93+
let mut tls = rustls::Stream::new(&mut conn, &mut stream);
94+
95+
{
96+
let mut buf = [0; CLIENT_MAGIC.len()];
97+
tls.read_exact(&mut buf).unwrap();
98+
assert_eq!(&buf, CLIENT_MAGIC);
99+
}
100+
101+
tls.write_all(SERVER_MAGIC)
102+
.expect("failed to write to client");
103+
tls.write_all(&random_data)
104+
.expect("failed to write random data to client");
105+
tls.conn.send_close_notify();
106+
tls.flush().expect("failed to flush connection");
107+
}
108+
})
109+
.unwrap();
110+
111+
std::thread::Builder::new()
112+
.name(format!(
113+
"{:?}-{:?}-client",
114+
provider.cipher_suites[0], provider.kx_groups[0]
115+
))
116+
.spawn_scoped(s, move || {
117+
let mut sock = socket_c2s;
118+
let server_name = "acme.com".try_into().expect("failed to get server name");
119+
let mut conn = rustls::ClientConnection::new(
120+
Arc::new(make_client_config(provider)),
121+
server_name,
122+
)
123+
.expect("failed to create client config");
124+
let mut tls = rustls::Stream::new(&mut conn, &mut sock);
125+
tls.write_all(CLIENT_MAGIC)
126+
.expect("failed to write to server");
127+
128+
{
129+
let mut buf = [0; SERVER_MAGIC.len()];
130+
tls.read_exact(&mut buf)
131+
.expect("failed to read from server");
132+
assert_eq!(&buf, SERVER_MAGIC);
133+
}
134+
135+
{
136+
let mut plaintext = Vec::new();
137+
tls.write_all(&random_data)
138+
.expect("failed to write random data to server");
139+
tls.read_to_end(&mut plaintext)
140+
.expect("failed to read from server");
141+
assert_eq!(plaintext, random_data);
142+
}
143+
})
144+
.unwrap();
145+
}
146+
});
147+
}
80148

81-
// RustCrypto is not fips
82-
assert!(!rustls_client_config.fips());
149+
fn generate_providers() -> impl Iterator<Item = CryptoProvider> {
150+
let CryptoProvider {
151+
cipher_suites,
152+
kx_groups,
153+
..
154+
} = rustcrypto_provider();
155+
156+
iproduct!(cipher_suites, kx_groups).map(|(cipher_suite, kx_group)| CryptoProvider {
157+
cipher_suites: vec![cipher_suite],
158+
kx_groups: vec![kx_group],
159+
signature_verification_algorithms: verify::ALGORITHMS,
160+
secure_random: &Provider,
161+
key_provider: &Provider,
162+
})
83163
}
164+
165+
mod mem_socket;

0 commit comments

Comments
 (0)