2019-10-17 18:57:00 +02:00
|
|
|
package com.topjohnwu.magisk.redesign.safetynet
|
|
|
|
|
2019-10-24 17:33:42 +02:00
|
|
|
import androidx.databinding.Bindable
|
|
|
|
import com.topjohnwu.magisk.BR
|
2019-10-23 21:17:53 +02:00
|
|
|
import com.topjohnwu.magisk.R
|
|
|
|
import com.topjohnwu.magisk.extensions.subscribeK
|
|
|
|
import com.topjohnwu.magisk.model.events.SafetyNetResult
|
|
|
|
import com.topjohnwu.magisk.model.events.UpdateSafetyNetEvent
|
2019-10-17 18:57:00 +02:00
|
|
|
import com.topjohnwu.magisk.redesign.compat.CompatViewModel
|
2020-01-12 09:07:30 +01:00
|
|
|
import com.topjohnwu.magisk.redesign.safetynet.SafetyNetState.*
|
2019-10-23 21:17:53 +02:00
|
|
|
import com.topjohnwu.magisk.utils.KObservableField
|
|
|
|
import com.topjohnwu.magisk.utils.RxBus
|
|
|
|
import com.topjohnwu.magisk.utils.SafetyNetHelper
|
2019-10-17 18:57:00 +02:00
|
|
|
|
2020-01-12 09:07:30 +01:00
|
|
|
enum class SafetyNetState {
|
|
|
|
LOADING, PASS, FAILED, IDLE
|
|
|
|
}
|
|
|
|
|
2019-10-23 21:17:53 +02:00
|
|
|
class SafetynetViewModel(
|
|
|
|
rxBus: RxBus
|
|
|
|
) : CompatViewModel() {
|
|
|
|
|
2019-10-24 17:33:42 +02:00
|
|
|
private var currentState = IDLE
|
|
|
|
set(value) {
|
|
|
|
field = value
|
|
|
|
notifyStateChanged()
|
|
|
|
}
|
2019-10-23 21:17:53 +02:00
|
|
|
val safetyNetTitle = KObservableField(R.string.empty)
|
2019-10-24 17:33:42 +02:00
|
|
|
val ctsState = KObservableField(false)
|
|
|
|
val basicIntegrityState = KObservableField(false)
|
|
|
|
|
|
|
|
val isChecking @Bindable get() = currentState == LOADING
|
|
|
|
val isFailed @Bindable get() = currentState == FAILED
|
|
|
|
val isSuccess @Bindable get() = currentState == PASS
|
2019-10-23 21:17:53 +02:00
|
|
|
|
|
|
|
init {
|
|
|
|
rxBus.register<SafetyNetResult>()
|
|
|
|
.subscribeK { resolveResponse(it.responseCode) }
|
|
|
|
.add()
|
2019-10-24 17:33:42 +02:00
|
|
|
|
2019-10-26 16:03:07 +02:00
|
|
|
if (safetyNetResult >= 0) {
|
|
|
|
resolveResponse(safetyNetResult)
|
|
|
|
} else {
|
|
|
|
attest()
|
|
|
|
}
|
2019-10-23 21:17:53 +02:00
|
|
|
}
|
|
|
|
|
2019-10-24 17:33:42 +02:00
|
|
|
override fun notifyStateChanged() {
|
|
|
|
super.notifyStateChanged()
|
|
|
|
notifyPropertyChanged(BR.loading)
|
|
|
|
notifyPropertyChanged(BR.failed)
|
|
|
|
notifyPropertyChanged(BR.success)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun attest() {
|
|
|
|
currentState = LOADING
|
|
|
|
UpdateSafetyNetEvent().publish()
|
|
|
|
}
|
|
|
|
|
|
|
|
fun reset() = attest()
|
2019-10-23 21:17:53 +02:00
|
|
|
|
|
|
|
private fun resolveResponse(response: Int) = when {
|
|
|
|
response and 0x0F == 0 -> {
|
|
|
|
val hasCtsPassed = response and SafetyNetHelper.CTS_PASS != 0
|
|
|
|
val hasBasicIntegrityPassed = response and SafetyNetHelper.BASIC_PASS != 0
|
2019-10-24 17:33:42 +02:00
|
|
|
val result = hasCtsPassed && hasBasicIntegrityPassed
|
2019-10-26 16:03:07 +02:00
|
|
|
safetyNetResult = response
|
2019-10-24 17:33:42 +02:00
|
|
|
ctsState.value = hasCtsPassed
|
|
|
|
basicIntegrityState.value = hasBasicIntegrityPassed
|
|
|
|
currentState = if (result) PASS else FAILED
|
|
|
|
safetyNetTitle.value =
|
|
|
|
if (result) R.string.safetynet_attest_success
|
|
|
|
else R.string.safetynet_attest_failure
|
2019-10-23 21:17:53 +02:00
|
|
|
}
|
|
|
|
response == -2 -> {
|
2019-10-24 17:33:42 +02:00
|
|
|
currentState = FAILED
|
|
|
|
ctsState.value = false
|
|
|
|
basicIntegrityState.value = false
|
|
|
|
back()
|
2019-10-23 21:17:53 +02:00
|
|
|
}
|
|
|
|
else -> {
|
2019-10-24 17:33:42 +02:00
|
|
|
currentState = FAILED
|
|
|
|
ctsState.value = false
|
|
|
|
basicIntegrityState.value = false
|
2019-10-23 21:17:53 +02:00
|
|
|
safetyNetTitle.value = when (response) {
|
|
|
|
SafetyNetHelper.RESPONSE_ERR -> R.string.safetyNet_res_invalid
|
|
|
|
else -> R.string.safetyNet_api_error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-26 16:03:07 +02:00
|
|
|
companion object {
|
|
|
|
private var safetyNetResult = -1
|
|
|
|
}
|
|
|
|
|
2020-01-12 09:07:30 +01:00
|
|
|
}
|