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 31using testing::_; 32using testing::DoAll; 33using testing::Eq; 34using testing::Field; 35using testing::InSequence; 36using testing::Return; 37using testing::ReturnPointee; 38using testing::SetArgumentPointee; 39using testing::StrictMock; 40 41namespace { 42 43const trunks::TPM_HANDLE kArbitraryObjectHandle = trunks::TRANSIENT_FIRST + 25; 44const trunks::TPM_HANDLE kArbitrarySessionHandle = trunks::HMAC_SESSION_FIRST; 45 46void Assign(std::string* to, const std::string& from) { 47 *to = from; 48} 49 50class ScopedDisableLogging { 51 public: 52 ScopedDisableLogging() : original_severity_(logging::GetMinLogLevel()) { 53 logging::SetMinLogLevel(logging::LOG_FATAL); 54 } 55 ~ScopedDisableLogging() { 56 logging::SetMinLogLevel(original_severity_); 57 } 58 59 private: 60 logging::LogSeverity original_severity_; 61}; 62 63} // namespace 64 65namespace trunks { 66 67class ResourceManagerTest : public testing::Test { 68 public: 69 const std::vector<TPM_HANDLE> kNoHandles; 70 const std::string kNoAuthorization; 71 const std::string kNoParameters; 72 73 ResourceManagerTest() : resource_manager_(factory_, &transceiver_) {} 74 ~ResourceManagerTest() override {} 75 76 void SetUp() override { 77 factory_.set_tpm(&tpm_); 78 } 79 80 // Builds a well-formed command. 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. 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. 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. 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 142 std::string GetHeader(const std::string& message) { 143 return message.substr(0, 10); 144 } 145 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. 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. 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. 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. 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. 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. 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 253TEST_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 268TEST_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 286TEST_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 310TEST_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 335TEST_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 381TEST_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 407TEST_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 419TEST_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 446TEST_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 482TEST_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 501TEST_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 525TEST_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 547TEST_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 575TEST_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 602TEST_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 626TEST_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 654TEST_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 704TEST_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 741TEST_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 801TEST_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 842TEST_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 854TEST_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 878TEST_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