mirror of
https://github.com/rustfs/rustfs.git
synced 2026-09-06 03:59:14 +00:00
fix(connect): preserve enrollment validation order
This commit is contained in:
@@ -380,6 +380,12 @@ impl OfflineEnrollment {
|
||||
return Err(EnrollmentError::MalformedDocument);
|
||||
}
|
||||
let issued_at = parse_timestamp(&routing.issued_at)?;
|
||||
|
||||
// The frozen decision order classifies the top-level signature before
|
||||
// parsing any trust-link routing fields. Otherwise a malformed first
|
||||
// link could mask a malformed artifact signature with DOCUMENT_MALFORMED.
|
||||
let signature = decode_signature(&envelope.signature)?;
|
||||
|
||||
let first = routing.trust_chain.first().ok_or(EnrollmentError::MalformedDocument)?;
|
||||
let first_bytes = decode_document_bytes(&first.bytes)?;
|
||||
let first_routing: TrustLinkRouting =
|
||||
@@ -388,10 +394,6 @@ impl OfflineEnrollment {
|
||||
return Err(EnrollmentError::MalformedDocument);
|
||||
}
|
||||
|
||||
// Only after the document can route verification do we classify the
|
||||
// top-level signature spelling and algorithm.
|
||||
let signature = decode_signature(&envelope.signature)?;
|
||||
|
||||
// Steps 3 to 5.
|
||||
let connect_key = verify_trust_chain(
|
||||
&routing.trust_chain,
|
||||
@@ -585,7 +587,7 @@ fn decode_trust_link(entry: &SignedDocument) -> Result<(TrustLink, Vec<u8>), Enr
|
||||
}
|
||||
|
||||
fn decode_document_bytes(value: &str) -> Result<Vec<u8>, EnrollmentError> {
|
||||
if value.len() % 4 != 0 {
|
||||
if !value.len().is_multiple_of(4) {
|
||||
return Err(EnrollmentError::MalformedDocument);
|
||||
}
|
||||
|
||||
|
||||
@@ -575,6 +575,25 @@ fn every_challenge_boundary_mutation_fails_with_its_frozen_reason() {
|
||||
assert_eq!(covered, 16, "boundary-vectors.json publishes sixteen executable challenge mutations");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn malformed_top_level_signature_precedes_malformed_first_link_routing() {
|
||||
let source = accept_vector_named("challenge signed by a chained signing key under the pinned root");
|
||||
let now = unix(field(&source, "evaluationTime"));
|
||||
let mut challenge_envelope = source["document"].clone();
|
||||
challenge_envelope["signature"]["algorithm"] = Value::String("ES384".to_string());
|
||||
|
||||
let mut challenge = signed_document(&challenge_envelope);
|
||||
let first_envelope = &mut challenge["trustChain"].as_array_mut().expect("challenge carries a chain")[0];
|
||||
let mut first_link = signed_document(first_envelope);
|
||||
first_link["issuerKeyId"] = Value::String("not-a-key-id".to_string());
|
||||
first_envelope["bytes"] = Value::String(encoded_document(&first_link));
|
||||
challenge_envelope["bytes"] = Value::String(encoded_document(&challenge));
|
||||
|
||||
let error = OfflineEnrollment::verify_challenge(&envelope(&challenge_envelope), now)
|
||||
.expect_err("a malformed top-level signature and first-link issuer must not verify");
|
||||
assert_eq!(error.reason(), "SIGNATURE_MALFORMED");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unpinned_root_precedes_a_malformed_chain_shape() {
|
||||
let source = accept_vector_named("challenge signed by a chained signing key under the pinned root");
|
||||
|
||||
Reference in New Issue
Block a user