Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/Skidbladnir

crates/installer/nordisk-pairing/src/mtls.rs

//! **The installer's mutual TLS — valid during bootstrap only.**
//!
//! The owner, 2026-09-24: the installer has a temporary mTLS certificate the
//! installing machines know, so they can contact the installer, which feeds
//! them what they need; and it is valid ONLY during bootstrap.
//!
//! One installer CA per MEDIUM (it was per lay until 2026-09-24 evening, and
//! that made every lay a new medium): minted by the laptop when the medium is
//! composed, its key kept beside the medium's receipt on the laptop (0600)
//! and pushed to each new front's door — never onto the medium, never onto a
//! box. It issues exactly three kinds of certificate:
//!
//! * **the door's** — the front's server certificate, for its utility address;
//!   every box PINS the installer CA, so a box talks to this door or to nothing
//!   (the join used to be plain HTTP, and a box believed whatever answered);
//! * **the bootstrap client certificate** — ON THE MEDIUM, with its key, the
//!   same for every box. A key on a medium is only as secret as the medium
//!   (it is uploaded to the cloud's storage), so this certificate is weak on
//!   purpose: it may only JOIN, the door accepts it only for a slot that has
//!   not joined yet, and it is refused outright once every slot has joined;
//! * **a box's own certificate** — signed at the first join from a request for
//!   a key the box minted itself (the private half never leaves the box). From
//!   then on that box speaks with it, and the bootstrap certificate is refused
//!   for its slot.
//!
//! **"Valid during bootstrap only" is the DOOR's rule, not an expiry.** When
//! every slot has joined the door refuses the bootstrap certificate outright
//! (`join-withdrawn`), and a slot that has joined refuses it for good
//! (`join-spent`) — per lay, because each lay's door has its own ledger. The
//! CA's own lifetime is the caller's choice, tied to the medium: long enough
//! that one medium serves many lays, and the medium is recomposed (with a new
//! CA) before it ends ([`cert_left`]). Pairing inside the tunnel then runs on
//! gunnar's own issuer, as it always has.
//!
//! Pure Rust (`rcgen` + `rustls` on `ring`, X25519MLKEM768 first —
//! [`crate::pqtls`]), blocking sockets: an OS-less
//! PID 1 and a laptop both drive it without an async runtime.

use rcgen::{BasicConstraints, CertificateParams, CertificateSigningRequestParams, DistinguishedName, DnType, ExtendedKeyUsagePurpose, IsCa, KeyPair, KeyUsagePurpose, SanType};
use rustls::pki_types::pem::PemObject;
use rustls::pki_types::{CertificateDer, PrivateKeyDer, ServerName};
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
use std::time::Duration;

/// The CN every bootstrap client certificate carries. A box's own certificate
/// carries its NAME; the door tells them apart by this.
pub const BOOTSTRAP_CN: &str = "bootstrap";

/// The CN of the installer's own client certificate — the ONLY client a VM's
/// bootstrap listener serves (0.3.0). A box name can never be this.
pub const INSTALLER_CN: &str = "installer";

/// **The one name every VM's bootstrap listener answers to** — a DNS SAN on
/// the bootstrap certificate and on every box certificate. The installer
/// checks the chain against the installer CA and this name, never the
/// address: the cloud hands the address out after the medium is composed.
pub const VM_SERVER_NAME: &str = "bootstrap.installer";

fn vm_sans() -> Vec<SanType> {
    match VM_SERVER_NAME.to_string().try_into() {
        Ok(n) => vec![SanType::DnsName(n)],
        Err(_) => Vec::new(),
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MtlsError(pub String);

impl std::fmt::Display for MtlsError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "REFUSED [pairing-mtls] {}", self.0)
    }
}

impl std::error::Error for MtlsError {}

fn e(what: &str) -> impl Fn(rcgen::Error) -> MtlsError + '_ {
    move |err| MtlsError(format!("{what}: {err}"))
}

/// A certificate and its private key, both PEM.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Issued {
    pub cert_pem: String,
    pub key_pem: String,
}

/// **The installer CA.** `key_pem` stays on the front.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct InstallerCa {
    pub cert_pem: String,
    pub key_pem: String,
}

fn window(valid_for: Duration) -> (time::OffsetDateTime, time::OffsetDateTime) {
    // Five minutes of back-dating: a fresh box's clock is set from the front
    // only after it has joined, and a certificate "not yet valid" by a few
    // seconds of skew would refuse the very join that fixes the clock.
    window_back(valid_for, time::Duration::minutes(5))
}

fn window_back(valid_for: Duration, back: time::Duration) -> (time::OffsetDateTime, time::OffsetDateTime) {
    let now = time::OffsetDateTime::now_utc();
    (now - back, now + time::Duration::seconds(valid_for.as_secs() as i64))
}

/// **How far the DOOR's certificate is back-dated: a day.** The door issues
/// it when it starts, from the front's clock, and the BOX checks it with its
/// own clock — which has not been set yet (it is set from the front AFTER the
/// join, `gunnar-clock` fed by the door). A box whose clock runs behind the
/// front's by more than the five minutes the other certificates allow would
/// refuse the only door that can fix it. Nothing about the door certificate
/// is weaker for it: the CA is pinned, and the address is in the SAN.
pub const DOOR_BACKDATE: Duration = Duration::from_secs(24 * 3600);

/// **How long a certificate (PEM) has left**, from its `notAfter`; zero once
/// it has ended. `now_unix` is injected so a caller's test does not wait. The
/// laptop asks it of a medium's installer CA (re-mint and recompose before it
/// ends), the door of its CA (its own certificate lives as long as the CA).
pub fn cert_left(pem: &str, now_unix: i64) -> Result<Duration, MtlsError> {
    let (_, p) = x509_parser::pem::parse_x509_pem(pem.trim().as_bytes()).map_err(|err| MtlsError(format!("not a PEM certificate: {err}")))?;
    let cert = p.parse_x509().map_err(|err| MtlsError(format!("not an X.509 certificate: {err}")))?;
    let end = cert.validity().not_after.timestamp();
    Ok(Duration::from_secs(end.saturating_sub(now_unix).max(0) as u64))
}

/// Seconds since the epoch, now (for [`cert_left`]).
pub fn now_unix() -> i64 {
    time::OffsetDateTime::now_utc().unix_timestamp()
}

impl InstallerCa {
    /// Mint the CA for one lay of `estate`, valid for `valid_for` (hours).
    pub fn mint(estate: &str, valid_for: Duration) -> Result<InstallerCa, MtlsError> {
        let key = KeyPair::generate().map_err(e("the CA key"))?;
        let mut p = ca_params(&format!("nordisk-pairing installer CA — {estate}"));
        (p.not_before, p.not_after) = window(valid_for);
        let cert = p.self_signed(&key).map_err(e("the CA certificate"))?;
        Ok(InstallerCa { cert_pem: cert.pem(), key_pem: key.serialize_pem() })
    }

    /// The CA as an `rcgen` issuer, rebuilt from its PEM and key.
    fn issuer(&self) -> Result<rcgen::Issuer<'static, KeyPair>, MtlsError> {
        let key = KeyPair::from_pem(&self.key_pem).map_err(e("the CA key"))?;
        rcgen::Issuer::from_ca_cert_pem(&self.cert_pem, key).map_err(e("the CA certificate"))
    }

    fn leaf(&self, cn: &str, sans: Vec<SanType>, purpose: Vec<ExtendedKeyUsagePurpose>, valid_for: Duration) -> Result<Issued, MtlsError> {
        self.leaf_back(cn, sans, purpose, window(valid_for))
    }

    fn leaf_back(&self, cn: &str, sans: Vec<SanType>, purpose: Vec<ExtendedKeyUsagePurpose>, validity: (time::OffsetDateTime, time::OffsetDateTime)) -> Result<Issued, MtlsError> {
        let ca = self.issuer()?;
        let key = KeyPair::generate().map_err(e("a leaf key"))?;
        let mut p = CertificateParams::default();
        let mut dn = DistinguishedName::new();
        dn.push(DnType::CommonName, cn);
        p.distinguished_name = dn;
        p.subject_alt_names = sans;
        p.extended_key_usages = purpose;
        (p.not_before, p.not_after) = validity;
        let cert = p.signed_by(&key, &ca).map_err(e("a leaf certificate"))?;
        Ok(Issued { cert_pem: cert.pem(), key_pem: key.serialize_pem() })
    }

    /// The door's server certificate, for the front's utility address —
    /// back-dated by [`DOOR_BACKDATE`], because a box checks it with a clock
    /// nobody has set yet.
    pub fn issue_door(&self, utility: Ipv4Addr, valid_for: Duration) -> Result<Issued, MtlsError> {
        let back = time::Duration::seconds(DOOR_BACKDATE.as_secs() as i64);
        self.leaf_back("nordisk-pairing door", vec![SanType::IpAddress(IpAddr::V4(utility))], vec![ExtendedKeyUsagePurpose::ServerAuth], window_back(valid_for, back))
    }

    /// **The bootstrap certificate the MEDIUM carries** — the same for every
    /// VM of the medium. Since 0.3.0 it is first of all what each VM's
    /// bootstrap listener SERVES the installer with (server auth, the fixed
    /// name [`VM_SERVER_NAME`]). Client auth stays for the 0.2 join against a
    /// front-hosted join service, which holger may still run.
    pub fn issue_bootstrap(&self, valid_for: Duration) -> Result<Issued, MtlsError> {
        self.leaf(BOOTSTRAP_CN, vm_sans(), vec![ExtendedKeyUsagePurpose::ServerAuth, ExtendedKeyUsagePurpose::ClientAuth], valid_for)
    }

    /// **The installer's own certificate** (0.3.0, owner 2026-09-24): the
    /// client certificate the installer on the operator's machine shows every
    /// VM it connects OUT to. CN [`INSTALLER_CN`] — the one role a VM's
    /// bootstrap listener accepts. Minted per medium with the CA and kept
    /// beside it on the operator's machine (0600); it never leaves that
    /// machine. Back-dated a day: a VM checks it with a clock nobody has set.
    pub fn issue_installer(&self, valid_for: Duration) -> Result<Issued, MtlsError> {
        let back = time::Duration::seconds(DOOR_BACKDATE.as_secs() as i64);
        self.leaf_back(INSTALLER_CN, Vec::new(), vec![ExtendedKeyUsagePurpose::ClientAuth], window_back(valid_for, back))
    }

    /// **A box's own certificate**, from its signing request: the CN is the
    /// NAME the door gave the box (whatever the request asked for), the key is
    /// the box's.
    pub fn sign_box(&self, csr_pem: &str, name: &str, valid_for: Duration) -> Result<String, MtlsError> {
        if name == BOOTSTRAP_CN || name == INSTALLER_CN {
            return Err(MtlsError(format!("`{name}` is not a box name")));
        }
        let ca = self.issuer()?;
        let mut csr = CertificateSigningRequestParams::from_pem(csr_pem).map_err(e("the box's signing request"))?;
        let mut dn = DistinguishedName::new();
        dn.push(DnType::CommonName, name);
        csr.params.distinguished_name = dn;
        // The VM name too: a VM that holds its own certificate serves its
        // bootstrap listener with it after a restart (0.3.0).
        csr.params.subject_alt_names = vm_sans();
        csr.params.is_ca = IsCa::NoCa;
        csr.params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ServerAuth, ExtendedKeyUsagePurpose::ClientAuth];
        (csr.params.not_before, csr.params.not_after) = window(valid_for);
        Ok(csr.signed_by(&ca).map_err(e("the box's certificate"))?.pem())
    }
}

impl InstallerCa {
    /// **A box's certificate renewed** (0.5.12): the SAME key and name as `current`, a new
    /// lifetime of `valid_for`, signed by this CA. No request is needed: the key is the box's
    /// own and stays on it.
    pub fn renew_box(&self, current: &str, valid_for: Duration) -> Result<String, MtlsError> {
        let (spki, cn) = key_and_name(current)?;
        if cn == BOOTSTRAP_CN || cn == INSTALLER_CN {
            return Err(MtlsError(format!("`{cn}` is not a box name")));
        }
        let ca = self.issuer()?;
        let public = rcgen::SubjectPublicKeyInfo::from_der(&spki).map_err(e("the box's public key"))?;
        let mut p = CertificateParams::default();
        let mut dn = DistinguishedName::new();
        dn.push(DnType::CommonName, cn);
        p.distinguished_name = dn;
        p.subject_alt_names = vm_sans();
        p.is_ca = IsCa::NoCa;
        p.extended_key_usages = vec![ExtendedKeyUsagePurpose::ServerAuth, ExtendedKeyUsagePurpose::ClientAuth];
        (p.not_before, p.not_after) = window(valid_for);
        Ok(p.signed_by(&public, &ca).map_err(e("the renewed certificate"))?.pem())
    }
}

impl InstallerCa {
    /// **The CA's own certificate renewed** (0.5.13, a planned roll before its end): the SAME
    /// key and name, a new lifetime. Every pin of the old certificate still holds — a trust
    /// anchor is its name and key — so nothing the boxes or the shop hold changes.
    pub fn renew_ca(&self, valid_for: Duration) -> Result<InstallerCa, MtlsError> {
        let key = KeyPair::from_pem(&self.key_pem).map_err(e("the CA key"))?;
        let (_, cn) = key_and_name(&self.cert_pem)?;
        let mut p = ca_params(&cn);
        (p.not_before, p.not_after) = window(valid_for);
        let cert = p.self_signed(&key).map_err(e("the renewed CA certificate"))?;
        Ok(InstallerCa { cert_pem: cert.pem(), key_pem: self.key_pem.clone() })
    }
}

/// Pure: **why `boot` is not a bootstrap pair a VM keeps for its next join** (0.5.13), or
/// `None`: a certificate named [`BOOTSTRAP_CN`] whose key is the one handed with it.
pub fn bootstrap_refusal(boot: &Issued) -> Option<String> {
    let (spki, cn) = match key_and_name(&boot.cert_pem) {
        Ok(v) => v,
        Err(err) => return Some(format!("REFUSED [rebootstrap-unreadable] the bootstrap certificate: {err}")),
    };
    if cn != BOOTSTRAP_CN {
        return Some(format!("REFUSED [rebootstrap-not-bootstrap] the certificate names `{cn}`, not a bootstrap certificate (`{BOOTSTRAP_CN}`)"));
    }
    match KeyPair::from_pem(&boot.key_pem) {
        Ok(k) if rcgen::PublicKeyData::subject_public_key_info(&k) == spki => None,
        Ok(_) => Some("REFUSED [rebootstrap-other-key] the key handed is not the bootstrap certificate's".into()),
        Err(err) => Some(format!("REFUSED [rebootstrap-unreadable] the bootstrap key: {err}")),
    }
}

/// The DER public key and the CN a certificate (PEM) carries.
fn key_and_name(pem: &str) -> Result<(Vec<u8>, String), MtlsError> {
    let (_, p) = x509_parser::pem::parse_x509_pem(pem.trim().as_bytes()).map_err(|err| MtlsError(format!("not a PEM certificate: {err}")))?;
    let cert = p.parse_x509().map_err(|err| MtlsError(format!("not an X.509 certificate: {err}")))?;
    let cn = cert.subject().iter_common_name().next().and_then(|a| a.as_str().ok()).ok_or_else(|| MtlsError("the certificate names no CN".into()))?;
    Ok((cert.public_key().raw.to_vec(), cn.to_string()))
}

/// The installer CA's parameters: its one CN, a CA of path length 0 that signs
/// certificates. [`InstallerCa::mint`] and [`InstallerCa::renew_ca`] build the same
/// subject from it, so a renewed CA keeps the name every pin holds (rcgen 0.14 no
/// longer rebuilds parameters from a certificate).
fn ca_params(cn: &str) -> CertificateParams {
    let mut p = CertificateParams::default();
    let mut dn = DistinguishedName::new();
    dn.push(DnType::CommonName, cn);
    p.distinguished_name = dn;
    p.is_ca = IsCa::Ca(BasicConstraints::Constrained(0));
    p.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::DigitalSignature];
    p
}

/// (notBefore, notAfter) of a certificate (PEM), unix seconds.
fn life(pem: &str) -> Result<(i64, i64), MtlsError> {
    let (_, p) = x509_parser::pem::parse_x509_pem(pem.trim().as_bytes()).map_err(|err| MtlsError(format!("not a PEM certificate: {err}")))?;
    let cert = p.parse_x509().map_err(|err| MtlsError(format!("not an X.509 certificate: {err}")))?;
    Ok((cert.validity().not_before.timestamp(), cert.validity().not_after.timestamp()))
}

/// The share of a certificate's life after which it is renewed: two thirds.
pub const RENEW_AT: (i64, i64) = (2, 3);

/// Pure: **is a certificate due for renewal at `now_unix`?** At two thirds of its life (or past
/// its end).
pub fn renewal_due(pem: &str, now_unix: i64) -> Result<bool, MtlsError> {
    let (from, to) = life(pem)?;
    let at = from + (to - from).max(0) * RENEW_AT.0 / RENEW_AT.1;
    Ok(now_unix >= at)
}

/// Pure: **why `new` is not a renewal of `current`**, or `None`: the same key, the same name, an
/// end no earlier.
pub fn renewal_refusal(current: &str, new: &str) -> Option<String> {
    let (old_key, old_cn) = match key_and_name(current) {
        Ok(v) => v,
        Err(e) => return Some(format!("REFUSED [renew-unreadable] this VM's own certificate: {e}")),
    };
    let (new_key, new_cn) = match key_and_name(new) {
        Ok(v) => v,
        Err(e) => return Some(format!("REFUSED [renew-unreadable] the renewed certificate: {e}")),
    };
    if new_key != old_key {
        return Some("REFUSED [renew-other-key] the certificate is for another key, not this VM's own".into());
    }
    if new_cn != old_cn {
        return Some(format!("REFUSED [renew-other-name] the certificate names `{new_cn}`, this VM is `{old_cn}`"));
    }
    match (life(current), life(new)) {
        (Ok((_, old_end)), Ok((_, new_end))) if new_end >= old_end => None,
        _ => Some("REFUSED [renew-not-later] the certificate ends before the one this VM holds".into()),
    }
}

/// **The CN of a certificate** (PEM) — what an attached estate's certificate
/// names (`<estate>/<box>`).
pub fn cert_cn(pem: &str) -> Result<String, MtlsError> {
    let (_, p) = x509_parser::pem::parse_x509_pem(pem.trim().as_bytes()).map_err(|err| MtlsError(format!("not a PEM certificate: {err}")))?;
    let cert = p.parse_x509().map_err(|err| MtlsError(format!("not an X.509 certificate: {err}")))?;
    let cn = cert.subject().iter_common_name().next().and_then(|a| a.as_str().ok()).ok_or_else(|| MtlsError("the certificate names no CN".into()))?;
    Ok(cn.to_string())
}

impl InstallerCa {
    /// **An attached estate's certificate** (f-attach-enrol): the central
    /// monetize's ATTACH CA signs the estate's own CSR — CN `cn`
    /// (`<estate>/<box>`), the estate's control-plane host as a SAN (a DNS
    /// name, or an IP), client AND server auth: the estate shows it calling the
    /// central, and the central's dial into it verifies it.
    pub fn sign_attached(&self, csr_pem: &str, cn: &str, host: &str, valid_for: Duration) -> Result<String, MtlsError> {
        let ca = self.issuer()?;
        let mut csr = CertificateSigningRequestParams::from_pem(csr_pem).map_err(e("the estate's signing request"))?;
        let mut dn = DistinguishedName::new();
        dn.push(DnType::CommonName, cn);
        csr.params.distinguished_name = dn;
        csr.params.subject_alt_names = match host.parse::<IpAddr>() {
            Ok(ip) => vec![SanType::IpAddress(ip)],
            Err(_) => vec![SanType::DnsName(host.try_into().map_err(e("the estate's host name"))?)],
        };
        csr.params.is_ca = IsCa::NoCa;
        csr.params.extended_key_usages = vec![ExtendedKeyUsagePurpose::ServerAuth, ExtendedKeyUsagePurpose::ClientAuth];
        (csr.params.not_before, csr.params.not_after) = window(valid_for);
        Ok(csr.signed_by(&ca).map_err(e("the estate's certificate"))?.pem())
    }
}

/// **A box's own key and its signing request.** The key stays on the box.
pub fn box_request() -> Result<(String, String), MtlsError> {
    let key = KeyPair::generate().map_err(e("the box key"))?;
    request_for(key)
}

/// A signing request for a key the box ALREADY holds (PEM) — a box that
/// minted its key on an earlier boot asks for the same key, not a new one.
pub fn box_request_for(key_pem: &str) -> Result<(String, String), MtlsError> {
    request_for(KeyPair::from_pem(key_pem).map_err(e("the box key"))?)
}

fn request_for(key: KeyPair) -> Result<(String, String), MtlsError> {
    let mut p = CertificateParams::default();
    let mut dn = DistinguishedName::new();
    dn.push(DnType::CommonName, "box");
    p.distinguished_name = dn;
    let csr = p.serialize_request(&key).map_err(e("the signing request"))?;
    Ok((csr.pem().map_err(e("the signing request as PEM"))?, key.serialize_pem()))
}

fn certs(pem: &str) -> Result<Vec<CertificateDer<'static>>, MtlsError> {
    let v: Vec<_> = CertificateDer::pem_slice_iter(pem.as_bytes()).collect::<Result<_, _>>().map_err(|err| MtlsError(format!("a certificate PEM: {err:?}")))?;
    if v.is_empty() {
        return Err(MtlsError("a certificate PEM with no certificate in it".into()));
    }
    Ok(v)
}

fn key(pem: &str) -> Result<PrivateKeyDer<'static>, MtlsError> {
    PrivateKeyDer::from_pem_slice(pem.as_bytes()).map_err(|err| MtlsError(format!("a private key PEM: {err:?}")))
}

/// ring, with X25519MLKEM768 offered first ([`crate::pqtls`]): the feed
/// crosses this TLS, and with it the estate's WireGuard pre-shared keys.
fn provider() -> Arc<rustls::crypto::CryptoProvider> {
    Arc::new(crate::pqtls::provider())
}

fn roots(ca_pem: &str) -> Result<rustls::RootCertStore, MtlsError> {
    let mut r = rustls::RootCertStore::empty();
    for c in certs(ca_pem)? {
        r.add(c).map_err(|err| MtlsError(format!("the installer CA as a root: {err}")))?;
    }
    Ok(r)
}

/// **The door's TLS**: its own certificate, and a client certificate from the
/// installer CA REQUIRED on every connection.
pub fn server_config(ca_pem: &str, door: &Issued) -> Result<Arc<rustls::ServerConfig>, MtlsError> {
    let verifier = rustls::server::WebPkiClientVerifier::builder_with_provider(Arc::new(roots(ca_pem)?), provider())
        .build()
        .map_err(|err| MtlsError(format!("the client verifier: {err}")))?;
    let cfg = rustls::ServerConfig::builder_with_provider(provider())
        .with_protocol_versions(&[&rustls::version::TLS13])
        .map_err(|err| MtlsError(format!("TLS 1.3: {err}")))?
        .with_client_cert_verifier(verifier)
        .with_single_cert(certs(&door.cert_pem)?, key(&door.key_pem)?)
        .map_err(|err| MtlsError(format!("the door's certificate: {err}")))?;
    Ok(Arc::new(cfg))
}

/// **A box's TLS**: the installer CA pinned as the ONLY root, and the client
/// certificate it presents (the bootstrap one, or its own after the first join).
pub fn client_config(ca_pem: &str, client: &Issued) -> Result<Arc<rustls::ClientConfig>, MtlsError> {
    let cfg = rustls::ClientConfig::builder_with_provider(provider())
        .with_protocol_versions(&[&rustls::version::TLS13])
        .map_err(|err| MtlsError(format!("TLS 1.3: {err}")))?
        .with_root_certificates(roots(ca_pem)?)
        .with_client_auth_cert(certs(&client.cert_pem)?, key(&client.key_pem)?)
        .map_err(|err| MtlsError(format!("the client certificate: {err}")))?;
    Ok(Arc::new(cfg))
}

/// The server name a box checks the door's certificate against: its address.
pub fn door_name(utility: Ipv4Addr) -> ServerName<'static> {
    ServerName::IpAddress(IpAddr::V4(utility).into())
}

/// The CN of the certificate a client presented — `bootstrap` or a box name.
/// The chain was already verified against the installer CA by the handshake.
pub fn peer_cn(conn: &rustls::ServerConnection) -> Option<String> {
    cn_of(conn.peer_certificates()?.first()?)
}

/// **The name the installer checks a VM's certificate against**
/// ([`VM_SERVER_NAME`]) — never the address it dialled (0.3.0).
pub fn vm_name() -> ServerName<'static> {
    ServerName::try_from(VM_SERVER_NAME).expect("VM_SERVER_NAME is a valid DNS name")
}

/// The CN of the certificate a VM SERVED the installer — `bootstrap`, or the
/// box's own name once it holds one. Verified against the installer CA and
/// [`VM_SERVER_NAME`] by the handshake.
pub fn server_cn(conn: &rustls::ClientConnection) -> Option<String> {
    cn_of(conn.peer_certificates()?.first()?)
}

fn cn_of(der: &CertificateDer<'_>) -> Option<String> {
    let (_, cert) = x509_parser::parse_x509_certificate(der.as_ref()).ok()?;
    let cn = cert.subject().iter_common_name().next()?.as_str().ok()?.to_string();
    Some(cn)
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::{Read, Write};

    const H: Duration = Duration::from_secs(3600);

    /// A real TLS 1.3 handshake over loopback: the door sees `bootstrap`, then
    /// the box's own name; a certificate from ANOTHER CA is refused, and a box
    /// that pins the installer CA refuses a door it did not issue.
    #[test]
    fn a_box_joins_with_the_bootstrap_cert_then_speaks_as_itself_and_strangers_are_refused_both_ways() {
        let ca = InstallerCa::mint("fleet.test", H).unwrap();
        let door = ca.issue_door(Ipv4Addr::LOCALHOST, H).unwrap();
        let boot = ca.issue_bootstrap(H).unwrap();
        let (csr, box_key) = box_request().unwrap();
        let mine = Issued { cert_pem: ca.sign_box(&csr, "main", H).unwrap(), key_pem: box_key };
        let other = InstallerCa::mint("another", H).unwrap();
        let stranger = other.issue_bootstrap(H).unwrap();

        let serve = |client: Issued, pin: String| -> Result<String, String> {
            let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
            let addr = l.local_addr().unwrap();
            let scfg = server_config(&ca.cert_pem, &door).unwrap();
            let t = std::thread::spawn(move || {
                let (s, _) = l.accept().unwrap();
                let conn = rustls::ServerConnection::new(scfg).unwrap();
                let mut tls = rustls::StreamOwned::new(conn, s);
                let mut b = [0u8; 5];
                match tls.read_exact(&mut b) {
                    Ok(()) => {
                        let cn = peer_cn(&tls.conn).unwrap_or_default();
                        let _ = tls.write_all(cn.as_bytes());
                        tls.conn.send_close_notify();
                        let _ = tls.flush();
                        Ok(cn)
                    }
                    Err(err) => Err(err.to_string()),
                }
            });
            let ccfg = client_config(&pin, &client).map_err(|e| e.to_string())?;
            let s = std::net::TcpStream::connect(addr).unwrap();
            let conn = rustls::ClientConnection::new(ccfg, door_name(Ipv4Addr::LOCALHOST)).unwrap();
            let mut tls = rustls::StreamOwned::new(conn, s);
            let sent = tls.write_all(b"hello").and_then(|_| tls.flush());
            let mut back = String::new();
            let read = tls.read_to_string(&mut back);
            let server = t.join().unwrap();
            match (sent, read, server) {
                (Ok(()), Ok(_), Ok(cn)) if back == cn => Ok(cn),
                (s, r, sv) => Err(format!("sent {s:?} read {r:?} server {sv:?}")),
            }
        };
        assert_eq!(serve(boot.clone(), ca.cert_pem.clone()), Ok(BOOTSTRAP_CN.to_string()));
        assert_eq!(serve(mine, ca.cert_pem.clone()), Ok("main".to_string()), "the box speaks as the name the door gave it");
        assert!(serve(stranger, ca.cert_pem.clone()).is_err(), "a certificate from another CA is refused by the door");
        assert!(serve(boot, other.cert_pem.clone()).is_err(), "a box that pins the installer CA refuses a door it did not issue");
    }

    /// **The installer's mutual TLS is post-quantum** (2026-10-06): the feed
    /// crosses it — and with the feed every WireGuard pre-shared key of the
    /// estate — so the door and a box negotiate X25519MLKEM768
    /// ([`crate::pqtls`]), and a recording of the link opens for nobody later.
    #[test]
    fn the_door_and_a_box_negotiate_x25519mlkem768() {
        let ca = InstallerCa::mint("fleet.test", H).unwrap();
        let door = ca.issue_door(Ipv4Addr::LOCALHOST, H).unwrap();
        let boot = ca.issue_bootstrap(H).unwrap();
        let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let addr = l.local_addr().unwrap();
        let scfg = server_config(&ca.cert_pem, &door).unwrap();
        let t = std::thread::spawn(move || {
            let (s, _) = l.accept().unwrap();
            let mut tls = rustls::StreamOwned::new(rustls::ServerConnection::new(scfg).unwrap(), s);
            let mut b = [0u8; 5];
            tls.read_exact(&mut b).unwrap();
            tls.write_all(b"done!").unwrap();
            tls.flush().unwrap();
            tls.conn.negotiated_key_exchange_group().map(|g| g.name())
        });
        let ccfg = client_config(&ca.cert_pem, &boot).unwrap();
        let conn = rustls::ClientConnection::new(ccfg, door_name(Ipv4Addr::LOCALHOST)).unwrap();
        let mut tls = rustls::StreamOwned::new(conn, std::net::TcpStream::connect(addr).unwrap());
        tls.write_all(b"hello").unwrap();
        tls.flush().unwrap();
        let mut b = [0u8; 5];
        tls.read_exact(&mut b).unwrap();
        let client = tls.conn.negotiated_key_exchange_group().map(|g| g.name());
        assert_eq!((t.join().unwrap(), client), (Some(rustls::NamedGroup::X25519MLKEM768), Some(rustls::NamedGroup::X25519MLKEM768)));
    }

    /// The door's certificate is valid from a day back (a box checks it with
    /// a clock nobody has set yet); the other leaves keep five minutes. And
    /// what a certificate has left is read off it.
    #[test]
    fn the_door_certificate_is_back_dated_a_day_and_what_a_certificate_has_left_is_read_off_it() {
        let ca = InstallerCa::mint("fleet.test", 90 * 24 * H).unwrap();
        let now = now_unix();
        let nb = |pem: &str| {
            let der = certs(pem).unwrap().remove(0);
            let (_, c) = x509_parser::parse_x509_certificate(der.as_ref()).unwrap();
            c.validity().not_before.timestamp()
        };
        let door = ca.issue_door(Ipv4Addr::LOCALHOST, H).unwrap();
        let back = now - nb(&door.cert_pem);
        assert!((24 * 3600 - 60..=24 * 3600 + 60).contains(&back), "the door is back-dated a day, got {back} s");
        let boot = ca.issue_bootstrap(H).unwrap();
        assert!(now - nb(&boot.cert_pem) <= 5 * 60 + 60, "the bootstrap certificate keeps five minutes");
        let left = cert_left(&ca.cert_pem, now).unwrap();
        assert!(left > 89 * 24 * H && left <= 90 * 24 * H, "{left:?}");
        assert_eq!(cert_left(&ca.cert_pem, now + 91 * 24 * 3600).unwrap(), Duration::ZERO, "ended");
        assert!(cert_left("not a pem", now).is_err());
    }

    #[test]
    fn the_box_request_is_signed_with_the_door_given_name_and_bootstrap_is_not_a_name() {
        let ca = InstallerCa::mint("fleet.test", H).unwrap();
        let (csr, _) = box_request().unwrap();
        let pem = ca.sign_box(&csr, "twin", H).unwrap();
        let der = certs(&pem).unwrap().remove(0);
        let (_, cert) = x509_parser::parse_x509_certificate(der.as_ref()).unwrap();
        assert_eq!(cert.subject().iter_common_name().next().unwrap().as_str().unwrap(), "twin");
        assert!(ca.sign_box(&csr, BOOTSTRAP_CN, H).is_err());
        assert!(ca.sign_box("not a csr", "twin", H).is_err());
    }

    /// ★ **The installer CA renews ITSELF before its end** (0.5.13, the 180-day gap): the same
    /// key and name, a later end; a door and a box certificate issued by the RENEWED CA are taken
    /// by peers that still pin the OLD certificate — the boxes' seeds and the shop's custody need
    /// nothing.
    #[test]
    fn a_renewed_ca_keeps_its_key_and_name_and_the_old_pin_still_holds() {
        let ca = InstallerCa::mint("fleet.test", H).unwrap();
        let renewed = ca.renew_ca(180 * 24 * H).unwrap();
        assert_eq!(renewed.key_pem, ca.key_pem, "the same key");
        assert_ne!(renewed.cert_pem, ca.cert_pem);
        assert_eq!(key_and_name(&renewed.cert_pem).unwrap(), key_and_name(&ca.cert_pem).unwrap(), "the same key and name");
        assert!(cert_left(&renewed.cert_pem, 0).unwrap() > cert_left(&ca.cert_pem, 0).unwrap(), "a later end");
        let door = renewed.issue_door(Ipv4Addr::LOCALHOST, H).unwrap();
        let (csr, k) = box_request().unwrap();
        let mine = Issued { cert_pem: renewed.sign_box(&csr, "main", H).unwrap(), key_pem: k };
        let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let addr = l.local_addr().unwrap();
        let scfg = server_config(&ca.cert_pem, &door).unwrap();
        let t = std::thread::spawn(move || {
            let (s, _) = l.accept().unwrap();
            let mut tls = rustls::StreamOwned::new(rustls::ServerConnection::new(scfg).unwrap(), s);
            let mut b = [0u8; 5];
            tls.read_exact(&mut b).map(|_| peer_cn(&tls.conn).unwrap_or_default()).map_err(|e| e.to_string())
        });
        let ccfg = client_config(&ca.cert_pem, &mine).unwrap();
        let s = std::net::TcpStream::connect(addr).unwrap();
        let mut tls = rustls::StreamOwned::new(rustls::ClientConnection::new(ccfg, door_name(Ipv4Addr::LOCALHOST)).unwrap(), s);
        tls.write_all(b"hello").and_then(|_| tls.flush()).expect("the box takes the renewed CA's door under the old pin");
        assert_eq!(t.join().unwrap(), Ok("main".to_string()), "the door takes the renewed CA's box under the old pin");
    }

    /// One mTLS handshake: a box holding `mine` dials a door holding `door`, both pinning
    /// `pin`. The door's answer: the box's CN, or why either side refused.
    fn handshake(pin: &str, door: Issued, mine: Issued) -> Result<String, String> {
        let l = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
        let addr = l.local_addr().unwrap();
        let scfg = server_config(pin, &door).map_err(|e| e.to_string())?;
        let t = std::thread::spawn(move || {
            let (s, _) = l.accept().map_err(|e| e.to_string())?;
            let mut tls = rustls::StreamOwned::new(rustls::ServerConnection::new(scfg).unwrap(), s);
            let mut b = [0u8; 5];
            tls.read_exact(&mut b).map(|_| peer_cn(&tls.conn).unwrap_or_default()).map_err(|e| e.to_string())
        });
        let ccfg = client_config(pin, &mine).map_err(|e| e.to_string())?;
        let s = std::net::TcpStream::connect(addr).unwrap();
        let mut tls = rustls::StreamOwned::new(rustls::ClientConnection::new(ccfg, door_name(Ipv4Addr::LOCALHOST)).unwrap(), s);
        let sent = tls.write_all(b"hello").and_then(|_| tls.flush()).map_err(|e| format!("the box: {e}"));
        drop(tls);
        let heard = t.join().unwrap();
        sent.and(heard)
    }

    /// ★ **S21: day 200 with the original installer CA** (its 180 days are over) — a trust
    /// anchor is its name and key: certificates the EXPIRED CA issues still pass under the pin
    /// both sides hold, so an estate whose front missed the renewal still joins and re-admits;
    /// the CA is due, renews (same key, a later end) and the old pin keeps holding.
    #[test]
    fn day_200_with_the_original_ca_still_joins_and_the_ca_renews_under_the_old_pin() {
        let fresh = InstallerCa::mint("fleet.test", H).unwrap();
        let key = KeyPair::from_pem(&fresh.key_pem).unwrap();
        let mut p = ca_params(&key_and_name(&fresh.cert_pem).unwrap().1);
        let now = time::OffsetDateTime::now_utc();
        (p.not_before, p.not_after) = (now - time::Duration::days(200), now - time::Duration::days(20));
        let expired = InstallerCa { cert_pem: p.self_signed(&key).unwrap().pem(), key_pem: fresh.key_pem.clone() };
        let now_unix = now.unix_timestamp();
        assert_eq!(cert_left(&expired.cert_pem, now_unix).unwrap(), Duration::ZERO, "the CA certificate is past its end");
        assert!(renewal_due(&expired.cert_pem, now_unix).unwrap(), "and due");
        let issue = |ca: &InstallerCa| {
            let (csr, k) = box_request().unwrap();
            (ca.issue_door(Ipv4Addr::LOCALHOST, H).unwrap(), Issued { cert_pem: ca.sign_box(&csr, "main", H).unwrap(), key_pem: k })
        };
        let (door, mine) = issue(&expired);
        assert_eq!(handshake(&expired.cert_pem, door, mine), Ok("main".to_string()), "an expired anchor still anchors");
        let renewed = expired.renew_ca(180 * 24 * H).unwrap();
        assert!(cert_left(&renewed.cert_pem, now_unix).unwrap() > 170 * 24 * H, "renewed past day 200: a new lifetime");
        assert!(!renewal_due(&renewed.cert_pem, now_unix).unwrap());
        let (door, mine) = issue(&renewed);
        assert_eq!(handshake(&expired.cert_pem, door, mine), Ok("main".to_string()), "the boxes' old pin takes the renewed CA's certificates");
    }

}