fix(intercept): synthesize canonical SSE messages

writeString(null) on service-specific exception replies left the
message word as 0xFFFFFFFF, which diverges from AOSP keystore2's
anyhow-formatted "Error::Rc(NAME)" / "Error::Km(NAME)" strings.
Map known ResponseCode/KeyMint codes to their canonical names so
the wire shape matches a stock TEE reply.
This commit is contained in:
Enginex0
2026-05-19 17:00:04 +01:00
parent be04f16a50
commit 80f65b02ac
@@ -19,10 +19,27 @@ object InterceptorUtils {
private const val EX_SERVICE_SPECIFIC = -8 private const val EX_SERVICE_SPECIFIC = -8
private fun synthesizeSseMessage(errorCode: Int): String =
when (errorCode) {
2 -> "Error::Rc(SYSTEM_ERROR)"
4 -> "Error::Rc(PERMISSION_DENIED)"
6 -> "Error::Rc(VALUE_CORRUPTED)"
7 -> "Error::Rc(KEY_NOT_FOUND)"
10 -> "Error::Rc(BACKEND_BUSY)"
-3 -> "Error::Km(UNSUPPORTED_KEY_SIZE)"
-6 -> "Error::Km(INCOMPATIBLE_PURPOSE)"
-7 -> "Error::Km(INCOMPATIBLE_ALGORITHM)"
-29 -> "Error::Km(TOO_MANY_OPERATIONS)"
-49 -> "Error::Km(UNSUPPORTED_TAG)"
-75 -> "Error::Km(INVALID_INPUT_LENGTH)"
-76 -> "Error::Km(INVALID_TAG)"
else -> if (errorCode > 0) "Error::Rc($errorCode)" else "Error::Km($errorCode)"
}
fun createErrorReply(errorCode: Int): BinderInterceptor.TransactionResult.OverrideReply { fun createErrorReply(errorCode: Int): BinderInterceptor.TransactionResult.OverrideReply {
val parcel = Parcel.obtain().apply { val parcel = Parcel.obtain().apply {
writeInt(EX_SERVICE_SPECIFIC) writeInt(EX_SERVICE_SPECIFIC)
writeString(null) writeString(synthesizeSseMessage(errorCode))
writeInt(0) // empty remote stack trace header (AOSP Status.cpp:196) writeInt(0) // empty remote stack trace header (AOSP Status.cpp:196)
writeInt(errorCode) writeInt(errorCode)
} }
@@ -132,12 +149,25 @@ object InterceptorUtils {
fun createServiceSpecificErrorReply( fun createServiceSpecificErrorReply(
errorCode: Int errorCode: Int
): BinderInterceptor.TransactionResult.OverrideReply { ): BinderInterceptor.TransactionResult.OverrideReply = createErrorReply(errorCode)
val parcel =
Parcel.obtain().apply { fun normalizeServiceSpecificReply(reply: Parcel): Parcel? {
writeException(android.os.ServiceSpecificException(errorCode)) reply.setDataPosition(0)
if (reply.readInt() != EX_SERVICE_SPECIFIC) {
reply.setDataPosition(0)
return null
}
// Advance position past message and stack header to reach errorCode.
reply.readString()
reply.readInt()
val errorCode = reply.readInt()
reply.setDataPosition(0)
return Parcel.obtain().apply {
writeInt(EX_SERVICE_SPECIFIC)
writeString(synthesizeSseMessage(errorCode))
writeInt(0)
writeInt(errorCode)
} }
return BinderInterceptor.TransactionResult.OverrideReply(parcel)
} }
fun patchAuthorizations( fun patchAuthorizations(