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::verify;
12 use crate::verify::ServerCertVerifier;
13 use crate::key;
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 Fsetup: Fn() -> S,
24           Ftest: Fn(S)
25 {
26     let mut times = Vec::new();
27 
28     for _ in 0..count {
29         let state = f_setup();
30         let start = Instant::now();
31         f_test(state);
32         times.push(duration_nanos(Instant::now().duration_since(start)));
33     }
34 
35     println!("{}: min {:?}us",
36              name,
37              times.iter().min().unwrap() / 1000);
38 }
39 
fixed_time() -> Result<webpki::Time, TLSError>40 fn fixed_time() -> Result<webpki::Time, TLSError> {
41     Ok(webpki::Time::from_seconds_since_unix_epoch(1500000000))
42 }
43 
44 static V: &'static verify::WebPKIVerifier = &verify::WebPKIVerifier {
45     time: fixed_time,
46 };
47 
48 #[test]
test_reddit_cert()49 fn test_reddit_cert() {
50     let cert0 = key::Certificate(include_bytes!("testdata/cert-reddit.0.der").to_vec());
51     let cert1 = key::Certificate(include_bytes!("testdata/cert-reddit.1.der").to_vec());
52     let chain = [ cert0, cert1 ];
53     let mut anchors = anchors::RootCertStore::empty();
54     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
55     bench(100, "verify_server_cert(reddit)",
56           || (),
57           |_| {
58         let dns_name = webpki::DNSNameRef::try_from_ascii_str("reddit.com")
59           .unwrap();
60         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
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(100, "verify_server_cert(github)",
72           || (),
73           |_| {
74         let dns_name = webpki::DNSNameRef::try_from_ascii_str("github.com")
75           .unwrap();
76         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
77     });
78 }
79 
80 #[test]
test_arstechnica_cert()81 fn test_arstechnica_cert() {
82     let cert0 = key::Certificate(include_bytes!("testdata/cert-arstechnica.0.der").to_vec());
83     let cert1 = key::Certificate(include_bytes!("testdata/cert-arstechnica.1.der").to_vec());
84     let cert2 = key::Certificate(include_bytes!("testdata/cert-arstechnica.2.der").to_vec());
85     let chain = [ cert0, cert1, cert2 ];
86     let mut anchors = anchors::RootCertStore::empty();
87     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
88     bench(100, "verify_server_cert(arstechnica)",
89           || (),
90           |_| {
91         let dns_name = webpki::DNSNameRef::try_from_ascii_str("arstechnica.com")
92             .unwrap();
93         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
94     });
95 }
96 
97 #[test]
test_servo_cert()98 fn test_servo_cert() {
99     let cert0 = key::Certificate(include_bytes!("testdata/cert-servo.0.der").to_vec());
100     let cert1 = key::Certificate(include_bytes!("testdata/cert-servo.1.der").to_vec());
101     let cert2 = key::Certificate(include_bytes!("testdata/cert-servo.2.der").to_vec());
102     let chain = [ cert0, cert1, cert2 ];
103     let mut anchors = anchors::RootCertStore::empty();
104     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
105     bench(100, "verify_server_cert(servo)",
106           || (),
107           |_| {
108         let dns_name = webpki::DNSNameRef::try_from_ascii_str("servo.org")
109             .unwrap();
110         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
111     });
112 }
113 
114 #[test]
test_twitter_cert()115 fn test_twitter_cert() {
116     let cert0 = key::Certificate(include_bytes!("testdata/cert-twitter.0.der").to_vec());
117     let cert1 = key::Certificate(include_bytes!("testdata/cert-twitter.1.der").to_vec());
118     let chain = [ cert0, cert1 ];
119     let mut anchors = anchors::RootCertStore::empty();
120     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
121     bench(100, "verify_server_cert(twitter)",
122           || (),
123           |_| {
124         let dns_name = webpki::DNSNameRef::try_from_ascii_str("twitter.com")
125             .unwrap();
126         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap(); });
127 }
128 
129 #[test]
test_wikipedia_cert()130 fn test_wikipedia_cert() {
131     let cert0 = key::Certificate(include_bytes!("testdata/cert-wikipedia.0.der").to_vec());
132     let cert1 = key::Certificate(include_bytes!("testdata/cert-wikipedia.1.der").to_vec());
133     let chain = [ cert0, cert1 ];
134     let mut anchors = anchors::RootCertStore::empty();
135     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
136     bench(100, "verify_server_cert(wikipedia)",
137           || (),
138           |_| {
139         let dns_name = webpki::DNSNameRef::try_from_ascii_str("wikipedia.org")
140             .unwrap();
141         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
142     });
143 }
144 
145 #[test]
test_google_cert()146 fn test_google_cert() {
147     let cert0 = key::Certificate(include_bytes!("testdata/cert-google.0.der").to_vec());
148     let cert1 = key::Certificate(include_bytes!("testdata/cert-google.1.der").to_vec());
149     let cert2 = key::Certificate(include_bytes!("testdata/cert-google.2.der").to_vec());
150     let chain = [ cert0, cert1, cert2 ];
151     let mut anchors = anchors::RootCertStore::empty();
152     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
153     bench(100, "verify_server_cert(google)",
154           || (),
155           |_| {
156         let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.google.com")
157             .unwrap();
158         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
159     });
160 }
161 
162 #[test]
test_hn_cert()163 fn test_hn_cert() {
164     let cert0 = key::Certificate(include_bytes!("testdata/cert-hn.0.der").to_vec());
165     let cert1 = key::Certificate(include_bytes!("testdata/cert-hn.1.der").to_vec());
166     let cert2 = key::Certificate(include_bytes!("testdata/cert-hn.2.der").to_vec());
167     let chain = [ cert0, cert1, cert2 ];
168     let mut anchors = anchors::RootCertStore::empty();
169     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
170     bench(100, "verify_server_cert(hn)",
171           || (),
172           |_| {
173         let dns_name = webpki::DNSNameRef::try_from_ascii_str("news.ycombinator.com")
174             .unwrap();
175         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
176     });
177 }
178 
179 #[test]
test_stackoverflow_cert()180 fn test_stackoverflow_cert() {
181     let cert0 = key::Certificate(include_bytes!("testdata/cert-stackoverflow.0.der").to_vec());
182     let cert1 = key::Certificate(include_bytes!("testdata/cert-stackoverflow.1.der").to_vec());
183     let chain = [ cert0, cert1 ];
184     let mut anchors = anchors::RootCertStore::empty();
185     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
186     bench(100, "verify_server_cert(stackoverflow)",
187           || (),
188           |_| {
189         let dns_name = webpki::DNSNameRef::try_from_ascii_str("stackoverflow.com")
190           .unwrap();
191         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
192     });
193 }
194 
195 #[test]
test_duckduckgo_cert()196 fn test_duckduckgo_cert() {
197     let cert0 = key::Certificate(include_bytes!("testdata/cert-duckduckgo.0.der").to_vec());
198     let cert1 = key::Certificate(include_bytes!("testdata/cert-duckduckgo.1.der").to_vec());
199     let chain = [ cert0, cert1 ];
200     let mut anchors = anchors::RootCertStore::empty();
201     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
202     bench(100, "verify_server_cert(duckduckgo)",
203           || (),
204           |_| {
205         let dns_name = webpki::DNSNameRef::try_from_ascii_str("duckduckgo.com")
206             .unwrap();
207         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
208     });
209 }
210 
211 #[test]
test_rustlang_cert()212 fn test_rustlang_cert() {
213     let cert0 = key::Certificate(include_bytes!("testdata/cert-rustlang.0.der").to_vec());
214     let cert1 = key::Certificate(include_bytes!("testdata/cert-rustlang.1.der").to_vec());
215     let cert2 = key::Certificate(include_bytes!("testdata/cert-rustlang.2.der").to_vec());
216     let chain = [ cert0, cert1, cert2 ];
217     let mut anchors = anchors::RootCertStore::empty();
218     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
219     bench(100, "verify_server_cert(rustlang)",
220           || (),
221           |_| {
222         let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.rust-lang.org")
223             .unwrap();
224         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
225     });
226 }
227 
228 #[test]
test_wapo_cert()229 fn test_wapo_cert() {
230     let cert0 = key::Certificate(include_bytes!("testdata/cert-wapo.0.der").to_vec());
231     let cert1 = key::Certificate(include_bytes!("testdata/cert-wapo.1.der").to_vec());
232     let cert2 = key::Certificate(include_bytes!("testdata/cert-wapo.2.der").to_vec());
233     let chain = [ cert0, cert1, cert2 ];
234     let mut anchors = anchors::RootCertStore::empty();
235     anchors.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
236     bench(100, "verify_server_cert(wapo)",
237           || (),
238           |_| {
239         let dns_name = webpki::DNSNameRef::try_from_ascii_str("www.washingtonpost.com")
240             .unwrap();
241         V.verify_server_cert(&anchors, &chain[..], dns_name, &[]).unwrap();
242     });
243 }
244 
245