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   LOG(INFO) << "TpmManager service started.";
39   worker_thread_.reset(new base::Thread("TpmManager Service Worker"));
40   worker_thread_->StartWithOptions(
41       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
42   base::Closure task = base::Bind(&TpmManagerService::InitializeTask,
43                                   base::Unretained(this));
44   worker_thread_->task_runner()->PostNonNestableTask(FROM_HERE, task);
45   return true;
46 }
47 
InitializeTask()48 void TpmManagerService::InitializeTask() {
49   if (!tpm_status_->IsTpmEnabled()) {
50     LOG(WARNING) << __func__ << ": TPM is disabled.";
51     return;
52   }
53   if (!wait_for_ownership_) {
54     VLOG(1) << "Initializing TPM.";
55     if (!tpm_initializer_->InitializeTpm()) {
56       LOG(WARNING) << __func__ << ": TPM initialization failed.";
57       return;
58     }
59   }
60 }
61 
GetTpmStatus(const GetTpmStatusRequest & request,const GetTpmStatusCallback & callback)62 void TpmManagerService::GetTpmStatus(const GetTpmStatusRequest& request,
63                                      const GetTpmStatusCallback& callback) {
64   PostTaskToWorkerThread<GetTpmStatusReply>(
65       request, callback, &TpmManagerService::GetTpmStatusTask);
66 }
67 
GetTpmStatusTask(const GetTpmStatusRequest & request,const std::shared_ptr<GetTpmStatusReply> & result)68 void TpmManagerService::GetTpmStatusTask(
69     const GetTpmStatusRequest& request,
70     const std::shared_ptr<GetTpmStatusReply>& result) {
71   VLOG(1) << __func__;
72   result->set_enabled(tpm_status_->IsTpmEnabled());
73   result->set_owned(tpm_status_->IsTpmOwned());
74   LocalData local_data;
75   if (local_data_store_ && local_data_store_->Read(&local_data)) {
76     *result->mutable_local_data() = local_data;
77   }
78   int counter;
79   int threshold;
80   bool lockout;
81   int lockout_time_remaining;
82   if (tpm_status_->GetDictionaryAttackInfo(&counter, &threshold, &lockout,
83                                            &lockout_time_remaining)) {
84     result->set_dictionary_attack_counter(counter);
85     result->set_dictionary_attack_threshold(threshold);
86     result->set_dictionary_attack_lockout_in_effect(lockout);
87     result->set_dictionary_attack_lockout_seconds_remaining(
88         lockout_time_remaining);
89   }
90   result->set_status(STATUS_SUCCESS);
91 }
92 
TakeOwnership(const TakeOwnershipRequest & request,const TakeOwnershipCallback & callback)93 void TpmManagerService::TakeOwnership(const TakeOwnershipRequest& request,
94                                       const TakeOwnershipCallback& callback) {
95   PostTaskToWorkerThread<TakeOwnershipReply>(
96       request, callback, &TpmManagerService::TakeOwnershipTask);
97 }
98 
TakeOwnershipTask(const TakeOwnershipRequest & request,const std::shared_ptr<TakeOwnershipReply> & result)99 void TpmManagerService::TakeOwnershipTask(
100     const TakeOwnershipRequest& request,
101     const std::shared_ptr<TakeOwnershipReply>& result) {
102   VLOG(1) << __func__;
103   if (!tpm_status_->IsTpmEnabled()) {
104     result->set_status(STATUS_NOT_AVAILABLE);
105     return;
106   }
107   if (!tpm_initializer_->InitializeTpm()) {
108     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
109     return;
110   }
111   result->set_status(STATUS_SUCCESS);
112 }
113 
RemoveOwnerDependency(const RemoveOwnerDependencyRequest & request,const RemoveOwnerDependencyCallback & callback)114 void TpmManagerService::RemoveOwnerDependency(
115     const RemoveOwnerDependencyRequest& request,
116     const RemoveOwnerDependencyCallback& callback) {
117   PostTaskToWorkerThread<RemoveOwnerDependencyReply>(
118       request, callback, &TpmManagerService::RemoveOwnerDependencyTask);
119 }
120 
RemoveOwnerDependencyTask(const RemoveOwnerDependencyRequest & request,const std::shared_ptr<RemoveOwnerDependencyReply> & result)121 void TpmManagerService::RemoveOwnerDependencyTask(
122     const RemoveOwnerDependencyRequest& request,
123     const std::shared_ptr<RemoveOwnerDependencyReply>& result) {
124   VLOG(1) << __func__;
125   LocalData local_data;
126   if (!local_data_store_->Read(&local_data)) {
127     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
128     return;
129   }
130   RemoveOwnerDependency(request.owner_dependency(), &local_data);
131   if (!local_data_store_->Write(local_data)) {
132     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
133     return;
134   }
135   result->set_status(STATUS_SUCCESS);
136 }
137 
RemoveOwnerDependency(const std::string & owner_dependency,LocalData * local_data)138 void TpmManagerService::RemoveOwnerDependency(
139     const std::string& owner_dependency, LocalData* local_data) {
140   google::protobuf::RepeatedPtrField<std::string>* dependencies =
141       local_data->mutable_owner_dependency();
142   for (int i = 0; i < dependencies->size(); i++) {
143     if (dependencies->Get(i) == owner_dependency) {
144       dependencies->SwapElements(i, (dependencies->size() - 1));
145       dependencies->RemoveLast();
146       break;
147     }
148   }
149   if (dependencies->empty()) {
150     local_data->clear_owner_password();
151     local_data->clear_endorsement_password();
152     local_data->clear_lockout_password();
153   }
154 }
155 
DefineNvram(const DefineNvramRequest & request,const DefineNvramCallback & callback)156 void TpmManagerService::DefineNvram(const DefineNvramRequest& request,
157                                     const DefineNvramCallback& callback) {
158   PostTaskToWorkerThread<DefineNvramReply>(
159       request, callback, &TpmManagerService::DefineNvramTask);
160 }
161 
DefineNvramTask(const DefineNvramRequest & request,const std::shared_ptr<DefineNvramReply> & result)162 void TpmManagerService::DefineNvramTask(
163     const DefineNvramRequest& request,
164     const std::shared_ptr<DefineNvramReply>& result) {
165   VLOG(1) << __func__;
166   if (!tpm_nvram_->DefineNvram(request.index(), request.length())) {
167     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
168     return;
169   }
170   result->set_status(STATUS_SUCCESS);
171 }
172 
DestroyNvram(const DestroyNvramRequest & request,const DestroyNvramCallback & callback)173 void TpmManagerService::DestroyNvram(const DestroyNvramRequest& request,
174                                      const DestroyNvramCallback& callback) {
175   PostTaskToWorkerThread<DestroyNvramReply>(
176       request, callback, &TpmManagerService::DestroyNvramTask);
177 }
178 
DestroyNvramTask(const DestroyNvramRequest & request,const std::shared_ptr<DestroyNvramReply> & result)179 void TpmManagerService::DestroyNvramTask(
180     const DestroyNvramRequest& request,
181     const std::shared_ptr<DestroyNvramReply>& result) {
182   VLOG(1) << __func__;
183   if (!tpm_nvram_->DestroyNvram(request.index())) {
184     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
185     return;
186   }
187   result->set_status(STATUS_SUCCESS);
188 }
189 
WriteNvram(const WriteNvramRequest & request,const WriteNvramCallback & callback)190 void TpmManagerService::WriteNvram(const WriteNvramRequest& request,
191                                    const WriteNvramCallback& callback) {
192   PostTaskToWorkerThread<WriteNvramReply>(
193       request, callback, &TpmManagerService::WriteNvramTask);
194 }
195 
WriteNvramTask(const WriteNvramRequest & request,const std::shared_ptr<WriteNvramReply> & result)196 void TpmManagerService::WriteNvramTask(
197     const WriteNvramRequest& request,
198     const std::shared_ptr<WriteNvramReply>& result) {
199   VLOG(1) << __func__;
200   if (!tpm_nvram_->WriteNvram(request.index(), request.data())) {
201     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
202     return;
203   }
204   result->set_status(STATUS_SUCCESS);
205 }
206 
ReadNvram(const ReadNvramRequest & request,const ReadNvramCallback & callback)207 void TpmManagerService::ReadNvram(const ReadNvramRequest& request,
208                                   const ReadNvramCallback& callback) {
209   PostTaskToWorkerThread<ReadNvramReply>(
210       request, callback, &TpmManagerService::ReadNvramTask);
211 }
212 
ReadNvramTask(const ReadNvramRequest & request,const std::shared_ptr<ReadNvramReply> & result)213 void TpmManagerService::ReadNvramTask(
214     const ReadNvramRequest& request,
215     const std::shared_ptr<ReadNvramReply>& result) {
216   VLOG(1) << __func__;
217   if (!tpm_nvram_->ReadNvram(request.index(), result->mutable_data())) {
218     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
219     return;
220   }
221   result->set_status(STATUS_SUCCESS);
222 }
223 
IsNvramDefined(const IsNvramDefinedRequest & request,const IsNvramDefinedCallback & callback)224 void TpmManagerService::IsNvramDefined(const IsNvramDefinedRequest& request,
225                                        const IsNvramDefinedCallback& callback) {
226   PostTaskToWorkerThread<IsNvramDefinedReply>(
227       request, callback, &TpmManagerService::IsNvramDefinedTask);
228 }
229 
IsNvramDefinedTask(const IsNvramDefinedRequest & request,const std::shared_ptr<IsNvramDefinedReply> & result)230 void TpmManagerService::IsNvramDefinedTask(
231     const IsNvramDefinedRequest& request,
232     const std::shared_ptr<IsNvramDefinedReply>& result) {
233   VLOG(1) << __func__;
234   bool defined;
235   if (!tpm_nvram_->IsNvramDefined(request.index(), &defined)) {
236     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
237     return;
238   }
239   result->set_is_defined(defined);
240   result->set_status(STATUS_SUCCESS);
241 }
242 
IsNvramLocked(const IsNvramLockedRequest & request,const IsNvramLockedCallback & callback)243 void TpmManagerService::IsNvramLocked(const IsNvramLockedRequest& request,
244                                       const IsNvramLockedCallback& callback) {
245   PostTaskToWorkerThread<IsNvramLockedReply>(
246       request, callback, &TpmManagerService::IsNvramLockedTask);
247 }
248 
IsNvramLockedTask(const IsNvramLockedRequest & request,const std::shared_ptr<IsNvramLockedReply> & result)249 void TpmManagerService::IsNvramLockedTask(
250     const IsNvramLockedRequest& request,
251     const std::shared_ptr<IsNvramLockedReply>& result) {
252   VLOG(1) << __func__;
253   bool locked;
254   if (!tpm_nvram_->IsNvramLocked(request.index(), &locked)) {
255     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
256     return;
257   }
258   result->set_is_locked(locked);
259   result->set_status(STATUS_SUCCESS);
260 }
261 
GetNvramSize(const GetNvramSizeRequest & request,const GetNvramSizeCallback & callback)262 void TpmManagerService::GetNvramSize(const GetNvramSizeRequest& request,
263                                      const GetNvramSizeCallback& callback) {
264   PostTaskToWorkerThread<GetNvramSizeReply>(
265       request, callback, &TpmManagerService::GetNvramSizeTask);
266 }
267 
GetNvramSizeTask(const GetNvramSizeRequest & request,const std::shared_ptr<GetNvramSizeReply> & result)268 void TpmManagerService::GetNvramSizeTask(
269     const GetNvramSizeRequest& request,
270     const std::shared_ptr<GetNvramSizeReply>& result) {
271   VLOG(1) << __func__;
272   size_t size;
273   if (!tpm_nvram_->GetNvramSize(request.index(), &size)) {
274     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
275     return;
276   }
277   result->set_size(size);
278   result->set_status(STATUS_SUCCESS);
279 }
280 
281 template<typename ReplyProtobufType>
TaskRelayCallback(const base::Callback<void (const ReplyProtobufType &)> callback,const std::shared_ptr<ReplyProtobufType> & reply)282 void TpmManagerService::TaskRelayCallback(
283     const base::Callback<void(const ReplyProtobufType&)> callback,
284     const std::shared_ptr<ReplyProtobufType>& reply) {
285   callback.Run(*reply);
286 }
287 
288 template<typename ReplyProtobufType,
289          typename RequestProtobufType,
290          typename ReplyCallbackType,
291          typename TaskType>
PostTaskToWorkerThread(RequestProtobufType & request,ReplyCallbackType & callback,TaskType task)292 void TpmManagerService::PostTaskToWorkerThread(RequestProtobufType& request,
293                                                ReplyCallbackType& callback,
294                                                TaskType task) {
295   auto result = std::make_shared<ReplyProtobufType>();
296   base::Closure background_task = base::Bind(task,
297                                              base::Unretained(this),
298                                              request,
299                                              result);
300   base::Closure reply = base::Bind(
301       &TpmManagerService::TaskRelayCallback<ReplyProtobufType>,
302       weak_factory_.GetWeakPtr(),
303       callback,
304       result);
305   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE,
306                                                   background_task,
307                                                   reply);
308 }
309 
310 }  // namespace tpm_manager
311