xref: /aosp_15_r20/external/tpm2-tss/test/unit/tcti-mssim.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************;
3  * Copyright (c) 2015 - 2018, Intel Corporation
4  * All rights reserved.
5  ***********************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <inttypes.h>
12 #include <limits.h>
13 #include <stdio.h>
14 #include <stdbool.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 #include <setjmp.h>
19 #include <cmocka.h>
20 
21 #include "tss2_tcti.h"
22 #include "tss2_tcti_mssim.h"
23 
24 #include "tss2-tcti/tcti-common.h"
25 #include "tss2-tcti/tcti-mssim.h"
26 #include "util/key-value-parse.h"
27 
28 /*
29  * This function is defined in the tcti-mssim module but not exposed through
30  * the header.
31  */
32 TSS2_RC
33 mssim_kv_callback (const key_value_t *key_value,
34                    void *user_data);
35 /*
36  * This tests our ability to handle conf strings that have a port
37  * component. In this case the 'conf_str_to_host_port' function
38  * should set the 'port' parameter and so we check to be sure it's
39  * set.
40  */
41 static void
conf_str_to_host_port_success_test(void ** state)42 conf_str_to_host_port_success_test (void **state)
43 {
44     TSS2_RC rc;
45     char conf[] = "host=127.0.0.1,port=2321";
46     mssim_conf_t mssim_conf = { 0 };
47 
48     rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
49     assert_int_equal (rc, TSS2_RC_SUCCESS);
50     assert_int_equal (mssim_conf.port, 2321);
51     assert_string_equal (mssim_conf.host, "127.0.0.1");
52 }
53 
54 /*
55  * This tests our ability to handle conf strings that don't have the port
56  * component of the URI. In this case the 'conf_str_to_host_port' function
57  * should not touch the 'port' parameter and so we check to be sure it's
58  * unchanged.
59  */
60 #define NO_PORT_VALUE 646
61 static void
conf_str_to_host_port_no_port_test(void ** state)62 conf_str_to_host_port_no_port_test (void **state)
63 {
64     TSS2_RC rc;
65     char conf[] = "host=127.0.0.1";
66     mssim_conf_t mssim_conf = {
67         .host = "foo",
68         .port = NO_PORT_VALUE,
69     };
70 
71     rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
72     assert_int_equal (rc, TSS2_RC_SUCCESS);
73     assert_string_equal (mssim_conf.host, "127.0.0.1");
74     assert_int_equal (mssim_conf.port, NO_PORT_VALUE);
75 }
76 
77 /*
78  * This tests our ability to handle conf strings that have an IPv6 address
79  * and port component. In this case the 'conf_str_to_host_port' function
80  * should set the 'hostname' parameter and so we check to be sure it's
81  * set without the [] brackets.
82  */
83 static void
conf_str_to_host_ipv6_port_success_test(void ** state)84 conf_str_to_host_ipv6_port_success_test (void **state)
85 {
86     TSS2_RC rc;
87     char conf[] = "host=::1,port=2321";
88     mssim_conf_t mssim_conf = { 0 };
89 
90     rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
91     assert_int_equal (rc, TSS2_RC_SUCCESS);
92     assert_int_equal (mssim_conf.port, 2321);
93     assert_string_equal (mssim_conf.host, "::1");
94 }
95 
96 /*
97  * This tests our ability to handle conf strings that have an IPv6 address
98  * but no port component. In this case the 'conf_str_to_host_port' function
99  * should not touch the 'port' parameter and so we check to be sure it's
100  * unchanged.
101  */
102 static void
conf_str_to_host_ipv6_port_no_port_test(void ** state)103 conf_str_to_host_ipv6_port_no_port_test (void **state)
104 {
105     TSS2_RC rc;
106     char conf[] = "host=::1";
107     mssim_conf_t mssim_conf = { .port = NO_PORT_VALUE };
108 
109     rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
110     assert_int_equal (rc, TSS2_RC_SUCCESS);
111     assert_int_equal (mssim_conf.port, NO_PORT_VALUE);
112     assert_string_equal (mssim_conf.host, "::1");
113 }
114 
115 /*
116  * The 'conf_str_to_host_port' function rejects ports over UINT16_MAX.
117  */
118 static void
conf_str_to_host_port_invalid_port_large_test(void ** state)119 conf_str_to_host_port_invalid_port_large_test (void **state)
120 {
121     TSS2_RC rc;
122     char conf[] = "host=127.0.0.1,port=99999";
123     mssim_conf_t mssim_conf = { 0 };
124 
125     rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
126     assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
127 }
128 /* The 'conf_str_to_host_port' function rejects URIs with port == 0 */
129 static void
conf_str_to_host_port_invalid_port_0_test(void ** state)130 conf_str_to_host_port_invalid_port_0_test (void **state)
131 {
132     TSS2_RC rc;
133     char conf[] = "host=127.0.0.1,port=0";
134     mssim_conf_t mssim_conf = { 0 };
135 
136     rc = parse_key_value_string (conf, mssim_kv_callback, &mssim_conf);
137     assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
138 }
139 
140 /* When passed all NULL values ensure that we get back the expected RC. */
141 static void
tcti_socket_init_all_null_test(void ** state)142 tcti_socket_init_all_null_test (void **state)
143 {
144     TSS2_RC rc;
145 
146     rc = Tss2_Tcti_Mssim_Init (NULL, NULL, NULL);
147     assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
148 }
149 /*
150  * Determine the size of a TCTI context structure. Requires calling the
151  * initialization function for the device TCTI with the first parameter
152  * (the TCTI context) NULL.
153  */
154 static void
tcti_socket_init_size_test(void ** state)155 tcti_socket_init_size_test (void **state)
156 {
157     size_t tcti_size = 0;
158     TSS2_RC ret = TSS2_RC_SUCCESS;
159 
160     ret = Tss2_Tcti_Mssim_Init (NULL, &tcti_size, NULL);
161     assert_int_equal (ret, TSS2_RC_SUCCESS);
162     assert_int_equal (tcti_size, sizeof (TSS2_TCTI_MSSIM_CONTEXT));
163 }
164 /*
165  * Wrap the 'connect' system call. The mock queue for this function must have
166  * an integer to return as a response.
167  */
168 int
__wrap_connect(int sockfd,const struct sockaddr * addr,socklen_t addrlen)169 __wrap_connect (int                    sockfd,
170                 const struct sockaddr *addr,
171                 socklen_t              addrlen)
172 {
173     return mock_type (int);
174 }
175 /*
176  * Wrap the 'recv' system call. The mock queue for this function must have an
177  * integer return value (the number of byts recv'd), as well as a pointer to
178  * a buffer to copy data from to return to the caller.
179  */
180 ssize_t
__wrap_read(int sockfd,void * buf,size_t len)181 __wrap_read (int sockfd,
182              void *buf,
183              size_t len)
184 {
185     ssize_t  ret = mock_type (ssize_t);
186     uint8_t *buf_in = mock_ptr_type (uint8_t*);
187 
188     memcpy (buf, buf_in, ret);
189     return ret;
190 }
191 /*
192  * Wrap the 'send' system call. The mock queue for this function must have an
193  * integer to return as a response.
194  */
195 ssize_t
__wrap_write(int sockfd,const void * buf,size_t len)196 __wrap_write (int sockfd,
197               const void *buf,
198               size_t len)
199 
200 {
201     return mock_type (TSS2_RC);
202 }
203 /*
204  * This is a utility function used by other tests to setup a TCTI context. It
205  * effectively wraps the init / allocate / init pattern as well as priming the
206  * mock functions necessary for a the successful call to
207  * 'Tss2_Tcti_Mssim_Init'.
208  */
209 static TSS2_TCTI_CONTEXT*
tcti_socket_init_from_conf(const char * conf)210 tcti_socket_init_from_conf (const char *conf)
211 {
212     size_t tcti_size = 0;
213     uint8_t recv_buf[4] = { 0 };
214     TSS2_RC ret = TSS2_RC_SUCCESS;
215     TSS2_TCTI_CONTEXT *ctx = NULL;
216 
217     printf ("%s: before first init\n", __func__);
218     ret = Tss2_Tcti_Mssim_Init (NULL, &tcti_size, NULL);
219     assert_true (ret == TSS2_RC_SUCCESS);
220     ctx = calloc (1, tcti_size);
221     assert_non_null (ctx);
222     /*
223      * two calls to connect, one for the data socket, one for the command
224      * socket
225      */
226     will_return (__wrap_connect, 0);
227     will_return (__wrap_connect, 0);
228     /*
229      * two 'platform commands are sent on initialization, 4 bytes sent for
230      * each, 4 byte response received (all 0's) for each.
231      */
232     will_return (__wrap_write, 4);
233     will_return (__wrap_read, 4);
234     will_return (__wrap_read, recv_buf);
235     will_return (__wrap_write, 4);
236     will_return (__wrap_read, 4);
237     will_return (__wrap_read, recv_buf);
238     printf ("%s: before second_init\n", __func__);
239     ret = Tss2_Tcti_Mssim_Init (ctx, &tcti_size, conf);
240     printf ("%s: after second init\n", __func__);
241     assert_int_equal (ret, TSS2_RC_SUCCESS);
242     return ctx;
243 }
244 
245 /*
246  * This is a utility function to setup the "default" TCTI context.
247  */
248 static int
tcti_socket_setup(void ** state)249 tcti_socket_setup (void **state)
250 {
251     printf ("%s: before tcti_socket_init_from_conf\n", __func__);
252     *state = tcti_socket_init_from_conf ("host=127.0.0.1,port=666");
253     printf ("%s: done\n", __func__);
254     return 0;
255 }
256 static void
tcti_socket_init_null_conf_test(void ** state)257 tcti_socket_init_null_conf_test (void **state)
258 {
259     TSS2_TCTI_CONTEXT *ctx = tcti_socket_init_from_conf (NULL);
260     assert_non_null (ctx);
261     free (ctx);
262 }
263 /*
264  * This is a utility function to teardown a TCTI context allocated by the
265  * tcti_socket_setup function.
266  */
267 static int
tcti_socket_teardown(void ** state)268 tcti_socket_teardown (void **state)
269 {
270     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
271 
272     Tss2_Tcti_Finalize (ctx);
273     free (ctx);
274     return 0;
275 }
276 /*
277  * This test ensures that the GetPollHandles function in the device TCTI
278  * returns the expected value. Since this TCTI does not support async I/O
279  * on account of limitations in the kernel it just returns the
280  * NOT_IMPLEMENTED response code.
281  */
282 static void
tcti_mssim_get_poll_handles_test(void ** state)283 tcti_mssim_get_poll_handles_test (void **state)
284 {
285     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
286     size_t num_handles = 5;
287     TSS2_TCTI_POLL_HANDLE handles [5] = { 0 };
288     TSS2_RC rc;
289 
290     rc = Tss2_Tcti_GetPollHandles (ctx, handles, &num_handles);
291     assert_int_equal (rc, TSS2_TCTI_RC_NOT_IMPLEMENTED);
292 }
293 /*
294  */
295 static void
tcti_socket_receive_null_size_test(void ** state)296 tcti_socket_receive_null_size_test (void **state)
297 {
298     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
299     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
300     TSS2_RC rc;
301 
302     /* Keep state machine check in `receive` from returning error. */
303     tcti_common->state = TCTI_STATE_RECEIVE;
304     rc = Tss2_Tcti_Receive (ctx,
305                             NULL, /* NULL 'size' parameter */
306                             NULL,
307                             TSS2_TCTI_TIMEOUT_BLOCK);
308     assert_int_equal (rc, TSS2_TCTI_RC_BAD_REFERENCE);
309     rc = Tss2_Tcti_Receive (ctx,
310                             NULL, /* NULL 'size' parameter */
311                             (uint8_t*)1, /* non-NULL buffer */
312                             TSS2_TCTI_TIMEOUT_BLOCK);
313     assert_int_equal (rc, TSS2_TCTI_RC_BAD_REFERENCE);
314 }
315 /*
316  * This test exercises the successful code path through the receive function.
317  */
318 static void
tcti_socket_receive_success_test(void ** state)319 tcti_socket_receive_success_test (void **state)
320 {
321     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
322     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
323     TSS2_RC rc = TSS2_RC_SUCCESS;
324     size_t response_size = 0xc;
325     uint8_t response_in [] = { 0x80, 0x02,
326                                0x00, 0x00, 0x00, 0x0c,
327                                0x00, 0x00, 0x00, 0x00,
328                                0x01, 0x02,
329     /* simulator appends 4 bytes of 0's to every response */
330                                0x00, 0x00, 0x00, 0x00 };
331     uint8_t response_out [12] = { 0 };
332 
333     /* Keep state machine check in `receive` from returning error. */
334     tcti_common->state = TCTI_STATE_RECEIVE;
335     /* receive response size */
336     will_return (__wrap_read, 4);
337     will_return (__wrap_read, &response_in [2]);
338     /* receive tag */
339     will_return (__wrap_read, 2);
340     will_return (__wrap_read, response_in);
341     /* receive size (again)  */
342     will_return (__wrap_read, 4);
343     will_return (__wrap_read, &response_in [2]);
344     /* receive the rest of the command */
345     will_return (__wrap_read, 0xc - sizeof (TPM2_ST) - sizeof (UINT32));
346     will_return (__wrap_read, &response_in [6]);
347     /* receive the 4 bytes of 0's appended by the simulator */
348     will_return (__wrap_read, 4);
349     will_return (__wrap_read, &response_in [12]);
350 
351     rc = Tss2_Tcti_Receive (ctx, &response_size, response_out, TSS2_TCTI_TIMEOUT_BLOCK);
352     assert_int_equal (rc, TSS2_RC_SUCCESS);
353     assert_memory_equal (response_in, response_out, response_size);
354 }
355 /*
356  */
357 static void
tcti_socket_receive_size_success_test(void ** state)358 tcti_socket_receive_size_success_test (void **state)
359 {
360     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
361     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
362     TSS2_RC rc = TSS2_RC_SUCCESS;
363     size_t response_size = 0;
364     uint8_t response_in [] = { 0x80, 0x02,
365                                0x00, 0x00, 0x00, 0x0c,
366                                0x00, 0x00, 0x00, 0x00,
367                                0x01, 0x02,
368     /* simulator appends 4 bytes of 0's to every response */
369                                0x00, 0x00, 0x00, 0x00 };
370     uint8_t response_out [12] = { 0 };
371 
372     /* Keep state machine check in `receive` from returning error. */
373     tcti_common->state = TCTI_STATE_RECEIVE;
374     /* receive response size */
375     will_return (__wrap_read, 4);
376     will_return (__wrap_read, &response_in [2]);
377     rc = Tss2_Tcti_Receive (ctx, &response_size, NULL, TSS2_TCTI_TIMEOUT_BLOCK);
378 
379     assert_int_equal (rc, TSS2_RC_SUCCESS);
380     assert_int_equal (response_size, 0xc);
381     /* receive tag */
382     will_return (__wrap_read, 2);
383     will_return (__wrap_read, response_in);
384     /* receive size (again)  */
385     will_return (__wrap_read, 4);
386     will_return (__wrap_read, &response_in [2]);
387     /* receive the rest of the command */
388     will_return (__wrap_read, 0xc - sizeof (TPM2_ST) - sizeof (UINT32));
389     will_return (__wrap_read, &response_in [6]);
390     /* receive the 4 bytes of 0's appended by the simulator */
391     will_return (__wrap_read, 4);
392     will_return (__wrap_read, &response_in [12]);
393 
394     rc = Tss2_Tcti_Receive (ctx, &response_size, response_out, TSS2_TCTI_TIMEOUT_BLOCK);
395     assert_int_equal (rc, TSS2_RC_SUCCESS);
396     assert_memory_equal (response_in, response_out, response_size);
397 }
398 /*
399  * This test causes the underlying 'read' call to return 0 / EOF when we
400  * call the TCTI 'receive' function. In this case the TCTI should return an
401  * IO error.
402  */
403 static void
tcti_mssim_receive_eof_first_read_test(void ** state)404 tcti_mssim_receive_eof_first_read_test (void **state)
405 {
406     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
407     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
408     TSS2_RC rc;
409     /* output buffer for response */
410     uint8_t buf [TPM_HEADER_SIZE] = { 0 };
411     size_t size = sizeof (buf);
412 
413     /* Keep state machine check in `receive` from returning error. */
414     tcti_common->state = TCTI_STATE_RECEIVE;
415     will_return (__wrap_read, 0);
416     will_return (__wrap_read, buf);
417     rc = Tss2_Tcti_Receive (ctx,
418                             &size,
419                             buf,
420                             TSS2_TCTI_TIMEOUT_BLOCK);
421     assert_true (rc == TSS2_TCTI_RC_IO_ERROR);
422 }
423 /*
424  * This test causes the underlying 'read' call to return EOF but only after
425  * a successful read that gets us the response size. This results in the
426  * an IO_ERROR RC being returned.
427  */
428 static void
tcti_mssim_receive_eof_second_read_test(void ** state)429 tcti_mssim_receive_eof_second_read_test (void **state)
430 {
431     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
432     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
433     TSS2_RC rc;
434     /* input response buffer */
435     uint8_t response_in [] = { 0x80, 0x02,
436                                0x00, 0x00, 0x00, 0x0c,
437                                0x00, 0x00, 0x00, 0x00,
438                                0x01, 0x02,
439     /* simulator appends 4 bytes of 0's to every response */
440                                0x00, 0x00, 0x00, 0x00 };
441     /* output response buffer */
442     uint8_t response_out [12] = { 0 };
443     size_t size = sizeof (response_out);
444 
445     /* Keep state machine check in `receive` from returning error. */
446     tcti_common->state = TCTI_STATE_RECEIVE;
447     /* setup response size for first read */
448     will_return (__wrap_read, 4);
449     will_return (__wrap_read, &response_in [2]);
450     /* setup 0 for EOF on second read */
451     will_return (__wrap_read, 0);
452     will_return (__wrap_read, response_in);
453     rc = Tss2_Tcti_Receive (ctx,
454                             &size,
455                             response_out,
456                             TSS2_TCTI_TIMEOUT_BLOCK);
457     assert_true (rc == TSS2_TCTI_RC_IO_ERROR);
458 }
459 /*
460  * This test exercises the successful code path through the transmit function.
461  */
462 static void
tcti_socket_transmit_success_test(void ** state)463 tcti_socket_transmit_success_test (void **state)
464 {
465     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
466     TSS2_RC rc = TSS2_RC_SUCCESS;
467     uint8_t command [] = { 0x80, 0x02,
468                            0x00, 0x00, 0x00, 0x0c,
469                            0x00, 0x00, 0x00, 0x00,
470                            0x01, 0x02 };
471     size_t  command_size = sizeof (command);
472 
473     /* send the TPM2_SEND_COMMAND code */
474     will_return (__wrap_write, 4);
475     /* send the locality for the command */
476     will_return (__wrap_write, 1);
477     /* send the number of bytes in command */
478     will_return (__wrap_write, 4);
479     /* send the command buffer */
480     will_return (__wrap_write, 0xc);
481     rc = Tss2_Tcti_Transmit (ctx, command_size, command);
482     assert_int_equal (rc, TSS2_RC_SUCCESS);
483 }
484 
485 int
main(int argc,char * argv[])486 main (int   argc,
487       char *argv[])
488 {
489     const struct CMUnitTest tests[] = {
490         cmocka_unit_test (conf_str_to_host_port_success_test),
491         cmocka_unit_test (conf_str_to_host_port_no_port_test),
492         cmocka_unit_test (conf_str_to_host_ipv6_port_success_test),
493         cmocka_unit_test (conf_str_to_host_ipv6_port_no_port_test),
494         cmocka_unit_test (conf_str_to_host_port_invalid_port_large_test),
495         cmocka_unit_test (conf_str_to_host_port_invalid_port_0_test),
496         cmocka_unit_test (tcti_socket_init_all_null_test),
497         cmocka_unit_test (tcti_socket_init_size_test),
498         cmocka_unit_test (tcti_socket_init_null_conf_test),
499         cmocka_unit_test_setup_teardown (tcti_mssim_get_poll_handles_test,
500                                          tcti_socket_setup,
501                                          tcti_socket_teardown),
502         cmocka_unit_test_setup_teardown (tcti_socket_receive_null_size_test,
503                                          tcti_socket_setup,
504                                          tcti_socket_teardown),
505         cmocka_unit_test_setup_teardown (tcti_socket_receive_success_test,
506                                   tcti_socket_setup,
507                                   tcti_socket_teardown),
508         cmocka_unit_test_setup_teardown (tcti_socket_receive_size_success_test,
509                                   tcti_socket_setup,
510                                   tcti_socket_teardown),
511         cmocka_unit_test_setup_teardown (tcti_mssim_receive_eof_first_read_test,
512                                          tcti_socket_setup,
513                                          tcti_socket_teardown),
514         cmocka_unit_test_setup_teardown (tcti_mssim_receive_eof_second_read_test,
515                                          tcti_socket_setup,
516                                          tcti_socket_teardown),
517         cmocka_unit_test_setup_teardown (tcti_socket_transmit_success_test,
518                                   tcti_socket_setup,
519                                   tcti_socket_teardown)
520     };
521     return cmocka_run_group_tests (tests, NULL, NULL);
522 }
523