Skip to content

Fix hardware keystore crash on MediaTek devices (AES wrapped import)#184

Open
davidtorcivia wants to merge 1 commit intoOpenBubbles:rustpushfrom
davidtorcivia:fix/aes-keystore-import-test
Open

Fix hardware keystore crash on MediaTek devices (AES wrapped import)#184
davidtorcivia wants to merge 1 commit intoOpenBubbles:rustpushfrom
davidtorcivia:fix/aes-keystore-import-test

Conversation

@davidtorcivia
Copy link

@davidtorcivia davidtorcivia commented Mar 11, 2026

Summary

  • Add AES 256 GCM key import test to supports_import() so devices that fail AES wrapped key import correctly fall back to SoftwareKeystore
  • Fixes crash during onboarding activation: KeyStoreException: Failed to import wrapped key. Keystore error code: -59

Problem

I was unable to select "use this device" when registering Open Bubbles on my Bluefox NX1 (mediatek) beginning in late January 2026. adb logcat revealed this was a hardware keystore issue.

The hardware keystore capability test in supports_import() (rust/src/keystore.rs) tests RSA 1024 and EC P384 key imports, but never tests AES 256 wrapped key import. On some MediaTek TEEs, RSA and EC imports succeed but AES wrapped key import fails with UNSUPPORTED_MIN_MAC_LENGTH / error code -59.

This causes a runtime crash when AesKeystoreKey::ensure("ids:identity-storage-key:openbubbles", 256, ...) is called during activation, because the device was incorrectly classified as hardware-compatible.

Affected device

  • BlueFox NX1 — MediaTek MT6769V/CB (Helio G85), Android 15, SDK 35
  • Likely affects other MediaTek devices where the TEE supports RSA/EC but not AES wrapped key import

Fix

Add an AES 256 key import test after the existing RSA and EC tests in supports_import(), using the same KeyType::Aes(256) and EncryptMode::Gcm access rules as the real ids:identity-storage-key. If this test fails, the device correctly falls back to SoftwareKeystore.

// Test AES 256 wrapped key import (fails on some MediaTek TEEs)
keystore.destroy_key("test:aes")?;
let aes_key: [u8; 32] = rand::random();
keystore.import_key("test:aes", KeyType::Aes(256), &aes_key, KeystoreAccessRules {
    block_modes: vec![EncryptMode::Gcm],
    can_encrypt: true,
    can_decrypt: true,
    ..Default::default()
})?;
keystore.destroy_key("test:aes")?;

Test plan

  • Built patched APK and installed on affected BlueFox NX1 device
  • Cleared app data to reset keystore detection
  • Confirmed via adb logcat that keystore2 reports Error::Km(r#UNSUPPORTED_MIN_MAC_LENGTH) during the new AES test
  • Confirmed app falls back to SoftwareKeystore (logs show keystore:software:encryptor)
  • Confirmed no KeyStoreException crash — app runs normally
  • Verify no regression on devices where hardware keystore works correctly (AES test should pass transparently)

(Can't test the last one, but I confirmed the app now works properly on my NX1 - compiled with dummy fairplay certs).

…failures

The `supports_import()` capability test only checked RSA and EC key imports,
missing AES 256 wrapped key import which fails on some MediaTek TEEs
(e.g. BlueFox NX1 / MT6769V Helio G85) with Keystore error code -59
(UNSUPPORTED_MIN_MAC_LENGTH). This caused a crash during onboarding when
importing the `ids:identity-storage-key` AES key.

Add an AES 256 GCM import test matching the exact key type and access rules
used by the real identity storage key, so affected devices correctly fall back
to SoftwareKeystore.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@davidtorcivia
Copy link
Author

Fixes #185

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant