From 1475c0be020dd43e8339703a684cad6cb03e57ed 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 Cherry-pick three upstream fixes: Parcel position reset in hasException() so the method doesn't consume reply data (bab7093), list_past_alias enumeration filter inversion (71f75de), and KeyMetadata alignment with AOSP semantics, modificationTimeMs, Tag.ORIGIN, KeyDescriptor normalization (4e3dcc5). 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