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