// // Copyright (C) 2015 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #include "tpm_manager/server/tpm_status_impl.h" #include <vector> #include <base/logging.h> #include <trousers/tss.h> #include <trousers/trousers.h> // NOLINT(build/include_alpha) namespace tpm_manager { // Minimum size of TPM_DA_INFO struct. const size_t kMinimumDaInfoSize = 21; bool TpmStatusImpl::IsTpmEnabled() { if (!is_enable_initialized_) { RefreshOwnedEnabledInfo(); } return is_enabled_; } bool TpmStatusImpl::IsTpmOwned() { if (!is_owned_) { RefreshOwnedEnabledInfo(); } return is_owned_; } bool TpmStatusImpl::GetDictionaryAttackInfo(int* counter, int* threshold, bool* lockout, int* seconds_remaining) { std::string capability_data; if (!GetCapability(TSS_TPMCAP_DA_LOGIC, TPM_ET_KEYHANDLE, &capability_data, nullptr) || capability_data.size() < kMinimumDaInfoSize) { LOG(ERROR) << "Error getting tpm capability data."; return false; } if (static_cast<uint16_t>(capability_data[1]) == TPM_TAG_DA_INFO) { TPM_DA_INFO da_info; uint64_t offset = 0; std::vector<BYTE> bytes(capability_data.begin(), capability_data.end()); Trspi_UnloadBlob_DA_INFO(&offset, bytes.data(), &da_info); if (counter) { *counter = da_info.currentCount; } if (threshold) { *threshold = da_info.thresholdCount; } if (lockout) { *lockout = (da_info.state == TPM_DA_STATE_ACTIVE); } if (seconds_remaining) { *seconds_remaining = da_info.actionDependValue; } } return true; } void TpmStatusImpl::RefreshOwnedEnabledInfo() { TSS_RESULT result; std::string capability_data; if (!GetCapability(TSS_TPMCAP_PROPERTY, TSS_TPMCAP_PROP_OWNER, &capability_data, &result)) { if (ERROR_CODE(result) == TPM_E_DISABLED) { is_enable_initialized_ = true; is_enabled_ = false; } } else { is_enable_initialized_ = true; is_enabled_ = true; // |capability_data| should be populated with a TSS_BOOL which is true iff // the Tpm is owned. if (capability_data.size() != sizeof(TSS_BOOL)) { LOG(ERROR) << "Error refreshing Tpm ownership information."; return; } is_owned_ = (capability_data[0] != 0); } } bool TpmStatusImpl::GetCapability(uint32_t capability, uint32_t sub_capability, std::string* data, TSS_RESULT* tpm_result) { CHECK(data); TSS_HTPM tpm_handle = tpm_connection_.GetTpm(); if (tpm_handle == 0) { return false; } uint32_t length = 0; trousers::ScopedTssMemory buf(tpm_connection_.GetContext()); TSS_RESULT result = Tspi_TPM_GetCapability( tpm_handle, capability, sizeof(uint32_t), reinterpret_cast<BYTE*>(&sub_capability), &length, buf.ptr()); if (tpm_result) { *tpm_result = result; } if (TPM_ERROR(result)) { LOG(ERROR) << "Error getting TPM capability data."; return false; } data->assign(buf.value(), buf.value() + length); return true; } } // namespace tpm_manager