forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement CTAP MakeCredential per device request logic
Implements FidoTask class and MakeCredentialTask class. FidoTask handles shared logic between MakeCredential request and GetAssertion request such as logic for AuthenticatorGetInfo request which is a preliminary request for MakeCredential request. MakeCredentialTask class initiates asynchronous MakeCredential request for a single device upon construction and decodes cbor encodeded response into MakeCredentialResponse object. Change-Id: Icbb6295436b4501bcb94be58b503821e9aa35ce8 Reviewed-on: https://chromium-review.googlesource.com/936382 Commit-Queue: Jun Choi <hongjunchoi@chromium.org> Reviewed-by: Jan Wilken Dörrie <jdoerrie@chromium.org> Reviewed-by: Balazs Engedy <engedy@chromium.org> Cr-Commit-Position: refs/heads/master@{#545293}
- Loading branch information
Jun Choi
authored and
Commit Bot
committed
Mar 22, 2018
1 parent
3df0f4e
commit f15afe4
Showing
15 changed files
with
523 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2018 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/fido_task.h" | ||
|
||
#include <utility> | ||
|
||
#include "base/bind.h" | ||
#include "base/bind_helpers.h" | ||
#include "base/threading/sequenced_task_runner_handle.h" | ||
#include "device/fido/ctap_empty_authenticator_request.h" | ||
#include "device/fido/device_response_converter.h" | ||
#include "device/fido/fido_constants.h" | ||
|
||
namespace device { | ||
|
||
FidoTask::FidoTask(FidoDevice* device) : device_(device), weak_factory_(this) { | ||
DCHECK(device_); | ||
base::SequencedTaskRunnerHandle::Get()->PostTask( | ||
FROM_HERE, | ||
base::BindOnce(&FidoTask::StartTask, weak_factory_.GetWeakPtr())); | ||
} | ||
|
||
FidoTask::~FidoTask() = default; | ||
|
||
void FidoTask::CancelTask() { | ||
if (device()->supported_protocol() != ProtocolVersion::kCtap) | ||
return; | ||
|
||
device()->DeviceTransact(AuthenticatorCancelRequest().Serialize(), | ||
base::DoNothing()); | ||
} | ||
|
||
void FidoTask::GetAuthenticatorInfo(base::OnceClosure ctap_callback, | ||
base::OnceClosure u2f_callback) { | ||
device()->DeviceTransact( | ||
AuthenticatorGetInfoRequest().Serialize(), | ||
base::BindOnce(&FidoTask::OnAuthenticatorInfoReceived, | ||
weak_factory_.GetWeakPtr(), std::move(ctap_callback), | ||
std::move(u2f_callback))); | ||
} | ||
|
||
void FidoTask::OnAuthenticatorInfoReceived( | ||
base::OnceClosure ctap_callback, | ||
base::OnceClosure u2f_callback, | ||
base::Optional<std::vector<uint8_t>> response) { | ||
device()->set_state(FidoDevice::State::kReady); | ||
|
||
base::Optional<AuthenticatorGetInfoResponse> get_info_response; | ||
if (!response || !(get_info_response = ReadCTAPGetInfoResponse(*response))) { | ||
device()->set_supported_protocol(ProtocolVersion::kU2f); | ||
std::move(u2f_callback).Run(); | ||
return; | ||
} | ||
|
||
device()->SetDeviceInfo(std::move(*get_info_response)); | ||
device()->set_supported_protocol(ProtocolVersion::kCtap); | ||
std::move(ctap_callback).Run(); | ||
} | ||
|
||
} // namespace device |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright 2018 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_FIDO_FIDO_TASK_H_ | ||
#define DEVICE_FIDO_FIDO_TASK_H_ | ||
|
||
#include <stdint.h> | ||
|
||
#include <vector> | ||
|
||
#include "base/callback.h" | ||
#include "base/component_export.h" | ||
#include "base/macros.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "base/optional.h" | ||
#include "device/fido/fido_device.h" | ||
|
||
namespace device { | ||
|
||
// Encapsulates per-device request logic shared between MakeCredential and | ||
// GetAssertion. Handles issuing the AuthenticatorGetInfo command to tokens, | ||
// caching device info, and distinguishing U2F tokens from CTAP tokens. | ||
// | ||
// FidoTask is owned by FidoRequestHandler and manages all interaction with | ||
// |device_|. It is created when a new device is discovered by FidoDiscovery and | ||
// destroyed when the device is removed or when a successful response has been | ||
// issued to the relying party from another authenticator. | ||
class COMPONENT_EXPORT(DEVICE_FIDO) FidoTask { | ||
public: | ||
// The |device| must outlive the FidoTask instance. | ||
explicit FidoTask(FidoDevice* device); | ||
virtual ~FidoTask(); | ||
|
||
// Invokes the AuthenticatorCancel method on |device_| if it supports the | ||
// CTAP protocol. Upon receiving AuthenticatorCancel request, authenticators | ||
// cancel ongoing requests (if any) immediately. Calling this method itself | ||
// neither destructs |this| instance nor destroys |device_|. | ||
void CancelTask(); | ||
|
||
protected: | ||
// Asynchronously initiates CTAP request operation for a single device. | ||
virtual void StartTask() = 0; | ||
|
||
// Invokes the AuthenticatorGetInfo method on |device_|. If successful and a | ||
// well formed response is received, then |device_| is deemed to support CTAP | ||
// protocol and |ctap_callback| is invoked, which sends CBOR encoded command | ||
// to the authenticator. For all failure cases, |device_| is assumed to | ||
// support the U2F protocol as FidoDiscovery selects only devices that support | ||
// either the U2F or CTAP protocols during discovery. Therefore |u2f_callback| | ||
// is invoked, which sends APDU encoded request to authenticator. | ||
void GetAuthenticatorInfo(base::OnceClosure ctap_callback, | ||
base::OnceClosure u2f_callback); | ||
|
||
FidoDevice* device() const { | ||
DCHECK(device_); | ||
return device_; | ||
} | ||
|
||
private: | ||
void OnAuthenticatorInfoReceived( | ||
base::OnceClosure ctap_callback, | ||
base::OnceClosure u2f_callback, | ||
base::Optional<std::vector<uint8_t>> response); | ||
|
||
FidoDevice* const device_; | ||
base::WeakPtrFactory<FidoTask> weak_factory_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(FidoTask); | ||
}; | ||
|
||
} // namespace device | ||
|
||
#endif // DEVICE_FIDO_FIDO_TASK_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// Copyright 2018 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/make_credential_task.h" | ||
|
||
#include <utility> | ||
|
||
#include "base/bind.h" | ||
#include "device/fido/ctap_empty_authenticator_request.h" | ||
#include "device/fido/device_response_converter.h" | ||
|
||
namespace device { | ||
|
||
MakeCredentialTask::MakeCredentialTask( | ||
FidoDevice* device, | ||
CtapMakeCredentialRequest request_parameter, | ||
MakeCredentialTaskCallback callback) | ||
: FidoTask(device), | ||
request_parameter_(std::move(request_parameter)), | ||
callback_(std::move(callback)), | ||
weak_factory_(this) {} | ||
|
||
MakeCredentialTask::~MakeCredentialTask() = default; | ||
|
||
void MakeCredentialTask::StartTask() { | ||
GetAuthenticatorInfo(base::BindOnce(&MakeCredentialTask::MakeCredential, | ||
weak_factory_.GetWeakPtr()), | ||
base::BindOnce(&MakeCredentialTask::U2fRegister, | ||
weak_factory_.GetWeakPtr())); | ||
} | ||
|
||
void MakeCredentialTask::MakeCredential() { | ||
device()->DeviceTransact( | ||
request_parameter_.EncodeAsCBOR(), | ||
base::BindOnce(&MakeCredentialTask::OnCtapMakeCredentialResponseReceived, | ||
weak_factory_.GetWeakPtr())); | ||
} | ||
|
||
void MakeCredentialTask::U2fRegister() { | ||
// TODO(hongjunchoi): Implement U2F register request logic to support | ||
// interoperability with U2F protocol. Currently all U2F devices are not | ||
// supported and request to U2F devices will be silently dropped. | ||
// See: https://crbug.com/798573 | ||
std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, | ||
base::nullopt); | ||
} | ||
|
||
void MakeCredentialTask::OnCtapMakeCredentialResponseReceived( | ||
base::Optional<std::vector<uint8_t>> device_response) { | ||
if (!device_response) { | ||
std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, | ||
base::nullopt); | ||
return; | ||
} | ||
|
||
std::move(callback_).Run(GetResponseCode(*device_response), | ||
ReadCTAPMakeCredentialResponse(*device_response)); | ||
} | ||
|
||
} // namespace device |
Oops, something went wrong.