From 8001a8678a097cc43930120bad10f2a2b3e7bb26 Mon Sep 17 00:00:00 2001 From: Enginex0 Date: Mon, 16 Mar 2026 13:23:36 +0100 Subject: [PATCH] fix(interception): absorb upstream correctness fixes and patch error reply format MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick three upstream fixes: Parcel position reset in hasException() so the method doesn't consume reply data (7804743), list_past_alias enumeration filter inversion (2aac65c), and KeyMetadata alignment with AOSP semantics — modificationTimeMs, Tag.ORIGIN, KeyDescriptor normalization (86db5bf). Additionally, createErrorReply() was missing the empty remote stack trace header int between the exception message and error code, per AOSP Status.cpp:196. Binder readers expecting the standard EX_SERVICE_SPECIFIC wire format would misparse our error replies. --- .../interception/keystore/InterceptorUtils.kt | 5 ++++- .../interception/keystore/ListEntriesHandler.kt | 2 +- .../shim/KeyMintSecurityLevelInterceptor.kt | 17 ++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt index bbfaeb4..af6ad64 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/InterceptorUtils.kt @@ -18,6 +18,7 @@ object InterceptorUtils { val parcel = Parcel.obtain().apply { writeInt(EX_SERVICE_SPECIFIC) writeString(null) + writeInt(0) // empty remote stack trace header (AOSP Status.cpp:196) writeInt(errorCode) } return BinderInterceptor.TransactionResult.OverrideReply(parcel) @@ -119,6 +120,8 @@ object InterceptorUtils { /** Checks if a reply parcel contains an exception without consuming it. */ fun hasException(reply: Parcel): Boolean { - return runCatching { reply.readException() }.exceptionOrNull() != null + val exception = runCatching { reply.readException() }.exceptionOrNull() + if (exception != null) reply.setDataPosition(0) + return exception != null } } diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/ListEntriesHandler.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/ListEntriesHandler.kt index 77e8bd0..05e4469 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/ListEntriesHandler.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/ListEntriesHandler.kt @@ -129,7 +129,7 @@ object ListEntriesHandler { startPastAlias: String?, ): List { return KeyMintSecurityLevelInterceptor.generatedKeys.keys - .filter { it.uid == uid && (startPastAlias == null || it.alias < startPastAlias) } + .filter { it.uid == uid && (startPastAlias == null || it.alias > startPastAlias) } .map { keyId -> KeyDescriptor().apply { this.domain = Domain.APP diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/KeyMintSecurityLevelInterceptor.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/KeyMintSecurityLevelInterceptor.kt index 7a99ba9..398287e 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/KeyMintSecurityLevelInterceptor.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/KeyMintSecurityLevelInterceptor.kt @@ -3,6 +3,7 @@ package org.matrix.TEESimulator.interception.keystore.shim import android.hardware.security.keymint.Algorithm import android.hardware.security.keymint.KeyParameter import android.hardware.security.keymint.KeyParameterValue +import android.hardware.security.keymint.KeyOrigin import android.hardware.security.keymint.Tag import android.os.IBinder import android.os.Parcel @@ -425,12 +426,20 @@ class KeyMintSecurityLevelInterceptor( params: KeyMintAttestation, descriptor: KeyDescriptor, ): KeyEntryResponse { + val normalizedKeyDescriptor = + KeyDescriptor().apply { + domain = Domain.KEY_ID + nspace = descriptor.nspace + alias = null + blob = null + } val metadata = KeyMetadata().apply { keySecurityLevel = securityLevel - key = descriptor + key = normalizedKeyDescriptor CertificateHelper.updateCertificateChain(this, chain.toTypedArray()).getOrThrow() authorizations = params.toAuthorizations(securityLevel) + modificationTimeMs = System.currentTimeMillis() } return KeyEntryResponse().apply { this.metadata = metadata @@ -665,6 +674,12 @@ private fun KeyMintAttestation.toAuthorizations(securityLevel: Int): Array