pub struct RootStore { /* private fields */ }Expand description
A set of trust anchors.
Implementations§
Source§impl RootStore
impl RootStore
Sourcepub fn empty() -> RootStore
pub fn empty() -> RootStore
Examples found in repository?
examples/../tests/fuzzing/mod.rs (line 124)
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}
162
163/// Feeds `data` in random-sized pieces and processes after each; checks that errors stick.
164fn feed(rng: &mut Rng, conn: &mut simoom_tls::Connection, data: &[u8]) {
165 let mut off = 0;
166 while off < data.len() {
167 let k = 1 + rng.below(data.len() - off);
168 let taken = conn.read_tls(&data[off..off + k]);
169 off += taken;
170 let r = conn.process_new_packets();
171 if let Err(e) = r {
172 assert_eq!(conn.process_new_packets().unwrap_err(), e, "errors must stick");
173 assert!(conn.tls_output().len() < 64 * 1024, "output stays bounded");
174 assert!(conn.write_plaintext(b"x").is_err(), "a failed connection refuses writes");
175 return;
176 }
177 if taken == 0 {
178 // buffer full: the application reads plaintext
179 let n = conn.plaintext().len();
180 if n == 0 {
181 return;
182 }
183 conn.consume_plaintext(n);
184 }
185 }
186}
187
188pub fn server_records(rng: &mut Rng, c: &Corpus, iters: usize) {
189 for _ in 0..iters {
190 let seed = &c.to_server[rng.below(c.to_server.len())];
191 let data = mutate(rng, seed, &c.to_client);
192 let mut s = ServerConnection::new(c.scfg.clone());
193 feed(rng, &mut s, &data);
194 }
195}
196
197pub fn client_records(rng: &mut Rng, c: &Corpus, iters: usize) {
198 for _ in 0..iters {
199 let data = mutate(rng, &c.to_client[0], &c.to_server);
200 let mut cl = ClientConnection::new(c.ccfg.clone(), "localhost").unwrap();
201 let n = cl.tls_output().len();
202 cl.consume_tls_output(n);
203 feed(rng, &mut cl, &data);
204 }
205}
206
207/// ClientHello parsing (and everything the server does with it) without the record layer.
208pub fn quic_server_messages(rng: &mut Rng, c: &Corpus, iters: usize) {
209 for _ in 0..iters {
210 let m = mutate(rng, &c.ch_msg, &[]);
211 let mut s = QuicConnection::new_server(c.scfg.clone(), vec![9]);
212 if s.read_handshake(Level::Initial, &m).is_err() {
213 assert!(s.tls_alert().is_some());
214 }
215 let mut out = Vec::new();
216 while s.write_handshake(&mut out).is_some() {}
217 }
218}
219
220/// EncryptedExtensions, Certificate (X.509), CertificateVerify and Finished parsing on the
221/// client: a real ServerHello, then a mutated Handshake-level flight.
222pub fn quic_client_messages(rng: &mut Rng, c: &Corpus, iters: usize) {
223 for _ in 0..iters {
224 let mut qc = QuicConnection::new_client(c.ccfg.clone(), "localhost", vec![1]).unwrap();
225 let mut qs = QuicConnection::new_server(c.scfg.clone(), vec![2]);
226 let mut ch = Vec::new();
227 qc.write_handshake(&mut ch);
228 qs.read_handshake(Level::Initial, &ch).unwrap();
229 let mut sh = Vec::new();
230 qs.write_handshake(&mut sh);
231 let mut hs = Vec::new();
232 qs.write_handshake(&mut hs);
233 qc.read_handshake(Level::Initial, &sh).unwrap();
234 let mut ignore = Vec::new();
235 qc.write_handshake(&mut ignore);
236 let m = mutate(rng, &hs, &[c.cert_der.clone()]);
237 let _ = qc.read_handshake(Level::Handshake, &m);
238 }
239}
240
241pub fn x509_and_keys(rng: &mut Rng, c: &Corpus, iters: usize) {
242 let mut roots = RootStore::empty();
243 roots.add_der(&c.cert_der).unwrap();
244 for _ in 0..iters {
245 let d = mutate(rng, &c.cert_der, &[]);
246 if let Ok(cert) = Certificate::from_der(&d) {
247 let _ = cert.matches_hostname("localhost");
248 }
249 let _ = x509::verify_chain(&[d], Some("localhost"), &roots, 1_800_000_000, x509::OID_EKU_SERVER_AUTH);
250 let k = mutate(rng, &c.key_der, &[]);
251 let _ = PrivateKey::from_der(&k);
252 let pem = simoom_tls::pem::encode_pem("PRIVATE KEY", &k);
253 let p = mutate(rng, pem.as_bytes(), &[]);
254 let _ = PrivateKey::from_pem(&p);
255 }
256}More examples
examples/bench_tls.rs (line 158)
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 system() -> RootStore
pub fn system() -> RootStore
The system trust store (SSL_CERT_FILE, else the first existing bundle in
SYSTEM_BUNDLE_PATHS, else the Windows ROOT certificate store; macOS is covered by
/etc/ssl/cert.pem); loaded once per process. Certificates that fail to parse are
skipped.
Sourcepub fn add_pem(&mut self, data: &[u8]) -> Result<usize, String>
pub fn add_pem(&mut self, data: &[u8]) -> Result<usize, String>
Adds every certificate in PEM text; fails if any block is malformed or none found.
pub fn add_pem_file(&mut self, path: impl AsRef<Path>) -> Result<usize, String>
Sourcepub fn add_der(&mut self, der: &[u8]) -> Result<(), String>
pub fn add_der(&mut self, der: &[u8]) -> Result<(), String>
Examples found in repository?
examples/../tests/fuzzing/mod.rs (line 125)
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}
162
163/// Feeds `data` in random-sized pieces and processes after each; checks that errors stick.
164fn feed(rng: &mut Rng, conn: &mut simoom_tls::Connection, data: &[u8]) {
165 let mut off = 0;
166 while off < data.len() {
167 let k = 1 + rng.below(data.len() - off);
168 let taken = conn.read_tls(&data[off..off + k]);
169 off += taken;
170 let r = conn.process_new_packets();
171 if let Err(e) = r {
172 assert_eq!(conn.process_new_packets().unwrap_err(), e, "errors must stick");
173 assert!(conn.tls_output().len() < 64 * 1024, "output stays bounded");
174 assert!(conn.write_plaintext(b"x").is_err(), "a failed connection refuses writes");
175 return;
176 }
177 if taken == 0 {
178 // buffer full: the application reads plaintext
179 let n = conn.plaintext().len();
180 if n == 0 {
181 return;
182 }
183 conn.consume_plaintext(n);
184 }
185 }
186}
187
188pub fn server_records(rng: &mut Rng, c: &Corpus, iters: usize) {
189 for _ in 0..iters {
190 let seed = &c.to_server[rng.below(c.to_server.len())];
191 let data = mutate(rng, seed, &c.to_client);
192 let mut s = ServerConnection::new(c.scfg.clone());
193 feed(rng, &mut s, &data);
194 }
195}
196
197pub fn client_records(rng: &mut Rng, c: &Corpus, iters: usize) {
198 for _ in 0..iters {
199 let data = mutate(rng, &c.to_client[0], &c.to_server);
200 let mut cl = ClientConnection::new(c.ccfg.clone(), "localhost").unwrap();
201 let n = cl.tls_output().len();
202 cl.consume_tls_output(n);
203 feed(rng, &mut cl, &data);
204 }
205}
206
207/// ClientHello parsing (and everything the server does with it) without the record layer.
208pub fn quic_server_messages(rng: &mut Rng, c: &Corpus, iters: usize) {
209 for _ in 0..iters {
210 let m = mutate(rng, &c.ch_msg, &[]);
211 let mut s = QuicConnection::new_server(c.scfg.clone(), vec![9]);
212 if s.read_handshake(Level::Initial, &m).is_err() {
213 assert!(s.tls_alert().is_some());
214 }
215 let mut out = Vec::new();
216 while s.write_handshake(&mut out).is_some() {}
217 }
218}
219
220/// EncryptedExtensions, Certificate (X.509), CertificateVerify and Finished parsing on the
221/// client: a real ServerHello, then a mutated Handshake-level flight.
222pub fn quic_client_messages(rng: &mut Rng, c: &Corpus, iters: usize) {
223 for _ in 0..iters {
224 let mut qc = QuicConnection::new_client(c.ccfg.clone(), "localhost", vec![1]).unwrap();
225 let mut qs = QuicConnection::new_server(c.scfg.clone(), vec![2]);
226 let mut ch = Vec::new();
227 qc.write_handshake(&mut ch);
228 qs.read_handshake(Level::Initial, &ch).unwrap();
229 let mut sh = Vec::new();
230 qs.write_handshake(&mut sh);
231 let mut hs = Vec::new();
232 qs.write_handshake(&mut hs);
233 qc.read_handshake(Level::Initial, &sh).unwrap();
234 let mut ignore = Vec::new();
235 qc.write_handshake(&mut ignore);
236 let m = mutate(rng, &hs, &[c.cert_der.clone()]);
237 let _ = qc.read_handshake(Level::Handshake, &m);
238 }
239}
240
241pub fn x509_and_keys(rng: &mut Rng, c: &Corpus, iters: usize) {
242 let mut roots = RootStore::empty();
243 roots.add_der(&c.cert_der).unwrap();
244 for _ in 0..iters {
245 let d = mutate(rng, &c.cert_der, &[]);
246 if let Ok(cert) = Certificate::from_der(&d) {
247 let _ = cert.matches_hostname("localhost");
248 }
249 let _ = x509::verify_chain(&[d], Some("localhost"), &roots, 1_800_000_000, x509::OID_EKU_SERVER_AUTH);
250 let k = mutate(rng, &c.key_der, &[]);
251 let _ = PrivateKey::from_der(&k);
252 let pem = simoom_tls::pem::encode_pem("PRIVATE KEY", &k);
253 let p = mutate(rng, pem.as_bytes(), &[]);
254 let _ = PrivateKey::from_pem(&p);
255 }
256}More examples
examples/bench_tls.rs (line 159)
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}pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
pub fn extend(&mut self, other: &RootStore)
Sourcepub fn certificates(&self) -> impl Iterator<Item = &Certificate>
pub fn certificates(&self) -> impl Iterator<Item = &Certificate>
The trust anchors.
Trait Implementations§
Auto Trait Implementations§
impl Forget for RootStore
impl Freeze for RootStore
impl Move for RootStore
impl RefUnwindSafe for RootStore
impl Send for RootStore
impl Sync for RootStore
impl Unpin for RootStore
impl UnsafeUnpin for RootStore
impl UnwindSafe for RootStore
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more