1// 2// Copyright (C) 2014 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 "trunks/tpm_state_impl.h" 18 19#include <base/logging.h> 20 21#include "trunks/error_codes.h" 22#include "trunks/tpm_generated.h" 23#include "trunks/trunks_factory.h" 24 25namespace { 26 27// From definition of TPMA_PERMANENT. 28const trunks::TPMA_PERMANENT kOwnerAuthSetMask = 1U; 29const trunks::TPMA_PERMANENT kEndorsementAuthSetMask = 1U << 1; 30const trunks::TPMA_PERMANENT kLockoutAuthSetMask = 1U << 2; 31const trunks::TPMA_PERMANENT kInLockoutMask = 1U << 9; 32 33// From definition of TPMA_STARTUP_CLEAR. 34const trunks::TPMA_STARTUP_CLEAR kPlatformHierarchyMask = 1U; 35const trunks::TPMA_STARTUP_CLEAR kStorageHierarchyMask = 1U << 1; 36const trunks::TPMA_STARTUP_CLEAR kEndorsementHierarchyMask = 1U << 2; 37const trunks::TPMA_STARTUP_CLEAR kOrderlyShutdownMask = 1U << 31; 38 39// From definition of TPMA_ALGORITHM 40const trunks::TPMA_ALGORITHM kAsymmetricAlgMask = 1U; 41 42} // namespace 43 44namespace trunks { 45 46TpmStateImpl::TpmStateImpl(const TrunksFactory& factory) 47 : factory_(factory), 48 initialized_(false), 49 permanent_flags_(0), 50 startup_clear_flags_(0), 51 rsa_flags_(0), 52 ecc_flags_(0) { 53} 54 55TpmStateImpl::~TpmStateImpl() {} 56 57TPM_RC TpmStateImpl::Initialize() { 58 TPM_RC result = GetTpmProperty(TPM_PT_PERMANENT, &permanent_flags_); 59 if (result != TPM_RC_SUCCESS) { 60 LOG(ERROR) << "Error getting permanent flags: " << GetErrorString(result); 61 return result; 62 } 63 result = GetTpmProperty(TPM_PT_STARTUP_CLEAR, &startup_clear_flags_); 64 if (result != TPM_RC_SUCCESS) { 65 LOG(ERROR) << "Error getting startup flags: " << GetErrorString(result); 66 return result; 67 } 68 result = GetTpmProperty(TPM_PT_LOCKOUT_COUNTER, &lockout_counter_); 69 if (result != TPM_RC_SUCCESS) { 70 LOG(ERROR) << "Error getting lockout counter: " << GetErrorString(result); 71 return result; 72 } 73 result = GetTpmProperty(TPM_PT_MAX_AUTH_FAIL, &lockout_threshold_); 74 if (result != TPM_RC_SUCCESS) { 75 LOG(ERROR) << "Error getting lockout threshold: " << GetErrorString(result); 76 return result; 77 } 78 result = GetTpmProperty(TPM_PT_LOCKOUT_INTERVAL, &lockout_interval_); 79 if (result != TPM_RC_SUCCESS) { 80 LOG(ERROR) << "Error getting lockout interval: " << GetErrorString(result); 81 return result; 82 } 83 result = GetTpmProperty(TPM_PT_LOCKOUT_RECOVERY, &lockout_recovery_); 84 if (result != TPM_RC_SUCCESS) { 85 LOG(ERROR) << "Error getting lockout recovery: " << GetErrorString(result); 86 return result; 87 } 88 89 TPMI_YES_NO more_data; 90 TPMS_CAPABILITY_DATA capability_data; 91 result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS, 92 TPM_ALG_RSA, 93 1, // There is only one value. 94 &more_data, 95 &capability_data, 96 nullptr); 97 if (result) { 98 LOG(ERROR) << __func__ << ": " << GetErrorString(result); 99 return result; 100 } 101 if (capability_data.capability != TPM_CAP_ALGS || 102 capability_data.data.algorithms.count != 1) { 103 LOG(ERROR) << __func__ << ": Unexpected capability data."; 104 return SAPI_RC_MALFORMED_RESPONSE; 105 } 106 if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_RSA) { 107 rsa_flags_ = 108 capability_data.data.algorithms.alg_properties[0].alg_properties; 109 } 110 result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_ALGS, 111 TPM_ALG_ECC, 112 1, // There is only one value. 113 &more_data, 114 &capability_data, 115 nullptr); 116 if (result) { 117 LOG(ERROR) << __func__ << ": " << GetErrorString(result); 118 return result; 119 } 120 if (capability_data.capability != TPM_CAP_ALGS || 121 capability_data.data.algorithms.count != 1) { 122 LOG(ERROR) << __func__ << ": Unexpected capability data."; 123 return SAPI_RC_MALFORMED_RESPONSE; 124 } 125 if (capability_data.data.algorithms.alg_properties[0].alg == TPM_ALG_ECC) { 126 ecc_flags_ = 127 capability_data.data.algorithms.alg_properties[0].alg_properties; 128 } 129 initialized_ = true; 130 return TPM_RC_SUCCESS; 131} 132 133bool TpmStateImpl::IsOwnerPasswordSet() { 134 CHECK(initialized_); 135 return ((permanent_flags_ & kOwnerAuthSetMask) == kOwnerAuthSetMask); 136} 137 138bool TpmStateImpl::IsEndorsementPasswordSet() { 139 CHECK(initialized_); 140 return ((permanent_flags_ & kEndorsementAuthSetMask) == 141 kEndorsementAuthSetMask); 142} 143 144bool TpmStateImpl::IsLockoutPasswordSet() { 145 CHECK(initialized_); 146 return ((permanent_flags_ & kLockoutAuthSetMask) == kLockoutAuthSetMask); 147} 148 149bool TpmStateImpl::IsOwned() { 150 return (IsOwnerPasswordSet() && 151 IsEndorsementPasswordSet() && 152 IsLockoutPasswordSet()); 153} 154 155bool TpmStateImpl::IsInLockout() { 156 CHECK(initialized_); 157 return ((permanent_flags_ & kInLockoutMask) == kInLockoutMask); 158} 159 160bool TpmStateImpl::IsPlatformHierarchyEnabled() { 161 CHECK(initialized_); 162 return ((startup_clear_flags_ & kPlatformHierarchyMask) == 163 kPlatformHierarchyMask); 164} 165 166bool TpmStateImpl::IsStorageHierarchyEnabled() { 167 CHECK(initialized_); 168 return ((startup_clear_flags_ & kStorageHierarchyMask) == 169 kStorageHierarchyMask); 170} 171 172bool TpmStateImpl::IsEndorsementHierarchyEnabled() { 173 CHECK(initialized_); 174 return ((startup_clear_flags_ & kEndorsementHierarchyMask) == 175 kEndorsementHierarchyMask); 176} 177 178bool TpmStateImpl::IsEnabled() { 179 return (!IsPlatformHierarchyEnabled() && 180 IsStorageHierarchyEnabled() && 181 IsEndorsementHierarchyEnabled()); 182} 183 184bool TpmStateImpl::WasShutdownOrderly() { 185 CHECK(initialized_); 186 return ((startup_clear_flags_ & kOrderlyShutdownMask) == 187 kOrderlyShutdownMask); 188} 189 190bool TpmStateImpl::IsRSASupported() { 191 CHECK(initialized_); 192 return ((rsa_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask); 193} 194 195bool TpmStateImpl::IsECCSupported() { 196 CHECK(initialized_); 197 return ((ecc_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask); 198} 199 200uint32_t TpmStateImpl::GetLockoutCounter() { 201 CHECK(initialized_); 202 return lockout_counter_; 203} 204 205uint32_t TpmStateImpl::GetLockoutThreshold() { 206 CHECK(initialized_); 207 return lockout_threshold_; 208} 209 210uint32_t TpmStateImpl::GetLockoutInterval() { 211 CHECK(initialized_); 212 return lockout_interval_; 213} 214 215uint32_t TpmStateImpl::GetLockoutRecovery() { 216 CHECK(initialized_); 217 return lockout_recovery_; 218} 219 220TPM_RC TpmStateImpl::GetTpmProperty(uint32_t property, 221 uint32_t* value) { 222 CHECK(value); 223 TPMI_YES_NO more_data; 224 TPMS_CAPABILITY_DATA capability_data; 225 TPM_RC result = factory_.GetTpm()->GetCapabilitySync(TPM_CAP_TPM_PROPERTIES, 226 property, 227 1, // Only one property. 228 &more_data, 229 &capability_data, 230 nullptr); 231 if (result != TPM_RC_SUCCESS) { 232 LOG(ERROR) << __func__ << ": " << GetErrorString(result); 233 return result; 234 } 235 if (capability_data.capability != TPM_CAP_TPM_PROPERTIES || 236 capability_data.data.tpm_properties.count != 1 || 237 capability_data.data.tpm_properties.tpm_property[0].property != 238 property) { 239 LOG(ERROR) << __func__ << ": Unexpected capability data."; 240 return SAPI_RC_MALFORMED_RESPONSE; 241 } 242 *value = capability_data.data.tpm_properties.tpm_property[0].value; 243 return TPM_RC_SUCCESS; 244} 245 246} // namespace trunks 247