1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "device/fido/fido_device.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/stl_util.h"
11 #include "components/device_event_log/device_event_log.h"
12 #include "device/fido/ctap_empty_authenticator_request.h"
13 #include "device/fido/device_response_converter.h"
14 #include "device/fido/fido_constants.h"
15 
16 namespace device {
17 
18 FidoDevice::FidoDevice() = default;
19 FidoDevice::~FidoDevice() = default;
20 
TryWink(base::OnceClosure callback)21 void FidoDevice::TryWink(base::OnceClosure callback) {
22   std::move(callback).Run();
23 }
24 
GetDisplayName() const25 base::string16 FidoDevice::GetDisplayName() const {
26   const auto id = GetId();
27   return base::string16(id.begin(), id.end());
28 }
29 
IsInPairingMode() const30 bool FidoDevice::IsInPairingMode() const {
31   NOTREACHED();
32   return false;
33 }
34 
IsPaired() const35 bool FidoDevice::IsPaired() const {
36   NOTREACHED();
37   return false;
38 }
39 
RequiresBlePairingPin() const40 bool FidoDevice::RequiresBlePairingPin() const {
41   NOTREACHED();
42   return true;
43 }
44 
DiscoverSupportedProtocolAndDeviceInfo(base::OnceClosure done)45 void FidoDevice::DiscoverSupportedProtocolAndDeviceInfo(
46     base::OnceClosure done) {
47   // Set the protocol version to CTAP2 for the purpose of sending the GetInfo
48   // request. The correct value will be set in the callback based on the
49   // device response.
50   supported_protocol_ = ProtocolVersion::kCtap2;
51   FIDO_LOG(DEBUG)
52       << "Sending CTAP2 AuthenticatorGetInfo request to authenticator.";
53   DeviceTransact(AuthenticatorGetInfoRequest().Serialize(),
54                  base::BindOnce(&FidoDevice::OnDeviceInfoReceived, GetWeakPtr(),
55                                 std::move(done)));
56 }
57 
SupportedProtocolIsInitialized()58 bool FidoDevice::SupportedProtocolIsInitialized() {
59   return (supported_protocol_ == ProtocolVersion::kU2f && !device_info_) ||
60          (supported_protocol_ == ProtocolVersion::kCtap2 && device_info_);
61 }
62 
OnDeviceInfoReceived(base::OnceClosure done,base::Optional<std::vector<uint8_t>> response)63 void FidoDevice::OnDeviceInfoReceived(
64     base::OnceClosure done,
65     base::Optional<std::vector<uint8_t>> response) {
66   // TODO(hongjunchoi): Add tests that verify this behavior.
67   if (state_ == FidoDevice::State::kDeviceError)
68     return;
69 
70   state_ = FidoDevice::State::kReady;
71   base::Optional<AuthenticatorGetInfoResponse> get_info_response =
72       response ? ReadCTAPGetInfoResponse(*response) : base::nullopt;
73   if (!get_info_response ||
74       !base::Contains(get_info_response->versions, ProtocolVersion::kCtap2)) {
75     supported_protocol_ = ProtocolVersion::kU2f;
76     needs_explicit_wink_ = true;
77     FIDO_LOG(DEBUG) << "The device only supports the U2F protocol.";
78   } else {
79     supported_protocol_ = ProtocolVersion::kCtap2;
80     device_info_ = std::move(*get_info_response);
81     FIDO_LOG(DEBUG) << "The device supports the CTAP2 protocol.";
82   }
83   std::move(done).Run();
84 }
85 
SetDeviceInfo(AuthenticatorGetInfoResponse device_info)86 void FidoDevice::SetDeviceInfo(AuthenticatorGetInfoResponse device_info) {
87   device_info_ = std::move(device_info);
88 }
89 
90 }  // namespace device
91