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