Harden crypto provider error handling and FIPS reporting

Implement provider-wide FIPS semantics by filtering non-FIPS suites in provider_with_ciphers() and wiring fips() reporting across provider components, KX groups, AEADs, and signature verifiers.

Replace panic-prone hotpath behavior with error returns across TLS/QUIC AEAD setup and header protection, enforce HKDF output bounds, and remove shared HMAC context cloning to tighten runtime safety.

Rework signing and verification paths to support SEC1 EC key loading, curve-aware scheme selection, and consistent malformed-input error handling without panics.

Add comprehensive regression coverage for malformed KX shares, verifier inputs, AEAD truncation and constructor failures, plus a panic-surface test that scans runtime provider/additions code for new panic constructs unless explicitly allowlisted.

Update the example client to return Result and eliminate non-test unwrap-style exits.
This commit is contained in:
Jan Rüth 2026-04-10 16:30:01 +02:00 committed by Jan
commit b88c87235d
19 changed files with 1235 additions and 277 deletions

View file

@ -2,7 +2,7 @@ use std::io::{stdout, Read, Write};
use std::net::TcpStream;
use std::sync::Arc;
fn main() {
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
let mut root_store = rustls::RootCertStore::empty();
@ -11,13 +11,15 @@ fn main() {
let config =
rustls::ClientConfig::builder_with_provider(boring_rustls_provider::provider().into())
.with_safe_default_protocol_versions()
.unwrap()
.map_err(|_| std::io::Error::other("failed selecting protocol versions"))?
.with_root_certificates(root_store)
.with_no_client_auth();
let server_name = "www.rust-lang.org".try_into().unwrap();
let mut conn = rustls::ClientConnection::new(Arc::new(config), server_name).unwrap();
let mut sock = TcpStream::connect("www.rust-lang.org:443").unwrap();
let server_name = "www.rust-lang.org"
.try_into()
.map_err(|_| std::io::Error::other("invalid server name"))?;
let mut conn = rustls::ClientConnection::new(Arc::new(config), server_name)?;
let mut sock = TcpStream::connect("www.rust-lang.org:443")?;
let mut tls = rustls::Stream::new(&mut conn, &mut sock);
tls.write_all(
concat!(
@ -28,16 +30,19 @@ fn main() {
"\r\n"
)
.as_bytes(),
)
.unwrap();
let ciphersuite = tls.conn.negotiated_cipher_suite().unwrap();
)?;
let ciphersuite = tls
.conn
.negotiated_cipher_suite()
.ok_or_else(|| std::io::Error::other("no negotiated ciphersuite"))?;
writeln!(
&mut std::io::stderr(),
"Current ciphersuite: {:?}",
ciphersuite.suite()
)
.unwrap();
)?;
let mut plaintext = Vec::new();
tls.read_to_end(&mut plaintext).unwrap();
stdout().write_all(&plaintext).unwrap();
tls.read_to_end(&mut plaintext)?;
stdout().write_all(&plaintext)?;
Ok(())
}