• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/error_codes.h>
23 #include <trunks/tpm_utility.h>
24 #include <trunks/trunks_factory_impl.h>
25 
26 #include "tpm_manager/common/tpm_manager.pb.h"
27 #include "tpm_manager/common/tpm_manager_constants.h"
28 #include "tpm_manager/server/openssl_crypto_util_impl.h"
29 
30 using trunks::TPM_RC;
31 using trunks::TPM_RC_SUCCESS;
32 
33 namespace {
34 const size_t kDefaultPasswordSize = 20;
35 }  // namespace
36 
37 namespace tpm_manager {
38 
Tpm2InitializerImpl(const trunks::TrunksFactory & factory,LocalDataStore * local_data_store,TpmStatus * tpm_status)39 Tpm2InitializerImpl::Tpm2InitializerImpl(const trunks::TrunksFactory& factory,
40                                          LocalDataStore* local_data_store,
41                                          TpmStatus* tpm_status)
42     : trunks_factory_(factory),
43       openssl_util_(new OpensslCryptoUtilImpl()),
44       local_data_store_(local_data_store),
45       tpm_status_(tpm_status) {}
46 
Tpm2InitializerImpl(const trunks::TrunksFactory & factory,OpensslCryptoUtil * openssl_util,LocalDataStore * local_data_store,TpmStatus * tpm_status)47 Tpm2InitializerImpl::Tpm2InitializerImpl(const trunks::TrunksFactory& factory,
48                                          OpensslCryptoUtil* openssl_util,
49                                          LocalDataStore* local_data_store,
50                                          TpmStatus* tpm_status)
51     : trunks_factory_(factory),
52       openssl_util_(openssl_util),
53       local_data_store_(local_data_store),
54       tpm_status_(tpm_status) {}
55 
InitializeTpm()56 bool Tpm2InitializerImpl::InitializeTpm() {
57   if (!SeedTpmRng()) {
58     return false;
59   }
60   if (tpm_status_->IsTpmOwned()) {
61     // Tpm is already owned, so we do not need to do anything.
62     VLOG(1) << "Tpm already owned.";
63     return true;
64   }
65   // First we read the local data. If we did not finish removing owner
66   // dependencies or if TakeOwnership failed, we want to retake ownership
67   // with the same passwords.
68   LocalData local_data;
69   if (!local_data_store_->Read(&local_data)) {
70     LOG(ERROR) << "Error reading local data.";
71     return false;
72   }
73   std::string owner_password;
74   std::string endorsement_password;
75   std::string lockout_password;
76   // If there are valid owner dependencies, we need to reuse the old passwords.
77   if (local_data.owner_dependency_size() > 0) {
78     owner_password.assign(local_data.owner_password());
79     endorsement_password.assign(local_data.endorsement_password());
80     lockout_password.assign(local_data.lockout_password());
81   } else {
82     if (!GetTpmRandomData(kDefaultPasswordSize, &owner_password)) {
83       LOG(ERROR) << "Error generating a random owner password.";
84       return false;
85     }
86     if (!GetTpmRandomData(kDefaultPasswordSize, &endorsement_password)) {
87       LOG(ERROR) << "Error generating a random endorsement password.";
88       return false;
89     }
90     if (!GetTpmRandomData(kDefaultPasswordSize, &lockout_password)) {
91       LOG(ERROR) << "Error generating a random lockout password.";
92       return false;
93     }
94   }
95   // We write the passwords to disk, in case there is an error while taking
96   // ownership.
97   local_data.clear_owner_dependency();
98   for (auto dependency : kInitialTpmOwnerDependencies) {
99     local_data.add_owner_dependency(dependency);
100   }
101   local_data.set_owner_password(owner_password);
102   local_data.set_endorsement_password(endorsement_password);
103   local_data.set_lockout_password(lockout_password);
104   if (!local_data_store_->Write(local_data)) {
105     LOG(ERROR) << "Error saving local data.";
106     return false;
107   }
108   TPM_RC result = trunks_factory_.GetTpmUtility()->TakeOwnership(
109       owner_password, endorsement_password, lockout_password);
110   if (result != TPM_RC_SUCCESS) {
111     LOG(ERROR) << "Error taking ownership of TPM2.0";
112     return false;
113   }
114 
115   return true;
116 }
117 
VerifiedBootHelper()118 void Tpm2InitializerImpl::VerifiedBootHelper() {
119   constexpr char kVerifiedBootLateStageTag[] = "BOOT_PCR_LATE_STAGE";
120   std::unique_ptr<trunks::TpmUtility> tpm_utility =
121       trunks_factory_.GetTpmUtility();
122   // Make sure PCRs 0-3 can't be spoofed from this point forward.
123   for (int pcr : {0, 1, 2, 3}) {
124     std::string value;
125     TPM_RC result = tpm_utility->ReadPCR(pcr, &value);
126     if (result) {
127       LOG(ERROR) << "Failed to read PCR " << pcr << ": "
128                  << trunks::GetErrorString(result);
129       continue;
130     }
131     if (value == std::string(32, 0)) {
132       LOG(WARNING) << "WARNING: Verified boot PCR " << pcr
133                    << " is not initialized.";
134       result = tpm_utility->ExtendPCR(pcr, kVerifiedBootLateStageTag, nullptr);
135       if (result) {
136         LOG(ERROR) << "Failed to extend PCR " << pcr << ": "
137                    << trunks::GetErrorString(result);
138       }
139     }
140   }
141 }
142 
ResetDictionaryAttackLock()143 bool Tpm2InitializerImpl::ResetDictionaryAttackLock() {
144   LocalData local_data;
145   if (!local_data_store_->Read(&local_data)) {
146     LOG(ERROR) << __func__ << ": Error reading local data.";
147     return false;
148   }
149   if (!local_data.has_lockout_password()) {
150     LOG(ERROR) << __func__ << ": Lockout password not available.";
151     return false;
152   }
153   std::unique_ptr<trunks::HmacSession> session =
154       trunks_factory_.GetHmacSession();
155   TPM_RC result = session->StartUnboundSession(false);
156   if (result != TPM_RC_SUCCESS) {
157     LOG(ERROR) << __func__ << ": Error initializing AuthorizationSession: "
158                << trunks::GetErrorString(result);
159     return false;
160   }
161   session->SetEntityAuthorizationValue(local_data.lockout_password());
162   std::unique_ptr<trunks::TpmUtility> tpm_utility =
163       trunks_factory_.GetTpmUtility();
164   result =
165       tpm_utility->ResetDictionaryAttackLock(session->GetDelegate());
166   if (result != TPM_RC_SUCCESS) {
167     LOG(ERROR) << __func__ << ": Error resetting lock: "
168                << trunks::GetErrorString(result);
169     return false;
170   }
171   return true;
172 }
173 
SeedTpmRng()174 bool Tpm2InitializerImpl::SeedTpmRng() {
175   std::string random_bytes;
176   if (!openssl_util_->GetRandomBytes(kDefaultPasswordSize, &random_bytes)) {
177     return false;
178   }
179   TPM_RC result = trunks_factory_.GetTpmUtility()->StirRandom(
180       random_bytes, nullptr /* No Authorization */);
181   if (result != TPM_RC_SUCCESS) {
182     return false;
183   }
184   return true;
185 }
186 
GetTpmRandomData(size_t num_bytes,std::string * random_data)187 bool Tpm2InitializerImpl::GetTpmRandomData(size_t num_bytes,
188                                            std::string* random_data) {
189   TPM_RC result = trunks_factory_.GetTpmUtility()->GenerateRandom(
190       num_bytes, nullptr /* No Authorization */, random_data);
191   if (result != TPM_RC_SUCCESS) {
192     return false;
193   }
194   return true;
195 }
196 
197 }  // namespace tpm_manager
198