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/tpm2_initializer_impl.h"
18
19 #include <string>
20
21 #include <base/logging.h>
22 #include <trunks/tpm_utility.h>
23 #include <trunks/trunks_factory_impl.h>
24
25 #include "tpm_manager/common/local_data.pb.h"
26 #include "tpm_manager/common/tpm_manager_constants.h"
27 #include "tpm_manager/server/openssl_crypto_util_impl.h"
28
29 namespace {
30 const size_t kDefaultPasswordSize = 20;
31 } // namespace
32
33 namespace tpm_manager {
34
Tpm2InitializerImpl(LocalDataStore * local_data_store,TpmStatus * tpm_status)35 Tpm2InitializerImpl::Tpm2InitializerImpl(LocalDataStore* local_data_store,
36 TpmStatus* tpm_status)
37 : trunks_factory_(new trunks::TrunksFactoryImpl()),
38 openssl_util_(new OpensslCryptoUtilImpl()),
39 local_data_store_(local_data_store),
40 tpm_status_(tpm_status) {}
41
Tpm2InitializerImpl(trunks::TrunksFactory * factory,OpensslCryptoUtil * openssl_util,LocalDataStore * local_data_store,TpmStatus * tpm_status)42 Tpm2InitializerImpl::Tpm2InitializerImpl(trunks::TrunksFactory* factory,
43 OpensslCryptoUtil* openssl_util,
44 LocalDataStore* local_data_store,
45 TpmStatus* tpm_status)
46 : trunks_factory_(factory),
47 openssl_util_(openssl_util),
48 local_data_store_(local_data_store),
49 tpm_status_(tpm_status) {}
50
InitializeTpm()51 bool Tpm2InitializerImpl::InitializeTpm() {
52 if (!SeedTpmRng()) {
53 return false;
54 }
55 if (tpm_status_->IsTpmOwned()) {
56 // Tpm is already owned, so we do not need to do anything.
57 VLOG(1) << "Tpm already owned.";
58 return true;
59 }
60 // First we read the local data. If we did not finish removing owner
61 // dependencies or if TakeOwnership failed, we want to retake ownership
62 // with the same passwords.
63 LocalData local_data;
64 if (!local_data_store_->Read(&local_data)) {
65 LOG(ERROR) << "Error reading local data.";
66 return false;
67 }
68 std::string owner_password;
69 std::string endorsement_password;
70 std::string lockout_password;
71 // If there are valid owner dependencies, we need to reuse the old passwords.
72 if (local_data.owner_dependency_size() > 0) {
73 owner_password.assign(local_data.owner_password());
74 endorsement_password.assign(local_data.endorsement_password());
75 lockout_password.assign(local_data.lockout_password());
76 } else {
77 if (!GetTpmRandomData(kDefaultPasswordSize, &owner_password)) {
78 LOG(ERROR) << "Error generating a random owner password.";
79 return false;
80 }
81 if (!GetTpmRandomData(kDefaultPasswordSize, &endorsement_password)) {
82 LOG(ERROR) << "Error generating a random endorsement password.";
83 return false;
84 }
85 if (!GetTpmRandomData(kDefaultPasswordSize, &lockout_password)) {
86 LOG(ERROR) << "Error generating a random lockout password.";
87 return false;
88 }
89 }
90 // We write the passwords to disk, in case there is an error while taking
91 // ownership.
92 local_data.clear_owner_dependency();
93 for (auto dependency: kInitialTpmOwnerDependencies) {
94 local_data.add_owner_dependency(dependency);
95 }
96 local_data.set_owner_password(owner_password);
97 local_data.set_endorsement_password(endorsement_password);
98 local_data.set_lockout_password(lockout_password);
99 if (!local_data_store_->Write(local_data)) {
100 LOG(ERROR) << "Error saving local data.";
101 return false;
102 }
103 trunks::TPM_RC result = trunks_factory_->GetTpmUtility()->TakeOwnership(
104 owner_password, endorsement_password, lockout_password);
105 if (result != trunks::TPM_RC_SUCCESS) {
106 LOG(ERROR) << "Error taking ownership of TPM2.0";
107 return false;
108 }
109 return true;
110 }
111
SeedTpmRng()112 bool Tpm2InitializerImpl::SeedTpmRng() {
113 std::string random_bytes;
114 if (!openssl_util_->GetRandomBytes(kDefaultPasswordSize, &random_bytes)) {
115 return false;
116 }
117 trunks::TPM_RC result = trunks_factory_->GetTpmUtility()->StirRandom(
118 random_bytes, nullptr /* No Authorization */);
119 if (result != trunks::TPM_RC_SUCCESS) {
120 return false;
121 }
122 return true;
123 }
124
GetTpmRandomData(size_t num_bytes,std::string * random_data)125 bool Tpm2InitializerImpl::GetTpmRandomData(size_t num_bytes,
126 std::string* random_data) {
127 trunks::TPM_RC result = trunks_factory_->GetTpmUtility()->GenerateRandom(
128 num_bytes, nullptr /* No Authorization */, random_data);
129 if (result != trunks::TPM_RC_SUCCESS) {
130 return false;
131 }
132 return true;
133 }
134
135 } // namespace tpm_manager
136