hammer-bootstrap: ancla soberana externa /etc/arje/rootkey.pub (I4 / Etapa D, hardening #3)
El producto atestado escribe la pubkey de la rootkey en /etc/arje/rootkey.pub (32 bytes raw), leyéndola del attest_rootkey del seed ya firmado (lo que arje-packager computó de nuestra rootkey privada) ⇒ cero criptografía nueva en hammer. El gate de arje (attest_gate.rs::ancla_externa) la PREFIERE sobre la rootkey auto-declarada del seed (trust = ancla.or(seed.attest_rootkey)): cierra el ataque "seed reescrito por completo" que el WARN "sin ancla soberana externa" señalaba (hueco A2). product_attested_hash v2. - assemble_attested_product_rootfs: tras firmar, extrae attest_rootkey (array 32B) y lo escribe en etc/arje/rootkey.pub; test hermético verifica el ancla. - scripts/attest-boot-test.sh: nuevo modo SEED_REWRITE=1 (re-firma el seed con rootkey ATACANTE, deja la rootkey.pub legítima intacta ⇒ debe HALT). Validado E2E en QEMU sobre el artefacto REAL v2 (hammer bootstrap product --attest): · ÍNTEGRO → WARN desaparece, "anclada a rootkey soberana externa", 3 ✓, SSH OK. · SEED_REWRITE → gate: ancla ≠ attest_rootkey, 3× "autor no confiable" → Halt → sin SSH. Nota: el ancla en fichero cierra el seed-rewrite; el ancla compilada ARJE_ATTEST_ROOTKEY (dentro del binario atestado) sería más fuerte pero exige rebuild por-rootkey (documentada en attest_gate.rs, no hecha). Queda sólo el pendiente #2 (Cargo.lock en tawasuyu). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -58,6 +58,27 @@ if [ "${TAMPER:-0}" = 1 ]; then
|
||||
echo "==> TAMPER: /usr/bin/hammerd alterado tras la firma — el gate debe HALT"
|
||||
fi
|
||||
|
||||
# SEED_REWRITE: el ataque que el ANCLA SOBERANA (#3) cierra. Un atacante reescribe el seed firmando los
|
||||
# binarios con SU rootkey y declara su pubkey en attest_rootkey (seed auto-consistente). Pero /etc/arje/
|
||||
# rootkey.pub (la pubkey LEGÍTIMA, fuera de la Card) queda intacta ⇒ el gate exige firmas del ancla ⇒ las
|
||||
# concesiones del atacante caen en AutorNoConfiable ⇒ Halt. Sin ancla, este seed arrancaría (hueco de A2).
|
||||
if [ "${SEED_REWRITE:-0}" = 1 ]; then
|
||||
PKGR=$(pick arje-packager)
|
||||
[ -n "$PKGR" ] && [ -e "$PKGR/usr/bin/arje-packager" ] || { echo "falta arje-packager para SEED_REWRITE"; exit 1; }
|
||||
[ -e "$RFS/etc/arje/rootkey.pub" ] || { echo "el product-attested-rootfs no trae /etc/arje/rootkey.pub (¿v2?)"; exit 1; }
|
||||
python3 - "$RFS/ente/seed.card.json" "$WORK/rewrite-in.json" <<'PY'
|
||||
import json,sys
|
||||
d=json.load(open(sys.argv[1])); d.pop("attest",None); d.pop("attest_rootkey",None); d["attest_policy"]="halt"
|
||||
json.dump(d,open(sys.argv[2],"w"),indent=2)
|
||||
PY
|
||||
printf 'hammer-EVIL-rootkey-attacker-001' > "$WORK/evil.bin" # 32 bytes, ≠ la rootkey legítima
|
||||
"$PKGR/usr/bin/arje-packager" --seed "$WORK/rewrite-in.json" --rootkey "$WORK/evil.bin" \
|
||||
--bin arje-zero="$RFS/usr/bin/arje-zero" --bin hammerd="$RFS/usr/bin/hammerd" \
|
||||
--bin console-getty="$RFS/bin/busybox" --bin sshd="$RFS/bin/busybox" \
|
||||
--seed-out "$RFS/ente/seed.card.json" >/dev/null 2>&1
|
||||
echo "==> SEED_REWRITE: seed re-firmado con rootkey ATACANTE; /etc/arje/rootkey.pub legítima intacta — el gate debe HALT"
|
||||
fi
|
||||
|
||||
# authorized_keys de prueba + empaquetar (root-owned)
|
||||
KG=$(ls store/*-openssh/usr/bin/ssh-keygen|head -1); "$KG" -t ed25519 -N '' -f "$WORK/clientkey" -q
|
||||
install -d -m 0700 "$RFS/root/.ssh"; cat "$WORK/clientkey.pub" > "$RFS/root/.ssh/authorized_keys"; chmod 0600 "$RFS/root/.ssh/authorized_keys"
|
||||
@@ -80,11 +101,12 @@ sleep 2; echo "---- consola: líneas de atestación ----"; grep -iE "atestaci|at
|
||||
|
||||
# veredicto
|
||||
echo "========================================"
|
||||
if [ "${TAMPER:-0}" = 1 ]; then
|
||||
if [ "${TAMPER:-0}" = 1 ] || [ "${SEED_REWRITE:-0}" = 1 ]; then
|
||||
caso=$([ "${SEED_REWRITE:-0}" = 1 ] && echo "SEED_REWRITE" || echo "TAMPER")
|
||||
if [ "$ssh_ok" = 0 ] && grep -qiE "ATESTACIÓN FALLÓ|atestación al arranque falló|ARRANQUE FALLIDO|rescate" "$LOG"; then
|
||||
echo "*** TAMPER OK — el gate detectó la manipulación y HALTeó (sin SSH) ***"; exit 0
|
||||
echo "*** $caso OK — el gate detectó el ataque y HALTeó (sin SSH) ***"; exit 0
|
||||
else
|
||||
echo "*** TAMPER FALLÓ — el sistema arrancó pese al binario alterado (ssh_ok=$ssh_ok) ***"; exit 1
|
||||
echo "*** $caso FALLÓ — el sistema arrancó pese al ataque (ssh_ok=$ssh_ok) ***"; exit 1
|
||||
fi
|
||||
else
|
||||
oks=$(grep -c "atestación ✓" "$LOG" 2>/dev/null || echo 0)
|
||||
|
||||
Reference in New Issue
Block a user