#![cfg(test)]
use super::*;
#[test]
fn decode_refuses_an_unknown_role_with_no_help_from_the_byte_compare() {
let canonical = payload_bytes(&claim());
let role_at = role_offset(&canonical);
let mut refused = 0;
for role in [0u8, 1, 4, 7, 23] {
let mut payload = canonical.clone();
payload[role_at + 1] = role;
let mutant = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert!(
matches!(
decode_fields(&mutant),
Err(TrustError::DelegationVerification)
),
"role {role} was carried through the decoder"
);
refused += 1;
}
assert_eq!(refused, 5, "every unknown role must have been tried");
}
#[test]
fn decode_refuses_an_unknown_subject_kind_with_no_help_from_the_byte_compare() {
let canonical = payload_bytes(&claim());
assert_eq!(&canonical[..3], &[0xa6, 0x01, 0x01]);
let mut refused = 0;
for kind in [0u8, 3, 4, 7, 23] {
let mut payload = canonical.clone();
payload[2] = kind;
let mutant = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert!(
matches!(
decode_fields(&mutant),
Err(TrustError::DelegationVerification)
),
"subject kind {kind} was carried through the decoder"
);
refused += 1;
}
assert_eq!(
refused, 5,
"every unknown subject kind must have been tried"
);
}
#[test]
fn decode_refuses_a_pair_outside_the_table_though_both_halves_decode() {
let canonical = payload_bytes(&claim());
assert_eq!(
&canonical[..3],
&[0xa6, 0x01, 0x01],
"kind value at index 2"
);
let role_at = role_offset(&canonical);
let mut refused = 0;
for (kind, role) in [(1u64, 3u64), (2, 2)] {
let kind_enum = DelegationSubjectKind::from_wire(kind)
.expect("clause 3 requires a RECOGNISED subject kind");
let role_enum =
DelegationRole::from_wire(role).expect("clause 3 requires a RECOGNISED role");
assert!(
!kind_enum.permits(role_enum),
"({kind}, {role}) must be outside the pair table"
);
let mut payload = canonical.clone();
payload[2] = u8::try_from(kind).unwrap();
payload[role_at + 1] = u8::try_from(role).unwrap();
assert_eq!(payload.len(), canonical.len(), "a repair, not a resize");
let mutant = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert!(
matches!(
decode_fields(&mutant),
Err(TrustError::DelegationVerification)
),
"the pair (kind {kind}, role {role}) was carried through the decoder"
);
refused += 1;
}
assert_eq!(refused, 2, "both invalid pairs must have been tried");
let mut accepted = 0;
for (kind, role, expected) in [(0x01u8, 0x02u8, claim()), (0x02, 0x03, seat_claim())] {
let mut payload = canonical.clone();
payload[2] = kind;
payload[role_at + 1] = role;
let ok = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert_eq!(decode_fields(&ok).unwrap().claim, expected);
accepted += 1;
}
assert_eq!(
accepted, 2,
"both valid pairs must have been controlled for"
);
}
#[test]
fn transposing_the_subject_kind_and_role_labels_fails_role_decode_not_the_pair_check() {
let canonical = payload_bytes(&claim());
let role_at = role_offset(&canonical);
assert_eq!(canonical[2], 0x01, "domain is wire value 1");
assert_eq!(canonical[role_at + 1], 0x02, "operational is wire value 2");
let mut payload = canonical.clone();
payload[2] = 0x02;
payload[role_at + 1] = 0x01;
assert_eq!(payload.len(), canonical.len());
assert!(
DelegationRole::from_wire(1).is_none(),
"1 must not be a role — this is what makes the vocabularies disjoint"
);
assert!(
DelegationSubjectKind::from_wire(2).is_some(),
"the transposed kind half is still a recognised kind, so the rejection is \
attributable to the role alone"
);
let mutant = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert!(matches!(
decode_fields(&mutant),
Err(TrustError::DelegationVerification)
));
let seat = payload_bytes(&seat_claim());
let seat_role_at = role_offset(&seat);
let mut swapped = seat.clone();
swapped[2] = 0x03;
swapped[seat_role_at + 1] = 0x02;
assert!(
DelegationSubjectKind::from_wire(3).is_none(),
"3 must not be a subject kind"
);
assert!(matches!(
decode_fields(&envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&swapped,
&SIGNATURE,
)),
Err(TrustError::DelegationVerification)
));
decode_fields(&envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&canonical,
&SIGNATURE,
))
.unwrap();
decode_fields(&envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&seat,
&SIGNATURE,
))
.unwrap();
}
#[test]
fn changing_only_the_subject_kind_byte_is_caught_by_the_pair_rule_not_the_kind_check() {
let canonical = payload_bytes(&claim());
let role_at = role_offset(&canonical);
let mut payload = canonical.clone();
payload[2] = 0x02;
let kind = DelegationSubjectKind::from_wire(2).expect("seat is a recognised kind");
let role = DelegationRole::from_wire(u64::from(canonical[role_at + 1]))
.expect("operational is a recognised role");
assert!(
!kind.permits(role),
"the mutant's pair must be the thing that is wrong with it"
);
assert!(matches!(
decode_fields(&envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
)),
Err(TrustError::DelegationVerification)
));
}
#[test]
fn decode_refuses_an_empty_subject_value_with_no_help_from_the_byte_compare() {
let mut payload = vec![0xa6, 0x01, 0x01, 0x02, 0x60, 0x03, 0x58, 0x20]; payload.extend_from_slice(&delegated_key());
payload.extend_from_slice(&[0x04, 0x02, 0x05, 0x1b]);
payload.extend_from_slice(&1_700_000_000_000u64.to_be_bytes());
payload.extend_from_slice(&[0x06, 0x19, 0x01, 0x2c]);
let mutant = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert!(matches!(
decode_fields(&mutant),
Err(TrustError::DelegationVerification)
));
let mut ok_payload = vec![0xa6, 0x01, 0x01, 0x02, 0x61, b'x', 0x03, 0x58, 0x20];
ok_payload.extend_from_slice(&delegated_key());
ok_payload.extend_from_slice(&[0x04, 0x02, 0x05, 0x1b]);
ok_payload.extend_from_slice(&1_700_000_000_000u64.to_be_bytes());
ok_payload.extend_from_slice(&[0x06, 0x19, 0x01, 0x2c]);
let ok = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&ok_payload,
&SIGNATURE,
);
assert_eq!(decode_fields(&ok).unwrap().claim.subject_value, "x");
}
#[test]
fn decode_refuses_an_unusable_delegated_key_with_no_help_from_the_byte_compare() {
let canonical = payload_bytes(&claim());
let delegated = delegated_key();
let at = canonical
.windows(KEY_LEN)
.position(|w| w == delegated)
.expect("the delegated key is in the payload");
let mut refused = 0;
for bad_key in unusable_keys() {
let mut payload = canonical.clone();
payload[at..at + KEY_LEN].copy_from_slice(&bad_key);
let mutant = envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&payload,
&SIGNATURE,
);
assert!(
matches!(
decode_fields(&mutant),
Err(TrustError::DelegationVerification)
),
"an unusable delegated key was carried through the decoder"
);
refused += 1;
}
assert_eq!(refused, 3, "every unusable key shape must have been tried");
decode_fields(&envelope_bytes(
&protected_bytes(CONTENT_TYPE, &ROOT_KEY),
&canonical,
&SIGNATURE,
))
.unwrap();
}