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 29namespace { 30const size_t kDefaultPasswordSize = 20; 31} // namespace 32 33namespace tpm_manager { 34 35Tpm2InitializerImpl::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 42Tpm2InitializerImpl::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 51bool 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 112bool 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 125bool 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