probe hw key applications if getDeviceInfo fails

This commit is contained in:
Adam Velebil 2024-04-19 16:01:35 +02:00
parent e203683e52
commit ca5f82f665
No known key found for this signature in database
GPG Key ID: C9B1E4A3CBBD2E10
4 changed files with 65 additions and 19 deletions

View File

@ -40,7 +40,6 @@ import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import com.google.android.material.color.DynamicColors
import com.yubico.authenticator.device.DeviceManager
import com.yubico.authenticator.device.UnknownDevice
import com.yubico.authenticator.fido.FidoManager
import com.yubico.authenticator.fido.FidoViewModel
import com.yubico.authenticator.logging.FlutterLog
@ -54,7 +53,6 @@ import com.yubico.yubikit.android.transport.nfc.NfcConfiguration
import com.yubico.yubikit.android.transport.nfc.NfcNotAvailable
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
import com.yubico.yubikit.android.transport.usb.UsbConfiguration
import com.yubico.yubikit.core.Transport
import com.yubico.yubikit.core.YubiKeyDevice
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
@ -273,17 +271,7 @@ class MainActivity : FlutterFragmentActivity() {
private fun processYubiKey(device: YubiKeyDevice) {
lifecycleScope.launch {
val deviceInfo = try {
getDeviceInfo(device)
} catch (e: IllegalArgumentException) {
logger.debug("Device was not recognized")
UnknownDevice.copy(isNfc = device.transport == Transport.NFC)
} catch (e: Exception) {
logger.error("Failure getting device info", e)
null
}
val deviceInfo = getDeviceInfo(device)
deviceManager.setDeviceInfo(deviceInfo)
if (deviceInfo == null) {

View File

@ -1,5 +1,7 @@
package com.yubico.authenticator.device
import com.yubico.yubikit.core.Transport
import com.yubico.yubikit.management.Capability
import com.yubico.yubikit.management.FormFactor
val UnknownDevice = Info(
@ -20,4 +22,29 @@ val UnknownDevice = Info(
usbPid = null,
pinComplexity = false,
supportedCapabilities = Capabilities()
)
)
fun unknownDeviceWithCapability(transport: Transport, bit: Int = 0) : Info {
val isNfc = transport == Transport.NFC
val capabilities = Capabilities(
nfc = if (isNfc) bit else null,
usb = if (!isNfc) bit else null
)
return UnknownDevice.copy(
isNfc = isNfc,
config = UnknownDevice.config.copy(enabledCapabilities = capabilities),
supportedCapabilities = capabilities
)
}
fun unknownOathDeviceInfo(transport: Transport) : Info {
return unknownDeviceWithCapability(transport, Capability.OATH.bit).copy(
name = "OATH device"
)
}
fun unknownFido2DeviceInfo(transport: Transport) : Info {
return unknownDeviceWithCapability(transport, Capability.FIDO2.bit).copy(
name = "FIDO2 device"
)
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2022-2023 Yubico.
* Copyright (C) 2022-2024 Yubico.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,18 +18,24 @@ package com.yubico.authenticator.yubikit
import com.yubico.authenticator.device.Info
import com.yubico.authenticator.compatUtil
import com.yubico.authenticator.device.unknownDeviceWithCapability
import com.yubico.authenticator.device.unknownFido2DeviceInfo
import com.yubico.authenticator.device.unknownOathDeviceInfo
import com.yubico.yubikit.android.transport.nfc.NfcYubiKeyDevice
import com.yubico.yubikit.android.transport.usb.UsbYubiKeyDevice
import com.yubico.yubikit.core.YubiKeyDevice
import com.yubico.yubikit.core.application.ApplicationNotAvailableException
import com.yubico.yubikit.core.fido.FidoConnection
import com.yubico.yubikit.core.otp.OtpConnection
import com.yubico.yubikit.core.smartcard.SmartCardConnection
import com.yubico.yubikit.fido.ctap.Ctap2Session
import com.yubico.yubikit.management.DeviceInfo
import com.yubico.yubikit.oath.OathSession
import com.yubico.yubikit.support.DeviceUtil
import org.slf4j.LoggerFactory
suspend fun getDeviceInfo(device: YubiKeyDevice): Info {
suspend fun getDeviceInfo(device: YubiKeyDevice): Info? {
val pid = (device as? UsbYubiKeyDevice)?.pid
val logger = LoggerFactory.getLogger("getDeviceInfo")
@ -45,8 +51,31 @@ suspend fun getDeviceInfo(device: YubiKeyDevice): Info {
logger.debug("FIDO connection not available: {}", t.message)
return SkyHelper(compatUtil).getDeviceInfo(device)
}.getOrElse {
logger.debug("Failed to recognize device: {}", it.message)
throw it
// this is not a YubiKey
logger.debug("Probing unknown device")
try {
device.openConnection(SmartCardConnection::class.java).use { smartCardConnection ->
try {
// if OATH session is available use it
OathSession(smartCardConnection)
logger.debug("Device supports OATH")
return unknownOathDeviceInfo(device.transport)
} catch (applicationNotAvailable: ApplicationNotAvailableException) {
try {
// probe for CTAP2 availability
Ctap2Session(smartCardConnection)
logger.debug("Device supports FIDO2")
return unknownFido2DeviceInfo(device.transport)
} catch (applicationNotAvailable: ApplicationNotAvailableException) {
logger.debug("Device not recognized")
return unknownDeviceWithCapability(device.transport)
}
}
}
} catch (e: Exception) {
// no smart card connectivity
return null
}
}
val name = DeviceUtil.getName(deviceInfo, pid?.type)

View File

@ -141,7 +141,9 @@ class _DeviceContent extends ConsumerWidget {
final name = deviceData.name;
final serial = deviceData.info.serial;
final version = deviceData.info.version;
final version = deviceData.info.version == const Version(0, 0, 0)
? 'unknown'
: deviceData.info.version;
final label = initialCustomization?.name;
String displayName = label != null ? '$label ($name)' : name;