From ab4f41eb2acbbda2e97e580ba6131821c191bd86 Mon Sep 17 00:00:00 2001 From: Enginex0 Date: Sat, 11 Jul 2026 13:23:29 +0100 Subject: [PATCH] fix(keymint): enforce operation authorizations Add checkOperationAuthorizations to the AuthorizeCreate chain so the interceptor rejects operations whose parameters are incompatible with the key, matching real KeyMint HAL behavior: - block mode, padding, digest, and RSA-OAEP MGF digest must each be a subset of the key's authorized set; - AES-GCM rejects a requested MAC length below the key minimum; - RSA-OAEP requires a digest. Add the four backing KeyMint error codes (INCOMPATIBLE_BLOCK_MODE, INCOMPATIBLE_PADDING_MODE, INCOMPATIBLE_DIGEST, INVALID_MAC_LENGTH) to KeystoreErrorCodes, resolved at runtime with AOSP-correct fallbacks. The check reads the raw request params (AuthorizeCreate.check is called with parsedParams), so no op-param construction change is needed, and execution is unaffected: our SoftwareOperation already runs GCM (128-bit tag) and OAEP. --- .../keystore/shim/AuthorizeCreate.kt | 43 +++++++++++++++++++ .../keystore/shim/SoftwareOperation.kt | 16 +++++++ 2 files changed, 59 insertions(+) diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/AuthorizeCreate.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/AuthorizeCreate.kt index 99ae55a..ec3ad29 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/AuthorizeCreate.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/shim/AuthorizeCreate.kt @@ -1,8 +1,10 @@ package org.matrix.TEESimulator.interception.keystore.shim import android.hardware.security.keymint.Algorithm +import android.hardware.security.keymint.BlockMode import android.hardware.security.keymint.KeyParameter import android.hardware.security.keymint.KeyPurpose +import android.hardware.security.keymint.PaddingMode import android.hardware.security.keymint.Tag import org.matrix.TEESimulator.attestation.KeyMintAttestation @@ -18,6 +20,7 @@ object AuthorizeCreate { // Algorithm-level rejection runs before purpose-list check (AOSP HAL behavior) return checkAlgorithmPurpose(keyParams, purpose) ?: checkPurpose(keyParams, purpose) + ?: checkOperationAuthorizations(keyParams, opParams) ?: checkTemporalValidity(keyParams, purpose) ?: checkCallerNonce(keyParams, purpose, rawOpParams) } @@ -41,6 +44,46 @@ object AuthorizeCreate { return null } + private fun checkOperationAuthorizations( + keyParams: KeyMintAttestation, + opParams: KeyMintAttestation, + ): Int? { + if (opParams.blockMode.any { it !in keyParams.blockMode }) { + return KeystoreErrorCodes.incompatibleBlockMode + } + if (opParams.padding.any { it !in keyParams.padding }) { + return KeystoreErrorCodes.incompatiblePaddingMode + } + if (opParams.digest.any { it !in keyParams.digest }) { + return KeystoreErrorCodes.incompatibleDigest + } + if (opParams.rsaOaepMgfDigest.any { it !in keyParams.rsaOaepMgfDigest }) { + return KeystoreErrorCodes.incompatibleDigest + } + + if (keyParams.algorithm == Algorithm.AES && opParams.blockMode.contains(BlockMode.GCM)) { + val requestedMacLength = opParams.minMacLength + val keyMinMacLength = keyParams.minMacLength + if ( + requestedMacLength != null && + keyMinMacLength != null && + requestedMacLength < keyMinMacLength + ) { + return KeystoreErrorCodes.invalidMacLength + } + } + + if ( + keyParams.algorithm == Algorithm.RSA && + opParams.padding.contains(PaddingMode.RSA_OAEP) && + opParams.digest.isEmpty() + ) { + return KeystoreErrorCodes.incompatibleDigest + } + + return null + } + private fun checkTemporalValidity(keyParams: KeyMintAttestation, purpose: Int): Int? { val now = System.currentTimeMillis() 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 bf8551c..fe7ec12 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 @@ -501,6 +501,22 @@ internal object KeystoreErrorCodes { resolveField("android.hardware.security.keymint.ErrorCode", "UNKNOWN_ERROR", -1000) } + val incompatibleBlockMode: Int by lazy { + resolveField("android.hardware.security.keymint.ErrorCode", "INCOMPATIBLE_BLOCK_MODE", -8) + } + + val incompatiblePaddingMode: Int by lazy { + resolveField("android.hardware.security.keymint.ErrorCode", "INCOMPATIBLE_PADDING_MODE", -11) + } + + val incompatibleDigest: Int by lazy { + resolveField("android.hardware.security.keymint.ErrorCode", "INCOMPATIBLE_DIGEST", -13) + } + + val invalidMacLength: Int by lazy { + resolveField("android.hardware.security.keymint.ErrorCode", "INVALID_MAC_LENGTH", -57) + } + fun resolveField(className: String, fieldName: String, fallback: Int): Int = runCatching { Class.forName(className).getField(fieldName).getInt(null) } .getOrElse {