#![cfg(test)]
use super::*;
#[test]
fn a_signed_delegation_verifies_and_carries_back_every_field() {
let key = root();
let cose = sign_delegation(&key, &claim()).unwrap();
let verified = verify_delegation(&cose, &key.public_key_bytes(), DOMAIN, ORIGIN).unwrap();
assert_eq!(verified.root_public_key, key.public_key_bytes());
assert_eq!(verified.claim, claim());
assert_eq!(
verified.claim.delegated_public_key,
operational().public_key_bytes()
);
assert_eq!(verified.claim.role, DelegationRole::Operational);
assert_eq!(verified.to_cose_bytes(), cose);
}
#[test]
fn the_two_phase_path_produces_the_same_artifact_as_the_one_shot_path() {
let key = root();
let root_key = key.public_key_bytes();
let preimage = delegation_preimage(&root_key, &claim());
let signature = key.sign(&preimage);
let assembled = assemble_delegation(&root_key, &claim(), &signature).unwrap();
assert_eq!(assembled, sign_delegation(&key, &claim()).unwrap());
assert_eq!(
preimage,
cbor::sig_structure_bytes(&protected_for(&key), &encoding::payload_bytes(&claim()))
);
assert_eq!(&preimage[..12], b"\x84\x6aSignature1");
let external_aad_at = 12 + 2 + encoding::PROTECTED_LEN;
assert_eq!(
preimage[external_aad_at], 0x40,
"external_aad must be the zero-length byte string"
);
assert_eq!(
&preimage[12..14],
&[0x58, 0x4f],
"the protected bstr head precedes it — 79 bytes"
);
}
#[test]
fn assembly_refuses_a_signature_that_does_not_match_its_own_bytes() {
let key = root();
let root_key = key.public_key_bytes();
let good = key.sign(&delegation_preimage(&root_key, &claim()));
let mut flipped = good;
flipped[0] ^= 0x01;
assert!(matches!(
assemble_delegation(&root_key, &claim(), &flipped),
Err(TrustError::DelegationVerification)
));
let wrong_signer = attacker().sign(&delegation_preimage(&root_key, &claim()));
assert!(assemble_delegation(&root_key, &claim(), &wrong_signer).is_err());
let wrong_claim = key.sign(&delegation_preimage(&root_key, &claim_for(OTHER_ORIGIN)));
assert!(assemble_delegation(&root_key, &claim(), &wrong_claim).is_err());
assert!(assemble_delegation(&root_key, &claim(), &good).is_ok());
}
#[test]
fn issuance_is_deterministic() {
let key = root();
assert_eq!(
sign_delegation(&key, &claim()).unwrap(),
sign_delegation(&key, &claim()).unwrap()
);
}
#[test]
fn issuance_refuses_an_invalid_kind_role_pair_through_both_entry_points() {
let key = root();
let root_key = key.public_key_bytes();
let mut refused = 0;
for (kind, role) in [
(DelegationSubjectKind::Domain, DelegationRole::SpeaksFor),
(DelegationSubjectKind::Seat, DelegationRole::Operational),
] {
let mut c = claim();
c.subject_kind = kind;
c.role = role;
assert!(
matches!(
sign_delegation(&key, &c),
Err(TrustError::DelegationEncoding { .. })
),
"({kind:?}, {role:?}) was issuable through the convenience path"
);
let signature = key.sign(&delegation_preimage(&root_key, &c));
assert!(
matches!(
assemble_delegation(&root_key, &c, &signature),
Err(TrustError::DelegationEncoding { .. })
),
"({kind:?}, {role:?}) was issuable through the two-phase path"
);
refused += 1;
}
assert_eq!(refused, 2, "both invalid pairs must have been tried");
let mut issued = 0;
for (c, kind_expected) in [(claim(), DOMAIN), (seat_claim_for(ORIGIN), SEAT)] {
let cose = sign_delegation(&key, &c).unwrap();
assert_eq!(
verify_delegation(&cose, &root_key, kind_expected, &c.subject_value)
.unwrap()
.claim,
c
);
issued += 1;
}
assert_eq!(issued, 2, "both valid pairs must have been issued");
}
#[test]
fn a_subject_of_any_length_that_issues_also_verifies_by_both_paths() {
let key = root();
let root_key = key.public_key_bytes();
let mut checked = 0;
for len in [23, 24, 255, 256, 3884, 3885, 4096, 65_535, 65_536] {
let claim = claim_at(&"o".repeat(len), 300);
let artifact = sign_delegation(&key, &claim).unwrap();
let verified =
verify_delegation(&artifact, &root_key, DOMAIN, &claim.subject_value).unwrap();
assert_eq!(verified.claim, claim, "length {len}");
let signature = key.sign(&delegation_preimage(&root_key, &claim));
let assembled = assemble_delegation(&root_key, &claim, &signature).unwrap();
assert_eq!(assembled, artifact, "length {len}");
checked += 1;
}
assert_eq!(checked, 9, "every length must have been exercised");
}
#[test]
fn issuance_refuses_an_empty_subject_value_and_an_unusable_delegated_key() {
let key = root();
let root_key = key.public_key_bytes();
let empty = claim_at("", 300);
assert!(matches!(
sign_delegation(&key, &empty),
Err(TrustError::DelegationEncoding { .. })
));
let mut identity_point = [0u8; 32];
identity_point[0] = 1;
let mut refused = 0;
for bad_key in [[0u8; 32], [0xffu8; 32], identity_point] {
let mut c = claim();
c.delegated_public_key = bad_key;
assert!(
matches!(
sign_delegation(&key, &c),
Err(TrustError::DelegationEncoding { .. })
),
"an unusable delegated key was issuable"
);
let signature = key.sign(&delegation_preimage(&root_key, &c));
assert!(matches!(
assemble_delegation(&root_key, &c, &signature),
Err(TrustError::DelegationEncoding { .. })
));
refused += 1;
}
assert_eq!(refused, 3, "every unusable key shape must have been tried");
sign_delegation(&key, &claim()).unwrap();
}