// 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 "arc/keymaster/keymaster_server.h"

#include <utility>

#include <base/bind.h>
#include <base/check.h>
#include <base/threading/platform_thread.h>
#include <base/threading/thread_task_runner_handle.h>
#include <keymaster/android_keymaster_messages.h>
#include <mojo/cert_store.mojom.h>
#include <mojo/keymaster.mojom.h>

#include "arc/keymaster/conversion.h"

// The implementations of |arc::mojom::KeymasterServer| methods below have the
// following overall pattern:
//
// * Generate an std::unique_ptr to a Keymaster request data structure from the
//   arguments received from Mojo, usually through the helpers in conversion.h.
//
// * Execute the operation in |backend->keymaster()|, posting this task to a
//   background thread. This produces a Keymaster response data structure.
//
// * Post the response to a callback that runs on the original thread (in this
//   case, the Mojo thread where the request started).
//
// * Convert the Keymaster response to the Mojo return values, and run the
//   result callback.
//
namespace arc {
namespace keymaster {

namespace {

constexpr size_t kOperationTableSize = 16;

}  // namespace

KeymasterServer::Backend::Backend()
    : context_(new context::ArcKeymasterContext()),
      keymaster_(context_, kOperationTableSize) {}

KeymasterServer::Backend::~Backend() = default;

KeymasterServer::KeymasterServer()
    : backend_thread_("BackendKeymasterThread"), weak_ptr_factory_(this) {
  CHECK(backend_thread_.Start()) << "Failed to start keymaster thread";
}

KeymasterServer::~KeymasterServer() = default;

void KeymasterServer::UpdateContextPlaceholderKeys(
    std::vector<mojom::ChromeOsKeyPtr> keys,
    base::OnceCallback<void(bool)> callback) {
  base::OnceCallback<void(bool)> callback_in_original_runner = base::BindOnce(
      [](scoped_refptr<base::TaskRunner> original_task_runner,
         base::OnceCallback<void(bool)> callback, bool success) {
        original_task_runner->PostTask(
            FROM_HERE, base::BindOnce(std::move(callback), success));
      },
      base::ThreadTaskRunnerHandle::Get(), std::move(callback));

  backend_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(
                     [](context::ArcKeymasterContext* context,
                        std::vector<mojom::ChromeOsKeyPtr> keys,
                        base::OnceCallback<void(bool)> callback) {
                       // |context| is guaranteed valid here because it's owned
                       // by |backend_|, which outlives the |backend_thread_|
                       // this runs on.
                       context->set_placeholder_keys(std::move(keys));
                       std::move(callback).Run(/*success=*/true);
                     },
                     backend_.context(), std::move(keys),
                     std::move(callback_in_original_runner)));
}

void KeymasterServer::SetSystemVersion(uint32_t os_version,
                                       uint32_t os_patchlevel) {
  backend_thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(
                     [](context::ArcKeymasterContext* context,
                        uint32_t os_version, uint32_t os_patchlevel) {
                       // |context| is guaranteed valid here because it's owned
                       // by |backend_|, which outlives the |backend_thread_|
                       // this runs on.
                       context->SetSystemVersion(os_version, os_patchlevel);
                     },
                     backend_.context(), os_version, os_patchlevel));
}

template <typename KmMember, typename KmRequest, typename KmResponse>
void KeymasterServer::RunKeymasterRequest(
    const base::Location& location,
    KmMember member,
    std::unique_ptr<KmRequest> request,
    base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) {
  // Post the Keymaster operation to a background thread while capturing the
  // current task runner.
  backend_thread_.task_runner()->PostTask(
      location,
      base::BindOnce(
          [](const base::Location& location,
             scoped_refptr<base::TaskRunner> original_task_runner,
             ::keymaster::AndroidKeymaster* keymaster, KmMember member,
             std::unique_ptr<KmRequest> request,
             base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) {
            // Prepare a Keymaster response data structure.
            auto response = std::make_unique<KmResponse>();
            // Execute the operation.
            (*keymaster.*member)(*request, response.get());
            // Post |callback| to the |original_task_runner| given |response|.
            original_task_runner->PostTask(
                location,
                base::BindOnce(std::move(callback), std::move(response)));
          },
          location, base::ThreadTaskRunnerHandle::Get(), backend_.keymaster(),
          member, std::move(request), std::move(callback)));
}

void KeymasterServer::AddRngEntropy(const std::vector<uint8_t>& data,
                                    AddRngEntropyCallback callback) {
  // Convert input |data| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = std::make_unique<::keymaster::AddEntropyRequest>();
  ConvertToMessage(data, &km_request->random_data);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::AddRngEntropy,
      std::move(km_request),
      base::BindOnce(
          [](AddRngEntropyCallback callback,
             std::unique_ptr<::keymaster::AddEntropyResponse> km_response) {
            // Run callback.
            std::move(callback).Run(km_response->error);
          },
          std::move(callback)));
}

void KeymasterServer::GetKeyCharacteristics(
    ::arc::mojom::GetKeyCharacteristicsRequestPtr request,
    GetKeyCharacteristicsCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeGetKeyCharacteristicsRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::GetKeyCharacteristics,
      std::move(km_request),
      base::BindOnce(
          [](GetKeyCharacteristicsCallback callback,
             std::unique_ptr<::keymaster::GetKeyCharacteristicsResponse>
                 km_response) {
            // Prepare mojo response.
            auto response = MakeGetKeyCharacteristicsResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::GenerateKey(
    std::vector<::arc::mojom::KeyParameterPtr> key_params,
    GenerateKeyCallback callback) {
  // Convert input |key_params| into |km_request|. All data is deep copied to
  // avoid use-after-free.
  auto km_request = MakeGenerateKeyRequest(key_params);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::GenerateKey,
      std::move(km_request),
      base::BindOnce(
          [](GenerateKeyCallback callback,
             std::unique_ptr<::keymaster::GenerateKeyResponse> km_response) {
            // Prepare mojo response.
            auto response = MakeGenerateKeyResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::ImportKey(arc::mojom::ImportKeyRequestPtr request,
                                ImportKeyCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeImportKeyRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::ImportKey,
      std::move(km_request),
      base::BindOnce(
          [](ImportKeyCallback callback,
             std::unique_ptr<::keymaster::ImportKeyResponse> km_response) {
            // Prepare mojo response.
            auto response = MakeImportKeyResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::ExportKey(arc::mojom::ExportKeyRequestPtr request,
                                ExportKeyCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeExportKeyRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::ExportKey,
      std::move(km_request),
      base::BindOnce(
          [](ExportKeyCallback callback,
             std::unique_ptr<::keymaster::ExportKeyResponse> km_response) {
            // Prepare mojo response.
            auto response = MakeExportKeyResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::AttestKey(arc::mojom::AttestKeyRequestPtr request,
                                AttestKeyCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeAttestKeyRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::AttestKey,
      std::move(km_request),
      base::BindOnce(
          [](AttestKeyCallback callback,
             std::unique_ptr<::keymaster::AttestKeyResponse> km_response) {
            // Prepare mojo response.
            auto response = MakeAttestKeyResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::UpgradeKey(arc::mojom::UpgradeKeyRequestPtr request,
                                 UpgradeKeyCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeUpgradeKeyRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::UpgradeKey,
      std::move(km_request),
      base::BindOnce(
          [](UpgradeKeyCallback callback,
             std::unique_ptr<::keymaster::UpgradeKeyResponse> km_response) {
            // Prepare mojo response.
            auto response = MakeUpgradeKeyResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::DeleteKey(const std::vector<uint8_t>& key_blob,
                                DeleteKeyCallback callback) {
  // Convert input |key_blob| into |km_request|. All data is deep copied to
  // avoid use-after-free.
  auto km_request = std::make_unique<::keymaster::DeleteKeyRequest>();
  km_request->SetKeyMaterial(key_blob.data(), key_blob.size());

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::DeleteKey,
      std::move(km_request),
      base::BindOnce(
          [](DeleteKeyCallback callback,
             std::unique_ptr<::keymaster::DeleteKeyResponse> km_response) {
            // Run callback.
            std::move(callback).Run(km_response->error);
          },
          std::move(callback)));
}

void KeymasterServer::DeleteAllKeys(DeleteAllKeysCallback callback) {
  // Prepare keymaster request.
  auto km_request = std::make_unique<::keymaster::DeleteAllKeysRequest>();

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::DeleteAllKeys,
      std::move(km_request),
      base::BindOnce(
          [](DeleteAllKeysCallback callback,
             std::unique_ptr<::keymaster::DeleteAllKeysResponse> km_response) {
            // Run callback.
            std::move(callback).Run(km_response->error);
          },
          std::move(callback)));
}

void KeymasterServer::Begin(arc::mojom::BeginRequestPtr request,
                            BeginCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeBeginOperationRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::BeginOperation,
      std::move(km_request),
      base::BindOnce(
          [](BeginCallback callback,
             std::unique_ptr<::keymaster::BeginOperationResponse> km_response) {
            // Prepare mojo response.
            auto response = MakeBeginResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::Update(arc::mojom::UpdateRequestPtr request,
                             UpdateCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeUpdateOperationRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::UpdateOperation,
      std::move(km_request),
      base::BindOnce(
          [](UpdateCallback callback,
             std::unique_ptr<::keymaster::UpdateOperationResponse>
                 km_response) {
            // Prepare mojo response.
            auto response = MakeUpdateResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::Finish(arc::mojom::FinishRequestPtr request,
                             FinishCallback callback) {
  // Convert input |request| into |km_request|. All data is deep copied to avoid
  // use-after-free.
  auto km_request = MakeFinishOperationRequest(request);

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::FinishOperation,
      std::move(km_request),
      base::BindOnce(
          [](FinishCallback callback,
             std::unique_ptr<::keymaster::FinishOperationResponse>
                 km_response) {
            // Prepare mojo response.
            auto response = MakeFinishResult(*km_response);
            // Run callback.
            std::move(callback).Run(std::move(response));
          },
          std::move(callback)));
}

void KeymasterServer::Abort(uint64_t op_handle, AbortCallback callback) {
  // Prepare keymaster request.
  auto km_request = std::make_unique<::keymaster::AbortOperationRequest>();
  km_request->op_handle = op_handle;

  // Call keymaster.
  RunKeymasterRequest(
      FROM_HERE, &::keymaster::AndroidKeymaster::AbortOperation,
      std::move(km_request),
      base::BindOnce(
          [](AbortCallback callback,
             std::unique_ptr<::keymaster::AbortOperationResponse> km_response) {
            // Run callback.
            std::move(callback).Run(km_response->error);
          },
          std::move(callback)));
}

}  // namespace keymaster
}  // namespace arc
