blob: 1f01267c169bfbf87360fe8365b5a0ab7372a1b3 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_WEBAUTH_VIRTUAL_AUTHENTICATOR_H_
#define CONTENT_BROWSER_WEBAUTH_VIRTUAL_AUTHENTICATOR_H_
#include <memory>
#include <string>
#include <vector>
#include "base/containers/span.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/scoped_observation.h"
#include "content/common/content_export.h"
#include "device/fido/virtual_fido_device.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
namespace content {
// Implements a stateful virtual authenticator.
//
// This class has very little logic itself, it merely stores a unique ID and the
// state of the authenticator, whereas performing all cryptographic operations
// is delegated to the VirtualFidoDevice class.
class CONTENT_EXPORT VirtualAuthenticator
: public device::VirtualFidoDevice::Observer {
public:
class Observer : public base::CheckedObserver {
public:
virtual void OnCredentialCreated(
VirtualAuthenticator* authenticator,
const device::VirtualFidoDevice::Credential& credential) = 0;
virtual void OnCredentialDeleted(
VirtualAuthenticator* authenticator,
base::span<const uint8_t> credential_id) = 0;
virtual void OnCredentialUpdated(
VirtualAuthenticator* authenticator,
const device::VirtualFidoDevice::Credential& credential) = 0;
virtual void OnAssertion(
VirtualAuthenticator* authenticator,
const device::VirtualFidoDevice::Credential& credential) = 0;
virtual void OnAuthenticatorWillBeDestroyed(
VirtualAuthenticator* authenticator) = 0;
};
// Attributes that the virtual authenticator should simulate.
struct CONTENT_EXPORT Options {
Options();
~Options();
// protocol is the client-to-authenticator protocol that the virtual
// authenticator simulates.
device::ProtocolVersion protocol = device::ProtocolVersion::kCtap2;
// ctap2_version indicates which minor version of CTAP2 the authenticator
// should simulate if |protocol| is CTAP2. It is ignored otherwise.
device::Ctap2Version ctap2_version = device::Ctap2Version::kCtap2_0;
device::FidoTransportProtocol transport =
device::FidoTransportProtocol::kUsbHumanInterfaceDevice;
device::AuthenticatorAttachment attachment =
device::AuthenticatorAttachment::kCrossPlatform;
bool has_resident_key = false;
bool has_user_verification = false;
bool is_user_present = true;
bool has_large_blob = false;
bool has_cred_blob = false;
bool has_min_pin_length = false;
bool has_prf = false;
bool default_backup_eligibility = false;
bool default_backup_state = false;
};
using GetLargeBlobCallback =
base::OnceCallback<void(std::optional<std::vector<uint8_t>>)>;
using SetLargeBlobCallback = base::OnceCallback<void(bool)>;
explicit VirtualAuthenticator(const Options& options);
VirtualAuthenticator(const VirtualAuthenticator&) = delete;
VirtualAuthenticator& operator=(const VirtualAuthenticator&) = delete;
~VirtualAuthenticator() override;
device::VirtualFidoDevice::State::RegistrationsMap& registrations() const {
return state_->registrations;
}
// Register a new credential. Returns true if the registration was successful,
// false otherwise.
bool AddRegistration(std::vector<uint8_t> key_handle,
const std::string& rp_id,
base::span<const uint8_t> private_key,
int32_t counter);
// Register a new resident credential. Returns true if the registration was
// successful, false otherwise.
bool AddResidentRegistration(std::vector<uint8_t> key_handle,
std::string rp_id,
base::span<const uint8_t> private_key,
int32_t counter,
std::vector<uint8_t> user_handle,
std::optional<std::string> user_name,
std::optional<std::string> user_display_name);
// Removes all the credentials.
void ClearRegistrations();
// Remove a credential identified by |key_handle|. Returns true if the
// credential was found and removed, false otherwise.
bool RemoveRegistration(const std::vector<uint8_t>& key_handle);
// Updates the name and display name of registrations matching
// |relying_party_id| and |user_id|.
void UpdateUserDetails(std::string_view relying_party_id,
base::span<const uint8_t> user_id,
std::string_view name,
std::string_view display_name);
// Sets whether tests of user presence succeed or not for new requests sent to
// this authenticator. The default is true.
void SetUserPresence(bool is_user_present);
// Sets whether user verification should succeed or not for new requests sent
// to this authenticator. Defaults to true.
void set_user_verified(bool is_user_verified) {
is_user_verified_ = is_user_verified;
}
// If set, overrides the signature in the authenticator response to be zero.
// Defaults to false.
void set_bogus_signature(bool is_bogus) {
state_->ctap2_invalid_signature = is_bogus;
}
// If set, overrides the UV bit in the flags in the authenticator response to
// be zero. Defaults to false.
void set_bad_uv_bit(bool is_bad_bit) { state_->unset_uv_bit = is_bad_bit; }
// If set, overrides the UP bit in the flags in the authenticator response to
// be zero. Defaults to false.
void set_bad_up_bit(bool is_bad_bit) { state_->unset_up_bit = is_bad_bit; }
bool has_resident_key() const { return has_resident_key_; }
device::FidoTransportProtocol transport() const { return state_->transport; }
const std::string& unique_id() const { return unique_id_; }
bool is_user_verifying_platform_authenticator() const {
return attachment_ == device::AuthenticatorAttachment::kPlatform &&
has_user_verification_;
}
// Constructs a VirtualFidoDevice instance that will perform cryptographic
// operations on behalf of, and using the state stored in this virtual
// authenticator.
//
// There is an N:1 relationship between VirtualFidoDevices and this class, so
// this method can be called any number of times.
std::unique_ptr<device::VirtualFidoDevice> ConstructDevice();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
bool HasObserversForTest();
// Set the BE flag for a given |key_handle|. |key_handle| must match a
// credential.
void SetBackupEligibility(const std::vector<uint8_t>& key_handle,
bool backup_eligibility);
// Set the BS flag for a given |key_handle|. |key_handle| must match a
// credential.
void SetBackupState(const std::vector<uint8_t>& key_handle,
bool backup_state);
void GetLargeBlob(const std::vector<uint8_t>& key_handle,
GetLargeBlobCallback callback);
void SetLargeBlob(const std::vector<uint8_t>& key_handle,
const std::vector<uint8_t>& blob,
SetLargeBlobCallback callback);
private:
void OnLargeBlobUncompressed(
GetLargeBlobCallback callback,
base::expected<mojo_base::BigBuffer, std::string> result);
void OnLargeBlobCompressed(
base::span<const uint8_t> key_handle,
uint64_t original_size,
SetLargeBlobCallback callback,
base::expected<mojo_base::BigBuffer, std::string> result);
// device::VirtualFidoDevice::Observer:
void OnCredentialCreated(
const device::VirtualFidoDevice::Credential& credential) override;
void OnCredentialDeleted(base::span<const uint8_t> credential_id) override;
void OnCredentialUpdated(
const device::VirtualFidoDevice::Credential& credential) override;
void OnAssertion(
const device::VirtualFidoDevice::Credential& credential) override;
const device::ProtocolVersion protocol_;
const device::Ctap2Version ctap2_version_;
const device::AuthenticatorAttachment attachment_;
const bool has_resident_key_;
const bool has_user_verification_;
const bool has_large_blob_;
const bool has_cred_blob_;
const bool has_min_pin_length_;
const bool has_prf_;
bool is_user_verified_ = true;
const std::string unique_id_;
bool is_user_present_;
base::ObserverList<Observer> observers_;
data_decoder::DataDecoder data_decoder_;
scoped_refptr<device::VirtualFidoDevice::State> state_;
base::ScopedObservation<device::VirtualFidoDevice::State,
device::VirtualFidoDevice::Observer>
observation_{this};
base::WeakPtrFactory<VirtualAuthenticator> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_WEBAUTH_VIRTUAL_AUTHENTICATOR_H_