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.
This commit is contained in:
@@ -18,6 +18,7 @@ object InterceptorUtils {
|
|||||||
val parcel = Parcel.obtain().apply {
|
val parcel = Parcel.obtain().apply {
|
||||||
writeInt(EX_SERVICE_SPECIFIC)
|
writeInt(EX_SERVICE_SPECIFIC)
|
||||||
writeString(null)
|
writeString(null)
|
||||||
|
writeInt(0) // empty remote stack trace header (AOSP Status.cpp:196)
|
||||||
writeInt(errorCode)
|
writeInt(errorCode)
|
||||||
}
|
}
|
||||||
return BinderInterceptor.TransactionResult.OverrideReply(parcel)
|
return BinderInterceptor.TransactionResult.OverrideReply(parcel)
|
||||||
@@ -119,6 +120,8 @@ object InterceptorUtils {
|
|||||||
|
|
||||||
/** Checks if a reply parcel contains an exception without consuming it. */
|
/** Checks if a reply parcel contains an exception without consuming it. */
|
||||||
fun hasException(reply: Parcel): Boolean {
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -129,7 +129,7 @@ object ListEntriesHandler {
|
|||||||
startPastAlias: String?,
|
startPastAlias: String?,
|
||||||
): List<KeyDescriptor> {
|
): List<KeyDescriptor> {
|
||||||
return KeyMintSecurityLevelInterceptor.generatedKeys.keys
|
return KeyMintSecurityLevelInterceptor.generatedKeys.keys
|
||||||
.filter { it.uid == uid && (startPastAlias == null || it.alias < startPastAlias) }
|
.filter { it.uid == uid && (startPastAlias == null || it.alias > startPastAlias) }
|
||||||
.map { keyId ->
|
.map { keyId ->
|
||||||
KeyDescriptor().apply {
|
KeyDescriptor().apply {
|
||||||
this.domain = Domain.APP
|
this.domain = Domain.APP
|
||||||
|
|||||||
+16
-1
@@ -3,6 +3,7 @@ package org.matrix.TEESimulator.interception.keystore.shim
|
|||||||
import android.hardware.security.keymint.Algorithm
|
import android.hardware.security.keymint.Algorithm
|
||||||
import android.hardware.security.keymint.KeyParameter
|
import android.hardware.security.keymint.KeyParameter
|
||||||
import android.hardware.security.keymint.KeyParameterValue
|
import android.hardware.security.keymint.KeyParameterValue
|
||||||
|
import android.hardware.security.keymint.KeyOrigin
|
||||||
import android.hardware.security.keymint.Tag
|
import android.hardware.security.keymint.Tag
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
@@ -425,12 +426,20 @@ class KeyMintSecurityLevelInterceptor(
|
|||||||
params: KeyMintAttestation,
|
params: KeyMintAttestation,
|
||||||
descriptor: KeyDescriptor,
|
descriptor: KeyDescriptor,
|
||||||
): KeyEntryResponse {
|
): KeyEntryResponse {
|
||||||
|
val normalizedKeyDescriptor =
|
||||||
|
KeyDescriptor().apply {
|
||||||
|
domain = Domain.KEY_ID
|
||||||
|
nspace = descriptor.nspace
|
||||||
|
alias = null
|
||||||
|
blob = null
|
||||||
|
}
|
||||||
val metadata =
|
val metadata =
|
||||||
KeyMetadata().apply {
|
KeyMetadata().apply {
|
||||||
keySecurityLevel = securityLevel
|
keySecurityLevel = securityLevel
|
||||||
key = descriptor
|
key = normalizedKeyDescriptor
|
||||||
CertificateHelper.updateCertificateChain(this, chain.toTypedArray()).getOrThrow()
|
CertificateHelper.updateCertificateChain(this, chain.toTypedArray()).getOrThrow()
|
||||||
authorizations = params.toAuthorizations(securityLevel)
|
authorizations = params.toAuthorizations(securityLevel)
|
||||||
|
modificationTimeMs = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
return KeyEntryResponse().apply {
|
return KeyEntryResponse().apply {
|
||||||
this.metadata = metadata
|
this.metadata = metadata
|
||||||
@@ -665,6 +674,12 @@ private fun KeyMintAttestation.toAuthorizations(securityLevel: Int): Array<Autho
|
|||||||
authList.add(createAuth(Tag.ALGORITHM, KeyParameterValue.algorithm(this.algorithm)))
|
authList.add(createAuth(Tag.ALGORITHM, KeyParameterValue.algorithm(this.algorithm)))
|
||||||
authList.add(createAuth(Tag.KEY_SIZE, KeyParameterValue.integer(this.keySize)))
|
authList.add(createAuth(Tag.KEY_SIZE, KeyParameterValue.integer(this.keySize)))
|
||||||
authList.add(createAuth(Tag.EC_CURVE, KeyParameterValue.ecCurve(this.ecCurve)))
|
authList.add(createAuth(Tag.EC_CURVE, KeyParameterValue.ecCurve(this.ecCurve)))
|
||||||
|
authList.add(
|
||||||
|
createAuth(
|
||||||
|
Tag.ORIGIN,
|
||||||
|
KeyParameterValue.origin(this.origin ?: KeyOrigin.GENERATED),
|
||||||
|
)
|
||||||
|
)
|
||||||
authList.add(createAuth(Tag.NO_AUTH_REQUIRED, KeyParameterValue.boolValue(true)))
|
authList.add(createAuth(Tag.NO_AUTH_REQUIRED, KeyParameterValue.boolValue(true)))
|
||||||
|
|
||||||
return authList.toTypedArray()
|
return authList.toTypedArray()
|
||||||
|
|||||||
Reference in New Issue
Block a user