blob: 62ccae096b0a94c90734f35a57751fe14a976078 [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.
#include "device/u2f/u2f_ble_frames.h"
#include <vector>
#include "device/u2f/u2f_command_type.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
std::vector<uint8_t> GetSomeData(size_t size) {
std::vector<uint8_t> data(size);
for (size_t i = 0; i < size; ++i)
data[i] = static_cast<uint8_t>((i * i) & 0xFF);
return data;
}
} // namespace
namespace device {
TEST(U2fBleFramesTest, InitializationFragment) {
const std::vector<uint8_t> data = GetSomeData(25);
constexpr uint16_t kDataLength = 21123;
U2fBleFrameInitializationFragment fragment(
U2fCommandType::CMD_MSG, kDataLength, base::make_span(data));
std::vector<uint8_t> buffer;
const size_t binary_size = fragment.Serialize(&buffer);
EXPECT_EQ(buffer.size(), binary_size);
EXPECT_EQ(data.size() + 3, binary_size);
U2fBleFrameInitializationFragment parsed_fragment;
ASSERT_TRUE(
U2fBleFrameInitializationFragment::Parse(buffer, &parsed_fragment));
EXPECT_EQ(kDataLength, parsed_fragment.data_length());
EXPECT_EQ(base::make_span(data), parsed_fragment.fragment());
EXPECT_EQ(U2fCommandType::CMD_MSG, parsed_fragment.command());
}
TEST(U2fBleFramesTest, ContinuationFragment) {
const auto data = GetSomeData(25);
constexpr uint8_t kSequence = 61;
U2fBleFrameContinuationFragment fragment(base::make_span(data), kSequence);
std::vector<uint8_t> buffer;
const size_t binary_size = fragment.Serialize(&buffer);
EXPECT_EQ(buffer.size(), binary_size);
EXPECT_EQ(data.size() + 1, binary_size);
U2fBleFrameContinuationFragment parsed_fragment;
ASSERT_TRUE(U2fBleFrameContinuationFragment::Parse(buffer, &parsed_fragment));
EXPECT_EQ(base::make_span(data), parsed_fragment.fragment());
EXPECT_EQ(kSequence, parsed_fragment.sequence());
}
TEST(U2fBleFramesTest, SplitAndAssemble) {
for (size_t size : {0, 1, 16, 17, 18, 20, 21, 22, 35, 36,
37, 39, 40, 41, 54, 55, 56, 60, 100, 65535}) {
SCOPED_TRACE(size);
U2fBleFrame frame(U2fCommandType::CMD_PING, GetSomeData(size));
auto fragments = frame.ToFragments(20);
EXPECT_EQ(frame.command(), fragments.first.command());
EXPECT_EQ(frame.data().size(),
static_cast<size_t>(fragments.first.data_length()));
U2fBleFrameAssembler assembler(fragments.first);
while (!fragments.second.empty()) {
ASSERT_TRUE(assembler.AddFragment(fragments.second.front()));
fragments.second.pop();
}
EXPECT_TRUE(assembler.IsDone());
ASSERT_TRUE(assembler.GetFrame());
auto result_frame = std::move(*assembler.GetFrame());
EXPECT_EQ(frame.command(), result_frame.command());
EXPECT_EQ(frame.data(), result_frame.data());
}
}
TEST(U2fBleFramesTest, FrameAssemblerError) {
U2fBleFrame frame(U2fCommandType::CMD_PING, GetSomeData(30));
auto fragments = frame.ToFragments(20);
ASSERT_EQ(1u, fragments.second.size());
fragments.second.front() =
U2fBleFrameContinuationFragment(fragments.second.front().fragment(), 51);
U2fBleFrameAssembler assembler(fragments.first);
EXPECT_FALSE(assembler.IsDone());
EXPECT_FALSE(assembler.GetFrame());
EXPECT_FALSE(assembler.AddFragment(fragments.second.front()));
EXPECT_FALSE(assembler.IsDone());
EXPECT_FALSE(assembler.GetFrame());
}
TEST(U2fBleFramesTest, FrameGettersAndValidity) {
{
U2fBleFrame frame(U2fCommandType::CMD_KEEPALIVE, std::vector<uint8_t>(2));
EXPECT_FALSE(frame.IsValid());
}
{
U2fBleFrame frame(U2fCommandType::CMD_ERROR, {});
EXPECT_FALSE(frame.IsValid());
}
for (auto code : {U2fBleFrame::KeepaliveCode::TUP_NEEDED,
U2fBleFrame::KeepaliveCode::PROCESSING}) {
U2fBleFrame frame(U2fCommandType::CMD_KEEPALIVE,
std::vector<uint8_t>(1, static_cast<uint8_t>(code)));
EXPECT_TRUE(frame.IsValid());
EXPECT_EQ(code, frame.GetKeepaliveCode());
}
for (auto code : {
U2fBleFrame::ErrorCode::INVALID_CMD,
U2fBleFrame::ErrorCode::INVALID_PAR,
U2fBleFrame::ErrorCode::INVALID_SEQ,
U2fBleFrame::ErrorCode::INVALID_LEN,
U2fBleFrame::ErrorCode::REQ_TIMEOUT, U2fBleFrame::ErrorCode::NA_1,
U2fBleFrame::ErrorCode::NA_2, U2fBleFrame::ErrorCode::NA_3,
}) {
U2fBleFrame frame(U2fCommandType::CMD_ERROR, {static_cast<uint8_t>(code)});
EXPECT_TRUE(frame.IsValid());
EXPECT_EQ(code, frame.GetErrorCode());
}
}
} // namespace device