//
// Copyright (C) 2015 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.
//
#ifndef TPM_MANAGER_SERVER_TPM_MANAGER_SERVICE_H_
#define TPM_MANAGER_SERVER_TPM_MANAGER_SERVICE_H_
#include <memory>
#include <base/callback.h>
#include <base/macros.h>
#include <base/memory/weak_ptr.h>
#include <base/threading/thread.h>
#include <brillo/bind_lambda.h>
#include "tpm_manager/common/tpm_nvram_interface.h"
#include "tpm_manager/common/tpm_ownership_interface.h"
#include "tpm_manager/server/local_data_store.h"
#include "tpm_manager/server/tpm_initializer.h"
#include "tpm_manager/server/tpm_nvram.h"
#include "tpm_manager/server/tpm_status.h"
namespace tpm_manager {
// This class implements the core tpm_manager service. All Tpm access is
// asynchronous, except for the initial setup in Initialize().
// Usage:
// std::unique_ptr<TpmManagerService> tpm_manager = new TpmManagerService();
// CHECK(tpm_manager->Initialize());
// tpm_manager->GetTpmStatus(...);
//
// THREADING NOTES:
// This class runs a worker thread and delegates all calls to it. This keeps the
// public methods non-blocking while allowing complex implementation details
// with dependencies on the TPM, network, and filesystem to be coded in a more
// readable way. It also serves to serialize method execution which reduces
// complexity with TPM state.
//
// Tasks that run on the worker thread are bound with base::Unretained which is
// safe because the thread is owned by this class (so it is guaranteed not to
// process a task after destruction). Weak pointers are used to post replies
// back to the main thread.
class TpmManagerService : public TpmNvramInterface,
public TpmOwnershipInterface {
public:
// If |wait_for_ownership| is set, TPM initialization will be postponed until
// an explicit TakeOwnership request is received. Does not take ownership of
// |local_data_store|, |tpm_status| or |tpm_initializer|.
explicit TpmManagerService(bool wait_for_ownership,
LocalDataStore* local_data_store,
TpmStatus* tpm_status,
TpmInitializer* tpm_initializer,
TpmNvram* tpm_nvram);
~TpmManagerService() override = default;
// Performs initialization tasks. This method must be called before calling
// any other method in this class. Returns true on success.
bool Initialize();
// TpmOwnershipInterface methods.
void GetTpmStatus(const GetTpmStatusRequest& request,
const GetTpmStatusCallback& callback) override;
void TakeOwnership(const TakeOwnershipRequest& request,
const TakeOwnershipCallback& callback) override;
void RemoveOwnerDependency(
const RemoveOwnerDependencyRequest& request,
const RemoveOwnerDependencyCallback& callback) override;
// TpmNvramInterface methods.
void DefineNvram(const DefineNvramRequest& request,
const DefineNvramCallback& callback) override;
void DestroyNvram(const DestroyNvramRequest& request,
const DestroyNvramCallback& callback) override;
void WriteNvram(const WriteNvramRequest& request,
const WriteNvramCallback& callback) override;
void ReadNvram(const ReadNvramRequest& request,
const ReadNvramCallback& callback) override;
void IsNvramDefined(const IsNvramDefinedRequest& request,
const IsNvramDefinedCallback& callback) override;
void IsNvramLocked(const IsNvramLockedRequest& request,
const IsNvramLockedCallback& callback) override;
void GetNvramSize(const GetNvramSizeRequest& request,
const GetNvramSizeCallback& callback) override;
private:
// A relay callback which allows the use of weak pointer semantics for a reply
// to TaskRunner::PostTaskAndReply.
template<typename ReplyProtobufType>
void TaskRelayCallback(
const base::Callback<void(const ReplyProtobufType&)> callback,
const std::shared_ptr<ReplyProtobufType>& reply);
// This templated method posts the provided |TaskType| to the background
// thread with the provided |RequestProtobufType|. When |TaskType| finishes
// executing, the |ReplyCallbackType| is called with the |ReplyProtobufType|.
template<typename ReplyProtobufType,
typename RequestProtobufType,
typename ReplyCallbackType,
typename TaskType>
void PostTaskToWorkerThread(RequestProtobufType& request,
ReplyCallbackType& callback,
TaskType task);
// Synchronously initializes the TPM according to the current configuration.
// If an initialization process was interrupted it will be continued. If the
// TPM is already initialized or cannot yet be initialized, this method has no
// effect.
void InitializeTask();
// Blocking implementation of GetTpmStatus that can be executed on the
// background worker thread.
void GetTpmStatusTask(const GetTpmStatusRequest& request,
const std::shared_ptr<GetTpmStatusReply>& result);
// Blocking implementation of TakeOwnership that can be executed on the
// background worker thread.
void TakeOwnershipTask(const TakeOwnershipRequest& request,
const std::shared_ptr<TakeOwnershipReply>& result);
// Blocking implementation of RemoveOwnerDependency that can be executed on
// the background worker thread.
void RemoveOwnerDependencyTask(
const RemoveOwnerDependencyRequest& request,
const std::shared_ptr<RemoveOwnerDependencyReply>& result);
// Removes a |owner_dependency| from the list of owner dependencies in
// |local_data|. If |owner_dependency| is not present in |local_data|,
// this method does nothing.
static void RemoveOwnerDependency(const std::string& owner_dependency,
LocalData* local_data);
// Blocking implementation of DefineNvram that can be executed on the
// background worker thread.
void DefineNvramTask(const DefineNvramRequest& request,
const std::shared_ptr<DefineNvramReply>& result);
// Blocking implementation of DestroyNvram that can be executed on the
// background worker thread.
void DestroyNvramTask(const DestroyNvramRequest& request,
const std::shared_ptr<DestroyNvramReply>& result);
// Blocking implementation of WriteNvram that can be executed on the
// background worker thread.
void WriteNvramTask(const WriteNvramRequest& request,
const std::shared_ptr<WriteNvramReply>& result);
// Blocking implementation of ReadNvram that can be executed on the
// background worker thread.
void ReadNvramTask(const ReadNvramRequest& request,
const std::shared_ptr<ReadNvramReply>& result);
// Blocking implementation of IsNvramDefined that can be executed on the
// background worker thread.
void IsNvramDefinedTask(const IsNvramDefinedRequest& request,
const std::shared_ptr<IsNvramDefinedReply>& result);
// Blocking implementation of IsNvramLocked that can be executed on the
// background worker thread.
void IsNvramLockedTask(const IsNvramLockedRequest& request,
const std::shared_ptr<IsNvramLockedReply>& result);
// Blocking implementation of GetNvramSize that can be executed on the
// background worker thread.
void GetNvramSizeTask(const GetNvramSizeRequest& request,
const std::shared_ptr<GetNvramSizeReply>& result);
LocalDataStore* local_data_store_;
TpmStatus* tpm_status_;
TpmInitializer* tpm_initializer_;
TpmNvram* tpm_nvram_;
// Whether to wait for an explicit call to 'TakeOwnership' before initializing
// the TPM. Normally tracks the --wait_for_ownership command line option.
bool wait_for_ownership_;
// Background thread to allow processing of potentially lengthy TPM requests
// in the background.
std::unique_ptr<base::Thread> worker_thread_;
// Declared last so any weak pointers are destroyed first.
base::WeakPtrFactory<TpmManagerService> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TpmManagerService);
};
} // namespace tpm_manager
#endif // TPM_MANAGER_SERVER_TPM_MANAGER_SERVICE_H_