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 
TpmManagerService(bool wait_for_ownership,LocalDataStore * local_data_store,TpmStatus * tpm_status,TpmInitializer * tpm_initializer,TpmNvram * tpm_nvram)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 
Initialize()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 
InitializeTask()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 
GetTpmStatus(const GetTpmStatusRequest & request,const GetTpmStatusCallback & callback)64 void TpmManagerService::GetTpmStatus(const GetTpmStatusRequest& request,
65                                      const GetTpmStatusCallback& callback) {
66   PostTaskToWorkerThread<GetTpmStatusReply>(
67       request, callback, &TpmManagerService::GetTpmStatusTask);
68 }
69 
GetTpmStatusTask(const GetTpmStatusRequest & request,const std::shared_ptr<GetTpmStatusReply> & reply)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 
TakeOwnership(const TakeOwnershipRequest & request,const TakeOwnershipCallback & callback)95 void TpmManagerService::TakeOwnership(const TakeOwnershipRequest& request,
96                                       const TakeOwnershipCallback& callback) {
97   PostTaskToWorkerThread<TakeOwnershipReply>(
98       request, callback, &TpmManagerService::TakeOwnershipTask);
99 }
100 
TakeOwnershipTask(const TakeOwnershipRequest & request,const std::shared_ptr<TakeOwnershipReply> & reply)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 
RemoveOwnerDependency(const RemoveOwnerDependencyRequest & request,const RemoveOwnerDependencyCallback & callback)116 void TpmManagerService::RemoveOwnerDependency(
117     const RemoveOwnerDependencyRequest& request,
118     const RemoveOwnerDependencyCallback& callback) {
119   PostTaskToWorkerThread<RemoveOwnerDependencyReply>(
120       request, callback, &TpmManagerService::RemoveOwnerDependencyTask);
121 }
122 
RemoveOwnerDependencyTask(const RemoveOwnerDependencyRequest & request,const std::shared_ptr<RemoveOwnerDependencyReply> & reply)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 
RemoveOwnerDependency(const std::string & owner_dependency,LocalData * local_data)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 
DefineSpace(const DefineSpaceRequest & request,const DefineSpaceCallback & callback)159 void TpmManagerService::DefineSpace(const DefineSpaceRequest& request,
160                                     const DefineSpaceCallback& callback) {
161   PostTaskToWorkerThread<DefineSpaceReply>(request, callback,
162                                            &TpmManagerService::DefineSpaceTask);
163 }
164 
DefineSpaceTask(const DefineSpaceRequest & request,const std::shared_ptr<DefineSpaceReply> & reply)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 
DestroySpace(const DestroySpaceRequest & request,const DestroySpaceCallback & callback)178 void TpmManagerService::DestroySpace(const DestroySpaceRequest& request,
179                                      const DestroySpaceCallback& callback) {
180   PostTaskToWorkerThread<DestroySpaceReply>(
181       request, callback, &TpmManagerService::DestroySpaceTask);
182 }
183 
DestroySpaceTask(const DestroySpaceRequest & request,const std::shared_ptr<DestroySpaceReply> & reply)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 
WriteSpace(const WriteSpaceRequest & request,const WriteSpaceCallback & callback)191 void TpmManagerService::WriteSpace(const WriteSpaceRequest& request,
192                                    const WriteSpaceCallback& callback) {
193   PostTaskToWorkerThread<WriteSpaceReply>(request, callback,
194                                           &TpmManagerService::WriteSpaceTask);
195 }
196 
WriteSpaceTask(const WriteSpaceRequest & request,const std::shared_ptr<WriteSpaceReply> & reply)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 
ReadSpace(const ReadSpaceRequest & request,const ReadSpaceCallback & callback)213 void TpmManagerService::ReadSpace(const ReadSpaceRequest& request,
214                                   const ReadSpaceCallback& callback) {
215   PostTaskToWorkerThread<ReadSpaceReply>(request, callback,
216                                          &TpmManagerService::ReadSpaceTask);
217 }
218 
ReadSpaceTask(const ReadSpaceRequest & request,const std::shared_ptr<ReadSpaceReply> & reply)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 
LockSpace(const LockSpaceRequest & request,const LockSpaceCallback & callback)235 void TpmManagerService::LockSpace(const LockSpaceRequest& request,
236                                   const LockSpaceCallback& callback) {
237   PostTaskToWorkerThread<LockSpaceReply>(request, callback,
238                                          &TpmManagerService::LockSpaceTask);
239 }
240 
LockSpaceTask(const LockSpaceRequest & request,const std::shared_ptr<LockSpaceReply> & reply)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 
ListSpaces(const ListSpacesRequest & request,const ListSpacesCallback & callback)258 void TpmManagerService::ListSpaces(const ListSpacesRequest& request,
259                                    const ListSpacesCallback& callback) {
260   PostTaskToWorkerThread<ListSpacesReply>(request, callback,
261                                           &TpmManagerService::ListSpacesTask);
262 }
263 
ListSpacesTask(const ListSpacesRequest & request,const std::shared_ptr<ListSpacesReply> & reply)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 
GetSpaceInfo(const GetSpaceInfoRequest & request,const GetSpaceInfoCallback & callback)277 void TpmManagerService::GetSpaceInfo(const GetSpaceInfoRequest& request,
278                                      const GetSpaceInfoCallback& callback) {
279   PostTaskToWorkerThread<GetSpaceInfoReply>(
280       request, callback, &TpmManagerService::GetSpaceInfoTask);
281 }
282 
GetSpaceInfoTask(const GetSpaceInfoRequest & request,const std::shared_ptr<GetSpaceInfoReply> & reply)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 
GetOwnerPassword()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>
TaskRelayCallback(const base::Callback<void (const ReplyProtobufType &)> callback,const std::shared_ptr<ReplyProtobufType> & reply)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>
PostTaskToWorkerThread(RequestProtobufType & request,ReplyCallbackType & callback,TaskType task)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