pub struct ServerConfig {
pub alpn: Vec<Vec<u8>>,
pub client_auth: ClientAuth,
pub suites: Vec<CipherSuite>,
pub groups: Vec<NamedGroup>,
pub ticketer: Option<Arc<Ticketer>>,
pub ticket_lifetime_secs: u32,
pub ticket_count: u8,
pub strict_sni: bool,
pub max_handshake_message: usize,
pub time: Arc<dyn TimeSource>,
/* private fields */
}Expand description
Server configuration. A clone shares the certificates and the session ticket keys
(they sit behind Arcs), so a TCP listener and a QUIC listener can use one parsed
certificate with their own ALPN lists.
Fields§
§alpn: Vec<Vec<u8>>ALPN protocols in preference order (empty: ALPN is ignored).
client_auth: ClientAuth§suites: Vec<CipherSuite>§groups: Vec<NamedGroup>§ticketer: Option<Arc<Ticketer>>Session tickets (None disables resumption).
ticket_lifetime_secs: u32Ticket lifetime advertised to clients and enforced on resumption.
ticket_count: u8NewSessionTickets sent after each full handshake.
strict_sni: boolReject clients whose SNI matches no configured name (unrecognized_name) instead of using the default certificate.
max_handshake_message: usizeLargest handshake message accepted.
time: Arc<dyn TimeSource>Implementations§
Source§impl ServerConfig
impl ServerConfig
Sourcepub fn require_tls13(&mut self)
pub fn require_tls13(&mut self)
Accept TLS 1.3 only. Without the tls12 feature that is already the only version, so
this is a no-op; with it, it raises min_version to TLS 1.3. Lets code that must never
accept TLS 1.2 say so whatever features feature unification switched on.
Sourcepub fn new(cert: CertifiedKey) -> ServerConfig
pub fn new(cert: CertifiedKey) -> ServerConfig
A configuration serving one certificate chain; tickets on, no client authentication.
Examples found in repository?
122pub fn corpus() -> Corpus {
123 let ss = certgen::issue(&CertParams::server(&["localhost"]), PrivateKey::generate_ec(EcCurve::P256), None);
124 let mut roots = RootStore::empty();
125 roots.add_der(&ss.cert_der).unwrap();
126 let scfg = Arc::new(ServerConfig::new(CertifiedKey::new(vec![ss.cert_der.clone()], ss.key.clone()).unwrap()).with_alpn(&[b"h3", b"http/1.1"]));
127 let mut cc = ClientConfig::new(roots).with_alpn(&[b"h3", b"http/1.1"]);
128 cc.sessions = None;
129 let ccfg = Arc::new(cc);
130 // a TLS handshake transcript
131 let mut c = ClientConnection::new(ccfg.clone(), "localhost").unwrap();
132 let mut s = ServerConnection::new(scfg.clone());
133 let ch = c.tls_output().to_vec();
134 c.consume_tls_output(ch.len());
135 s.read_tls(&ch);
136 s.process_new_packets().unwrap();
137 let flight = s.tls_output().to_vec();
138 let mut ch_plus = ch.clone();
139 ch_plus.extend_from_slice(&[20, 3, 3, 0, 1, 1, 23, 3, 3, 0, 20]);
140 ch_plus.extend(std::iter::repeat_n(0xaa, 20));
141 // a QUIC handshake: the ClientHello message and the server's Handshake-level flight
142 let mut qc = QuicConnection::new_client(ccfg.clone(), "localhost", vec![1, 2, 3]).unwrap();
143 let mut qs = QuicConnection::new_server(scfg.clone(), vec![4, 5, 6]);
144 let mut ch_msg = Vec::new();
145 qc.write_handshake(&mut ch_msg);
146 qs.read_handshake(Level::Initial, &ch_msg).unwrap();
147 let mut sh = Vec::new();
148 qs.write_handshake(&mut sh);
149 let mut hs = Vec::new();
150 qs.write_handshake(&mut hs);
151 Corpus {
152 scfg,
153 ccfg,
154 to_server: vec![ch, ch_plus],
155 to_client: vec![flight],
156 ch_msg,
157 server_hs_flight: hs,
158 key_der: ss.key_der.clone(),
159 cert_der: ss.cert_der,
160 }
161}More examples
63fn main() {
64 let openssl = std::env::args().any(|a| a == "--openssl");
65 let d = Duration::from_millis(if std::env::args().any(|a| a == "--quick") { 300 } else { 1500 });
66 println!("simoom-tls benchmarks (single thread), hardware AES: {}, CLMUL: {}, SHA-NI: {}", simoom_sys::arch::has_aes(), simoom_sys::arch::has_clmul(), simoom_sys::arch::has_sha256());
67 println!();
68 println!("{:<34} {:>12} {:>12}", "AEAD seal (encrypt + tag)", "16384 B", "1400 B");
69 let aad = [0u8; 13];
70 let mut buf = vec![0x5au8; 16384];
71 let gcm128 = AesGcm::new(&[1u8; 16]);
72 let gcm256 = AesGcm::new(&[1u8; 32]);
73 let gcm128s = AesGcm::new_soft(&[1u8; 16]);
74 let chacha = ChaCha20Poly1305::new(&[2u8; 32]);
75 let mut seq = 0u64;
76 let mut nonce = || {
77 seq += 1;
78 let mut n = [0u8; 12];
79 n[4..].copy_from_slice(&seq.to_be_bytes());
80 n
81 };
82 let f1 = |n: &[u8; 12], b: &mut [u8]| gcm128.seal(n, &aad, b);
83 let f2 = |n: &[u8; 12], b: &mut [u8]| gcm256.seal(n, &aad, b);
84 let f3 = |n: &[u8; 12], b: &mut [u8]| gcm128s.seal(n, &aad, b);
85 let f4 = |n: &[u8; 12], b: &mut [u8]| chacha.seal(n, &aad, b);
86 let algs: [(&str, &dyn Fn(&[u8; 12], &mut [u8]) -> [u8; 16]); 4] =
87 [("AES-128-GCM", &f1), ("AES-256-GCM", &f2), ("AES-128-GCM (portable, bitsliced)", &f3), ("ChaCha20-Poly1305", &f4)];
88 for (name, f) in algs {
89 let size_d = if name.contains("portable") { d / 3 } else { d };
90 let a = rate(size_d, || {
91 black_box(f(&nonce(), &mut buf));
92 });
93 let b = rate(size_d, || {
94 black_box(f(&nonce(), &mut buf[..1400]));
95 });
96 println!("{:<34} {:>9.2} GB/s {:>7.2} GB/s", name, gbps(a, 16384), gbps(b, 1400));
97 }
98 let mut tag = [0u8; 16];
99 let n12 = [0u8; 12];
100 tag.copy_from_slice(&gcm128.seal(&n12, &aad, &mut buf));
101 let o = rate(d, || {
102 // open fails (buffer changed) but does the full work: GHASH, CTR, tag compare
103 black_box(gcm128.open(&n12, &aad, &mut buf, &tag));
104 });
105 println!("{:<34} {:>9.2} GB/s", "AES-128-GCM open", gbps(o, 16384));
106
107 println!();
108 println!("{:<34} {:>12}", "Primitive", "ops/s");
109 let sk = [7u8; 32];
110 let pk = x25519::x25519_base(&[9u8; 32]);
111 println!("{:<34} {:>12.0}", "X25519 key generation (table)", rate(d, || {
112 black_box(x25519::x25519_base(black_box(&sk)));
113 }));
114 println!("{:<34} {:>12.0}", "X25519 shared secret (ladder)", rate(d, || {
115 black_box(x25519::x25519(black_box(&sk), &pk));
116 }));
117 let d256 = p256::generate_private();
118 let q256 = p256::public_key(&p256::generate_private()).unwrap();
119 let h = [3u8; 32];
120 println!("{:<34} {:>12.0}", "P-256 key generation", rate(d, || {
121 black_box(p256::public_key(black_box(&d256)));
122 }));
123 println!("{:<34} {:>12.0}", "P-256 ECDH", rate(d, || {
124 black_box(p256::ecdh(black_box(&d256), &q256));
125 }));
126 let (r, s) = p256::sign(&d256, &h, simoom_tls::crypto::sha2::HashAlg::Sha256).unwrap();
127 let pub256 = p256::public_key(&d256).unwrap();
128 println!("{:<34} {:>12.0}", "ECDSA P-256 sign", rate(d, || {
129 black_box(p256::sign(black_box(&d256), &h, simoom_tls::crypto::sha2::HashAlg::Sha256));
130 }));
131 println!("{:<34} {:>12.0}", "ECDSA P-256 verify", rate(d, || {
132 black_box(p256::verify(&pub256, &h, &r, &s));
133 }));
134 let seed = [5u8; 32];
135 let edpub = simoom_tls::crypto::ed25519::public_key(&seed);
136 // as the server signs: the key's public half is known (OpenSSL keeps it in the key too)
137 println!("{:<34} {:>12.0}", "Ed25519 sign", rate(d, || {
138 black_box(simoom_tls::crypto::ed25519::sign_with_public(&seed, &edpub, b"message"));
139 }));
140 let edsig = simoom_tls::crypto::ed25519::sign(&seed, b"message");
141 println!("{:<34} {:>12.0}", "Ed25519 verify", rate(d, || {
142 black_box(simoom_tls::crypto::ed25519::verify(&edpub, b"message", &edsig));
143 }));
144 let rsa = PrivateKey::from_pem(include_bytes!("../testdata/rsa2048.pkcs1.pem")).unwrap();
145 if let PrivateKey::Rsa(k) = &rsa {
146 let dg = [1u8; 32];
147 println!("{:<34} {:>12.0}", "RSA-2048 PSS sign", rate(d, || {
148 black_box(k.sign_pss(simoom_tls::crypto::sha2::HashAlg::Sha256, &dg));
149 }));
150 let sig = k.sign_pss(simoom_tls::crypto::sha2::HashAlg::Sha256, &dg).unwrap();
151 println!("{:<34} {:>12.0}", "RSA-2048 PSS verify", rate(d, || {
152 black_box(k.public.verify_pss(simoom_tls::crypto::sha2::HashAlg::Sha256, &dg, &sig, Some(32)));
153 }));
154 }
155
156 // handshakes
157 let ss = certgen::issue(&CertParams::server(&["localhost"]), PrivateKey::generate_ec(EcCurve::P256), None);
158 let mut roots = RootStore::empty();
159 roots.add_der(&ss.cert_der).unwrap();
160 let mut scfg = ServerConfig::new(CertifiedKey::new(vec![ss.cert_der.clone()], ss.key.clone()).unwrap());
161 scfg.groups = vec![NamedGroup::X25519];
162 let scfg = Arc::new(scfg);
163 let mut cfull = ClientConfig::new(roots.clone());
164 cfull.sessions = None;
165 cfull.groups = vec![NamedGroup::X25519];
166 let cfull = Arc::new(cfull);
167 let mut cres = ClientConfig::new(roots);
168 cres.groups = vec![NamedGroup::X25519];
169 let cres = Arc::new(cres);
170
171 println!();
172 println!("{:<44} {:>12}", "TLS 1.3 handshake (X25519, ECDSA P-256 cert)", "per second");
173 let full = rate(d, || {
174 let mut c = ClientConnection::new(cfull.clone(), "localhost").unwrap();
175 let mut s = ServerConnection::new(scfg.clone());
176 pump(&mut c, &mut s);
177 assert!(!s.is_handshaking());
178 });
179 println!("{:<44} {:>12.0}", "full, client + server", full);
180 // server side only: replay a fresh ClientHello per iteration and time the server's work
181 let mut server_time = Duration::ZERO;
182 let mut n = 0u32;
183 let t0 = Instant::now();
184 while t0.elapsed() < d {
185 let mut c = ClientConnection::new(cfull.clone(), "localhost").unwrap();
186 let mut s = ServerConnection::new(scfg.clone());
187 let ch = c.tls_output().to_vec();
188 c.consume_tls_output(ch.len());
189 let t = Instant::now();
190 s.read_tls(&ch);
191 s.process_new_packets().unwrap();
192 server_time += t.elapsed();
193 let flight = s.tls_output().to_vec();
194 s.consume_tls_output(flight.len());
195 c.read_tls(&flight);
196 c.process_new_packets().unwrap();
197 let fin = c.tls_output().to_vec();
198 let t = Instant::now();
199 s.read_tls(&fin);
200 s.process_new_packets().unwrap();
201 server_time += t.elapsed();
202 n += 1;
203 }
204 println!("{:<44} {:>12.0}", "full, server side only", n as f64 / server_time.as_secs_f64());
205 // resumption: prime the cache, then each connection uses one ticket and stores a new one
206 let mut c = ClientConnection::new(cres.clone(), "localhost").unwrap();
207 let mut s = ServerConnection::new(scfg.clone());
208 pump(&mut c, &mut s);
209 let resumed = rate(d, || {
210 let mut c = ClientConnection::new(cres.clone(), "localhost").unwrap();
211 let mut s = ServerConnection::new(scfg.clone());
212 pump(&mut c, &mut s);
213 assert!(c.is_resumed());
214 });
215 println!("{:<44} {:>12.0}", "PSK-DHE resumption, client + server", resumed);
216
217 if openssl {
218 println!();
219 println!("openssl speed (same machine, single thread):");
220 for args in [
221 &["speed", "-seconds", "2", "-bytes", "16384", "-evp", "aes-128-gcm"][..],
222 &["speed", "-seconds", "2", "-bytes", "1400", "-evp", "aes-128-gcm"][..],
223 &["speed", "-seconds", "2", "-bytes", "16384", "-evp", "chacha20-poly1305"][..],
224 &["speed", "-seconds", "2", "-bytes", "1400", "-evp", "chacha20-poly1305"][..],
225 &["speed", "-seconds", "2", "ecdhx25519", "ecdhp256", "ecdsap256", "ed25519", "rsa2048"][..],
226 ] {
227 match std::process::Command::new("openssl").args(args).output() {
228 Ok(o) => {
229 let out = String::from_utf8_lossy(&o.stdout);
230 for line in out.lines().filter(|l| {
231 l.starts_with("AES-128-GCM") || l.starts_with("ChaCha20-Poly1305") || l.contains(" sign ") || l.contains("op/s") || l.starts_with("rsa") || l.contains("ecdh") || l.contains("ecdsa") || l.contains("Ed25519") || l.contains("type")
232 }) {
233 println!(" {line}");
234 }
235 }
236 Err(e) => println!(" openssl not available: {e}"),
237 }
238 }
239 }
240}Sourcepub fn from_pem(cert_pem: &[u8], key_pem: &[u8]) -> Result<ServerConfig>
pub fn from_pem(cert_pem: &[u8], key_pem: &[u8]) -> Result<ServerConfig>
From PEM certificate chain and key.
Examples found in repository?
12fn main() {
13 let args: Vec<String> = std::env::args().collect();
14 if args.len() < 3 {
15 eprintln!("usage: size_server CERT.pem KEY.pem < client_flight");
16 std::process::exit(2);
17 }
18 let cert = std::fs::read(&args[1]).expect("certificate");
19 let key = std::fs::read(&args[2]).expect("key");
20 let cfg = Arc::new(ServerConfig::from_pem(&cert, &key).expect("server config").with_alpn(&[b"h2", b"http/1.1"]));
21 let mut conn = ServerConnection::new(cfg);
22 let mut input = Vec::new();
23 std::io::stdin().read_to_end(&mut input).expect("stdin");
24 conn.read_tls(&input);
25 if let Err(e) = conn.process_new_packets() {
26 eprintln!("{e:?}");
27 }
28 let out = conn.tls_output().to_vec();
29 conn.consume_tls_output(out.len());
30 std::io::stdout().write_all(&out).expect("stdout");
31 let mut buf = [0u8; 1024];
32 let n = conn.read_plaintext(&mut buf);
33 std::io::stdout().write_all(&buf[..n]).expect("stdout");
34}More examples
15fn config(args: &[String]) -> ServerConfig {
16 let cert = std::fs::read(&args[1]).expect("certificate");
17 let key = std::fs::read(&args[2]).expect("key");
18 #[cfg(feature = "keystore")]
19 let mut cfg = {
20 let p = simoom_tls::params::SslContextParameters::new()
21 .key_pair_pem(&String::from_utf8_lossy(&cert), &String::from_utf8_lossy(&key))
22 .key_password(args.get(3).map(|s| s.as_str()).unwrap_or(""));
23 let p = match args.get(4) {
24 // a key store file instead (PKCS#12 / JKS / JCEKS, detected)
25 Some(ks) => simoom_tls::params::SslContextParameters::new().key_store(ks, args.get(3).map(|s| s.as_str()).unwrap_or("")),
26 None => p,
27 };
28 p.server_config().expect("server config")
29 };
30 #[cfg(not(feature = "keystore"))]
31 let mut cfg = ServerConfig::from_pem(&cert, &key).expect("server config");
32 #[cfg(feature = "revocation")]
33 {
34 let staple = simoom_tls::revocation::StapleSource::new();
35 if let Some(der) = args.get(5).and_then(|p| std::fs::read(p).ok()) {
36 staple.set(Some(der));
37 }
38 cfg.ocsp_staple = Some(staple);
39 if let Some(crl) = args.get(6).and_then(|p| std::fs::read(p).ok()) {
40 let mut pol = simoom_tls::revocation::RevocationPolicy::new();
41 pol.add_crls(&crl).expect("CRL");
42 cfg.client_revocation = Some(pol);
43 }
44 }
45 cfg.with_alpn(&[b"h2", b"http/1.1"])
46}Sourcepub fn add_sni_cert(&mut self, cert: CertifiedKey)
pub fn add_sni_cert(&mut self, cert: CertifiedKey)
Adds a certificate selected by SNI for every DNS name in its leaf (wildcards included).
Sourcepub fn with_alpn(self, protocols: &[&[u8]]) -> ServerConfig
pub fn with_alpn(self, protocols: &[&[u8]]) -> ServerConfig
Examples found in repository?
12fn main() {
13 let args: Vec<String> = std::env::args().collect();
14 if args.len() < 3 {
15 eprintln!("usage: size_server CERT.pem KEY.pem < client_flight");
16 std::process::exit(2);
17 }
18 let cert = std::fs::read(&args[1]).expect("certificate");
19 let key = std::fs::read(&args[2]).expect("key");
20 let cfg = Arc::new(ServerConfig::from_pem(&cert, &key).expect("server config").with_alpn(&[b"h2", b"http/1.1"]));
21 let mut conn = ServerConnection::new(cfg);
22 let mut input = Vec::new();
23 std::io::stdin().read_to_end(&mut input).expect("stdin");
24 conn.read_tls(&input);
25 if let Err(e) = conn.process_new_packets() {
26 eprintln!("{e:?}");
27 }
28 let out = conn.tls_output().to_vec();
29 conn.consume_tls_output(out.len());
30 std::io::stdout().write_all(&out).expect("stdout");
31 let mut buf = [0u8; 1024];
32 let n = conn.read_plaintext(&mut buf);
33 std::io::stdout().write_all(&buf[..n]).expect("stdout");
34}More examples
15fn config(args: &[String]) -> ServerConfig {
16 let cert = std::fs::read(&args[1]).expect("certificate");
17 let key = std::fs::read(&args[2]).expect("key");
18 #[cfg(feature = "keystore")]
19 let mut cfg = {
20 let p = simoom_tls::params::SslContextParameters::new()
21 .key_pair_pem(&String::from_utf8_lossy(&cert), &String::from_utf8_lossy(&key))
22 .key_password(args.get(3).map(|s| s.as_str()).unwrap_or(""));
23 let p = match args.get(4) {
24 // a key store file instead (PKCS#12 / JKS / JCEKS, detected)
25 Some(ks) => simoom_tls::params::SslContextParameters::new().key_store(ks, args.get(3).map(|s| s.as_str()).unwrap_or("")),
26 None => p,
27 };
28 p.server_config().expect("server config")
29 };
30 #[cfg(not(feature = "keystore"))]
31 let mut cfg = ServerConfig::from_pem(&cert, &key).expect("server config");
32 #[cfg(feature = "revocation")]
33 {
34 let staple = simoom_tls::revocation::StapleSource::new();
35 if let Some(der) = args.get(5).and_then(|p| std::fs::read(p).ok()) {
36 staple.set(Some(der));
37 }
38 cfg.ocsp_staple = Some(staple);
39 if let Some(crl) = args.get(6).and_then(|p| std::fs::read(p).ok()) {
40 let mut pol = simoom_tls::revocation::RevocationPolicy::new();
41 pol.add_crls(&crl).expect("CRL");
42 cfg.client_revocation = Some(pol);
43 }
44 }
45 cfg.with_alpn(&[b"h2", b"http/1.1"])
46}122pub fn corpus() -> Corpus {
123 let ss = certgen::issue(&CertParams::server(&["localhost"]), PrivateKey::generate_ec(EcCurve::P256), None);
124 let mut roots = RootStore::empty();
125 roots.add_der(&ss.cert_der).unwrap();
126 let scfg = Arc::new(ServerConfig::new(CertifiedKey::new(vec![ss.cert_der.clone()], ss.key.clone()).unwrap()).with_alpn(&[b"h3", b"http/1.1"]));
127 let mut cc = ClientConfig::new(roots).with_alpn(&[b"h3", b"http/1.1"]);
128 cc.sessions = None;
129 let ccfg = Arc::new(cc);
130 // a TLS handshake transcript
131 let mut c = ClientConnection::new(ccfg.clone(), "localhost").unwrap();
132 let mut s = ServerConnection::new(scfg.clone());
133 let ch = c.tls_output().to_vec();
134 c.consume_tls_output(ch.len());
135 s.read_tls(&ch);
136 s.process_new_packets().unwrap();
137 let flight = s.tls_output().to_vec();
138 let mut ch_plus = ch.clone();
139 ch_plus.extend_from_slice(&[20, 3, 3, 0, 1, 1, 23, 3, 3, 0, 20]);
140 ch_plus.extend(std::iter::repeat_n(0xaa, 20));
141 // a QUIC handshake: the ClientHello message and the server's Handshake-level flight
142 let mut qc = QuicConnection::new_client(ccfg.clone(), "localhost", vec![1, 2, 3]).unwrap();
143 let mut qs = QuicConnection::new_server(scfg.clone(), vec![4, 5, 6]);
144 let mut ch_msg = Vec::new();
145 qc.write_handshake(&mut ch_msg);
146 qs.read_handshake(Level::Initial, &ch_msg).unwrap();
147 let mut sh = Vec::new();
148 qs.write_handshake(&mut sh);
149 let mut hs = Vec::new();
150 qs.write_handshake(&mut hs);
151 Corpus {
152 scfg,
153 ccfg,
154 to_server: vec![ch, ch_plus],
155 to_client: vec![flight],
156 ch_msg,
157 server_hs_flight: hs,
158 key_der: ss.key_der.clone(),
159 cert_der: ss.cert_der,
160 }
161}