#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "device/fido/virtual_ctap2_device.h"
#include <array>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/not_fatal_until.h"
#include "base/numerics/safe_conversions.h"
#include "base/ranges/algorithm.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "components/apdu/apdu_response.h"
#include "components/cbor/reader.h"
#include "components/cbor/writer.h"
#include "crypto/ec_private_key.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/authenticator_make_credential_response.h"
#include "device/fido/authenticator_supported_options.h"
#include "device/fido/bio/enrollment.h"
#include "device/fido/credential_management.h"
#include "device/fido/ctap_get_assertion_request.h"
#include "device/fido/ctap_make_credential_request.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_types.h"
#include "device/fido/large_blob.h"
#include "device/fido/opaque_attestation_statement.h"
#include "device/fido/pin.h"
#include "device/fido/pin_internal.h"
#include "device/fido/public_key.h"
#include "device/fido/virtual_u2f_device.h"
#include "third_party/boringssl/src/include/openssl/aes.h"
#include "third_party/boringssl/src/include/openssl/digest.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ec_key.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/boringssl/src/include/openssl/hmac.h"
#include "third_party/boringssl/src/include/openssl/mem.h"
#include "third_party/boringssl/src/include/openssl/rand.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
namespace device {
namespace {
constexpr std::array<uint8_t, kAaguidLength> kDeviceAaguid = …;
constexpr size_t kMaxCredBlob = …;
static_assert …;
struct PinUvAuthTokenPermissions { … };
uint8_t GetSupportedPermissionsMask(const VirtualCtap2Device::Config& config) { … }
std::vector<uint8_t> ConstructResponse(CtapDeviceResponseCode response_code,
base::span<const uint8_t> data) { … }
bool PermissionsRequireRPID(uint8_t permissions) { … }
CtapDeviceResponseCode ExtractPermissions(
const cbor::Value::MapValue& request_map,
const VirtualCtap2Device::Config& config,
PinUvAuthTokenPermissions& out_permissions) { … }
void ReturnCtap2Response(
FidoDevice::DeviceCallback cb,
CtapDeviceResponseCode response_code,
std::optional<base::span<const uint8_t>> data = std::nullopt) { … }
std::vector<uint8_t> ConstructSignatureBuffer(
const AuthenticatorData& authenticator_data,
base::span<const uint8_t, kClientDataHashLength> client_data_hash) { … }
std::vector<uint8_t> ConstructMakeCredentialResponse(
const std::optional<std::vector<uint8_t>> attestation_certificate,
base::span<const uint8_t> signature,
AuthenticatorData authenticator_data,
bool enterprise_attestation_requested,
std::optional<LargeBlobSupportType> large_blob_type,
bool prf_enabled,
std::optional<std::vector<uint8_t>> prf_results) { … }
std::optional<std::vector<uint8_t>> GetPINBytestring(
const cbor::Value::MapValue& request,
pin::RequestKey key) { … }
std::optional<bssl::UniquePtr<EC_POINT>> GetPINKey(
const cbor::Value::MapValue& request,
pin::RequestKey map_key) { … }
CtapDeviceResponseCode ConfirmPresentedPIN(
PINUVAuthProtocol pin_protocol,
VirtualCtap2Device::State* state,
const std::vector<uint8_t>& shared_key,
const std::vector<uint8_t>& encrypted_pin_hash) { … }
CtapDeviceResponseCode SetPIN(
PINUVAuthProtocol protocol,
VirtualCtap2Device::State* state,
const std::vector<uint8_t>& shared_key,
const std::vector<uint8_t>& encrypted_pin,
const std::vector<uint8_t>& pin_auth,
std::optional<base::span<const uint8_t>> current_encrypted_pin_hash) { … }
CtapDeviceResponseCode VerifyPINUVAuthToken(
const AuthenticatorGetInfoResponse& authenticator_info,
base::span<const uint8_t> pin_token,
const cbor::Value::MapValue& request_map,
const cbor::Value& pin_protocol_map_key,
const cbor::Value& pin_auth_map_key,
base::span<const uint8_t> pinauth_bytes) { … }
std::optional<cbor::Value> RpEntityAsCBOR(const PublicKeyCredentialRpEntity& rp,
bool allow_invalid_utf8) { … }
std::optional<cbor::Value> UserEntityAsCBOR(
const PublicKeyCredentialUserEntity& user,
bool user_verification,
bool allow_invalid_utf8) { … }
std::vector<uint8_t> WriteCBOR(cbor::Value value,
bool allow_invalid_utf8 = false) { … }
std::vector<uint8_t> EncodeGetAssertionResponse(
const AuthenticatorGetAssertionResponse& response,
bool allow_invalid_utf8) { … }
std::vector<uint8_t> GenerateAndEncryptToken(
PINUVAuthProtocol pin_protocol,
base::span<const uint8_t> shared_key,
base::span<uint8_t, 32> pin_token) { … }
bool CheckCredentialListForExtraKeys(
base::span<const PublicKeyCredentialDescriptor> creds) { … }
std::vector<uint8_t> EvaluateHMAC(
base::span<const uint8_t> hmac_key,
const std::array<uint8_t, 32>& hmac_salt1,
const std::optional<std::array<uint8_t, 32>>& hmac_salt2) { … }
}
VirtualCtap2Device::Config::Config() = default;
VirtualCtap2Device::Config::Config(const Config&) = default;
VirtualCtap2Device::Config& VirtualCtap2Device::Config::operator=(
const Config&) = default;
VirtualCtap2Device::Config::~Config() = default;
VirtualCtap2Device::RequestState::RequestState() = default;
VirtualCtap2Device::RequestState::~RequestState() = default;
VirtualCtap2Device::VirtualCtap2Device() { … }
VirtualCtap2Device::VirtualCtap2Device(scoped_refptr<State> state,
const Config& config)
: … { … }
VirtualCtap2Device::~VirtualCtap2Device() = default;
void VirtualCtap2Device::SetPin(std::string pin) { … }
void VirtualCtap2Device::SetForcePinChange(bool force_pin_change) { … }
void VirtualCtap2Device::SetMinPinLength(uint32_t min_pin_length) { … }
void VirtualCtap2Device::Cancel(CancelToken) { … }
FidoDevice::CancelToken VirtualCtap2Device::DeviceTransact(
std::vector<uint8_t> command,
DeviceCallback cb) { … }
base::WeakPtr<FidoDevice> VirtualCtap2Device::GetWeakPtr() { … }
void VirtualCtap2Device::Init(std::vector<ProtocolVersion> versions) { … }
std::optional<CtapDeviceResponseCode> VirtualCtap2Device::CheckUserVerification(
CheckUserVerificationMode mode,
const AuthenticatorGetInfoResponse& authenticator_info,
const std::string& rp_id,
const std::optional<std::vector<uint8_t>>& pin_auth,
const std::optional<PINUVAuthProtocol>& pin_protocol,
base::span<const uint8_t> client_data_hash,
UserVerificationRequirement user_verification,
bool user_presence_required,
bool* out_user_verified) { … }
std::optional<CtapDeviceResponseCode> VirtualCtap2Device::OnMakeCredential(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
std::optional<CtapDeviceResponseCode> VirtualCtap2Device::OnGetAssertion(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
CtapDeviceResponseCode VirtualCtap2Device::OnGetNextAssertion(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
std::optional<CtapDeviceResponseCode> VirtualCtap2Device::OnPINCommand(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
CtapDeviceResponseCode VirtualCtap2Device::OnCredentialManagement(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
CtapDeviceResponseCode VirtualCtap2Device::OnBioEnrollment(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
CtapDeviceResponseCode VirtualCtap2Device::OnLargeBlobs(
base::span<const uint8_t> request_bytes,
std::vector<uint8_t>* response) { … }
void VirtualCtap2Device::InitPendingRPs() { … }
void VirtualCtap2Device::InitPendingRegistrations(
base::span<const uint8_t> rp_id_hash) { … }
void VirtualCtap2Device::RegenerateKeyAgreementKey() { … }
void VirtualCtap2Device::GetNextRP(cbor::Value::MapValue* response_map) { … }
CtapDeviceResponseCode VirtualCtap2Device::OnAuthenticatorGetInfo(
std::vector<uint8_t>* response) const { … }
AttestedCredentialData VirtualCtap2Device::ConstructAttestedCredentialData(
base::span<const uint8_t> key_handle,
std::unique_ptr<PublicKey> public_key) { … }
size_t VirtualCtap2Device::remaining_resident_credentials() const { … }
bool VirtualCtap2Device::SupportsAtLeast(Ctap2Version ctap2_version) const { … }
}