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_initializer_impl.h"
18
19 #include <string>
20
21 #include <base/logging.h>
22 #include <base/stl_util.h>
23 #include <trousers/scoped_tss_type.h>
24
25 #include "tpm_manager/server/local_data_store.h"
26 #include "tpm_manager/server/tpm_connection.h"
27 #include "tpm_manager/common/tpm_manager_constants.h"
28 #include "tpm_manager/server/tpm_status.h"
29 #include "tpm_manager/server/tpm_util.h"
30
31 namespace {
32
33 const char kDefaultOwnerPassword[] = TSS_WELL_KNOWN_SECRET;
34 const size_t kDefaultPasswordSize = 20;
35 const int kMaxOwnershipTimeoutRetries = 5;
36 const char* kWellKnownSrkSecret = "well_known_srk_secret";
37
38 } // namespace
39
40 namespace tpm_manager {
41
TpmInitializerImpl(LocalDataStore * local_data_store,TpmStatus * tpm_status)42 TpmInitializerImpl::TpmInitializerImpl(LocalDataStore* local_data_store,
43 TpmStatus* tpm_status)
44 : local_data_store_(local_data_store),
45 tpm_status_(tpm_status) {}
46
InitializeTpm()47 bool TpmInitializerImpl::InitializeTpm() {
48 if (tpm_status_->IsTpmOwned() && !TestTpmAuth(kDefaultOwnerPassword)) {
49 // Tpm is already owned, so we do not need to do anything.
50 VLOG(1) << "Tpm already owned.";
51 return true;
52 }
53 TSS_HTPM tpm_handle = tpm_connection_.GetTpm();
54 if (tpm_handle == 0) {
55 return false;
56 }
57 if (!InitializeEndorsementKey(tpm_handle) ||
58 !TakeOwnership(tpm_handle) ||
59 !InitializeSrk(tpm_handle)) {
60 return false;
61 }
62 std::string owner_password;
63 if (!openssl_util_.GetRandomBytes(kDefaultPasswordSize, &owner_password)) {
64 return false;
65 }
66 LocalData local_data;
67 local_data.clear_owner_dependency();
68 for (auto value: kInitialTpmOwnerDependencies) {
69 local_data.add_owner_dependency(value);
70 }
71 local_data.set_owner_password(owner_password);
72 if (!local_data_store_->Write(local_data)) {
73 LOG(ERROR) << "Error saving local data.";
74 return false;
75 }
76 if (!ChangeOwnerPassword(tpm_handle, owner_password)) {
77 return false;
78 }
79 return true;
80 }
81
InitializeEndorsementKey(TSS_HTPM tpm_handle)82 bool TpmInitializerImpl::InitializeEndorsementKey(TSS_HTPM tpm_handle) {
83 trousers::ScopedTssKey local_key_handle(tpm_connection_.GetContext());
84 TSS_RESULT result = Tspi_TPM_GetPubEndorsementKey(tpm_handle,
85 false,
86 nullptr,
87 local_key_handle.ptr());
88 if (TPM_ERROR(result) == TPM_SUCCESS) {
89 // In this case the EK already exists, so we can return true here.
90 return true;
91 }
92 // At this point the EK does not exist, so we create it.
93 TSS_FLAG init_flags = TSS_KEY_TYPE_LEGACY | TSS_KEY_SIZE_2048;
94 if (TPM_ERROR(result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
95 TSS_OBJECT_TYPE_RSAKEY,
96 init_flags,
97 local_key_handle.ptr()))) {
98 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
99 return false;
100 }
101 if (TPM_ERROR(result = Tspi_TPM_CreateEndorsementKey(tpm_handle,
102 local_key_handle,
103 NULL))) {
104 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_CreateEndorsementKey";
105 return false;
106 }
107 return true;
108 }
109
TakeOwnership(TSS_HTPM tpm_handle)110 bool TpmInitializerImpl::TakeOwnership(TSS_HTPM tpm_handle) {
111 if (TestTpmAuth(kDefaultOwnerPassword)) {
112 VLOG(1) << "The Tpm already has the default owner password.";
113 return true;
114 }
115 TSS_RESULT result;
116 trousers::ScopedTssKey srk_handle(tpm_connection_.GetContext());
117 TSS_FLAG init_flags = TSS_KEY_TSP_SRK | TSS_KEY_AUTHORIZATION;
118 if (TPM_ERROR(result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
119 TSS_OBJECT_TYPE_RSAKEY,
120 init_flags,
121 srk_handle.ptr()))) {
122 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
123 return false;
124 }
125 TSS_HPOLICY srk_usage_policy;
126 if (TPM_ERROR(result = Tspi_GetPolicyObject(srk_handle,
127 TSS_POLICY_USAGE,
128 &srk_usage_policy))) {
129 TPM_LOG(ERROR, result) << "Error calling Tspi_GetPolicyObject";
130 return false;
131 }
132 if (TPM_ERROR(result = Tspi_Policy_SetSecret(
133 srk_usage_policy,
134 TSS_SECRET_MODE_PLAIN,
135 strlen(kWellKnownSrkSecret),
136 const_cast<BYTE *>(reinterpret_cast<const BYTE *>(
137 kWellKnownSrkSecret))))) {
138 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
139 return false;
140 }
141 // Tspi_TPM_TakeOwnership can potentailly take a long time to complete,
142 // so we retry if there is a timeout in any layer. I chose 5, because the
143 // longest TakeOwnership call that I have seen took ~2min, and the default
144 // TSS timeout is 30s. This means that after 5 calls, it is quite likely that
145 // this call will succeed.
146 int retry_count = 0;
147 do {
148 result = Tspi_TPM_TakeOwnership(tpm_handle, srk_handle, 0);
149 retry_count++;
150 } while (((result == TDDL_E_TIMEOUT) ||
151 (result == (TSS_LAYER_TDDL | TDDL_E_TIMEOUT)) ||
152 (result == (TSS_LAYER_TDDL | TDDL_E_IOERROR))) &&
153 (retry_count < kMaxOwnershipTimeoutRetries));
154 if (result) {
155 TPM_LOG(ERROR, result)
156 << "Error calling Tspi_TPM_TakeOwnership, attempts: " << retry_count;
157 return false;
158 }
159 return true;
160 }
161
InitializeSrk(TSS_HTPM tpm_handle)162 bool TpmInitializerImpl::InitializeSrk(TSS_HTPM tpm_handle) {
163 TSS_RESULT result;
164 trousers::ScopedTssKey srk_handle(tpm_connection_.GetContext());
165 TSS_UUID SRK_UUID = TSS_UUID_SRK;
166 if (TPM_ERROR(result = Tspi_Context_LoadKeyByUUID(
167 tpm_connection_.GetContext(),
168 TSS_PS_TYPE_SYSTEM,
169 SRK_UUID,
170 srk_handle.ptr()))) {
171 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_LoadKeyByUUID";
172 return false;
173 }
174
175 trousers::ScopedTssPolicy policy_handle(tpm_connection_.GetContext());
176 if (TPM_ERROR(result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
177 TSS_OBJECT_TYPE_POLICY,
178 TSS_POLICY_USAGE,
179 policy_handle.ptr()))) {
180 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
181 return false;
182 }
183 BYTE new_password[0];
184 if (TPM_ERROR(result = Tspi_Policy_SetSecret(policy_handle,
185 TSS_SECRET_MODE_PLAIN,
186 0,
187 new_password))) {
188 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
189 return false;
190 }
191
192 if (TPM_ERROR(result = Tspi_ChangeAuth(srk_handle,
193 tpm_handle,
194 policy_handle))) {
195 TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
196 return false;
197 }
198 TSS_BOOL is_srk_restricted = false;
199 if (TPM_ERROR(result = Tspi_TPM_GetStatus(tpm_handle,
200 TSS_TPMSTATUS_DISABLEPUBSRKREAD,
201 &is_srk_restricted))) {
202 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_GetStatus";
203 return false;
204 }
205 // If the SRK is restricted, we unrestrict it.
206 if (is_srk_restricted) {
207 if (TPM_ERROR(result = Tspi_TPM_SetStatus(tpm_handle,
208 TSS_TPMSTATUS_DISABLEPUBSRKREAD,
209 false))) {
210 TPM_LOG(ERROR, result) << "Error calling Tspi_TPM_SetStatus";
211 return false;
212 }
213 }
214 return true;
215 }
216
ChangeOwnerPassword(TSS_HTPM tpm_handle,const std::string & owner_password)217 bool TpmInitializerImpl::ChangeOwnerPassword(
218 TSS_HTPM tpm_handle, const std::string& owner_password) {
219 TSS_RESULT result;
220 trousers::ScopedTssPolicy policy_handle(tpm_connection_.GetContext());
221 if (TPM_ERROR(result = Tspi_Context_CreateObject(tpm_connection_.GetContext(),
222 TSS_OBJECT_TYPE_POLICY,
223 TSS_POLICY_USAGE,
224 policy_handle.ptr()))) {
225 TPM_LOG(ERROR, result) << "Error calling Tspi_Context_CreateObject";
226 return false;
227 }
228 std::string mutable_owner_password(owner_password);
229 if (TPM_ERROR(result = Tspi_Policy_SetSecret(policy_handle,
230 TSS_SECRET_MODE_PLAIN,
231 owner_password.size(),
232 reinterpret_cast<BYTE *>(string_as_array(&mutable_owner_password))))) {
233 TPM_LOG(ERROR, result) << "Error calling Tspi_Policy_SetSecret";
234 return false;
235 }
236
237 if (TPM_ERROR(result = Tspi_ChangeAuth(tpm_handle, 0, policy_handle))) {
238 TPM_LOG(ERROR, result) << "Error calling Tspi_ChangeAuth";
239 return false;
240 }
241
242 return true;
243 }
244
TestTpmAuth(const std::string & owner_password)245 bool TpmInitializerImpl::TestTpmAuth(const std::string& owner_password) {
246 TSS_HTPM tpm_handle = tpm_connection_.GetTpmWithAuth(owner_password);
247 if (tpm_handle == 0) {
248 return false;
249 }
250 // Call Tspi_TPM_GetStatus to test the |owner_password| provided.
251 TSS_RESULT result;
252 TSS_BOOL current_status = false;
253 if (TPM_ERROR(result = Tspi_TPM_GetStatus(tpm_handle,
254 TSS_TPMSTATUS_DISABLED,
255 ¤t_status))) {
256 return false;
257 }
258 return true;
259 }
260
261 } // namespace tpm_manager
262