mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-06 11:28:22 +00:00
The GHSA-5fjp-ghh8-wch8 change made every ApplicationDao read decrypt the `secret`/`localKey` columns, and each decryption re-fetched the AMBER_AES_KEY Keystore key: KeyStore.getInstance().load(null) + containsAlias() + getEntry(), three sequential binder IPCs to the keystore daemon, per call. The Applications screen paid 2 x rows of those per page (Paging's initial load is 3 x pageSize rows), fully serialized, plus the TEE cipher operation itself — several seconds on a populated account. Two independent fixes: - SecureCryptoHelper: cache the SecretKey handle (the material never leaves the TEE/StrongBox; the object is a lightweight reference). Fast path is a volatile read; miss path double-checks under a synchronized block. All four public entry points run through withFreshKeyRetry, which retries exactly once with a re-fetched handle on stale-handle errors (InvalidKeyException, KeyStoreException, UnrecoverableKeyException, ProviderException) so concurrent key rotation or the opt-in unlocked-device policy cannot wedge reads. GCM AEADBadTagException (corrupt/wrong-key ciphertext) still propagates immediately, preserving the decryptField failure contract. rotateKey updates the cache in both of its branches. - ApplicationDao: the Applications list now queries a dedicated projection (ApplicationListItem: key, name, relays, icon, lastUsed) that never selects the encrypted columns, so the screen performs zero Keystore operations regardless of row count. The screen renders neither secret nor localKey, so the SELECT * decrypts were pure overhead. DecryptingPagingSource is removed with its only caller. The Pager is also remember(account.hexKey)-ed: it was previously rebuilt on every recomposition (killSwitch / backup-warning state flips), re-running the initial load each time. Also adapts ApplicationsScreen to the NavHostControllerWrapper stability pattern used by the other screens. Verified: ktlintCheck, lint, test (all variants), assembleFreeDebug, assembleOfflineDebug.