Skip to content

Commit 2f74325

Browse files
committed
Force intermediates and revocation to be specified
1 parent f2b2b01 commit 2f74325

8 files changed

Lines changed: 81 additions & 92 deletions

File tree

src/verify_cert.rs

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ pub struct PathBuilder<'a, 'p> {
4646
impl<'a, 'p: 'a> PathBuilder<'a, 'p> {
4747
/// Build a new [`PathBuilder`] with the given parameters.
4848
///
49+
/// * `intermediate_certs` is the list of intermediate certificates to use for path building.
50+
/// These certificates should be sent by the peer. They are not trusted, but can be used to
51+
/// build a path to a trusted root.
52+
/// * `revocation` provides the revocation options to use for path building. If `None`, no
53+
/// revocation checks will be performed.
4954
/// * `eku` is the intended usage of the certificate, indicating what kind
5055
/// of usage we're verifying the certificate for. The default [`ExtendedKeyUsageValidator`]
5156
/// implementation is [`ExtendedKeyUsage`].
@@ -54,6 +59,8 @@ impl<'a, 'p: 'a> PathBuilder<'a, 'p> {
5459
/// public key is not validated against this list.
5560
/// * `trust_anchors` is the list of root CAs to trust in the built path.
5661
pub fn new(
62+
intermediate_certs: &'p [CertificateDer<'p>],
63+
revocation: Option<RevocationOptions<'a>>,
5764
eku: &'p dyn ExtendedKeyUsageValidator,
5865
supported_sig_algs: &'a [&'a dyn SignatureVerificationAlgorithm],
5966
trust_anchors: &'p [TrustAnchor<'p>],
@@ -62,28 +69,12 @@ impl<'a, 'p: 'a> PathBuilder<'a, 'p> {
6269
eku,
6370
supported_sig_algs,
6471
trust_anchors,
65-
intermediate_certs: &[],
66-
revocation: None,
72+
intermediate_certs,
73+
revocation,
6774
verify_path: None,
6875
}
6976
}
7077

71-
/// Set the sequence of intermediate certificates to use for path building.
72-
///
73-
/// These should be sent by the peer. Defaults to empty.
74-
pub fn with_intermediate_certs(mut self, intermediate_certs: &'p [CertificateDer<'p>]) -> Self {
75-
self.intermediate_certs = intermediate_certs;
76-
self
77-
}
78-
79-
/// Set the revocation options to use for path building.
80-
///
81-
/// By default, revocation checking is disabled.
82-
pub fn with_revocation(mut self, revocation: RevocationOptions<'a>) -> Self {
83-
self.revocation = Some(revocation);
84-
self
85-
}
86-
8778
/// Set a path verification function to use for path building.
8879
///
8980
/// `verify()` will only be called for potentially verified paths, that is, paths that
@@ -1509,11 +1500,12 @@ mod tests {
15091500
let mut path = PartialPath::new(ee_cert);
15101501

15111502
let builder = PathBuilder::new(
1503+
intermediate_certs,
1504+
None,
15121505
&ExtendedKeyUsage::SERVER_AUTH,
15131506
rustls_aws_lc_rs::ALL_VERIFICATION_ALGS,
15141507
trust_anchors,
1515-
)
1516-
.with_intermediate_certs(intermediate_certs);
1508+
);
15171509
let builder = match verify_path {
15181510
Some(verify) => builder.with_path_verification(verify),
15191511
None => builder,

tests/amazon.rs

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -237,58 +237,42 @@ pub fn amazon() {
237237
Some(&all_crls),
238238
] {
239239
let builder = PathBuilder::new(
240+
&intermediates,
241+
crls.map(|c| revocation_options_for_test(c)),
240242
&ExtendedKeyUsage::SERVER_AUTH,
241243
ALL_VERIFICATION_ALGS,
242244
&anchors,
243-
)
244-
.with_intermediate_certs(&intermediates);
245-
246-
let builder = match crls {
247-
Some(crls) => builder.with_revocation(revocation_options_for_test(crls)),
248-
None => builder,
249-
};
245+
);
250246

251247
assert!(builder.build(&cert, time).is_ok());
252248

253249
let builder = PathBuilder::new(
250+
&intermediates_legacy,
251+
crls.map(|c| revocation_options_for_test(c)),
254252
&ExtendedKeyUsage::SERVER_AUTH,
255253
ALL_VERIFICATION_ALGS,
256254
&legacy_anchors,
257-
)
258-
.with_intermediate_certs(&intermediates_legacy);
259-
260-
let builder = match crls {
261-
Some(crls) => builder.with_revocation(revocation_options_for_test(crls)),
262-
None => builder,
263-
};
255+
);
264256

265257
assert!(builder.build(&cert, time).is_ok());
266258

267259
let builder = PathBuilder::new(
260+
&intermediates_legacy,
261+
crls.map(|c| revocation_options_for_test(c)),
268262
&ExtendedKeyUsage::SERVER_AUTH,
269263
ALL_VERIFICATION_ALGS,
270264
&all_anchors,
271-
)
272-
.with_intermediate_certs(&intermediates_legacy);
273-
274-
let builder = match crls {
275-
Some(crls) => builder.with_revocation(revocation_options_for_test(crls)),
276-
None => builder,
277-
};
265+
);
278266

279267
assert!(builder.build(&cert, time).is_ok());
280268

281269
let builder = PathBuilder::new(
270+
&intermediates_legacy,
271+
crls.map(|c| revocation_options_for_test(c)),
282272
&ExtendedKeyUsage::SERVER_AUTH,
283273
ALL_VERIFICATION_ALGS,
284274
&all_anchors,
285-
)
286-
.with_intermediate_certs(&intermediates_legacy);
287-
288-
let builder = match crls {
289-
Some(crls) => builder.with_revocation(revocation_options_for_test(crls)),
290-
None => builder,
291-
};
275+
);
292276

293277
// verify should find shortest path
294278
let path = builder.build(&cert, time).unwrap();
@@ -302,28 +286,24 @@ pub fn amazon() {
302286

303287
for &crls in &[None, Some(&roots_crls)] {
304288
let builder = PathBuilder::new(
289+
&intermediates,
290+
crls.map(|c| revocation_options_for_test(c)),
305291
&ExtendedKeyUsage::SERVER_AUTH,
306292
ALL_VERIFICATION_ALGS,
307293
&anchors,
308-
)
309-
.with_intermediate_certs(&intermediates);
310-
311-
let builder = match crls {
312-
Some(crls) => builder.with_revocation(revocation_options_for_test(crls)),
313-
None => builder,
314-
};
294+
);
315295

316296
assert!(builder.build(&cert, time).is_ok());
317297
}
318298

319299
for &crls in &[&intermediates_crls, &all_crls] {
320300
let builder = PathBuilder::new(
301+
&intermediates,
302+
Some(revocation_options_for_test(crls)),
321303
&ExtendedKeyUsage::SERVER_AUTH,
322304
ALL_VERIFICATION_ALGS,
323305
&anchors,
324-
)
325-
.with_intermediate_certs(&intermediates)
326-
.with_revocation(revocation_options_for_test(crls));
306+
);
327307

328308
assert!(
329309
builder
@@ -335,11 +315,12 @@ pub fn amazon() {
335315

336316
for &(cert, _dns_name) in expired_certs {
337317
let builder = PathBuilder::new(
318+
&intermediates,
319+
None,
338320
&ExtendedKeyUsage::SERVER_AUTH,
339321
ALL_VERIFICATION_ALGS,
340322
&anchors,
341-
)
342-
.with_intermediate_certs(&intermediates);
323+
);
343324

344325
let cert = CertificateDer::from(cert);
345326
let cert = EndEntityCert::try_from(&cert).unwrap();

tests/client_auth.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ fn cert_with_serverauth_eku_rejected_for_client_auth() {
7979
fn check_cert(ee: &[u8], ca: CertificateDer<'static>) -> Result<(), webpki::Error> {
8080
let anchors = &[anchor_from_trusted_cert(&ca).unwrap()];
8181
let builder = PathBuilder::new(
82+
&[],
83+
None,
8284
&ExtendedKeyUsage::CLIENT_AUTH,
8385
rustls_aws_lc_rs::ALL_VERIFICATION_ALGS,
8486
anchors,

tests/client_auth_revocation.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,13 @@ fn check_cert(
5050
.map(|cert| CertificateDer::from(*cert))
5151
.collect::<Vec<_>>();
5252

53-
let builder = PathBuilder::new(&ExtendedKeyUsage::CLIENT_AUTH, ALGS, anchors)
54-
.with_intermediate_certs(&intermediates);
55-
56-
let builder = match revocation {
57-
Some(crls) => builder.with_revocation(crls),
58-
None => builder,
59-
};
53+
let builder = PathBuilder::new(
54+
&intermediates,
55+
revocation,
56+
&ExtendedKeyUsage::CLIENT_AUTH,
57+
ALGS,
58+
anchors,
59+
);
6060

6161
let ee = CertificateDer::from(ee);
6262
let cert = webpki::EndEntityCert::try_from(&ee).unwrap();

tests/custom_ekus.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ fn check_cert(
1414
) {
1515
let ca = CertificateDer::from(ca);
1616
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
17-
let builder = PathBuilder::new(eku, rustls_aws_lc_rs::ALL_VERIFICATION_ALGS, &anchors);
17+
let builder = PathBuilder::new(
18+
&[],
19+
None,
20+
eku,
21+
rustls_aws_lc_rs::ALL_VERIFICATION_ALGS,
22+
&anchors,
23+
);
1824

1925
let ee = CertificateDer::from(ee);
2026
let cert = webpki::EndEntityCert::try_from(&ee).unwrap();

tests/integration.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,12 @@ fn netflix() {
3333
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
3434
let intermediates = &[inter];
3535
let builder = PathBuilder::new(
36+
intermediates,
37+
None,
3638
&ExtendedKeyUsage::SERVER_AUTH,
3739
ALL_VERIFICATION_ALGS,
3840
&anchors,
39-
)
40-
.with_intermediate_certs(intermediates);
41+
);
4142

4243
let time = UnixTime::since_unix_epoch(Duration::from_secs(1_492_441_716)); // 2017-04-17T15:08:36Z
4344
let ee = CertificateDer::from(ee);
@@ -56,11 +57,12 @@ fn sanofi_rsa_signature_with_absent_algorithm_params() {
5657
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
5758
let intermediates = &[inter];
5859
let builder = PathBuilder::new(
60+
intermediates,
61+
None,
5962
&ExtendedKeyUsage::SERVER_AUTH,
6063
ALL_VERIFICATION_ALGS,
6164
&anchors,
62-
)
63-
.with_intermediate_certs(intermediates);
65+
);
6466

6567
let time = UnixTime::since_unix_epoch(Duration::from_secs(1_746_549_566)); // 2025-05-06T17:39:26Z
6668
let ee = CertificateDer::from(ee);
@@ -81,11 +83,12 @@ fn cloudflare_dns() {
8183
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
8284
let intermediates = &[inter];
8385
let builder = PathBuilder::new(
86+
intermediates,
87+
None,
8488
&ExtendedKeyUsage::SERVER_AUTH,
8589
ALL_VERIFICATION_ALGS,
8690
&anchors,
87-
)
88-
.with_intermediate_certs(intermediates);
91+
);
8992

9093
let time = UnixTime::since_unix_epoch(Duration::from_secs(1_663_495_771));
9194
let ee = CertificateDer::from(ee);
@@ -131,6 +134,8 @@ fn wpt() {
131134

132135
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
133136
let builder = PathBuilder::new(
137+
&[],
138+
None,
134139
&ExtendedKeyUsage::SERVER_AUTH,
135140
ALL_VERIFICATION_ALGS,
136141
&anchors,
@@ -148,6 +153,8 @@ fn ed25519() {
148153

149154
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
150155
let builder = PathBuilder::new(
156+
&[],
157+
None,
151158
&ExtendedKeyUsage::SERVER_AUTH,
152159
ALL_VERIFICATION_ALGS,
153160
&anchors,
@@ -167,11 +174,12 @@ fn critical_extensions() {
167174
let anchors = [anchor_from_trusted_cert(&root).unwrap()];
168175
let intermediates = &[ca];
169176
let builder = PathBuilder::new(
177+
intermediates,
178+
None,
170179
&ExtendedKeyUsage::SERVER_AUTH,
171180
ALL_VERIFICATION_ALGS,
172181
&anchors,
173-
)
174-
.with_intermediate_certs(intermediates);
182+
);
175183

176184
let time = UnixTime::since_unix_epoch(Duration::from_secs(1_670_779_098));
177185
let ee = CertificateDer::from(
@@ -215,6 +223,8 @@ fn read_ee_with_neg_serial() {
215223

216224
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
217225
let builder = PathBuilder::new(
226+
&[],
227+
None,
218228
&ExtendedKeyUsage::SERVER_AUTH,
219229
ALL_VERIFICATION_ALGS,
220230
&anchors,
@@ -380,11 +390,12 @@ fn cert_time_validity() {
380390

381391
let anchors = [anchor_from_trusted_cert(&ca).unwrap()];
382392
let builder = PathBuilder::new(
393+
slice::from_ref(&inter),
394+
None,
383395
&ExtendedKeyUsage::SERVER_AUTH,
384396
ALL_VERIFICATION_ALGS,
385397
&anchors,
386-
)
387-
.with_intermediate_certs(slice::from_ref(&inter));
398+
);
388399

389400
let not_before = UnixTime::since_unix_epoch(Duration::from_secs(1_478_563_200));
390401
let not_after = UnixTime::since_unix_epoch(Duration::from_secs(1_541_203_199));

tests/tls_server_certs.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ fn check_cert(
3737
let ca_cert_der = CertificateDer::from(ca);
3838
let anchors = [anchor_from_trusted_cert(&ca_cert_der).unwrap()];
3939
let builder = PathBuilder::new(
40+
&[],
41+
None,
4042
&ExtendedKeyUsage::SERVER_AUTH,
4143
rustls_aws_lc_rs::ALL_VERIFICATION_ALGS,
4244
&anchors,

tests/x509_limbo.rs

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -113,13 +113,6 @@ fn run_validation(tc: &Testcase) -> Result<(), String> {
113113
.map(|ic| cert_der_from_pem(ic))
114114
.collect::<Vec<_>>();
115115

116-
let builder = PathBuilder::new(
117-
&ExtendedKeyUsage::SERVER_AUTH,
118-
rustls_aws_lc_rs::ALL_VERIFICATION_ALGS,
119-
&trust_anchors,
120-
)
121-
.with_intermediate_certs(&intermediates);
122-
123116
let crls = tc
124117
.crls
125118
.iter()
@@ -134,18 +127,20 @@ fn run_validation(tc: &Testcase) -> Result<(), String> {
134127
.collect::<Result<Vec<_>, _>>()?;
135128
let crls = crls.iter().collect::<Vec<_>>();
136129

137-
let builder = if !crls.is_empty() {
138-
builder.with_revocation(
130+
let builder = PathBuilder::new(
131+
&intermediates,
132+
(!crls.is_empty()).then(|| {
139133
RevocationOptionsBuilder::new(crls.as_slice())
140134
.unwrap()
141135
.with_depth(RevocationCheckDepth::Chain)
142136
.with_status_policy(UnknownStatusPolicy::Deny)
143137
.with_expiration_policy(ExpirationPolicy::Enforce)
144-
.build(),
145-
)
146-
} else {
147-
builder
148-
};
138+
.build()
139+
}),
140+
&ExtendedKeyUsage::SERVER_AUTH,
141+
rustls_aws_lc_rs::ALL_VERIFICATION_ALGS,
142+
&trust_anchors,
143+
);
149144

150145
let leaf_der = cert_der_from_pem(&tc.peer_certificate);
151146
let leaf =

0 commit comments

Comments
 (0)