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
TpmStateImpl(const TrunksFactory & factory)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
~TpmStateImpl()55 TpmStateImpl::~TpmStateImpl() {}
56
Initialize()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
IsOwnerPasswordSet()133 bool TpmStateImpl::IsOwnerPasswordSet() {
134 CHECK(initialized_);
135 return ((permanent_flags_ & kOwnerAuthSetMask) == kOwnerAuthSetMask);
136 }
137
IsEndorsementPasswordSet()138 bool TpmStateImpl::IsEndorsementPasswordSet() {
139 CHECK(initialized_);
140 return ((permanent_flags_ & kEndorsementAuthSetMask) ==
141 kEndorsementAuthSetMask);
142 }
143
IsLockoutPasswordSet()144 bool TpmStateImpl::IsLockoutPasswordSet() {
145 CHECK(initialized_);
146 return ((permanent_flags_ & kLockoutAuthSetMask) == kLockoutAuthSetMask);
147 }
148
IsOwned()149 bool TpmStateImpl::IsOwned() {
150 return (IsOwnerPasswordSet() &&
151 IsEndorsementPasswordSet() &&
152 IsLockoutPasswordSet());
153 }
154
IsInLockout()155 bool TpmStateImpl::IsInLockout() {
156 CHECK(initialized_);
157 return ((permanent_flags_ & kInLockoutMask) == kInLockoutMask);
158 }
159
IsPlatformHierarchyEnabled()160 bool TpmStateImpl::IsPlatformHierarchyEnabled() {
161 CHECK(initialized_);
162 return ((startup_clear_flags_ & kPlatformHierarchyMask) ==
163 kPlatformHierarchyMask);
164 }
165
IsStorageHierarchyEnabled()166 bool TpmStateImpl::IsStorageHierarchyEnabled() {
167 CHECK(initialized_);
168 return ((startup_clear_flags_ & kStorageHierarchyMask) ==
169 kStorageHierarchyMask);
170 }
171
IsEndorsementHierarchyEnabled()172 bool TpmStateImpl::IsEndorsementHierarchyEnabled() {
173 CHECK(initialized_);
174 return ((startup_clear_flags_ & kEndorsementHierarchyMask) ==
175 kEndorsementHierarchyMask);
176 }
177
IsEnabled()178 bool TpmStateImpl::IsEnabled() {
179 return (!IsPlatformHierarchyEnabled() &&
180 IsStorageHierarchyEnabled() &&
181 IsEndorsementHierarchyEnabled());
182 }
183
WasShutdownOrderly()184 bool TpmStateImpl::WasShutdownOrderly() {
185 CHECK(initialized_);
186 return ((startup_clear_flags_ & kOrderlyShutdownMask) ==
187 kOrderlyShutdownMask);
188 }
189
IsRSASupported()190 bool TpmStateImpl::IsRSASupported() {
191 CHECK(initialized_);
192 return ((rsa_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
193 }
194
IsECCSupported()195 bool TpmStateImpl::IsECCSupported() {
196 CHECK(initialized_);
197 return ((ecc_flags_ & kAsymmetricAlgMask) == kAsymmetricAlgMask);
198 }
199
GetLockoutCounter()200 uint32_t TpmStateImpl::GetLockoutCounter() {
201 CHECK(initialized_);
202 return lockout_counter_;
203 }
204
GetLockoutThreshold()205 uint32_t TpmStateImpl::GetLockoutThreshold() {
206 CHECK(initialized_);
207 return lockout_threshold_;
208 }
209
GetLockoutInterval()210 uint32_t TpmStateImpl::GetLockoutInterval() {
211 CHECK(initialized_);
212 return lockout_interval_;
213 }
214
GetLockoutRecovery()215 uint32_t TpmStateImpl::GetLockoutRecovery() {
216 CHECK(initialized_);
217 return lockout_recovery_;
218 }
219
GetTpmProperty(uint32_t property,uint32_t * value)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