123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // 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/fido/mock_fido_device.h"
- #include <utility>
- #include "base/bind.h"
- #include "base/location.h"
- #include "base/strings/strcat.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "components/apdu/apdu_response.h"
- #include "components/cbor/writer.h"
- #include "device/fido/device_response_converter.h"
- #include "device/fido/fido_constants.h"
- #include "device/fido/fido_parsing_utils.h"
- #include "device/fido/fido_test_data.h"
- namespace device {
- namespace {
- AuthenticatorGetInfoResponse DefaultAuthenticatorInfo() {
- return *ReadCTAPGetInfoResponse(test_data::kTestAuthenticatorGetInfoResponse);
- }
- } // namespace
- // static
- std::unique_ptr<MockFidoDevice> MockFidoDevice::MakeU2f() {
- return std::make_unique<MockFidoDevice>(ProtocolVersion::kU2f, absl::nullopt);
- }
- // static
- std::unique_ptr<MockFidoDevice> MockFidoDevice::MakeCtap(
- absl::optional<AuthenticatorGetInfoResponse> device_info) {
- if (!device_info) {
- device_info = DefaultAuthenticatorInfo();
- }
- auto device = std::make_unique<MockFidoDevice>(ProtocolVersion::kCtap2,
- std::move(*device_info));
- device->StubGetDisplayName();
- return device;
- }
- // static
- std::unique_ptr<MockFidoDevice>
- MockFidoDevice::MakeU2fWithGetInfoExpectation() {
- auto device = std::make_unique<MockFidoDevice>();
- device->StubGetId();
- device->StubGetDisplayName();
- device->ExpectWinkedAtLeastOnce();
- device->ExpectCtap2CommandAndRespondWith(
- CtapRequestCommand::kAuthenticatorGetInfo, absl::nullopt);
- return device;
- }
- // static
- std::unique_ptr<MockFidoDevice> MockFidoDevice::MakeCtapWithGetInfoExpectation(
- absl::optional<base::span<const uint8_t>> get_info_response) {
- if (!get_info_response) {
- get_info_response = test_data::kTestAuthenticatorGetInfoResponse;
- }
- auto get_info = ReadCTAPGetInfoResponse(*get_info_response);
- CHECK(get_info);
- auto device = MockFidoDevice::MakeCtap(std::move(*get_info));
- device->StubGetId();
- device->StubGetDisplayName();
- device->ExpectCtap2CommandAndRespondWith(
- CtapRequestCommand::kAuthenticatorGetInfo, std::move(get_info_response));
- return device;
- }
- std::vector<uint8_t> MockFidoDevice::EncodeCBORRequest(
- std::pair<CtapRequestCommand, absl::optional<cbor::Value>> request) {
- std::vector<uint8_t> request_bytes;
- if (request.second) {
- absl::optional<std::vector<uint8_t>> cbor_bytes =
- cbor::Writer::Write(*request.second);
- DCHECK(cbor_bytes);
- request_bytes = std::move(*cbor_bytes);
- }
- request_bytes.insert(request_bytes.begin(),
- static_cast<uint8_t>(request.first));
- return request_bytes;
- }
- // Matcher to compare the first byte of the incoming requests.
- MATCHER_P(IsCtap2Command, expected_command, "") {
- return !arg.empty() && arg[0] == base::strict_cast<uint8_t>(expected_command);
- }
- MockFidoDevice::MockFidoDevice() = default;
- MockFidoDevice::MockFidoDevice(
- ProtocolVersion protocol_version,
- absl::optional<AuthenticatorGetInfoResponse> device_info)
- : MockFidoDevice() {
- set_supported_protocol(protocol_version);
- if (device_info) {
- SetDeviceInfo(std::move(*device_info));
- }
- }
- MockFidoDevice::~MockFidoDevice() = default;
- FidoDevice::CancelToken MockFidoDevice::DeviceTransact(
- std::vector<uint8_t> command,
- DeviceCallback cb) {
- return DeviceTransactPtr(command, cb);
- }
- void MockFidoDevice::TryWink(base::OnceClosure cb) {
- TryWinkRef(cb);
- }
- FidoTransportProtocol MockFidoDevice::DeviceTransport() const {
- return transport_protocol_;
- }
- base::WeakPtr<FidoDevice> MockFidoDevice::GetWeakPtr() {
- return weak_factory_.GetWeakPtr();
- }
- void MockFidoDevice::ExpectWinkedAtLeastOnce() {
- EXPECT_CALL(*this, TryWinkRef(::testing::_))
- .Times(::testing::AtLeast(1))
- .WillRepeatedly([](base::OnceClosure& cb) { std::move(cb).Run(); });
- }
- void MockFidoDevice::StubGetId() {
- // Use a counter to keep the device ID unique.
- static size_t i = 0;
- EXPECT_CALL(*this, GetId())
- .WillRepeatedly(
- testing::Return(base::StrCat({"mockdevice", std::to_string(i++)})));
- }
- void MockFidoDevice::ExpectCtap2CommandAndRespondWith(
- CtapRequestCommand command,
- absl::optional<base::span<const uint8_t>> response,
- base::TimeDelta delay,
- testing::Matcher<base::span<const uint8_t>> request_matcher) {
- auto data = fido_parsing_utils::MaterializeOrNull(response);
- auto send_response = [ data(std::move(data)), delay ](DeviceCallback & cb) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::BindOnce(std::move(cb), std::move(data)), delay);
- };
- EXPECT_CALL(*this,
- DeviceTransactPtr(AllOf(IsCtap2Command(command), request_matcher),
- ::testing::_))
- .WillOnce(::testing::DoAll(
- ::testing::WithArg<1>(::testing::Invoke(send_response)),
- ::testing::Return(0)));
- }
- void MockFidoDevice::ExpectCtap2CommandAndRespondWithError(
- CtapRequestCommand command,
- CtapDeviceResponseCode response_code,
- base::TimeDelta delay) {
- std::array<uint8_t, 1> data{base::strict_cast<uint8_t>(response_code)};
- return ExpectCtap2CommandAndRespondWith(std::move(command), data, delay);
- }
- void MockFidoDevice::ExpectRequestAndRespondWith(
- base::span<const uint8_t> request,
- absl::optional<base::span<const uint8_t>> response,
- base::TimeDelta delay) {
- auto data = fido_parsing_utils::MaterializeOrNull(response);
- auto send_response = [ data(std::move(data)), delay ](DeviceCallback & cb) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::BindOnce(std::move(cb), std::move(data)), delay);
- };
- auto request_as_vector = fido_parsing_utils::Materialize(request);
- EXPECT_CALL(*this,
- DeviceTransactPtr(std::move(request_as_vector), ::testing::_))
- .WillOnce(::testing::DoAll(
- ::testing::WithArg<1>(::testing::Invoke(send_response)),
- ::testing::Return(0)));
- }
- void MockFidoDevice::ExpectCtap2CommandAndDoNotRespond(
- CtapRequestCommand command) {
- EXPECT_CALL(*this, DeviceTransactPtr(IsCtap2Command(command), ::testing::_))
- .WillOnce(::testing::Return(0));
- }
- void MockFidoDevice::ExpectRequestAndDoNotRespond(
- base::span<const uint8_t> request) {
- auto request_as_vector = fido_parsing_utils::Materialize(request);
- EXPECT_CALL(*this,
- DeviceTransactPtr(std::move(request_as_vector), ::testing::_))
- .WillOnce(::testing::Return(0));
- }
- void MockFidoDevice::SetDeviceTransport(
- FidoTransportProtocol transport_protocol) {
- transport_protocol_ = transport_protocol;
- }
- void MockFidoDevice::StubGetDisplayName() {
- EXPECT_CALL(*this, GetDisplayName())
- .WillRepeatedly(testing::Return(std::string()));
- }
- } // namespace device
|