//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "trunks/trunks_factory_impl.h"

#include <memory>

#include <base/logging.h>

#include "trunks/blob_parser.h"
#include "trunks/error_codes.h"
#include "trunks/hmac_session_impl.h"
#include "trunks/password_authorization_delegate.h"
#include "trunks/policy_session_impl.h"
#include "trunks/session_manager_impl.h"
#include "trunks/tpm_generated.h"
#include "trunks/tpm_state_impl.h"
#include "trunks/tpm_utility_impl.h"
#include "trunks/trunks_dbus_proxy.h"

namespace {

constexpr int kDefaultRetryDelayInMS = 250;
constexpr int kDefaultRetryTimeoutInMS = 10*1000;
constexpr int kDefaultRetries = kDefaultRetryTimeoutInMS/kDefaultRetryDelayInMS;
constexpr base::TimeDelta kDefaultRetryDelay =
    base::TimeDelta::FromMilliseconds(kDefaultRetryDelayInMS);

}  // namespace

namespace trunks {

// A post-processing transceiver that attaches on top of the transceiver passed
// to TrunksFactoryImpl. Peforms the following functions:
// - Checks the response in SendCommandAndWait and retries the command
//   in case the response code requests a retry. See RetryNeededFor() for
//   details.
class TrunksFactoryImpl::PostProcessingTransceiver : public CommandTransceiver {
 public:
  explicit PostProcessingTransceiver(CommandTransceiver* transceiver)
      : command_retry_delay_(kDefaultRetryDelay),
        max_command_retries_(kDefaultRetries),
        transceiver_(transceiver) {
    CHECK(transceiver_);
  }

  void set_max_command_retries(int max_command_retries) {
    max_command_retries_ = max_command_retries;
  }

  void set_command_retry_delay(base::TimeDelta command_retry_delay) {
    command_retry_delay_ = command_retry_delay;
  }

  bool Init() override { return transceiver_->Init(); }

  void SendCommand(const std::string& command,
                   const ResponseCallback& callback) override {
    transceiver_->SendCommand(command, callback);
  }

  std::string SendCommandAndWait(const std::string& command) override {
    int attempt_num = 0;
    std::string response;
    do {
      if (attempt_num > 0) {
        base::PlatformThread::Sleep(command_retry_delay_);
      }
      response = transceiver_->SendCommandAndWait(command);
    } while (RetryNeededFor(response, ++attempt_num));
    VLOG_IF(2, attempt_num > 1) << "Command sent " << attempt_num << " times.";
    return response;
  }

 private:
  bool RetryNeededFor(const std::string& response, int attempt_num) {
    if (attempt_num > max_command_retries_) {
      LOG(WARNING) << "Gave up retrying command after "
                   << attempt_num << " attempts.";
      return false;
    }
    TPM_RC rc;
    if (!GetResponseCode(response, &rc)) {
      return false;
    }
    switch (rc) {
      case TPM_RC_RETRY:
      case TPM_RC_NV_RATE:
        if (attempt_num == 1) {
          LOG(WARNING) << "Retrying command after " << GetErrorString(rc);
        } else {
          VLOG(2) << "Retrying command after " << GetErrorString(rc);
        }
        return true;
      default:
        return false;
    }
  }

  bool GetResponseCode(const std::string& response, TPM_RC* rc) {
    DCHECK(rc);
    std::string buffer(response);
    trunks::TPM_ST tag;
    if (Parse_TPM_ST(&buffer, &tag, nullptr) != TPM_RC_SUCCESS) {
      return false;
    }
    trunks::UINT32 response_size;
    if (Parse_UINT32(&buffer, &response_size, nullptr) != TPM_RC_SUCCESS) {
      return false;
    }
    if (response_size != response.size()) {
      return false;
    }
    return Parse_TPM_RC(&buffer, rc, nullptr) == TPM_RC_SUCCESS;
  }

  base::TimeDelta command_retry_delay_;
  int max_command_retries_;
  CommandTransceiver* transceiver_;

  DISALLOW_COPY_AND_ASSIGN(PostProcessingTransceiver);
};

TrunksFactoryImpl::TrunksFactoryImpl() {
  default_transceiver_.reset(new TrunksDBusProxy());
  transceiver_.reset(new PostProcessingTransceiver(default_transceiver_.get()));
}

TrunksFactoryImpl::TrunksFactoryImpl(CommandTransceiver* transceiver) {
  transceiver_.reset(new PostProcessingTransceiver(transceiver));
}

TrunksFactoryImpl::~TrunksFactoryImpl() {}

bool TrunksFactoryImpl::Initialize() {
  if (initialized_) {
    return true;
  }
  tpm_.reset(new Tpm(transceiver_.get()));
  if (!IsDefaultTransceiverUsed()) {
    initialized_ = true;
  } else {
    initialized_ = transceiver_->Init();
    if (!initialized_) {
      LOG(WARNING) << "Failed to initialize the trunks IPC proxy; "
                   << "trunksd is not ready.";
    }
  }
  return initialized_;
}

Tpm* TrunksFactoryImpl::GetTpm() const {
  return tpm_.get();
}

std::unique_ptr<TpmState> TrunksFactoryImpl::GetTpmState() const {
  return std::make_unique<TpmStateImpl>(*this);
}

std::unique_ptr<TpmUtility> TrunksFactoryImpl::GetTpmUtility() const {
  return std::make_unique<TpmUtilityImpl>(*this);
}

std::unique_ptr<AuthorizationDelegate>
TrunksFactoryImpl::GetPasswordAuthorization(const std::string& password) const {
  return std::make_unique<PasswordAuthorizationDelegate>(password);
}

std::unique_ptr<SessionManager> TrunksFactoryImpl::GetSessionManager() const {
  return std::make_unique<SessionManagerImpl>(*this);
}

std::unique_ptr<HmacSession> TrunksFactoryImpl::GetHmacSession() const {
  return std::make_unique<HmacSessionImpl>(*this);
}

std::unique_ptr<PolicySession> TrunksFactoryImpl::GetPolicySession() const {
  return std::make_unique<PolicySessionImpl>(*this, TPM_SE_POLICY);
}

std::unique_ptr<PolicySession> TrunksFactoryImpl::GetTrialSession() const {
  return std::make_unique<PolicySessionImpl>(*this, TPM_SE_TRIAL);
}

std::unique_ptr<BlobParser> TrunksFactoryImpl::GetBlobParser() const {
  return std::make_unique<BlobParser>();
}

void TrunksFactoryImpl::set_max_command_retries(int max_command_retries) {
  transceiver_->set_max_command_retries(max_command_retries);
}

void TrunksFactoryImpl::set_command_retry_delay(
    base::TimeDelta command_retry_delay) {
  transceiver_->set_command_retry_delay(command_retry_delay);
}

}  // namespace trunks
