// 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/time/time.h>
#include <chromeos/cbor/values.h>
#include <chromeos/cbor/writer.h>
#include <u2f/proto_bindings/u2f_interface.pb.h>

#include "u2fd/util.h"

namespace u2f {

namespace {

constexpr int kVerificationTimeoutMs = 10000;
constexpr int kVerificationRetryDelayUs = 500 * 1000;

// Cr50 Response codes.
// TODO(louiscollard): Don't duplicate these.
constexpr uint32_t kCr50StatusNotAllowed = 0x507;

constexpr char kAttestationFormatNone[] = "none";
// \xa0 is empty map in CBOR
constexpr char kAttestationStatementNone = '\xa0';

// AAGUID should be empty for none-attestation.
const std::vector<uint8_t> kAaguid(16);

// 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,
};

// COSE key parameters.
// https://tools.ietf.org/html/rfc8152#section-7.1
const int kCoseKeyKtyLabel = 1;
const int kCoseKeyKtyEC2 = 2;
const int kCoseKeyAlgLabel = 3;
const int kCoseKeyAlgES256 = -7;

// Double coordinate curve parameters.
// https://tools.ietf.org/html/rfc8152#section-13.1.1
const int kCoseECKeyCrvLabel = -1;
const int kCoseECKeyXLabel = -2;
const int kCoseECKeyYLabel = -3;

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> EncodeCredentialPublicKeyInCBOR(
    const std::vector<uint8_t>& credential_public_key) {
  DCHECK_EQ(credential_public_key.size(), sizeof(struct u2f_ec_point));
  cbor::Value::MapValue cbor_map;
  cbor_map[cbor::Value(kCoseKeyKtyLabel)] = cbor::Value(kCoseKeyKtyEC2);
  cbor_map[cbor::Value(kCoseKeyAlgLabel)] = cbor::Value(kCoseKeyAlgES256);
  cbor_map[cbor::Value(kCoseECKeyCrvLabel)] = cbor::Value(1);
  cbor_map[cbor::Value(kCoseECKeyXLabel)] =
      cbor::Value(base::make_span<const uint8_t>(
          credential_public_key.data() + offsetof(struct u2f_ec_point, x),
          U2F_EC_KEY_SIZE));
  cbor_map[cbor::Value(kCoseECKeyYLabel)] =
      cbor::Value(base::make_span<const uint8_t>(
          credential_public_key.data() + offsetof(struct u2f_ec_point, y),
          U2F_EC_KEY_SIZE));
  return *cbor::Writer::Write(cbor::Value(std::move(cbor_map)));
}

}  // namespace

WebAuthnHandler::WebAuthnHandler()
    : tpm_proxy_(nullptr), user_state_(nullptr) {}

void WebAuthnHandler::Initialize(TpmVendorCommandProxy* tpm_proxy,
                                 UserState* user_state,
                                 std::function<void()> request_presence) {
  tpm_proxy_ = tpm_proxy;
  user_state_ = user_state;
  request_presence_ = request_presence;
}

bool WebAuthnHandler::Initialized() {
  return tpm_proxy_ != nullptr && user_state_ != nullptr;
}

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 (request.rp_id().empty()) {
    response.set_status(MakeCredentialResponse::INVALID_REQUEST);
    method_response->Return(response);
    return;
  }

  if (request.verification_type() !=
      VerificationType::VERIFICATION_USER_PRESENCE) {
    // TODO(yichengli): Add support for VERIFICATION_USER_VERIFICATION
    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)};
  DoMakeCredential(std::move(session), PresenceRequirement::kPowerButton);
}

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;

  MakeCredentialResponse::MakeCredentialStatus generate_status = DoU2fGenerate(
      rp_id_hash, presence_requirement, &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);
  } else if (ret == HasCredentialsResponse::SUCCESS) {
    response.set_status(MakeCredentialResponse::EXCLUDED_CREDENTIAL_ID);
    session.response_->Return(response);
  }

  AppendToString(MakeAuthenticatorData(
                     rp_id_hash, credential_id,
                     EncodeCredentialPublicKeyInCBOR(credential_public_key),
                     session.request_.verification_type() ==
                         VerificationType::VERIFICATION_USER_VERIFICATION,
                     true),
                 response.mutable_authenticator_data());
  AppendNoneAttestation(&response);

  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
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) {
  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);
  util::AppendToVector(GetTimestampSignatureCounter(), &authenticator_data);

  if (include_attested_credential_data) {
    util::AppendToVector(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);
}

void WebAuthnHandler::CallAndWaitForPresence(std::function<uint32_t()> fn,
                                             uint32_t* status) {
  *status = fn();
  base::TimeTicks verification_start = base::TimeTicks::Now();
  while (*status == kCr50StatusNotAllowed &&
         base::TimeTicks::Now() - verification_start <
             base::TimeDelta::FromMilliseconds(kVerificationTimeoutMs)) {
    // We need user presence. Show a notification requesting it, and try again.
    request_presence_();
    usleep(kVerificationRetryDelayUs);
    *status = fn();
  }
}

MakeCredentialResponse::MakeCredentialStatus WebAuthnHandler::DoU2fGenerate(
    const std::vector<uint8_t>& rp_id_hash,
    PresenceRequirement presence_requirement,
    std::vector<uint8_t>* credential_id,
    std::vector<uint8_t>* credential_public_key) {
  DCHECK(rp_id_hash.size() == SHA256_DIGEST_LENGTH);
  base::Optional<brillo::SecureBlob> user_secret = user_state_->GetUserSecret();
  if (!user_secret.has_value()) {
    return MakeCredentialResponse::INTERNAL_ERROR;
  }

  if (presence_requirement != PresenceRequirement::kPowerButton) {
    // TODO(yichengli): Add support for requiring fingerprint GPIO active.
    return MakeCredentialResponse::INTERNAL_ERROR;
  }

  struct u2f_generate_req generate_req = {
      .flags = U2F_AUTH_ENFORCE  // Require user presence, consume.
  };
  util::VectorToObject(rp_id_hash, generate_req.appId);
  util::VectorToObject(*user_secret, generate_req.userSecret);

  struct u2f_generate_resp generate_resp = {};

  uint32_t generate_status = -1;
  base::AutoLock(tpm_proxy_->GetLock());
  CallAndWaitForPresence(
      [this, &generate_req, &generate_resp]() {
        return tpm_proxy_->SendU2fGenerate(generate_req, &generate_resp);
      },
      &generate_status);

  if (generate_status == 0) {
    util::AppendToVector(generate_resp.pubKey, credential_public_key);
    util::AppendToVector(generate_resp.keyHandle, credential_id);
    return MakeCredentialResponse::SUCCESS;
  }

  return MakeCredentialResponse::VERIFICATION_FAILED;
}

HasCredentialsResponse::HasCredentialsStatus
WebAuthnHandler::HasExcludedCredentials(const MakeCredentialRequest& request) {
  std::vector<uint8_t> rp_id_hash = util::Sha256(request.rp_id());
  for (auto credential : request.excluded_credential_id()) {
    auto ret = DoU2fSignCheckOnly(rp_id_hash, util::ToVector(credential));
    if (ret == HasCredentialsResponse::SUCCESS)
      return ret;
    if (ret == HasCredentialsResponse::INTERNAL_ERROR)
      return ret;
  }
  return HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID;
}

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 (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_USER_PRESENCE) {
    // TODO(yichengli): Add support for VERIFICATION_USER_VERIFICATION
    response.set_status(GetAssertionResponse::VERIFICATION_FAILED);
    method_response->Return(response);
    return;
  }

  // TODO(louiscollard): Support multiple credentials.
  // TODO(louiscollard): Support resident credentials.
  if (request.allowed_credential_id().size() != 1 ||
      request.allowed_credential_id().Get(0).size() !=
          sizeof(struct u2f_key_handle)) {
    response.set_status(GetAssertionResponse::INVALID_REQUEST);
    method_response->Return(response);
    return;
  }

  // If credential_id is not recognized or there's an internal error, don't
  // even start auth flow.
  std::vector<uint8_t> rp_id_hash = util::Sha256(request.rp_id());
  auto ret = DoU2fSignCheckOnly(
      rp_id_hash, util::ToVector(request.allowed_credential_id().Get(0)));
  if (ret == HasCredentialsResponse::INTERNAL_ERROR) {
    response.set_status(GetAssertionResponse::INTERNAL_ERROR);
    method_response->Return(response);
    return;
  } else if (ret == HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID) {
    response.set_status(GetAssertionResponse::UNKNOWN_CREDENTIAL_ID);
    method_response->Return(response);
    return;
  }

  struct GetAssertionSession session = {
      static_cast<uint64_t>(base::Time::Now().ToTimeT()), request,
      std::move(method_response)};
  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;
  const std::vector<uint8_t> rp_id_hash =
      util::Sha256(session.request_.rp_id());
  std::vector<uint8_t> authenticator_data = MakeAuthenticatorData(
      rp_id_hash, std::vector<uint8_t>(), std::vector<uint8_t>(),
      session.request_.verification_type() ==
          VerificationType::VERIFICATION_USER_VERIFICATION,
      false);
  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 =
      DoU2fSign(rp_id_hash, hash_to_sign,
                util::ToVector(session.request_.allowed_credential_id().Get(0)),
                presence_requirement, &signature);
  response.set_status(sign_status);
  if (sign_status == GetAssertionResponse::SUCCESS) {
    auto* assertion = response.add_assertion();
    assertion->set_credential_id(
        session.request_.allowed_credential_id().Get(0));
    AppendToString(authenticator_data, assertion->mutable_authenticator_data());
    AppendToString(signature, assertion->mutable_signature());
  }

  session.response_->Return(response);
}

GetAssertionResponse::GetAssertionStatus WebAuthnHandler::DoU2fSign(
    const std::vector<uint8_t>& rp_id_hash,
    const std::vector<uint8_t>& hash_to_sign,
    const std::vector<uint8_t>& credential_id,
    PresenceRequirement presence_requirement,
    std::vector<uint8_t>* signature) {
  DCHECK(rp_id_hash.size() == SHA256_DIGEST_LENGTH);
  base::Optional<brillo::SecureBlob> user_secret = user_state_->GetUserSecret();
  if (!user_secret.has_value()) {
    return GetAssertionResponse::INTERNAL_ERROR;
  }

  if (presence_requirement != PresenceRequirement::kPowerButton) {
    // TODO(yichengli): Add support for requiring fingerprint GPIO active.
    return GetAssertionResponse::INTERNAL_ERROR;
  }

  struct u2f_sign_req sign_req = {
      .flags = U2F_AUTH_ENFORCE  // Require user presence, consume.
  };
  util::VectorToObject(rp_id_hash, sign_req.appId);
  util::VectorToObject(*user_secret, sign_req.userSecret);
  util::VectorToObject(credential_id, &sign_req.keyHandle);
  util::VectorToObject(hash_to_sign, sign_req.hash);

  struct u2f_sign_resp sign_resp = {};

  uint32_t sign_status = -1;
  base::AutoLock(tpm_proxy_->GetLock());
  CallAndWaitForPresence(
      [this, &sign_req, &sign_resp]() {
        return tpm_proxy_->SendU2fSign(sign_req, &sign_resp);
      },
      &sign_status);
  brillo::SecureMemset(&sign_req.userSecret, 0, sizeof(sign_req.userSecret));

  if (sign_status == 0) {
    base::Optional<std::vector<uint8_t>> opt_signature =
        util::SignatureToDerBytes(sign_resp.sig_r, sign_resp.sig_s);
    if (!opt_signature.has_value()) {
      return GetAssertionResponse::INTERNAL_ERROR;
    }
    *signature = *opt_signature;
    return GetAssertionResponse::SUCCESS;
  }

  return GetAssertionResponse::VERIFICATION_FAILED;
}

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;
  }

  std::vector<uint8_t> rp_id_hash = util::Sha256(request.rp_id());
  for (const auto& credential_id : request.credential_id()) {
    auto ret = DoU2fSignCheckOnly(rp_id_hash, util::ToVector(credential_id));
    if (ret == HasCredentialsResponse::INTERNAL_ERROR) {
      response.set_status(ret);
      return response;
    } else if (ret == HasCredentialsResponse::SUCCESS) {
      *response.add_credential_id() = credential_id;
    }
  }

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

HasCredentialsResponse::HasCredentialsStatus
WebAuthnHandler::DoU2fSignCheckOnly(const std::vector<uint8_t>& rp_id_hash,
                                    const std::vector<uint8_t>& credential_id) {
  base::Optional<brillo::SecureBlob> user_secret = user_state_->GetUserSecret();
  if (!user_secret.has_value()) {
    return HasCredentialsResponse::INTERNAL_ERROR;
  }

  struct u2f_sign_req sign_req = {.flags = U2F_AUTH_CHECK_ONLY};
  util::VectorToObject(rp_id_hash, sign_req.appId);
  util::VectorToObject(*user_secret, sign_req.userSecret);
  util::VectorToObject(credential_id, &sign_req.keyHandle);

  struct u2f_sign_resp sign_resp;
  base::AutoLock(tpm_proxy_->GetLock());
  uint32_t sign_status = tpm_proxy_->SendU2fSign(sign_req, &sign_resp);
  brillo::SecureMemset(&sign_req.userSecret, 0, sizeof(sign_req.userSecret));

  // Return status of 0 indicates the credential is valid.
  return (sign_status == 0) ? HasCredentialsResponse::SUCCESS
                            : HasCredentialsResponse::UNKNOWN_CREDENTIAL_ID;
}

}  // namespace u2f
