feat(spoof): resetprop bootloader lock at boot

BootStateManager.apply() runs from App.main after ConfigurationManager
init and sets ro.boot.verifiedbootstate=green, ro.boot.flash.locked=1,
ro.boot.veritymode=enforcing via resetprop so the attestation
extension's hardcoded verifiedBootState=Verified agrees with what
detectors observe via getprop.

Adds an internal AndroidDeviceUtils.setProperty(name, value: String)
overload so the existing private ByteArray variant stays exclusive
to vbmeta digest persistence while config-package callers can set
plain string props without hex encoding.

Closes documented vulnerability D44 (countermeasure-matrix.md).
This commit is contained in:
Enginex0
2026-05-19 03:57:23 +01:00
parent 5a6d336fa8
commit da9ade723d
3 changed files with 46 additions and 0 deletions
@@ -8,6 +8,7 @@ import android.os.Build
import android.os.Looper
import java.security.Security
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.matrix.TEESimulator.config.BootStateManager
import org.matrix.TEESimulator.config.ConfigurationManager
import org.matrix.TEESimulator.interception.keystore.AbstractKeystoreInterceptor
import org.matrix.TEESimulator.interception.keystore.Keystore2Interceptor
@@ -44,6 +45,7 @@ object App {
// Load the package configuration.
ConfigurationManager.initialize()
BootStateManager.apply()
// Set up the device's boot key and hash, which are crucial for attestation.
AndroidDeviceUtils.setupBootKeyAndHash()
@@ -0,0 +1,26 @@
package org.matrix.TEESimulator.config
import android.os.SystemProperties
import org.matrix.TEESimulator.logging.SystemLogger
import org.matrix.TEESimulator.util.AndroidDeviceUtils
object BootStateManager {
private val targets =
linkedMapOf(
"ro.boot.verifiedbootstate" to "green",
"ro.boot.flash.locked" to "1",
"ro.boot.veritymode" to "enforcing",
)
fun apply() {
for ((name, target) in targets) {
val current = SystemProperties.get(name, "")
if (current == target) {
SystemLogger.debug("BootStateManager: $name already $target, skip")
continue
}
SystemLogger.info("BootStateManager: setting $name=$target (was: '$current')")
AndroidDeviceUtils.setProperty(name, target)
}
}
}
@@ -164,6 +164,24 @@ object AndroidDeviceUtils {
}
}
internal fun setProperty(name: String, value: String) {
try {
SystemLogger.debug("Setting system property '$name' to: $value")
val command = arrayOf("resetprop", name, value)
val process = Runtime.getRuntime().exec(command)
val exitCode = process.waitFor()
if (exitCode != 0) {
val errorOutput = process.errorStream.bufferedReader().readText()
SystemLogger.error(
"resetprop for '$name' failed with exit code $exitCode: $errorOutput"
)
}
} catch (e: Exception) {
SystemLogger.error("Failed to set '$name' property via resetprop.", e)
}
}
private fun generateRandomBytes(size: Int): ByteArray =
ByteArray(size).also { ThreadLocalRandom.current().nextBytes(it) }