Skip to content

Commit 8461dc8

Browse files
committed
Support secp521r1 and Ed448, expand tests
Add support for the `secp521r1` (P-521) key exchange group and the `Ed448` signature scheme to broaden the supported cryptographic capabilities. Update the basic integration tests to verify functionality across multiple protocol versions (TLS 1.2, TLS 1.3) and cipher suites (AES-128, AES-256, ChaCha20) rather than relying on default negotiations. Additionally, the test client now validates the connection by downloading and verifying a specific file, ensuring accurate data transfer instead of just asserting a successful handshake. Assisted-by: Gemini <gemini@google.com> Signed-off-by: Simo Sorce <simo@redhat.com>
1 parent 9305012 commit 8461dc8

3 files changed

Lines changed: 107 additions & 11 deletions

File tree

rustls/ossl/src/keyex.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ impl SupportedKxGroup for OsslEcKxGroup {
1616
NamedGroup::X25519 => EvpPkeyType::X25519,
1717
NamedGroup::secp256r1 => EvpPkeyType::P256,
1818
NamedGroup::secp384r1 => EvpPkeyType::P384,
19+
NamedGroup::secp521r1 => EvpPkeyType::P521,
1920
_ => return Err(Error::General("Unsupported KX group".into())),
2021
};
2122

@@ -56,6 +57,9 @@ impl SupportedKxGroup for OsslEcKxGroup {
5657
NamedGroup::secp384r1 => {
5758
EvpPkey::available(osslctx(), EvpPkeyType::P384)
5859
}
60+
NamedGroup::secp521r1 => {
61+
EvpPkey::available(osslctx(), EvpPkeyType::P521)
62+
}
5963
_ => false,
6064
}
6165
}
@@ -80,7 +84,9 @@ impl ActiveKeyExchange for OsslEcdh {
8084
))?;
8185
}
8286
}
83-
NamedGroup::secp256r1 | NamedGroup::secp384r1 => {
87+
NamedGroup::secp256r1
88+
| NamedGroup::secp384r1
89+
| NamedGroup::secp521r1 => {
8490
if peer.first() != Some(&0x04) {
8591
return Err(Error::PeerMisbehaved(
8692
PeerMisbehaved::InvalidKeyShare,
@@ -199,6 +205,8 @@ pub static SECP256R1: OsslEcKxGroup = OsslEcKxGroup(NamedGroup::secp256r1);
199205

200206
pub static SECP384R1: OsslEcKxGroup = OsslEcKxGroup(NamedGroup::secp384r1);
201207

208+
pub static SECP521R1: OsslEcKxGroup = OsslEcKxGroup(NamedGroup::secp521r1);
209+
202210
pub static MLKEM768: OsslKemKxGroup = OsslKemKxGroup(NamedGroup::MLKEM768);
203211

204212
pub static MLKEM1024: OsslKemKxGroup = OsslKemKxGroup(NamedGroup::MLKEM1024);
@@ -220,6 +228,9 @@ pub fn supported_kx_groups() -> Vec<&'static dyn SupportedKxGroup> {
220228
if EvpPkey::available(osslctx(), EvpPkeyType::X25519) {
221229
v.push(&X25519);
222230
}
231+
if EvpPkey::available(osslctx(), EvpPkeyType::P521) {
232+
v.push(&SECP521R1);
233+
}
223234
if EvpPkey::available(osslctx(), EvpPkeyType::P384) {
224235
v.push(&SECP384R1);
225236
}

rustls/ossl/src/signer.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,10 @@ static ECC_SIG_SCHEMES: OnceLock<Vec<SignatureScheme>> = OnceLock::new();
129129

130130
pub fn supported_ecc_sig_schemes() -> &'static [SignatureScheme] {
131131
let schemes = ECC_SIG_SCHEMES.get_or_init(|| {
132-
let mut v = Vec::with_capacity(6);
132+
let mut v = Vec::with_capacity(5);
133133
for s in [
134134
(SigAlg::Ed25519, SignatureScheme::ED25519),
135+
(SigAlg::Ed448, SignatureScheme::ED448),
135136
(
136137
SigAlg::EcdsaSha2_512,
137138
SignatureScheme::ECDSA_NISTP521_SHA512,

rustls/ossl/tests/basic.rs

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ use std::time::{Duration, SystemTime};
88

99
mod common;
1010

11-
fn run_openssl_server_basic(key_args: &[&str]) {
11+
fn run_openssl_server_basic(
12+
key_args: &[&str],
13+
version: &'static rustls::SupportedProtocolVersion,
14+
cipher_filter: &str,
15+
) {
1216
let dir = std::env::temp_dir().join(format!(
1317
"rustls_ossl_test_{}_{}",
1418
std::process::id(),
@@ -22,6 +26,11 @@ fn run_openssl_server_basic(key_args: &[&str]) {
2226
let key_path = dir.join("key.pem");
2327
let cert_path = dir.join("cert.pem");
2428

29+
// Generate a file to be served to the client
30+
let test_file_path = dir.join("test.txt");
31+
let test_content = b"OpenSSL -WWW test file content";
32+
std::fs::write(&test_file_path, test_content).unwrap();
33+
2534
// Generate self-signed certificate
2635
let mut args = vec!["req", "-x509"];
2736
args.extend_from_slice(key_args);
@@ -50,6 +59,7 @@ fn run_openssl_server_basic(key_args: &[&str]) {
5059

5160
// Start OpenSSL server
5261
let mut server = Command::new("openssl")
62+
.current_dir(&dir)
5363
.args(&[
5464
"s_server",
5565
"-key",
@@ -58,7 +68,7 @@ fn run_openssl_server_basic(key_args: &[&str]) {
5868
cert_path.to_str().unwrap(),
5969
"-accept",
6070
&port.to_string(),
61-
"-www",
71+
"-WWW",
6272
])
6373
.stdout(Stdio::null())
6474
.stderr(Stdio::null())
@@ -82,11 +92,19 @@ fn run_openssl_server_basic(key_args: &[&str]) {
8292
let cert = rustls_pemfile::certs(&mut reader).next().unwrap().unwrap();
8393

8494
// Use the rustls ossl module as CryptoProvider
85-
let provider = Arc::new(rustls_ossl::default_provider());
95+
let mut provider = rustls_ossl::default_provider();
96+
provider
97+
.cipher_suites
98+
.retain(|cs| format!("{:?}", cs.suite()).contains(cipher_filter));
99+
assert!(
100+
!provider.cipher_suites.is_empty(),
101+
"No cipher suites matched filter"
102+
);
103+
let provider = Arc::new(provider);
86104
let verifier = common::PinnedSelfSignedVerifier::new(cert.into_owned());
87105

88106
let config = ClientConfig::builder_with_provider(provider)
89-
.with_safe_default_protocol_versions()
107+
.with_protocol_versions(&[version])
90108
.unwrap()
91109
.dangerous()
92110
.with_custom_certificate_verifier(Arc::new(verifier))
@@ -99,10 +117,20 @@ fn run_openssl_server_basic(key_args: &[&str]) {
99117
let mut socket = TcpStream::connect(("127.0.0.1", port)).unwrap();
100118
let mut stream = rustls::Stream::new(&mut client, &mut socket);
101119

102-
stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
120+
stream.write_all(b"GET /test.txt HTTP/1.0\r\n\r\n").unwrap();
103121
let mut plaintext = Vec::new();
104122
stream.read_to_end(&mut plaintext).unwrap();
105-
std::io::stdout().write_all(&plaintext).unwrap();
123+
124+
let header_end = plaintext
125+
.windows(4)
126+
.position(|window| window == b"\r\n\r\n")
127+
.expect("Response does not contain HTTP headers");
128+
129+
let body = &plaintext[header_end + 4..];
130+
assert_eq!(
131+
body, test_content,
132+
"Downloaded content does not match original"
133+
);
106134

107135
// Ensure we can properly kill the process and clean up
108136
server.kill().unwrap();
@@ -111,9 +139,65 @@ fn run_openssl_server_basic(key_args: &[&str]) {
111139

112140
macro_rules! test_openssl_server_basic {
113141
($name:ident, $args:expr) => {
114-
#[test]
115-
fn $name() {
116-
run_openssl_server_basic($args);
142+
mod $name {
143+
use super::*;
144+
145+
#[cfg(feature = "tls12")]
146+
#[test]
147+
fn tls12_aes128() {
148+
run_openssl_server_basic(
149+
$args,
150+
&rustls::version::TLS12,
151+
"AES_128",
152+
);
153+
}
154+
155+
#[cfg(feature = "tls12")]
156+
#[test]
157+
fn tls12_aes256() {
158+
run_openssl_server_basic(
159+
$args,
160+
&rustls::version::TLS12,
161+
"AES_256",
162+
);
163+
}
164+
165+
#[cfg(feature = "tls12")]
166+
#[test]
167+
fn tls12_chacha20() {
168+
run_openssl_server_basic(
169+
$args,
170+
&rustls::version::TLS12,
171+
"CHACHA20",
172+
);
173+
}
174+
175+
#[test]
176+
fn tls13_aes128() {
177+
run_openssl_server_basic(
178+
$args,
179+
&rustls::version::TLS13,
180+
"AES_128",
181+
);
182+
}
183+
184+
#[test]
185+
fn tls13_aes256() {
186+
run_openssl_server_basic(
187+
$args,
188+
&rustls::version::TLS13,
189+
"AES_256",
190+
);
191+
}
192+
193+
#[test]
194+
fn tls13_chacha20() {
195+
run_openssl_server_basic(
196+
$args,
197+
&rustls::version::TLS13,
198+
"CHACHA20",
199+
);
200+
}
117201
}
118202
};
119203
}

0 commit comments

Comments
 (0)