use corim::profile::{MatchContext, Profile};
use corim::types::common::MeasuredElement;
use corim::types::corim::ProfileChoice;
use corim::types::environment::EnvironmentMap;
use corim::types::measurement::{Digest, MeasurementMap, MeasurementValuesMap};
use corim::types::triples::{
CesCondition, ConditionalEndorsementSeriesTriple, ConditionalSeriesRecord, ReferenceTriple,
};
use corim::validate::{
apply_endorsement_series, apply_endorsement_series_with_profile, match_reference_values,
match_reference_values_with_profile, EvidenceClaim,
};
fn ctx() -> MatchContext {
MatchContext::new()
}
struct PassthroughProfile {
id: ProfileChoice,
}
impl Profile for PassthroughProfile {
fn identifier(&self) -> &ProfileChoice {
&self.id
}
}
struct AlwaysMatchProfile {
id: ProfileChoice,
}
impl Profile for AlwaysMatchProfile {
fn identifier(&self) -> &ProfileChoice {
&self.id
}
fn match_measurement(
&self,
_reference: &MeasurementMap,
_evidence: &MeasurementMap,
_ctx: &MatchContext,
) -> Option<bool> {
Some(true)
}
}
struct AlwaysRejectProfile {
id: ProfileChoice,
}
impl Profile for AlwaysRejectProfile {
fn identifier(&self) -> &ProfileChoice {
&self.id
}
fn match_measurement(
&self,
_reference: &MeasurementMap,
_evidence: &MeasurementMap,
_ctx: &MatchContext,
) -> Option<bool> {
Some(false)
}
}
fn test_id() -> ProfileChoice {
ProfileChoice::Uri("urn:example:test-profile".into())
}
fn ref_with_digest(byte: u8) -> ReferenceTriple {
ReferenceTriple::new(
EnvironmentMap::for_class("ACME", "Widget"),
vec![MeasurementMap {
mkey: None,
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![byte; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
)
}
fn evidence_with_digest(byte: u8) -> EvidenceClaim {
EvidenceClaim {
environment: EnvironmentMap::for_class("ACME", "Widget"),
measurements: vec![MeasurementMap {
mkey: None,
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![byte; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
}
}
#[test]
fn with_profile_none_matches_default_behavior_on_match() {
let triples = vec![ref_with_digest(0xAA)];
let evidence = vec![evidence_with_digest(0xAA)];
let default = match_reference_values(&triples, &evidence);
let with_none = match_reference_values_with_profile(
&triples,
&evidence,
None::<&dyn corim::profile::Profile>,
&ctx(),
);
assert_eq!(default.len(), 1);
assert_eq!(with_none.len(), default.len());
}
#[test]
fn with_profile_none_matches_default_behavior_on_mismatch() {
let triples = vec![ref_with_digest(0xAA)];
let evidence = vec![evidence_with_digest(0xBB)];
let default = match_reference_values(&triples, &evidence);
let with_none = match_reference_values_with_profile(
&triples,
&evidence,
None::<&dyn corim::profile::Profile>,
&ctx(),
);
assert_eq!(default.len(), 0);
assert_eq!(with_none.len(), 0);
}
#[test]
fn passthrough_profile_returns_none_so_defers_to_core() {
let profile = PassthroughProfile { id: test_id() };
let triples = vec![ref_with_digest(0xAA)];
let evidence_match = vec![evidence_with_digest(0xAA)];
let evidence_miss = vec![evidence_with_digest(0xBB)];
let claims_match =
match_reference_values_with_profile(&triples, &evidence_match, Some(&profile), &ctx());
let claims_miss =
match_reference_values_with_profile(&triples, &evidence_miss, Some(&profile), &ctx());
assert_eq!(
claims_match.len(),
1,
"passthrough should match when core matches"
);
assert_eq!(
claims_miss.len(),
0,
"passthrough should miss when core misses"
);
}
#[test]
fn always_match_profile_overrides_core_mismatch() {
let profile = AlwaysMatchProfile { id: test_id() };
let triples = vec![ref_with_digest(0xAA)];
let evidence = vec![evidence_with_digest(0xBB)];
let core_claims = match_reference_values(&triples, &evidence);
assert_eq!(core_claims.len(), 0);
let profile_claims =
match_reference_values_with_profile(&triples, &evidence, Some(&profile), &ctx());
assert_eq!(profile_claims.len(), 1, "AlwaysMatch should force a match");
}
#[test]
fn always_reject_profile_blocks_core_match() {
let profile = AlwaysRejectProfile { id: test_id() };
let triples = vec![ref_with_digest(0xAA)];
let evidence = vec![evidence_with_digest(0xAA)];
let core_claims = match_reference_values(&triples, &evidence);
assert_eq!(core_claims.len(), 1);
let profile_claims =
match_reference_values_with_profile(&triples, &evidence, Some(&profile), &ctx());
assert_eq!(
profile_claims.len(),
0,
"AlwaysReject should block the match"
);
}
#[test]
fn empty_triples_with_profile_yields_empty() {
let profile = AlwaysMatchProfile { id: test_id() };
let evidence = vec![evidence_with_digest(0xAA)];
let claims = match_reference_values_with_profile(&[], &evidence, Some(&profile), &ctx());
assert!(claims.is_empty());
}
#[test]
fn environment_mismatch_skipped_before_profile_consulted() {
let profile = AlwaysMatchProfile { id: test_id() };
let triples = vec![ReferenceTriple::new(
EnvironmentMap::for_class("ACME", "Widget"),
vec![MeasurementMap {
mkey: None,
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![0xAA; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
)];
let evidence = vec![EvidenceClaim {
environment: EnvironmentMap::for_class("OTHER", "Thing"),
measurements: vec![MeasurementMap {
mkey: None,
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![0xAA; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
}];
let claims = match_reference_values_with_profile(&triples, &evidence, Some(&profile), &ctx());
assert!(
claims.is_empty(),
"environment mismatch should still gate the match"
);
}
fn build_series_triple(
selection_byte: u8,
addition_byte: u8,
) -> ConditionalEndorsementSeriesTriple {
let condition = CesCondition {
environment: EnvironmentMap::for_class("ACME", "Widget"),
claims_list: Vec::new(),
authorized_by: None,
};
let selection = vec![MeasurementMap {
mkey: Some(MeasuredElement::Text("k".into())),
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![selection_byte; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}];
let addition = vec![MeasurementMap {
mkey: Some(MeasuredElement::Text("k".into())),
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![addition_byte; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}];
let record = ConditionalSeriesRecord::new(selection, addition);
ConditionalEndorsementSeriesTriple::new(condition, vec![record])
}
#[test]
fn endorsement_series_with_profile_none_matches_default() {
let triples = vec![build_series_triple(0xAA, 0xCC)];
let evidence = vec![EvidenceClaim {
environment: EnvironmentMap::for_class("ACME", "Widget"),
measurements: vec![MeasurementMap {
mkey: Some(MeasuredElement::Text("k".into())),
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![0xAA; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
}];
let default = apply_endorsement_series(&triples, &evidence).unwrap();
let with_none = apply_endorsement_series_with_profile(
&triples,
&evidence,
None::<&dyn corim::profile::Profile>,
&ctx(),
)
.unwrap();
assert_eq!(default.len(), 1);
assert_eq!(with_none.len(), default.len());
}
#[test]
fn endorsement_series_always_match_profile_forces_endorsement() {
let profile = AlwaysMatchProfile { id: test_id() };
let triples = vec![build_series_triple(0xAA, 0xCC)];
let evidence = vec![EvidenceClaim {
environment: EnvironmentMap::for_class("ACME", "Widget"),
measurements: vec![MeasurementMap {
mkey: Some(MeasuredElement::Text("k".into())),
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![0xBB; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
}];
let core = apply_endorsement_series(&triples, &evidence).unwrap();
assert_eq!(core.len(), 0, "core should not endorse");
let with_profile =
apply_endorsement_series_with_profile(&triples, &evidence, Some(&profile), &ctx()).unwrap();
assert_eq!(with_profile.len(), 1, "profile should force endorsement");
}
#[test]
fn endorsement_series_always_reject_profile_blocks_endorsement() {
let profile = AlwaysRejectProfile { id: test_id() };
let triples = vec![build_series_triple(0xAA, 0xCC)];
let evidence = vec![EvidenceClaim {
environment: EnvironmentMap::for_class("ACME", "Widget"),
measurements: vec![MeasurementMap {
mkey: Some(MeasuredElement::Text("k".into())),
mval: MeasurementValuesMap {
digests: Some(vec![Digest::new(7, vec![0xAA; 32])]),
..MeasurementValuesMap::default()
},
authorized_by: None,
}],
}];
let core = apply_endorsement_series(&triples, &evidence).unwrap();
assert_eq!(core.len(), 1, "core should endorse");
let with_profile =
apply_endorsement_series_with_profile(&triples, &evidence, Some(&profile), &ctx()).unwrap();
assert_eq!(with_profile.len(), 0, "profile should block endorsement");
}