Skip to content

Releases: Enginex0/TEESimulator-RS

TEESimulator-RS v6.0.1-251

30 May 12:47

Choose a tag to compare

TEESimulator-RS v6.0.1-251

14 commits since v6.0.0-235. Clears the remaining Duck Detector grant-domain rows (incl. the Android 16 OnePlus report), restores Google Wallet and fingerprint compatibility, and removes the in-module patch-level/bulletin resolvers. Test device (SDK 35) TEE tamper score 28 → 8.

Detection coverage

  • Grant plane virtualized: owner read and cross-app Domain.GRANT read return one identical chain. 6 RED rows cleared. (28 → 18)
  • Generate-mode fingerprint: dropped 2 surplus authorizations (both patchlevels), USER_ID moved to SOFTWARE to mirror a captured device. (18 → 8)
  • Android 16 grant: patch-mode keys now served on the grant plane, so owner and grant reads match — fixes CHAIN_SPLIT.
  • Grant gated to SDK ≥ 36: Android 15 answers PERMISSION_DENIED, no synthetic over-capability.
  • Stale-chain eviction: import and updateSubcomponent drop the cached attestation; no pre-mutation chain replays.
  • Lifecycle coherence: clearNamespace / deleteAllKeys / migrateKeyNamespace mirror synthetic key and grant state — defeats delete-then-read probes.
  • Device-ID attestation mirrors the real TEE: returns CANNOT_ATTEST_IDS where silicon can't attest, instead of forging it.

App compatibility

  • Google Wallet: INCLUDE_UNIQUE_ID stripped (not rejected) when the caller lacks the permission; card binding works. (PR #27)
  • Fingerprint / vendor keys: KEY_ID miss skips the post-handler, so real HAL operations are no longer wrapped and broken. (PR #26)

Removed

  • PatchLevelManager — auto-resolved the security-patch date from an installed PlayIntegrityFix module (with hot-reload) and applied it to props.
  • BulletinPoller — scheduled security-bulletin refresh.

Other

  • Release builds purge stale teesim-*.bin diagnostics from /data/local/tmp at boot.
  • Vol-key confirmation rewritten to 1s getevent bursts (piped stream missed single presses on Magisk).

Verified

  • SDK 35, Xiaomi 23106RN0DA: tamper 28 → 8; generate-mode signal gone; 4 grant rows UNAVAILABLE (correct for Android 15); no regressions.
  • Android 16 grant fix built but unconfirmed on SDK 36 — needs an affected OnePlus user to confirm the grant rows clear.

TEESimulator-RS v6.0.0-235

20 May 06:06

Choose a tag to compare

11 commits since v6.0.0-224. Duck Detector generate-mode fingerprint cleared. Shizuku-routed BYO attestation fixed. Vol-key confirmation restored on Magisk.

Detection Coverage

  • Duck Detector "TEE Simulator generate-mode fingerprint" cleared. toAuthorizations reordered to AOSP keymint reference order; KEY_SIZE moves from auth#4 to auth#2, breaking the byte-224 anchor the probe relied on. 0/31 matches on fresh self-probes (was 15/36).
  • persist.logd.size variants blanked at boot via service.sh. Removes a logd-tuning side-channel.

BYO & Shizuku Routing

  • Shizuku-routed BYO attestation no longer fails with -49 UNSUPPORTED_TAG. shouldSkipUid moved into handleGenerateKey, evaluated after BYO parameters are parsed.
  • createOperation parallel fix: outer UID gate removed; the cache-or-forward lookup is the sole gate. BYO keys created under Shizuku UID can now be used for signing under the same UID.
  • forceGenerate simplified: any attest-key or BYO request routes to software unconditionally.
  • BYO attest-key miss returns the full keybox chain instead of a malformed depth-1 chain.
  • AUTO TEE race dispatch removed. Resolution uses DeviceAttestationService.isTeeFunctional only.
  • Symmetric gen rejects attestationKey != null early with INVALID_ARGUMENT. Unsupported-algorithm branch returns -38 instead of -49.

Action Button

  • Vol+ / Vol- confirmation restored on Magisk. Streaming getevent -lq matched inline against KEY_VOLUMEUP DOWN / KEY_VOLUMEDOWN DOWN, wrapped in /system/bin/timeout 10. The prior polled approach timed out on six-events-per-keypress kernels.

Verified

  • Android 15 (SDK 35), daemon PID 1466.
  • Cross-device confirmation pending on OnePlus PKX110 and Samsung SM-S928B.

v6.0.0-224: Action button hardened + 22-language i18n

19 May 19:11

Choose a tag to compare

Action button hardened: vol+ confirm + 22-language i18n

Builds on v6.0.0-222 (TEE probe cleared). Two commits address a
user-reported UX issue where the root manager's Action button was
being triggered by accident, wiping persistent_keys.

ff5eb79 feat(action): require vol+ confirm to clear keys
6455903 feat(action): i18n the clear-keys confirmation

Action flow:

  • Vol+ confirms clear, Vol- cancels, 10-second timeout defaults to
    cancel (destructive op stays explicit-only).
  • Every echoed string resolves through _msg() against the device
    locale.

Languages shipped (22 + English default):
ar, az, bn, de, el, es-ES, fa, fr, id, it, ja, ko, pl, pt-BR, ru,
th, tl, tr, uk, vi, zh-CN, zh-TW.

Verified on Xiaomi Android 16 (en) v6.0.0-224-Release: vol+ clears,
vol- cancels, 10s timeout cancels. Daemon alive PID 1392.

Changelog: https://github.com/Enginex0/TEESimulator-RS/blob/main/module/changelog.md

v6.0.0-222: TEE probe cleared on Xiaomi

19 May 19:12

Choose a tag to compare

TEE probe cleared on Xiaomi (AOSP-like behavior)

Three commits land the full fix for Duck Detector's TamperScore-4
TimingSideChannelProbe needle across all configured modes:

6bc1e43 fix(config): isAutoMode reads raw package mode
599fd39 feat(intercept): resolve KEY_ID via teeResponses
be91ea7 fix(intercept): cache non-attested keys for parity

Verified on Xiaomi Android 16 (SDK 35) v6.0.0-222-Release:

TEE verdict: WARNING -> CLEAR
'Local TEE attestation checks aligned'
Timing ratio: 1.555x Positive -> 1.055x Not positive
(threshold > 1.1x)
Attested: 0.976ms -> 0.846ms
Non-attested: 1.517ms -> 0.802ms

Pending cross-device confirmation on OnePlus PKX110 (qcom sun) and
Samsung SM-S928B (pineapple), both of which showed the same needle
on v6.0.0-211.

v6.0.0-162

31 Mar 18:47

Choose a tag to compare

Repository consolidation release. All tee-rebuild work merged as the new main branch.

AOSP Self-Signed Cert Compliance

  • No-challenge keys now generate self-signed certs (subject == issuer, depth 1), matching AOSP ta/src/keys.rs:451-478
  • Both Kotlin (BouncyCastle) and Rust (native-certgen) paths corrected
  • Eliminates attestation behavioral probes that detect keybox issuer on non-attested keys

Stability

  • Binder stress crash hardening for concurrent generateKey calls
  • AUTO mode TEE race for consistent attestation on devices with working G10
  • Oversized transactions routed to software gen instead of crashing
  • Operation-time params (BLOCK_MODE, PADDING, DIGEST) passed through to CipherPrimitive

Banking App Compatibility

  • Bare target.txt entries now default to AUTO mode, resolved at config level to PATCH (working TEE) or GENERATE (broken TEE)
  • Fixes BHIM and similar banking apps that require TEE-backed attestation keys
  • Restores v5.0 behavior where AUTO was resolved before the interceptor dispatch, avoiding the non-deterministic raceTeePatch path

Infrastructure

  • Version scheme changed to semver (v6.0.0)
  • Repository moved to TEESimulator-RS as canonical source

v6.0.0-156

26 Mar 11:38

Choose a tag to compare

Repository consolidation release. All tee-rebuild work merged as the new main branch.

AOSP Self-Signed Cert Compliance

  • No-challenge keys now generate self-signed certs (subject == issuer, depth 1), matching AOSP ta/src/keys.rs:451-478
  • Both Kotlin (BouncyCastle) and Rust (native-certgen) paths corrected
  • Eliminates attestation behavioral probes that detect keybox issuer on non-attested keys

Stability

  • Binder stress crash hardening for concurrent generateKey calls
  • AUTO mode TEE race for consistent attestation on devices with working G10
  • Oversized transactions routed to software gen instead of crashing
  • Operation-time params (BLOCK_MODE, PADDING, DIGEST) passed through to CipherPrimitive

Infrastructure

  • Version scheme changed to semver (v6.0.0)
  • Repository moved to TEESimulator-RS as canonical source

v5.1.1-164

22 Mar 00:54

Choose a tag to compare

Restores all custom hardening fixes that were lost during the PR JingMatrix#157 migration. These were working in pre-stash builds but never carried over to the post-stash codebase, causing user-reported regressions (boot hash instability, DuckDetector score regression, config crash on file deletion).

  • Boot hash persistence restored: 4-step fallback (sysprop, TEE, file, random) with file writes at every step. Fixes "Boot: Unavailable" where boot hash randomized every reboot on devices without ro.boot.vbmeta.digest
  • Presence-based findBoolean for KeyMint tags: boolean tags are presence-based per AIDL spec, .boolValue field isn't reliably populated across Android versions
  • noAuthRequired defaults to true when not explicitly false, matching AOSP KeyMint behavior
  • callerNonce tag now flows through to software-enforced attestation list
  • CTR block mode restored in cipher algorithm mapping (was dropped in PR JingMatrix#157)
  • AEAD guard on updateAad: non-GCM operations throw INVALID_TAG
  • Error code resolution via lazy reflection with correct KeyMint AIDL fallback values
  • Latency floor on SoftwareOperation.finish() for StrongBox timing simulation
  • FileObserver NPE fixed: null-safe handling on config file DELETE events
  • system=prop consistency: forces boot/vendor patch levels to derive from device props
  • StrongBox simulation restored: capability checks (RSA<=2048, EC=P256), concurrent op limits (4 max), keygen latency floor (250ms), op latency floor (80ms)
  • Binder buffer guard: MAX_ALIAS_LENGTH (256KB) rejects oversized aliases before processing
  • Key lifecycle tracking: deletedSoftwareKeys set prevents ghost key responses after deletion
  • Per-UID operation limits: 15 TEE, 4 StrongBox with LRU eviction
  • EC+DECRYPT rejection in createOperation, matching AOSP unsupported purpose check
  • Attest key nspace update aligned with upstream PR JingMatrix#169

v5.1-153

21 Mar 14:10

Choose a tag to compare

Major release. 27 files changed, 2300 lines rewritten. The entire Kotlin interception layer has been rebuilt with a clean architecture, proper AIDL alignment, and significantly lower binder overhead.

Interception Layer Rewrite

  • KeyMintSecurityLevelInterceptor completely restructured: GeneratedKeyInfo now carries full KeyMintAttestation instead of nullable stub, eliminating scattered null checks across every operation path
  • SoftwareOperation rewritten with sealed CryptoPrimitive interface separating Signer, Verifier, Encryptor, and Decryptor into isolated implementations with proper JCA algorithm mapping
  • KeystoreErrorCode centralized object replaces scattered magic numbers for all KeyMint and Keystore2 error codes
  • listEntries moved from pre-transact parameter caching to post-transact injection, eliminating a race condition where cached params could go stale
  • deleteKey now handles both APP domain (by alias) and KEY_ID domain (by nspace) resolution paths correctly
  • AuthorizeCreate and AndroidPermissionUtils removed, authorization logic consolidated into the operation dispatch path
  • DeviceAttestationService removed, attestation routing simplified into the main interceptor

Software Crypto Operations

  • GCM nonce returned in CreateOperationResponse.parameters for encrypt operations, matching real KeyMint HAL behavior
  • updateAad correctly throws INVALID_TAG on non-AEAD operations instead of silently succeeding
  • Cipher algorithm mapping cleaned up: dropped CTR block mode and RSA_PKCS1_1_5_SIGN padding that caused JCA provider mismatches
  • All crypto exceptions wrapped as ServiceSpecificException with correct KeyMint error codes instead of raw exceptions

Attestation & Certificate Generation

  • CertificateGenerator rewritten with clean Kotlin Pair return type instead of Android's util.Pair
  • AttestationBuilder field ordering aligned with AOSP KeyDescription ASN.1 schema
  • Unique ID computation follows KeyMint HAL spec: HMAC-SHA256(temporal_counter || AAID || reset_flag, HBK) truncated to 128 bits
  • Patch level logging removed from hot path to reduce logcat noise on every attestation

Configuration & Device Properties

  • ConfigurationManager target package parsing refactored: mode/package extraction deduplicated across GENERATE/PATCH/AUTO branches
  • system=prop forced boot/vendor override removed, now respects explicit per-component patch level configuration
  • FileObserver delete handler simplified with direct file access instead of defensive null-checks
  • AndroidDeviceUtils expanded with additional device property accessors for attestation fields

Binder Performance

  • Safe parcel reads at 6 deserialization sites, replacing force-unwrap NPE paths with early-return on null. A single NPE generates a full stack trace that blocks the binder thread for ~2ms
  • teeResponses cache populated on generateKey/importKey post-transact, reducing getKeyEntry from 2+ binder round-trips to 1
  • pingBinder liveness check removed from pre-transact failure path, eliminating a synchronous IPC call on every failed transaction
  • Native transaction code filtering at C++ level, skipping JNI entirely for PING/INTERFACE/DUMP

Dynamic SecurityLevel Binder Registration

  • Intercepts getSecurityLevel replies to register hooks on every new BBinder instance keystore2 returns, not just the initial one from setup
  • Identity hash deduplication prevents double-hooking when keystore2 returns the same binder across multiple calls
  • Resolves apps that call getSecurityLevel independently and receive a different binder than the one registered at startup

Build & Packaging

  • Rust native build task integrated into Gradle with cargo-ndk for aarch64/armv7/x86/x86_64
  • Module ZIP includes all 4 native libraries (libTEESimulator, libsupervisor, libcertgen, libinject)
  • customize.sh extraction restored for supervisor daemon and native cert gen library
  • TeeLatencySimulator added as standalone utility for log-normal hardware latency emulation

v5.0-138

19 Mar 06:41

Choose a tag to compare

Major release integrating 30+ AOSP compliance improvements from upstream PR JingMatrix#157 analysis, layered on top of our StrongBox hardening and native cert gen architecture.

Attestation Extension Alignment

  • 17 enforcement tags added to KeyMintAttestation (ACTIVE_DATETIME, ORIGINATION_EXPIRE, USAGE_EXPIRE, USAGE_COUNT_LIMIT, CALLER_NONCE, UNLOCKED_DEVICE_REQUIRED, INCLUDE_UNIQUE_ID, ROLLBACK_RESISTANCE, EARLY_BOOT_ONLY, ALLOW_WHILE_ON_BODY, TRUSTED_USER_PRESENCE_REQUIRED, TRUSTED_CONFIRMATION_REQUIRED, NO_AUTH_REQUIRED, MAX_USES_PER_BOOT, MAX_BOOT_LEVEL, MIN_MAC_LENGTH, RSA_OAEP_MGF_DIGEST)
  • BLOCK_MODE encoded as SET OF INTEGER per AOSP attestation_record.h
  • Version-guarded tags (RSA_OAEP_MGF_DIGEST >=100, ROLLBACK_RESISTANCE >=3, EARLY_BOOT_ONLY >=4)
  • INCLUDE_UNIQUE_ID computed via HMAC-SHA256 per KeyMint HAL spec using device HBK
  • AAID gated on attestation challenge presence
  • Certificate validity defaults aligned with AOSP (epoch notBefore, 9999-12-31 notAfter)

Binder Infrastructure

  • Native transaction code filtering at C++ level, skipping JNI for non-intercepted codes
  • getNumberOfEntries includes software-generated key count
  • deleteKey resolves KEY_ID domain via generatedKeys lookup
  • patchAuthorizations for OS/VENDOR/BOOT patch levels in authorization arrays

Software Operation AOSP Conformance

  • updateAad on non-AEAD operations returns INVALID_TAG (-76), matching AOSP operation.rs
  • All crypto exceptions wrapped as ServiceSpecificException with correct KeyMint error codes
  • GCM IV returned in CreateOperationResponse.parameters for encrypt operations
  • SoftwareOperationBinder methods @synchronized, matching AOSP Mutex per operation
  • authorize_create enforcement: PURPOSE validation, algorithm-purpose compatibility, temporal constraints, CALLER_NONCE prohibition, WRAP_KEY rejection

Security and Configuration

  • SELinux permission checks via /proc/pid/attr/current
  • Per-UID permission verification through IPackageManager.checkPermission
  • Imported key tracking prevents stale attest-key overrides in getKeyEntry
  • nspace consistency fix in attest-key override path
  • TeeLatencySimulator with log-normal distribution matching real hardware profiles
  • Device-unique HBK seed generated on install (32 bytes from /dev/random)

Preserved from v4.8

  • StrongBox op limits (4 concurrent max, TOO_MANY_OPERATIONS rejection)
  • LRU operation pruning per security level
  • Hardware keygen rate limiting (2/30s sliding window, 2 concurrent cap)
  • Native Rust cert generation with BouncyCastle fallback
  • Key persistence across reboots

v4.8-132

18 Mar 02:29

Choose a tag to compare

  • StrongBox op limit gate fixtrackAndEnforceOpLimit was only called in the Domain.KEY_ID not-found path, so software-generated keys (found via Domain.APP) bypassed STRONGBOX_MAX_CONCURRENT_OPS=4 entirely. DuckDetector's concurrent signing handles test created 24+ operations that all succeeded via LRU pruning instead of being rejected with TOO_MANY_OPERATIONS (-29). Now enforced for all StrongBox createOperation paths.

Tested against DuckDetector on OnePlus (Android 16, KSU). Tamper score dropped from 32 to 8.

  • LRU operation pruning — Concurrent software operations capped at 15 per UID (TEE) and 4 per UID (StrongBox), with oldest-first eviction. Pruned operations return INVALID_OPERATION_HANDLE (-28), matching AOSP keystore2 malus-based pruning.
  • StrongBox param guard — Unsupported StrongBox params (RSA >2048-bit, non-P256 EC curves) forwarded to real HAL for proper rejection instead of generating in software.
  • StrongBox timing — Key generation floors at 250ms, signing at 80ms on StrongBox security level to match real secure element latency.
  • StrongBox op limit — Sliding-window enforcer caps concurrent StrongBox operations for both software and hardware key paths, returning TOO_MANY_OPERATIONS (-29) when exceeded.
  • ECDSA algorithm alias — Accept "ECDSA" in addition to "EC" as JCA private key algorithm name. Fixes SIGSEGV crash on Android 10 devices where the provider reports EC keys as "ECDSA". Closes #4.
  • createOperation domain handling — Software-generated keys now found via both Domain.APP (alias) and Domain.KEY_ID (nspace) lookup paths.
  • Permission guards — Device ID attestation tags (IMEI, MEID, serial) require caller permission checks.