Skip to content

Commit 22725b9

Browse files
cpucomplexspaces
authored andcommitted
tests: use fixed SystemTime for certificate validation
Fixing the `SystemTime` that we pass to the certificate verifier for the mock and real world verification tests will ensure that the tests don't start to fail just because the vendored certificates have expired.
1 parent 65b2a97 commit 22725b9

File tree

4 files changed

+49
-12
lines changed

4 files changed

+49
-12
lines changed

rustls-platform-verifier/src/tests/mod.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pub mod ffi;
33

44
use std::error::Error as StdError;
5+
use std::time::{Duration, SystemTime};
56

67
mod verification_real_world;
78

@@ -19,6 +20,9 @@ struct TestCase<'a, E: StdError> {
1920
/// The stapled OCSP response given to us by Rustls, if any.
2021
pub stapled_ocsp: Option<&'a [u8]>,
2122

23+
/// The time to use as the current time for verification.
24+
pub verification_time: SystemTime,
25+
2226
pub expected_result: Result<(), TlsError>,
2327

2428
/// An error that should be present inside an expected `CertificateError::Other` variant.
@@ -46,3 +50,13 @@ pub fn assert_cert_error_eq<E: StdError + PartialEq + 'static>(
4650
assert_eq!(result, expected);
4751
}
4852
}
53+
54+
/// Return a fixed [SystemTime] for certificate validation purposes.
55+
///
56+
/// We fix the "now" value used for certificate validation to a fixed point in time at which
57+
/// we know the test certificates are valid. This must be updated if the mock certificates
58+
/// are regenerated.
59+
pub(crate) fn verification_time() -> SystemTime {
60+
// Wednesday, January 3, 2024 6:03:08 PM UTC
61+
SystemTime::UNIX_EPOCH + Duration::from_secs(1_704_304_988)
62+
}

rustls-platform-verifier/src/tests/verification_mock/ca.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
// Generates the test data files used in the tests in verification_mock.rs.
22
//
3+
// After re-generating mock certificates be sure to also update the fixed
4+
// verification timestamp in `mod.rs`'s `verification_time` fn to match
5+
// the current time.
6+
//
37
// The primary point of this program is to fully automate the creation of the
48
// test data, with minimal tool dependencies (e.g. no OpenSSL), with low effort.
59
//

rustls-platform-verifier/src/tests/verification_mock/mod.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
))]
2222

2323
use super::TestCase;
24-
use crate::tests::assert_cert_error_eq;
24+
use crate::tests::{assert_cert_error_eq, verification_time};
2525
use crate::verification::{EkuError, Verifier};
2626
use rustls::{client::ServerCertVerifier, CertificateError, Error as TlsError};
2727
use std::convert::TryFrom;
@@ -95,7 +95,7 @@ pub(super) fn verification_without_mock_root() {
9595
&server_name,
9696
&mut std::iter::empty(),
9797
&[],
98-
std::time::SystemTime::now(),
98+
verification_time(),
9999
);
100100

101101
assert_eq!(
@@ -120,41 +120,47 @@ mock_root_test_cases! {
120120
reference_id: EXAMPLE_COM,
121121
chain: &[ROOT1_INT1_EXAMPLE_COM_GOOD, ROOT1_INT1],
122122
stapled_ocsp: None,
123+
verification_time: verification_time(),
123124
expected_result: Ok(()),
124125
other_error: no_error!(),
125126
},
126127
valid_no_stapling_ipv4 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
127128
reference_id: LOCALHOST_IPV4,
128129
chain: &[ROOT1_INT1_LOCALHOST_IPV4_GOOD, ROOT1_INT1],
129130
stapled_ocsp: None,
131+
verification_time: verification_time(),
130132
expected_result: Ok(()),
131133
other_error: no_error!(),
132134
},
133135
valid_no_stapling_ipv6 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
134136
reference_id: LOCALHOST_IPV6,
135137
chain: &[ROOT1_INT1_LOCALHOST_IPV6_GOOD, ROOT1_INT1],
136138
stapled_ocsp: None,
139+
verification_time: verification_time(),
137140
expected_result: Ok(()),
138141
other_error: no_error!(),
139142
},
140143
valid_stapled_good_dns [ any(windows, target_os = "android", target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
141144
reference_id: EXAMPLE_COM,
142145
chain: &[ROOT1_INT1_EXAMPLE_COM_GOOD, ROOT1_INT1],
143146
stapled_ocsp: Some(include_bytes!("root1-int1-ee_example.com-good.ocsp")),
147+
verification_time: verification_time(),
144148
expected_result: Ok(()),
145149
other_error: no_error!(),
146150
},
147151
valid_stapled_good_ipv4 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
148152
reference_id: LOCALHOST_IPV4,
149153
chain: &[ROOT1_INT1_LOCALHOST_IPV4_GOOD, ROOT1_INT1],
150154
stapled_ocsp: Some(include_bytes!("root1-int1-ee_127.0.0.1-good.ocsp")),
155+
verification_time: verification_time(),
151156
expected_result: Ok(()),
152157
other_error: no_error!(),
153158
},
154159
valid_stapled_good_ipv6 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
155160
reference_id: LOCALHOST_IPV6,
156161
chain: &[ROOT1_INT1_LOCALHOST_IPV6_GOOD, ROOT1_INT1],
157162
stapled_ocsp: Some(include_bytes!("root1-int1-ee_1-good.ocsp")),
163+
verification_time: verification_time(),
158164
expected_result: Ok(()),
159165
other_error: no_error!(),
160166
},
@@ -166,20 +172,23 @@ mock_root_test_cases! {
166172
reference_id: EXAMPLE_COM,
167173
chain: &[include_bytes!("root1-int1-ee_example.com-revoked.crt"), ROOT1_INT1],
168174
stapled_ocsp: Some(include_bytes!("root1-int1-ee_example.com-revoked.ocsp")),
175+
verification_time: verification_time(),
169176
expected_result: Err(TlsError::InvalidCertificate(CertificateError::Revoked)),
170177
other_error: no_error!(),
171178
},
172179
stapled_revoked_ipv4 [ any(windows, target_os = "android", target_os = "macos") ] => TestCase {
173180
reference_id: LOCALHOST_IPV4,
174181
chain: &[include_bytes!("root1-int1-ee_127.0.0.1-revoked.crt"), ROOT1_INT1],
175182
stapled_ocsp: Some(include_bytes!("root1-int1-ee_127.0.0.1-revoked.ocsp")),
183+
verification_time: verification_time(),
176184
expected_result: Err(TlsError::InvalidCertificate(CertificateError::Revoked)),
177185
other_error: no_error!(),
178186
},
179187
stapled_revoked_ipv6 [ any(windows, target_os = "android", target_os = "macos") ] => TestCase {
180188
reference_id: LOCALHOST_IPV6,
181189
chain: &[include_bytes!("root1-int1-ee_1-revoked.crt"), ROOT1_INT1],
182190
stapled_ocsp: Some(include_bytes!("root1-int1-ee_1-revoked.ocsp")),
191+
verification_time: verification_time(),
183192
expected_result: Err(TlsError::InvalidCertificate(CertificateError::Revoked)),
184193
other_error: no_error!(),
185194
},
@@ -192,20 +201,23 @@ mock_root_test_cases! {
192201
reference_id: EXAMPLE_COM,
193202
chain: &[ROOT1_INT1_EXAMPLE_COM_GOOD],
194203
stapled_ocsp: None,
204+
verification_time: verification_time(),
195205
expected_result: Err(TlsError::InvalidCertificate(CertificateError::UnknownIssuer)),
196206
other_error: no_error!(),
197207
},
198208
ee_only_ipv4 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
199209
reference_id: LOCALHOST_IPV4,
200210
chain: &[ROOT1_INT1_LOCALHOST_IPV4_GOOD],
201211
stapled_ocsp: None,
212+
verification_time: verification_time(),
202213
expected_result: Err(TlsError::InvalidCertificate(CertificateError::UnknownIssuer)),
203214
other_error: no_error!(),
204215
},
205216
ee_only_ipv6 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
206217
reference_id: LOCALHOST_IPV6,
207218
chain: &[ROOT1_INT1_LOCALHOST_IPV6_GOOD],
208219
stapled_ocsp: None,
220+
verification_time: verification_time(),
209221
expected_result: Err(TlsError::InvalidCertificate(CertificateError::UnknownIssuer)),
210222
other_error: no_error!(),
211223
},
@@ -214,27 +226,31 @@ mock_root_test_cases! {
214226
reference_id: "example.org",
215227
chain: &[ROOT1_INT1_EXAMPLE_COM_GOOD, ROOT1_INT1],
216228
stapled_ocsp: None,
229+
verification_time: verification_time(),
217230
expected_result: Err(TlsError::InvalidCertificate(CertificateError::NotValidForName)),
218231
other_error: no_error!(),
219232
},
220233
domain_mismatch_ipv4 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
221234
reference_id: "198.168.0.1",
222235
chain: &[ROOT1_INT1_LOCALHOST_IPV4_GOOD, ROOT1_INT1],
223236
stapled_ocsp: None,
237+
verification_time: verification_time(),
224238
expected_result: Err(TlsError::InvalidCertificate(CertificateError::NotValidForName)),
225239
other_error: no_error!(),
226240
},
227241
domain_mismatch_ipv6 [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
228242
reference_id: "::ffff:c6a8:1",
229243
chain: &[ROOT1_INT1_LOCALHOST_IPV6_GOOD, ROOT1_INT1],
230244
stapled_ocsp: None,
245+
verification_time: verification_time(),
231246
expected_result: Err(TlsError::InvalidCertificate(CertificateError::NotValidForName)),
232247
other_error: no_error!(),
233248
},
234249
wrong_eku_dns [ any(windows, target_os = "android", target_os = "macos", target_os = "linux") ] => TestCase {
235250
reference_id: EXAMPLE_COM,
236251
chain: &[include_bytes!("root1-int1-ee_example.com-wrong_eku.crt"), ROOT1_INT1],
237252
stapled_ocsp: None,
253+
verification_time: verification_time(),
238254
expected_result: Err(TlsError::InvalidCertificate(
239255
CertificateError::Other(Arc::from(EkuError)))),
240256
other_error: Some(EkuError),
@@ -243,6 +259,7 @@ mock_root_test_cases! {
243259
reference_id: LOCALHOST_IPV4,
244260
chain: &[include_bytes!("root1-int1-ee_127.0.0.1-wrong_eku.crt"), ROOT1_INT1],
245261
stapled_ocsp: None,
262+
verification_time: verification_time(),
246263
expected_result: Err(TlsError::InvalidCertificate(
247264
CertificateError::Other(Arc::from(EkuError)))),
248265
other_error: Some(EkuError),
@@ -251,6 +268,7 @@ mock_root_test_cases! {
251268
reference_id: LOCALHOST_IPV6,
252269
chain: &[include_bytes!("root1-int1-ee_1-wrong_eku.crt"), ROOT1_INT1],
253270
stapled_ocsp: None,
271+
verification_time: verification_time(),
254272
expected_result: Err(TlsError::InvalidCertificate(
255273
CertificateError::Other(Arc::from(EkuError)))),
256274
other_error: Some(EkuError),
@@ -289,7 +307,7 @@ fn test_with_mock_root<E: std::error::Error + PartialEq + 'static>(test_case: &T
289307
&server_name,
290308
&mut std::iter::empty(),
291309
test_case.stapled_ocsp.unwrap_or(&[]),
292-
std::time::SystemTime::now(),
310+
test_case.verification_time,
293311
);
294312

295313
assert_cert_error_eq(

rustls-platform-verifier/src/tests/verification_real_world/mod.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,6 @@
2222
//! fetching then the trust anchors for these certificates might not be
2323
//! trusted by the operating system's root store.
2424
//!
25-
//! XXX: Currently these tests are a time-bomb because they validate the
26-
//! certificates as of the current system time, because the version of
27-
//! Rustls we use does not support passing in a different time. The newest
28-
//! version of Rustls does have that capability. We need to upgrade to that
29-
//! version of Rustls, and/or otherwise change these tests, before these
30-
//! certificates expire in Fall/Winter 2022.
31-
//!
3225
//! XXX: These tests should be using a stapled OCSP responses so that the
3326
//! (operating-system-based) verifier doesn't try to fetch an OCSP
3427
//! response or CRL certificate. However, until we can fix the validation
@@ -42,7 +35,8 @@
4235
//! Thus we don't expect these tests to be flaky w.r.t. that, except for
4336
//! potentially poor performance.
4437
use super::TestCase;
45-
use crate::{tests::assert_cert_error_eq, Verifier};
38+
use crate::tests::{assert_cert_error_eq, verification_time};
39+
use crate::Verifier;
4640
use rustls::{client::ServerCertVerifier, CertificateError, Error as TlsError};
4741
use std::convert::TryFrom;
4842

@@ -145,7 +139,7 @@ fn real_world_test<E: std::error::Error>(test_case: &TestCase<E>) {
145139
&server_name,
146140
&mut std::iter::empty(),
147141
stapled_ocsp,
148-
std::time::SystemTime::now(),
142+
test_case.verification_time,
149143
)
150144
.map(|_| ());
151145

@@ -165,6 +159,7 @@ real_world_test_cases! {
165159
reference_id: MY_1PASSWORD_COM,
166160
chain: VALID_1PASSWORD_COM_CHAIN,
167161
stapled_ocsp: None,
162+
verification_time: verification_time(),
168163
expected_result: Ok(()),
169164
other_error: no_error!(),
170165
},
@@ -173,6 +168,7 @@ real_world_test_cases! {
173168
reference_id: MY_1PASSWORD_COM,
174169
chain: VALID_1PASSWORD_COM_CHAIN,
175170
stapled_ocsp: None,
171+
verification_time: verification_time(),
176172
expected_result: Ok(()),
177173
other_error: no_error!(),
178174
},
@@ -181,6 +177,7 @@ real_world_test_cases! {
181177
reference_id: "1password.com",
182178
chain: VALID_1PASSWORD_COM_CHAIN,
183179
stapled_ocsp: None,
180+
verification_time: verification_time(),
184181
expected_result: Ok(()),
185182
other_error: no_error!(),
186183
},
@@ -189,6 +186,7 @@ real_world_test_cases! {
189186
reference_id: VALID_UNRELATED_DOMAIN,
190187
chain: VALID_1PASSWORD_COM_CHAIN,
191188
stapled_ocsp: None,
189+
verification_time: verification_time(),
192190
expected_result: Err(TlsError::InvalidCertificate(CertificateError::NotValidForName)),
193191
other_error: no_error!(),
194192
},
@@ -198,6 +196,7 @@ real_world_test_cases! {
198196
reference_id: VALID_UNRELATED_DOMAIN,
199197
chain: VALID_UNRELATED_CHAIN,
200198
stapled_ocsp: None,
199+
verification_time: verification_time(),
201200
expected_result: Ok(()),
202201
other_error: no_error!(),
203202
},
@@ -207,13 +206,15 @@ real_world_test_cases! {
207206
reference_id: MY_1PASSWORD_COM,
208207
chain: VALID_UNRELATED_CHAIN,
209208
stapled_ocsp: None,
209+
verification_time: verification_time(),
210210
expected_result: Err(TlsError::InvalidCertificate(CertificateError::NotValidForName)),
211211
other_error: no_error!(),
212212
},
213213
letsencrypt => TestCase {
214214
reference_id: LETSENCRYPT_ORG,
215215
chain: VALID_LETSENCRYPT_ORG_CHAIN,
216216
stapled_ocsp: None,
217+
verification_time: verification_time(),
217218
expected_result: Ok(()),
218219
other_error: no_error!(),
219220
},

0 commit comments

Comments
 (0)