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 <gmock/gmock.h>
18 #include <gtest/gtest.h>
19
20 #include "trunks/mock_tpm.h"
21 #include "trunks/tpm_generated.h"
22 #include "trunks/tpm_state_impl.h"
23 #include "trunks/trunks_factory_for_test.h"
24
25 using testing::_;
26 using testing::DoAll;
27 using testing::Invoke;
28 using testing::NiceMock;
29 using testing::Return;
30 using testing::SetArgPointee;
31 using testing::WithArgs;
32
33 namespace trunks {
34
35 // A test fixture for TpmState tests.
36 class TpmStateTest : public testing::Test {
37 public:
38 TpmStateTest() = default;
39 ~TpmStateTest() override = default;
40
SetUp()41 void SetUp() override {
42 factory_.set_tpm(&mock_tpm_);
43 // All auth set (i.e. IsOwned() -> true) and in lockout.
44 fake_tpm_properties_[TPM_PT_PERMANENT] = 0x207;
45 // Orderly shutdown, storage and endorsement enabled, platform disabled
46 // (i.e. IsEnabled() -> true).
47 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = 0x80000006;
48 fake_tpm_properties_[TPM_PT_LOCKOUT_COUNTER] = 2;
49 fake_tpm_properties_[TPM_PT_MAX_AUTH_FAIL] = 5;
50 fake_tpm_properties_[TPM_PT_LOCKOUT_INTERVAL] = 100;
51 fake_tpm_properties_[TPM_PT_LOCKOUT_RECOVERY] = 200;
52 fake_tpm_properties_[TPM_PT_NV_INDEX_MAX] = 2048;
53 fake_tpm_properties_[TPM_PT_NV_BUFFER_MAX] = 2048;
54 fake_algorithm_properties_[TPM_ALG_RSA] = 0x9;
55 fake_algorithm_properties_[TPM_ALG_ECC] = 0x9;
56 EXPECT_CALL(mock_tpm_, GetCapabilitySync(_, _, _, _, _, _))
57 .WillRepeatedly(Invoke(this, &TpmStateTest::FakeGetCapability));
58 }
59
60 protected:
FakeGetCapability(const TPM_CAP & capability,const UINT32 & property,const UINT32 & property_count,TPMI_YES_NO * more_data,TPMS_CAPABILITY_DATA * capability_data,AuthorizationDelegate *)61 TPM_RC FakeGetCapability(const TPM_CAP& capability,
62 const UINT32& property,
63 const UINT32& property_count,
64 TPMI_YES_NO* more_data,
65 TPMS_CAPABILITY_DATA* capability_data,
66 AuthorizationDelegate* /* not_used */) {
67 // Return only two properties at a time, this will exercise the more_data
68 // logic.
69 constexpr uint32_t kMaxProperties = 2;
70 *more_data = NO;
71 memset(capability_data, 0, sizeof(TPMS_CAPABILITY_DATA));
72 capability_data->capability = capability;
73 TPMU_CAPABILITIES& data = capability_data->data;
74 if (capability == TPM_CAP_TPM_PROPERTIES) {
75 // TPM properties get returned one group at a time, mimic this.
76 uint32_t group = (property >> 8);
77 uint32_t stop = PT_GROUP * (group + 1);
78 for (uint32_t i = property; i < stop; ++i) {
79 if (fake_tpm_properties_.count(i) > 0) {
80 if (data.tpm_properties.count == kMaxProperties ||
81 data.tpm_properties.count == property_count) {
82 // There are more properties than we can fit.
83 *more_data = YES;
84 break;
85 }
86 data.tpm_properties.tpm_property[data.tpm_properties.count].property =
87 i;
88 data.tpm_properties.tpm_property[data.tpm_properties.count].value =
89 fake_tpm_properties_[i];
90 data.tpm_properties.count++;
91 }
92 }
93 } else if (capability == TPM_CAP_ALGS) {
94 // Algorithm properties.
95 uint32_t stop = TPM_ALG_LAST + 1;
96 for (uint32_t i = property; i < stop; ++i) {
97 if (fake_algorithm_properties_.count(i) > 0) {
98 if (data.algorithms.count == kMaxProperties ||
99 data.algorithms.count == property_count) {
100 // There are more properties than we can fit.
101 *more_data = YES;
102 break;
103 }
104 data.algorithms.alg_properties[data.algorithms.count].alg = i;
105 data.algorithms.alg_properties[data.algorithms.count].alg_properties =
106 fake_algorithm_properties_[i];
107 data.algorithms.count++;
108 }
109 }
110 }
111 return TPM_RC_SUCCESS;
112 }
113
114 TrunksFactoryForTest factory_;
115 NiceMock<MockTpm> mock_tpm_;
116 std::map<TPM_PT, uint32_t> fake_tpm_properties_;
117 std::map<TPM_ALG_ID, TPMA_ALGORITHM> fake_algorithm_properties_;
118 };
119
TEST(TpmState_DeathTest,NotInitialized)120 TEST(TpmState_DeathTest, NotInitialized) {
121 TrunksFactoryForTest factory;
122 TpmStateImpl tpm_state(factory);
123 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsOwnerPasswordSet(), "Check failed");
124 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsEndorsementPasswordSet(),
125 "Check failed");
126 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsLockoutPasswordSet(), "Check failed");
127 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsOwned(), "Check failed");
128 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsInLockout(), "Check failed");
129 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsPlatformHierarchyEnabled(),
130 "Check failed");
131 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsStorageHierarchyEnabled(),
132 "Check failed");
133 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsEndorsementHierarchyEnabled(),
134 "Check failed");
135 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsEnabled(), "Check failed");
136 EXPECT_DEATH_IF_SUPPORTED(tpm_state.WasShutdownOrderly(), "Check failed");
137 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsRSASupported(), "Check failed");
138 EXPECT_DEATH_IF_SUPPORTED(tpm_state.IsECCSupported(), "Check failed");
139 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutCounter(), "Check failed");
140 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutThreshold(), "Check failed");
141 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutInterval(), "Check failed");
142 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetLockoutRecovery(), "Check failed");
143 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetMaxNVSize(), "Check failed");
144 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetTpmProperty(0, nullptr),
145 "Check failed");
146 EXPECT_DEATH_IF_SUPPORTED(tpm_state.GetAlgorithmProperties(0, nullptr),
147 "Check failed");
148 }
149
TEST_F(TpmStateTest,FlagsClear)150 TEST_F(TpmStateTest, FlagsClear) {
151 fake_tpm_properties_[TPM_PT_PERMANENT] = 0;
152 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = 0;
153 TpmStateImpl tpm_state(factory_);
154 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
155 EXPECT_FALSE(tpm_state.IsOwnerPasswordSet());
156 EXPECT_FALSE(tpm_state.IsEndorsementPasswordSet());
157 EXPECT_FALSE(tpm_state.IsLockoutPasswordSet());
158 EXPECT_FALSE(tpm_state.IsInLockout());
159 EXPECT_FALSE(tpm_state.IsOwned());
160 EXPECT_FALSE(tpm_state.IsPlatformHierarchyEnabled());
161 EXPECT_FALSE(tpm_state.IsStorageHierarchyEnabled());
162 EXPECT_FALSE(tpm_state.IsEndorsementHierarchyEnabled());
163 EXPECT_FALSE(tpm_state.WasShutdownOrderly());
164 }
165
TEST_F(TpmStateTest,FlagsSet)166 TEST_F(TpmStateTest, FlagsSet) {
167 fake_tpm_properties_[TPM_PT_PERMANENT] = ~0;
168 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = ~0;
169
170 TpmStateImpl tpm_state(factory_);
171 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
172 EXPECT_TRUE(tpm_state.IsOwnerPasswordSet());
173 EXPECT_TRUE(tpm_state.IsEndorsementPasswordSet());
174 EXPECT_TRUE(tpm_state.IsLockoutPasswordSet());
175 EXPECT_TRUE(tpm_state.IsOwned());
176 EXPECT_TRUE(tpm_state.IsInLockout());
177 EXPECT_TRUE(tpm_state.IsPlatformHierarchyEnabled());
178 EXPECT_TRUE(tpm_state.IsStorageHierarchyEnabled());
179 EXPECT_TRUE(tpm_state.IsEndorsementHierarchyEnabled());
180 EXPECT_TRUE(tpm_state.WasShutdownOrderly());
181 }
182
TEST_F(TpmStateTest,EnabledTpm)183 TEST_F(TpmStateTest, EnabledTpm) {
184 TpmStateImpl tpm_state(factory_);
185 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
186 EXPECT_TRUE(tpm_state.IsEnabled());
187 // All hierarchies enabled.
188 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = 0x7;
189 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
190 EXPECT_FALSE(tpm_state.IsEnabled());
191 // All hierarchies disabled.
192 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = 0x0;
193 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
194 EXPECT_FALSE(tpm_state.IsEnabled());
195 // Storage disabled.
196 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = 0x5;
197 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
198 EXPECT_FALSE(tpm_state.IsEnabled());
199 // Endorsement disabled.
200 fake_tpm_properties_[TPM_PT_STARTUP_CLEAR] = 0x3;
201 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
202 EXPECT_FALSE(tpm_state.IsEnabled());
203 }
204
TEST_F(TpmStateTest,OwnedTpm)205 TEST_F(TpmStateTest, OwnedTpm) {
206 TpmStateImpl tpm_state(factory_);
207 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
208 EXPECT_TRUE(tpm_state.IsOwned());
209 // All auth missing.
210 fake_tpm_properties_[TPM_PT_PERMANENT] = 0x0;
211 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
212 EXPECT_FALSE(tpm_state.IsOwned());
213 // Owner auth missing.
214 fake_tpm_properties_[TPM_PT_PERMANENT] = 0x6;
215 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
216 EXPECT_FALSE(tpm_state.IsOwned());
217 // Endorsement auth missing.
218 fake_tpm_properties_[TPM_PT_PERMANENT] = 0x5;
219 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
220 EXPECT_FALSE(tpm_state.IsOwned());
221 // Lockout auth missing.
222 fake_tpm_properties_[TPM_PT_PERMANENT] = 0x3;
223 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
224 EXPECT_FALSE(tpm_state.IsOwned());
225 }
226
TEST_F(TpmStateTest,AlgorithmSupport)227 TEST_F(TpmStateTest, AlgorithmSupport) {
228 TpmStateImpl tpm_state(factory_);
229 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
230 EXPECT_TRUE(tpm_state.IsRSASupported());
231 EXPECT_TRUE(tpm_state.IsECCSupported());
232
233 fake_algorithm_properties_.clear();
234 // Use a new instance because algorithm properties will not be queried again.
235 TpmStateImpl tpm_state2(factory_);
236 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state2.Initialize());
237 EXPECT_FALSE(tpm_state2.IsRSASupported());
238 EXPECT_FALSE(tpm_state2.IsECCSupported());
239 }
240
TEST_F(TpmStateTest,LockoutValuePassthrough)241 TEST_F(TpmStateTest, LockoutValuePassthrough) {
242 TpmStateImpl tpm_state(factory_);
243 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
244 EXPECT_EQ(tpm_state.GetLockoutCounter(),
245 fake_tpm_properties_[TPM_PT_LOCKOUT_COUNTER]);
246 EXPECT_EQ(tpm_state.GetLockoutThreshold(),
247 fake_tpm_properties_[TPM_PT_MAX_AUTH_FAIL]);
248 EXPECT_EQ(tpm_state.GetLockoutInterval(),
249 fake_tpm_properties_[TPM_PT_LOCKOUT_INTERVAL]);
250 EXPECT_EQ(tpm_state.GetLockoutRecovery(),
251 fake_tpm_properties_[TPM_PT_LOCKOUT_RECOVERY]);
252
253 fake_tpm_properties_[TPM_PT_LOCKOUT_COUNTER]++;
254 fake_tpm_properties_[TPM_PT_MAX_AUTH_FAIL]++;
255 fake_tpm_properties_[TPM_PT_LOCKOUT_INTERVAL]++;
256 fake_tpm_properties_[TPM_PT_LOCKOUT_RECOVERY]++;
257 // Refresh and check for the new values.
258 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
259 EXPECT_EQ(tpm_state.GetLockoutCounter(),
260 fake_tpm_properties_[TPM_PT_LOCKOUT_COUNTER]);
261 EXPECT_EQ(tpm_state.GetLockoutThreshold(),
262 fake_tpm_properties_[TPM_PT_MAX_AUTH_FAIL]);
263 EXPECT_EQ(tpm_state.GetLockoutInterval(),
264 fake_tpm_properties_[TPM_PT_LOCKOUT_INTERVAL]);
265 EXPECT_EQ(tpm_state.GetLockoutRecovery(),
266 fake_tpm_properties_[TPM_PT_LOCKOUT_RECOVERY]);
267 }
268
TEST_F(TpmStateTest,MaxNVSize)269 TEST_F(TpmStateTest, MaxNVSize) {
270 auto CheckMaxNVSize = [this]() {
271 TpmStateImpl tpm_state(factory_);
272 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
273 bool has_index = fake_tpm_properties_.count(TPM_PT_NV_INDEX_MAX) > 0;
274 bool has_buffer = fake_tpm_properties_.count(TPM_PT_NV_BUFFER_MAX) > 0;
275 if (has_index && has_buffer) {
276 EXPECT_EQ(tpm_state.GetMaxNVSize(),
277 std::min(fake_tpm_properties_[TPM_PT_NV_INDEX_MAX],
278 fake_tpm_properties_[TPM_PT_NV_BUFFER_MAX]));
279 } else if (has_index) {
280 EXPECT_EQ(tpm_state.GetMaxNVSize(),
281 fake_tpm_properties_[TPM_PT_NV_INDEX_MAX]);
282 } else if (has_buffer) {
283 EXPECT_EQ(tpm_state.GetMaxNVSize(),
284 fake_tpm_properties_[TPM_PT_NV_BUFFER_MAX]);
285 } else {
286 // Check for a reasonable default value. Brillo specs a minimum of 2048 so
287 // it shouldn't be less than that.
288 EXPECT_GE(tpm_state.GetMaxNVSize(), 2048u);
289 }
290 };
291 // Check with the defaults (same index and buffer max).
292 CheckMaxNVSize();
293 // Check with lower buffer max.
294 fake_tpm_properties_[TPM_PT_NV_INDEX_MAX] = 20;
295 fake_tpm_properties_[TPM_PT_NV_BUFFER_MAX] = 10;
296 CheckMaxNVSize();
297 // Check with lower index max.
298 fake_tpm_properties_[TPM_PT_NV_INDEX_MAX] = 10;
299 fake_tpm_properties_[TPM_PT_NV_BUFFER_MAX] = 20;
300 CheckMaxNVSize();
301 // Check without index property.
302 fake_tpm_properties_.erase(TPM_PT_NV_INDEX_MAX);
303 fake_tpm_properties_[TPM_PT_NV_BUFFER_MAX] = 5;
304 CheckMaxNVSize();
305 // Check without buffer property.
306 fake_tpm_properties_[TPM_PT_NV_INDEX_MAX] = 5;
307 fake_tpm_properties_.erase(TPM_PT_NV_BUFFER_MAX);
308 CheckMaxNVSize();
309 // Check without any properties.
310 fake_tpm_properties_.erase(TPM_PT_NV_INDEX_MAX);
311 fake_tpm_properties_.erase(TPM_PT_NV_BUFFER_MAX);
312 CheckMaxNVSize();
313 }
314
TEST_F(TpmStateTest,RawTpmProperty)315 TEST_F(TpmStateTest, RawTpmProperty) {
316 constexpr TPM_PT kProperty = 0x2FF;
317 TpmStateImpl tpm_state(factory_);
318 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
319 EXPECT_FALSE(tpm_state.GetTpmProperty(kProperty, nullptr));
320 uint32_t value;
321 EXPECT_FALSE(tpm_state.GetTpmProperty(kProperty, &value));
322
323 fake_tpm_properties_[kProperty] = 1234;
324 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
325 EXPECT_TRUE(tpm_state.GetTpmProperty(kProperty, nullptr));
326 EXPECT_TRUE(tpm_state.GetTpmProperty(kProperty, &value));
327 EXPECT_EQ(value, fake_tpm_properties_[kProperty]);
328 }
329
TEST_F(TpmStateTest,RawAlgorithmProperties)330 TEST_F(TpmStateTest, RawAlgorithmProperties) {
331 constexpr TPM_ALG_ID kAlgorithm = 0x39;
332 TpmStateImpl tpm_state(factory_);
333 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state.Initialize());
334 EXPECT_FALSE(tpm_state.GetAlgorithmProperties(kAlgorithm, nullptr));
335 uint32_t value;
336 EXPECT_FALSE(tpm_state.GetAlgorithmProperties(kAlgorithm, &value));
337
338 fake_algorithm_properties_[kAlgorithm] = 1234;
339 TpmStateImpl tpm_state2(factory_);
340 ASSERT_EQ(TPM_RC_SUCCESS, tpm_state2.Initialize());
341 EXPECT_TRUE(tpm_state2.GetAlgorithmProperties(kAlgorithm, nullptr));
342 EXPECT_TRUE(tpm_state2.GetAlgorithmProperties(kAlgorithm, &value));
343 EXPECT_EQ(value, fake_algorithm_properties_[kAlgorithm]);
344 }
345
TEST_F(TpmStateTest,InitFailOnMissingPermanentFlags)346 TEST_F(TpmStateTest, InitFailOnMissingPermanentFlags) {
347 fake_tpm_properties_.erase(TPM_PT_PERMANENT);
348 TpmStateImpl tpm_state(factory_);
349 EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
350 }
351
TEST_F(TpmStateTest,InitFailOnMissingStartupClearFlags)352 TEST_F(TpmStateTest, InitFailOnMissingStartupClearFlags) {
353 fake_tpm_properties_.erase(TPM_PT_STARTUP_CLEAR);
354 TpmStateImpl tpm_state(factory_);
355 EXPECT_NE(TPM_RC_SUCCESS, tpm_state.Initialize());
356 }
357
TEST_F(TpmStateTest,InitFailOnFailedTPMCommand)358 TEST_F(TpmStateTest, InitFailOnFailedTPMCommand) {
359 EXPECT_CALL(mock_tpm_, GetCapabilitySync(_, _, _, _, _, _))
360 .WillRepeatedly(Return(TPM_RC_FAILURE));
361 TpmStateImpl tpm_state(factory_);
362 EXPECT_EQ(TPM_RC_FAILURE, tpm_state.Initialize());
363 }
364
365 } // namespace trunks
366