Unable to read/write FIDO2 charactersitics

604 Views Asked by At

I am building an Android authenticator for FIDO2. I got stuck with read/write characteristics. I am working on Mac - Chrome 75. Chrome can detect my Android BLE authenticator. After detecting my BLE Authenticator, onCharacteristicReadRequest() is called from authenticator side. Inside the onCharacteristicReadRequest() I am using the code written below but there is no response from client after that.

I have tried U2F with version 0b01000000. It's working fine. When I moved FIDO2 version 0b100000, I am facing this issue. I am advertising fido service and device info service from authenticator. Both services has been added with Thread.sleep(1000) interval. I couldn't add both services sequentially. When I add both services sequentially, I am getting ArrayIndexOutofBoundException.

I don't know if both issues are interlinked. Please correct me if I am doing anything wrong.

{
...
}else if (characteristic.getUuid().equals(FidoUUIDConstants.FIDO_SERVICE_REVISION_BITFIELD)) {
    status = BluetoothGatt.GATT_SUCCESS;
    ByteBuffer bb = ByteBuffer.allocate(1);
    bb.order(ByteOrder.BIG_ENDIAN);
    bb.put((byte) (1 << 5));
    bytes = bb.array();
}
mGattServer.sendResponse(device, requestId, status, 0, bytes);

Client should read/write characteristics after fidoServiceBitFieldversion is expected.

3

There are 3 best solutions below

0
Huong On BEST ANSWER

I agreed with @Bao's concern. According to CTAP specification, you should define descriptor corresponding to each characteristic with READ/WRITE permission. Note that the UUIDs for each descriptor are needed a valid UUID 128-bit format. All descriptors have both permissions READ and WRITE. For example:

UUID CONTROL_POINT_DESCRIPTOR_UUID = UUID.fromString("00002901-0000-1000-8000-00805f9b34fb");
BluetoothGattDescriptor controlPointDescriptor = new BluetoothGattDescriptor(
    CONTROL_POINT_DESCRIPTOR_UUID,
    BluetoothGattDescriptor.PERMISSION_READ | BluetoothGattDescriptor.PERMISSION_WRITE
);
1
Huong On

I couldn't add both services sequentially

I think you could add the device info service like the following:

gattServer = bleManager.openGattServer(this, new BluetoothGattServerCallback() {
    @Override
    public void onServiceAdded(int status, BluetoothGattService service) {
        if (service.getUuid().equals(FidoUUIDConstants.FIDO2_GATT_SERVICE)) {
            gattServer.addService(deviceInfoService);
        }
    }
});
gattServer.addService(fido2GattService)

For the characteristic fidoServiceRevisionBitfield, I just simply followed this statement a device that only supports FIDO2 Rev 1 will only have a fidoServiceRevisionBitfield characteristic of length 1 with value 0x20. at index 8.3.5.1. FIDO Service of CTAP document. Hence, my implementation was:

if(characteristic.getUuid().equals(FIDO2GattService.SERVICE_REVISION_BITFIELD)) {
    status = BluetoothGatt.GATT_SUCCESS;
    bytes = new byte[] {0x20}
}
gattServer.sendResponse(device, requestId, status, 0, bytes);
1
Bao HQ On

You should override all the methods of BluetoothGattServerCallback

I think you are missing onDescriptorReadRequest, onDescriptorWriteRequest implements.

@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
    if (descriptor.getCharacteristic().getUuid().equals(FIDO2GattService.CONTROL_POINT_UUID) &&
            descriptor.getUuid().equals(FIDO2GattService.CONTROL_POINT_DESCRIPTOR_UUID)) {
        gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, new byte[] {0x31, 0x2e, 0x32});
    } else {
        gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, new byte[] {0x00, 0x00});
    }
}
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
    gattServer.sendResponse(device, requestId, BluetoothGatt.GATT_SUCCESS, offset, value);
}