blob: 7fe221d92225d90b55365b3bee9a78f4205e5a71 [file] [log] [blame]
// Copyright 2017 The Chromium OS 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 U2FD_U2FHID_H_
#define U2FD_U2FHID_H_
#include <functional>
#include <memory>
#include <string>
#include <vector>
#include <base/timer/timer.h>
#include <brillo/errors/error.h>
#include <metrics/metrics_library.h>
#include <trunks/cr50_headers/u2f.h>
#include "u2fd/hid_interface.h"
#include "u2fd/u2f_apdu.h"
#include "u2fd/u2f_msg_handler_interface.h"
#include "u2fd/user_state.h"
namespace u2f {
// Mandatory length of the U2F HID report.
constexpr size_t kU2fReportSize = 64;
// HID frame CMD/SEQ byte definitions.
constexpr uint8_t kFrameTypeMask = 0x80;
constexpr uint8_t kFrameTypeInit = 0x80;
// when bit 7 is not set, the frame type is CONTinuation.
// INIT command parameters
constexpr uint32_t kCidBroadcast = -1U;
constexpr size_t kInitNonceSize = 8;
constexpr uint8_t kCapFlagLock = 0x02;
constexpr size_t kMaxPayloadSize = (64 - 7 + 128 * (64 - 5)); // 7609 bytes
// U2fHid emulates U2FHID protocol on top of the TPM U2F implementation.
// The object reads the HID report sent by the HIDInterface passed to the
// constructor, parses it and extracts the U2FHID command. If this is a U2F
// message, finally sends the raw U2F APDU to the |transmit_func| callback
// passed to the constructor. It returns the final result (response APDU or
// error code) inside an HID report through the HIDInterface.
class U2fHid {
// U2FHID Command codes
enum class U2fHidCommand : uint8_t {
kPing = 1,
kMsg = 3,
kLock = 4,
kVendorSysInfo = 5,
kInit = 6,
kWink = 8,
kError = 0x3f,
// U2FHID error codes
enum class U2fHidError : uint8_t {
kNone = 0,
kInvalidCmd = 1,
kInvalidPar = 2,
kInvalidLen = 3,
kInvalidSeq = 4,
kMsgTimeout = 5,
kChannelBusy = 6,
kLockRequired = 10,
kInvalidCid = 11,
kOther = 127,
// Create a new virtual U2F HID Device. Does not take ownership of
// msg_handler, which must outlive this instance.
U2fHid(std::unique_ptr<HidInterface> hid,
U2fMessageHandlerInterface* msg_handler);
U2fHid(const U2fHid&) = delete;
U2fHid& operator=(const U2fHid&) = delete;
bool Init();
// U2FHID protocol commands implementation.
void CmdInit(uint32_t cid, const std::string& payload);
int CmdLock(std::string* resp);
int CmdMsg(std::string* resp);
int CmdPing(std::string* resp);
int CmdSysInfo(std::string* resp);
// Fully resets the state of the possibly on-going U2FHID transaction.
void ClearTransaction();
// Sends back a U2FHID report with just the |errcode| error code inside
// on channel |cid|.
// If |clear| is set, clear the transaction state at the same time.
void ReturnError(U2fHidError errcode, uint32_t cid, bool clear);
// Called when we reach the deadline for the on-going transaction.
void TransactionTimeout();
// Called when we reach the deadline for an unreleased channel lock.
void LockTimeout();
// Sends back a U2FHID report indicating success and carrying the response
// payload |resp|.
void ReturnResponse(const std::string& resp);
// Executes the action requested by the command contained in the current
// transaction.
void ExecuteCmd();
// Parses the HID report contained in |report| and append the content to the
// current U2FHID transaction or create a new one.
void ProcessReport(const std::string& report);
std::unique_ptr<HidInterface> hid_;
uint32_t free_cid_;
uint32_t locked_cid_;
base::OneShotTimer lock_timeout_;
U2fMessageHandlerInterface* msg_handler_;
class HidPacket;
class HidMessage;
struct Transaction;
std::unique_ptr<Transaction> transaction_;
} // namespace u2f
#endif // U2FD_U2FHID_H_