blob: 631e810035881f26382e2077383e5e00e947ee88 [file] [log] [blame]
// Copyright 2026 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::io::{PipeReader, PipeWriter, Read, Write, pipe};
use std::sync::Arc;
use super::*;
use rustls::crypto::ring;
use rustls::{
RootCertStore, ServerConfig, ServerConnection, Stream, SupportedProtocolVersion,
client::{ClientConfig, ClientConnection},
pki_types::{CertificateDer, ServerName, pem::PemObject},
version::{TLS12, TLS13},
};
use tracing::{Level, debug};
// ===================================================================================
// All CSRs `server.csr` is generated from
// openssl req -new -nodes -key <input key> -out server.csr -subj '/CN=www.google.com'
// ===================================================================================
const CA_CERT: &'static [u8] = include_bytes!("./tests/BoringSSLCATest.crt");
const RSA_SVC_CERT: &'static [u8] = include_bytes!("./tests/BoringSSLServerTest-RSA.crt");
const RSA_SVC_KEY: &'static [u8] = include_bytes!("./tests/BoringSSLServerTest-RSA.key");
const ECDSA_P256_SVC_CERT: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-ECDSA-P256.crt");
const ECDSA_P256_SVC_KEY: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-ECDSA-P256.key");
const ECDSA_P384_SVC_CERT: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-ECDSA-P384.crt");
const ECDSA_P384_SVC_KEY: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-ECDSA-P384.key");
const ED25519_SVC_CERT: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-Ed25519.crt");
const ED25519_SVC_KEY: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-Ed25519.key");
const RSA_PSS_SVC_CERT: &'static [u8] =
include_bytes!("./tests/BoringSSLServerTest-RSA-PSS-SHA256.crt");
struct PipeSocket {
tx: PipeWriter,
rx: PipeReader,
}
impl Read for PipeSocket {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
self.rx.read(buf)
}
}
impl Write for PipeSocket {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.tx.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.tx.flush()
}
}
const EXPECTED_SERVER_MSG: &[u8; 18] = b"Awesome BoringSSL!";
const EXPECTED_CLIENT_MSG: &[u8; 19] = b"Oh yeah definitely!";
fn init_tracing() {
let _ = tracing_subscriber::fmt()
.with_max_level(Level::DEBUG)
.try_init();
}
fn test_cipher_suite(
ca: &[u8],
svc_cert: &[u8],
svc_key: &[u8],
client_protocols: &[&'static SupportedProtocolVersion],
server_crypto_provider: CryptoProvider,
client_crypto_provider: CryptoProvider,
) {
init_tracing();
let ca_cert = CertificateDer::from_pem_slice(ca).unwrap();
let svc_cert = CertificateDer::from_pem_slice(svc_cert).unwrap();
let svc_key = PrivateKeyDer::from_pem_slice(svc_key).unwrap();
let mut root_ca = RootCertStore::empty();
assert_eq!(root_ca.add_parsable_certificates([ca_cert.clone()]), (1, 0));
let client_conf = ClientConfig::builder_with_provider(Arc::new(client_crypto_provider))
.with_protocol_versions(client_protocols)
.unwrap()
.with_root_certificates(Arc::new(root_ca))
.with_no_client_auth();
let server_conf = ServerConfig::builder_with_provider(Arc::new(server_crypto_provider))
.with_protocol_versions(&[&TLS12, &TLS13])
.unwrap()
.with_no_client_auth()
.with_single_cert(vec![svc_cert, ca_cert], svc_key)
.unwrap();
let (server_rx, server_tx) = pipe().unwrap();
let (client_rx, client_tx) = pipe().unwrap();
let mut server_sock = PipeSocket {
tx: client_tx,
rx: server_rx,
};
let mut client_sock = PipeSocket {
tx: server_tx,
rx: client_rx,
};
let mut client_conn = ClientConnection::new(
Arc::new(client_conf),
ServerName::try_from("www.google.com").unwrap(),
)
.unwrap();
let client_thread = std::thread::spawn(move || {
let mut client_stream = Stream::new(&mut client_conn, &mut client_sock);
let mut buf = [0; EXPECTED_SERVER_MSG.len()];
client_stream.read_exact(&mut buf).unwrap();
assert_eq!(&buf, EXPECTED_SERVER_MSG);
client_stream.write_all(EXPECTED_CLIENT_MSG).unwrap();
});
let mut server_conn = ServerConnection::new(Arc::new(server_conf)).unwrap();
let mut server_stream = Stream::new(&mut server_conn, &mut server_sock);
server_stream.write_all(EXPECTED_SERVER_MSG).unwrap();
debug!("scheduled server message, polling client message");
let mut buf = [0; EXPECTED_CLIENT_MSG.len()];
server_stream.read_exact(&mut buf).unwrap();
assert_eq!(&buf, EXPECTED_CLIENT_MSG);
debug!("received client message");
server_stream.conn.send_close_notify();
if server_stream.conn.write_tls(server_stream.sock).is_err() {
return;
}
let _ = server_stream;
let _ = server_conn;
let _ = server_sock;
client_thread.join().unwrap();
}
#[test]
fn all_key_agreement_algorithms() {
for group in [
super::key_exchange::ECDH_P256,
super::key_exchange::ECDH_P384,
super::key_exchange::X25519,
#[cfg(feature = "mlalgs")]
super::key_exchange::X25519MLKEM768,
] {
test_cipher_suite(
CA_CERT,
RSA_SVC_CERT,
RSA_SVC_KEY,
&[&TLS13],
CryptoProviderBuilder::new()
.with_key_exchange_group(group)
.with_cipher_suite(SupportedCipherSuite::Tls13(
cipher_suites::TLS13_AES_256_GCM_SHA384,
))
.build(),
CryptoProviderBuilder::new()
.with_key_exchange_group(group)
.with_full_cipher_suites()
.build(),
);
}
for group in [
super::key_exchange::ECDH_P256,
super::key_exchange::ECDH_P384,
super::key_exchange::X25519,
] {
test_cipher_suite(
CA_CERT,
RSA_SVC_CERT,
RSA_SVC_KEY,
&[&TLS13],
CryptoProviderBuilder::new()
.with_key_exchange_group(group)
.with_cipher_suite(SupportedCipherSuite::Tls13(
cipher_suites::TLS13_AES_256_GCM_SHA384,
))
.build(),
ring::default_provider(),
);
}
}
fn test_half_connection(
providers: &[fn() -> CryptoProvider],
test_provider: fn() -> CryptoProvider,
run_test_suite: impl Fn(CryptoProvider, CryptoProvider),
) {
for provider in providers {
run_test_suite(provider(), test_provider());
run_test_suite(test_provider(), provider());
}
}
#[test]
fn tls12_ecdhe_rsa_aes_128_gcm() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
RSA_SVC_CERT,
RSA_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
);
},
);
}
#[test]
fn tls12_ecdhe_rsa_pss_aes_128_gcm() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
RSA_PSS_SVC_CERT,
RSA_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls12_ecdhe_rsa_with_aes_256_gcm_sha384() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
RSA_SVC_CERT,
RSA_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls12_ecdhe_ecdsa_with_chacha20_poly1305_sha256() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls12_ecdhe_ecdsa_with_aes_128_gcm_sha256() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls12_ecdhe_ecdsa_with_aes_256_gcm_sha384() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls13_aes_128_gcm_sha256() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls13(
cipher_suites::TLS13_AES_128_GCM_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS13],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls13_aes_256_gcm_sha384() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls13(
cipher_suites::TLS13_AES_256_GCM_SHA384,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS13],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls13_chacha20_poly1305_sha256() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls13(
cipher_suites::TLS13_CHACHA20_POLY1305_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS13],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls12_ecdhe_rsa_with_chacha20_poly1305_sha256() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_cipher_suite(SupportedCipherSuite::Tls12(
cipher_suites::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
))
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
RSA_SVC_CERT,
RSA_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls13_rsa_server_cert() {
test_cipher_suite(
CA_CERT,
RSA_SVC_CERT,
RSA_SVC_KEY,
&[&TLS13],
CryptoProviderBuilder::full(),
CryptoProviderBuilder::full(),
);
}
#[test]
fn tls13_rsa_pss_server_cert() {
test_cipher_suite(
CA_CERT,
RSA_PSS_SVC_CERT,
RSA_SVC_KEY,
&[&TLS13],
CryptoProviderBuilder::full(),
CryptoProviderBuilder::full(),
);
}
#[test]
fn tls13_ecdsa_p384_server_cert() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_full_cipher_suites()
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P384_SVC_CERT,
ECDSA_P384_SVC_KEY,
&[&TLS13],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls12_ecdsa_p384_server_cert() {
let providers = [CryptoProviderBuilder::full, ring::default_provider];
let test_provider = || {
CryptoProviderBuilder::new()
.with_default_key_exchange_groups()
.with_full_cipher_suites()
.build()
};
test_half_connection(
&providers,
test_provider,
|client_provider, server_provider| {
test_cipher_suite(
CA_CERT,
ECDSA_P384_SVC_CERT,
ECDSA_P384_SVC_KEY,
&[&TLS12],
server_provider,
client_provider,
)
},
);
}
#[test]
fn tls13_ed25519_server_cert() {
// Ed25519 is not supported by ring, so test BoringSSL on both sides.
test_cipher_suite(
CA_CERT,
ED25519_SVC_CERT,
ED25519_SVC_KEY,
&[&TLS13],
CryptoProviderBuilder::full(),
CryptoProviderBuilder::full(),
);
}
#[test]
fn full_provider_both_sides_tls13() {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS13],
CryptoProviderBuilder::full(),
CryptoProviderBuilder::full(),
);
}
#[test]
fn full_provider_both_sides_tls12() {
test_cipher_suite(
CA_CERT,
ECDSA_P256_SVC_CERT,
ECDSA_P256_SVC_KEY,
&[&TLS12],
CryptoProviderBuilder::full(),
CryptoProviderBuilder::full(),
);
}