Skip to content

Commit b5bd2d8

Browse files
committed
upki: add binary index to improve performance
1 parent 5f8b57b commit b5bd2d8

10 files changed

Lines changed: 601 additions & 71 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ aws-lc-rs = "1.15.2"
1313
base64 = "0.22.1"
1414
chrono = { version = "0.4.42", features = ["alloc"], default-features = false }
1515
clap = { version = "4.5", features = ["derive"] }
16-
clubcard-crlite = "0.3.2"
16+
clubcard-crlite = "0.3.3"
1717
criterion = "0.8"
1818
directories = "6"
1919
eyre = "0.6"
@@ -62,3 +62,6 @@ unreachable_pub = "warn"
6262
unused_extern_crates = "warn"
6363
unused_import_braces = "warn"
6464
unused_qualifications = "warn"
65+
66+
[patch.crates-io]
67+
clubcard-crlite = { git = "https://github.com/mozilla/clubcard-crlite", rev = "83d4afe61d511fe88e8bf22e8a71c3b582536e69" }

revoke-test/benches/bench.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use codspeed_criterion_compat::{Criterion, criterion_group, criterion_main};
1010
use criterion::{Criterion, criterion_group, criterion_main};
1111
use revoke_test::RevocationTestSites;
1212
use rustls_pki_types::CertificateDer;
13-
use upki::revocation::{Manifest, RevocationCheckInput, RevocationStatus};
13+
use upki::revocation::{Index, Manifest, RevocationCheckInput, RevocationStatus};
1414
use upki::{Config, ConfigPath};
1515

1616
fn revocation(c: &mut Criterion) {
@@ -47,10 +47,10 @@ fn revocation(c: &mut Criterion) {
4747
let revoked_certs = certificates_for_test_site(BENCHMARK_CASE);
4848

4949
b.iter(|| {
50-
let manifest = Manifest::from_config(&config).unwrap();
50+
let mut index = Index::from_cache(&config).unwrap();
5151
let input = RevocationCheckInput::from_certificates(&revoked_certs).unwrap();
5252
assert_eq!(
53-
manifest.check(&input, &config).unwrap(),
53+
index.check(&input).unwrap(),
5454
RevocationStatus::CertainlyRevoked
5555
);
5656
})

rustls-upki/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use rustls::{
1414
ExtendedKeyPurpose, RootCertStore, SignatureScheme, SupportedCipherSuite,
1515
};
1616
use upki::revocation::{
17-
CertSerial, CtTimestamp, IssuerSpkiHash, Manifest, RevocationCheckInput, RevocationStatus,
17+
CertSerial, CtTimestamp, Index, IssuerSpkiHash, Manifest, RevocationCheckInput,
18+
RevocationStatus,
1819
};
1920
use upki::{self, Config, ConfigPath};
2021
use webpki::{EndEntityCert, ExtendedKeyUsage, InvalidNameContext, VerifiedPath};
@@ -128,9 +129,7 @@ impl ServerVerifier {
128129
sct_timestamps,
129130
};
130131

131-
match Manifest::from_config(&self.config)
132-
.and_then(|manifest| manifest.check(&input, &self.config))
133-
{
132+
match Index::from_cache(&self.config).and_then(|mut index| index.check(&input)) {
134133
Ok(rs) => Ok(rs),
135134
Err(e) => Err(rustls::Error::General(e.to_string())),
136135
}

upki-ffi/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::path::Path;
88
use std::slice;
99

1010
use rustls_pki_types::CertificateDer;
11-
use upki::revocation::{self, Manifest, RevocationCheckInput, RevocationStatus};
11+
use upki::revocation::{self, Index, RevocationCheckInput, RevocationStatus};
1212
use upki::{Config, Error};
1313

1414
/// Check the revocation status of a certificate.
@@ -47,12 +47,12 @@ pub unsafe extern "C" fn upki_check_revocation(
4747
Err(err) => return Error::Revocation(err).into(),
4848
};
4949

50-
let manifest = match Manifest::from_config(config) {
51-
Ok(manifest) => manifest,
50+
let mut index = match Index::from_cache(config) {
51+
Ok(index) => index,
5252
Err(err) => return Error::Revocation(err).into(),
5353
};
5454

55-
match manifest.check(&input, config) {
55+
match index.check(&input) {
5656
Ok(status) => match status {
5757
RevocationStatus::NotCoveredByRevocationData => {
5858
upki_result::UPKI_REVOCATION_NOT_COVERED

upki/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clap::{Parser, Subcommand};
88
use eyre::{Context, Report};
99
use rustls_pki_types::CertificateDer;
1010
use rustls_pki_types::pem::PemObject;
11-
use upki::revocation::{Manifest, RevocationCheckInput, fetch};
11+
use upki::revocation::{Index, Manifest, RevocationCheckInput, fetch};
1212
use upki::{Config, ConfigPath};
1313

1414
#[tokio::main(flavor = "current_thread")]
@@ -51,8 +51,8 @@ async fn main() -> Result<ExitCode, Report> {
5151
}
5252

5353
let input = RevocationCheckInput::from_certificates(&certs)?;
54-
Manifest::from_config(&config)?
55-
.check(&input, &config)?
54+
Index::from_cache(&config)?
55+
.check(&input)?
5656
.to_cli()
5757
}
5858
})

upki/src/revocation/fetch.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use std::process::ExitCode;
2020
use aws_lc_rs::digest;
2121
use tracing::{debug, info};
2222

23-
use super::{Error, Filter, Manifest};
23+
use super::index::INDEX_BIN;
24+
use super::{Error, Filter, Index, Manifest};
2425
use crate::Config;
2526

2627
/// Update the local revocation cache by fetching updates over the network.
@@ -157,6 +158,11 @@ impl Plan {
157158
steps.push(PlanStep::download(filter, remote_url, local));
158159
}
159160

161+
steps.push(PlanStep::SaveIndex {
162+
manifest: manifest.clone(),
163+
local_dir: local.to_owned(),
164+
});
165+
160166
steps.push(PlanStep::SaveManifest {
161167
manifest: manifest.clone(),
162168
local_dir: local.to_owned(),
@@ -197,6 +203,12 @@ enum PlanStep {
197203
/// Delete the given single local file.
198204
Delete(PathBuf),
199205

206+
/// Build and save the index from filter universe metadata.
207+
SaveIndex {
208+
manifest: Manifest,
209+
local_dir: PathBuf,
210+
},
211+
200212
/// Save the manifest structure
201213
SaveManifest {
202214
manifest: Manifest,
@@ -264,6 +276,46 @@ impl PlanStep {
264276
path: target,
265277
})?;
266278
}
279+
Self::SaveIndex {
280+
manifest,
281+
local_dir,
282+
} => {
283+
debug!("building index");
284+
let Some(buf) = Index::write(&manifest, &local_dir) else {
285+
return Ok(());
286+
};
287+
288+
#[cfg(target_family = "unix")]
289+
let temp = tempfile::Builder::new()
290+
.permissions(Permissions::from_mode(0o644))
291+
.suffix(".new")
292+
.tempfile_in(&local_dir);
293+
#[cfg(not(target_family = "unix"))]
294+
let temp = tempfile::Builder::new()
295+
.suffix(".new")
296+
.tempfile_in(&local_dir);
297+
298+
let mut local_temp = temp.map_err(|error| Error::FileWrite {
299+
error,
300+
path: local_dir.clone(),
301+
})?;
302+
303+
local_temp
304+
.as_file_mut()
305+
.write_all(&buf)
306+
.map_err(|error| Error::FileWrite {
307+
error,
308+
path: local_temp.path().to_owned(),
309+
})?;
310+
311+
let path = local_dir.join(INDEX_BIN);
312+
local_temp
313+
.persist(&path)
314+
.map_err(|error| Error::FileWrite {
315+
error: error.error,
316+
path,
317+
})?;
318+
}
267319
Self::SaveManifest {
268320
manifest,
269321
local_dir,
@@ -305,6 +357,9 @@ impl fmt::Display for PlanStep {
305357
filter.size
306358
),
307359
Self::Delete(path) => write!(f, "delete stale file {path:?}"),
360+
Self::SaveIndex { local_dir, .. } => {
361+
write!(f, "build index from filters into {local_dir:?}")
362+
}
308363
Self::SaveManifest { local_dir, .. } => {
309364
write!(f, "save new manifest into {local_dir:?}")
310365
}

0 commit comments

Comments
 (0)