1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2017, Intel Corporation
4  * All rights reserved.
5  */
6 #include <glib.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 
10 #include <setjmp.h>
11 #include <cmocka.h>
12 
13 #include "tpm2-header.h"
14 #include "tpm2-response.h"
15 #include "util.h"
16 
17 #define HANDLE_TEST 0xdeadbeef
18 #define HANDLE_TYPE 0xde
19 
20 typedef struct {
21     Tpm2Response *response;
22     guint8       *buffer;
23     size_t        buffer_size;
24     Connection   *connection;
25 } test_data_t;
26 /*
27  * This function does all of the setup required to run a test *except*
28  * for instantiating the Tpm2Response object.
29  */
30 static int
tpm2_response_setup_base(void ** state)31 tpm2_response_setup_base (void **state)
32 {
33     test_data_t *data   = NULL;
34     gint         client_fd;
35     HandleMap   *handle_map;
36     GIOStream   *iostream;
37 
38     data = calloc (1, sizeof (test_data_t));
39     /* allocate a buffer large enough to hold a TPM2 header and a handle */
40     data->buffer_size = TPM_RESPONSE_HEADER_SIZE + sizeof (TPM2_HANDLE);
41     data->buffer   = calloc (1, data->buffer_size);
42     handle_map = handle_map_new (TPM2_HT_TRANSIENT, MAX_ENTRIES_DEFAULT);
43     iostream = create_connection_iostream (&client_fd);
44     data->connection  = connection_new (iostream, 0, handle_map);
45     g_object_unref (handle_map);
46     g_object_unref (iostream);
47 
48     *state = data;
49     return 0;
50 }
51 /*
52  * This function sets up all required test data with a Tpm2Response
53  * object that has no attributes set.
54  */
55 static int
tpm2_response_setup(void ** state)56 tpm2_response_setup (void **state)
57 {
58     test_data_t *data;
59 
60     tpm2_response_setup_base (state);
61     data = (test_data_t*)*state;
62     data->response = tpm2_response_new (data->connection,
63                                         data->buffer,
64                                         data->buffer_size,
65                                         (TPMA_CC){ 0, });
66     return 0;
67 }
68 /*
69  * This function sets up all required test data with a Tpm2Response
70  * object that has attributes indicating the response has a handle
71  * in it.
72  */
73 static int
tpm2_response_setup_with_handle(void ** state)74 tpm2_response_setup_with_handle (void **state)
75 {
76     test_data_t *data;
77     TPMA_CC attributes = 1 << 28;
78 
79     tpm2_response_setup_base (state);
80     data = (test_data_t*)*state;
81     data->buffer_size = TPM_RESPONSE_HEADER_SIZE + sizeof (TPM2_HANDLE);
82     data->response = tpm2_response_new (data->connection,
83                                         data->buffer,
84                                         data->buffer_size,
85                                         attributes);
86     set_response_size (data->buffer, data->buffer_size);
87     data->buffer [TPM_RESPONSE_HEADER_SIZE]     = 0xde;
88     data->buffer [TPM_RESPONSE_HEADER_SIZE + 1] = 0xad;
89     data->buffer [TPM_RESPONSE_HEADER_SIZE + 2] = 0xbe;
90     data->buffer [TPM_RESPONSE_HEADER_SIZE + 3] = 0xef;
91     return 0;
92 }
93 /**
94  * Tear down all of the data from the setup function. We don't have to
95  * free the data buffer (data->buffer) since the Tpm2Response frees it as
96  * part of its finalize function.
97  */
98 static int
tpm2_response_teardown(void ** state)99 tpm2_response_teardown (void **state)
100 {
101     test_data_t *data = (test_data_t*)*state;
102 
103     g_object_unref (data->connection);
104     g_object_unref (data->response);
105     free (data);
106     return 0;
107 }
108 /**
109  * Here we check to be sure that the object instantiated in the setup
110  * function is actually the type that we expect. This is a test to be sure
111  * the type is registered properly with the type system.
112  */
113 static void
tpm2_response_type_test(void ** state)114 tpm2_response_type_test (void **state)
115 {
116     test_data_t *data = (test_data_t*)*state;
117 
118     assert_true (G_IS_OBJECT (data->response));
119     assert_true (IS_TPM2_RESPONSE (data->response));
120 }
121 /**
122  * In the setup function we save a reference to the Connection object
123  * instantiated as well as passing it into the Tpm2Response object. Here we
124  * check to be sure that the Connection object returned by the Tpm2Response
125  * object is the same one that we passed it.
126  */
127 static void
tpm2_response_get_connection_test(void ** state)128 tpm2_response_get_connection_test (void **state)
129 {
130     test_data_t *data = (test_data_t*)*state;
131     Connection *connection;
132 
133     connection = tpm2_response_get_connection (data->response);
134     assert_int_equal (data->connection, connection);
135     g_object_unref (connection);
136 }
137 /**
138  * In the setup function we passed the Tpm2Response object a data buffer.
139  * Here we check to be sure it passes the same one back to us when we ask
140  * for it.
141  */
142 static void
tpm2_response_get_buffer_test(void ** state)143 tpm2_response_get_buffer_test (void **state)
144 {
145     test_data_t *data = (test_data_t*)*state;
146 
147     assert_int_equal (data->buffer, tpm2_response_get_buffer (data->response));
148 }
149 /**
150  * Here we retrieve the data buffer from the Tpm2Response and manually set
151  * the tag part of the response buffer to TPM2_ST_SESSIONS in network byte
152  * order (aka big endian). We then use the tpm2_response_get_tag function
153  * to retrieve this data and we compare it to TPM2_ST_SESSIONS to be sure we
154  * got the value in host byte order.
155  */
156 static void
tpm2_response_get_tag_test(void ** state)157 tpm2_response_get_tag_test (void **state)
158 {
159     test_data_t  *data   = (test_data_t*)*state;
160     guint8       *buffer = tpm2_response_get_buffer (data->response);
161     TPM2_ST        tag_ret;
162 
163     /* this is TPM2_ST_SESSIONS in network byte order */
164     buffer[0] = 0x80;
165     buffer[1] = 0x02;
166 
167     tag_ret = tpm2_response_get_tag (data->response);
168     assert_int_equal (tag_ret, TPM2_ST_SESSIONS);
169 }
170 /**
171  * Again we're getting the response buffer from the Tpm2Response object
172  * but this time we're setting the additional size field (uint32) to 0x6
173  * in big endian format. We then use the tpm2_response_get_size function
174  * to get this value back and we compare it to 0x6 to be sure it's returned
175  * in host byte order.
176  */
177 static void
tpm2_response_get_size_test(void ** state)178 tpm2_response_get_size_test (void **state)
179 {
180     test_data_t *data     = (test_data_t*)*state;
181     guint8      *buffer   = tpm2_response_get_buffer (data->response);
182     guint32      size_ret = 0;
183 
184     /* this is TPM2_ST_SESSIONS in network byte order */
185     buffer[0] = 0x80;
186     buffer[1] = 0x02;
187     buffer[2] = 0x00;
188     buffer[3] = 0x00;
189     buffer[4] = 0x00;
190     buffer[5] = 0x06;
191 
192     size_ret = tpm2_response_get_size (data->response);
193     assert_int_equal (0x6, size_ret);
194 }
195 /**
196  * Again we're getting the response buffer from the Tpm2Response object
197  * but this time we're setting the additional response code field (TPM_RC)
198  * to a known value in big endian format. We then use tpm2_response_get_code
199  * to retrieve the RC and compare it to the appropriate constant to be sure
200  * it's sent back to us in host byte order.
201  */
202 static void
tpm2_response_get_code_test(void ** state)203 tpm2_response_get_code_test (void **state)
204 {
205     test_data_t *data     = (test_data_t*)*state;
206     guint8      *buffer   = tpm2_response_get_buffer (data->response);
207     TPM2_CC       response_code;
208 
209     /**
210      * This is TPM2_ST_SESSIONS + a size of 0x0a + the response code for
211      * GetCapability in network byte order
212      */
213     buffer[0] = 0x80;
214     buffer[1] = 0x02;
215     buffer[2] = 0x00;
216     buffer[3] = 0x00;
217     buffer[4] = 0x00;
218     buffer[5] = 0x0a;
219     buffer[6] = 0x00;
220     buffer[7] = 0x00;
221     buffer[8] = 0x01;
222     buffer[9] = 0x00;
223 
224     response_code = tpm2_response_get_code (data->response);
225     assert_int_equal (response_code, TPM2_RC_INITIALIZE);
226 }
227 /**
228  * This is a setup function for testing the "short-cut" constructor for the
229  * Tpm2Response object that creates the response buffer with the provided RC.
230  */
231 static int
tpm2_response_new_rc_setup(void ** state)232 tpm2_response_new_rc_setup (void **state)
233 {
234     test_data_t *data   = NULL;
235     gint         client_fd;
236     GIOStream   *iostream;
237     HandleMap   *handle_map;
238 
239     data = calloc (1, sizeof (test_data_t));
240     /* allocate a buffer large enough to hold a TPM2 header */
241     handle_map = handle_map_new (TPM2_HT_TRANSIENT, MAX_ENTRIES_DEFAULT);
242     iostream = create_connection_iostream (&client_fd);
243     data->connection  = connection_new (iostream, 0, handle_map);
244     g_object_unref (handle_map);
245     g_object_unref (iostream);
246     data->response = tpm2_response_new_rc (data->connection, TPM2_RC_BINDING);
247 
248     *state = data;
249     return 0;
250 }
251 /**
252  * The tpm2_response_new_rc sets the TPM2_ST_NO_SESSIONS tag for us since
253  * it's just returning an RC and cannot have connections. Here we check to be
254  * sure we can retrieve this tag and that's it's returned in host byte order.
255  */
256 static void
tpm2_response_new_rc_tag_test(void ** state)257 tpm2_response_new_rc_tag_test (void **state)
258 {
259     test_data_t *data = (test_data_t*)*state;
260     TPM2_ST       tag  = 0;
261 
262     tag = tpm2_response_get_tag (data->response);
263     assert_int_equal (tag, TPM2_ST_NO_SESSIONS);
264 }
265 /**
266  * The tpm2_response_new_rc sets the size to the appropriate
267  * TPM_RESPONSE_HEADER size (which is 10 bytes) for us since the response
268  * buffer is just a header. Here we check to be sure that we get this value
269  * back in the proper host byte order.
270  */
271 static void
tpm2_response_new_rc_size_test(void ** state)272 tpm2_response_new_rc_size_test (void **state)
273 {
274     test_data_t *data = (test_data_t*)*state;
275     guint32      size = 0;
276 
277     size = tpm2_response_get_size (data->response);
278     assert_int_equal (size, TPM_RESPONSE_HEADER_SIZE);
279 }
280 /**
281  * The tpm2_response_new_rc sets the response code to whatever RC is passed
282  * as a parameter. In the paired setup function we passed it TPM2_RC_BINDING.
283  * This function ensures that we get the same value back from the
284  * tpm2_response_get_code function in the proper host byte order.
285  */
286 static void
tpm2_response_new_rc_code_test(void ** state)287 tpm2_response_new_rc_code_test (void **state)
288 {
289     test_data_t *data = (test_data_t*)*state;
290     TSS2_RC       rc   = TPM2_RC_SUCCESS;
291 
292     rc = tpm2_response_get_code (data->response);
293     assert_int_equal (rc, TPM2_RC_BINDING);
294 }
295 /**
296  * The tpm2_response_new_rc takes a connection as a parameter. We save a
297  * reference to this in the test_data_t structure. Here we ensure that the
298  * tpm2_response_get_connection function returns the same connection to us.
299  */
300 static void
tpm2_response_new_rc_connection_test(void ** state)301 tpm2_response_new_rc_connection_test (void **state)
302 {
303     test_data_t *data = (test_data_t*)*state;
304     Connection *connection = data->connection;
305 
306     assert_int_equal (connection, tpm2_response_get_connection (data->response));
307 }
308 /*
309  * This test ensures that a tpm2_response_has_handle reports the
310  * actual value in the TPMA_CC attributes field when the rHandle bit
311  * in the attributes is *not* set.
312  */
313 static void
tpm2_response_no_handle_test(void ** state)314 tpm2_response_no_handle_test (void **state)
315 {
316     test_data_t *data = (test_data_t*)*state;
317     gboolean has_handle;
318 
319     has_handle = tpm2_response_has_handle (data->response);
320     assert_false (has_handle);
321 }
322 /*
323  * This test ensures that a tpm2_response_has_handle reports the
324  * actual value in the TPMA_CC attributes field when the rHandle bit
325  * in the attributes *is* set.
326  */
327 static void
tpm2_response_has_handle_test(void ** state)328 tpm2_response_has_handle_test (void **state)
329 {
330     test_data_t *data = (test_data_t*)*state;
331     gboolean has_handle = FALSE;
332 
333     has_handle = tpm2_response_has_handle (data->response);
334     assert_true (has_handle);
335 }
336 /*
337  * This tests the Tpm2Response objects ability to return the handle that
338  * we set in the setup function.
339  */
340 static void
tpm2_response_get_handle_test(void ** state)341 tpm2_response_get_handle_test (void **state)
342 {
343     test_data_t *data = (test_data_t*)*state;
344     TPM2_HANDLE handle;
345 
346     handle = tpm2_response_get_handle (data->response);
347     assert_int_equal (handle, HANDLE_TEST);
348 }
349 /*
350  * This tests the Tpm2Response object's ability detect an attempt to read
351  * beyond the end of its internal buffer. We fake this by changing the
352  * buffer_size field manually and then trying to access the handle.
353  */
354 static void
tpm2_response_get_handle_no_handle_test(void ** state)355 tpm2_response_get_handle_no_handle_test (void **state)
356 {
357     test_data_t *data = (test_data_t*)*state;
358     TPM2_HANDLE handle;
359 
360     data->response->buffer_size = TPM_HEADER_SIZE;
361     handle = tpm2_response_get_handle (data->response);
362     assert_int_equal (handle, 0);
363 }
364 /*
365  * This tests the Tpm2Response objects ability to return the handle type
366  * from the handle we set in the setup function.
367  */
368 static void
tpm2_response_get_handle_type_test(void ** state)369 tpm2_response_get_handle_type_test (void **state)
370 {
371     test_data_t *data = (test_data_t*)*state;
372     TPM2_HT handle_type;
373 
374     handle_type = tpm2_response_get_handle_type (data->response);
375     assert_int_equal (handle_type, HANDLE_TYPE);
376 }
377 /*
378  * This tests the Tpm2Response objects ability to set the response handle
379  * field. We do this by first setting the handle to some value and then
380  * querying the Tpm2Response object for the handle. The value returned
381  * should be the handle that we set in the previous call.
382  */
383 static void
tpm2_response_set_handle_test(void ** state)384 tpm2_response_set_handle_test (void **state)
385 {
386     test_data_t *data = (test_data_t*)*state;
387     TPM2_HANDLE handle_in = 0x80fffffe, handle_out = 0;
388 
389     tpm2_response_set_handle (data->response, handle_in);
390     handle_out = tpm2_response_get_handle (data->response);
391 
392     assert_int_equal (handle_in, handle_out);
393 }
394 /*
395  * This tests the Tpm2Response object's ability detect an attempt to write
396  * beyond the end of its internal buffer. We fake this by changing the
397  * buffer_size field manually and then trying to set the handle.
398  */
399 static void
tpm2_response_set_handle_no_handle_test(void ** state)400 tpm2_response_set_handle_no_handle_test (void **state)
401 {
402     test_data_t *data = (test_data_t*)*state;
403     TPM2_HANDLE handle_in = 0x80fffffe, handle_out = 0;
404 
405     data->response->buffer_size = TPM_HEADER_SIZE;
406     tpm2_response_set_handle (data->response, handle_in);
407     handle_out = tpm2_response_get_handle (data->response);
408 
409     assert_int_equal (handle_out, 0);
410 }
411 gint
main(void)412 main (void)
413 {
414     const struct CMUnitTest tests[] = {
415         cmocka_unit_test_setup_teardown (tpm2_response_type_test,
416                                          tpm2_response_setup,
417                                          tpm2_response_teardown),
418         cmocka_unit_test_setup_teardown (tpm2_response_get_connection_test,
419                                          tpm2_response_setup,
420                                          tpm2_response_teardown),
421         cmocka_unit_test_setup_teardown (tpm2_response_get_buffer_test,
422                                          tpm2_response_setup,
423                                          tpm2_response_teardown),
424         cmocka_unit_test_setup_teardown (tpm2_response_get_tag_test,
425                                          tpm2_response_setup,
426                                          tpm2_response_teardown),
427         cmocka_unit_test_setup_teardown (tpm2_response_get_size_test,
428                                          tpm2_response_setup,
429                                          tpm2_response_teardown),
430         cmocka_unit_test_setup_teardown (tpm2_response_get_code_test,
431                                          tpm2_response_setup,
432                                          tpm2_response_teardown),
433         cmocka_unit_test_setup_teardown (tpm2_response_new_rc_tag_test,
434                                          tpm2_response_new_rc_setup,
435                                          tpm2_response_teardown),
436         cmocka_unit_test_setup_teardown (tpm2_response_new_rc_size_test,
437                                          tpm2_response_new_rc_setup,
438                                          tpm2_response_teardown),
439         cmocka_unit_test_setup_teardown (tpm2_response_new_rc_code_test,
440                                          tpm2_response_new_rc_setup,
441                                          tpm2_response_teardown),
442         cmocka_unit_test_setup_teardown (tpm2_response_new_rc_connection_test,
443                                          tpm2_response_new_rc_setup,
444                                          tpm2_response_teardown),
445         cmocka_unit_test_setup_teardown (tpm2_response_no_handle_test,
446                                          tpm2_response_setup,
447                                          tpm2_response_teardown),
448         cmocka_unit_test_setup_teardown (tpm2_response_has_handle_test,
449                                          tpm2_response_setup_with_handle,
450                                          tpm2_response_teardown),
451         cmocka_unit_test_setup_teardown (tpm2_response_get_handle_test,
452                                          tpm2_response_setup_with_handle,
453                                          tpm2_response_teardown),
454         cmocka_unit_test_setup_teardown (tpm2_response_get_handle_no_handle_test,
455                                          tpm2_response_setup_with_handle,
456                                          tpm2_response_teardown),
457         cmocka_unit_test_setup_teardown (tpm2_response_get_handle_type_test,
458                                          tpm2_response_setup_with_handle,
459                                          tpm2_response_teardown),
460         cmocka_unit_test_setup_teardown (tpm2_response_set_handle_test,
461                                          tpm2_response_setup_with_handle,
462                                          tpm2_response_teardown),
463         cmocka_unit_test_setup_teardown (tpm2_response_set_handle_no_handle_test,
464                                          tpm2_response_setup_with_handle,
465                                          tpm2_response_teardown),
466     };
467     return cmocka_run_group_tests (tests, NULL, NULL);
468 }
469