From e2dc7aa2104532257423c9a8177e18ac7a9beb8f Mon Sep 17 00:00:00 2001 From: Enginex0 Date: Thu, 25 Jun 2026 00:58:00 +0100 Subject: [PATCH] fix(keystore): vendor-gate real-op updateAad OperationInterceptor rejected non-AEAD updateAad with INVALID_TAG unconditionally, while SoftwareOperation's VendorQuirks gate returns success on Samsung and Xiaomi-MTK. On those devices the real-key and forged-key paths disagreed, and the genuine TEE accepts the call, so the inconsistency fingerprinted the injection layer through Duck Detector's operation error-path probe. Apply the same gate to the real-op path: a void success reply where nonAeadUpdateAadSucceeds(), else the INVALID_TAG reply. Promote VendorQuirks to internal so both paths share one decision. Refs #36 --- .../interception/keystore/shim/OperationInterceptor.kt | 9 ++++++++- .../interception/keystore/shim/SoftwareOperation.kt | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/OperationInterceptor.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/OperationInterceptor.kt index b8051ac..fa6792f 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/OperationInterceptor.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/OperationInterceptor.kt @@ -28,8 +28,15 @@ class OperationInterceptor( val methodName = transactionNames[code] ?: "unknown code=$code" logTransaction(txId, methodName, callingUid, callingPid, true) + // Mirror SoftwareOperation's vendor gate: a real-key op must answer non-AEAD updateAad + // exactly as the forged-key path does. Samsung and Xiaomi-MTK TEEs accept it; rejecting + // here while the forged path accepts diverges the two and fingerprints the injection. if (code == UPDATE_AAD_TRANSACTION && !isAead) { - return InterceptorUtils.createServiceSpecificErrorReply(KeystoreErrorCodes.invalidTag) + return if (VendorQuirks.nonAeadUpdateAadSucceeds()) { + InterceptorUtils.createSuccessReply(writeResultCode = false) + } else { + InterceptorUtils.createServiceSpecificErrorReply(KeystoreErrorCodes.invalidTag) + } } if (code == FINISH_TRANSACTION || code == ABORT_TRANSACTION) { diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/SoftwareOperation.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/SoftwareOperation.kt index e3831a2..bf8551c 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/SoftwareOperation.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/SoftwareOperation.kt @@ -29,7 +29,7 @@ import org.matrix.TEESimulator.logging.SystemLogger * device-identity fields the probe reads, so a forged software operation answers exactly as that * vendor's real TEE would. */ -private object VendorQuirks { +internal object VendorQuirks { private val UPDATE_AAD_ALLOWS_SUCCESS = setOf("samsung") private val XIAOMI_BRANDS = setOf("xiaomi", "redmi", "poco")