Files
LibreMail/app
JMR-devandClaude Opus 4.8 63b49b10da feat(security): screen-lock app gate + auth-bound cache decrypt (#22)
Add an opt-in "Require screen lock" setting that gates the whole app behind
BiometricPrompt (strong biometric with device-credential fallback) and binds
the encrypted cache's SQLCipher passphrase to user authentication.

- App-lock gate: AppLockGateHost wraps the app; a pure AppLockGate state machine
  locks on cold start / resume-after-timeout and unlocks on auth.
- Auth-bound decrypt: DatabaseKeyCipher seals the DB passphrase with a Keystore
  key requiring user auth (setUserAuthenticationRequired, time-bound validity,
  setInvalidatedByBiometricEnrollment). PassphraseSession holds the unwrapped
  passphrase in memory; provideDatabase reads it only after auth.
- The non-auth master key (KeystoreCrypto) is unchanged, so background credential
  access (IDLE push) still works.
- Invalidation / lock removal: KeyInvalidationPolicy decides clear-vs-disable;
  the cache is wiped only at cold start in provideDatabase (never while Room holds
  it open) via a persisted flag + process restart, then re-synced. No corruption.
- Enabling requires a secure device lock; disabling reseals the passphrase back
  under the master key first (guarded to avoid a passphrase mismatch).

Adds androidx.biometric; MainActivity becomes a FragmentActivity (required by
BiometricPrompt). JVM tests cover the gate state machine, invalidation policy,
and passphrase session; the Keystore/BiometricPrompt/restart paths are
device-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 00:24:37 -05:00
..