246 lines
8.1 KiB
C++
246 lines
8.1 KiB
C++
//
|
|
// Copyright (C) 2014 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 "trunks/tpm_state_impl.h"
|
|
|
|
#include <base/logging.h>
|
|
|
|
#include "trunks/error_codes.h"
|
|
#include "trunks/tpm_generated.h"
|
|
#include "trunks/trunks_factory.h"
|
|
|
|
namespace {
|
|
|
|
// From definition of TPMA_PERMANENT.
|
|
const trunks::TPMA_PERMANENT kOwnerAuthSetMask = 1U;
|
|
const trunks::TPMA_PERMANENT kEndorsementAuthSetMask = 1U << 1;
|
|
const trunks::TPMA_PERMANENT kLockoutAuthSetMask = 1U << 2;
|
|
const trunks::TPMA_PERMANENT kInLockoutMask = 1U << 9;
|
|
|
|
// From definition of TPMA_STARTUP_CLEAR.
|
|
const trunks::TPMA_STARTUP_CLEAR kPlatformHierarchyMask = 1U;
|
|
const trunks::TPMA_STARTUP_CLEAR kStorageHierarchyMask = 1U << 1;
|
|
const trunks::TPMA_STARTUP_CLEAR kEndorsementHierarchyMask = 1U << 2;
|
|
const trunks::TPMA_STARTUP_CLEAR kOrderlyShutdownMask = 1U << 31;
|
|
|
|
// From definition of TPMA_ALGORITHM
|
|
const trunks::TPMA_ALGORITHM kAsymmetricAlgMask = 1U;
|
|
|
|
} // namespace
|
|
|
|
namespace trunks {
|
|
|
|
TpmStateImpl::TpmStateImpl(const TrunksFactory& factory)
|
|
: factory_(factory),
|
|
initialized_(false),
|
|
permanent_flags_(0),
|
|
startup_clear_flags_(0),
|
|
rsa_flags_(0),
|
|
ecc_flags_(0) {
|
|
}
|
|
|
|
TpmStateImpl::~TpmStateImpl() {}
|
|
|
|
TPM_RC TpmStateImpl::Initialize() {
|
|
TPM_RC result = GetTpmProperty(TPM_PT_PERMANENT, &permanent_flags_);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << "Error getting permanent flags: " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
result = GetTpmProperty(TPM_PT_STARTUP_CLEAR, &startup_clear_flags_);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << "Error getting startup flags: " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
result = GetTpmProperty(TPM_PT_LOCKOUT_COUNTER, &lockout_counter_);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << "Error getting lockout counter: " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
result = GetTpmProperty(TPM_PT_MAX_AUTH_FAIL, &lockout_threshold_);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << "Error getting lockout threshold: " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
result = GetTpmProperty(TPM_PT_LOCKOUT_INTERVAL, &lockout_interval_);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << "Error getting lockout interval: " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
result = GetTpmProperty(TPM_PT_LOCKOUT_RECOVERY, &lockout_recovery_);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << "Error getting lockout recovery: " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
|
|
TPMI_YES_NO more_data;
|
|
TPMS_CAPABILITY_DATA capability_data;
|
|
result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS,
|
|
TPM_ALG_RSA,
|
|
1, // There is only one value.
|
|
&more_data,
|
|
&capability_data,
|
|
nullptr);
|
|
if (result) {
|
|
LOG(ERROR) << __func__ << ": " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
if (capability_data.capability != TPM_CAP_ALGS ||
|
|
capability_data.data.algorithms.count != 1) {
|
|
LOG(ERROR) << __func__ << ": Unexpected capability data.";
|
|
return SAPI_RC_MALFORMED_RESPONSE;
|
|
}
|
|
if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_RSA) {
|
|
rsa_flags_ =
|
|
capability_data.data.algorithms.alg_properties[0].alg_properties;
|
|
}
|
|
result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS,
|
|
TPM_ALG_ECC,
|
|
1, // There is only one value.
|
|
&more_data,
|
|
&capability_data,
|
|
nullptr);
|
|
if (result) {
|
|
LOG(ERROR) << __func__ << ": " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
if (capability_data.capability != TPM_CAP_ALGS ||
|
|
capability_data.data.algorithms.count != 1) {
|
|
LOG(ERROR) << __func__ << ": Unexpected capability data.";
|
|
return SAPI_RC_MALFORMED_RESPONSE;
|
|
}
|
|
if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_ECC) {
|
|
ecc_flags_ =
|
|
capability_data.data.algorithms.alg_properties[0].alg_properties;
|
|
}
|
|
initialized_ = true;
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
bool TpmStateImpl::IsOwnerPasswordSet() {
|
|
CHECK(initialized_);
|
|
return ((permanent_flags_ & kOwnerAuthSetMask) == kOwnerAuthSetMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsEndorsementPasswordSet() {
|
|
CHECK(initialized_);
|
|
return ((permanent_flags_ & kEndorsementAuthSetMask) ==
|
|
kEndorsementAuthSetMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsLockoutPasswordSet() {
|
|
CHECK(initialized_);
|
|
return ((permanent_flags_ & kLockoutAuthSetMask) == kLockoutAuthSetMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsOwned() {
|
|
return (IsOwnerPasswordSet() &&
|
|
IsEndorsementPasswordSet() &&
|
|
IsLockoutPasswordSet());
|
|
}
|
|
|
|
bool TpmStateImpl::IsInLockout() {
|
|
CHECK(initialized_);
|
|
return ((permanent_flags_ & kInLockoutMask) == kInLockoutMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsPlatformHierarchyEnabled() {
|
|
CHECK(initialized_);
|
|
return ((startup_clear_flags_ & kPlatformHierarchyMask) ==
|
|
kPlatformHierarchyMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsStorageHierarchyEnabled() {
|
|
CHECK(initialized_);
|
|
return ((startup_clear_flags_ & kStorageHierarchyMask) ==
|
|
kStorageHierarchyMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsEndorsementHierarchyEnabled() {
|
|
CHECK(initialized_);
|
|
return ((startup_clear_flags_ & kEndorsementHierarchyMask) ==
|
|
kEndorsementHierarchyMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsEnabled() {
|
|
return (!IsPlatformHierarchyEnabled() &&
|
|
IsStorageHierarchyEnabled() &&
|
|
IsEndorsementHierarchyEnabled());
|
|
}
|
|
|
|
bool TpmStateImpl::WasShutdownOrderly() {
|
|
CHECK(initialized_);
|
|
return ((startup_clear_flags_ & kOrderlyShutdownMask) ==
|
|
kOrderlyShutdownMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsRSASupported() {
|
|
CHECK(initialized_);
|
|
return ((rsa_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
|
|
}
|
|
|
|
bool TpmStateImpl::IsECCSupported() {
|
|
CHECK(initialized_);
|
|
return ((ecc_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
|
|
}
|
|
|
|
uint32_t TpmStateImpl::GetLockoutCounter() {
|
|
CHECK(initialized_);
|
|
return lockout_counter_;
|
|
}
|
|
|
|
uint32_t TpmStateImpl::GetLockoutThreshold() {
|
|
CHECK(initialized_);
|
|
return lockout_threshold_;
|
|
}
|
|
|
|
uint32_t TpmStateImpl::GetLockoutInterval() {
|
|
CHECK(initialized_);
|
|
return lockout_interval_;
|
|
}
|
|
|
|
uint32_t TpmStateImpl::GetLockoutRecovery() {
|
|
CHECK(initialized_);
|
|
return lockout_recovery_;
|
|
}
|
|
|
|
TPM_RC TpmStateImpl::GetTpmProperty(uint32_t property,
|
|
uint32_t* value) {
|
|
CHECK(value);
|
|
TPMI_YES_NO more_data;
|
|
TPMS_CAPABILITY_DATA capability_data;
|
|
TPM_RC result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_TPM_PROPERTIES,
|
|
property,
|
|
1, // Only one property.
|
|
&more_data,
|
|
&capability_data,
|
|
nullptr);
|
|
if (result != TPM_RC_SUCCESS) {
|
|
LOG(ERROR) << __func__ << ": " << GetErrorString(result);
|
|
return result;
|
|
}
|
|
if (capability_data.capability != TPM_CAP_TPM_PROPERTIES ||
|
|
capability_data.data.tpm_properties.count != 1 ||
|
|
capability_data.data.tpm_properties.tpm_property[0].property !=
|
|
property) {
|
|
LOG(ERROR) << __func__ << ": Unexpected capability data.";
|
|
return SAPI_RC_MALFORMED_RESPONSE;
|
|
}
|
|
*value = capability_data.data.tpm_properties.tpm_property[0].value;
|
|
return TPM_RC_SUCCESS;
|
|
}
|
|
|
|
} // namespace trunks
|