Wrap getPinRetries in Result to propagate errors

This commit is contained in:
mimi89999
2025-12-20 21:25:21 +01:00
parent d9107d7a6a
commit d4993a3633
3 changed files with 18 additions and 13 deletions
@@ -456,12 +456,12 @@ class CredentialProviderActivity : AppCompatActivity() {
}
// UV required/preferred and device has PIN - need to get PIN
userVerification != UserVerification.DISCOURAGED && deviceHasPin -> {
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() } ?: 8
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }.getOrDefault(8)
showPinDialog(retries, json)
}
// UV discouraged but device has alwaysUv - need PIN anyway
userVerification == UserVerification.DISCOURAGED && alwaysUv && deviceHasPin -> {
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() } ?: 8
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }.getOrDefault(8)
showPinDialog(retries, json)
}
// UV discouraged or preferred with no PIN - try without
@@ -487,7 +487,7 @@ class CredentialProviderActivity : AppCompatActivity() {
e.error == CTAP.Error.PIN_AUTH_INVALID) {
Log.d(TAG, "Authenticator requires PIN despite UV=discouraged")
val protocol = pinProtocol ?: throw Exception("No PIN protocol")
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() } ?: 8
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }.getOrDefault(8)
showPinDialog(retries, json)
} else {
throw e
@@ -535,7 +535,7 @@ class CredentialProviderActivity : AppCompatActivity() {
protocol.getPinToken(pin, permissions, rpId)
}
if (!authenticated) {
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() } ?: 0
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }.getOrThrow()
if (retries > 0) {
runOnUiThread {
showProgress(false)
@@ -427,9 +427,8 @@ class MainActivity : AppCompatActivity() {
}
val protocol = pinProtocol ?: throw Exception("PIN protocol not initialized")
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }
if (retries == null) {
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }.getOrElse { e ->
if (e is java.io.IOException) throw e
resultText.text = getString(R.string.error_could_not_get_pin_status)
pendingAction = null
return@launch
@@ -626,7 +625,7 @@ class MainActivity : AppCompatActivity() {
resultText.text = getString(R.string.checking_pin_status)
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }
val retries = withContext(Dispatchers.IO) { protocol.getPinRetries() }.getOrNull()
val dialogView = layoutInflater.inflate(R.layout.dialog_pin, null)
val currentPinEdit = dialogView.findViewById<EditText>(R.id.currentPin)
@@ -125,18 +125,24 @@ class PinProtocol(private val transport: FidoTransport) {
}
}
suspend fun getPinRetries(): Int? {
try {
suspend fun getPinRetries(): Result<Int> {
return try {
val response = transport.sendCtapCommand(CTAP.buildGetPinRetriesCommand())
if (!CTAP.isSuccess(response)) {
return null
return Result.failure(CTAP.Exception(
CTAP.getResponseError(response) ?: CTAP.Error.OTHER
))
}
val data = response.drop(1).toByteArray()
val parsed = CborMap.decode(data)
return parsed?.int(3)
?: return Result.failure(Exception("Failed to parse response"))
val retries = parsed.int(3)
?: return Result.failure(Exception("Missing retries field"))
Result.success(retries)
} catch (e: Exception) {
return null
Result.failure(e)
}
}