// Copyright 2020 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 <regex>  // NOLINT(build/c++11)
#include <string>
#include <utility>
#include <vector>

#include <base/check.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/dbus/mock_dbus_method_response.h>
#include <chromeos/cbor/values.h>
#include <chromeos/cbor/writer.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/bus.h>
#include <dbus/mock_bus.h>
#include <dbus/mock_object_proxy.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <metrics/metrics_library_mock.h>
#include <user_data_auth-client-test/user_data_auth/dbus-proxy-mocks.h>

#include "u2fd/mock_allowlisting_util.h"
#include "u2fd/mock_u2f_command_processor.h"
#include "u2fd/mock_user_state.h"
#include "u2fd/mock_webauthn_storage.h"
#include "u2fd/util.h"

namespace u2f {
namespace {

using ::brillo::dbus_utils::MockDBusMethodResponse;

using ::testing::_;
using ::testing::DoAll;
using ::testing::Matcher;
using ::testing::MatchesRegex;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SetArgPointee;
using ::testing::StrictMock;
using ::testing::Unused;

// Dummy User State.
constexpr char kUserSecret[65] = {[0 ... 63] = 'E', '\0'};
constexpr char kCredentialSecret[65] = {[0 ... 63] = 'F', '\0'};
// Dummy RP id.
constexpr char kRpId[] = "example.com";
// Wrong RP id is used to test app id extension path.
constexpr char kWrongRpId[] = "wrong.com";

// // Dummy cr50 U2F_SIGN_RESP.
const struct u2f_sign_resp kU2fSignResponse = {.sig_r = {[0 ... 31] = 0x12},
                                               .sig_s = {[0 ... 31] = 0x34}};

// AuthenticatorData field sizes, in bytes.
constexpr int kRpIdHashBytes = 32;
constexpr int kAuthenticatorDataFlagBytes = 1;
constexpr int kSignatureCounterBytes = 4;
constexpr int kAaguidBytes = 16;
constexpr int kCredentialIdLengthBytes = 2;

std::vector<uint8_t> GetAuthTimeSecretHash() {
  return std::vector<uint8_t>(32, 0x12);
}

std::vector<uint8_t> GetRpIdHash() {
  return util::Sha256(std::string(kRpId));
}

std::vector<uint8_t> GetWrongRpIdHash() {
  return util::Sha256(std::string(kWrongRpId));
}

std::vector<uint8_t> GetCorrectUserSecret() {
  return std::vector<uint8_t>(32, '\xee');
}

std::string GetClientDataHash() {
  return std::string(SHA256_DIGEST_LENGTH, 0xcd);
}

// // AAGUID for none attestation.
std::vector<uint8_t> GetAaguid() {
  return std::vector<uint8_t>{0x84, 0x03, 0x98, 0x77, 0xa5, 0x4b, 0xdf, 0xbb,
                              0x04, 0xa8, 0x2d, 0xf2, 0xfa, 0x2a, 0x11, 0x6e};
}

std::vector<uint8_t> GetCredId() {
  return std::vector<uint8_t>(64, 0xFD);
}

std::vector<uint8_t> GetVersionedCredId() {
  return std::vector<uint8_t>(145, 0xFD);
}

std::string GetCredIdString() {
  auto cred_id = GetCredId();
  return std::string(cred_id.begin(), cred_id.end());
}

std::string GetVersionedCredIdString() {
  auto cred_id = GetVersionedCredId();
  return std::string(cred_id.begin(), cred_id.end());
}

std::vector<uint8_t> GetCredPubKey() {
  return std::vector<uint8_t>(65, 0xAB);
}

std::vector<uint8_t> GetSignature() {
  return *util::SignatureToDerBytes(kU2fSignResponse.sig_r,
                                    kU2fSignResponse.sig_s);
}

brillo::SecureBlob ArrayToSecureBlob(const char* array) {
  brillo::SecureBlob blob;
  CHECK(brillo::SecureBlob::HexStringToSecureBlob(array, &blob));
  return blob;
}

brillo::Blob HexArrayToBlob(const char* array) {
  brillo::Blob blob;
  CHECK(base::HexStringToBytes(array, &blob));
  return blob;
}

}  // namespace

// The base test fixture tests behaviors seen by general consumers. It
// disallows presence-only mode, because U2F isn't offered to general
// consumers.
class WebAuthnHandlerTestBase : public ::testing::Test {
 public:
  void SetUp() override {
    PrepareMockBus();
    CreateHandler(U2fMode::kDisabled, /*allowlisting_util=*/nullptr);
    PrepareMockStorage();
    // We use per-credential secret instead of the old user secret.
    ExpectNoGetUserSecret();
  }

 protected:
  void PrepareMockBus() {
    dbus::Bus::Options options;
    options.bus_type = dbus::Bus::SYSTEM;
    mock_bus_ = new dbus::MockBus(options);

    mock_auth_dialog_proxy_ = new dbus::MockObjectProxy(
        mock_bus_.get(), chromeos::kUserAuthenticationServiceName,
        dbus::ObjectPath(chromeos::kUserAuthenticationServicePath));

    // Set an expectation so that the MockBus will return our mock proxy.
    EXPECT_CALL(*mock_bus_,
                GetObjectProxy(
                    chromeos::kUserAuthenticationServiceName,
                    dbus::ObjectPath(chromeos::kUserAuthenticationServicePath)))
        .WillOnce(Return(mock_auth_dialog_proxy_.get()));
  }

  void CreateHandler(U2fMode u2f_mode,
                     std::unique_ptr<AllowlistingUtil> allowlisting_util) {
    handler_ = std::make_unique<WebAuthnHandler>();
    PrepareMockCryptohome();
    handler_->Initialize(
        mock_bus_.get(), /*tpm_proxy=*/nullptr, &mock_user_state_, u2f_mode,
        /*request_presence=*/[]() {}, std::move(allowlisting_util),
        &mock_metrics_);
    auto mock_processor = std::make_unique<MockU2fCommandProcessor>();
    mock_processor_ = mock_processor.get();
    handler_->SetU2fCommandProcessorForTesting(std::move(mock_processor));
  }

  void PrepareMockCryptohome() {
    auto mock_cryptohome_proxy =
        std::make_unique<org::chromium::UserDataAuthInterfaceProxyMock>();
    mock_cryptohome_proxy_ = mock_cryptohome_proxy.get();
    handler_->SetCryptohomeInterfaceProxyForTesting(
        std::move(mock_cryptohome_proxy));
  }

  void PrepareMockStorage() {
    auto mock_storage = std::make_unique<MockWebAuthnStorage>();
    mock_webauthn_storage_ = mock_storage.get();
    handler_->SetWebAuthnStorageForTesting(std::move(mock_storage));
    mock_webauthn_storage_->set_allow_access(true);
  }

  void ExpectUVFlowSuccess() {
    mock_auth_dialog_response_ = dbus::Response::CreateEmpty();
    dbus::Response* response = mock_auth_dialog_response_.get();
    dbus::MessageWriter writer(response);
    writer.AppendBool(true);
    EXPECT_CALL(*mock_auth_dialog_proxy_, DoCallMethod(_, _, _))
        .WillOnce(
            [response](Unused, Unused,
                       base::OnceCallback<void(dbus::Response*)>* callback) {
              std::move(*callback).Run(response);
            });
  }

  void ExpectNoGetUserSecret() {
    EXPECT_CALL(mock_user_state_, GetUserSecret()).Times(0);
  }

  void ExpectGetUserSecret() { ExpectGetUserSecretForTimes(1); }

  void ExpectGetUserSecretForTimes(int times) {
    EXPECT_CALL(mock_user_state_, GetUserSecret())
        .Times(times)
        .WillRepeatedly(Return(ArrayToSecureBlob(kUserSecret)));
  }

  void ExpectGetCounter() {
    static const std::vector<uint8_t> kSignatureCounter({42, 23, 42, 23});
    EXPECT_CALL(mock_user_state_, GetCounter())
        .WillOnce(Return(kSignatureCounter));
  }

  void ExpectIncrementCounter() {
    EXPECT_CALL(mock_user_state_, IncrementCounter()).WillOnce(Return(true));
  }

  std::vector<uint8_t> MakeAuthenticatorData(
      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) {
    base::Optional<std::vector<uint8_t>> authenticator_data =
        handler_->MakeAuthenticatorData(
            GetRpIdHash(), credential_id, credential_public_key, user_verified,
            include_attested_credential_data, is_u2f_authenticator_credential);
    DCHECK(authenticator_data);
    return *authenticator_data;
  }

  // Set up an auth-time secret hash as if a user has logged in.
  void SetUpAuthTimeSecretHash() {
    handler_->auth_time_secret_hash_ =
        std::make_unique<brillo::Blob>(GetAuthTimeSecretHash());
  }

  StrictMock<MockUserState> mock_user_state_;

  std::unique_ptr<WebAuthnHandler> handler_;
  MockWebAuthnStorage* mock_webauthn_storage_;
  MockU2fCommandProcessor* mock_processor_;

 private:
  scoped_refptr<dbus::MockBus> mock_bus_;
  scoped_refptr<dbus::MockObjectProxy> mock_auth_dialog_proxy_;
  std::unique_ptr<dbus::Response> mock_auth_dialog_response_;
  org::chromium::UserDataAuthInterfaceProxyMock* mock_cryptohome_proxy_;
  testing::NiceMock<MetricsLibraryMock> mock_metrics_;
};

namespace {

TEST_F(WebAuthnHandlerTestBase, MakeCredentialUninitialized) {
  // Use an uninitialized WebAuthnHandler object.
  handler_.reset(new WebAuthnHandler());
  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const MakeCredentialResponse& resp) {
        EXPECT_EQ(resp.status(), MakeCredentialResponse::INTERNAL_ERROR);
        *called_ptr = true;
      },
      &called));

  MakeCredentialRequest request;
  handler_->MakeCredential(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, MakeCredentialEmptyRpId) {
  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const MakeCredentialResponse& resp) {
        EXPECT_EQ(resp.status(), MakeCredentialResponse::INVALID_REQUEST);
        *called_ptr = true;
      },
      &called));

  MakeCredentialRequest request;
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);
  handler_->MakeCredential(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, MakeCredentialNoAuthTimeSecretHash) {
  MakeCredentialRequest request;
  request.set_rp_id(kRpId);
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  ExpectUVFlowSuccess();
  EXPECT_CALL(*mock_processor_,
              U2fGenerate(GetRpIdHash(), _, PresenceRequirement::kNone, true,
                          nullptr, _, _))
      .WillRepeatedly(Return(MakeCredentialResponse::INTERNAL_ERROR));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const MakeCredentialResponse& resp) {
        EXPECT_EQ(resp.status(), MakeCredentialResponse::INTERNAL_ERROR);
        *called_ptr = true;
      },
      &called));

  handler_->MakeCredential(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, MakeCredentialUPUpgradedToUV) {
  MakeCredentialRequest request;
  request.set_rp_id(kRpId);
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  // Though it's going to be UV, we will still check if any exclude credential
  // matches legacy credentials.
  ExpectGetUserSecret();
  ExpectUVFlowSuccess();
  SetUpAuthTimeSecretHash();
  EXPECT_CALL(*mock_processor_,
              U2fGenerate(GetRpIdHash(), _, PresenceRequirement::kNone, true,
                          Pointee(GetAuthTimeSecretHash()), _, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetVersionedCredId()),
                      SetArgPointee<6>(GetCredPubKey()),
                      Return(MakeCredentialResponse::SUCCESS)));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  handler_->MakeCredential(std::move(mock_method_response), request);
}

TEST_F(WebAuthnHandlerTestBase, MakeCredentialVerificationSuccess) {
  MakeCredentialRequest request;
  request.set_rp_id(kRpId);
  request.set_verification_type(
      VerificationType::VERIFICATION_USER_VERIFICATION);

  // Thought it's going to be UV, we will still check if any exclude credential
  // matches legacy credentials.
  ExpectGetUserSecret();
  ExpectUVFlowSuccess();

  SetUpAuthTimeSecretHash();
  EXPECT_CALL(*mock_processor_,
              U2fGenerate(GetRpIdHash(), _, PresenceRequirement::kNone, true,
                          Pointee(GetAuthTimeSecretHash()), _, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetVersionedCredId()),
                      SetArgPointee<6>(GetCredPubKey()),
                      Return(MakeCredentialResponse::SUCCESS)));
  // TODO(yichengli): Specify the parameter to WriteRecord.
  EXPECT_CALL(*mock_webauthn_storage_, WriteRecord(_)).WillOnce(Return(true));

  auto rp_id_hash = GetRpIdHash();
  auto aaguid = GetAaguid();

  const std::string expected_authenticator_data_regex =
      base::HexEncode(rp_id_hash.data(),
                      rp_id_hash.size()) +  // RP ID hash
      std::string(
          "45"          // Flag: user present, user verified, attested
                        // credential data included.
          "(..){4}") +  // Signature counter
      base::HexEncode(aaguid.data(), aaguid.size()) +  // AAGUID
      std::string(
          "0091"      // Credential ID length
                      // Credential ID, from kU2fGenerateVersionedResponse:
          "(FD){65}"  // Versioned key handle header
          "(FD){16}"  // Authorization salt
          "(FD){32}"  // Hash of authorization secret
          "(FD){32}"  // Authorization hmac
                      // CBOR encoded credential public key:
          "(AB){65}");

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const std::string& expected_authenticator_data,
         const MakeCredentialResponse& resp) {
        EXPECT_EQ(resp.status(), MakeCredentialResponse::SUCCESS);
        EXPECT_THAT(base::HexEncode(resp.authenticator_data().data(),
                                    resp.authenticator_data().size()),
                    MatchesRegex(expected_authenticator_data));
        EXPECT_EQ(resp.attestation_format(), "none");
        EXPECT_EQ(resp.attestation_statement(), "\xa0");
        *called_ptr = true;
      },
      &called, expected_authenticator_data_regex));

  handler_->MakeCredential(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, GetAssertionUninitialized) {
  // Use an uninitialized WebAuthnHandler object.
  handler_.reset(new WebAuthnHandler());
  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::INTERNAL_ERROR);
        *called_ptr = true;
      },
      &called));

  GetAssertionRequest request;
  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, GetAssertionEmptyRpId) {
  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::INVALID_REQUEST);
        *called_ptr = true;
      },
      &called));

  GetAssertionRequest request;
  request.set_client_data_hash(GetClientDataHash());
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);
  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, GetAssertionWrongClientDataHashLength) {
  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::INVALID_REQUEST);
        *called_ptr = true;
      },
      &called));

  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(std::string(SHA256_DIGEST_LENGTH - 1, 0xcd));
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);
  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

// Simulates the case where the KH doesn't match any record in daemon-store, or
// any legacy credential id.
TEST_F(WebAuthnHandlerTestBase, GetAssertionNoCredentialSecret) {
  GetAssertionRequest request;
  request.set_rp_id(kWrongRpId);
  request.set_app_id(kWrongRpId);
  request.set_client_data_hash(GetClientDataHash());
  request.add_allowed_credential_id(GetCredIdString());
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .WillOnce(Return(base::nullopt));
  ExpectGetUserSecret();

  // We will check for legacy credentials, so two check-only calls to TPM.
  EXPECT_CALL(
      *mock_processor_,
      U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), GetCorrectUserSecret()))
      .Times(2)
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::UNKNOWN_CREDENTIAL_ID);
        *called_ptr = true;
      },
      &called));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

// Simulates the case where the KH matches a record in daemon-store but is not
// recognized by cr50. This is not very likely in reality unless daemon-store is
// compromised.
TEST_F(WebAuthnHandlerTestBase, GetAssertionInvalidKeyHandle) {
  GetAssertionRequest request;
  request.set_rp_id(kWrongRpId);
  request.set_app_id(kWrongRpId);
  request.set_client_data_hash(GetClientDataHash());
  request.add_allowed_credential_id(GetCredIdString());
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .WillOnce(Return(HexArrayToBlob(kCredentialSecret)));
  ExpectGetUserSecret();
  // 3 calls to SignCheckOnly, one for each credential type.
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), _))
      .Times(3)
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::UNKNOWN_CREDENTIAL_ID);
        *called_ptr = true;
      },
      &called));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, GetAssertionUPUpgradedToUV) {
  // Needed for "InsertAuthTimeSecretHash" workaround.
  SetUpAuthTimeSecretHash();

  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());
  request.add_allowed_credential_id(GetVersionedCredIdString());

  request.set_verification_type(
      VerificationType::VERIFICATION_USER_VERIFICATION);

  // Pass DoU2fSignCheckOnly so that we can get to UV flow.
  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetVersionedCredIdString()))
      .WillRepeatedly(Return(HexArrayToBlob(kCredentialSecret)));
  ExpectGetUserSecret();

  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               HexArrayToBlob(kCredentialSecret)))
      .WillRepeatedly(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(_, GetVersionedCredId(), GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetVersionedCredId(),
                      HexArrayToBlob(kCredentialSecret),
                      PresenceRequirement::kAuthorizationSecret, _))
      .WillOnce(Return(GetAssertionResponse::SUCCESS));

  ExpectUVFlowSuccess();

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  handler_->GetAssertion(std::move(mock_method_response), request);
}

TEST_F(WebAuthnHandlerTestBase, GetAssertionVerificationSuccess) {
  // Needed for "InsertAuthTimeSecretHash" workaround.
  SetUpAuthTimeSecretHash();

  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());

  request.add_allowed_credential_id(GetVersionedCredIdString());

  request.set_verification_type(
      VerificationType::VERIFICATION_USER_VERIFICATION);

  ExpectUVFlowSuccess();

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetVersionedCredIdString()))
      .WillRepeatedly(Return(HexArrayToBlob(kCredentialSecret)));

  ExpectGetUserSecret();

  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               HexArrayToBlob(kCredentialSecret)))
      .WillRepeatedly(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(_, GetVersionedCredId(), GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetVersionedCredId(),
                      HexArrayToBlob(kCredentialSecret),
                      PresenceRequirement::kAuthorizationSecret, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetSignature()),
                      Return(GetAssertionResponse::SUCCESS)));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const std::string& expected_credential_id,
         const GetAssertionResponse& resp) {
        auto rp_id_hash = GetRpIdHash();
        EXPECT_EQ(resp.status(), GetAssertionResponse::SUCCESS);
        ASSERT_EQ(resp.assertion_size(), 1);
        auto assertion = resp.assertion(0);
        EXPECT_EQ(assertion.credential_id(), expected_credential_id);
        EXPECT_THAT(
            base::HexEncode(assertion.authenticator_data().data(),
                            assertion.authenticator_data().size()),
            MatchesRegex(base::HexEncode(rp_id_hash.data(),
                                         rp_id_hash.size()) +  // RP ID hash
                         std::string("05"  // Flag: user present, user verified
                                     "(..){4}")));  // Signature counter
        EXPECT_EQ(util::ToVector(assertion.signature()),
                  util::SignatureToDerBytes(kU2fSignResponse.sig_r,
                                            kU2fSignResponse.sig_s));
        *called_ptr = true;
      },
      &called, GetVersionedCredIdString()));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestBase, HasCredentialsNoMatch) {
  HasCredentialsRequest request;
  request.set_rp_id(kWrongRpId);
  request.set_app_id(kWrongRpId);
  request.add_credential_id(GetCredIdString());
  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .WillRepeatedly(Return(base::nullopt));
  ExpectGetUserSecret();

  EXPECT_CALL(
      *mock_processor_,
      U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), GetCorrectUserSecret()))
      .Times(2)
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto resp = handler_->HasCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 0);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID);
}

// Match first of the 3 types of credentials, i.e. a credential generated by the
// platform authenticator with a versioned key handle.
TEST_F(WebAuthnHandlerTestBase, HasCredentialsMatchPlatformAuthenticator) {
  HasCredentialsRequest request;
  request.set_rp_id(kRpId);
  request.set_app_id(kRpId);
  request.add_credential_id(GetVersionedCredIdString());

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetVersionedCredIdString()))
      .WillOnce(Return(HexArrayToBlob(kCredentialSecret)));
  ExpectGetUserSecret();

  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               HexArrayToBlob(kCredentialSecret)))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               GetCorrectUserSecret()))
      .Times(2)
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto resp = handler_->HasCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

// Match second of the 3 types of credentials: a legacy u2f credential created
// by WebAuthnHandler, scoped to an RP ID.
TEST_F(WebAuthnHandlerTestBase, HasCredentialsMatchU2fhidWebAuthn) {
  HasCredentialsRequest request;
  request.set_rp_id(kRpId);
  request.add_credential_id(GetCredIdString());

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .WillOnce(Return(base::nullopt));
  ExpectGetUserSecret();
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));

  auto resp = handler_->HasCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

// Match third of the 3 types of credentials: a legacy credential created by
// u2fhid, scoped to an App ID.
TEST_F(WebAuthnHandlerTestBase, HasCredentialsMatchAppId) {
  HasCredentialsRequest request;
  request.set_rp_id(kWrongRpId);
  request.set_app_id(kRpId);
  request.add_credential_id(GetCredIdString());

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .WillOnce(Return(base::nullopt));
  ExpectGetUserSecret();
  // Matching rp_id fails.
  EXPECT_CALL(
      *mock_processor_,
      U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  // Matching app_id succeeds.
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));

  auto resp = handler_->HasCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

TEST_F(WebAuthnHandlerTestBase, HasCredentialsSomeMatches) {
  // Test that HasCredentials with a mix of correct and wrong length credential
  // IDs succeeds.
  HasCredentialsRequest request;
  request.set_rp_id(kRpId);
  request.set_app_id(kRpId);
  request.add_credential_id(GetVersionedCredIdString());
  std::vector<uint8_t> unknown_credential_id(U2F_V0_KH_SIZE + 1, 0xab);
  std::string unknown_credential_id_string(unknown_credential_id.begin(),
                                           unknown_credential_id.end());
  request.add_credential_id(unknown_credential_id_string);

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetVersionedCredIdString()))
      .WillOnce(Return(HexArrayToBlob(kCredentialSecret)));
  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(unknown_credential_id_string))
      .WillOnce(Return(base::nullopt));
  ExpectGetUserSecret();

  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               HexArrayToBlob(kCredentialSecret)))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), unknown_credential_id,
                               GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto resp = handler_->HasCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.credential_id()[0], GetVersionedCredIdString());
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

TEST_F(WebAuthnHandlerTestBase, HasLegacyCredentialsNoMatch) {
  HasCredentialsRequest request;
  request.set_rp_id(kWrongRpId);
  request.set_app_id(kWrongRpId);
  request.add_credential_id(GetCredIdString());

  ExpectGetUserSecret();
  EXPECT_CALL(
      *mock_processor_,
      U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), GetCorrectUserSecret()))
      .Times(2)
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto resp = handler_->HasLegacyCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 0);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID);
}

// Match second of the 3 types of credentials.
// If rp_id matches, it's a legacy credential registered with u2fhid on WebAuthn
// API.
TEST_F(WebAuthnHandlerTestBase, HasLegacyCredentialsMatchU2fhidWebAuthn) {
  HasCredentialsRequest request;
  request.set_rp_id(kRpId);
  request.add_credential_id(GetCredIdString());

  ExpectGetUserSecret();
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));

  auto resp = handler_->HasLegacyCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

// Match third of the 3 types of credentials.
// If app_id matches, it's a legacy credential registered with U2F API.
TEST_F(WebAuthnHandlerTestBase, HasLegacyCredentialsMatchAppId) {
  HasCredentialsRequest request;
  request.set_rp_id(kWrongRpId);
  request.set_app_id(kRpId);
  request.add_credential_id(GetCredIdString());

  ExpectGetUserSecret();
  // Matching rp_id fails.
  EXPECT_CALL(
      *mock_processor_,
      U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  // Matching app_id succeeds.
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));

  auto resp = handler_->HasLegacyCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

TEST_F(WebAuthnHandlerTestBase, HasLegacyCredentialsSomeMatches) {
  // Test that HasLegacyCredentials with a mix of correct and wrong length
  // credential IDs succeeds.
  HasCredentialsRequest request;
  request.set_rp_id(kRpId);
  request.set_app_id(kRpId);
  request.add_credential_id(GetCredIdString());
  std::vector<uint8_t> unknown_credential_id(U2F_V0_KH_SIZE + 1, 0xab);
  std::string unknown_credential_id_string(unknown_credential_id.begin(),
                                           unknown_credential_id.end());
  request.add_credential_id(unknown_credential_id_string);

  ExpectGetUserSecret();
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), unknown_credential_id,
                               GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));

  auto resp = handler_->HasLegacyCredentials(request);
  EXPECT_EQ(resp.credential_id_size(), 1);
  EXPECT_EQ(resp.credential_id()[0], GetCredIdString());
  EXPECT_EQ(resp.status(), HasCredentialsResponse::SUCCESS);
}

TEST_F(WebAuthnHandlerTestBase, MakeAuthenticatorDataWithAttestedCredData) {
  const std::vector<uint8_t> cred_id(64, 0xAA);
  const std::vector<uint8_t> cred_pubkey(65, 0xBB);

  std::vector<uint8_t> authenticator_data =
      MakeAuthenticatorData(cred_id, cred_pubkey, /* user_verified = */
                            false,
                            /* include_attested_credential_data = */ true,
                            /* is_u2f_authenticator_credential = */ false);
  EXPECT_EQ(authenticator_data.size(),
            kRpIdHashBytes + kAuthenticatorDataFlagBytes +
                kSignatureCounterBytes + kAaguidBytes +
                kCredentialIdLengthBytes + cred_id.size() + cred_pubkey.size());
  auto rp_id_hash = GetRpIdHash();
  auto aaguid = GetAaguid();
  const std::string rp_id_hash_hex =
      base::HexEncode(rp_id_hash.data(), rp_id_hash.size());
  const std::string expected_authenticator_data_regex =
      rp_id_hash_hex +  // RP ID hash
      std::string(
          "41"          // Flag: user present, attested credential data included
          "(..){4}") +  // Signature counter
      base::HexEncode(aaguid.data(), aaguid.size()) +  // AAGUID
      std::string(
          "0040"        // Credential ID length
          "(AA){64}"    // Credential ID
          "(BB){65}");  // Credential public key
  EXPECT_THAT(
      base::HexEncode(authenticator_data.data(), authenticator_data.size()),
      MatchesRegex(expected_authenticator_data_regex));
}

TEST_F(WebAuthnHandlerTestBase, MakeAuthenticatorDataNoAttestedCredData) {
  std::vector<uint8_t> authenticator_data =
      MakeAuthenticatorData(std::vector<uint8_t>(), std::vector<uint8_t>(),
                            /* user_verified = */ false,
                            /* include_attested_credential_data = */ false,
                            /* is_u2f_authenticator_credential = */ false);
  EXPECT_EQ(
      authenticator_data.size(),
      kRpIdHashBytes + kAuthenticatorDataFlagBytes + kSignatureCounterBytes);
  auto rp_id_hash = GetRpIdHash();
  const std::string rp_id_hash_hex =
      base::HexEncode(rp_id_hash.data(), rp_id_hash.size());
  const std::string expected_authenticator_data_regex =
      rp_id_hash_hex +  // RP ID hash
      std::string(
          "01"         // Flag: user present
          "(..){4}");  // Signature counter
  EXPECT_THAT(
      base::HexEncode(authenticator_data.data(), authenticator_data.size()),
      MatchesRegex(expected_authenticator_data_regex));
}

TEST_F(WebAuthnHandlerTestBase,
       MakeAuthenticatorDataU2fAuthenticatorCredential) {
  // For U2F authenticator credentials only, the counter comes from UserState.
  ExpectGetCounter();
  ExpectIncrementCounter();

  std::vector<uint8_t> authenticator_data =
      MakeAuthenticatorData(std::vector<uint8_t>(), std::vector<uint8_t>(),
                            /* user_verified = */ false,
                            /* include_attested_credential_data = */ false,
                            /* is_u2f_authenticator_credential = */ true);

  EXPECT_EQ(
      base::HexEncode(authenticator_data),
      base::HexEncode(GetRpIdHash()) +
          std::string("01"           // Flag: user present
                      "2A172A17"));  // kSignatureCounter in network byte order
}

}  // namespace

// This test fixture tests the behavior when u2f is enabled on the device.
class WebAuthnHandlerTestU2fMode : public WebAuthnHandlerTestBase {
 public:
  void SetUp() override {
    PrepareMockBus();
    CreateHandler(U2fMode::kU2f, /*allowlisting_util=*/nullptr);
    PrepareMockStorage();
  }
};

namespace {

TEST_F(WebAuthnHandlerTestU2fMode, MakeCredentialPresenceSuccess) {
  MakeCredentialRequest request;
  request.set_rp_id(kRpId);
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  ExpectGetCounter();
  ExpectIncrementCounter();

  // 1. LegacyCredential uses "user secret" instead of per credential secret.
  // 2. We will still check if any exclude credential matches legacy
  // credentials.
  ExpectGetUserSecretForTimes(2);
  SetUpAuthTimeSecretHash();
  EXPECT_CALL(*mock_processor_,
              U2fGenerate(GetRpIdHash(), GetCorrectUserSecret(),
                          PresenceRequirement::kPowerButton, false,
                          Pointee(GetAuthTimeSecretHash()), _, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetCredId()),
                      SetArgPointee<6>(GetCredPubKey()),
                      Return(MakeCredentialResponse::SUCCESS)));

  // Since this creates a legacy credential with legacy secret, we won't write
  // to storage.
  EXPECT_CALL(*mock_webauthn_storage_, WriteRecord(_)).Times(0);

  const std::string expected_authenticator_data_regex =
      base::HexEncode(GetRpIdHash()) +
      std::string(
          "41"        // Flag: user present, attested credential data included
          "2A172A17"  // kSignatureCounter in network byte order
          "(00){16}"  // AAGUID
          "0040"      // Credential ID length
                      // Credential ID, from kU2fGenerateResponse:
          "(FD){64}"  // (non-versioned) key handle
                      // CBOR encoded credential public key:
          "(AB){65}");

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const std::string& expected_authenticator_data,
         const MakeCredentialResponse& resp) {
        EXPECT_EQ(resp.status(), MakeCredentialResponse::SUCCESS);
        EXPECT_THAT(base::HexEncode(resp.authenticator_data().data(),
                                    resp.authenticator_data().size()),
                    MatchesRegex(expected_authenticator_data));
        EXPECT_EQ(resp.attestation_format(), "fido-u2f");
        const std::string expected_attestation_statement =
            "A2"      // Start a CBOR map of 2 elements
            "63"      // Start CBOR text of 3 chars
            "736967"  // "sig"
            ".+"      // Random signature
            "63"      // Start CBOR text of 3 chars
            "783563"  // "x5c"
            "81"      // Start CBOR array of 1 element
            ".+";     // Random x509
        EXPECT_THAT(base::HexEncode(resp.attestation_statement().data(),
                                    resp.attestation_statement().size()),
                    MatchesRegex(expected_attestation_statement));
        *called_ptr = true;
      },
      &called, expected_authenticator_data_regex));

  handler_->MakeCredential(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestU2fMode, GetAssertionSignLegacyCredentialNoPresence) {
  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());
  request.add_allowed_credential_id(GetCredIdString());
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  ExpectGetCounter();
  ExpectIncrementCounter();

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .Times(2)
      .WillRepeatedly(Return(base::nullopt));
  // LegacyCredential uses "user secret" instead of per credential secret.
  ExpectGetUserSecretForTimes(2);

  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetCredId(), GetCorrectUserSecret(),
                      PresenceRequirement::kPowerButton, _))
      .WillOnce(Return(GetAssertionResponse::VERIFICATION_FAILED));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::VERIFICATION_FAILED);
        *called_ptr = true;
      },
      &called));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestU2fMode, GetAssertionSignLegacyCredentialSuccess) {
  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());
  request.add_allowed_credential_id(GetCredIdString());
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  ExpectGetCounter();
  ExpectIncrementCounter();

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .Times(2)
      .WillRepeatedly(Return(base::nullopt));
  // LegacyCredential uses "user secret" instead of per credential secret.
  ExpectGetUserSecretForTimes(2);
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetCredId(), GetCorrectUserSecret(),
                      PresenceRequirement::kPowerButton, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetSignature()),
                      Return(GetAssertionResponse::SUCCESS)));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::SUCCESS);
        ASSERT_EQ(resp.assertion_size(), 1);
        auto assertion = resp.assertion(0);
        EXPECT_EQ(assertion.credential_id(), GetCredIdString());
        EXPECT_EQ(
            base::HexEncode(assertion.authenticator_data().data(),
                            assertion.authenticator_data().size()),
            base::HexEncode(GetRpIdHash()) +
                std::string(
                    "01"           // Flag: user present
                    "2A172A17"));  // kSignatureCounter in network byte order
        EXPECT_EQ(util::ToVector(assertion.signature()),
                  util::SignatureToDerBytes(kU2fSignResponse.sig_r,
                                            kU2fSignResponse.sig_s));
        *called_ptr = true;
      },
      &called));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestU2fMode, GetAssertionSignLegacyCredentialAppIdMatch) {
  GetAssertionRequest request;
  request.set_rp_id(kWrongRpId);
  // Legacy credentials registered via U2F interface use the app id.
  request.set_app_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());
  request.add_allowed_credential_id(GetCredIdString());
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);

  ExpectGetCounter();
  ExpectIncrementCounter();

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .Times(2)
      .WillRepeatedly(Return(base::nullopt));
  // LegacyCredential uses "user secret" instead of per credential secret.
  ExpectGetUserSecretForTimes(2);

  // Rp id doesn't match.
  EXPECT_CALL(
      *mock_processor_,
      U2fSignCheckOnly(GetWrongRpIdHash(), GetCredId(), GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  // App id matches.
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetCredId(), GetCorrectUserSecret(),
                      PresenceRequirement::kPowerButton, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetSignature()),
                      Return(GetAssertionResponse::SUCCESS)));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const GetAssertionResponse& resp) {
        EXPECT_EQ(resp.status(), GetAssertionResponse::SUCCESS);
        ASSERT_EQ(resp.assertion_size(), 1);
        auto assertion = resp.assertion(0);
        EXPECT_EQ(assertion.credential_id(), GetCredIdString());
        EXPECT_EQ(
            base::HexEncode(assertion.authenticator_data().data(),
                            assertion.authenticator_data().size()),
            base::HexEncode(GetRpIdHash()) +
                std::string(
                    "01"           // Flag: user present
                    "2A172A17"));  // kSignatureCounter in network byte order
        EXPECT_EQ(util::ToVector(assertion.signature()),
                  util::SignatureToDerBytes(kU2fSignResponse.sig_r,
                                            kU2fSignResponse.sig_s));
        *called_ptr = true;
      },
      &called));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestU2fMode,
       GetAssertionSignVersionedCredentialInUVMode) {
  // Needed for "InsertAuthTimeSecretHash" workaround.
  SetUpAuthTimeSecretHash();

  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());

  request.add_allowed_credential_id(GetVersionedCredIdString());

  request.set_verification_type(
      VerificationType::VERIFICATION_USER_VERIFICATION);

  ExpectUVFlowSuccess();

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetVersionedCredIdString()))
      .WillRepeatedly(Return(HexArrayToBlob(kCredentialSecret)));
  ExpectGetUserSecret();
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               HexArrayToBlob(kCredentialSecret)))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(_, GetVersionedCredId(), GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetVersionedCredId(),
                      HexArrayToBlob(kCredentialSecret),
                      PresenceRequirement::kAuthorizationSecret, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetSignature()),
                      Return(GetAssertionResponse::SUCCESS)));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const std::string& expected_credential_id,
         const GetAssertionResponse& resp) {
        auto rp_id_hash = GetRpIdHash();
        EXPECT_EQ(resp.status(), GetAssertionResponse::SUCCESS);
        ASSERT_EQ(resp.assertion_size(), 1);
        auto assertion = resp.assertion(0);
        EXPECT_EQ(assertion.credential_id(), expected_credential_id);
        EXPECT_THAT(
            base::HexEncode(assertion.authenticator_data().data(),
                            assertion.authenticator_data().size()),
            MatchesRegex(base::HexEncode(rp_id_hash.data(),
                                         rp_id_hash.size()) +  // RP ID hash
                         std::string("05"  // Flag: user present, user verified
                                     "(..){4}")));  // Signature counter
        EXPECT_EQ(util::ToVector(assertion.signature()),
                  util::SignatureToDerBytes(kU2fSignResponse.sig_r,
                                            kU2fSignResponse.sig_s));
        *called_ptr = true;
      },
      &called, GetVersionedCredIdString()));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

TEST_F(WebAuthnHandlerTestU2fMode,
       GetAssertionWithTwoTypesOfAllowedCredentials) {
  // Needed for "InsertAuthTimeSecretHash" workaround.
  SetUpAuthTimeSecretHash();

  GetAssertionRequest request;
  request.set_rp_id(kRpId);
  request.set_client_data_hash(GetClientDataHash());
  // Add a U2F credential to the allow list first.
  request.add_allowed_credential_id(GetCredIdString());
  // Add a platform credential (second type).
  request.add_allowed_credential_id(GetVersionedCredIdString());
  request.set_verification_type(
      VerificationType::VERIFICATION_USER_VERIFICATION);

  ExpectUVFlowSuccess();

  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetVersionedCredIdString()))
      .WillRepeatedly(Return(HexArrayToBlob(kCredentialSecret)));
  EXPECT_CALL(*mock_webauthn_storage_,
              GetSecretByCredentialId(GetCredIdString()))
      .WillRepeatedly(Return(base::nullopt));
  ExpectGetUserSecret();
  // Both credentials should pass U2fSignCheckOnly, but only the platform
  // credential should go through U2fSign.
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(GetRpIdHash(), GetVersionedCredId(),
                               HexArrayToBlob(kCredentialSecret)))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));
  EXPECT_CALL(*mock_processor_,
              U2fSignCheckOnly(_, GetVersionedCredId(), GetCorrectUserSecret()))
      .WillRepeatedly(Return(HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID));
  EXPECT_CALL(*mock_processor_, U2fSignCheckOnly(GetRpIdHash(), GetCredId(),
                                                 GetCorrectUserSecret()))
      .WillOnce(Return(HasCredentialsResponse::SUCCESS));

  EXPECT_CALL(*mock_processor_,
              U2fSign(GetRpIdHash(), _, GetVersionedCredId(),
                      HexArrayToBlob(kCredentialSecret),
                      PresenceRequirement::kAuthorizationSecret, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetSignature()),
                      Return(GetAssertionResponse::SUCCESS)));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<GetAssertionResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const std::string& expected_credential_id,
         const GetAssertionResponse& resp) {
        auto rp_id_hash = GetRpIdHash();
        EXPECT_EQ(resp.status(), GetAssertionResponse::SUCCESS);
        ASSERT_EQ(resp.assertion_size(), 1);
        auto assertion = resp.assertion(0);
        EXPECT_EQ(assertion.credential_id(), expected_credential_id);
        EXPECT_THAT(
            base::HexEncode(assertion.authenticator_data().data(),
                            assertion.authenticator_data().size()),
            MatchesRegex(base::HexEncode(rp_id_hash.data(),
                                         rp_id_hash.size()) +  // RP ID hash
                         std::string("05"  // Flag: user present, user verified
                                     "(..){4}")));  // Signature counter
        EXPECT_EQ(util::ToVector(assertion.signature()),
                  util::SignatureToDerBytes(kU2fSignResponse.sig_r,
                                            kU2fSignResponse.sig_s));
        *called_ptr = true;
      },
      // The platform credential should appear in the assertion even though it
      // comes second in the allowed credential list.
      &called, GetVersionedCredIdString()));

  handler_->GetAssertion(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

}  // namespace

// This test fixture tests the behavior when g2f is enabled on the device.
class WebAuthnHandlerTestG2fMode : public WebAuthnHandlerTestU2fMode {
 public:
  void SetUp() override {
    PrepareMockBus();
    mock_allowlisting_util_ = new StrictMock<MockAllowlistingUtil>();
    CreateHandler(U2fMode::kU2fExtended,
                  std::unique_ptr<AllowlistingUtil>(mock_allowlisting_util_));
    PrepareMockStorage();
  }

 protected:
  StrictMock<MockAllowlistingUtil>* mock_allowlisting_util_;  // Not Owned.
};

namespace {

// Example of a cert that would be returned by cr50.
constexpr char kDummyG2fCert[] =
    "308201363081DDA0030201020210442D32429223D041240350303716EE6B300A06082A8648"
    "CE3D040302300F310D300B06035504031304637235303022180F3230303030313031303030"
    "3030305A180F32303939313233313233353935395A300F310D300B06035504031304637235"
    "303059301306072A8648CE3D020106082A8648CE3D030107034200045165719A9975F6FD30"
    "CC2516C22FE841F65F9D2EE7B8B72F76807AEBD8CA3376005C7FA86453E4B10DB7BFAD5D2B"
    "D00DB4A7C4845AD06D686ACD0252387618ECA31730153013060B2B0601040182E51C020101"
    "040403020308300A06082A8648CE3D0403020348003045022100F09976F373920FEF8205C4"
    "B1FB1DA21EB9F3F176B7DF433A1ADE0F3F38B721960220179D9B9051BFCCCC90BA6BB42B86"
    "111D7A9C4FB56DFD39FB426081DD027AD609";

std::vector<uint8_t> GetDummyG2fCert() {
  std::vector<uint8_t> cert;
  base::HexStringToBytes(kDummyG2fCert, &cert);
  return cert;
}

TEST_F(WebAuthnHandlerTestG2fMode, MakeCredentialPresenceSuccess) {
  MakeCredentialRequest request;
  request.set_rp_id(kRpId);
  request.set_verification_type(VerificationType::VERIFICATION_USER_PRESENCE);
  request.set_attestation_conveyance_preference(MakeCredentialRequest::G2F);

  ExpectGetCounter();
  ExpectIncrementCounter();

  // We will need user secret 3 times:
  // first time for u2f_generate (legacy credential),
  // second time for g2f attestation command,
  // third time for checking if any exclude credential matches legacy
  // credentials.
  ExpectGetUserSecretForTimes(3);
  SetUpAuthTimeSecretHash();
  EXPECT_CALL(*mock_processor_,
              U2fGenerate(GetRpIdHash(), _, PresenceRequirement::kPowerButton,
                          false, Pointee(GetAuthTimeSecretHash()), _, _))
      .WillOnce(DoAll(SetArgPointee<5>(GetCredId()),
                      SetArgPointee<6>(GetCredPubKey()),
                      Return(MakeCredentialResponse::SUCCESS)));

  // Since this creates a legacy credential with legacy secret, we won't write
  // to storage.
  EXPECT_CALL(*mock_webauthn_storage_, WriteRecord(_)).Times(0);

  // G2f attestation mock.
  EXPECT_CALL(*mock_processor_, GetG2fCert())
      .WillOnce(Return(GetDummyG2fCert()));
  EXPECT_CALL(*mock_processor_, G2fAttest(_, _, _, _))
      .WillOnce(Return(MakeCredentialResponse::SUCCESS));
  EXPECT_CALL(*mock_allowlisting_util_, AppendDataToCert(_))
      .WillOnce(Return(true));

  auto mock_method_response =
      std::make_unique<MockDBusMethodResponse<MakeCredentialResponse>>();
  bool called = false;
  mock_method_response->set_return_callback(base::Bind(
      [](bool* called_ptr, const MakeCredentialResponse& resp) {
        EXPECT_EQ(resp.status(), MakeCredentialResponse::SUCCESS);
        EXPECT_EQ(resp.attestation_format(), "fido-u2f");
        const std::string expected_attestation_statement =
            "A2"      // Start a CBOR map of 2 elements
            "63"      // Start CBOR text of 3 chars
            "736967"  // "sig"
            ".+"      // Random signature
            "63"      // Start CBOR text of 3 chars
            "783563"  // "x5c"
            "81"      // Start CBOR array of 1 element
            ".+";     // Random x509
        EXPECT_THAT(base::HexEncode(resp.attestation_statement().data(),
                                    resp.attestation_statement().size()),
                    MatchesRegex(expected_attestation_statement));
        *called_ptr = true;
      },
      &called));

  handler_->MakeCredential(std::move(mock_method_response), request);
  ASSERT_TRUE(called);
}

}  // namespace
}  // namespace u2f
