1 //
2 // Copyright (C) 2014 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 // Note: These tests are not generated. They test generated code.
18
19 #include <base/bind.h>
20 #include <base/callback.h>
21 #include <base/message_loop/message_loop.h>
22 #include <base/run_loop.h>
23 #include <gtest/gtest.h>
24
25 #include "trunks/mock_authorization_delegate.h"
26 #include "trunks/mock_command_transceiver.h"
27 #include "trunks/tpm_generated.h"
28
29 using testing::_;
30 using testing::DoAll;
31 using testing::Invoke;
32 using testing::Return;
33 using testing::SetArgPointee;
34 using testing::StrictMock;
35 using testing::WithArg;
36
37 namespace trunks {
38
39 // This test is designed to get good coverage of the different types of code
40 // generated for serializing and parsing structures / unions / typedefs.
TEST(GeneratorTest,SerializeParseStruct)41 TEST(GeneratorTest, SerializeParseStruct) {
42 TPM2B_CREATION_DATA data;
43 memset(&data, 0, sizeof(TPM2B_CREATION_DATA));
44 data.creation_data.pcr_select.count = 1;
45 data.creation_data.pcr_select.pcr_selections[0].hash = TPM_ALG_SHA256;
46 data.creation_data.pcr_select.pcr_selections[0].sizeof_select = 1;
47 data.creation_data.pcr_select.pcr_selections[0].pcr_select[0] = 0;
48 data.creation_data.pcr_digest.size = 2;
49 data.creation_data.locality = 0;
50 data.creation_data.parent_name_alg = TPM_ALG_SHA256;
51 data.creation_data.parent_name.size = 3;
52 data.creation_data.parent_qualified_name.size = 4;
53 data.creation_data.outside_info.size = 5;
54 std::string buffer;
55 TPM_RC rc = Serialize_TPM2B_CREATION_DATA(data, &buffer);
56 ASSERT_EQ(TPM_RC_SUCCESS, rc);
57 EXPECT_EQ(35u, buffer.size());
58 TPM2B_CREATION_DATA data2;
59 memset(&data2, 0, sizeof(TPM2B_CREATION_DATA));
60 std::string buffer_before = buffer;
61 std::string buffer_parsed;
62 rc = Parse_TPM2B_CREATION_DATA(&buffer, &data2, &buffer_parsed);
63 ASSERT_EQ(TPM_RC_SUCCESS, rc);
64 EXPECT_EQ(0u, buffer.size());
65 EXPECT_EQ(buffer_before, buffer_parsed);
66 EXPECT_EQ(buffer_before.size() - 2, data2.size);
67 EXPECT_EQ(0, memcmp(&data.creation_data, &data2.creation_data,
68 sizeof(TPMS_CREATION_DATA)));
69 }
70
TEST(GeneratorTest,SerializeBufferOverflow)71 TEST(GeneratorTest, SerializeBufferOverflow) {
72 TPM2B_MAX_BUFFER value;
73 value.size = arraysize(value.buffer) + 1;
74 std::string tmp;
75 EXPECT_EQ(TPM_RC_INSUFFICIENT, Serialize_TPM2B_MAX_BUFFER(value, &tmp));
76 }
77
TEST(GeneratorTest,ParseBufferOverflow)78 TEST(GeneratorTest, ParseBufferOverflow) {
79 TPM2B_MAX_BUFFER tmp;
80 // Case 1: Sufficient source but overflow the destination.
81 std::string malformed1 = "\x10\x00";
82 malformed1 += std::string(0x1000, 'A');
83 ASSERT_GT(0x1000u, sizeof(tmp.buffer));
84 EXPECT_EQ(TPM_RC_INSUFFICIENT,
85 Parse_TPM2B_MAX_BUFFER(&malformed1, &tmp, nullptr));
86 // Case 2: Sufficient destination but overflow the source.
87 std::string malformed2 = "\x00\x01";
88 EXPECT_EQ(TPM_RC_INSUFFICIENT,
89 Parse_TPM2B_MAX_BUFFER(&malformed2, &tmp, nullptr));
90 }
91
TEST(GeneratorTest,SynchronousCommand)92 TEST(GeneratorTest, SynchronousCommand) {
93 // A hand-rolled TPM2_Startup command.
94 std::string expected_command(
95 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
96 "\x00\x00\x00\x0C" // size=12
97 "\x00\x00\x01\x44" // code=TPM_CC_Startup
98 "\x00\x00", // param=TPM_SU_CLEAR
99 12);
100 std::string command_response(
101 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
102 "\x00\x00\x00\x0A" // size=10
103 "\x00\x00\x00\x00", // code=TPM_RC_SUCCESS
104 10);
105 StrictMock<MockCommandTransceiver> transceiver;
106 EXPECT_CALL(transceiver, SendCommandAndWait(expected_command))
107 .WillOnce(Return(command_response));
108 StrictMock<MockAuthorizationDelegate> authorization;
109 EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
110 .WillOnce(Return(true));
111 Tpm tpm(&transceiver);
112 EXPECT_EQ(TPM_RC_SUCCESS, tpm.StartupSync(TPM_SU_CLEAR, &authorization));
113 }
114
TEST(GeneratorTest,SynchronousCommandWithError)115 TEST(GeneratorTest, SynchronousCommandWithError) {
116 // A hand-rolled TPM2_Startup command.
117 std::string expected_command(
118 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
119 "\x00\x00\x00\x0C" // size=12
120 "\x00\x00\x01\x44" // code=TPM_CC_Startup
121 "\x00\x00", // param=TPM_SU_CLEAR
122 12);
123 std::string command_response(
124 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
125 "\x00\x00\x00\x0A" // size=10
126 "\x00\x00\x01\x01", // code=TPM_RC_FAILURE
127 10);
128 StrictMock<MockCommandTransceiver> transceiver;
129 EXPECT_CALL(transceiver, SendCommandAndWait(expected_command))
130 .WillOnce(Return(command_response));
131 StrictMock<MockAuthorizationDelegate> authorization;
132 EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
133 .WillOnce(Return(true));
134 Tpm tpm(&transceiver);
135 EXPECT_EQ(TPM_RC_FAILURE, tpm.StartupSync(TPM_SU_CLEAR, &authorization));
136 }
137
TEST(GeneratorTest,SynchronousCommandResponseTest)138 TEST(GeneratorTest, SynchronousCommandResponseTest) {
139 std::string auth_in(10, 'A');
140 std::string auth_out(10, 'B');
141 std::string auth_size("\x00\x00\x00\x0A", 4);
142 std::string handle_in("\x40\x00\x00\x07", 4); // primary_handle = TPM_RH_NULL
143 std::string handle_out("\x80\x00\x00\x01", 4); // out_handle
144 std::string sensitive(
145 "\x00\x05" // sensitive.size = 5
146 "\x00\x01" // sensitive.auth.size = 1
147 "\x61" // sensitive.auth.buffer[0] = 0x65
148 "\x00\x00", // sensitive.data.size = 0
149 7);
150 std::string public_data(
151 "\x00\x12" // public.size = 18
152 "\x00\x25" // public.type = TPM_ALG_SYMCIPHER
153 "\x00\x0B" // public.name_alg = SHA256
154 "\x00\x00\x00\x00"
155 "\x00\x00" // public.auth_policy.size = 0
156 "\x00\x06" // public.sym.alg = TPM_ALG_AES
157 "\x00\x80" // public.sym.key_bits = 128
158 "\x00\x43" // public.sym.mode = TPM_ALG_CFB
159 "\x00\x00", // public.unique.size = 0
160 20);
161 std::string outside("\x00\x00", 2); // outside_info.size = 0
162 std::string pcr_select("\x00\x00\x00\x00", 4); // pcr_select.size = 0
163
164 std::string data(
165 "\x00\x0F" // creation_data.size = 15
166 "\x00\x00\x00\x00" // creation.pcr = 0
167 "\x00\x00" // creation.digest.size = 0
168 "\x00" // creation.locality = 0
169 "\x00\x00" // creation.parent_alg = 0
170 "\x00\x00" // creation.parent_name.size = 0
171 "\x00\x00"
172 "\x00\x00", // creation.outside.size = 0
173 17);
174 std::string hash(
175 "\x00\x01"
176 "\x62",
177 3);
178 std::string ticket(
179 "\x80\x02" // tag = TPM_ST_SESSIONS
180 "\x40\x00\x00\x07" // parent = TPM_RH_NULL
181 "\x00\x00",
182 8);
183 std::string name(
184 "\x00\x03"
185 "KEY",
186 5);
187 std::string parameter_size("\x00\x00\x00\x35", 4); // param_size = 38
188
189 std::string command_tag(
190 "\x80\x02" // tag = TPM_ST_SESSIONS
191 "\x00\x00\x00\x3D" // size = 61
192 "\x00\x00\x01\x31", // code = TPM_CC_CreatePrimary
193 10);
194 std::string response_tag(
195 "\x80\x02" // tag = TPM_ST_SESSIONS
196 "\x00\x00\x00\x51" // size = 79
197 "\x00\x00\x00\x00", // rc = TPM_RC_SUCCESS
198 10);
199
200 std::string expected_command = command_tag + handle_in + auth_size + auth_in +
201 sensitive + public_data + outside + pcr_select;
202 std::string command_response = response_tag + handle_out + parameter_size +
203 public_data + data + hash + ticket + name +
204 auth_out;
205
206 StrictMock<MockCommandTransceiver> transceiver;
207 EXPECT_CALL(transceiver, SendCommandAndWait(expected_command))
208 .WillOnce(Return(command_response));
209 StrictMock<MockAuthorizationDelegate> authorization;
210 EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
211 .WillOnce(DoAll(SetArgPointee<3>(auth_in), Return(true)));
212 EXPECT_CALL(authorization, CheckResponseAuthorization(_, auth_out))
213 .WillOnce(Return(true));
214 EXPECT_CALL(authorization, EncryptCommandParameter(_)).WillOnce(Return(true));
215 EXPECT_CALL(authorization, DecryptResponseParameter(_))
216 .WillOnce(Return(true));
217
218 TPM2B_SENSITIVE_CREATE in_sensitive;
219 in_sensitive.size = 5;
220 in_sensitive.sensitive.user_auth.size = 1;
221 in_sensitive.sensitive.user_auth.buffer[0] = 'a';
222 in_sensitive.sensitive.data.size = 0;
223 TPM2B_PUBLIC in_public;
224 in_public.size = 18;
225 in_public.public_area.type = TPM_ALG_SYMCIPHER;
226 in_public.public_area.name_alg = TPM_ALG_SHA256;
227 in_public.public_area.object_attributes = 0;
228 in_public.public_area.auth_policy.size = 0;
229 in_public.public_area.parameters.sym_detail.sym.algorithm = TPM_ALG_AES;
230 in_public.public_area.parameters.sym_detail.sym.key_bits.aes = 128;
231 in_public.public_area.parameters.sym_detail.sym.mode.aes = TPM_ALG_CFB;
232 in_public.public_area.unique.sym.size = 0;
233 TPM2B_DATA outside_info;
234 outside_info.size = 0;
235 TPML_PCR_SELECTION create_pcr;
236 create_pcr.count = 0;
237
238 TPM_HANDLE key_handle;
239 TPM2B_PUBLIC out_public;
240 TPM2B_CREATION_DATA creation_data;
241 TPM2B_DIGEST creation_hash;
242 TPMT_TK_CREATION creation_ticket;
243 TPM2B_NAME key_name;
244
245 Tpm tpm(&transceiver);
246 TPM_RC rc = tpm.CreatePrimarySync(
247 trunks::TPM_RH_NULL, "", in_sensitive, in_public, outside_info,
248 create_pcr, &key_handle, &out_public, &creation_data, &creation_hash,
249 &creation_ticket, &key_name, &authorization);
250 ASSERT_EQ(rc, TPM_RC_SUCCESS);
251 EXPECT_EQ(key_handle, 0x80000001);
252 EXPECT_EQ(out_public.size, 18);
253 EXPECT_EQ(creation_data.size, 15);
254 EXPECT_EQ(creation_hash.size, 1);
255 EXPECT_EQ(creation_hash.buffer[0], 'b');
256 EXPECT_EQ(creation_ticket.tag, 0x8002);
257 EXPECT_EQ(creation_ticket.hierarchy, 0x40000007u);
258 EXPECT_EQ(creation_ticket.digest.size, 0);
259 EXPECT_EQ(key_name.size, 3);
260 EXPECT_EQ(key_name.name[0], 'K');
261 EXPECT_EQ(key_name.name[1], 'E');
262 EXPECT_EQ(key_name.name[2], 'Y');
263 }
264
265 // A fixture for asynchronous command flow tests.
266 class CommandFlowTest : public testing::Test {
267 public:
CommandFlowTest()268 CommandFlowTest() : response_code_(TPM_RC_SUCCESS) {}
~CommandFlowTest()269 ~CommandFlowTest() override {}
270
StartupCallback(TPM_RC response_code)271 void StartupCallback(TPM_RC response_code) { response_code_ = response_code; }
272
CertifyCallback(TPM_RC response_code,const TPM2B_ATTEST & certify_info,const TPMT_SIGNATURE & signature)273 void CertifyCallback(TPM_RC response_code,
274 const TPM2B_ATTEST& certify_info,
275 const TPMT_SIGNATURE& signature) {
276 response_code_ = response_code;
277 signed_data_ = StringFrom_TPM2B_ATTEST(certify_info);
278 signature_ =
279 StringFrom_TPM2B_PUBLIC_KEY_RSA(signature.signature.rsassa.sig);
280 }
281
282 protected:
Run()283 void Run() {
284 base::RunLoop run_loop;
285 run_loop.RunUntilIdle();
286 }
287
288 base::MessageLoop message_loop_;
289 TPM_RC response_code_;
290 std::string signature_;
291 std::string signed_data_;
292 };
293
294 // A functor for posting command responses. This is different than invoking the
295 // callback directly (e.g. via InvokeArgument) in that the original call will
296 // return before the response callback is invoked. This more closely matches how
297 // this code is expected to work when integrated.
298 class PostResponse {
299 public:
PostResponse(const std::string & response)300 explicit PostResponse(const std::string& response) : response_(response) {}
operator ()(const base::Callback<void (const std::string &)> & callback)301 void operator()(const base::Callback<void(const std::string&)>& callback) {
302 base::MessageLoop::current()->PostTask(FROM_HERE,
303 base::Bind(callback, response_));
304 }
305
306 private:
307 std::string response_;
308 };
309
310 // A functor to handle fake encryption / decryption of parameters.
311 class Encryptor {
312 public:
Encryptor(const std::string & expected_input,const std::string & output)313 Encryptor(const std::string& expected_input, const std::string& output)
314 : expected_input_(expected_input), output_(output) {}
operator ()(std::string * value)315 bool operator()(std::string* value) {
316 EXPECT_EQ(expected_input_, *value);
317 value->assign(output_);
318 return true;
319 }
320
321 private:
322 std::string expected_input_;
323 std::string output_;
324 };
325
TEST_F(CommandFlowTest,SimpleCommandFlow)326 TEST_F(CommandFlowTest, SimpleCommandFlow) {
327 // A hand-rolled TPM2_Startup command.
328 std::string expected_command(
329 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
330 "\x00\x00\x00\x0C" // size=12
331 "\x00\x00\x01\x44" // code=TPM_CC_Startup
332 "\x00\x00", // param=TPM_SU_CLEAR
333 12);
334 std::string command_response(
335 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
336 "\x00\x00\x00\x0A" // size=10
337 "\x00\x00\x00\x00", // code=TPM_RC_SUCCESS
338 10);
339 StrictMock<MockCommandTransceiver> transceiver;
340 EXPECT_CALL(transceiver, SendCommand(expected_command, _))
341 .WillOnce(WithArg<1>(Invoke(PostResponse(command_response))));
342 StrictMock<MockAuthorizationDelegate> authorization;
343 EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
344 .WillOnce(Return(true));
345 Tpm tpm(&transceiver);
346 response_code_ = TPM_RC_FAILURE;
347 tpm.Startup(
348 TPM_SU_CLEAR, &authorization,
349 base::Bind(&CommandFlowTest::StartupCallback, base::Unretained(this)));
350 Run();
351 EXPECT_EQ(TPM_RC_SUCCESS, response_code_);
352 }
353
TEST_F(CommandFlowTest,SimpleCommandFlowWithError)354 TEST_F(CommandFlowTest, SimpleCommandFlowWithError) {
355 // A hand-rolled TPM2_Startup command.
356 std::string expected_command(
357 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
358 "\x00\x00\x00\x0C" // size=12
359 "\x00\x00\x01\x44" // code=TPM_CC_Startup
360 "\x00\x00", // param=TPM_SU_CLEAR
361 12);
362 std::string command_response(
363 "\x80\x01" // tag=TPM_ST_NO_SESSIONS
364 "\x00\x00\x00\x0A" // size=10
365 "\x00\x00\x01\x01", // code=TPM_RC_FAILURE
366 10);
367 StrictMock<MockCommandTransceiver> transceiver;
368 EXPECT_CALL(transceiver, SendCommand(expected_command, _))
369 .WillOnce(WithArg<1>(Invoke(PostResponse(command_response))));
370 StrictMock<MockAuthorizationDelegate> authorization;
371 EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
372 .WillOnce(Return(true));
373 Tpm tpm(&transceiver);
374 tpm.Startup(
375 TPM_SU_CLEAR, &authorization,
376 base::Bind(&CommandFlowTest::StartupCallback, base::Unretained(this)));
377 Run();
378 EXPECT_EQ(TPM_RC_FAILURE, response_code_);
379 }
380
381 // This test is designed to get good coverage of the different types of code
382 // generated for command / response processing. It covers:
383 // - input handles
384 // - authorization
385 // - multiple input and output parameters
386 // - parameter encryption and decryption
TEST_F(CommandFlowTest,FullCommandFlow)387 TEST_F(CommandFlowTest, FullCommandFlow) {
388 // A hand-rolled TPM2_Certify command.
389 std::string auth_in(10, 'A');
390 std::string auth_out(20, 'B');
391 std::string user_data(
392 "\x00\x0C"
393 "ct_user_data",
394 14);
395 std::string scheme("\x00\x10", 2); // scheme=TPM_ALG_NULL
396 std::string signed_data(
397 "\x00\x0E"
398 "ct_signed_data",
399 16);
400 std::string signature(
401 "\x00\x14" // sig_scheme=RSASSA
402 "\x00\x0B" // hash_scheme=SHA256
403 "\x00\x09" // signature size
404 "signature", // signature bytes
405 15);
406 std::string expected_command(
407 "\x80\x02" // tag=TPM_ST_SESSIONS
408 "\x00\x00\x00\x30" // size=48
409 "\x00\x00\x01\x48" // code=TPM_CC_Certify
410 "\x11\x22\x33\x44" // @objectHandle
411 "\x55\x66\x77\x88" // @signHandle
412 "\x00\x00\x00\x0A", // auth_size=10
413 22);
414 expected_command += auth_in + user_data + scheme;
415 std::string command_response(
416 "\x80\x02" // tag=TPM_ST_SESSIONS
417 "\x00\x00\x00\x41" // size=65
418 "\x00\x00\x00\x00" // code=TPM_RC_SUCCESS
419 "\x00\x00\x00\x1F", // param_size=31
420 14);
421 command_response += signed_data + signature + auth_out;
422
423 StrictMock<MockCommandTransceiver> transceiver;
424 EXPECT_CALL(transceiver, SendCommand(expected_command, _))
425 .WillOnce(WithArg<1>(Invoke(PostResponse(command_response))));
426 StrictMock<MockAuthorizationDelegate> authorization;
427 EXPECT_CALL(authorization, GetCommandAuthorization(_, _, _, _))
428 .WillOnce(DoAll(SetArgPointee<3>(auth_in), Return(true)));
429 EXPECT_CALL(authorization, CheckResponseAuthorization(_, auth_out))
430 .WillOnce(Return(true));
431 EXPECT_CALL(authorization, EncryptCommandParameter(_))
432 .WillOnce(Invoke(Encryptor("pt_user_data", "ct_user_data")));
433 EXPECT_CALL(authorization, DecryptResponseParameter(_))
434 .WillOnce(Invoke(Encryptor("ct_signed_data", "pt_signed_data")));
435
436 TPMT_SIG_SCHEME null_scheme;
437 null_scheme.scheme = TPM_ALG_NULL;
438 null_scheme.details.rsassa.hash_alg = TPM_ALG_SHA256;
439 Tpm tpm(&transceiver);
440 tpm.Certify(
441 0x11223344u, "object_handle", 0x55667788u, "sign_handle",
442 Make_TPM2B_DATA("pt_user_data"), null_scheme, &authorization,
443 base::Bind(&CommandFlowTest::CertifyCallback, base::Unretained(this)));
444 Run();
445 ASSERT_EQ(TPM_RC_SUCCESS, response_code_);
446 EXPECT_EQ("pt_signed_data", signed_data_);
447 EXPECT_EQ("signature", signature_);
448 }
449
450 } // namespace trunks
451