• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &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 
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, &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 
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