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