Skip to content

Commit 9737b79

Browse files
fix: timestamp grace for legacy manifests (#1502)
Disable TSA trust check for 1.x legacy manifests Fix TSA check to follow spec and only use system trust list Remove default OCSP fetching from our settings sample toml Fix broken unit test
1 parent 1d12815 commit 9737b79

File tree

13 files changed

+135
-73
lines changed

13 files changed

+135
-73
lines changed

cli/tests/fixtures/trust/cawg_sign_settings.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
version = 1
55

66
# Trust settings for certificate validation.
7-
# [trust]
7+
[trust]
88
# String to user-provided trust anchors (PEM format).
99
# user_anchors = ""
1010
# String to system trust anchors (PEM format).
@@ -406,8 +406,8 @@ tsa_url = "http://timestamp.digicert.com"
406406

407407
# Configuration for the `Builder`.
408408
[builder]
409-
certificate_status_fetch = "all"
410-
certificate_status_should_override = true
409+
#certificate_status_fetch = "all"
410+
#certificate_status_should_override = true
411411

412412
# Claim generator info list.
413413
[builder.claim_generator_info]

cli/tests/fixtures/trust/cawg_test_settings.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[verify]
2-
trusted = true
2+
verify_trust = true
33

44
[trust]
55
trust_config = """

sdk/src/claim.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1911,6 +1911,11 @@ impl Claim {
19111911
let sig = claim.signature_val();
19121912
let additional_bytes: Vec<u8> = Vec::new();
19131913

1914+
let mut adjusted_settings = settings.clone();
1915+
if claim.version() == 1 {
1916+
adjusted_settings.verify.verify_timestamp_trust = false;
1917+
}
1918+
19141919
// use the signature uri as the current uri while validating the signature info
19151920
validation_log.push_current_uri(to_signature_uri(claim.label()));
19161921

@@ -1956,7 +1961,7 @@ impl Claim {
19561961
svi.certificate_statuses.get(&certificate_serial_num),
19571962
svi.timestamps.get(claim.label()),
19581963
validation_log,
1959-
settings,
1964+
&adjusted_settings,
19601965
)?;
19611966

19621967
let verified = verify_cose(
@@ -1967,11 +1972,17 @@ impl Claim {
19671972
ctp,
19681973
svi.timestamps.get(claim.label()),
19691974
validation_log,
1970-
settings,
1975+
&adjusted_settings,
19711976
);
19721977

1973-
let result =
1974-
Claim::verify_internal(claim, asset_data, svi, verified, validation_log, settings);
1978+
let result = Claim::verify_internal(
1979+
claim,
1980+
asset_data,
1981+
svi,
1982+
verified,
1983+
validation_log,
1984+
&adjusted_settings,
1985+
);
19751986
validation_log.pop_current_uri();
19761987
result
19771988
}

sdk/src/crypto/cose/certificate_trust_policy.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ pub struct CertificateTrustPolicy {
5858

5959
/// passthrough mode
6060
passthrough: bool,
61+
62+
/// Use only system trust for this check
63+
trust_anchors_only: bool,
6164
}
6265

6366
impl Default for CertificateTrustPolicy {
@@ -68,6 +71,7 @@ impl Default for CertificateTrustPolicy {
6871
end_entity_cert_set: HashSet::default(),
6972
additional_ekus: HashSet::default(),
7073
passthrough: false,
74+
trust_anchors_only: false,
7175
};
7276

7377
this.add_valid_ekus(include_bytes!("./valid_eku_oids.cfg"));
@@ -98,6 +102,7 @@ impl CertificateTrustPolicy {
98102
end_entity_cert_set: HashSet::default(),
99103
additional_ekus: HashSet::default(),
100104
passthrough: false,
105+
trust_anchors_only: false,
101106
}
102107
}
103108

@@ -109,6 +114,7 @@ impl CertificateTrustPolicy {
109114
end_entity_cert_set: HashSet::default(),
110115
additional_ekus: HashSet::default(),
111116
passthrough: true,
117+
trust_anchors_only: false,
112118
}
113119
}
114120

@@ -341,6 +347,19 @@ impl CertificateTrustPolicy {
341347
}
342348
}
343349

350+
/// Set whether we only want to use system trust_achors and ignores user_anchors,
351+
/// returns last trust_anchors_value
352+
pub fn set_trust_anchors_only(&mut self, trust_anchors_only: bool) -> bool {
353+
let val = self.trust_anchors_only;
354+
self.trust_anchors_only = trust_anchors_only;
355+
val
356+
}
357+
358+
/// Get whether we only want to use system trust_achors and ignores user_anchors
359+
pub fn trust_anchors_only(&self) -> bool {
360+
self.trust_anchors_only
361+
}
362+
344363
/// Remove all trust anchors, private credentials, and EKUs previously
345364
/// configured.
346365
pub fn clear(&mut self) {

sdk/src/crypto/cose/ocsp.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ fn check_stapled_ocsp_response(
298298
if check_end_entity_certificate_profile(
299299
&ocsp_certs[0],
300300
ctp,
301-
validation_log,
301+
&mut current_validation_log,
302302
tst_info.as_ref(),
303303
)
304304
.is_err()
@@ -320,7 +320,7 @@ pub(crate) fn fetch_and_check_ocsp_response(
320320
sign1: &CoseSign1,
321321
data: &[u8],
322322
ctp: &CertificateTrustPolicy,
323-
_tst_info: Option<&TstInfo>,
323+
tst_info: Option<&TstInfo>,
324324
validation_log: &mut StatusTracker,
325325
settings: &Settings,
326326
) -> Result<OcspResponse, CoseError> {
@@ -340,10 +340,13 @@ pub(crate) fn fetch_and_check_ocsp_response(
340340

341341
let ocsp_response_der = ocsp_der;
342342

343-
let signing_time: Option<DateTime<Utc>> =
344-
validate_cose_tst_info(sign1, data, ctp, validation_log, settings)
343+
// use supplied override time if provided
344+
let signing_time: Option<DateTime<Utc>> = match tst_info {
345+
Some(tst_info) => Some(tst_info.gen_time.clone().into()),
346+
None => validate_cose_tst_info(sign1, data, ctp, validation_log, settings)
345347
.ok()
346-
.map(|tst_info| tst_info.gen_time.clone().into());
348+
.map(|tst_info| tst_info.gen_time.clone().into()),
349+
};
347350

348351
// Check the OCSP response, but only if it is well-formed.
349352
// Revocation errors are reported in the validation log.

sdk/src/crypto/raw_signature/openssl/check_certificate_trust.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ pub(crate) fn check_certificate_trust(
6868
let mut store_ctx = X509StoreContext::new()?;
6969
if store_ctx.init(&store, cert.as_ref(), &cert_chain, |f| f.verify_cert())? {
7070
Ok(TrustAnchorType::System)
71-
} else {
71+
} else if !ctp.trust_anchors_only() {
7272
// try the user trust anchors
7373
let mut builder = openssl::x509::store::X509StoreBuilder::new()?;
7474
builder.set_flags(X509VerifyFlags::X509_STRICT)?;
@@ -89,5 +89,7 @@ pub(crate) fn check_certificate_trust(
8989
} else {
9090
Err(CertificateTrustError::CertificateNotTrusted)
9191
}
92+
} else {
93+
Err(CertificateTrustError::CertificateNotTrusted)
9294
}
9395
}

sdk/src/crypto/raw_signature/rust_native/check_certificate_trust.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,22 +120,24 @@ pub(crate) fn check_certificate_trust(
120120
}
121121

122122
// Check against user provided trust anchors.
123-
for (anchor_cert, anchor_der) in &user_anchors {
124-
if chain_cert.issuer() == anchor_cert.subject() {
125-
let data = chain_cert.tbs_certificate.as_ref();
126-
let sig = chain_cert.signature_value.as_ref();
123+
if !ctp.trust_anchors_only() {
124+
for (anchor_cert, anchor_der) in &user_anchors {
125+
if chain_cert.issuer() == anchor_cert.subject() {
126+
let data = chain_cert.tbs_certificate.as_ref();
127+
let sig = chain_cert.signature_value.as_ref();
127128

128-
let sig_alg = cert_signing_alg(&chain_cert);
129+
let sig_alg = cert_signing_alg(&chain_cert);
129130

130-
let result = verify_data(anchor_der, sig_alg, sig, data);
131+
let result = verify_data(anchor_der, sig_alg, sig, data);
131132

132-
match result {
133-
Ok(b) => {
134-
if b {
135-
return Ok(TrustAnchorType::User);
133+
match result {
134+
Ok(b) => {
135+
if b {
136+
return Ok(TrustAnchorType::User);
137+
}
136138
}
139+
Err(_) => continue,
137140
}
138-
Err(_) => continue,
139141
}
140142
}
141143
}

sdk/src/crypto/time_stamp/verify.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -533,21 +533,26 @@ pub fn verify_time_stamp(
533533
// the certificate must be on the trust list to be considered valid
534534
let verify_trust = settings.verify.verify_timestamp_trust;
535535

536-
if verify_trust
537-
&& ctp
536+
if verify_trust {
537+
// per the spec TSA trust can only be checked against the system trust list not the user trust list
538+
let mut adjusted_ctp = ctp.clone();
539+
adjusted_ctp.set_trust_anchors_only(true);
540+
541+
if adjusted_ctp
538542
.check_certificate_trust(&cert_ders[0..], &cert_ders[0], Some(signing_time))
539543
.is_err()
540-
{
541-
log_item!(
542-
"",
543-
format!("timestamp cert untrusted: {}", &common_name),
544-
"verify_time_stamp"
545-
)
546-
.validation_status(TIMESTAMP_UNTRUSTED)
547-
.informational(&mut current_validation_log);
544+
{
545+
log_item!(
546+
"",
547+
format!("timestamp cert untrusted: {}", &common_name),
548+
"verify_time_stamp"
549+
)
550+
.validation_status(TIMESTAMP_UNTRUSTED)
551+
.informational(&mut current_validation_log);
548552

549-
last_err = TimeStampError::Untrusted;
550-
continue;
553+
last_err = TimeStampError::Untrusted;
554+
continue;
555+
}
551556
}
552557

553558
log_item!(

sdk/src/store.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,10 @@ impl Store {
576576
) -> Result<Vec<u8>> {
577577
let claim_bytes = claim.data()?;
578578

579+
// no verification of timestamp trust while signing
580+
let mut adjusted_settings = settings.clone();
581+
adjusted_settings.verify.verify_timestamp_trust = false;
582+
579583
let tss = if claim.version() > 1 {
580584
TimeStampStorage::V2_sigTst2_CTT
581585
} else {
@@ -587,7 +591,7 @@ impl Store {
587591
// Let the signer do all the COSE processing and return the structured COSE data.
588592
return signer.sign(&claim_bytes); // do not verify remote signers (we never did)
589593
} else {
590-
cose_sign(signer, &claim_bytes, box_size, tss, settings)
594+
cose_sign(signer, &claim_bytes, box_size, tss, &adjusted_settings)
591595
}
592596
} else {
593597
if signer.direct_cose_handling() {
@@ -616,7 +620,7 @@ impl Store {
616620
&self.ctp,
617621
None,
618622
&mut cose_log,
619-
settings,
623+
&adjusted_settings,
620624
)
621625
} else {
622626
verify_cose_async(
@@ -627,7 +631,7 @@ impl Store {
627631
&self.ctp,
628632
None,
629633
&mut cose_log,
630-
settings,
634+
&adjusted_settings,
631635
)
632636
.await
633637
};
@@ -1575,7 +1579,7 @@ impl Store {
15751579

15761580
// allow the extra ingredient trust checks
15771581
// these checks are to prevent the trust spoofing
1578-
let check_ingredient_trust: bool = settings.verify.check_ingredient_trust;
1582+
let check_ingredient_trust: bool = settings.verify.verify_trust;
15791583

15801584
// get the 1.1-1.2 box hash
15811585
let ingredient_hashes = store.get_manifest_box_hashes(ingredient);
@@ -2062,18 +2066,26 @@ impl Store {
20622066

20632067
// save the valid timestamps stored in the StoreValidationInfo
20642068
// we only use valid timestamps, otherwise just ignore
2069+
let mut adjusted_settings = settings.clone();
2070+
let original_trust_val = adjusted_settings.verify.verify_timestamp_trust;
20652071
for (referenced_claim, time_stamp_token) in timestamp_assertion.as_ref() {
20662072
if let Some(rc) = svi.manifest_map.get(referenced_claim) {
2073+
if rc.version() == 1 {
2074+
// no trust checks for leagacy timestamps
2075+
adjusted_settings.verify.verify_timestamp_trust = false;
2076+
}
2077+
20672078
if let Ok(tst_info) = verify_time_stamp(
20682079
time_stamp_token,
20692080
rc.signature_val(),
20702081
&self.ctp,
20712082
validation_log,
2072-
settings,
2083+
&adjusted_settings,
20732084
) {
20742085
svi.timestamps.insert(rc.label().to_owned(), tst_info);
20752086
}
20762087
}
2088+
adjusted_settings.verify.verify_timestamp_trust = original_trust_val;
20772089
}
20782090
}
20792091

@@ -4276,11 +4288,19 @@ impl Store {
42764288
) -> Result<Vec<(String, Vec<u8>)>> {
42774289
let mut oscp_response_ders = Vec::new();
42784290

4291+
let mut adjusted_settings = settings.clone();
4292+
let original_trust_val = adjusted_settings.verify.verify_timestamp_trust;
4293+
42794294
for manifest_label in manifest_labels {
42804295
if let Some(claim) = self.claims_map.get(&manifest_label) {
42814296
let sig = claim.signature_val().clone();
42824297
let data = claim.data()?;
42834298

4299+
// no timestamp trust checks for 1.x manifests
4300+
if claim.version() == 1 {
4301+
adjusted_settings.verify.verify_timestamp_trust = false;
4302+
}
4303+
42844304
let sign1 = parse_cose_sign1(&sig, &data, validation_log)?;
42854305
let ocsp_response_der = if _sync {
42864306
fetch_and_check_ocsp_response(
@@ -4309,6 +4329,7 @@ impl Store {
43094329
oscp_response_ders.push((manifest_label, ocsp_response_der));
43104330
}
43114331
}
4332+
adjusted_settings.verify.verify_timestamp_trust = original_trust_val;
43124333
}
43134334

43144335
Ok(oscp_response_ders)

sdk/tests/fixtures/test_settings_with_cawg_signing.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,8 +408,8 @@ tsa_url = "http://timestamp.digicert.com"
408408

409409
# Configuration for the `Builder`.
410410
[builder]
411-
certificate_status_fetch = "all"
412-
certificate_status_should_override = true
411+
#certificate_status_fetch = "all"
412+
#certificate_status_should_override = true
413413

414414
# Claim generator info list.
415415
[builder.claim_generator_info]

0 commit comments

Comments
 (0)