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