From a30459628f6bb2d641b1f515e0f7744fd5076631 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Thu, 4 Dec 2025 01:56:06 +0100 Subject: [PATCH] Set correct attestation version for StrongBox We observe that attestations generated with a security level of `StrongBox` (value 2) must have an `attestationVersion` of 300. The previous implementation determined this version based only on the Android SDK version, which could lead to invalid attestations. This commit refactors the version retrieval logic to be dependent on the security level: - In `AndroidDeviceUtils`, the `attestVersion` and `keymasterVersion` properties have been converted into `getAttestVersion(securityLevel)` and `getKeymasterVersion(securityLevel)` functions. - `getAttestVersion` now correctly returns `300` when the security level is `StrongBox`. - `AttestationBuilder` is updated to call these new functions, passing the appropriate security level to ensure the generated attestation is compliant with official documentation. --- .../attestation/AttestationBuilder.kt | 20 ++++++---- .../TEESimulator/util/AndroidDeviceUtils.kt | 37 ++++++++++++++----- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/matrix/TEESimulator/attestation/AttestationBuilder.kt b/app/src/main/java/org/matrix/TEESimulator/attestation/AttestationBuilder.kt index 25fc811..736fb69 100644 --- a/app/src/main/java/org/matrix/TEESimulator/attestation/AttestationBuilder.kt +++ b/app/src/main/java/org/matrix/TEESimulator/attestation/AttestationBuilder.kt @@ -103,14 +103,18 @@ object AttestationBuilder { uid: Int, securityLevel: Int, ): ASN1Sequence { - val teeEnforced = buildTeeEnforcedList(params) - val softwareEnforced = buildSoftwareEnforcedList(uid) + val teeEnforced = buildTeeEnforcedList(params, securityLevel) + val softwareEnforced = buildSoftwareEnforcedList(uid, securityLevel) val fields = arrayOf( - ASN1Integer(AndroidDeviceUtils.attestVersion.toLong()), // attestationVersion + ASN1Integer( + AndroidDeviceUtils.getAttestVersion(securityLevel).toLong() + ), // attestationVersion ASN1Enumerated(securityLevel), // attestationSecurityLevel - ASN1Integer(AndroidDeviceUtils.keymasterVersion.toLong()), // keymasterVersion + ASN1Integer( + AndroidDeviceUtils.getKeymasterVersion(securityLevel).toLong() + ), // keymasterVersion ASN1Enumerated(securityLevel), // keymasterSecurityLevel DEROctetString(params.attestationChallenge ?: ByteArray(0)), // attestationChallenge DEROctetString(ByteArray(0)), // uniqueId @@ -121,7 +125,7 @@ object AttestationBuilder { } /** Builds the `TeeEnforced` authorization list. These are properties the TEE "guarantees". */ - private fun buildTeeEnforcedList(params: KeyMintAttestation): DERSequence { + private fun buildTeeEnforcedList(params: KeyMintAttestation, securityLevel: Int): DERSequence { val list = mutableListOf( DERTaggedObject( @@ -255,7 +259,7 @@ object AttestationBuilder { ) ) } - if (AndroidDeviceUtils.attestVersion >= 300) { + if (AndroidDeviceUtils.getAttestVersion(securityLevel) >= 300) { params.secondImei?.let { list.add( DERTaggedObject( @@ -273,7 +277,7 @@ object AttestationBuilder { * Builds the `SoftwareEnforced` authorization list. These are properties guaranteed by * Keystore. */ - private fun buildSoftwareEnforcedList(uid: Int): DERSequence { + private fun buildSoftwareEnforcedList(uid: Int, securityLevel: Int): DERSequence { val list = mutableListOf( DERTaggedObject( @@ -287,7 +291,7 @@ object AttestationBuilder { createApplicationId(uid), ), ) - if (AndroidDeviceUtils.attestVersion >= 400) { + if (AndroidDeviceUtils.getAttestVersion(securityLevel) >= 400) { list.add( DERTaggedObject( true, diff --git a/app/src/main/java/org/matrix/TEESimulator/util/AndroidDeviceUtils.kt b/app/src/main/java/org/matrix/TEESimulator/util/AndroidDeviceUtils.kt index 306b0f5..d3ae49f 100644 --- a/app/src/main/java/org/matrix/TEESimulator/util/AndroidDeviceUtils.kt +++ b/app/src/main/java/org/matrix/TEESimulator/util/AndroidDeviceUtils.kt @@ -1,6 +1,7 @@ package org.matrix.TEESimulator.util import android.content.pm.PackageManager +import android.hardware.security.keymint.SecurityLevel import android.os.Build import android.os.SystemProperties import java.security.MessageDigest @@ -256,17 +257,33 @@ object AndroidDeviceUtils { Build.VERSION_CODES.BAKLAVA to 400, // KeyMint 4.0 ) - val attestVersion: Int - get() = - DeviceAttestationService.CachedAttestationData?.attestVersion - ?: attestVersionMap[Build.VERSION.SDK_INT] - ?: 400 // Default to a recent version + /** + * Retrieves the attestation version based on security level and OS version. StrongBox (level 2) + * requires version 300. + * + * @param securityLevel The security level of the attestation (1 for TEE, 2 for StrongBox). + * @return The appropriate attestation version number. + */ + fun getAttestVersion(securityLevel: Int): Int { + // StrongBox security level requires an attestation version of at least 300. + if (securityLevel == SecurityLevel.STRONGBOX) { + return 300 + } + return DeviceAttestationService.CachedAttestationData?.attestVersion + ?: attestVersionMap[Build.VERSION.SDK_INT] + ?: 400 // Default to a recent version + } - val keymasterVersion: Int - get() = - DeviceAttestationService.CachedAttestationData?.keymasterVersion - ?: if (attestVersion >= 100) attestVersion - else 41 // Keymaster 4.1 for older versions + /** + * Retrieves the Keymaster/KeyMint version based on the attestation version. + * + * @param securityLevel The security level, used to determine the correct attestation version. + * @return The appropriate Keymaster or KeyMint version number. + */ + fun getKeymasterVersion(securityLevel: Int): Int { + val attestVersion = getAttestVersion(securityLevel) + return if (attestVersion >= 100) attestVersion else 41 // Keymaster 4.1 for older versions + } // --- APEX and Module Hash Properties ---