Files
AXP-Resurection/docs/009-hardening-signing-checklist.md
T
sunfish-admin deaaf42caa 009: Magisk ship pack through US-S5-1 + US-S4 OpenSSH/Jelly/Gallery2.
Release-keys/AVB, CVE clean+hi batches, Yama/slabrand, Pro branding,
bundled apps, and AXP-class product surface docs/scripts.
2026-10-05 10:42:00 +02:00

249 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 009 — Userspace hardening / signing / AVB checklist (Gate G)
**Task:** T040.
**Companion:** kernel half = `docs/009-gate-g-kernel-attribution.md`.
**Policy (2026-09-29):** project **release keys yes**; **bootloader relock no**
(AXP/LOS unlocked norm; IOdes-class lock = non-goal). See
`specs/009-axp-los23-port/research.md`.
Secrets never enter Git. Host material lives under `/srv/rom/secrets/` on
`rom-dev01` only.
---
## Measured baseline (2026-09-29)
| Prop / fact | GOLDEN (AXP Pro) | LAB (Stage1 pack) | Target |
|-------------|------------------|-------------------|--------|
| `ro.build.type` | `user` | `userdebug` | `user` for ship; `userdebug` OK while developing |
| `ro.build.tags` | `release-keys` | `test-keys` | `release-keys` |
| `ro.build.flavor` | `lineage_sunfish-user` | `lineage_sunfish-userdebug` | `…-user` at ship |
| `ro.debuggable` | `0` | `0` on LAB measure wait — typically `1` on userdebug | `0` on ship |
| `ro.secure` | `1` | (LOS default) | `1` |
| `ro.boot.flash.locked` | `0` | `0` | `0` (unlocked — intentional) |
| `ro.boot.verifiedbootstate` | `orange` | `orange` | `orange` while unlocked |
| `ro.boot.vbmeta.device_state` | `unlocked` | (same class) | unlocked |
| `ro.boot.veritymode` | `enforcing` | expect enforcing | keep |
| SELinux | Enforcing (expect) | **Enforcing** | keep |
| OTA zip cert | AXP releasekey | **AOSP `testkey.x509.pem`** (byte-match on stage1 zip) | project releasekey |
| AVB signing key in tree | AXP custom | `external/avb/test/data/testkey_rsa2048.pem` | project AVB key |
| `BOARD_AVB_MAKE_VBMETA_IMAGE_ARGS --flags 3` | AXP sets real AVB when enabled | LOS sunfish adds `--flags 3` unless `WITH_AVB=true` | keep flags 3 (signing infra only; not runtime harden) |
LAB adb sample (device `11231JEC207477`, Stage1 sideload):
`test-keys` / `userdebug` / `orange` / `flash.locked=0` / `getenforce=Enforcing`.
GOLDEN source: `/srv/rom/references/axp/golden/2026-09-13/getprop.txt`.
---
## What “done” means for Gate G userspace
1. Ship images/OTAs verify as **`release-keys`** (not AOSP test-keys).
2. Phonesky / microG keep **their** project JKS identities under
`/srv/rom/secrets/{phonesky,microg}-signing/` (already exist).
3. AVB *build* uses project keys where LOS23/sunfish allows; device stays
**unlocked** (`orange`). Relock is **out of scope**.
4. Userspace hardening stages are attributable (patch dir + map) or explicitly
deferred/skipped with reason.
5. Gaps written down — no silent omit.
---
## Stages (do in order)
### US-S0 — Inventory (this doc) — **done 2026-09-29**
- [x] Compare GOLDEN vs LAB signing/AVB props.
- [x] Confirm stage1 zip OTA cert == AOSP testkey.
- [x] Confirm no `~/.android-certs` / platform release keys on host yet
(only Phonesky + microG JKS).
- [x] Record bootloader-lock = wont.
### US-S1 — Generate project Android signing keys — **done 2026-09-29 (host)**
Host-only. Never commit `.pk8` / private PEM.
| Key | Role |
|-----|------|
| `releasekey` | Default APK/OTA (`PRODUCT_DEFAULT_DEV_CERTIFICATE`) |
| `platform` | `platform`-signed priv-apps |
| `shared` / `media` / `networkstack` / `sdk_sandbox` / `bluetooth` / `nfc` | AOSP partition signing set |
Procedure: `scripts/009-generate-release-keys.sh` on `rom-dev01`
→ prefers `/srv/rom/secrets/android-certs/` if writable, else
`$HOME/.android-certs` (Lineage default; used 2026-09-29 because secrets/
is root-owned 750 without group write).
**Mandatory before first signed ship bacon:** encrypted/offline backup of that
directory (constitution). Public `*.x509.pem` may later be copied into Git for
docs; private material must not.
Acceptance:
- [x] `$HOME/.android-certs/{releasekey,platform,…}.{pk8,x509.pem}` + `avb.pem`
exist on `rom-dev01` (2026-09-29T16:37Z)
- [x] Host tar backup: `/home/android-build/backups/android-certs-20260929T1637Z.tar.gz`
(mode 600; SHA256 in `.sha256`) — **still copy offline/encrypted**
- [x] `releasekey` DN = `O=AXP-Resurection, OU=sunfish-a16, CN=release`
(not AOSP testkey)
- [ ] Root later: `install -d` `/srv/rom/secrets/android-certs` and move keys there
- [ ] Owner offline encrypted copy confirmed
### US-S2 — Wire release keys into bacon — **in progress**
Lineage convention: `PRODUCT_DEFAULT_DEV_CERTIFICATE` → path without suffix
(e.g. `…/releasekey`). On LOS 23 / soong, **env export alone is ignored** —
must be a product makefile `PRODUCT_` (see `vendor/sunfish-a16/signing.mk`,
inherited via `magisk.mk`). Verified `get_build_var` → project releasekey.
Keys **present** on rom-dev01 (`$HOME/.android-certs/releasekey.pk8`, 2026-09-29).
First artifact `20261001T221102Z-…-cve-hi-releasekeys` was **still AOSP testkey**
(env-only wire). Rebacon after `signing.mk` (2026-10-01T22:12Z).
CVE LAB bacons keep test-keys. First real signed bacon stays **`userdebug`**.
**LAB 2026-10-02:** first signed sideload booted Wi‑Fi OK but Bluetooth
crash-looped — zygote `selinux_android_setcontext` failed with
`seinfo=default` for `com.android.bluetooth`. Cause: APK signed with project
`certs/bluetooth.pk8` while `MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES`
stayed on AOSP `build/make/target/product/security/` (non-`com.google.android.bt`
default in `config.mk`). Fix: `PRODUCT_MAINLINE_BLUETOOTH_SEPOLICY_DEV_CERTIFICATES`
in `signing.mk` (rebacon required; boot-only flash insufficient).
Acceptance:
- [ ] Zip `META-INF/com/android/otacert` ≠ AOSP testkey
- [ ] `ro.build.tags=release-keys` on LAB after **sideload** (boot-only flash insufficient)
(note: first RK sideload still showed `dev-keys` on userdebug — recheck after BT fix)
- [x] Magisk preroot + microG + Wi‑Fi **and Bluetooth** OK on Stage1+combo4+CVE-hi ship pack
(`20261002T085915Z-…-cve-hi-releasekeys`, LAB 2026-10-02: BT ON, crashed 0)
- [x] `plat_mac_permissions.xml` embeds project `bluetooth.x509.pem` (`seinfo=bluetooth`)
- [ ] Minor: LOS SetupWizard after Wi‑Fi connect can bounce to language step
(Wi‑Fi stays connected; non-blocking; note only)
- [ ] Prior test-keys image retained for bisect
(`20261001T201836Z-…-cve-hi-batch2` / `#49`, or hi-batch3 when OK)
Script: `scripts/009-bacon-axp-stage1-combo4-cve-hi-releasekeys.sh` +
`vendor/sunfish-a16/signing.mk` → `vendor/sunfish-a16/certs/releasekey`
(in-tree copy of `$HOME/.android-certs`; **gitignored** — soong rejects paths
outside `ANDROID_BUILD_TOP`).
### US-S3 — Project AVB key (unlocked device)
Today sunfish often signs with AOSP `testkey_rsa4096` (or rsa2048) and adds
`--flags 3` unless `WITH_AVB=true` (`BoardConfigLineage.mk` /
`BoardConfig-common.mk`). LAB `20261002T085915Z` vbmeta = AOSP testkey_rsa4096
+ flags 3 (not project `avb.pem`).
AXP ships custom AVB keys and documents AVB2; GOLDEN stays **unlocked/orange**.
Clone that *signing* posture, not IOdes lock.
**Bootloader / OEM unlocking (2026-10-02):** relock remains **wont** for this
Magisk track (orange + preroot). Locking with Magisk-patched boot is a brick
risk on Pixel unless the full AVB chain is enforced end-to-end — out of scope.
Keep `flash.locked=0` / `verifiedbootstate=orange`. Prefer leaving **OEM
unlocking** enabled in Developer options as a *best-effort* escape hatch for
future unlock attempts — it is **not** a guarantee of recovery, data
preservation, or rescue from every failure mode (AOSP: unlock ability is
conditional). Do **not** turn it off casually.
Wire: `vendor/sunfish-a16/BoardConfig.mk` overrides `BOARD_AVB_*` →
`vendor/sunfish-a16/certs/avb.pem` + `SHA256_RSA4096`. Leave `WITH_AVB`
unset so `--flags 3` stays (Magisk-friendly).
**What flags 3 means (libavb):** `HASHTREE_DISABLED (1) | VERIFICATION_DISABLED (2)`.
Descriptors are not enforced at boot; this is **AVB signing infrastructure**,
not “AVB-hardened verified boot”. Do not call US-S3 “AVB endurecido” while
flags stay 3. A later stage may measure `WITH_AVB=true` (flags 0) + Magisk
resign — separate acceptance.
Acceptance:
- [x] `BOARD_AVB_KEY_PATH` → project `vendor/sunfish-a16/certs/avb.pem`
- [x] Artifact gates **fail closed** on **target_files/IMAGES** (not OUT make
images): pubkey sha1 == `avb_pkmd.bin` (≠ AOSP `2597c218…`); Flags `3`;
`verify_image --key` vbmeta + `--expected_chain_partition` vbmeta_system;
Magisk boot hash matches vbmeta; `magiskboot cpio test` ≠ 0
- [x] Document clearly: runtime AVB enforce = **off** (flags 3) — not “AVB endurecido”
- [x] Device still boots unlocked; Magisk preroot intact (LAB 2026-10-02 sideload
+ boot/vbmeta reinforce; `magiskd`, `flash.locked=0`, orange)
- [x] No bootloader relock; OEM unlocking left enabled (escape hatch, not guarantee)
### Branding (no rebacon-only)
- [x] Wire `vendor/sunfish-a16/branding.mk` →
`TARGET_UNOFFICIAL_BUILD_ID=AXP-Resurection-Pro` (full Magisk track, not slim;
next bacon embeds it in `ro.lineage.version`)
- [x] Ship script publishes sibling `AXP-Resurection-Pro-*-sunfish.zip`
(hardlink/copy of Lineage bacon zip). Current artifact renamed the same way
without rebuild.
### US-S4 — Userspace hardening (first attributable pack)
See `docs/009-us-s4-userspace-hardening.md`.
- [x] Stage 0 LAB measure (Enforcing + FBE)
- [x] US-S4-1: strip Openssh/rsync/procmem packages from Lineage `common.mk`
(`apply_009_drop_openssh_packages.py`); keep `init.openssh.rc` (AXP PRO)
- [x] LAB 2026-10-02: ship `20261002T151944Z` sideloaded + reinforced;
see `docs/009-lab-acceptance-20261002-uss4.md`
- [ ] **US-S4-2** (wired, pending bacon): drop Jelly + Gallery2 (AXP PRO
product oracle — Fossify stays); `apply_009_drop_jelly_gallery2.py` +
`NoLineageJelly`; see `docs/009-axp-pro-product-apps-20260324.md`
| Candidate | Priority | Notes |
|-----------|----------|-------|
| Confirm SELinux Enforcing + encryption | **done** | LAB Enforcing + FBE |
| ptrace/Yama | **done US-S5-1** | LAB `162840Z` `CONFIG_SECURITY_YAMA=y` |
| Debug/bugreport surface trim | **done US-S4-1** | AXP PRO product oracle |
| Jelly + Gallery2 debloat | **US-S4-2 wired** | AXP PRO product; Fossify kept |
| mount flags / noexec where stock allows | early | don't break HW |
| hardened_malloc | later | Graphene/AXP; portability cost |
| Broad Graphene framework (scopes, etc.) | later / deferred | high UX cost; not Magisk-clone MVP |
Ship patches under `vendor/sunfish-a16/patches/009-axp-los23-port/hardening/` with README
attribution. One stage per bacon when risk is unclear.
### US-S5 — Kernel CVE mega / more Graphene (on boot-OK pack)
**Do not** flash old `20260918*-axp-kh-cve` / `kh-full` (logo hang).
- [x] CVE clean-offset 429 + hi-batch1–3 on Magisk ship (`151944Z` LAB OK)
- [x] **US-S5-1** LAB OK (`162840Z`): `CONFIG_SECURITY_YAMA=y` +
`CONFIG_SLAB_FREELIST_RANDOM=y` — see
`docs/009-lab-acceptance-20261002-uss5.md`
- [ ] Optional later: `CVE-2022-49980` lock-scope port; Stage1 slab FAIL
retries; `hardened_malloc`
Map updates: `docs/009-kernel-hardening-map.md` + Gate G attribution.
### US-S6 — Optional later
- [ ] Switch default lunch to `lineage_sunfish-user` for ship
- [ ] GPG-sign published SHA sums (AXP does; nice-to-have)
- [ ] LOS23 nightly rebase (vanilla + re-apply Magisk/stage1/keys)
- [ ] Bootloader lock — **wont**
---
## Host paths
| What | Path |
|------|------|
| Platform / OTA / AVB secrets | `$HOME/.android-certs/` on rom-dev01 (2026-09-29); prefer `/srv/rom/secrets/android-certs/` after root relocate |
| Certs tar backup | `/home/android-build/backups/android-certs-20260929T1637Z.tar.gz` |
| Phonesky JKS | `/srv/rom/secrets/phonesky-signing/` |
| microG JKS | `/srv/rom/secrets/microg-signing/` |
| Keygen script (repo) | `scripts/009-generate-release-keys.sh` |
| Signing README (vendor) | `vendor/sunfish-a16/patches/009-axp-los23-port/signing/README.md` |
| GOLDEN props | `/srv/rom/references/axp/golden/2026-09-13/` |
| AXP docs (mirror) | `…/axpos.org/docs/knowledge/{signatures,verifiedboot}/` |
---
## Explicit non-goals
- Bootloader relock / green verified-boot for end users.
- Replacing Phonesky/microG keys with platform keys.
- Committing private keys or passphrases to Git.
- Treating missing lock as Gate G failure.