keysources: expose host certs through KeySource trait
- KeydbSource implements KeySource::host_certs(), delegating to the inherent host_certs() — surfaces the | HC | / | HC2 | certs already parsed from keydb.cfg by libfreemkv's parser, so the OEM cert route collects them across the keysource layer. No new parsing. - OnlineSource::host_certs() is a no-op stub: returns empty with zero network access (no client fetch, no server endpoint). Online host-cert serving is deferred. TODO(owner) marker left in place. Tests: trait host_certs returns the keydb HC row; empty when keydb missing; online host_certs is an empty no-op without network.
This commit is contained in:
@@ -98,6 +98,14 @@ impl KeydbSource {
|
||||
}
|
||||
|
||||
impl KeySource for KeydbSource {
|
||||
/// Expose the keydb's host certs through the trait — the OEM/AACS cert-auth
|
||||
/// route collects them across every source via this method. Delegates to the
|
||||
/// inherent [`KeydbSource::host_certs`] (same `| HC |`/`| HC2 |` rows parsed
|
||||
/// by libfreemkv's keydb parser); no new parsing.
|
||||
fn host_certs(&self) -> Vec<HostCert> {
|
||||
KeydbSource::host_certs(self)
|
||||
}
|
||||
|
||||
fn next_key(&mut self, inputs: &DiscInputs) -> Option<Key> {
|
||||
// On the first ask, parse the keydb once and build the ordered candidate
|
||||
// list; later asks just advance the cursor. A missing/unreadable keydb
|
||||
@@ -235,4 +243,40 @@ mod tests {
|
||||
.is_empty()
|
||||
);
|
||||
}
|
||||
|
||||
/// The KeySource TRAIT method exposes the keydb's host cert(s) — this is the
|
||||
/// path the OEM/AACS cert-auth route collects certs through. A keydb with a
|
||||
/// `| HC |` row must surface a HostCert via `KeySource::host_certs`, so the
|
||||
/// handshake (which iterates `opts.key_sources[..].host_certs()`) finds it.
|
||||
/// Placeholder all-zero material (never a real key) — same convention as
|
||||
/// libfreemkv's own `parse_host_cert` test.
|
||||
#[test]
|
||||
fn trait_host_certs_returns_keydb_hc_row() {
|
||||
let dir = std::env::temp_dir().join(format!("fmk_hc_{}", std::process::id()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let path = dir.join("keydb.cfg");
|
||||
let line = format!(
|
||||
"| HC | HOST_PRIV_KEY 0x{} | HOST_CERT 0x{}\n",
|
||||
"00".repeat(20),
|
||||
"00".repeat(92)
|
||||
);
|
||||
std::fs::write(&path, line).unwrap();
|
||||
|
||||
let src = KeydbSource::new(&path);
|
||||
// Consult through the TRAIT, exactly as the OEM route does.
|
||||
let certs = KeySource::host_certs(&src);
|
||||
assert_eq!(certs.len(), 1, "trait host_certs must surface the HC row");
|
||||
assert_eq!(certs[0].certificate.len(), 92);
|
||||
|
||||
std::fs::remove_dir_all(&dir).ok();
|
||||
}
|
||||
|
||||
/// Zero certs from a (missing) keydb through the TRAIT method — the OEM route
|
||||
/// sees an empty vec here and, with no other source supplying a cert, fails
|
||||
/// gracefully with `AacsNoHostCert` rather than panicking.
|
||||
#[test]
|
||||
fn trait_host_certs_empty_when_keydb_missing() {
|
||||
let src = KeydbSource::new("/nonexistent/path/keydb.cfg");
|
||||
assert!(KeySource::host_certs(&src).is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,6 +305,16 @@ impl KeySource for OnlineSource {
|
||||
fn errored(&self) -> bool {
|
||||
self.errored
|
||||
}
|
||||
|
||||
fn host_certs(&self) -> Vec<libfreemkv::aacs::HostCert> {
|
||||
// NO-OP STUB. The online service does not serve host certs today: there
|
||||
// is no client-side fetch and no server-side endpoint for them. Returning
|
||||
// empty makes the OEM cert route fall back to whatever other source
|
||||
// (e.g. the keydb) supplies — and fail gracefully if none does. No
|
||||
// network is touched here.
|
||||
// TODO(owner): online host-cert serving — design when 0x83 cert is recovered
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_uk(hex: &str) -> Option<[u8; 16]> {
|
||||
@@ -381,6 +391,20 @@ mod tests {
|
||||
))));
|
||||
}
|
||||
|
||||
/// The online source serves NO host certs today (no fetch, no endpoint).
|
||||
/// `host_certs()` must return empty WITHOUT touching the network, so the OEM
|
||||
/// route falls back to whatever else (the keydb) supplies. Uses a non-empty
|
||||
/// base URL to prove the empty result isn't merely "no service configured" —
|
||||
/// it's the deliberate no-op stub.
|
||||
#[test]
|
||||
fn host_certs_is_noop_empty_no_network() {
|
||||
let src = OnlineSource::new("http://example.invalid/keys", "secret");
|
||||
assert!(
|
||||
KeySource::host_certs(&src).is_empty(),
|
||||
"online host_certs must be an empty no-op (no network)"
|
||||
);
|
||||
}
|
||||
|
||||
// ── resolve_and_guard ──────────────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user