Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit cba44326 authored by Marvin W.'s avatar Marvin W. 🐿️
Browse files

Fido: Allow CTAP HID devices with subclass/protocol != 0

[1] suggests that subclass and protocol must be 0 and this is indeed the case
for some, but not all security keys.

[1] https://fidoalliance.org/specs/fido-v2.0-ps-20190130/fido-client-to-authenticator-protocol-v2.0-ps-20190130.html#usb-descriptors
parent b34baa01
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -49,8 +49,6 @@ class UsbTransportHandler(private val context: Context, callback: TransportHandl
    suspend fun getCtapHidInterface(device: UsbDevice): UsbInterface? {
        for (iface in device.interfaces) {
            if (iface.interfaceClass != USB_CLASS_HID) continue
            if (iface.interfaceSubclass != 0) continue
            if (iface.interfaceProtocol != 0) continue
            if (iface.endpointCount != 2) continue
            if (!iface.endpoints.all { it.type == USB_ENDPOINT_XFER_INT }) continue
            if (!iface.endpoints.any { it.direction == USB_DIR_IN }) continue
@@ -65,11 +63,14 @@ class UsbTransportHandler(private val context: Context, callback: TransportHandl
                    val read = connection.controlTransfer(0x81, 0x06, 0x2200, iface.id, buf, buf.size, 5000)
                    read >= 5 && buf.slice(0 until 5) eq CTAPHID_SIGNATURE
                } else {
                    Log.d(TAG, "Failed claiming interface")
                    false
                }
            } == true
            if (match) {
                return iface
            } else {
                Log.d(TAG, "${device.productName} signature does not match")
            }
        }
        return null
@@ -217,6 +218,7 @@ class UsbTransportHandler(private val context: Context, callback: TransportHandl
        device: UsbDevice,
        iface: UsbInterface
    ): AuthenticatorResponse {
        Log.d(TAG, "Trying to use ${device.productName} for ${options.type}")
        invokeStatusChanged(
            TransportHandlerCallback.STATUS_WAITING_FOR_USER,
            Bundle().apply { putParcelable(UsbManager.EXTRA_DEVICE, device) })
+8 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbDeviceConnection
import android.hardware.usb.UsbInterface
import android.hardware.usb.UsbRequest
import android.util.Base64
import android.util.Log
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
@@ -16,6 +17,7 @@ import org.microg.gms.fido.core.protocol.msgs.Ctap1Request
import org.microg.gms.fido.core.protocol.msgs.Ctap1Response
import org.microg.gms.fido.core.transport.usb.endpoints
import org.microg.gms.fido.core.transport.usb.usbManager
import org.microg.gms.utils.toBase64
import java.nio.ByteBuffer
import kotlin.experimental.and

@@ -40,8 +42,10 @@ class CtapHidConnection(
        get() = capabilities and CtapHidInitResponse.CAPABILITY_WINK > 0

    suspend fun open(): Boolean {
        Log.d(TAG, "Opening connection")
        connection = context.usbManager?.openDevice(device)
        if (connection?.claimInterface(iface, true) != true) {
            Log.d(TAG, "Failed claiming interface")
            close()
            return false
        }
@@ -49,6 +53,7 @@ class CtapHidConnection(
        sendRequest(initRequest)
        val initResponse = readResponse()
        if (initResponse !is CtapHidInitResponse || !initResponse.nonce.contentEquals(initRequest.nonce)) {
            Log.d(TAG, "Failed init procedure")
            close()
            return false
        }
@@ -73,6 +78,7 @@ class CtapHidConnection(
        for (packet in packets) {
            if (outRequest.queue(ByteBuffer.wrap(packet.bytes), packet.bytes.size)) {
                withContext(Dispatchers.IO) { connection.requestWait() }
                Log.d(TAG, "Sent packet ${packet.bytes.toBase64(Base64.NO_WRAP)}")
            } else {
                throw RuntimeException("Failed queuing packet")
            }
@@ -89,7 +95,9 @@ class CtapHidConnection(
        while (true) {
            buffer.clear()
            if (inRequest.queue(buffer, inEndpoint.maxPacketSize)) {
                Log.d(TAG, "Reading ${inEndpoint.maxPacketSize} bytes from usb")
                withContext(Dispatchers.IO) { connection.requestWait() }
                Log.d(TAG, "Received packet ${buffer.array().toBase64(Base64.NO_WRAP)}")
                if (initializationPacket == null) {
                    initializationPacket = CtapHidInitializationPacket.decode(buffer.array())
                    packets.add(initializationPacket)