Home | History | Annotate | Download | only in server
      1 //
      2 // Copyright (C) 2015 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "tpm_manager/server/tpm_manager_service.h"
     18 
     19 #include <base/callback.h>
     20 #include <base/command_line.h>
     21 #include <brillo/bind_lambda.h>
     22 
     23 namespace tpm_manager {
     24 
     25 TpmManagerService::TpmManagerService(bool wait_for_ownership,
     26                                      LocalDataStore* local_data_store,
     27                                      TpmStatus* tpm_status,
     28                                      TpmInitializer* tpm_initializer,
     29                                      TpmNvram* tpm_nvram)
     30     : local_data_store_(local_data_store),
     31       tpm_status_(tpm_status),
     32       tpm_initializer_(tpm_initializer),
     33       tpm_nvram_(tpm_nvram),
     34       wait_for_ownership_(wait_for_ownership),
     35       weak_factory_(this) {}
     36 
     37 bool TpmManagerService::Initialize() {
     38   worker_thread_.reset(new base::Thread("TpmManager Service Worker"));
     39   worker_thread_->StartWithOptions(
     40       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
     41   base::Closure task =
     42       base::Bind(&TpmManagerService::InitializeTask, base::Unretained(this));
     43   worker_thread_->task_runner()->PostNonNestableTask(FROM_HERE, task);
     44   VLOG(1) << "Worker thread started.";
     45   return true;
     46 }
     47 
     48 void TpmManagerService::InitializeTask() {
     49   VLOG(1) << "Initializing service...";
     50   if (!tpm_status_->IsTpmEnabled()) {
     51     LOG(WARNING) << __func__ << ": TPM is disabled.";
     52     return;
     53   }
     54   tpm_initializer_->VerifiedBootHelper();
     55   if (!wait_for_ownership_) {
     56     VLOG(1) << "Initializing TPM.";
     57     if (!tpm_initializer_->InitializeTpm()) {
     58       LOG(WARNING) << __func__ << ": TPM initialization failed.";
     59       return;
     60     }
     61   }
     62 }
     63 
     64 void TpmManagerService::GetTpmStatus(const GetTpmStatusRequest& request,
     65                                      const GetTpmStatusCallback& callback) {
     66   PostTaskToWorkerThread<GetTpmStatusReply>(
     67       request, callback, &TpmManagerService::GetTpmStatusTask);
     68 }
     69 
     70 void TpmManagerService::GetTpmStatusTask(
     71     const GetTpmStatusRequest& request,
     72     const std::shared_ptr<GetTpmStatusReply>& reply) {
     73   VLOG(1) << __func__;
     74   reply->set_enabled(tpm_status_->IsTpmEnabled());
     75   reply->set_owned(tpm_status_->IsTpmOwned());
     76   LocalData local_data;
     77   if (local_data_store_ && local_data_store_->Read(&local_data)) {
     78     *reply->mutable_local_data() = local_data;
     79   }
     80   int counter;
     81   int threshold;
     82   bool lockout;
     83   int lockout_time_remaining;
     84   if (tpm_status_->GetDictionaryAttackInfo(&counter, &threshold, &lockout,
     85                                            &lockout_time_remaining)) {
     86     reply->set_dictionary_attack_counter(counter);
     87     reply->set_dictionary_attack_threshold(threshold);
     88     reply->set_dictionary_attack_lockout_in_effect(lockout);
     89     reply->set_dictionary_attack_lockout_seconds_remaining(
     90         lockout_time_remaining);
     91   }
     92   reply->set_status(STATUS_SUCCESS);
     93 }
     94 
     95 void TpmManagerService::TakeOwnership(const TakeOwnershipRequest& request,
     96                                       const TakeOwnershipCallback& callback) {
     97   PostTaskToWorkerThread<TakeOwnershipReply>(
     98       request, callback, &TpmManagerService::TakeOwnershipTask);
     99 }
    100 
    101 void TpmManagerService::TakeOwnershipTask(
    102     const TakeOwnershipRequest& request,
    103     const std::shared_ptr<TakeOwnershipReply>& reply) {
    104   VLOG(1) << __func__;
    105   if (!tpm_status_->IsTpmEnabled()) {
    106     reply->set_status(STATUS_NOT_AVAILABLE);
    107     return;
    108   }
    109   if (!tpm_initializer_->InitializeTpm()) {
    110     reply->set_status(STATUS_DEVICE_ERROR);
    111     return;
    112   }
    113   reply->set_status(STATUS_SUCCESS);
    114 }
    115 
    116 void TpmManagerService::RemoveOwnerDependency(
    117     const RemoveOwnerDependencyRequest& request,
    118     const RemoveOwnerDependencyCallback& callback) {
    119   PostTaskToWorkerThread<RemoveOwnerDependencyReply>(
    120       request, callback, &TpmManagerService::RemoveOwnerDependencyTask);
    121 }
    122 
    123 void TpmManagerService::RemoveOwnerDependencyTask(
    124     const RemoveOwnerDependencyRequest& request,
    125     const std::shared_ptr<RemoveOwnerDependencyReply>& reply) {
    126   VLOG(1) << __func__;
    127   LocalData local_data;
    128   if (!local_data_store_->Read(&local_data)) {
    129     reply->set_status(STATUS_DEVICE_ERROR);
    130     return;
    131   }
    132   RemoveOwnerDependency(request.owner_dependency(), &local_data);
    133   if (!local_data_store_->Write(local_data)) {
    134     reply->set_status(STATUS_DEVICE_ERROR);
    135     return;
    136   }
    137   reply->set_status(STATUS_SUCCESS);
    138 }
    139 
    140 void TpmManagerService::RemoveOwnerDependency(
    141     const std::string& owner_dependency,
    142     LocalData* local_data) {
    143   google::protobuf::RepeatedPtrField<std::string>* dependencies =
    144       local_data->mutable_owner_dependency();
    145   for (int i = 0; i < dependencies->size(); i++) {
    146     if (dependencies->Get(i) == owner_dependency) {
    147       dependencies->SwapElements(i, (dependencies->size() - 1));
    148       dependencies->RemoveLast();
    149       break;
    150     }
    151   }
    152   if (dependencies->empty()) {
    153     local_data->clear_owner_password();
    154     local_data->clear_endorsement_password();
    155     local_data->clear_lockout_password();
    156   }
    157 }
    158 
    159 void TpmManagerService::DefineSpace(const DefineSpaceRequest& request,
    160                                     const DefineSpaceCallback& callback) {
    161   PostTaskToWorkerThread<DefineSpaceReply>(request, callback,
    162                                            &TpmManagerService::DefineSpaceTask);
    163 }
    164 
    165 void TpmManagerService::DefineSpaceTask(
    166     const DefineSpaceRequest& request,
    167     const std::shared_ptr<DefineSpaceReply>& reply) {
    168   VLOG(1) << __func__;
    169   std::vector<NvramSpaceAttribute> attributes;
    170   for (int i = 0; i < request.attributes_size(); ++i) {
    171     attributes.push_back(request.attributes(i));
    172   }
    173   reply->set_result(
    174       tpm_nvram_->DefineSpace(request.index(), request.size(), attributes,
    175                               request.authorization_value(), request.policy()));
    176 }
    177 
    178 void TpmManagerService::DestroySpace(const DestroySpaceRequest& request,
    179                                      const DestroySpaceCallback& callback) {
    180   PostTaskToWorkerThread<DestroySpaceReply>(
    181       request, callback, &TpmManagerService::DestroySpaceTask);
    182 }
    183 
    184 void TpmManagerService::DestroySpaceTask(
    185     const DestroySpaceRequest& request,
    186     const std::shared_ptr<DestroySpaceReply>& reply) {
    187   VLOG(1) << __func__;
    188   reply->set_result(tpm_nvram_->DestroySpace(request.index()));
    189 }
    190 
    191 void TpmManagerService::WriteSpace(const WriteSpaceRequest& request,
    192                                    const WriteSpaceCallback& callback) {
    193   PostTaskToWorkerThread<WriteSpaceReply>(request, callback,
    194                                           &TpmManagerService::WriteSpaceTask);
    195 }
    196 
    197 void TpmManagerService::WriteSpaceTask(
    198     const WriteSpaceRequest& request,
    199     const std::shared_ptr<WriteSpaceReply>& reply) {
    200   VLOG(1) << __func__;
    201   std::string authorization_value = request.authorization_value();
    202   if (request.use_owner_authorization()) {
    203     authorization_value = GetOwnerPassword();
    204     if (authorization_value.empty()) {
    205       reply->set_result(NVRAM_RESULT_ACCESS_DENIED);
    206       return;
    207     }
    208   }
    209   reply->set_result(tpm_nvram_->WriteSpace(request.index(), request.data(),
    210                                            authorization_value));
    211 }
    212 
    213 void TpmManagerService::ReadSpace(const ReadSpaceRequest& request,
    214                                   const ReadSpaceCallback& callback) {
    215   PostTaskToWorkerThread<ReadSpaceReply>(request, callback,
    216                                          &TpmManagerService::ReadSpaceTask);
    217 }
    218 
    219 void TpmManagerService::ReadSpaceTask(
    220     const ReadSpaceRequest& request,
    221     const std::shared_ptr<ReadSpaceReply>& reply) {
    222   VLOG(1) << __func__;
    223   std::string authorization_value = request.authorization_value();
    224   if (request.use_owner_authorization()) {
    225     authorization_value = GetOwnerPassword();
    226     if (authorization_value.empty()) {
    227       reply->set_result(NVRAM_RESULT_ACCESS_DENIED);
    228       return;
    229     }
    230   }
    231   reply->set_result(tpm_nvram_->ReadSpace(
    232       request.index(), reply->mutable_data(), authorization_value));
    233 }
    234 
    235 void TpmManagerService::LockSpace(const LockSpaceRequest& request,
    236                                   const LockSpaceCallback& callback) {
    237   PostTaskToWorkerThread<LockSpaceReply>(request, callback,
    238                                          &TpmManagerService::LockSpaceTask);
    239 }
    240 
    241 void TpmManagerService::LockSpaceTask(
    242     const LockSpaceRequest& request,
    243     const std::shared_ptr<LockSpaceReply>& reply) {
    244   VLOG(1) << __func__;
    245   std::string authorization_value = request.authorization_value();
    246   if (request.use_owner_authorization()) {
    247     authorization_value = GetOwnerPassword();
    248     if (authorization_value.empty()) {
    249       reply->set_result(NVRAM_RESULT_ACCESS_DENIED);
    250       return;
    251     }
    252   }
    253   reply->set_result(tpm_nvram_->LockSpace(request.index(), request.lock_read(),
    254                                           request.lock_write(),
    255                                           authorization_value));
    256 }
    257 
    258 void TpmManagerService::ListSpaces(const ListSpacesRequest& request,
    259                                    const ListSpacesCallback& callback) {
    260   PostTaskToWorkerThread<ListSpacesReply>(request, callback,
    261                                           &TpmManagerService::ListSpacesTask);
    262 }
    263 
    264 void TpmManagerService::ListSpacesTask(
    265     const ListSpacesRequest& request,
    266     const std::shared_ptr<ListSpacesReply>& reply) {
    267   VLOG(1) << __func__;
    268   std::vector<uint32_t> index_list;
    269   reply->set_result(tpm_nvram_->ListSpaces(&index_list));
    270   if (reply->result() == NVRAM_RESULT_SUCCESS) {
    271     for (auto index : index_list) {
    272       reply->add_index_list(index);
    273     }
    274   }
    275 }
    276 
    277 void TpmManagerService::GetSpaceInfo(const GetSpaceInfoRequest& request,
    278                                      const GetSpaceInfoCallback& callback) {
    279   PostTaskToWorkerThread<GetSpaceInfoReply>(
    280       request, callback, &TpmManagerService::GetSpaceInfoTask);
    281 }
    282 
    283 void TpmManagerService::GetSpaceInfoTask(
    284     const GetSpaceInfoRequest& request,
    285     const std::shared_ptr<GetSpaceInfoReply>& reply) {
    286   VLOG(1) << __func__;
    287   std::vector<NvramSpaceAttribute> attributes;
    288   size_t size = 0;
    289   bool is_read_locked = false;
    290   bool is_write_locked = false;
    291   NvramSpacePolicy policy = NVRAM_POLICY_NONE;
    292   reply->set_result(tpm_nvram_->GetSpaceInfo(request.index(), &size,
    293                                              &is_read_locked, &is_write_locked,
    294                                              &attributes, &policy));
    295   if (reply->result() == NVRAM_RESULT_SUCCESS) {
    296     reply->set_size(size);
    297     reply->set_is_read_locked(is_read_locked);
    298     reply->set_is_write_locked(is_write_locked);
    299     for (auto attribute : attributes) {
    300       reply->add_attributes(attribute);
    301     }
    302     reply->set_policy(policy);
    303   }
    304 }
    305 
    306 std::string TpmManagerService::GetOwnerPassword() {
    307   LocalData local_data;
    308   if (local_data_store_ && local_data_store_->Read(&local_data)) {
    309     return local_data.owner_password();
    310   }
    311   LOG(ERROR) << "TPM owner password requested but not available.";
    312   return std::string();
    313 }
    314 
    315 template <typename ReplyProtobufType>
    316 void TpmManagerService::TaskRelayCallback(
    317     const base::Callback<void(const ReplyProtobufType&)> callback,
    318     const std::shared_ptr<ReplyProtobufType>& reply) {
    319   callback.Run(*reply);
    320 }
    321 
    322 template <typename ReplyProtobufType,
    323           typename RequestProtobufType,
    324           typename ReplyCallbackType,
    325           typename TaskType>
    326 void TpmManagerService::PostTaskToWorkerThread(RequestProtobufType& request,
    327                                                ReplyCallbackType& callback,
    328                                                TaskType task) {
    329   auto result = std::make_shared<ReplyProtobufType>();
    330   base::Closure background_task =
    331       base::Bind(task, base::Unretained(this), request, result);
    332   base::Closure reply =
    333       base::Bind(&TpmManagerService::TaskRelayCallback<ReplyProtobufType>,
    334                  weak_factory_.GetWeakPtr(), callback, result);
    335   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, background_task,
    336                                                   reply);
    337 }
    338 
    339 }  // namespace tpm_manager
    340