fix(homecore-server): provision stable HAP identity securely

This commit is contained in:
ruv
2026-07-27 15:08:52 -04:00
parent 42684a7a1e
commit e7c598e64c
3 changed files with 32 additions and 7 deletions
+19 -1
View File
@@ -11,6 +11,7 @@ use homecore::HomeCore;
pub(crate) struct HapRuntimeConfig {
pub bind_addr: Option<SocketAddr>,
pub device_id: Option<String>,
pub setup_code: Option<String>,
pub advertise_addr: Option<IpAddr>,
pub hostname: String,
pub instance_name: String,
@@ -84,7 +85,24 @@ pub(crate) async fn start(hc: &HomeCore, config: HapRuntimeConfig) -> Result<Hap
config.hostname.clone(),
advertise_addr,
)?);
let pairings = Arc::new(PairingStore::open(&config.pairing_store)?);
let pairings = if config.pairing_store.exists() {
if config.setup_code.is_some() {
tracing::warn!(
"ignoring --hap-setup-code because the pairing store already exists"
);
}
PairingStore::open(&config.pairing_store)?
} else {
let setup_code = config.setup_code.as_deref().ok_or_else(|| {
anyhow::anyhow!("--hap-setup-code is required when creating a HAP pairing store")
})?;
PairingStore::create(
&config.pairing_store,
homecore_hap::SetupCode::parse(setup_code)?,
Some(device_id.to_owned()),
)?
};
let pairings = Arc::new(pairings);
let record =
HapServiceRecord::bridge(config.instance_name.clone(), bind_addr.port(), device_id);
let bridge = HapBridge::new(record);
+7 -1
View File
@@ -149,6 +149,11 @@ struct Cli {
#[arg(long, env = "HOMECORE_HAP_DEVICE_ID")]
hap_device_id: Option<String>,
/// HAP setup code in `XXX-XX-XXX` form. Required only when creating a
/// pairing store for the first time and never persisted in plaintext.
#[arg(long, env = "HOMECORE_HAP_SETUP_CODE", hide_env_values = true)]
hap_setup_code: Option<String>,
/// LAN address published in the HAP mDNS record. Required when HAP is enabled.
#[arg(long, env = "HOMECORE_HAP_ADVERTISE_ADDR")]
hap_advertise_addr: Option<std::net::IpAddr>,
@@ -177,7 +182,7 @@ struct Cli {
#[tokio::main]
async fn main() -> Result<()> {
init_tracing();
let cli = Cli::parse();
let mut cli = Cli::parse();
let has_tokens = std::env::var("HOMECORE_TOKENS")
.map(|value| !value.trim().is_empty())
.unwrap_or(false);
@@ -325,6 +330,7 @@ async fn main() -> Result<()> {
hap::HapRuntimeConfig {
bind_addr: cli.hap_bind,
device_id: cli.hap_device_id.clone(),
setup_code: cli.hap_setup_code.take(),
advertise_addr: cli.hap_advertise_addr,
hostname: cli.hap_hostname.clone(),
instance_name: cli.hap_instance_name.clone(),
+6 -5
View File
@@ -68,11 +68,12 @@ registry currently returns a valid empty list.
native plugins must be linked into the binary and registered in code.
- HAP is disabled by default. Enabling it requires an explicit bind address,
stable six-octet device identifier, advertised LAN address, hostname, and
durable pairing-store path.
- The HAP listener fails closed for cryptographic phases that are unavailable
in the selected build. Do not claim Apple Home interoperability unless the
Pair-Setup, Pair-Verify, and encrypted transport conformance tests for that
build pass.
durable pairing-store path. First provisioning also requires an explicit
non-trivial `XXX-XX-XXX` setup code; only its SRP verifier is persisted.
- The HAP listener implements SRP-6a Pair-Setup, X25519/Ed25519 Pair-Verify,
ChaCha20-Poly1305 HAP IP records, controller administration, and paired-state
mDNS updates. Internal protocol/tamper/replay tests pass; external Apple Home
certification is not claimed.
- STT and TTS are provider contracts; a deployment must supply real providers.
The built-in disabled providers return typed errors rather than fabricated
speech results.