1 //
2 // Copyright (C) 2015 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/resource_manager.h"
18
19 #include <string>
20 #include <vector>
21
22 #include <base/bind.h>
23 #include <gmock/gmock.h>
24 #include <gtest/gtest.h>
25
26 #include "trunks/error_codes.h"
27 #include "trunks/mock_command_transceiver.h"
28 #include "trunks/mock_tpm.h"
29 #include "trunks/trunks_factory_for_test.h"
30
31 using testing::_;
32 using testing::DoAll;
33 using testing::Eq;
34 using testing::Field;
35 using testing::InSequence;
36 using testing::Return;
37 using testing::ReturnPointee;
38 using testing::SetArgumentPointee;
39 using testing::StrictMock;
40
41 namespace {
42
43 const trunks::TPM_HANDLE kArbitraryObjectHandle = trunks::TRANSIENT_FIRST + 25;
44 const trunks::TPM_HANDLE kArbitrarySessionHandle = trunks::HMAC_SESSION_FIRST;
45
Assign(std::string * to,const std::string & from)46 void Assign(std::string* to, const std::string& from) {
47 *to = from;
48 }
49
50 class ScopedDisableLogging {
51 public:
ScopedDisableLogging()52 ScopedDisableLogging() : original_severity_(logging::GetMinLogLevel()) {
53 logging::SetMinLogLevel(logging::LOG_FATAL);
54 }
~ScopedDisableLogging()55 ~ScopedDisableLogging() {
56 logging::SetMinLogLevel(original_severity_);
57 }
58
59 private:
60 logging::LogSeverity original_severity_;
61 };
62
63 } // namespace
64
65 namespace trunks {
66
67 class ResourceManagerTest : public testing::Test {
68 public:
69 const std::vector<TPM_HANDLE> kNoHandles;
70 const std::string kNoAuthorization;
71 const std::string kNoParameters;
72
ResourceManagerTest()73 ResourceManagerTest() : resource_manager_(factory_, &transceiver_) {}
~ResourceManagerTest()74 ~ResourceManagerTest() override {}
75
SetUp()76 void SetUp() override {
77 factory_.set_tpm(&tpm_);
78 }
79
80 // Builds a well-formed command.
CreateCommand(TPM_CC code,const std::vector<TPM_HANDLE> & handles,const std::string & authorization,const std::string & parameters)81 std::string CreateCommand(TPM_CC code,
82 const std::vector<TPM_HANDLE>& handles,
83 const std::string& authorization,
84 const std::string& parameters) {
85 std::string buffer;
86 TPM_ST tag = authorization.empty() ? TPM_ST_NO_SESSIONS : TPM_ST_SESSIONS;
87 UINT32 size = 10 + (handles.size() * 4) + authorization.size() +
88 parameters.size() + (authorization.empty() ? 0 : 4);
89 Serialize_TPM_ST(tag, &buffer);
90 Serialize_UINT32(size, &buffer);
91 Serialize_TPM_CC(code, &buffer);
92 for (auto handle : handles) {
93 Serialize_TPM_HANDLE(handle, &buffer);
94 }
95 if (!authorization.empty()) {
96 Serialize_UINT32(authorization.size(), &buffer);
97 }
98 return buffer + authorization + parameters;
99 }
100
101 // Builds a well-formed response.
CreateResponse(TPM_RC code,const std::vector<TPM_HANDLE> & handles,const std::string & authorization,const std::string & parameters)102 std::string CreateResponse(TPM_RC code,
103 const std::vector<TPM_HANDLE>& handles,
104 const std::string& authorization,
105 const std::string& parameters) {
106 std::string buffer;
107 TPM_ST tag = authorization.empty() ? TPM_ST_NO_SESSIONS : TPM_ST_SESSIONS;
108 UINT32 size = 10 + (handles.size() * 4) + authorization.size() +
109 parameters.size() + (authorization.empty() ? 0 : 4);
110 Serialize_TPM_ST(tag, &buffer);
111 Serialize_UINT32(size, &buffer);
112 Serialize_TPM_RC(code, &buffer);
113 for (auto handle : handles) {
114 Serialize_TPM_HANDLE(handle, &buffer);
115 }
116 if (!authorization.empty()) {
117 Serialize_UINT32(parameters.size(), &buffer);
118 }
119 return buffer + parameters + authorization;
120 }
121
122 // Builds a well-formed command authorization section.
CreateCommandAuthorization(TPM_HANDLE handle,bool continue_session)123 std::string CreateCommandAuthorization(TPM_HANDLE handle,
124 bool continue_session) {
125 std::string buffer;
126 Serialize_TPM_HANDLE(handle, &buffer);
127 Serialize_TPM2B_NONCE(Make_TPM2B_DIGEST(std::string(32, 'A')), &buffer);
128 Serialize_BYTE(continue_session ? 1 : 0, &buffer);
129 Serialize_TPM2B_DIGEST(Make_TPM2B_DIGEST(std::string(32, 'B')), &buffer);
130 return buffer;
131 }
132
133 // Builds a well-formed response authorization section.
CreateResponseAuthorization(bool continue_session)134 std::string CreateResponseAuthorization(bool continue_session) {
135 std::string buffer;
136 Serialize_TPM2B_NONCE(Make_TPM2B_DIGEST(std::string(32, 'A')), &buffer);
137 Serialize_BYTE(continue_session ? 1 : 0, &buffer);
138 Serialize_TPM2B_DIGEST(Make_TPM2B_DIGEST(std::string(32, 'B')), &buffer);
139 return buffer;
140 }
141
GetHeader(const std::string & message)142 std::string GetHeader(const std::string& message) {
143 return message.substr(0, 10);
144 }
145
StripHeader(const std::string & message)146 std::string StripHeader(const std::string& message) {
147 return message.substr(10);
148 }
149
150 // Makes the resource manager aware of a transient object handle and returns
151 // the newly associated virtual handle.
LoadHandle(TPM_HANDLE handle)152 TPM_HANDLE LoadHandle(TPM_HANDLE handle) {
153 std::vector<TPM_HANDLE> input_handles = {PERSISTENT_FIRST};
154 std::string command = CreateCommand(TPM_CC_Load,
155 input_handles,
156 kNoAuthorization,
157 kNoParameters);
158 std::vector<TPM_HANDLE> output_handles = {handle};
159 std::string response = CreateResponse(TPM_RC_SUCCESS,
160 output_handles,
161 kNoAuthorization,
162 kNoParameters);
163 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
164 .WillOnce(Return(response));
165 std::string actual_response = resource_manager_.SendCommandAndWait(command);
166 std::string handle_blob = StripHeader(actual_response);
167 TPM_HANDLE virtual_handle;
168 CHECK_EQ(TPM_RC_SUCCESS, Parse_TPM_HANDLE(&handle_blob, &virtual_handle,
169 NULL));
170 return virtual_handle;
171 }
172
173 // Causes the resource manager to evict existing object handles.
EvictObjects()174 void EvictObjects() {
175 std::string command = CreateCommand(TPM_CC_Startup,
176 kNoHandles,
177 kNoAuthorization,
178 kNoParameters);
179 std::string response = CreateErrorResponse(TPM_RC_OBJECT_MEMORY);
180 std::string success_response = CreateResponse(TPM_RC_SUCCESS,
181 kNoHandles,
182 kNoAuthorization,
183 kNoParameters);
184 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
185 .WillOnce(Return(response))
186 .WillRepeatedly(Return(success_response));
187 EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
188 .WillRepeatedly(Return(TPM_RC_SUCCESS));
189 EXPECT_CALL(tpm_, FlushContextSync(_, _))
190 .WillRepeatedly(Return(TPM_RC_SUCCESS));
191 resource_manager_.SendCommandAndWait(command);
192 }
193
194 // Makes the resource manager aware of a session handle.
StartSession(TPM_HANDLE handle)195 void StartSession(TPM_HANDLE handle) {
196 std::vector<TPM_HANDLE> input_handles = {1, 2};
197 std::string command = CreateCommand(TPM_CC_StartAuthSession,
198 input_handles,
199 kNoAuthorization,
200 kNoParameters);
201 std::vector<TPM_HANDLE> output_handles = {handle};
202 std::string response = CreateResponse(TPM_RC_SUCCESS,
203 output_handles,
204 kNoAuthorization,
205 kNoParameters);
206 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
207 .WillOnce(Return(response));
208 std::string actual_response = resource_manager_.SendCommandAndWait(command);
209 ASSERT_EQ(response, actual_response);
210 }
211
212 // Causes the resource manager to evict an existing session handle.
EvictSession()213 void EvictSession() {
214 std::string command = CreateCommand(TPM_CC_Startup,
215 kNoHandles,
216 kNoAuthorization,
217 kNoParameters);
218 std::string response = CreateErrorResponse(TPM_RC_SESSION_MEMORY);
219 std::string success_response = CreateResponse(TPM_RC_SUCCESS,
220 kNoHandles,
221 kNoAuthorization,
222 kNoParameters);
223 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
224 .WillOnce(Return(response))
225 .WillRepeatedly(Return(success_response));
226 EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
227 .WillOnce(Return(TPM_RC_SUCCESS));
228 resource_manager_.SendCommandAndWait(command);
229 }
230
231 // Creates a TPMS_CONTEXT with the given sequence field.
CreateContext(UINT64 sequence)232 TPMS_CONTEXT CreateContext(UINT64 sequence) {
233 TPMS_CONTEXT context;
234 memset(&context, 0, sizeof(context));
235 context.sequence = sequence;
236 return context;
237 }
238
239 // Creates a serialized TPMS_CONTEXT with the given sequence field.
CreateContextParameter(UINT64 sequence)240 std::string CreateContextParameter(UINT64 sequence) {
241 std::string buffer;
242 Serialize_TPMS_CONTEXT(CreateContext(sequence), &buffer);
243 return buffer;
244 }
245
246 protected:
247 StrictMock<MockTpm> tpm_;
248 TrunksFactoryForTest factory_;
249 StrictMock<MockCommandTransceiver> transceiver_;
250 ResourceManager resource_manager_;
251 };
252
TEST_F(ResourceManagerTest,BasicPassThrough)253 TEST_F(ResourceManagerTest, BasicPassThrough) {
254 std::string command = CreateCommand(TPM_CC_Startup,
255 kNoHandles,
256 kNoAuthorization,
257 kNoParameters);
258 std::string response = CreateResponse(TPM_RC_SUCCESS,
259 kNoHandles,
260 kNoAuthorization,
261 kNoParameters);
262 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
263 .WillOnce(Return(response));
264 std::string actual_response = resource_manager_.SendCommandAndWait(command);
265 EXPECT_EQ(actual_response, response);
266 }
267
TEST_F(ResourceManagerTest,BasicPassThroughAsync)268 TEST_F(ResourceManagerTest, BasicPassThroughAsync) {
269 std::string command = CreateCommand(TPM_CC_Startup,
270 kNoHandles,
271 kNoAuthorization,
272 kNoParameters);
273 std::string response = CreateResponse(TPM_RC_SUCCESS,
274 kNoHandles,
275 kNoAuthorization,
276 kNoParameters);
277 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
278 .WillOnce(Return(response));
279 std::string actual_response;
280 CommandTransceiver::ResponseCallback callback =
281 base::Bind(&Assign, &actual_response);
282 resource_manager_.SendCommand(command, callback);
283 EXPECT_EQ(actual_response, response);
284 }
285
TEST_F(ResourceManagerTest,VirtualHandleOutput)286 TEST_F(ResourceManagerTest, VirtualHandleOutput) {
287 std::vector<TPM_HANDLE> input_handles = {PERSISTENT_FIRST};
288 std::string command = CreateCommand(TPM_CC_Load,
289 input_handles,
290 kNoAuthorization,
291 kNoParameters);
292 std::vector<TPM_HANDLE> output_handles = {kArbitraryObjectHandle};
293 std::string response = CreateResponse(TPM_RC_SUCCESS,
294 output_handles,
295 kNoAuthorization,
296 kNoParameters);
297 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
298 .WillOnce(Return(response));
299 std::string actual_response = resource_manager_.SendCommandAndWait(command);
300 EXPECT_EQ(response.size(), actual_response.size());
301 // We expect the resource manager has replaced the output handle with a
302 // virtual handle (which we can't predict, but it's unlikely to be the same as
303 // the handle emitted by the mock).
304 EXPECT_EQ(GetHeader(response), GetHeader(actual_response));
305 EXPECT_NE(StripHeader(response), StripHeader(actual_response));
306 TPM_HT handle_type = static_cast<TPM_HT>(StripHeader(actual_response)[0]);
307 EXPECT_EQ(TPM_HT_TRANSIENT, handle_type);
308 }
309
TEST_F(ResourceManagerTest,VirtualHandleInput)310 TEST_F(ResourceManagerTest, VirtualHandleInput) {
311 TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
312 TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
313 std::vector<TPM_HANDLE> input_handles = {virtual_handle};
314 std::string command = CreateCommand(TPM_CC_Sign,
315 input_handles,
316 kNoAuthorization,
317 kNoParameters);
318 // We expect the resource manager to replace |virtual_handle| with
319 // |tpm_handle|.
320 std::vector<TPM_HANDLE> expected_input_handles = {tpm_handle};
321 std::string expected_command = CreateCommand(TPM_CC_Sign,
322 expected_input_handles,
323 kNoAuthorization,
324 kNoParameters);
325 std::string response = CreateResponse(TPM_RC_SUCCESS,
326 kNoHandles,
327 kNoAuthorization,
328 kNoParameters);
329 EXPECT_CALL(transceiver_, SendCommandAndWait(expected_command))
330 .WillOnce(Return(response));
331 std::string actual_response = resource_manager_.SendCommandAndWait(command);
332 EXPECT_EQ(response, actual_response);
333 }
334
TEST_F(ResourceManagerTest,VirtualHandleCleanup)335 TEST_F(ResourceManagerTest, VirtualHandleCleanup) {
336 TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
337 TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
338 std::string parameters;
339 Serialize_TPM_HANDLE(virtual_handle, ¶meters);
340 std::string command = CreateCommand(TPM_CC_FlushContext,
341 kNoHandles,
342 kNoAuthorization,
343 parameters);
344 std::string expected_parameters;
345 Serialize_TPM_HANDLE(tpm_handle, &expected_parameters);
346 std::string expected_command = CreateCommand(TPM_CC_FlushContext,
347 kNoHandles,
348 kNoAuthorization,
349 expected_parameters);
350 std::string response = CreateResponse(TPM_RC_SUCCESS,
351 kNoHandles,
352 kNoAuthorization,
353 kNoParameters);
354 EXPECT_CALL(transceiver_, SendCommandAndWait(expected_command))
355 .WillOnce(Return(response));
356 std::string actual_response = resource_manager_.SendCommandAndWait(command);
357 EXPECT_EQ(response, actual_response);
358 // Now we expect there to be no record of |virtual_handle|.
359 std::vector<TPM_HANDLE> input_handles = {virtual_handle};
360 command = CreateCommand(TPM_CC_Sign,
361 input_handles,
362 kNoAuthorization,
363 kNoParameters);
364 response = CreateErrorResponse(TPM_RC_HANDLE | kResourceManagerTpmErrorBase);
365 actual_response = resource_manager_.SendCommandAndWait(command);
366 EXPECT_EQ(response, actual_response);
367
368 // Try again but attempt to flush |tpm_handle| instead of |virtual_handle|.
369 virtual_handle = LoadHandle(tpm_handle);
370 parameters.clear();
371 Serialize_TPM_HANDLE(tpm_handle, ¶meters);
372 command = CreateCommand(TPM_CC_FlushContext,
373 kNoHandles,
374 kNoAuthorization,
375 parameters);
376 actual_response = resource_manager_.SendCommandAndWait(command);
377 // TPM_RC_HANDLE also expected here.
378 EXPECT_EQ(response, actual_response);
379 }
380
TEST_F(ResourceManagerTest,VirtualHandleLoadBeforeUse)381 TEST_F(ResourceManagerTest, VirtualHandleLoadBeforeUse) {
382 TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
383 TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
384 EvictObjects();
385 std::vector<TPM_HANDLE> input_handles = {virtual_handle};
386 std::string command = CreateCommand(TPM_CC_Sign,
387 input_handles,
388 kNoAuthorization,
389 kNoParameters);
390 std::vector<TPM_HANDLE> expected_input_handles = {tpm_handle};
391 std::string expected_command = CreateCommand(TPM_CC_Sign,
392 expected_input_handles,
393 kNoAuthorization,
394 kNoParameters);
395 std::string response = CreateResponse(TPM_RC_SUCCESS,
396 kNoHandles,
397 kNoAuthorization,
398 kNoParameters);
399 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
400 .WillOnce(Return(TPM_RC_SUCCESS));
401 EXPECT_CALL(transceiver_, SendCommandAndWait(expected_command))
402 .WillOnce(Return(response));
403 std::string actual_response = resource_manager_.SendCommandAndWait(command);
404 EXPECT_EQ(response, actual_response);
405 }
406
TEST_F(ResourceManagerTest,InvalidVirtualHandle)407 TEST_F(ResourceManagerTest, InvalidVirtualHandle) {
408 std::vector<TPM_HANDLE> input_handles = {kArbitraryObjectHandle};
409 std::string command = CreateCommand(TPM_CC_Sign,
410 input_handles,
411 kNoAuthorization,
412 kNoParameters);
413 std::string response = CreateErrorResponse(TPM_RC_HANDLE |
414 kResourceManagerTpmErrorBase);
415 std::string actual_response = resource_manager_.SendCommandAndWait(command);
416 EXPECT_EQ(response, actual_response);
417 }
418
TEST_F(ResourceManagerTest,SimpleFuzzInputParser)419 TEST_F(ResourceManagerTest, SimpleFuzzInputParser) {
420 std::vector<TPM_HANDLE> handles = {1, 2};
421 std::string parameters = "12345";
422 std::string command = CreateCommand(TPM_CC_StartAuthSession,
423 handles,
424 CreateCommandAuthorization(
425 kArbitrarySessionHandle,
426 true), // continue_session
427 parameters);
428 // We don't care about what happens, only that it doesn't crash.
429 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
430 .WillRepeatedly(Return(CreateErrorResponse(TPM_RC_FAILURE)));
431 ScopedDisableLogging no_logging;
432 for (size_t i = 0; i < command.size(); ++i) {
433 resource_manager_.SendCommandAndWait(command.substr(0, i));
434 resource_manager_.SendCommandAndWait(command.substr(i));
435 std::string fuzzed_command(command);
436 for (uint8_t value = 0; ; value++) {
437 fuzzed_command[i] = static_cast<char>(value);
438 resource_manager_.SendCommandAndWait(fuzzed_command);
439 if (value == 255) {
440 break;
441 }
442 }
443 }
444 }
445
TEST_F(ResourceManagerTest,SimpleFuzzOutputParser)446 TEST_F(ResourceManagerTest, SimpleFuzzOutputParser) {
447 std::vector<TPM_HANDLE> handles = {1, 2};
448 std::string parameters = "12345";
449 std::string command = CreateCommand(TPM_CC_StartAuthSession,
450 handles,
451 CreateCommandAuthorization(
452 kArbitrarySessionHandle,
453 true), // continue_session
454 parameters);
455 std::vector<TPM_HANDLE> out_handles = {3};
456 std::string response = CreateResponse(TPM_RC_SUCCESS,
457 out_handles,
458 CreateResponseAuthorization(
459 true), // continue_session
460 parameters);
461 std::string fuzzed_response;
462 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
463 .WillRepeatedly(ReturnPointee(&fuzzed_response));
464 ScopedDisableLogging no_logging;
465 for (size_t i = 0; i < response.size(); ++i) {
466 fuzzed_response = response.substr(0, i);
467 resource_manager_.SendCommandAndWait(command);
468 fuzzed_response = response.substr(i);
469 resource_manager_.SendCommandAndWait(command);
470 fuzzed_response = response;
471 for (uint8_t value = 0; ; value++) {
472 fuzzed_response[i] = static_cast<char>(value);
473 resource_manager_.SendCommandAndWait(command);
474 if (value == 255) {
475 break;
476 }
477 }
478 fuzzed_response[i] = response[i];
479 }
480 }
481
TEST_F(ResourceManagerTest,NewSession)482 TEST_F(ResourceManagerTest, NewSession) {
483 StartSession(kArbitrarySessionHandle);
484 std::string command = CreateCommand(TPM_CC_Startup,
485 kNoHandles,
486 CreateCommandAuthorization(
487 kArbitrarySessionHandle,
488 true), // continue_session
489 kNoParameters);
490 std::string response = CreateResponse(TPM_RC_SUCCESS,
491 kNoHandles,
492 CreateResponseAuthorization(
493 true), // continue_session
494 kNoParameters);
495 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
496 .WillOnce(Return(response));
497 std::string actual_response = resource_manager_.SendCommandAndWait(command);
498 EXPECT_EQ(response, actual_response);
499 }
500
TEST_F(ResourceManagerTest,DiscontinuedSession)501 TEST_F(ResourceManagerTest, DiscontinuedSession) {
502 StartSession(kArbitrarySessionHandle);
503 // Use the session but do not continue.
504 std::string command = CreateCommand(TPM_CC_Startup,
505 kNoHandles,
506 CreateCommandAuthorization(
507 kArbitrarySessionHandle,
508 false), // continue_session
509 kNoParameters);
510 std::string response = CreateResponse(TPM_RC_SUCCESS,
511 kNoHandles,
512 CreateResponseAuthorization(
513 false), // continue_session
514 kNoParameters);
515 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
516 .WillOnce(Return(response));
517 std::string actual_response = resource_manager_.SendCommandAndWait(command);
518 EXPECT_EQ(response, actual_response);
519 // Now attempt to use it again and expect a handle error.
520 response = CreateErrorResponse(TPM_RC_HANDLE | kResourceManagerTpmErrorBase);
521 actual_response = resource_manager_.SendCommandAndWait(command);
522 EXPECT_EQ(response, actual_response);
523 }
524
TEST_F(ResourceManagerTest,LoadSessionBeforeUse)525 TEST_F(ResourceManagerTest, LoadSessionBeforeUse) {
526 StartSession(kArbitrarySessionHandle);
527 EvictSession();
528 std::string command = CreateCommand(TPM_CC_Startup,
529 kNoHandles,
530 CreateCommandAuthorization(
531 kArbitrarySessionHandle,
532 true), // continue_session
533 kNoParameters);
534 std::string response = CreateResponse(TPM_RC_SUCCESS,
535 kNoHandles,
536 CreateResponseAuthorization(
537 true), // continue_session
538 kNoParameters);
539 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
540 .WillOnce(Return(response));
541 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
542 .WillOnce(Return(TPM_RC_SUCCESS));
543 std::string actual_response = resource_manager_.SendCommandAndWait(command);
544 EXPECT_EQ(response, actual_response);
545 }
546
TEST_F(ResourceManagerTest,SessionHandleCleanup)547 TEST_F(ResourceManagerTest, SessionHandleCleanup) {
548 StartSession(kArbitrarySessionHandle);
549 std::string parameters;
550 Serialize_TPM_HANDLE(kArbitrarySessionHandle, ¶meters);
551 std::string command = CreateCommand(TPM_CC_FlushContext,
552 kNoHandles,
553 kNoAuthorization,
554 parameters);
555 std::string response = CreateResponse(TPM_RC_SUCCESS,
556 kNoHandles,
557 kNoAuthorization,
558 kNoParameters);
559 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
560 .WillOnce(Return(response));
561 std::string actual_response = resource_manager_.SendCommandAndWait(command);
562 EXPECT_EQ(response, actual_response);
563 // Now we expect there to be no record of |kArbitrarySessionHandle|.
564 command = CreateCommand(TPM_CC_Startup,
565 kNoHandles,
566 CreateCommandAuthorization(
567 kArbitrarySessionHandle,
568 true), // continue_session
569 kNoParameters);
570 response = CreateErrorResponse(TPM_RC_HANDLE | kResourceManagerTpmErrorBase);
571 actual_response = resource_manager_.SendCommandAndWait(command);
572 EXPECT_EQ(response, actual_response);
573 }
574
TEST_F(ResourceManagerTest,EvictWhenObjectInUse)575 TEST_F(ResourceManagerTest, EvictWhenObjectInUse) {
576 TPM_HANDLE tpm_handle = kArbitraryObjectHandle;
577 TPM_HANDLE virtual_handle = LoadHandle(tpm_handle);
578 TPM_HANDLE tpm_handle2 = kArbitraryObjectHandle + 1;
579 LoadHandle(tpm_handle2);
580 std::vector<TPM_HANDLE> input_handles = {virtual_handle};
581 std::string command = CreateCommand(TPM_CC_Sign,
582 input_handles,
583 kNoAuthorization,
584 kNoParameters);
585 // Trigger evict logic and verify |input_handles| are not evicted.
586 std::string response = CreateErrorResponse(TPM_RC_OBJECT_MEMORY);
587 std::string success_response = CreateResponse(TPM_RC_SUCCESS,
588 kNoHandles,
589 kNoAuthorization,
590 kNoParameters);
591 EXPECT_CALL(tpm_, ContextSaveSync(tpm_handle2, _, _, _))
592 .WillOnce(Return(TPM_RC_SUCCESS));
593 EXPECT_CALL(tpm_, FlushContextSync(tpm_handle2, _))
594 .WillOnce(Return(TPM_RC_SUCCESS));
595 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
596 .WillOnce(Return(response))
597 .WillRepeatedly(Return(success_response));
598 std::string actual_response = resource_manager_.SendCommandAndWait(command);
599 EXPECT_EQ(success_response, actual_response);
600 }
601
TEST_F(ResourceManagerTest,EvictWhenSessionInUse)602 TEST_F(ResourceManagerTest, EvictWhenSessionInUse) {
603 StartSession(kArbitrarySessionHandle);
604 StartSession(kArbitrarySessionHandle + 1);
605 std::string command = CreateCommand(TPM_CC_Startup,
606 kNoHandles,
607 CreateCommandAuthorization(
608 kArbitrarySessionHandle,
609 true), // continue_session
610 kNoParameters);
611 std::string response = CreateResponse(TPM_RC_SUCCESS,
612 kNoHandles,
613 CreateResponseAuthorization(
614 true), // continue_session
615 kNoParameters);
616 std::string error_response = CreateErrorResponse(TPM_RC_SESSION_MEMORY);
617 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
618 .WillOnce(Return(error_response))
619 .WillRepeatedly(Return(response));
620 EXPECT_CALL(tpm_, ContextSaveSync(kArbitrarySessionHandle + 1, _, _, _))
621 .WillOnce(Return(TPM_RC_SUCCESS));
622 std::string actual_response = resource_manager_.SendCommandAndWait(command);
623 EXPECT_EQ(response, actual_response);
624 }
625
TEST_F(ResourceManagerTest,EvictMultipleObjects)626 TEST_F(ResourceManagerTest, EvictMultipleObjects) {
627 const int kNumObjects = 10;
628 std::map<TPM_HANDLE, TPM_HANDLE> handles;
629 for (int i = 0; i < kNumObjects; ++i) {
630 TPM_HANDLE handle = kArbitraryObjectHandle + i;
631 handles[LoadHandle(handle)] = handle;
632 }
633 EvictObjects();
634 std::string response = CreateResponse(TPM_RC_SUCCESS,
635 kNoHandles,
636 kNoAuthorization,
637 kNoParameters);
638 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
639 .Times(kNumObjects)
640 .WillRepeatedly(Return(TPM_RC_SUCCESS));
641 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
642 .WillRepeatedly(Return(response));
643 for (auto item : handles) {
644 std::vector<TPM_HANDLE> input_handles = {item.first};
645 std::string command = CreateCommand(TPM_CC_Sign,
646 input_handles,
647 kNoAuthorization,
648 kNoParameters);
649 std::string actual_response = resource_manager_.SendCommandAndWait(command);
650 EXPECT_EQ(response, actual_response);
651 }
652 }
653
TEST_F(ResourceManagerTest,EvictMostStaleSession)654 TEST_F(ResourceManagerTest, EvictMostStaleSession) {
655 StartSession(kArbitrarySessionHandle);
656 StartSession(kArbitrarySessionHandle + 1);
657 StartSession(kArbitrarySessionHandle + 2);
658 std::string response = CreateResponse(TPM_RC_SUCCESS,
659 kNoHandles,
660 CreateResponseAuthorization(
661 true), // continue_session
662 kNoParameters);
663 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
664 .WillRepeatedly(Return(response));
665 // Use the first two sessions, leaving the third as the most stale.
666 for (int i = 0; i < 2; ++i) {
667 std::string command = CreateCommand(TPM_CC_Startup,
668 kNoHandles,
669 CreateCommandAuthorization(
670 kArbitrarySessionHandle + i,
671 true), // continue_session
672 kNoParameters);
673 std::string actual_response = resource_manager_.SendCommandAndWait(command);
674 EXPECT_EQ(response, actual_response);
675 }
676 EvictSession();
677 // EvictSession will have messed with the expectations; set them again.
678 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
679 .WillRepeatedly(Return(response));
680 // Use the first two sessions again, expecting no calls to ContextLoad.
681 for (int i = 0; i < 2; ++i) {
682 std::string command = CreateCommand(TPM_CC_Startup,
683 kNoHandles,
684 CreateCommandAuthorization(
685 kArbitrarySessionHandle + i,
686 true), // continue_session
687 kNoParameters);
688 std::string actual_response = resource_manager_.SendCommandAndWait(command);
689 EXPECT_EQ(response, actual_response);
690 }
691 // Expect a call to ContextLoad if we use the third session.
692 std::string command = CreateCommand(TPM_CC_Startup,
693 kNoHandles,
694 CreateCommandAuthorization(
695 kArbitrarySessionHandle + 2,
696 true), // continue_session
697 kNoParameters);
698 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
699 .WillOnce(Return(TPM_RC_SUCCESS));
700 std::string actual_response = resource_manager_.SendCommandAndWait(command);
701 EXPECT_EQ(response, actual_response);
702 }
703
TEST_F(ResourceManagerTest,HandleContextGap)704 TEST_F(ResourceManagerTest, HandleContextGap) {
705 const int kNumSessions = 7;
706 const int kNumSessionsToUngap = 4;
707 std::vector<TPM_HANDLE> expected_ungap_order;
708 for (int i = 0; i < kNumSessions; ++i) {
709 StartSession(kArbitrarySessionHandle + i);
710 if (i < kNumSessionsToUngap) {
711 EvictSession();
712 expected_ungap_order.push_back(kArbitrarySessionHandle + i);
713 }
714 }
715 // Invoke a context gap.
716 std::string command = CreateCommand(TPM_CC_Startup,
717 kNoHandles,
718 kNoAuthorization,
719 kNoParameters);
720 std::string response = CreateErrorResponse(TPM_RC_CONTEXT_GAP);
721 std::string success_response = CreateResponse(TPM_RC_SUCCESS,
722 kNoHandles,
723 kNoAuthorization,
724 kNoParameters);
725 {
726 InSequence ungap_order;
727 for (auto handle : expected_ungap_order) {
728 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
729 .WillOnce(Return(TPM_RC_SUCCESS));
730 EXPECT_CALL(tpm_, ContextSaveSync(handle, _, _, _))
731 .WillOnce(Return(TPM_RC_SUCCESS));
732 }
733 }
734 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
735 .WillOnce(Return(response))
736 .WillRepeatedly(Return(success_response));
737 std::string actual_response = resource_manager_.SendCommandAndWait(command);
738 EXPECT_EQ(success_response, actual_response);
739 }
740
TEST_F(ResourceManagerTest,ExternalContext)741 TEST_F(ResourceManagerTest, ExternalContext) {
742 StartSession(kArbitrarySessionHandle);
743 // Do an external context save.
744 std::vector<TPM_HANDLE> handles = {kArbitrarySessionHandle};
745 std::string context_save = CreateCommand(TPM_CC_ContextSave,
746 handles,
747 kNoAuthorization,
748 kNoParameters);
749 std::string context_parameter1 = CreateContextParameter(1);
750 std::string context_save_response1 = CreateResponse(TPM_RC_SUCCESS,
751 kNoHandles,
752 kNoAuthorization,
753 context_parameter1);
754 EXPECT_CALL(transceiver_, SendCommandAndWait(context_save))
755 .WillOnce(Return(context_save_response1));
756 std::string actual_response = resource_manager_.SendCommandAndWait(
757 context_save);
758 EXPECT_EQ(context_save_response1, actual_response);
759
760 // Invoke a context gap (which will cause context1 to be mapped to context2).
761 EXPECT_CALL(tpm_, ContextLoadSync(Field(&TPMS_CONTEXT::sequence, Eq(1u)),
762 _, _))
763 .WillOnce(Return(TPM_RC_SUCCESS));
764 EXPECT_CALL(tpm_, ContextSaveSync(kArbitrarySessionHandle, _, _, _))
765 .WillOnce(DoAll(SetArgumentPointee<2>(CreateContext(2)),
766 Return(TPM_RC_SUCCESS)));
767 std::string command = CreateCommand(TPM_CC_Startup,
768 kNoHandles,
769 kNoAuthorization,
770 kNoParameters);
771 std::string response = CreateErrorResponse(TPM_RC_CONTEXT_GAP);
772 std::string success_response = CreateResponse(TPM_RC_SUCCESS,
773 kNoHandles,
774 kNoAuthorization,
775 kNoParameters);
776 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
777 .WillOnce(Return(response))
778 .WillOnce(Return(success_response));
779 actual_response = resource_manager_.SendCommandAndWait(command);
780 EXPECT_EQ(success_response, actual_response);
781
782 // Now load external context1 and expect an actual load of context2.
783 std::string context_load1 = CreateCommand(TPM_CC_ContextLoad,
784 kNoHandles,
785 kNoAuthorization,
786 context_parameter1);
787 std::string context_load2 = CreateCommand(TPM_CC_ContextLoad,
788 kNoHandles,
789 kNoAuthorization,
790 CreateContextParameter(2));
791 std::string context_load_response = CreateResponse(TPM_RC_SUCCESS,
792 handles,
793 kNoAuthorization,
794 kNoParameters);
795 EXPECT_CALL(transceiver_, SendCommandAndWait(context_load2))
796 .WillOnce(Return(context_load_response));
797 actual_response = resource_manager_.SendCommandAndWait(context_load1);
798 EXPECT_EQ(context_load_response, actual_response);
799 }
800
TEST_F(ResourceManagerTest,NestedFailures)801 TEST_F(ResourceManagerTest, NestedFailures) {
802 // The scenario being tested is when a command results in a warning to be
803 // handled by the resource manager, and in the process of handling the first
804 // warning another warning occurs which should be handled by the resource
805 // manager, etc..
806 for (int i = 0; i < 3; ++i) {
807 LoadHandle(kArbitraryObjectHandle + i);
808 }
809 EvictObjects();
810 for (int i = 3; i < 6; ++i) {
811 LoadHandle(kArbitraryObjectHandle + i);
812 }
813 for (int i = 0; i < 10; ++i) {
814 StartSession(kArbitrarySessionHandle + i);
815 EvictSession();
816 }
817 for (int i = 10; i < 20; ++i) {
818 StartSession(kArbitrarySessionHandle + i);
819 }
820 std::string error_response = CreateErrorResponse(TPM_RC_MEMORY);
821 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
822 .WillRepeatedly(Return(error_response));
823 // The TPM_RC_MEMORY will result in a context save, make that fail too.
824 EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
825 .WillRepeatedly(Return(TPM_RC_CONTEXT_GAP));
826 // The TPM_RC_CONTEXT_GAP will result in a context load.
827 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
828 .WillRepeatedly(Return(TPM_RC_SESSION_HANDLES));
829 // The TPM_RC_SESSION_HANDLES will result in a context flush.
830 EXPECT_CALL(tpm_, FlushContextSync(_, _))
831 .WillRepeatedly(Return(TPM_RC_SESSION_MEMORY));
832 // The resource manager should not handle the same warning twice so we expect
833 // the error of the original call to bubble up.
834 std::string command = CreateCommand(TPM_CC_Startup,
835 kNoHandles,
836 kNoAuthorization,
837 kNoParameters);
838 std::string response = resource_manager_.SendCommandAndWait(command);
839 EXPECT_EQ(error_response, response);
840 }
841
TEST_F(ResourceManagerTest,OutOfMemory)842 TEST_F(ResourceManagerTest, OutOfMemory) {
843 std::string error_response = CreateErrorResponse(TPM_RC_MEMORY);
844 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
845 .WillRepeatedly(Return(error_response));
846 std::string command = CreateCommand(TPM_CC_Startup,
847 kNoHandles,
848 kNoAuthorization,
849 kNoParameters);
850 std::string response = resource_manager_.SendCommandAndWait(command);
851 EXPECT_EQ(error_response, response);
852 }
853
TEST_F(ResourceManagerTest,ReentrantFixGap)854 TEST_F(ResourceManagerTest, ReentrantFixGap) {
855 for (int i = 0; i < 3; ++i) {
856 StartSession(kArbitrarySessionHandle + i);
857 EvictSession();
858 }
859 for (int i = 3; i < 6; ++i) {
860 StartSession(kArbitrarySessionHandle + i);
861 }
862 std::string error_response = CreateErrorResponse(TPM_RC_CONTEXT_GAP);
863 EXPECT_CALL(transceiver_, SendCommandAndWait(_))
864 .WillRepeatedly(Return(error_response));
865 EXPECT_CALL(tpm_, ContextSaveSync(_, _, _, _))
866 .WillRepeatedly(Return(TPM_RC_CONTEXT_GAP));
867 EXPECT_CALL(tpm_, ContextLoadSync(_, _, _))
868 .WillOnce(Return(TPM_RC_CONTEXT_GAP))
869 .WillRepeatedly(Return(TPM_RC_SUCCESS));
870 std::string command = CreateCommand(TPM_CC_Startup,
871 kNoHandles,
872 kNoAuthorization,
873 kNoParameters);
874 std::string response = resource_manager_.SendCommandAndWait(command);
875 EXPECT_EQ(error_response, response);
876 }
877
TEST_F(ResourceManagerTest,PasswordAuthorization)878 TEST_F(ResourceManagerTest, PasswordAuthorization) {
879 std::string command = CreateCommand(TPM_CC_Startup,
880 kNoHandles,
881 CreateCommandAuthorization(
882 TPM_RS_PW,
883 false), // continue_session
884 kNoParameters);
885 std::string response = CreateResponse(TPM_RC_SUCCESS,
886 kNoHandles,
887 CreateResponseAuthorization(
888 false), // continue_session
889 kNoParameters);
890 EXPECT_CALL(transceiver_, SendCommandAndWait(command))
891 .WillOnce(Return(response));
892 std::string actual_response = resource_manager_.SendCommandAndWait(command);
893 EXPECT_EQ(response, actual_response);
894 }
895
896 } // namespace trunks
897