1 // This program does benchmarking of the functions in verify.rs,
2 // that do certificate chain validation and signature verification.
3 //
4 // Note: we don't use any of the standard 'cargo bench', 'test::Bencher',
5 // etc. because it's unstable at the time of writing.
6 
7 use std::time::{Duration, Instant};
8 
9 use crate::anchors;
10 use crate::error::TLSError;
11 use crate::key;
12 use crate::verify;
13 use crate::verify::ServerCertVerifier;
14 use webpki;
15 
16 use webpki_roots;
17 
duration_nanos(d: Duration) -> u6418 fn duration_nanos(d: Duration) -> u64 {
19     ((d.as_secs() as f64) * 1e9 + (d.subsec_nanos() as f64)) as u64
20 }
21 
bench<Fsetup, Ftest, S>(count: usize, name: &'static str, f_setup: Fsetup, f_test: Ftest) where Fsetup: Fn() -> S, Ftest: Fn(S),22 fn bench<Fsetup, Ftest, S>(count: usize, name: &'static str, f_setup: Fsetup, f_test: Ftest)
23 where
24     Fsetup: Fn() -> S,
25     Ftest: Fn(S),
26 {
27     let mut times = Vec::new();
28 
29     for _ in 0..count {
30         let state = f_setup();
31         let start = Instant::now();
32         f_test(state);
33         times.push(duration_nanos(Instant::now().duration_since(start)));
34     }
35 
36     println!("{}: min {:?}us", name, times.iter().min().unwrap() / 1000);
37 }
38 
fixed_time() -> Result<webpki::Time, TLSError>39 fn fixed_time() -> Result<webpki::Time, TLSError> {
40     Ok(webpki::Time::from_seconds_since_unix_epoch(1500000000))
41 }
42 
43 static V: &'static verify::WebPKIVerifier = &verify::WebPKIVerifier { time: fixed_time };
44 
45 #[test]
test_reddit_cert()46 fn test_reddit_cert() {
47     let cert0 = key::Certificate(include_bytes!("testdata/cert-reddit.0.der").to_vec());
48     let cert1 = key::Certificate(include_bytes!("testdata/cert-reddit.1.der").to_vec());
49     let chain = [cert0, cert1];
50     let mut anchors = anchors::RootCertStore::empty();
51     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
52     bench(
53         100,
54         "verify_server_cert(reddit)",
55         || (),
56         |_| {
57             let dns_name = webpki::DNSNameRef::try_from_ascii_str("reddit.com").unwrap();
58             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
59                 .unwrap();
60         },
61     );
62 }
63 
64 #[test]
test_github_cert()65 fn test_github_cert() {
66     let cert0 = key::Certificate(include_bytes!("testdata/cert-github.0.der").to_vec());
67     let cert1 = key::Certificate(include_bytes!("testdata/cert-github.1.der").to_vec());
68     let chain = [cert0, cert1];
69     let mut anchors = anchors::RootCertStore::empty();
70     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
71     bench(
72         100,
73         "verify_server_cert(github)",
74         || (),
75         |_| {
76             let dns_name = webpki::DNSNameRef::try_from_ascii_str("github.com").unwrap();
77             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
78                 .unwrap();
79         },
80     );
81 }
82 
83 #[test]
test_arstechnica_cert()84 fn test_arstechnica_cert() {
85     let cert0 = key::Certificate(include_bytes!("testdata/cert-arstechnica.0.der").to_vec());
86     let cert1 = key::Certificate(include_bytes!("testdata/cert-arstechnica.1.der").to_vec());
87     let cert2 = key::Certificate(include_bytes!("testdata/cert-arstechnica.2.der").to_vec());
88     let chain = [cert0, cert1, cert2];
89     let mut anchors = anchors::RootCertStore::empty();
90     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
91     bench(
92         100,
93         "verify_server_cert(arstechnica)",
94         || (),
95         |_| {
96             let dns_name = webpki::DNSNameRef::try_from_ascii_str("arstechnica.com").unwrap();
97             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
98                 .unwrap();
99         },
100     );
101 }
102 
103 #[test]
test_servo_cert()104 fn test_servo_cert() {
105     let cert0 = key::Certificate(include_bytes!("testdata/cert-servo.0.der").to_vec());
106     let cert1 = key::Certificate(include_bytes!("testdata/cert-servo.1.der").to_vec());
107     let cert2 = key::Certificate(include_bytes!("testdata/cert-servo.2.der").to_vec());
108     let chain = [cert0, cert1, cert2];
109     let mut anchors = anchors::RootCertStore::empty();
110     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
111     bench(
112         100,
113         "verify_server_cert(servo)",
114         || (),
115         |_| {
116             let dns_name = webpki::DNSNameRef::try_from_ascii_str("servo.org").unwrap();
117             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
118                 .unwrap();
119         },
120     );
121 }
122 
123 #[test]
test_twitter_cert()124 fn test_twitter_cert() {
125     let cert0 = key::Certificate(include_bytes!("testdata/cert-twitter.0.der").to_vec());
126     let cert1 = key::Certificate(include_bytes!("testdata/cert-twitter.1.der").to_vec());
127     let chain = [cert0, cert1];
128     let mut anchors = anchors::RootCertStore::empty();
129     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
130     bench(
131         100,
132         "verify_server_cert(twitter)",
133         || (),
134         |_| {
135             let dns_name = webpki::DNSNameRef::try_from_ascii_str("twitter.com").unwrap();
136             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
137                 .unwrap();
138         },
139     );
140 }
141 
142 #[test]
test_wikipedia_cert()143 fn test_wikipedia_cert() {
144     let cert0 = key::Certificate(include_bytes!("testdata/cert-wikipedia.0.der").to_vec());
145     let cert1 = key::Certificate(include_bytes!("testdata/cert-wikipedia.1.der").to_vec());
146     let chain = [cert0, cert1];
147     let mut anchors = anchors::RootCertStore::empty();
148     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
149     bench(
150         100,
151         "verify_server_cert(wikipedia)",
152         || (),
153         |_| {
154             let dns_name = webpki::DNSNameRef::try_from_ascii_str("wikipedia.org").unwrap();
155             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
156                 .unwrap();
157         },
158     );
159 }
160 
161 #[test]
test_google_cert()162 fn test_google_cert() {
163     let cert0 = key::Certificate(include_bytes!("testdata/cert-google.0.der").to_vec());
164     let cert1 = key::Certificate(include_bytes!("testdata/cert-google.1.der").to_vec());
165     let cert2 = key::Certificate(include_bytes!("testdata/cert-google.2.der").to_vec());
166     let chain = [cert0, cert1, cert2];
167     let mut anchors = anchors::RootCertStore::empty();
168     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
169     bench(
170         100,
171         "verify_server_cert(google)",
172         || (),
173         |_| {
174             let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.google.com").unwrap();
175             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
176                 .unwrap();
177         },
178     );
179 }
180 
181 #[test]
test_hn_cert()182 fn test_hn_cert() {
183     let cert0 = key::Certificate(include_bytes!("testdata/cert-hn.0.der").to_vec());
184     let cert1 = key::Certificate(include_bytes!("testdata/cert-hn.1.der").to_vec());
185     let cert2 = key::Certificate(include_bytes!("testdata/cert-hn.2.der").to_vec());
186     let chain = [cert0, cert1, cert2];
187     let mut anchors = anchors::RootCertStore::empty();
188     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
189     bench(
190         100,
191         "verify_server_cert(hn)",
192         || (),
193         |_| {
194             let dns_name = webpki::DNSNameRef::try_from_ascii_str("news.ycombinator.com").unwrap();
195             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
196                 .unwrap();
197         },
198     );
199 }
200 
201 #[test]
test_stackoverflow_cert()202 fn test_stackoverflow_cert() {
203     let cert0 = key::Certificate(include_bytes!("testdata/cert-stackoverflow.0.der").to_vec());
204     let cert1 = key::Certificate(include_bytes!("testdata/cert-stackoverflow.1.der").to_vec());
205     let chain = [cert0, cert1];
206     let mut anchors = anchors::RootCertStore::empty();
207     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
208     bench(
209         100,
210         "verify_server_cert(stackoverflow)",
211         || (),
212         |_| {
213             let dns_name = webpki::DNSNameRef::try_from_ascii_str("stackoverflow.com").unwrap();
214             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
215                 .unwrap();
216         },
217     );
218 }
219 
220 #[test]
test_duckduckgo_cert()221 fn test_duckduckgo_cert() {
222     let cert0 = key::Certificate(include_bytes!("testdata/cert-duckduckgo.0.der").to_vec());
223     let cert1 = key::Certificate(include_bytes!("testdata/cert-duckduckgo.1.der").to_vec());
224     let chain = [cert0, cert1];
225     let mut anchors = anchors::RootCertStore::empty();
226     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
227     bench(
228         100,
229         "verify_server_cert(duckduckgo)",
230         || (),
231         |_| {
232             let dns_name = webpki::DNSNameRef::try_from_ascii_str("duckduckgo.com").unwrap();
233             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
234                 .unwrap();
235         },
236     );
237 }
238 
239 #[test]
test_rustlang_cert()240 fn test_rustlang_cert() {
241     let cert0 = key::Certificate(include_bytes!("testdata/cert-rustlang.0.der").to_vec());
242     let cert1 = key::Certificate(include_bytes!("testdata/cert-rustlang.1.der").to_vec());
243     let cert2 = key::Certificate(include_bytes!("testdata/cert-rustlang.2.der").to_vec());
244     let chain = [cert0, cert1, cert2];
245     let mut anchors = anchors::RootCertStore::empty();
246     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
247     bench(
248         100,
249         "verify_server_cert(rustlang)",
250         || (),
251         |_| {
252             let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.rust-lang.org").unwrap();
253             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
254                 .unwrap();
255         },
256     );
257 }
258 
259 #[test]
test_wapo_cert()260 fn test_wapo_cert() {
261     let cert0 = key::Certificate(include_bytes!("testdata/cert-wapo.0.der").to_vec());
262     let cert1 = key::Certificate(include_bytes!("testdata/cert-wapo.1.der").to_vec());
263     let cert2 = key::Certificate(include_bytes!("testdata/cert-wapo.2.der").to_vec());
264     let chain = [cert0, cert1, cert2];
265     let mut anchors = anchors::RootCertStore::empty();
266     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
267     bench(
268         100,
269         "verify_server_cert(wapo)",
270         || (),
271         |_| {
272             let dns_name =
273                 webpki::DNSNameRef::try_from_ascii_str("www.washingtonpost.com").unwrap();
274             V.verify_server_cert(&anchors, &chain[..], dns_name, &[])
275                 .unwrap();
276         },
277     );
278 }
279