// Copyright 2019 The Chromium OS 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 "u2fd/webauthn_handler.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/callback_helpers.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/time/time.h>
#include <chromeos/cbor/values.h>
#include <chromeos/cbor/writer.h>
#include <chromeos/dbus/service_constants.h>
#include <openssl/rand.h>
#include <u2f/proto_bindings/u2f_interface.pb.h>

#include "u2fd/u2f_command_processor_gsc.h"
#include "u2fd/util.h"

namespace u2f {

namespace {

// User a big timeout for cryptohome. See b/172945202.
constexpr base::TimeDelta kCryptohomeTimeout = base::TimeDelta::FromMinutes(2);

constexpr int kCancelUVFlowTimeoutMs = 5000;

constexpr char kAttestationFormatNone[] = "none";
// \xa0 is empty map in CBOR
constexpr char kAttestationStatementNone = '\xa0';
constexpr char kAttestationFormatU2f[] = "fido-u2f";
// Keys for attestation statement CBOR map.
constexpr char kSignatureKey[] = "sig";
constexpr char kX509CertKey[] = "x5c";

// The AAGUID for none-attestation (for platform-authenticator). For u2f/g2f
// attestation, empty AAGUID should be used.
const std::vector<uint8_t> kAaguid = {0x84, 0x03, 0x98, 0x77, 0xa5, 0x4b,
                                      0xdf, 0xbb, 0x04, 0xa8, 0x2d, 0xf2,
                                      0xfa, 0x2a, 0x11, 0x6e};

// AuthenticatorData flags are defined in
// https://www.w3.org/TR/webauthn-2/#sctn-authenticator-data
enum class AuthenticatorDataFlag : uint8_t {
  kTestOfUserPresence = 1u << 0,
  kTestOfUserVerification = 1u << 2,
  kAttestedCredentialData = 1u << 6,
  kExtensionDataIncluded = 1u << 7,
};

// Key label in cryptohome.
constexpr char kCryptohomePinLabel[] = "pin";

// Relative DBus object path for fingerprint manager in biod.
const char kCrosFpBiometricsManagerRelativePath[] = "/CrosFpBiometricsManager";

std::vector<uint8_t> Uint16ToByteVector(uint16_t value) {
  return std::vector<uint8_t>({static_cast<uint8_t>((value >> 8) & 0xff),
                               static_cast<uint8_t>(value & 0xff)});
}

void AppendToString(const std::vector<uint8_t>& vect, std::string* str) {
  str->append(reinterpret_cast<const char*>(vect.data()), vect.size());
}

void AppendAttestedCredential(const std::vector<uint8_t>& credential_id,
                              const std::vector<uint8_t>& credential_public_key,
                              std::vector<uint8_t>* authenticator_data) {
  util::AppendToVector(credential_id, authenticator_data);
  util::AppendToVector(credential_public_key, authenticator_data);
}

// Returns the current time in seconds since epoch as a privacy-preserving
// signature counter. Because of the conversion to a 32-bit unsigned integer,
// the counter will overflow in the year 2108.
std::vector<uint8_t> GetTimestampSignatureCounter() {
  uint32_t sign_counter = static_cast<uint32_t>(base::Time::Now().ToDoubleT());
  return std::vector<uint8_t>{
      static_cast<uint8_t>((sign_counter >> 24) & 0xff),
      static_cast<uint8_t>((sign_counter >> 16) & 0xff),
      static_cast<uint8_t>((sign_counter >> 8) & 0xff),
      static_cast<uint8_t>(sign_counter & 0xff),
  };
}

std::vector<uint8_t> EncodeU2fAttestationStatementInCBOR(
    const std::vector<uint8_t>& signature, const std::vector<uint8_t>& cert) {
  cbor::Value::MapValue attestation_statement_map;
  attestation_statement_map[cbor::Value(kSignatureKey)] =
      cbor::Value(signature);
  // The "x5c" field is an array of just one cert.
  std::vector<cbor::Value> certificate_array;
  certificate_array.push_back(cbor::Value(cert));
  attestation_statement_map[cbor::Value(kX509CertKey)] =
      cbor::Value(std::move(certificate_array));
  return *cbor::Writer::Write(
      cbor::Value(std::move(attestation_statement_map)));
}

}  // namespace

WebAuthnHandler::WebAuthnHandler()
    : user_state_(nullptr),
      webauthn_storage_(std::make_unique<WebAuthnStorage>()),
      u2f_command_processor_(std::unique_ptr<U2fCommandProcessor>()) {}

WebAuthnHandler::~WebAuthnHandler() {}

void WebAuthnHandler::Initialize(
    dbus::Bus* bus,
    TpmVendorCommandProxy* tpm_proxy,
    UserState* user_state,
    U2fMode u2f_mode,
    std::function<void()> request_presence,
    std::unique_ptr<AllowlistingUtil> allowlisting_util,
    MetricsLibraryInterface* metrics) {
  if (Initialized()) {
    LOG(INFO) << "WebAuthn handler already initialized, doing nothing.";
    return;
  }

  metrics_ = metrics;
  user_state_ = user_state;
  user_state_->SetSessionStartedCallback(
      base::Bind(&WebAuthnHandler::OnSessionStarted, base::Unretained(this)));
  user_state_->SetSessionStoppedCallback(
      base::Bind(&WebAuthnHandler::OnSessionStopped, base::Unretained(this)));
  u2f_mode_ = u2f_mode;
  allowlisting_util_ = std::move(allowlisting_util);
  bus_ = bus;
  auth_dialog_dbus_proxy_ = bus_->GetObjectProxy(
      chromeos::kUserAuthenticationServiceName,
      dbus::ObjectPath(chromeos::kUserAuthenticationServicePath));
  // Testing can inject a mock.
  if (!cryptohome_proxy_)
    cryptohome_proxy_ =
        std::make_unique<org::chromium::UserDataAuthInterfaceProxy>(bus_);
  DCHECK(auth_dialog_dbus_proxy_);

  u2f_command_processor_ =
      std::make_unique<U2fCommandProcessorGsc>(tpm_proxy, request_presence);

  if (user_state_->HasUser()) {
    // WebAuthnHandler should normally initialize on boot, before any user has
    // logged in. If there's already a user, then we have crashed during a user
    // session, so catch up on the state.
    base::Optional<std::string> user = user_state_->GetUser();
    DCHECK(user);
    OnSessionStarted(*user);
  }
}

bool WebAuthnHandler::Initialized() {
  return u2f_command_processor_ && user_state_;
}

bool WebAuthnHandler::AllowPresenceMode() {
  return u2f_mode_ == U2fMode::kU2f || u2f_mode_ == U2fMode::kU2fExtended;
}

void WebAuthnHandler::OnSessionStarted(const std::string& account_id) {
  // Do this first because there's a timeout for reading the secret.
  GetWebAuthnSecretHashAsync(account_id);

  webauthn_storage_->set_allow_access(true);
  base::Optional<std::string> sanitized_user = user_state_->GetSanitizedUser();
  DCHECK(sanitized_user);
  webauthn_storage_->set_sanitized_user(*sanitized_user);

  if (!webauthn_storage_->LoadRecords()) {
    LOG(ERROR) << "Did not load all records for user " << *sanitized_user;
    return;
  }
  webauthn_storage_->SendRecordCountToUMA(metrics_);
}

void WebAuthnHandler::OnSessionStopped() {
  auth_time_secret_hash_.reset();
  webauthn_storage_->Reset();
}

void WebAuthnHandler::GetWebAuthnSecretHashAsync(
    const std::string& account_id) {
  user_data_auth::GetWebAuthnSecretHashRequest request;
  request.mutable_account_id()->set_account_id(account_id);

  cryptohome_proxy_->GetWebAuthnSecretHashAsync(
      request,
      base::BindOnce(&WebAuthnHandler::OnGetWebAuthnSecretHashResp,
                     base::Unretained(this)),
      base::BindOnce(&WebAuthnHandler::OnGetWebAuthnSecretHashCallFailed,
                     base::Unretained(this)),
      kCryptohomeTimeout.InMilliseconds());
}

void WebAuthnHandler::OnGetWebAuthnSecretHashCallFailed(brillo::Error* error) {
  LOG(ERROR) << "Failed to call GetWebAuthnSecretHash on cryptohome, error: "
             << error->GetMessage();
}

void WebAuthnHandler::OnGetWebAuthnSecretHashResp(
    const user_data_auth::GetWebAuthnSecretHashReply& reply) {
  // In case there's any error, read the backup hash first.
  auth_time_secret_hash_ = webauthn_storage_->LoadAuthTimeSecretHash();

  if (reply.error() !=
      user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_NOT_SET) {
    LOG(ERROR) << "GetWebAuthnSecretHash reply has error " << reply.error();
    return;
  }

  brillo::Blob secret_hash =
      brillo::BlobFromString(reply.webauthn_secret_hash());
  if (secret_hash.size() != SHA256_DIGEST_LENGTH) {
    LOG(ERROR) << "WebAuthn auth time secret hash size is wrong.";
    return;
  }

  // Persist to daemon-store in case we crash during a user session.
  webauthn_storage_->PersistAuthTimeSecretHash(secret_hash);
  auth_time_secret_hash_ =
      std::make_unique<brillo::Blob>(std::move(secret_hash));
}

void WebAuthnHandler::MakeCredential(
    std::unique_ptr<MakeCredentialMethodResponse> method_response,
    const MakeCredentialRequest& request) {
  MakeCredentialResponse response;

  if (!Initialized()) {
    response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
    method_response->Return(response);
    return;
  }

  if (pending_uv_make_credential_session_ ||
      pending_uv_get_assertion_session_) {
    response.set_status(MakeCredentialResponse::REQUEST_PENDING);
    method_response->Return(response);
    return;
  }

  if (request.rp_id().empty()) {
    response.set_status(MakeCredentialResponse::INVALID_REQUEST);
    method_response->Return(response);
    return;
  }

  if (request.verification_type() == VerificationType::VERIFICATION_UNKNOWN) {
    response.set_status(MakeCredentialResponse::VERIFICATION_FAILED);
    method_response->Return(response);
    return;
  }

  struct MakeCredentialSession session = {
      static_cast<uint64_t>(base::Time::Now().ToTimeT()), request,
      std::move(method_response)};

  if (!AllowPresenceMode()) {
    // Upgrade UP requests to UV.
    session.request.set_verification_type(
        VerificationType::VERIFICATION_USER_VERIFICATION);
  }

  if (session.request.verification_type() ==
      VerificationType::VERIFICATION_USER_VERIFICATION) {
    dbus::MethodCall call(
        chromeos::kUserAuthenticationServiceInterface,
        chromeos::kUserAuthenticationServiceShowAuthDialogMethod);
    dbus::MessageWriter writer(&call);
    writer.AppendString(session.request.rp_id());
    writer.AppendInt32(session.request.verification_type());
    writer.AppendUint64(session.request.request_id());

    pending_uv_make_credential_session_ = std::move(session);
    auth_dialog_dbus_proxy_->CallMethod(
        &call, dbus::ObjectProxy::TIMEOUT_INFINITE,
        base::Bind(&WebAuthnHandler::HandleUVFlowResultMakeCredential,
                   base::Unretained(this)));
    return;
  }

  DoMakeCredential(std::move(session), PresenceRequirement::kPowerButton);
}

CancelWebAuthnFlowResponse WebAuthnHandler::Cancel(
    const CancelWebAuthnFlowRequest& request) {
  CancelWebAuthnFlowResponse response;
  if (!pending_uv_make_credential_session_ &&
      !pending_uv_get_assertion_session_) {
    LOG(ERROR) << "No pending session to cancel.";
    response.set_canceled(false);
    return response;
  }

  if (pending_uv_make_credential_session_ &&
      pending_uv_make_credential_session_->request.request_id() !=
          request.request_id()) {
    LOG(ERROR)
        << "MakeCredential session has a different request_id, not cancelling.";
    response.set_canceled(false);
    return response;
  }

  if (pending_uv_get_assertion_session_ &&
      pending_uv_get_assertion_session_->request.request_id() !=
          request.request_id()) {
    LOG(ERROR)
        << "GetAssertion session has a different request_id, not cancelling.";
    response.set_canceled(false);
    return response;
  }

  dbus::MethodCall call(chromeos::kUserAuthenticationServiceInterface,
                        chromeos::kUserAuthenticationServiceCancelMethod);
  std::unique_ptr<dbus::Response> cancel_ui_resp =
      auth_dialog_dbus_proxy_->CallMethodAndBlock(&call,
                                                  kCancelUVFlowTimeoutMs);

  if (!cancel_ui_resp) {
    LOG(ERROR) << "Failed to dismiss WebAuthn user verification UI.";
    response.set_canceled(false);
    return response;
  }

  // We do not reset |pending_uv_make_credential_session_| or
  // |pending_uv_get_assertion_session_| here because UI will still respond
  // to the cancelled request through these, though the response will be
  // ignored by Chrome.
  if (pending_uv_make_credential_session_) {
    pending_uv_make_credential_session_->canceled = true;
  } else {
    pending_uv_get_assertion_session_->canceled = true;
  }
  response.set_canceled(true);
  return response;
}

void WebAuthnHandler::HandleUVFlowResultMakeCredential(
    dbus::Response* flow_response) {
  MakeCredentialResponse response;

  DCHECK(pending_uv_make_credential_session_);

  if (!flow_response) {
    LOG(ERROR) << "User auth flow had no response.";
    response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
    pending_uv_make_credential_session_->response->Return(response);
    pending_uv_make_credential_session_.reset();
    return;
  }

  dbus::MessageReader response_reader(flow_response);
  bool success;
  if (!response_reader.PopBool(&success)) {
    LOG(ERROR) << "Failed to parse user auth flow result.";
    response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
    pending_uv_make_credential_session_->response->Return(response);
    pending_uv_make_credential_session_.reset();
    return;
  }

  if (!success) {
    if (pending_uv_make_credential_session_->canceled) {
      LOG(INFO) << "WebAuthn MakeCredential operation canceled.";
      response.set_status(MakeCredentialResponse::CANCELED);
    } else {
      LOG(ERROR) << "User auth flow failed. Aborting MakeCredential.";
      response.set_status(MakeCredentialResponse::VERIFICATION_FAILED);
    }
    pending_uv_make_credential_session_->response->Return(response);
    pending_uv_make_credential_session_.reset();
    return;
  }

  DoMakeCredential(std::move(*pending_uv_make_credential_session_),
                   PresenceRequirement::kNone);
  pending_uv_make_credential_session_.reset();
}

void WebAuthnHandler::HandleUVFlowResultGetAssertion(
    dbus::Response* flow_response) {
  GetAssertionResponse response;

  DCHECK(pending_uv_get_assertion_session_);

  if (!flow_response) {
    LOG(ERROR) << "User auth flow had no response.";
    response.set_status(GetAssertionResponse::INTERNAL_ERROR);
    pending_uv_get_assertion_session_->response->Return(response);
    pending_uv_get_assertion_session_.reset();
    return;
  }

  dbus::MessageReader response_reader(flow_response);
  bool success;
  if (!response_reader.PopBool(&success)) {
    LOG(ERROR) << "Failed to parse user auth flow result.";
    response.set_status(GetAssertionResponse::INTERNAL_ERROR);
    pending_uv_get_assertion_session_->response->Return(response);
    pending_uv_get_assertion_session_.reset();
    return;
  }

  if (!success) {
    if (pending_uv_get_assertion_session_->canceled) {
      LOG(INFO) << "WebAuthn GetAssertion operation canceled.";
      response.set_status(GetAssertionResponse::CANCELED);
    } else {
      LOG(ERROR) << "User auth flow failed. Aborting GetAssertion.";
      response.set_status(GetAssertionResponse::VERIFICATION_FAILED);
    }
    pending_uv_get_assertion_session_->response->Return(response);
    pending_uv_get_assertion_session_.reset();
    return;
  }

  DoGetAssertion(std::move(*pending_uv_get_assertion_session_),
                 PresenceRequirement::kAuthorizationSecret);
  pending_uv_get_assertion_session_.reset();
}

void WebAuthnHandler::DoMakeCredential(
    struct MakeCredentialSession session,
    PresenceRequirement presence_requirement) {
  MakeCredentialResponse response;
  const std::vector<uint8_t> rp_id_hash = util::Sha256(session.request.rp_id());
  std::vector<uint8_t> credential_id;
  std::vector<uint8_t> credential_public_key;

  // If we are in u2f or g2f mode, and the request says it wants presence only,
  // make a non-versioned (i.e. non-uv-compatible) credential.
  bool uv_compatible = !(AllowPresenceMode() &&
                         session.request.verification_type() ==
                             VerificationType::VERIFICATION_USER_PRESENCE);

  brillo::Blob credential_secret(kCredentialSecretSize);
  if (uv_compatible) {
    if (RAND_bytes(credential_secret.data(), credential_secret.size()) != 1) {
      LOG(ERROR) << "Failed to generate secret for new credential.";
      response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
      session.response->Return(response);
      return;
    }
  } else {
    // We are creating a credential that can only be signed with power button
    // press, and can be signed by u2f/g2f, so we must use the legacy secret.
    base::Optional<brillo::SecureBlob> legacy_secret =
        user_state_->GetUserSecret();
    if (!legacy_secret) {
      LOG(ERROR) << "Cannot find user secret when trying to create u2f/g2f "
                    "credential.";
      response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
      session.response->Return(response);
      return;
    }
    credential_secret =
        std::vector<uint8_t>(legacy_secret->begin(), legacy_secret->end());
  }

  MakeCredentialResponse::MakeCredentialStatus generate_status =
      u2f_command_processor_->U2fGenerate(
          rp_id_hash, credential_secret, presence_requirement, uv_compatible,
          auth_time_secret_hash_.get(), &credential_id, &credential_public_key);

  if (generate_status != MakeCredentialResponse::SUCCESS) {
    response.set_status(generate_status);
    session.response->Return(response);
    return;
  }

  if (credential_id.empty() || credential_public_key.empty()) {
    response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
    session.response->Return(response);
    return;
  }

  auto ret = HasExcludedCredentials(session.request);
  if (ret == HasCredentialsResponse::INTERNAL_ERROR) {
    response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
    session.response->Return(response);
    return;
  } else if (ret == HasCredentialsResponse::SUCCESS) {
    response.set_status(MakeCredentialResponse::EXCLUDED_CREDENTIAL_ID);
    session.response->Return(response);
    return;
  }

  const base::Optional<std::vector<uint8_t>> authenticator_data =
      MakeAuthenticatorData(
          rp_id_hash, credential_id, credential_public_key,
          /* user_verified = */ session.request.verification_type() ==
              VerificationType::VERIFICATION_USER_VERIFICATION,
          /* include_attested_credential_data = */ true,
          /* is_u2f_authenticator_credential = */ !uv_compatible);
  if (!authenticator_data) {
    LOG(ERROR) << "MakeAuthenticatorData failed";
    response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
    session.response->Return(response);
    return;
  }
  AppendToString(*authenticator_data, response.mutable_authenticator_data());

  // If a credential is not UV-compatible, it is a legacy U2F/G2F credential
  // and should come with U2F/G2F attestation for backward compatibility.
  if (uv_compatible) {
    AppendNoneAttestation(&response);
  } else {
    const std::vector<uint8_t> data_to_sign =
        util::BuildU2fRegisterResponseSignedData(
            rp_id_hash, util::ToVector(session.request.client_data_hash()),
            credential_public_key, credential_id);
    base::Optional<std::vector<uint8_t>> attestation_statement =
        MakeFidoU2fAttestationStatement(
            data_to_sign, session.request.attestation_conveyance_preference());
    if (!attestation_statement) {
      response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
      session.response->Return(response);
      return;
    }
    response.set_attestation_format(kAttestationFormatU2f);
    AppendToString(*attestation_statement,
                   response.mutable_attestation_statement());
  }

  // u2f/g2f credentials should not be written to record.
  if (uv_compatible) {
    // All steps succeeded, so write to record.
    WebAuthnRecord record;
    AppendToString(credential_id, &record.credential_id);
    record.secret = std::move(credential_secret);
    record.rp_id = session.request.rp_id();
    record.rp_display_name = session.request.rp_display_name();
    record.user_id = session.request.user_id();
    record.user_display_name = session.request.user_display_name();
    record.timestamp = base::Time::Now().ToDoubleT();
    record.is_resident_key = session.request.resident_key_required();
    if (!webauthn_storage_->WriteRecord(std::move(record))) {
      response.set_status(MakeCredentialResponse::INTERNAL_ERROR);
      session.response->Return(response);
      return;
    }
  }

  response.set_status(MakeCredentialResponse::SUCCESS);
  session.response->Return(response);
}

// AuthenticatorData layout:
// (See https://www.w3.org/TR/webauthn-2/#table-authData)
// -----------------------------------------------------------------------
// | RP ID hash:       32 bytes
// | Flags:             1 byte
// | Signature counter: 4 bytes
// |                           -------------------------------------------
// |                           | AAGUID:                  16 bytes
// | Attested Credential Data: | Credential ID length (L): 2 bytes
// | (if present)              | Credential ID:            L bytes
// |                           | Credential public key:    variable length
base::Optional<std::vector<uint8_t>> WebAuthnHandler::MakeAuthenticatorData(
    const std::vector<uint8_t>& rp_id_hash,
    const std::vector<uint8_t>& credential_id,
    const std::vector<uint8_t>& credential_public_key,
    bool user_verified,
    bool include_attested_credential_data,
    bool is_u2f_authenticator_credential) {
  std::vector<uint8_t> authenticator_data(rp_id_hash);
  uint8_t flags =
      static_cast<uint8_t>(AuthenticatorDataFlag::kTestOfUserPresence);
  if (user_verified)
    flags |=
        static_cast<uint8_t>(AuthenticatorDataFlag::kTestOfUserVerification);
  if (include_attested_credential_data)
    flags |=
        static_cast<uint8_t>(AuthenticatorDataFlag::kAttestedCredentialData);
  authenticator_data.emplace_back(flags);

  // The U2F authenticator keeps a user-global signature counter in UserState.
  // For platform authenticator credentials, we derive a counter from a
  // timestamp instead.
  if (is_u2f_authenticator_credential) {
    base::Optional<std::vector<uint8_t>> counter = user_state_->GetCounter();
    if (!counter || !user_state_->IncrementCounter()) {
      // UserState logs an error in this case.
      return base::nullopt;
    }
    util::AppendToVector(*counter, &authenticator_data);
  } else {
    util::AppendToVector(GetTimestampSignatureCounter(), &authenticator_data);
  }

  if (include_attested_credential_data) {
    util::AppendToVector(is_u2f_authenticator_credential
                             ? std::vector<uint8_t>(kAaguid.size(), 0)
                             : kAaguid,
                         &authenticator_data);
    uint16_t length = credential_id.size();
    util::AppendToVector(Uint16ToByteVector(length), &authenticator_data);

    AppendAttestedCredential(credential_id, credential_public_key,
                             &authenticator_data);
  }

  return authenticator_data;
}

void WebAuthnHandler::AppendNoneAttestation(MakeCredentialResponse* response) {
  response->set_attestation_format(kAttestationFormatNone);
  response->mutable_attestation_statement()->push_back(
      kAttestationStatementNone);
}

base::Optional<std::vector<uint8_t>>
WebAuthnHandler::MakeFidoU2fAttestationStatement(
    const std::vector<uint8_t>& data_to_sign,
    const MakeCredentialRequest::AttestationConveyancePreference
        attestation_conveyance_preference) {
  std::vector<uint8_t> attestation_cert;
  std::vector<uint8_t> signature;
  if (attestation_conveyance_preference == MakeCredentialRequest::G2F &&
      u2f_mode_ == U2fMode::kU2fExtended) {
    base::Optional<std::vector<uint8_t>> g2f_cert =
        u2f_command_processor_->GetG2fCert();
    if (g2f_cert.has_value()) {
      attestation_cert = *g2f_cert;
    } else {
      LOG(ERROR) << "Failed to get G2f cert for MakeCredential";
      return base::nullopt;
    }

    base::Optional<brillo::SecureBlob> user_secret =
        user_state_->GetUserSecret();
    if (!user_secret.has_value()) {
      LOG(ERROR) << "No user secret.";
      return base::nullopt;
    }

    MakeCredentialResponse::MakeCredentialStatus attest_status =
        u2f_command_processor_->G2fAttest(
            data_to_sign, *user_secret, U2F_ATTEST_FORMAT_REG_RESP, &signature);

    if (attest_status != MakeCredentialResponse::SUCCESS) {
      LOG(ERROR) << "Failed to do G2f attestation for MakeCredential";
      return base::nullopt;
    }

    if (allowlisting_util_ != nullptr &&
        !allowlisting_util_->AppendDataToCert(&attestation_cert)) {
      LOG(ERROR) << "Failed to get allowlisting data for G2F Enroll Request";
      return base::nullopt;
    }
  } else {
    if (!util::DoSoftwareAttest(data_to_sign, &attestation_cert, &signature)) {
      LOG(ERROR) << "Failed to do software attestation for MakeCredential";
      return base::nullopt;
    }
  }

  return EncodeU2fAttestationStatementInCBOR(signature, attestation_cert);
}

HasCredentialsResponse::HasCredentialsStatus
WebAuthnHandler::HasExcludedCredentials(const MakeCredentialRequest& request) {
  MatchedCredentials matched =
      FindMatchedCredentials(request.excluded_credential_id(), request.rp_id(),
                             request.app_id_exclude());
  if (matched.has_internal_error) {
    return HasCredentialsResponse::INTERNAL_ERROR;
  }

  if (matched.platform_credentials.empty() &&
      matched.legacy_credentials_for_rp_id.empty() &&
      matched.legacy_credentials_for_app_id.empty()) {
    return HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID;
  }
  return HasCredentialsResponse::SUCCESS;
}

void WebAuthnHandler::GetAssertion(
    std::unique_ptr<GetAssertionMethodResponse> method_response,
    const GetAssertionRequest& request) {
  GetAssertionResponse response;

  if (!Initialized()) {
    response.set_status(GetAssertionResponse::INTERNAL_ERROR);
    method_response->Return(response);
    return;
  }

  if (pending_uv_make_credential_session_ ||
      pending_uv_get_assertion_session_) {
    response.set_status(GetAssertionResponse::REQUEST_PENDING);
    method_response->Return(response);
    return;
  }

  if (request.rp_id().empty() ||
      request.client_data_hash().size() != SHA256_DIGEST_LENGTH) {
    response.set_status(GetAssertionResponse::INVALID_REQUEST);
    method_response->Return(response);
    return;
  }

  if (request.verification_type() == VerificationType::VERIFICATION_UNKNOWN) {
    response.set_status(GetAssertionResponse::VERIFICATION_FAILED);
    method_response->Return(response);
    return;
  }

  // TODO(louiscollard): Support resident credentials.

  std::string* credential_to_use;
  bool is_legacy_credential = false;
  bool use_app_id = false;

  MatchedCredentials matched = FindMatchedCredentials(
      request.allowed_credential_id(), request.rp_id(), request.app_id());
  if (matched.has_internal_error) {
    response.set_status(GetAssertionResponse::INTERNAL_ERROR);
    method_response->Return(response);
    return;
  }

  if (!matched.platform_credentials.empty()) {
    credential_to_use = &matched.platform_credentials[0];
  } else if (!matched.legacy_credentials_for_rp_id.empty()) {
    credential_to_use = &matched.legacy_credentials_for_rp_id[0];
    is_legacy_credential = true;
  } else if (!matched.legacy_credentials_for_app_id.empty()) {
    credential_to_use = &matched.legacy_credentials_for_app_id[0];
    is_legacy_credential = true;
    use_app_id = true;
  } else {
    response.set_status(GetAssertionResponse::UNKNOWN_CREDENTIAL_ID);
    method_response->Return(response);
    return;
  }

  struct GetAssertionSession session = {
      static_cast<uint64_t>(base::Time::Now().ToTimeT()), request,
      *credential_to_use, std::move(method_response)};
  if (use_app_id) {
    // App id was matched instead of rp id, so discard rp id.
    session.request.set_rp_id(request.app_id());
  }

  if (!AllowPresenceMode()) {
    // Upgrade UP requests to UV.
    session.request.set_verification_type(
        VerificationType::VERIFICATION_USER_VERIFICATION);
  }

  // Legacy credentials should go through power button, not UV.
  if (session.request.verification_type() ==
          VerificationType::VERIFICATION_USER_VERIFICATION &&
      !is_legacy_credential) {
    dbus::MethodCall call(
        chromeos::kUserAuthenticationServiceInterface,
        chromeos::kUserAuthenticationServiceShowAuthDialogMethod);
    dbus::MessageWriter writer(&call);
    writer.AppendString(session.request.rp_id());
    writer.AppendInt32(session.request.verification_type());
    writer.AppendUint64(session.request.request_id());

    pending_uv_get_assertion_session_ = std::move(session);
    auth_dialog_dbus_proxy_->CallMethod(
        &call, dbus::ObjectProxy::TIMEOUT_INFINITE,
        base::Bind(&WebAuthnHandler::HandleUVFlowResultGetAssertion,
                   base::Unretained(this)));
    return;
  }

  DoGetAssertion(std::move(session), PresenceRequirement::kPowerButton);
}

// If already seeing failure, then no need to get user secret. This means
// in the fingerprint case, this signal should ideally come from UI instead of
// biod because only UI knows about retry.
void WebAuthnHandler::DoGetAssertion(struct GetAssertionSession session,
                                     PresenceRequirement presence_requirement) {
  GetAssertionResponse response;

  bool is_u2f_authenticator_credential = false;
  base::Optional<std::vector<uint8_t>> credential_secret =
      webauthn_storage_->GetSecretByCredentialId(session.credential_id);
  if (!credential_secret) {
    if (!AllowPresenceMode()) {
      LOG(ERROR) << "No credential secret for credential id "
                 << session.credential_id << ", aborting GetAssertion.";
      response.set_status(GetAssertionResponse::UNKNOWN_CREDENTIAL_ID);
      session.response->Return(response);
      return;
    }

    // Maybe signing u2fhid credentials. Use legacy secret instead.
    base::Optional<brillo::SecureBlob> legacy_secret =
        user_state_->GetUserSecret();
    if (!legacy_secret) {
      LOG(ERROR)
          << "Cannot find user secret when trying to sign u2fhid credentials";
      response.set_status(GetAssertionResponse::INTERNAL_ERROR);
      session.response->Return(response);
      return;
    }
    credential_secret =
        std::vector<uint8_t>(legacy_secret->begin(), legacy_secret->end());
    is_u2f_authenticator_credential = true;
  }

  const std::vector<uint8_t> rp_id_hash = util::Sha256(session.request.rp_id());
  const base::Optional<std::vector<uint8_t>> authenticator_data =
      MakeAuthenticatorData(
          rp_id_hash, std::vector<uint8_t>(), std::vector<uint8_t>(),
          // If presence requirement is "power button" then the user was not
          // verified. Otherwise the user was verified through UI.
          /* user_verified = */ presence_requirement !=
              PresenceRequirement::kPowerButton,
          /* include_attested_credential_data = */ false,
          is_u2f_authenticator_credential);
  if (!authenticator_data) {
    LOG(ERROR) << "MakeAuthenticatorData failed";
    response.set_status(GetAssertionResponse::INTERNAL_ERROR);
    session.response->Return(response);
    return;
  }

  std::vector<uint8_t> data_to_sign(*authenticator_data);
  util::AppendToVector(session.request.client_data_hash(), &data_to_sign);
  std::vector<uint8_t> hash_to_sign = util::Sha256(data_to_sign);

  std::vector<uint8_t> signature;
  GetAssertionResponse::GetAssertionStatus sign_status =
      u2f_command_processor_->U2fSign(
          rp_id_hash, hash_to_sign, util::ToVector(session.credential_id),
          *credential_secret, presence_requirement, &signature);
  response.set_status(sign_status);
  if (sign_status == GetAssertionResponse::SUCCESS) {
    auto* assertion = response.add_assertion();
    assertion->set_credential_id(session.credential_id);
    AppendToString(*authenticator_data,
                   assertion->mutable_authenticator_data());
    AppendToString(signature, assertion->mutable_signature());
  }

  session.response->Return(response);
}

MatchedCredentials WebAuthnHandler::FindMatchedCredentials(
    const RepeatedPtrField<std::string>& all_credentials,
    const std::string& rp_id,
    const std::string& app_id) {
  std::vector<uint8_t> rp_id_hash = util::Sha256(rp_id);
  std::vector<uint8_t> app_id_hash = util::Sha256(app_id);
  MatchedCredentials result;

  // Platform authenticator credentials.
  for (const auto& credential_id : all_credentials) {
    base::Optional<std::vector<uint8_t>> credential_secret =
        webauthn_storage_->GetSecretByCredentialId(credential_id);
    if (!credential_secret)
      continue;

    auto ret = u2f_command_processor_->U2fSignCheckOnly(
        rp_id_hash, util::ToVector(credential_id), *credential_secret);
    if (ret == HasCredentialsResponse::INTERNAL_ERROR) {
      result.has_internal_error = true;
      return result;
    } else if (ret == HasCredentialsResponse::SUCCESS) {
      result.platform_credentials.emplace_back(credential_id);
    }
  }

  const base::Optional<brillo::SecureBlob> user_secret =
      user_state_->GetUserSecret();
  if (!user_secret) {
    result.has_internal_error = true;
    return result;
  }

  // Legacy credentials. If a legacy credential matches both rp_id and app_id,
  // it will only appear in result.legacy_credentials_for_rp_id.
  for (const auto& credential_id : all_credentials) {
    // First try matching rp_id.
    HasCredentialsResponse::HasCredentialsStatus ret =
        u2f_command_processor_->U2fSignCheckOnly(
            rp_id_hash, util::ToVector(credential_id),
            std::vector<uint8_t>(user_secret->begin(), user_secret->end()));
    DCHECK(HasCredentialsResponse::HasCredentialsStatus_IsValid(ret));
    switch (ret) {
      case HasCredentialsResponse::SUCCESS:
        // rp_id matched, it's a credential registered with u2fhid on WebAuthn
        // API.
        result.legacy_credentials_for_rp_id.emplace_back(credential_id);
        continue;
      case HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID:
        break;
      case HasCredentialsResponse::UNKNOWN:
      case HasCredentialsResponse::INVALID_REQUEST:
      case HasCredentialsResponse::INTERNAL_ERROR:
        result.has_internal_error = true;
        return result;
      case google::protobuf::kint32min:
      case google::protobuf::kint32max:
        NOTREACHED();
    }

    // Try matching app_id.
    ret = u2f_command_processor_->U2fSignCheckOnly(
        app_id_hash, util::ToVector(credential_id),
        std::vector<uint8_t>(user_secret->begin(), user_secret->end()));
    DCHECK(HasCredentialsResponse::HasCredentialsStatus_IsValid(ret));
    switch (ret) {
      case HasCredentialsResponse::SUCCESS:
        // App id extension matched. It's a legacy credential registered with
        // the U2F interface.
        result.legacy_credentials_for_app_id.emplace_back(credential_id);
        continue;
      case HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID:
        break;
      case HasCredentialsResponse::UNKNOWN:
      case HasCredentialsResponse::INVALID_REQUEST:
      case HasCredentialsResponse::INTERNAL_ERROR:
        result.has_internal_error = true;
        return result;
      case google::protobuf::kint32min:
      case google::protobuf::kint32max:
        NOTREACHED();
    }
  }

  return result;
}

HasCredentialsResponse WebAuthnHandler::HasCredentials(
    const HasCredentialsRequest& request) {
  HasCredentialsResponse response;

  if (!Initialized()) {
    response.set_status(HasCredentialsResponse::INTERNAL_ERROR);
    return response;
  }

  if (request.rp_id().empty() || request.credential_id().empty()) {
    response.set_status(HasCredentialsResponse::INVALID_REQUEST);
    return response;
  }

  MatchedCredentials matched = FindMatchedCredentials(
      request.credential_id(), request.rp_id(), request.app_id());
  if (matched.has_internal_error) {
    response.set_status(HasCredentialsResponse::INTERNAL_ERROR);
    return response;
  }

  for (const auto& credential_id : matched.platform_credentials) {
    *response.add_credential_id() = credential_id;
  }
  for (const auto& credential_id : matched.legacy_credentials_for_rp_id) {
    *response.add_credential_id() = credential_id;
  }
  for (const auto& credential_id : matched.legacy_credentials_for_app_id) {
    *response.add_credential_id() = credential_id;
  }

  response.set_status((response.credential_id_size() > 0)
                          ? HasCredentialsResponse::SUCCESS
                          : HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID);
  return response;
}

HasCredentialsResponse WebAuthnHandler::HasLegacyCredentials(
    const HasCredentialsRequest& request) {
  HasCredentialsResponse response;

  if (!Initialized()) {
    response.set_status(HasCredentialsResponse::INTERNAL_ERROR);
    return response;
  }

  if (request.credential_id().empty()) {
    response.set_status(HasCredentialsResponse::INVALID_REQUEST);
    return response;
  }

  MatchedCredentials matched = FindMatchedCredentials(
      request.credential_id(), request.rp_id(), request.app_id());
  if (matched.has_internal_error) {
    response.set_status(HasCredentialsResponse::INTERNAL_ERROR);
    return response;
  }

  // Do not include platform credentials.
  for (const auto& credential_id : matched.legacy_credentials_for_rp_id) {
    *response.add_credential_id() = credential_id;
  }
  for (const auto& credential_id : matched.legacy_credentials_for_app_id) {
    *response.add_credential_id() = credential_id;
  }

  response.set_status((response.credential_id_size() > 0)
                          ? HasCredentialsResponse::SUCCESS
                          : HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID);
  return response;
}

IsU2fEnabledResponse WebAuthnHandler::IsU2fEnabled(
    const IsU2fEnabledRequest& request) {
  IsU2fEnabledResponse response;
  response.set_enabled(AllowPresenceMode());
  return response;
}

void WebAuthnHandler::IsUvpaa(
    std::unique_ptr<IsUvpaaMethodResponse> method_response,
    const IsUvpaaRequest& request) {
  // Checking with the authentication dialog (in Ash) will not work, because
  // currently in Chrome the IsUvpaa is a blocking call, and Ash can't respond
  // to us since it runs in the same process as Chrome. After the Chrome side
  // is refactored to take a callback or Ash is split into a separate binary,
  // we can change the implementation here to query with Ash.

  IsUvpaaResponse response;

  if (!Initialized()) {
    LOG(INFO) << "IsUvpaa called but WebAuthnHandler not initialized. Maybe "
                 "U2F is on.";
    response.set_available(false);
    method_response->Return(response);
    return;
  }

  if (!auth_time_secret_hash_) {
    LOG(ERROR) << "No auth-time secret hash. MakeCredential will fail, so "
                  "reporting IsUVPAA=false.";
    response.set_available(false);
    method_response->Return(response);
    return;
  }

  base::Optional<std::string> account_id = user_state_->GetUser();
  if (!account_id) {
    LOG(ERROR) << "IsUvpaa called but no user.";
    response.set_available(false);
    method_response->Return(response);
    return;
  }

  if (HasPin(*account_id)) {
    response.set_available(true);
    method_response->Return(response);
    return;
  }

  base::Optional<std::string> sanitized_user = user_state_->GetSanitizedUser();
  DCHECK(sanitized_user);
  if (HasFingerprint(*sanitized_user)) {
    response.set_available(true);
    method_response->Return(response);
    return;
  }

  response.set_available(false);
  method_response->Return(response);
}

bool WebAuthnHandler::HasPin(const std::string& account_id) {
  user_data_auth::GetKeyDataRequest request;
  request.mutable_account_id()->set_account_id(account_id);
  // Touch mutable_authorization_request() so that has_authorization_request()
  // would return true.
  request.mutable_authorization_request();
  request.mutable_key()->mutable_data()->set_label(kCryptohomePinLabel);

  user_data_auth::GetKeyDataReply reply;
  brillo::ErrorPtr error;

  if (!cryptohome_proxy_->GetKeyData(request, &reply, &error,
                                     kCryptohomeTimeout.InMilliseconds())) {
    LOG(ERROR) << "Cannot query PIN availability from cryptohome, error: "
               << error->GetMessage();
    return false;
  }

  if (reply.error() !=
      user_data_auth::CryptohomeErrorCode::CRYPTOHOME_ERROR_NOT_SET) {
    LOG(ERROR) << "GetKeyData response has error " << reply.error();
    return false;
  }

  return reply.key_data_size() > 0;
}

bool WebAuthnHandler::HasFingerprint(const std::string& sanitized_user) {
  dbus::ObjectProxy* biod_proxy = bus_->GetObjectProxy(
      biod::kBiodServiceName,
      dbus::ObjectPath(std::string(biod::kBiodServicePath)
                           .append(kCrosFpBiometricsManagerRelativePath)));

  dbus::MethodCall method_call(biod::kBiometricsManagerInterface,
                               biod::kBiometricsManagerGetRecordsForUserMethod);
  dbus::MessageWriter method_writer(&method_call);
  method_writer.AppendString(sanitized_user);

  std::unique_ptr<dbus::Response> response = biod_proxy->CallMethodAndBlock(
      &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
  if (!response) {
    LOG(ERROR)
        << "Cannot check fingerprint availability: no response from biod.";
    return false;
  }

  dbus::MessageReader response_reader(response.get());
  dbus::MessageReader records_reader(nullptr);
  if (!response_reader.PopArray(&records_reader)) {
    LOG(ERROR) << "Cannot parse GetRecordsForUser response from biod.";
    return false;
  }

  int records_count = 0;
  while (records_reader.HasMoreData()) {
    dbus::ObjectPath record_path;
    if (!records_reader.PopObjectPath(&record_path)) {
      LOG(WARNING) << "Cannot parse fingerprint record path";
      continue;
    }
    records_count++;
  }
  return records_count > 0;
}

void WebAuthnHandler::SetWebAuthnStorageForTesting(
    std::unique_ptr<WebAuthnStorage> storage) {
  webauthn_storage_ = std::move(storage);
}

void WebAuthnHandler::SetCryptohomeInterfaceProxyForTesting(
    std::unique_ptr<org::chromium::UserDataAuthInterfaceProxyInterface>
        cryptohome_proxy) {
  cryptohome_proxy_ = std::move(cryptohome_proxy);
}

void WebAuthnHandler::SetU2fCommandProcessorForTesting(
    std::unique_ptr<U2fCommandProcessor> helper) {
  u2f_command_processor_ = std::move(helper);
}

}  // namespace u2f
