Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d21822eb9d | ||
|
|
095a658996 | ||
|
|
70e8968e44 | ||
|
|
c122ded7bf | ||
|
|
7b510a9915 | ||
|
|
8f63dda31b | ||
|
|
9896df93de | ||
|
|
0280bcf189 | ||
|
|
438a462bdf | ||
|
|
40b08cd648 | ||
|
|
c5ed627f68 | ||
|
|
bee73eb39b | ||
|
|
a0ee77202c |
+92
-65
@@ -3,16 +3,10 @@ name: Build
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/**'
|
||||
paths-ignore: [ '**.md' ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
- '.github/**'
|
||||
- '!.github/workflows/**'
|
||||
paths-ignore: [ '**.md' ]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
@@ -22,18 +16,9 @@ concurrency:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
contents: read
|
||||
|
||||
outputs:
|
||||
releaseName: ${{ steps.prepareArtifact.outputs.releaseName }}
|
||||
debugName: ${{ steps.prepareArtifact.outputs.debugName }}
|
||||
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: "recursive"
|
||||
fetch-depth: 0
|
||||
@@ -45,6 +30,25 @@ jobs:
|
||||
java-version: 21
|
||||
cache: 'gradle'
|
||||
|
||||
- name: Setup Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android
|
||||
|
||||
- name: Cache Rust artifacts
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
~/.cargo/bin/cargo-ndk
|
||||
native-certgen/target
|
||||
key: rust-${{ runner.os }}-${{ hashFiles('native-certgen/Cargo.lock') }}
|
||||
restore-keys: rust-${{ runner.os }}-
|
||||
|
||||
- name: Install cargo-ndk
|
||||
run: command -v cargo-ndk || cargo install cargo-ndk
|
||||
|
||||
- name: Set up ccache
|
||||
uses: hendrikmuhs/ccache-action@v1.2
|
||||
with:
|
||||
@@ -60,73 +64,96 @@ jobs:
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
chmod +x ./gradlew
|
||||
|
||||
./gradlew zipRelease zipDebug -Porg.gradle.parallel=true -Porg.gradle.vfs.watch=true -Dorg.gradle.jvmargs=-Xmx2048m
|
||||
|
||||
- name: Prepare artifact
|
||||
if: success()
|
||||
id: prepareArtifact
|
||||
- name: Read version
|
||||
id: ver
|
||||
run: |
|
||||
ver=$(grep 'val verName' app/build.gradle.kts | sed 's/.*"\(.*\)".*/\1/')
|
||||
echo "version=${ver}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Rename ZIPs for release
|
||||
run: |
|
||||
set -e
|
||||
RELEASE_FILE=$(find out -name "*Release*.zip" | head -1)
|
||||
DEBUG_FILE=$(find out -name "*Debug*.zip" | head -1)
|
||||
|
||||
if [[ -z "$RELEASE_FILE" || -z "$DEBUG_FILE" ]]; then
|
||||
echo "Error: Could not find release or debug files in out/"
|
||||
echo "Contents of out/ directory:"
|
||||
ls -la out/ || echo "out/ directory does not exist"
|
||||
echo "::error::Could not find release or debug ZIPs in out/"
|
||||
ls -la out/ || echo "out/ does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract names
|
||||
RELEASE_NAME=$(basename "$RELEASE_FILE" .zip)
|
||||
DEBUG_NAME=$(basename "$DEBUG_FILE" .zip)
|
||||
mv "$RELEASE_FILE" "out/TEESimulator-${VER}-Release.zip"
|
||||
mv "$DEBUG_FILE" "out/TEESimulator-${VER}-Debug.zip"
|
||||
|
||||
echo "releaseName=$RELEASE_NAME" >> $GITHUB_OUTPUT
|
||||
echo "debugName=$DEBUG_NAME" >> $GITHUB_OUTPUT
|
||||
echo "Release: TEESimulator-${VER}-Release.zip ($(du -h "out/TEESimulator-${VER}-Release.zip" | cut -f1))"
|
||||
echo "Debug: TEESimulator-${VER}-Debug.zip ($(du -h "out/TEESimulator-${VER}-Debug.zip" | cut -f1))"
|
||||
env:
|
||||
VER: ${{ steps.ver.outputs.version }}
|
||||
|
||||
mkdir -p module-release module-debug
|
||||
unzip -q "$RELEASE_FILE" -d module-release
|
||||
unzip -q "$DEBUG_FILE" -d module-debug
|
||||
echo " Release: $RELEASE_NAME"
|
||||
echo " Debug: $DEBUG_NAME"
|
||||
|
||||
- name: Upload release
|
||||
if: success()
|
||||
id: release
|
||||
uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.prepareArtifact.outputs.releaseName }}
|
||||
path: "./module-release/*"
|
||||
name: TEESimulator-release-zip
|
||||
path: out/TEESimulator-*-Release.zip
|
||||
retention-days: 30
|
||||
compression-level: 6
|
||||
compression-level: 0
|
||||
|
||||
- name: Upload debug
|
||||
if: success()
|
||||
id: debug
|
||||
uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ steps.prepareArtifact.outputs.debugName }}
|
||||
path: "./module-debug/*"
|
||||
name: TEESimulator-debug-zip
|
||||
path: out/TEESimulator-*-Debug.zip
|
||||
retention-days: 7
|
||||
compression-level: 6
|
||||
compression-level: 0
|
||||
|
||||
- name: Upload release mappings
|
||||
if: success()
|
||||
uses: actions/upload-artifact@v4
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-mappings-${{ github.run_number }}
|
||||
path: "./app/build/outputs/mapping/release"
|
||||
name: release-mappings
|
||||
path: app/build/outputs/mapping/release
|
||||
retention-days: 30
|
||||
compression-level: 9
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
release:
|
||||
needs: build
|
||||
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Read version
|
||||
id: ver
|
||||
run: |
|
||||
echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Status**: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Gradle Tasks**: assembleRelease, assembleDebug" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ job.status }}" == "success" ]]; then
|
||||
echo "- **Release Artifact**: ${{ steps.prepareArtifact.outputs.releaseName }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- **Debug Artifact**: ${{ steps.prepareArtifact.outputs.debugName }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
ver=$(grep 'val verName' app/build.gradle.kts | sed 's/.*"\(.*\)".*/\1/')
|
||||
echo "version=${ver}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: TEESimulator-release-zip
|
||||
path: zips
|
||||
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: TEESimulator-debug-zip
|
||||
path: zips
|
||||
|
||||
- name: Extract changelog
|
||||
run: |
|
||||
ver="${VER#v}"
|
||||
awk "/^## TEESimulator v${ver}/{flag=1; next} /^## TEESimulator v/{if(flag) exit} flag" module/changelog.md > /tmp/notes.md
|
||||
cat /tmp/notes.md
|
||||
env:
|
||||
VER: ${{ steps.ver.outputs.version }}
|
||||
|
||||
- name: Create release
|
||||
run: |
|
||||
gh release delete "$VER" --yes 2>/dev/null || true
|
||||
gh release create "$VER" \
|
||||
--title "$VER" \
|
||||
--latest \
|
||||
--notes-file /tmp/notes.md \
|
||||
"zips/TEESimulator-${VER}-Release.zip" \
|
||||
"zips/TEESimulator-${VER}-Debug.zip"
|
||||
env:
|
||||
VER: ${{ steps.ver.outputs.version }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
<p align="center"><b>Full TEE Emulation for Rooted Android</b></p>
|
||||
<p align="center">Hardware attestation. Software keys. Zero detection.</p>
|
||||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/version-v4.0-blue?style=for-the-badge" alt="v4.0">
|
||||
<a href="https://github.com/Enginex0/TEESimulator/actions/workflows/build.yml"><img src="https://github.com/Enginex0/TEESimulator/actions/workflows/build.yml/badge.svg" alt="Build"></a>
|
||||
<img src="https://img.shields.io/badge/version-v4.2-blue?style=for-the-badge" alt="v4.2">
|
||||
<img src="https://img.shields.io/badge/Android-10%2B-green?style=for-the-badge&logo=android" alt="Android 10+">
|
||||
<img src="https://img.shields.io/badge/Telegram-community-blue?style=for-the-badge&logo=telegram" alt="Telegram">
|
||||
</p>
|
||||
@@ -112,6 +113,24 @@ TEESimulator replaces TrickyStore, TrickyStoreOSS, and their forks. Existing con
|
||||
|
||||
---
|
||||
|
||||
## 🔨 Building from Source
|
||||
|
||||
The CI workflow builds on every push to `main`. You can also build locally or trigger a build from your own fork.
|
||||
|
||||
**Prerequisites:** JDK 21, Android SDK/NDK 27, Rust stable with `aarch64-linux-android` target, `cargo-ndk`.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Enginex0/TEESimulator.git
|
||||
cd TEESimulator
|
||||
./gradlew zipRelease zipDebug
|
||||
```
|
||||
|
||||
Output ZIPs land in `out/`. The Gradle build automatically invokes `cargo ndk` to cross-compile `libcertgen.so` before packaging.
|
||||
|
||||
To rebuild from a fork, push to `main` or use **Actions → Build → Run workflow**. The workflow installs all toolchains (Java, Rust, cargo-ndk, ccache) and uploads Release + Debug ZIPs as artifacts.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Configuration
|
||||
|
||||
All configuration files live at `/data/adb/tricky_store/` and are monitored by `FileObserver` — changes take effect immediately without rebooting.
|
||||
|
||||
@@ -29,7 +29,7 @@ val gitExecutor = objects.newInstance(GitExecutor::class.java)
|
||||
|
||||
val gitCommitCount = gitExecutor.execute("git rev-list HEAD --count", rootDir).toInt()
|
||||
val gitCommitHash = gitExecutor.execute("git rev-parse --verify --short HEAD", rootDir)
|
||||
val verName = "v4.1"
|
||||
val verName = "v4.3"
|
||||
|
||||
android {
|
||||
namespace = "org.matrix.TEESimulator"
|
||||
@@ -121,8 +121,8 @@ androidComponents {
|
||||
dependsOn("package${capitalized}")
|
||||
} else {
|
||||
dependsOn("minify${capitalized}WithR8")
|
||||
dependsOn("strip${capitalized}DebugSymbols")
|
||||
}
|
||||
dependsOn("strip${capitalized}DebugSymbols")
|
||||
dependsOn(buildRustCertgen)
|
||||
|
||||
if (isDebug) {
|
||||
@@ -140,12 +140,13 @@ androidComponents {
|
||||
}
|
||||
}
|
||||
|
||||
from(
|
||||
project.layout.buildDirectory.dir(
|
||||
"intermediates/stripped_native_libs/${variant.name}/strip${capitalized}DebugSymbols/out/lib"
|
||||
)
|
||||
) {
|
||||
into("lib") // Place them in the 'lib' subfolder of the staging directory.
|
||||
val nativeLibsDir = if (isDebug) {
|
||||
"intermediates/merged_native_libs/${variant.name}/merge${capitalized}NativeLibs/out/lib"
|
||||
} else {
|
||||
"intermediates/stripped_native_libs/${variant.name}/strip${capitalized}DebugSymbols/out/lib"
|
||||
}
|
||||
from(project.layout.buildDirectory.dir(nativeLibsDir)) {
|
||||
into("lib")
|
||||
include("**/libinject.so", "**/libTEESimulator.so", "**/libsupervisor.so", "**/libcertgen.so")
|
||||
}
|
||||
|
||||
|
||||
@@ -358,6 +358,12 @@ void inspectAndRewriteTransaction(binder_transaction_data *txn_data) {
|
||||
if (txn_data->data_size > kMaxInterceptableDataSize)
|
||||
return;
|
||||
|
||||
// AIDL methods use codes in [FIRST_CALL_TRANSACTION, LAST_CALL_TRANSACTION] (1..0x00ffffff).
|
||||
// System transactions (PING, INTERFACE, DUMP, SHELL_COMMAND) use codes above that range.
|
||||
// Skip those — intercepting a ping adds measurable latency that timing detectors flag.
|
||||
if (txn_data->code > 0x00ffffffu && txn_data->code != intercept::kBackdoorCode)
|
||||
return;
|
||||
|
||||
bool hijack = false;
|
||||
ThreadTransactionInfo info;
|
||||
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
static volatile sig_atomic_t should_exit = 0;
|
||||
|
||||
@@ -27,7 +29,12 @@ int main(int argc, char *argv[]) {
|
||||
const char *daemon_path = argv[1];
|
||||
char **daemon_argv = &argv[1];
|
||||
|
||||
int backoff_ms = 500;
|
||||
|
||||
while (!should_exit) {
|
||||
struct timespec child_start;
|
||||
clock_gettime(CLOCK_MONOTONIC, &child_start);
|
||||
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid < 0) {
|
||||
@@ -39,6 +46,7 @@ int main(int argc, char *argv[]) {
|
||||
if (pid == 0) {
|
||||
// Child: become the daemon
|
||||
prctl(PR_SET_PDEATHSIG, SIGKILL); // Die if parent dies
|
||||
setpriority(PRIO_PROCESS, 0, 10); // lower CPU priority than foreground
|
||||
execv(daemon_path, daemon_argv);
|
||||
perror("execv failed");
|
||||
_exit(127);
|
||||
@@ -50,7 +58,18 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
if (should_exit) break;
|
||||
|
||||
// Instant restart - no delay
|
||||
// Exponential backoff on rapid crashes, reset if child was stable
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
long lived_ms = (now.tv_sec - child_start.tv_sec) * 1000 +
|
||||
(now.tv_nsec - child_start.tv_nsec) / 1000000;
|
||||
|
||||
if (lived_ms > 30000) {
|
||||
backoff_ms = 500;
|
||||
} else {
|
||||
usleep(backoff_ms * 1000);
|
||||
if (backoff_ms < 30000) backoff_ms *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -23,8 +23,6 @@ import org.matrix.TEESimulator.util.AndroidDeviceUtils
|
||||
object App {
|
||||
// The delay in milliseconds before retrying to initialize the interceptor.
|
||||
private const val RETRY_DELAY_MS = 1000L
|
||||
// The sleep duration in milliseconds for the main service loop to keep the process alive.
|
||||
private const val SERVICE_SLEEP_MS = 1000000L
|
||||
|
||||
/**
|
||||
* The main entry point of the TEESimulator application.
|
||||
|
||||
@@ -17,8 +17,8 @@ object InterceptorUtils {
|
||||
fun createErrorReply(errorCode: Int): BinderInterceptor.TransactionResult.OverrideReply {
|
||||
val parcel = Parcel.obtain().apply {
|
||||
writeInt(EX_SERVICE_SPECIFIC)
|
||||
writeInt(errorCode)
|
||||
writeString(null)
|
||||
writeInt(errorCode)
|
||||
}
|
||||
return BinderInterceptor.TransactionResult.OverrideReply(parcel)
|
||||
}
|
||||
|
||||
+2
@@ -129,6 +129,7 @@ object GeneratedKeyPersistence {
|
||||
val file = File(PERSISTENCE_DIR, keyFileName(keyId.uid, keyId.alias))
|
||||
if (file.exists()) {
|
||||
if (file.delete()) {
|
||||
fileLocks.remove(keyFileName(keyId.uid, keyId.alias))
|
||||
SystemLogger.debug("Deleted persisted key: $keyId")
|
||||
} else {
|
||||
SystemLogger.warning("Failed to delete persisted key file: ${file.name}")
|
||||
@@ -158,6 +159,7 @@ object GeneratedKeyPersistence {
|
||||
if (file.delete()) count++
|
||||
}
|
||||
}
|
||||
fileLocks.clear()
|
||||
SystemLogger.info("Deleted $count persisted key files")
|
||||
}.onFailure { e ->
|
||||
SystemLogger.error("Failed to delete all persisted keys", e)
|
||||
|
||||
+18
@@ -254,6 +254,18 @@ class KeyMintSecurityLevelInterceptor(
|
||||
return InterceptorUtils.createErrorReply(KEYMINT_INVALID_INPUT_LENGTH)
|
||||
}
|
||||
|
||||
if (params.any { it.tag == Tag.CREATION_DATETIME }) {
|
||||
SystemLogger.warning("[TX_ID: $txId] Rejecting CREATION_DATETIME in generateKey params")
|
||||
return InterceptorUtils.createErrorReply(RESPONSE_INVALID_ARGUMENT)
|
||||
}
|
||||
|
||||
if (parsedParams.serial != null || parsedParams.imei != null ||
|
||||
parsedParams.meid != null || parsedParams.secondImei != null ||
|
||||
params.any { it.tag == Tag.DEVICE_UNIQUE_ATTESTATION }) {
|
||||
SystemLogger.warning("[TX_ID: $txId] Rejecting device ID attestation for uid=$callingUid")
|
||||
return InterceptorUtils.createErrorReply(KEYMINT_CANNOT_ATTEST_IDS)
|
||||
}
|
||||
|
||||
val keyId = KeyIdentifier(callingUid, keyDescriptor.alias)
|
||||
val isAttestKeyRequest = parsedParams.isAttestKey()
|
||||
|
||||
@@ -515,6 +527,8 @@ class KeyMintSecurityLevelInterceptor(
|
||||
// Binder buffer is ~1MB; 256KB provides 4x safety margin for transaction overhead
|
||||
private const val MAX_ALIAS_LENGTH = 256 * 1024
|
||||
private const val KEYMINT_INVALID_INPUT_LENGTH = -21
|
||||
private const val RESPONSE_INVALID_ARGUMENT = 20
|
||||
private const val KEYMINT_CANNOT_ATTEST_IDS = -66
|
||||
private const val MAX_CONCURRENT_HW_KEYGEN_PER_UID = 2
|
||||
// Sliding window: max hardware keygen permits per UID within the burst window
|
||||
private const val MAX_HW_KEYGEN_PER_WINDOW = 2
|
||||
@@ -532,6 +546,10 @@ class KeyMintSecurityLevelInterceptor(
|
||||
val timestamps = uidKeygenTimestamps.computeIfAbsent(uid) { mutableListOf() }
|
||||
synchronized(timestamps) {
|
||||
timestamps.removeAll { now - it > BURST_WINDOW_MS }
|
||||
if (timestamps.isEmpty()) {
|
||||
uidKeygenTimestamps.remove(uid, timestamps)
|
||||
uidHardwareKeygenCount.remove(uid)
|
||||
}
|
||||
return timestamps.size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ object SystemLogger {
|
||||
* @param message The message to log.
|
||||
*/
|
||||
fun debug(message: String) {
|
||||
if (!isDebugBuild) return
|
||||
Log.d(TAG, message)
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ object CertificateGenerator {
|
||||
uid: Int,
|
||||
securityLevel: Int,
|
||||
): Certificate {
|
||||
val subject = params.certificateSubject ?: X500Name("CN=Android KeyStore Key")
|
||||
val subject = params.certificateSubject ?: X500Name("CN=Android Keystore Key")
|
||||
val leafNotAfter =
|
||||
(signingKeyPair.public as? X509Certificate)?.notAfter
|
||||
?: Date(System.currentTimeMillis() + 31536000000L)
|
||||
|
||||
@@ -1,3 +1,35 @@
|
||||
## TEESimulator v4.3: Performance & Reliability
|
||||
|
||||
- **Debug log gating** — `SystemLogger.debug()` now skipped entirely in release builds, eliminating unnecessary logcat syscalls on every intercepted transaction.
|
||||
- **Supervisor backoff** — Exponential restart delay (500ms → 30s cap) prevents CPU spin if the daemon crashes repeatedly. Resets automatically once stable.
|
||||
- **Process priority** — Daemon runs at nice=10, yielding CPU to foreground apps on constrained devices.
|
||||
- **Map eviction** — Rate limiter and file lock maps now evict stale entries instead of growing unbounded.
|
||||
- **CI pipeline** — Single-trigger build→release pipeline with proper changelog extraction and correctly sized artifacts.
|
||||
|
||||
---
|
||||
|
||||
## TEESimulator v4.2: Detection Evasion Hardening
|
||||
|
||||
Fixes 6 detection vectors flagged by attestation validator apps.
|
||||
|
||||
### Attestation Policy Enforcement
|
||||
|
||||
Replicate AOSP keystore2's `add_required_parameters()` validation that our software keygen path was bypassing:
|
||||
|
||||
- **CREATION_DATETIME** — Reject caller-provided input with `INVALID_ARGUMENT (20)`, matching `security_level.rs:424`. Our cert gen still adds its own timestamp, same as real keystore2.
|
||||
- **Device ID attestation** — Reject ATTESTATION_ID_SERIAL, IMEI, MEID, SECOND_IMEI, and DEVICE_UNIQUE_ATTESTATION with `CANNOT_ATTEST_IDS (-66)`. No consumer app has READ_PRIVILEGED_PHONE_STATE.
|
||||
- **Error reply format** — Fixed AIDL ServiceSpecificException parcel write order (was errorCode→message, now message→errorCode).
|
||||
|
||||
### Certificate Fix
|
||||
|
||||
Leaf certificate Subject CN corrected from "Android KeyStore Key" to "Android Keystore Key" (lowercase s), matching AOSP `KeyGenParameterSpec.java:282`. Both Kotlin and Rust paths.
|
||||
|
||||
### Binder Timing
|
||||
|
||||
Skip interception for system transaction codes (PING, INTERFACE, DUMP) above LAST_CALL_TRANSACTION. Eliminates the JNI round-trip that inflated binder ping ratio to 3.85x (detector threshold: 3.0x).
|
||||
|
||||
---
|
||||
|
||||
## TEESimulator v4.1: Boot Identity Persistence
|
||||
|
||||
Bugfix release. The vbmeta boot key digest was randomizing on every reboot, producing a different RootOfTrust in attestation certificates each boot.
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"version": "v4.1",
|
||||
"versionCode": 94,
|
||||
"zipUrl": "https://github.com/Enginex0/TEESimulator/releases/download/v4.1/TEESimulator-v4.1-Release.zip",
|
||||
"version": "v4.3",
|
||||
"versionCode": 107,
|
||||
"zipUrl": "https://github.com/Enginex0/TEESimulator/releases/download/v4.3/TEESimulator-v4.3-Release.zip",
|
||||
"changelog": "https://raw.githubusercontent.com/Enginex0/TEESimulator/main/module/changelog.md"
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ fn build_leaf_cert(
|
||||
let subject_dn_der = if let Some(ref subject) = params.cert_subject {
|
||||
subject.clone()
|
||||
} else {
|
||||
encode_simple_cn_dn("Android KeyStore Key")
|
||||
encode_simple_cn_dn("Android Keystore Key")
|
||||
};
|
||||
|
||||
// Validity
|
||||
|
||||
Reference in New Issue
Block a user