blob: ca9f7b009e8426cef62ec42d1a482882b1ec1498 [file] [log] [blame]
//
// 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