secure validation cache reuse

This commit is contained in:
2026-07-11 21:57:46 +08:00
parent 8613cfae60
commit 60796299b0
7 changed files with 428 additions and 107 deletions

View File

@@ -506,6 +506,7 @@ pub struct CachedRoaValidationResult {
source_object_hash: [u8; 32],
ee_serial: Option<Vec<u8>>,
crl_uri: Option<String>,
earliest_safe_reuse_time_unix: i64,
outputs_effective_until_unix: i64,
outputs: Vec<VcirLocalOutput>,
}
@@ -543,6 +544,12 @@ impl RoaValidationCacheView {
}
for entry in &projection.entries {
let Some(earliest_safe_reuse_time_unix) = entry.earliest_safe_reuse_time_unix else {
continue;
};
if time::OffsetDateTime::from_unix_timestamp(earliest_safe_reuse_time_unix).is_err() {
continue;
}
let outputs = entry
.outputs
.iter()
@@ -563,6 +570,7 @@ impl RoaValidationCacheView {
source_object_hash: entry.source_object_hash,
ee_serial: entry.ee_serial.clone(),
crl_uri: entry.crl_uri.clone(),
earliest_safe_reuse_time_unix,
outputs_effective_until_unix: entry.outputs_effective_until_unix,
outputs,
},
@@ -674,7 +682,9 @@ impl RoaValidationCacheView {
if cached.outputs.is_empty() {
return_entry_gate!(RoaCacheLookupResult::Miss);
}
if cached.outputs_effective_until_unix <= validation_time.unix_timestamp() {
if validation_time.unix_timestamp() < cached.earliest_safe_reuse_time_unix
|| cached.outputs_effective_until_unix <= validation_time.unix_timestamp()
{
return_entry_gate!(RoaCacheLookupResult::ExpiredBlocked);
}
@@ -760,6 +770,10 @@ impl RoaValidationCacheView {
source_object_hash: file.sha256,
ee_serial: ee_serial.clone(),
crl_uri: crl_uri.to_string(),
earliest_safe_reuse_time: PackTime::from_utc_offset_datetime(
time::OffsetDateTime::from_unix_timestamp(cached.earliest_safe_reuse_time_unix)
.expect("cached ROA safe reuse time must be valid"),
),
}),
};
metrics.materialize_nanos = metrics
@@ -821,6 +835,14 @@ fn crl_valid_at_time(
validation_time >= this_update && validation_time < next_update
}
fn roa_cache_earliest_safe_reuse_time(
ee_not_before: time::OffsetDateTime,
crl_this_update: time::OffsetDateTime,
validation_time: time::OffsetDateTime,
) -> PackTime {
PackTime::from_utc_offset_datetime(ee_not_before.max(crl_this_update).max(validation_time))
}
fn record_roa_cache_block(
stats: &mut RoaValidationCacheStats,
lookup_result: &RoaCacheLookupResult,
@@ -2736,6 +2758,11 @@ fn process_roa_with_issuer(
source_object_hash: file.sha256,
ee_serial: BigUnsigned::from_biguint(&ee.resource_cert.tbs.serial_number).bytes_be,
crl_uri: issuer_crl_rsync_uri.to_string(),
earliest_safe_reuse_time: roa_cache_earliest_safe_reuse_time(
ee.resource_cert.tbs.validity_not_before,
verified_crl.crl.this_update.utc,
validation_time,
),
};
if !collect_vcir_local_outputs {
return Ok((vrps, Vec::new(), Some(cache_object_meta)));
@@ -2866,6 +2893,11 @@ fn process_roa_with_issuer_parallel_cached(
source_object_hash: file.sha256,
ee_serial: BigUnsigned::from_biguint(&ee.resource_cert.tbs.serial_number).bytes_be,
crl_uri: issuer_crl_rsync_uri.clone(),
earliest_safe_reuse_time: roa_cache_earliest_safe_reuse_time(
ee.resource_cert.tbs.validity_not_before,
verified_crl.crl.this_update.utc,
validation_time,
),
};
if !collect_vcir_local_outputs {
return Ok((vrps, Vec::new(), Some(cache_object_meta)));
@@ -3908,6 +3940,7 @@ mod tests {
source_object_hash: roa_hash,
ee_serial: vec![0x01],
crl_uri: TEST_CRL_URI.to_string(),
earliest_safe_reuse_time: vcir.last_successful_validation_time.clone(),
}],
}),
)
@@ -4299,7 +4332,7 @@ mod tests {
issuer_der,
crl_hash,
roa_hash,
fixed_time("2026-06-04T00:00:00Z"),
fixed_time("2026-06-04T01:00:00Z"),
fixed_time("2026-06-08T00:00:00Z"),
);
let projection = sample_roa_cache_projection(&vcir, roa_hash);
@@ -4594,6 +4627,7 @@ mod tests {
source_object_hash: roa_hash,
ee_serial: Some(vec![0x01]),
crl_uri: None,
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
outputs_effective_until_unix,
outputs: vec![output.clone()],
},
@@ -4610,6 +4644,7 @@ mod tests {
source_object_hash: roa_hash,
ee_serial: None,
crl_uri: Some(TEST_CRL_URI.to_string()),
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
outputs_effective_until_unix,
outputs: vec![output.clone()],
},
@@ -4626,6 +4661,7 @@ mod tests {
source_object_hash: roa_hash,
ee_serial: Some(vec![0x01]),
crl_uri: Some(TEST_CRL_URI.to_string()),
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
outputs_effective_until_unix,
outputs: vec![output.clone()],
},
@@ -4652,6 +4688,7 @@ mod tests {
source_object_hash: [0xff; 32],
ee_serial: Some(vec![0x01]),
crl_uri: Some(TEST_CRL_URI.to_string()),
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
outputs_effective_until_unix,
outputs: vec![output.clone()],
},
@@ -4668,6 +4705,7 @@ mod tests {
source_object_hash: roa_hash,
ee_serial: Some(vec![0x01]),
crl_uri: Some(TEST_CRL_URI.to_string()),
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
outputs_effective_until_unix,
outputs: Vec::new(),
},
@@ -4688,6 +4726,7 @@ mod tests {
source_object_hash: roa_hash,
ee_serial: Some(vec![0x01]),
crl_uri: Some(TEST_CRL_URI.to_string()),
earliest_safe_reuse_time_unix: validation_time.unix_timestamp(),
outputs_effective_until_unix,
outputs: vec![output],
},