Home | History | Annotate | Download | only in trunks
      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 
     46 void Assign(std::string* to, const std::string& from) {
     47   *to = from;
     48 }
     49 
     50 class 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 
     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 
     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 
    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 
    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 
    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 
    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 
    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, &parameters);
    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, &parameters);
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    547 TEST_F(ResourceManagerTest, SessionHandleCleanup) {
    548   StartSession(kArbitrarySessionHandle);
    549   std::string parameters;
    550   Serialize_TPM_HANDLE(kArbitrarySessionHandle, &parameters);
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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