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 df34b85..a4d0181 100644 --- a/app/src/main/java/org/matrix/TEESimulator/attestation/AttestationBuilder.kt +++ b/app/src/main/java/org/matrix/TEESimulator/attestation/AttestationBuilder.kt @@ -182,11 +182,36 @@ object AttestationBuilder { AttestationConstants.TAG_DIGEST, DERSet(params.digest.map { ASN1Integer(it.toLong()) }.toTypedArray()), ), + ) + + if (params.ecCurve != null) { + list.add( DERTaggedObject( true, AttestationConstants.TAG_EC_CURVE, ASN1Integer(params.ecCurve.toLong()), - ), + ) + ) + } + + params.padding.forEach { + list.add( + DERTaggedObject(true, AttestationConstants.TAG_PADDING, ASN1Integer(it.toLong())) + ) + } + + if (params.rsaPublicExponent != null) { + list.add( + DERTaggedObject( + true, + AttestationConstants.TAG_RSA_PUBLIC_EXPONENT, + ASN1Integer(params.rsaPublicExponent.toLong()), + ) + ) + } + + list.addAll( + listOf( DERTaggedObject(true, AttestationConstants.TAG_NO_AUTH_REQUIRED, DERNull.INSTANCE), DERTaggedObject( true, @@ -199,6 +224,7 @@ object AttestationBuilder { buildRootOfTrust(null), ), ) + ) // Use the same logic as getSimulatedHardwareProperties to conditionally add patch levels. val simulatedProperties = getSimulatedHardwareProperties(uid) diff --git a/app/src/main/java/org/matrix/TEESimulator/attestation/KeyMintAttestation.kt b/app/src/main/java/org/matrix/TEESimulator/attestation/KeyMintAttestation.kt index 04818d7..6c3c549 100644 --- a/app/src/main/java/org/matrix/TEESimulator/attestation/KeyMintAttestation.kt +++ b/app/src/main/java/org/matrix/TEESimulator/attestation/KeyMintAttestation.kt @@ -19,7 +19,7 @@ import org.matrix.TEESimulator.logging.KeyMintParameterLogger data class KeyMintAttestation( val keySize: Int, val algorithm: Int, - val ecCurve: Int, + val ecCurve: Int?, val ecCurveName: String, val origin: Int?, val blockMode: List, @@ -53,7 +53,7 @@ data class KeyMintAttestation( algorithm = params.findAlgorithm(Tag.ALGORITHM) ?: 0, // AOSP: [key_param(tag = EC_CURVE, field = EcCurve)] - ecCurve = params.findEcCurve(Tag.EC_CURVE) ?: 0, + ecCurve = params.findEcCurve(Tag.EC_CURVE), ecCurveName = params.deriveEcCurveName(), // AOSP: [key_param(tag = ORIGIN, field = Origin)] diff --git a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/Keystore2Interceptor.kt b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/Keystore2Interceptor.kt index 09056c2..a43d775 100644 --- a/app/src/main/java/org/matrix/TEESimulator/interception/keystore/Keystore2Interceptor.kt +++ b/app/src/main/java/org/matrix/TEESimulator/interception/keystore/Keystore2Interceptor.kt @@ -305,7 +305,7 @@ object Keystore2Interceptor : AbstractKeystoreInterceptor() { certChain = keyData.second, algorithm = parsedParameters.algorithm, keySize = parsedParameters.keySize, - ecCurve = parsedParameters.ecCurve, + ecCurve = parsedParameters.ecCurve ?: 0, purposes = parsedParameters.purpose, digests = parsedParameters.digest, isAttestationKey = true, @@ -337,6 +337,7 @@ object Keystore2Interceptor : AbstractKeystoreInterceptor() { ) finalChain = AttestationPatcher.patchCertificateChain(originalChain, callingUid) + KeyMintSecurityLevelInterceptor.patchedChains[keyId] = finalChain } CertificateHelper.updateCertificateChain(response.metadata, finalChain) 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 32cd9a9..b1b491a 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 @@ -333,7 +333,7 @@ class KeyMintSecurityLevelInterceptor( } ?: throw Exception("Both native and BouncyCastle cert gen failed.") cleanupKeyData(keyId) - val response = buildKeyEntryResponse(keyData.second, parsedParams, keyDescriptor) + val response = buildKeyEntryResponse(callingUid, keyData.second, parsedParams, keyDescriptor) generatedKeys[keyId] = GeneratedKeyInfo(keyData.first, keyDescriptor.nspace, response) if (isAttestKeyRequest) attestationKeys.add(keyId) @@ -345,7 +345,7 @@ class KeyMintSecurityLevelInterceptor( certChain = keyData.second.toList(), algorithm = parsedParams.algorithm, keySize = parsedParams.keySize, - ecCurve = parsedParams.ecCurve, + ecCurve = parsedParams.ecCurve ?: 0, purposes = parsedParams.purpose, digests = parsedParams.digest, isAttestationKey = isAttestKeyRequest, @@ -383,7 +383,7 @@ class KeyMintSecurityLevelInterceptor( val config = CertGenConfig( algorithm = params.algorithm, keySize = params.keySize, - ecCurve = params.ecCurve, + ecCurve = params.ecCurve ?: 0, rsaPublicExponent = params.rsaPublicExponent?.toLong() ?: 65537L, attestationChallenge = params.attestationChallenge, purposes = params.purpose.toIntArray(), @@ -427,6 +427,7 @@ class KeyMintSecurityLevelInterceptor( } private fun buildKeyEntryResponse( + callingUid: Int, chain: List, params: KeyMintAttestation, descriptor: KeyDescriptor, @@ -443,7 +444,7 @@ class KeyMintSecurityLevelInterceptor( keySecurityLevel = securityLevel key = normalizedKeyDescriptor CertificateHelper.updateCertificateChain(this, chain.toTypedArray()).getOrThrow() - authorizations = params.toAuthorizations(securityLevel) + authorizations = params.toAuthorizations(callingUid, securityLevel) modificationTimeMs = System.currentTimeMillis() } return KeyEntryResponse().apply { @@ -521,7 +522,7 @@ class KeyMintSecurityLevelInterceptor( secondImei = null, ) - val response = buildKeyEntryResponse(certChain, attestation, descriptor) + val response = buildKeyEntryResponse(record.uid, certChain, attestation, descriptor) generatedKeys[keyId] = GeneratedKeyInfo(keyPair, record.nspace, response) if (record.isAttestationKey) attestationKeys.add(keyId) @@ -605,8 +606,7 @@ class KeyMintSecurityLevelInterceptor( } val generatedKeys = ConcurrentHashMap() - // Caches patched chains to prevent re-generation and signature inconsistencies - private val patchedChains = ConcurrentHashMap>() + val patchedChains = ConcurrentHashMap>() val attestationKeys: MutableSet = ConcurrentHashMap.newKeySet() private val interceptedOperations = ConcurrentHashMap() @@ -666,7 +666,10 @@ class KeyMintSecurityLevelInterceptor( } } -private fun KeyMintAttestation.toAuthorizations(securityLevel: Int): Array { +private fun KeyMintAttestation.toAuthorizations( + callingUid: Int, + securityLevel: Int, +): Array { val authList = mutableListOf() fun createAuth(tag: Int, value: KeyParameterValue): Authorization { @@ -681,19 +684,35 @@ private fun KeyMintAttestation.toAuthorizations(securityLevel: Int): Array