blob: 2307e38ca842eeac1286f01142edd54c213c623b [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_U2F_U2F_HID_DEVICE_H_
#define DEVICE_U2F_U2F_HID_DEVICE_H_
#include <memory>
#include <queue>
#include <string>
#include <utility>
#include <vector>
#include "base/cancelable_callback.h"
#include "device/u2f/u2f_device.h"
#include "services/device/public/interfaces/hid.mojom.h"
namespace device {
class U2fMessage;
class U2fHidDevice : public U2fDevice {
public:
U2fHidDevice(device::mojom::HidDeviceInfoPtr device_info,
device::mojom::HidManager* hid_manager);
~U2fHidDevice() final;
// Send a U2f command to this device
void DeviceTransact(std::unique_ptr<U2fApduCommand> command,
DeviceCallback callback) final;
// Send a wink command if supported
void TryWink(WinkCallback callback) final;
// Use a string identifier to compare to other devices
std::string GetId() const final;
// Get a string identifier for a given device info
static std::string GetIdForDevice(
const device::mojom::HidDeviceInfo& device_info);
// Command line flag to enable tests on actual U2f HID hardware
static bool IsTestEnabled();
private:
FRIEND_TEST_ALL_PREFIXES(U2fHidDeviceTest, TestConnectionFailure);
FRIEND_TEST_ALL_PREFIXES(U2fHidDeviceTest, TestDeviceError);
static constexpr uint8_t kWinkCapability = 0x01;
static constexpr uint8_t kLockCapability = 0x02;
static constexpr uint32_t kBroadcastChannel = 0xffffffff;
// Internal state machine states
enum class State { INIT, CONNECTED, BUSY, IDLE, DEVICE_ERROR };
using U2fHidMessageCallback =
base::OnceCallback<void(bool, std::unique_ptr<U2fMessage>)>;
using ConnectCallback = device::mojom::HidManager::ConnectCallback;
// Open a connection to this device
void Connect(ConnectCallback callback);
void OnConnect(std::unique_ptr<U2fApduCommand> command,
DeviceCallback callback,
device::mojom::HidConnectionPtr connection);
// Ask device to allocate a unique channel id for this connection
void AllocateChannel(std::unique_ptr<U2fApduCommand> command,
DeviceCallback callback);
void OnAllocateChannel(std::vector<uint8_t> nonce,
std::unique_ptr<U2fApduCommand> command,
DeviceCallback callback,
bool success,
std::unique_ptr<U2fMessage> message);
void Transition(std::unique_ptr<U2fApduCommand> command,
DeviceCallback callback);
// Write all message packets to device, and read response if expected
void WriteMessage(std::unique_ptr<U2fMessage> message,
bool response_expected,
U2fHidMessageCallback callback);
void PacketWritten(std::unique_ptr<U2fMessage> message,
bool response_expected,
U2fHidMessageCallback callback,
bool success);
// Read all response message packets from device
void ReadMessage(U2fHidMessageCallback callback);
void MessageReceived(DeviceCallback callback,
bool success,
std::unique_ptr<U2fMessage> message);
void OnRead(U2fHidMessageCallback callback,
bool success,
uint8_t report_id,
const base::Optional<std::vector<uint8_t>>& buf);
void OnReadContinuation(std::unique_ptr<U2fMessage> message,
U2fHidMessageCallback callback,
bool success,
uint8_t report_id,
const base::Optional<std::vector<uint8_t>>& buf);
void OnWink(WinkCallback callback,
bool success,
std::unique_ptr<U2fMessage> response);
void ArmTimeout(DeviceCallback callback);
void OnTimeout(DeviceCallback callback);
void OnDeviceTransact(bool success,
std::unique_ptr<U2fApduResponse> response);
base::WeakPtr<U2fDevice> GetWeakPtr() override;
uint32_t channel_id_ = kBroadcastChannel;
uint8_t capabilities_ = 0;
State state_ = State::INIT;
base::CancelableOnceClosure timeout_callback_;
std::queue<std::pair<std::unique_ptr<U2fApduCommand>, DeviceCallback>>
pending_transactions_;
// All the U2fHidDevice instances are owned by U2fRequest. So it is safe to
// let the U2fHidDevice share the device::mojo::HidManager raw pointer from
// U2fRequest.
device::mojom::HidManager* hid_manager_;
device::mojom::HidDeviceInfoPtr device_info_;
device::mojom::HidConnectionPtr connection_;
base::WeakPtrFactory<U2fHidDevice> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(U2fHidDevice);
};
} // namespace device
#endif // DEVICE_U2F_U2F_HID_DEVICE_H_