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 25 namespace { 26 27 // From definition of TPMA_PERMANENT. 28 const trunks::TPMA_PERMANENT kOwnerAuthSetMask = 1U; 29 const trunks::TPMA_PERMANENT kEndorsementAuthSetMask = 1U << 1; 30 const trunks::TPMA_PERMANENT kLockoutAuthSetMask = 1U << 2; 31 const trunks::TPMA_PERMANENT kInLockoutMask = 1U << 9; 32 33 // From definition of TPMA_STARTUP_CLEAR. 34 const trunks::TPMA_STARTUP_CLEAR kPlatformHierarchyMask = 1U; 35 const trunks::TPMA_STARTUP_CLEAR kStorageHierarchyMask = 1U << 1; 36 const trunks::TPMA_STARTUP_CLEAR kEndorsementHierarchyMask = 1U << 2; 37 const trunks::TPMA_STARTUP_CLEAR kOrderlyShutdownMask = 1U << 31; 38 39 // From definition of TPMA_ALGORITHM 40 const trunks::TPMA_ALGORITHM kAsymmetricAlgMask = 1U; 41 42 } // namespace 43 44 namespace trunks { 45 46 TpmStateImpl::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 55 TpmStateImpl::~TpmStateImpl() {} 56 57 TPM_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 133 bool TpmStateImpl::IsOwnerPasswordSet() { 134 CHECK(initialized_); 135 return ((permanent_flags_ & kOwnerAuthSetMask) == kOwnerAuthSetMask); 136 } 137 138 bool TpmStateImpl::IsEndorsementPasswordSet() { 139 CHECK(initialized_); 140 return ((permanent_flags_ & kEndorsementAuthSetMask) == 141 kEndorsementAuthSetMask); 142 } 143 144 bool TpmStateImpl::IsLockoutPasswordSet() { 145 CHECK(initialized_); 146 return ((permanent_flags_ & kLockoutAuthSetMask) == kLockoutAuthSetMask); 147 } 148 149 bool TpmStateImpl::IsOwned() { 150 return (IsOwnerPasswordSet() && 151 IsEndorsementPasswordSet() && 152 IsLockoutPasswordSet()); 153 } 154 155 bool TpmStateImpl::IsInLockout() { 156 CHECK(initialized_); 157 return ((permanent_flags_ & kInLockoutMask) == kInLockoutMask); 158 } 159 160 bool TpmStateImpl::IsPlatformHierarchyEnabled() { 161 CHECK(initialized_); 162 return ((startup_clear_flags_ & kPlatformHierarchyMask) == 163 kPlatformHierarchyMask); 164 } 165 166 bool TpmStateImpl::IsStorageHierarchyEnabled() { 167 CHECK(initialized_); 168 return ((startup_clear_flags_ & kStorageHierarchyMask) == 169 kStorageHierarchyMask); 170 } 171 172 bool TpmStateImpl::IsEndorsementHierarchyEnabled() { 173 CHECK(initialized_); 174 return ((startup_clear_flags_ & kEndorsementHierarchyMask) == 175 kEndorsementHierarchyMask); 176 } 177 178 bool TpmStateImpl::IsEnabled() { 179 return (!IsPlatformHierarchyEnabled() && 180 IsStorageHierarchyEnabled() && 181 IsEndorsementHierarchyEnabled()); 182 } 183 184 bool TpmStateImpl::WasShutdownOrderly() { 185 CHECK(initialized_); 186 return ((startup_clear_flags_ & kOrderlyShutdownMask) == 187 kOrderlyShutdownMask); 188 } 189 190 bool TpmStateImpl::IsRSASupported() { 191 CHECK(initialized_); 192 return ((rsa_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask); 193 } 194 195 bool TpmStateImpl::IsECCSupported() { 196 CHECK(initialized_); 197 return ((ecc_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask); 198 } 199 200 uint32_t TpmStateImpl::GetLockoutCounter() { 201 CHECK(initialized_); 202 return lockout_counter_; 203 } 204 205 uint32_t TpmStateImpl::GetLockoutThreshold() { 206 CHECK(initialized_); 207 return lockout_threshold_; 208 } 209 210 uint32_t TpmStateImpl::GetLockoutInterval() { 211 CHECK(initialized_); 212 return lockout_interval_; 213 } 214 215 uint32_t TpmStateImpl::GetLockoutRecovery() { 216 CHECK(initialized_); 217 return lockout_recovery_; 218 } 219 220 TPM_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