blob: 125099f0c9c27b10e71dd5e6f3e5fa87e6b7ab4b [file] [log] [blame]
// Copyright 2016 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_MESSAGE_H_
#define DEVICE_U2F_U2F_MESSAGE_H_
#include <list>
#include <vector>
#include "base/gtest_prod_util.h"
#include "device/u2f/u2f_packet.h"
namespace net {
class IOBufferWithSize;
} // namespace net
namespace device {
// U2fMessages are defined by the specification at
// http://fidoalliance.org/specs/u2f-specs-1.0-bt-nfc-id-amendment/fido-u2f-hid-protocol.html
// A U2fMessage object represents a list of U2fPackets. Basic information
// about the message are available through class methods.
class U2fMessage : public base::RefCountedThreadSafe<U2fMessage> {
public:
enum class Type : uint8_t {
CMD_PING = 0x81,
CMD_MSG = 0x83,
CMD_INIT = 0x86,
CMD_WINK = 0x88,
CMD_ERROR = 0xbf,
};
static scoped_refptr<U2fMessage> Create(uint32_t channel_id,
Type type,
const std::vector<uint8_t>& data);
// Reconstruct a message from serialized message data
static scoped_refptr<U2fMessage> CreateFromSerializedData(
scoped_refptr<net::IOBufferWithSize> buf);
// Pop front of queue with next packet
scoped_refptr<net::IOBufferWithSize> PopNextPacket();
// Adds a continuation packet to the packet list, from the serialized
// response value
bool AddContinuationPacket(scoped_refptr<net::IOBufferWithSize> packet_buf);
size_t NumPackets();
// Returns entire message payload
std::vector<uint8_t> GetMessagePayload() const;
uint32_t channel_id() { return channel_id_; }
// Message construction complete
bool MessageComplete();
std::list<scoped_refptr<U2fPacket>>::const_iterator begin();
std::list<scoped_refptr<U2fPacket>>::const_iterator end();
protected:
virtual ~U2fMessage();
private:
friend class base::RefCountedThreadSafe<U2fMessage>;
FRIEND_TEST_ALL_PREFIXES(U2fMessageTest, TestMaxLengthPacketConstructors);
FRIEND_TEST_ALL_PREFIXES(U2fMessageTest, TestMessagePartitoning);
FRIEND_TEST_ALL_PREFIXES(U2fMessageTest, TestDeconstruct);
FRIEND_TEST_ALL_PREFIXES(U2fMessageTest, TestMaxSize);
FRIEND_TEST_ALL_PREFIXES(U2fMessageTest, TestDeserialize);
static constexpr size_t kInitPacketHeader = 7;
static constexpr size_t kContinuationPacketHeader = 5;
static constexpr size_t kMaxHidPacketSize = 64;
static constexpr size_t kInitPacketDataSize =
kMaxHidPacketSize - kInitPacketHeader;
static constexpr size_t kContinuationPacketDataSize =
kMaxHidPacketSize - kContinuationPacketHeader;
// Messages are limited to an init packet and 128 continuation packets
// Maximum payload length therefore is 64-7 + 128 * (64-5) = 7609 bytes
static constexpr size_t kMaxMessageSize = 7609;
U2fMessage(uint32_t channel_id, Type type, const std::vector<uint8_t>& data);
U2fMessage(scoped_refptr<U2fInitPacket> init_packet, size_t remaining_size);
std::list<scoped_refptr<U2fPacket>> packets_;
size_t remaining_size_;
uint32_t channel_id_;
};
} // namespace device
#endif // DEVICE_U2F_U2F_MESSAGE_H_