use super::ssdf::{cdxa_note, standard_references_eucc};
use super::*;
use crate::model::AttestationRuleFamily;
impl ComplianceChecker {
pub(crate) fn check_eucc_substantial(
&self,
sbom: &NormalizedSbom,
violations: &mut Vec<Violation>,
) {
let sidecar = self.sidecar.as_ref();
let pp_present = sidecar
.and_then(|s| s.eucc_protection_profile_id.as_deref())
.is_some_and(|s| !s.is_empty());
if !pp_present {
violations.push(Violation {
severity: ViolationSeverity::Error,
category: ViolationCategory::DocumentMetadata,
message: "[EUCC] Missing Common Criteria Protection Profile reference — set sidecar `eucc_protection_profile_id`".to_string(),
element: None,
requirement: "EUCC Substantial: Protection Profile reference".to_string(),
rule_id: "SBOM-EUCC-PP",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
let toe_present = sidecar
.and_then(|s| s.eucc_target_of_evaluation.as_deref())
.is_some_and(|s| !s.is_empty());
if !toe_present {
violations.push(Violation {
severity: ViolationSeverity::Error,
category: ViolationCategory::DocumentMetadata,
message: "[EUCC] Missing Target of Evaluation reference — set sidecar `eucc_target_of_evaluation`".to_string(),
element: None,
requirement: "EUCC Substantial: Target of Evaluation reference".to_string(),
rule_id: "SBOM-EUCC-TOE",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
let itsef_present = sidecar
.and_then(|s| s.eucc_itsef_identifier.as_deref())
.is_some_and(|s| !s.is_empty());
if !itsef_present {
violations.push(Violation {
severity: ViolationSeverity::Error,
category: ViolationCategory::DocumentMetadata,
message: "[EUCC] Missing ITSEF (IT Security Evaluation Facility) identifier — set sidecar `eucc_itsef_identifier`".to_string(),
element: None,
requirement: "EUCC Substantial: ITSEF identifier".to_string(),
rule_id: "SBOM-EUCC-ITSEF",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
match sidecar.and_then(|s| s.eucc_valid_until) {
None => {
violations.push(Violation {
severity: ViolationSeverity::Error,
category: ViolationCategory::DocumentMetadata,
message: "[EUCC] Missing certificate valid-until date — set sidecar `eucc_valid_until`".to_string(),
element: None,
requirement: "EUCC Substantial: certificate valid-until date".to_string(),
rule_id: "SBOM-EUCC-VALIDITY",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
Some(until) if until <= self.now() => {
violations.push(Violation {
severity: ViolationSeverity::Error,
category: ViolationCategory::DocumentMetadata,
message: format!(
"[EUCC] EUCC certificate has expired (valid-until {})",
until.format("%Y-%m-%d")
),
element: None,
requirement: "EUCC Substantial: certificate validity".to_string(),
rule_id: "SBOM-EUCC-VALIDITY",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
Some(until) if until <= self.now() + chrono::Duration::days(180) => {
violations.push(Violation {
severity: ViolationSeverity::Warning,
category: ViolationCategory::DocumentMetadata,
message: format!(
"[EUCC] EUCC certificate expires within 180 days ({})",
until.format("%Y-%m-%d")
),
element: None,
requirement: "EUCC Substantial: certificate validity".to_string(),
rule_id: "SBOM-EUCC-VALIDITY",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
Some(_) => {}
}
let ctx = ComplianceContext::new(self, sbom);
let cdxa_eucc_attested = ctx
.evidence_for(AttestationRuleFamily::Cra)
.iter()
.any(|s| standard_references_eucc(s.standard));
let eucc_ref_present = cdxa_eucc_attested
|| sbom.components.values().any(|c| {
c.external_refs.iter().any(|r| {
let url = r.url.to_lowercase();
matches!(
r.ref_type,
crate::model::ExternalRefType::Certification
| crate::model::ExternalRefType::Attestation
) && (url.contains("eucc") || url.contains("common-criteria"))
})
});
if !eucc_ref_present {
let mut message = "[EUCC] No Certification/Attestation external reference points at an EUCC URL (recommended)".to_string();
if let Some(note) = cdxa_note(
ctx.attestation_declarations(),
AttestationRuleFamily::Cra,
&|s, _| standard_references_eucc(s),
self.now(),
"an EUCC / Common Criteria certification",
) {
message.push_str(¬e);
}
violations.push(Violation {
severity: ViolationSeverity::Warning,
category: ViolationCategory::DocumentMetadata,
message,
element: None,
requirement: "EUCC Substantial: Certification external reference".to_string(),
rule_id: "SBOM-EUCC-CERTREF",
component_id: None,
counts: None,
standard_refs: Vec::new(),
});
}
}
}