Skip to content

Commit 875fcef

Browse files
djcctz
authored andcommitted
Unify high-level API to make key usage explicit
1 parent ee95916 commit 875fcef

File tree

9 files changed

+126
-58
lines changed

9 files changed

+126
-58
lines changed

src/end_entity.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@
1616
use crate::subject_name::GeneralDnsNameRef;
1717
use crate::{
1818
cert, signed_data, subject_name, verify_cert, CertRevocationList, Error, KeyUsage,
19-
NonTlsTrustAnchors, SignatureAlgorithm, SubjectNameRef, Time, TlsClientTrustAnchors,
20-
TlsServerTrustAnchors, TrustAnchor,
19+
SignatureAlgorithm, SubjectNameRef, Time, TrustAnchor,
2120
};
21+
#[allow(deprecated)]
22+
use crate::{TlsClientTrustAnchors, TlsServerTrustAnchors};
2223

2324
/// An end-entity certificate.
2425
///
@@ -100,28 +101,33 @@ impl<'a> EndEntityCert<'a> {
100101
/// Verifies that the end-entity certificate is valid for use against the
101102
/// specified Extended Key Usage (EKU).
102103
///
103-
/// `supported_sig_algs` is the list of signature algorithms that are
104-
/// trusted for use in certificate signatures; the end-entity certificate's
105-
/// public key is not validated against this list. `trust_anchors` is the
106-
/// list of root CAs to trust. `intermediate_certs` is the sequence of
107-
/// intermediate certificates that the server sent in the TLS handshake.
108-
/// `time` is the time for which the validation is effective (usually the
109-
/// current time).
110-
pub fn verify_is_valid_cert_with_eku(
104+
/// * `supported_sig_algs` is the list of signature algorithms that are
105+
/// trusted for use in certificate signatures; the end-entity certificate's
106+
/// public key is not validated against this list.
107+
/// * `trust_anchors` is the list of root CAs to trust
108+
/// * `intermediate_certs` is the sequence of intermediate certificates that
109+
/// the server sent in the TLS handshake.
110+
/// * `time` is the time for which the validation is effective (usually the
111+
/// current time).
112+
/// * `usage` is the intended usage of the certificate, indicating what kind
113+
/// of usage we're verifying the certificate for.
114+
/// * `crls` is the list of certificate revocation lists to check
115+
/// the certificate against.
116+
pub fn verify_for_usage(
111117
&self,
112118
supported_sig_algs: &[&SignatureAlgorithm],
113-
&NonTlsTrustAnchors(trust_anchors): &NonTlsTrustAnchors,
119+
trust_anchors: &[TrustAnchor],
114120
intermediate_certs: &[&[u8]],
115121
time: Time,
116-
eku: KeyUsage,
122+
usage: KeyUsage,
117123
crls: &[&dyn CertRevocationList],
118124
) -> Result<(), Error> {
119125
self.verify_is_valid_cert(
120126
supported_sig_algs,
121127
trust_anchors,
122128
intermediate_certs,
123129
time,
124-
eku,
130+
usage,
125131
crls,
126132
)
127133
}
@@ -136,6 +142,8 @@ impl<'a> EndEntityCert<'a> {
136142
/// intermediate certificates that the server sent in the TLS handshake.
137143
/// `time` is the time for which the validation is effective (usually the
138144
/// current time).
145+
#[allow(deprecated)]
146+
#[deprecated(since = "0.101.2", note = "Use `verify_for_usage` instead")]
139147
pub fn verify_is_valid_tls_server_cert(
140148
&self,
141149
supported_sig_algs: &[&SignatureAlgorithm],
@@ -164,6 +172,8 @@ impl<'a> EndEntityCert<'a> {
164172
/// `cert` is the purported end-entity certificate of the client. `time` is
165173
/// the time for which the validation is effective (usually the current
166174
/// time).
175+
#[allow(deprecated)]
176+
#[deprecated(since = "0.101.2", note = "Use `verify_for_usage` instead")]
167177
pub fn verify_is_valid_tls_client_cert(
168178
&self,
169179
supported_sig_algs: &[&SignatureAlgorithm],

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ mod crl;
5858
mod verify_cert;
5959
mod x509;
6060

61+
#[allow(deprecated)]
62+
pub use trust_anchor::{TlsClientTrustAnchors, TlsServerTrustAnchors};
6163
pub use {
6264
cert::{Cert, EndEntityOrCa},
6365
crl::{BorrowedCertRevocationList, BorrowedRevokedCert, CertRevocationList, RevocationReason},
@@ -72,7 +74,7 @@ pub use {
7274
SubjectNameRef,
7375
},
7476
time::Time,
75-
trust_anchor::{NonTlsTrustAnchors, TlsClientTrustAnchors, TlsServerTrustAnchors, TrustAnchor},
77+
trust_anchor::TrustAnchor,
7678
verify_cert::KeyUsage,
7779
};
7880

src/trust_anchor.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,13 @@ pub struct TrustAnchor<'a> {
2323
pub name_constraints: Option<&'a [u8]>,
2424
}
2525

26-
/// Trust anchors which may be used for authenticating certificates of any kind.
27-
#[derive(Debug)]
28-
pub struct NonTlsTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]);
29-
3026
/// Trust anchors which may be used for authenticating servers.
27+
#[deprecated(since = "0.101.2")]
3128
#[derive(Debug)]
3229
pub struct TlsServerTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]);
3330

3431
/// Trust anchors which may be used for authenticating clients.
32+
#[deprecated(since = "0.101.2")]
3533
#[derive(Debug)]
3634
pub struct TlsClientTrustAnchors<'a>(pub &'a [TrustAnchor<'a>]);
3735

tests/better_tls.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use base64::{engine::general_purpose, Engine as _};
22
use serde::Deserialize;
33
use std::collections::HashMap;
4-
use webpki::TrustAnchor;
4+
use webpki::{KeyUsage, TrustAnchor};
55

66
#[test]
77
pub fn path_building() {
@@ -11,7 +11,6 @@ pub fn path_building() {
1111

1212
let root_der = &better_tls.root_der();
1313
let roots = &[TrustAnchor::try_from_cert_der(root_der).expect("invalid trust anchor")];
14-
let trust_anchors = &webpki::TlsServerTrustAnchors(roots);
1514

1615
let path_building_suite = better_tls
1716
.suites
@@ -35,11 +34,13 @@ pub fn path_building() {
3534
// certificates won't expire.
3635
let now = webpki::Time::from_seconds_since_unix_epoch(1_688_651_734);
3736

38-
let result = ee_cert.verify_is_valid_tls_server_cert(
37+
let result = ee_cert.verify_for_usage(
3938
&[&webpki::ECDSA_P256_SHA256], // All of the BetterTLS testcases use P256 keys.
40-
trust_anchors,
39+
roots,
4140
intermediates,
4241
now,
42+
KeyUsage::server_auth(),
43+
&[],
4344
);
4445

4546
match testcase.expected {

tests/client_auth.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1313
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15-
extern crate webpki;
15+
#[cfg(feature = "alloc")]
16+
use webpki::KeyUsage;
1617

1718
#[cfg(feature = "alloc")]
1819
static ALL_SIGALGS: &[&webpki::SignatureAlgorithm] = &[
@@ -29,12 +30,18 @@ static ALL_SIGALGS: &[&webpki::SignatureAlgorithm] = &[
2930

3031
#[cfg(feature = "alloc")]
3132
fn check_cert(ee: &[u8], ca: &[u8]) -> Result<(), webpki::Error> {
32-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
33-
let anchors = webpki::TlsClientTrustAnchors(&anchors);
33+
let anchors = &[webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
3434

3535
let time = webpki::Time::from_seconds_since_unix_epoch(0x1fed_f00d);
3636
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
37-
cert.verify_is_valid_tls_client_cert(ALL_SIGALGS, &anchors, &[], time, &[])
37+
cert.verify_for_usage(
38+
ALL_SIGALGS,
39+
anchors,
40+
&[],
41+
time,
42+
KeyUsage::client_auth(),
43+
&[],
44+
)
3845
}
3946

4047
// DO NOT EDIT BELOW: generated by tests/generate.py

tests/client_auth_revocation.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1313
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15-
extern crate webpki;
15+
use webpki::KeyUsage;
1616

1717
fn check_cert(
1818
ee: &[u8],
@@ -21,15 +21,15 @@ fn check_cert(
2121
crls: &[&dyn webpki::CertRevocationList],
2222
) -> Result<(), webpki::Error> {
2323
let anchors = &[webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
24-
let anchors = webpki::TlsClientTrustAnchors(anchors.as_slice());
2524
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
2625
let time = webpki::Time::from_seconds_since_unix_epoch(0x1fed_f00d);
2726

28-
cert.verify_is_valid_tls_client_cert(
27+
cert.verify_for_usage(
2928
&[&webpki::ECDSA_P256_SHA256],
30-
&anchors,
29+
anchors,
3130
intermediates,
3231
time,
32+
KeyUsage::client_auth(),
3333
crls,
3434
)
3535
}

tests/custom_ekus.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ fn check_cert(
99
time: webpki::Time,
1010
result: Result<(), webpki::Error>,
1111
) {
12-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
13-
let anchors = webpki::NonTlsTrustAnchors(&anchors);
12+
let anchors = [webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
1413
let algs = &[
1514
&webpki::RSA_PKCS1_2048_8192_SHA256,
1615
&webpki::ECDSA_P256_SHA256,
@@ -19,7 +18,7 @@ fn check_cert(
1918
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
2019

2120
assert_eq!(
22-
cert.verify_is_valid_cert_with_eku(algs, &anchors, &[], time, eku, &[]),
21+
cert.verify_for_usage(algs, &anchors, &[], time, eku, &[]),
2322
result
2423
);
2524
}

tests/integration.rs

Lines changed: 66 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1313
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1414

15-
extern crate webpki;
15+
use webpki::KeyUsage;
1616

1717
static ALL_SIGALGS: &[&webpki::SignatureAlgorithm] = &[
1818
&webpki::ECDSA_P256_SHA256,
@@ -39,15 +39,21 @@ pub fn netflix() {
3939
let inter = include_bytes!("netflix/inter.der");
4040
let ca = include_bytes!("netflix/ca.der");
4141

42-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
43-
let anchors = webpki::TlsServerTrustAnchors(&anchors);
42+
let anchors = [webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
4443

4544
let time = webpki::Time::from_seconds_since_unix_epoch(1_492_441_716); // 2017-04-17T15:08:36Z
4645

4746
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
4847
assert_eq!(
4948
Ok(()),
50-
cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[inter], time)
49+
cert.verify_for_usage(
50+
ALL_SIGALGS,
51+
&anchors,
52+
&[inter],
53+
time,
54+
KeyUsage::server_auth(),
55+
&[]
56+
)
5157
);
5258
}
5359

@@ -59,15 +65,21 @@ pub fn cloudflare_dns() {
5965
let inter = include_bytes!("cloudflare_dns/inter.der");
6066
let ca = include_bytes!("cloudflare_dns/ca.der");
6167

62-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
63-
let anchors = webpki::TlsServerTrustAnchors(&anchors);
68+
let anchors = [webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
6469

6570
let time = webpki::Time::from_seconds_since_unix_epoch(1_663_495_771);
6671

6772
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
6873
assert_eq!(
6974
Ok(()),
70-
cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[inter], time)
75+
cert.verify_for_usage(
76+
ALL_SIGALGS,
77+
&anchors,
78+
&[inter],
79+
time,
80+
KeyUsage::server_auth(),
81+
&[]
82+
)
7183
);
7284

7385
let check_name = |name: &str| {
@@ -107,15 +119,21 @@ pub fn wpt() {
107119
let ee: &[u8] = include_bytes!("wpt/ee.der");
108120
let ca = include_bytes!("wpt/ca.der");
109121

110-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
111-
let anchors = webpki::TlsServerTrustAnchors(&anchors);
122+
let anchors = [webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
112123

113124
let time = webpki::Time::from_seconds_since_unix_epoch(1_619_256_684); // 2021-04-24T09:31:24Z
114125

115126
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
116127
assert_eq!(
117128
Ok(()),
118-
cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[], time)
129+
cert.verify_for_usage(
130+
ALL_SIGALGS,
131+
&anchors,
132+
&[],
133+
time,
134+
KeyUsage::server_auth(),
135+
&[]
136+
)
119137
);
120138
}
121139

@@ -124,15 +142,21 @@ pub fn ed25519() {
124142
let ee: &[u8] = include_bytes!("ed25519/ee.der");
125143
let ca = include_bytes!("ed25519/ca.der");
126144

127-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
128-
let anchors = webpki::TlsServerTrustAnchors(&anchors);
145+
let anchors = [webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
129146

130147
let time = webpki::Time::from_seconds_since_unix_epoch(1_547_363_522); // 2019-01-13T07:12:02Z
131148

132149
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
133150
assert_eq!(
134151
Ok(()),
135-
cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[], time)
152+
cert.verify_for_usage(
153+
ALL_SIGALGS,
154+
&anchors,
155+
&[],
156+
time,
157+
KeyUsage::server_auth(),
158+
&[]
159+
)
136160
);
137161
}
138162

@@ -144,16 +168,31 @@ fn critical_extensions() {
144168

145169
let time = webpki::Time::from_seconds_since_unix_epoch(1_670_779_098);
146170
let anchors = [webpki::TrustAnchor::try_from_cert_der(root).unwrap()];
147-
let anchors = webpki::TlsServerTrustAnchors(&anchors);
148171

149172
let ee = include_bytes!("critical_extensions/ee-cert-noncrit-unknown-ext.der");
150-
let res = webpki::EndEntityCert::try_from(&ee[..])
151-
.and_then(|cert| cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[ca], time));
173+
let res = webpki::EndEntityCert::try_from(&ee[..]).and_then(|cert| {
174+
cert.verify_for_usage(
175+
ALL_SIGALGS,
176+
&anchors,
177+
&[ca],
178+
time,
179+
KeyUsage::server_auth(),
180+
&[],
181+
)
182+
});
152183
assert_eq!(res, Ok(()), "accept non-critical unknown extension");
153184

154185
let ee = include_bytes!("critical_extensions/ee-cert-crit-unknown-ext.der");
155-
let res = webpki::EndEntityCert::try_from(&ee[..])
156-
.and_then(|cert| cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[ca], time));
186+
let res = webpki::EndEntityCert::try_from(&ee[..]).and_then(|cert| {
187+
cert.verify_for_usage(
188+
ALL_SIGALGS,
189+
&anchors,
190+
&[ca],
191+
time,
192+
KeyUsage::server_auth(),
193+
&[],
194+
)
195+
});
157196
assert_eq!(
158197
res,
159198
Err(webpki::Error::UnsupportedCriticalExtension),
@@ -180,15 +219,21 @@ fn read_ee_with_neg_serial() {
180219
let ca: &[u8] = include_bytes!("misc/serial_neg_ca.der");
181220
let ee: &[u8] = include_bytes!("misc/serial_neg_ee.der");
182221

183-
let anchors = vec![webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
184-
let anchors = webpki::TlsServerTrustAnchors(&anchors);
222+
let anchors = [webpki::TrustAnchor::try_from_cert_der(ca).unwrap()];
185223

186224
let time = webpki::Time::from_seconds_since_unix_epoch(1_667_401_500); // 2022-11-02T15:05:00Z
187225

188226
let cert = webpki::EndEntityCert::try_from(ee).unwrap();
189227
assert_eq!(
190228
Ok(()),
191-
cert.verify_is_valid_tls_server_cert(ALL_SIGALGS, &anchors, &[], time)
229+
cert.verify_for_usage(
230+
ALL_SIGALGS,
231+
&anchors,
232+
&[],
233+
time,
234+
KeyUsage::server_auth(),
235+
&[]
236+
)
192237
);
193238
}
194239

0 commit comments

Comments
 (0)