xref: /aosp_15_r20/external/tpm2-tss/test/unit/tcti-device.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /***********************************************************************
3  * Copyright (c) 2017-2018, Intel Corporation
4  *
5  * All rights reserved.
6  ***********************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <inttypes.h>
12 #include <stdarg.h>
13 #include <stdbool.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <poll.h>
17 
18 #include <setjmp.h>
19 #include <cmocka.h>
20 
21 #include "tss2_mu.h"
22 #include "tss2_tcti_device.h"
23 
24 #include "tss2-tcti/tcti-common.h"
25 #include "tss2-tcti/tcti-device.h"
26 
27 /*
28  * Size of the TPM2 buffer used in these tests. In some cases this will be
29  * the command sent (transmit tests) and in others it's used as the response
30  * buffer returned by the TCTI. The only field used by the TCTI is the size
31  * field.
32  */
33 #define BUF_SIZE 20
34 static uint8_t tpm2_buf [BUF_SIZE] = {
35     0x80, 0x02, /* TAG */
36     0x00, 0x00, 0x00, 0x14, /* size (BUF_SIZE) */
37     0x00, 0x00, 0x00, 0x00, /* rc (success) */
38     0xde, 0xad, 0xbe, 0xef, /* junk data */
39     0xca, 0xfe, 0xba, 0xbe,
40     0xfe, 0xef
41 };
42 int
43 __real_open(const char *pathname, int flags, ...);
44 /* wrap function for open required to test init */
45 int
__wrap_open(const char * pathname,int flags,...)46 __wrap_open(const char *pathname, int flags, ...)
47 {
48     const char* pathname_prefix_dev = "/dev";
49     if (strncmp(pathname, pathname_prefix_dev, strlen(pathname_prefix_dev)) == 0) {
50         return mock_type (int);
51     } else {
52         /* only mock opening of device files as the open() syscall is needed
53            for code coverage reports as well */
54         return __real_open(pathname, flags);
55     }
56 }
57 /**
58  * When passed all NULL values ensure that we get back the expected RC
59  * indicating bad values.
60  */
61 static void
tcti_device_init_all_null_test(void ** state)62 tcti_device_init_all_null_test (void **state)
63 {
64     TSS2_RC rc;
65 
66     rc = Tss2_Tcti_Device_Init (NULL, NULL, NULL);
67     assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
68 }
69 /* Determine the size of a TCTI context structure. Requires calling the
70  * initialization function for the device TCTI with the first parameter
71  * (the TCTI context) NULL.
72  */
73 static void
tcti_device_init_size_test(void ** state)74 tcti_device_init_size_test (void **state)
75 {
76     size_t tcti_size = 0;
77     TSS2_RC ret = TSS2_RC_SUCCESS;
78 
79     ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
80     assert_int_equal (ret, TSS2_RC_SUCCESS);
81 }
82 /* Test the failure of opening a specified device file */
83 static void
tcti_device_init_conf_fail(void ** state)84 tcti_device_init_conf_fail (void **state)
85 {
86     size_t tcti_size = 0;
87     TSS2_RC ret = TSS2_RC_SUCCESS;
88     TSS2_TCTI_CONTEXT *ctx = NULL;
89 
90     ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
91     assert_true (ret == TSS2_RC_SUCCESS);
92     ctx = calloc (1, tcti_size);
93     assert_non_null (ctx);
94     errno = ENOENT; /* No such file or directory */
95     will_return (__wrap_open, -1);
96     ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, "/dev/nonexistent");
97     assert_true (ret == TSS2_TCTI_RC_IO_ERROR);
98 
99     free(ctx);
100 }
101 /* Test the device file recognition if no config string was specified */
102 static void
tcti_device_init_conf_default_fail(void ** state)103 tcti_device_init_conf_default_fail (void **state)
104 {
105     size_t tcti_size = 0;
106     TSS2_RC ret = TSS2_RC_SUCCESS;
107     TSS2_TCTI_CONTEXT *ctx = NULL;
108 
109     ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
110     assert_true (ret == TSS2_RC_SUCCESS);
111     ctx = calloc (1, tcti_size);
112     assert_non_null (ctx);
113     errno = EACCES; /* Permission denied */
114     will_return (__wrap_open, -1);
115     will_return (__wrap_open, -1);
116     ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, NULL);
117     assert_true (ret == TSS2_TCTI_RC_IO_ERROR);
118 
119     free(ctx);
120 }
121 /* Test the device file recognition if no config string was specified */
122 static void
tcti_device_init_conf_default_success(void ** state)123 tcti_device_init_conf_default_success (void **state)
124 {
125     size_t tcti_size = 0;
126     TSS2_RC ret = TSS2_RC_SUCCESS;
127     TSS2_TCTI_CONTEXT *ctx = NULL;
128 
129     ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
130     assert_true (ret == TSS2_RC_SUCCESS);
131     ctx = calloc (1, tcti_size);
132     assert_non_null (ctx);
133     will_return (__wrap_open, 3);
134     ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, NULL);
135     assert_true (ret == TSS2_RC_SUCCESS);
136 
137     free(ctx);
138 }
139 /* wrap functions for read & write required to test receive / transmit */
140 ssize_t
__wrap_read(int fd,void * buf,size_t count)141 __wrap_read (int fd, void *buf, size_t count)
142 {
143     ssize_t ret = mock_type (ssize_t);
144     uint8_t *buf_in = mock_type (uint8_t*);
145 
146     memcpy (buf, buf_in, ret);
147     return ret;
148 }
149 ssize_t
__wrap_write(int fd,const void * buffer,size_t buffer_size)150 __wrap_write (int fd, const void *buffer, size_t buffer_size)
151 {
152     ssize_t ret = mock_type (ssize_t);
153     uint8_t *buf_out = mock_type (uint8_t*);
154 
155     memcpy (buf_out, buffer, ret);
156     return ret;
157 }
158 
159 int
__wrap_poll(struct pollfd * fds,nfds_t nfds,int timeout)160 __wrap_poll (struct pollfd *fds, nfds_t nfds, int timeout)
161 {
162     int ret = mock_type (int);
163 
164     fds->revents = fds->events;
165     return ret;
166 }
167 
168 /* Setup functions to create the context for the device TCTI */
169 static int
tcti_device_setup(void ** state)170 tcti_device_setup (void **state)
171 {
172     size_t tcti_size = 0;
173     TSS2_RC ret = TSS2_RC_SUCCESS;
174     TSS2_TCTI_CONTEXT *ctx = NULL;
175 
176     ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
177     assert_true (ret == TSS2_RC_SUCCESS);
178     ctx = calloc (1, tcti_size);
179     assert_non_null (ctx);
180     will_return (__wrap_open, 3);
181     ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, "/dev/null");
182     assert_true (ret == TSS2_RC_SUCCESS);
183 
184     *state = ctx;
185     return 0;
186 }
187 
188 static int
tcti_device_teardown(void ** state)189 tcti_device_teardown (void **state)
190 {
191     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
192 
193     Tss2_Tcti_Finalize (ctx);
194     free (ctx);
195 
196     return 0;
197 
198 }
199 /*
200  * This test ensures that the GetPollHandles function in the device TCTI
201  * returns the expected value. Since this TCTI does not support async I/O
202  * on account of limitations in the kernel it just returns the
203  * NOT_IMPLEMENTED response code.
204  */
205 static void
tcti_device_get_poll_handles_test(void ** state)206 tcti_device_get_poll_handles_test (void **state)
207 {
208     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
209     size_t num_handles = 5;
210     TSS2_TCTI_POLL_HANDLE handles [5] = { 0 };
211     TSS2_RC rc;
212 
213     rc = Tss2_Tcti_GetPollHandles (ctx, handles, &num_handles);
214 #ifdef TCTI_ASYNC
215     assert_int_equal (rc, TSS2_RC_SUCCESS);
216     assert_int_equal (num_handles, 1);
217 #else
218     assert_int_equal (rc, TSS2_TCTI_RC_NOT_IMPLEMENTED);
219 #endif
220 }
221 /*
222  */
223 static void
tcti_device_receive_null_size_test(void ** state)224 tcti_device_receive_null_size_test (void **state)
225 {
226     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
227     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
228     TSS2_RC rc;
229 
230     /* Keep state machine check in `receive` from returning error. */
231     tcti_common->state = TCTI_STATE_RECEIVE;
232     rc = Tss2_Tcti_Receive (ctx,
233                             NULL, /* NULL 'size' parameter */
234                             NULL,
235                             TSS2_TCTI_TIMEOUT_BLOCK);
236     assert_int_equal (rc, TSS2_TCTI_RC_BAD_REFERENCE);
237     rc = Tss2_Tcti_Receive (ctx,
238                             NULL, /* NULL 'size' parameter */
239                             (uint8_t*)1, /* non-NULL buffer */
240                             TSS2_TCTI_TIMEOUT_BLOCK);
241     assert_int_equal (rc, TSS2_TCTI_RC_BAD_REFERENCE);
242 }
243 /*
244  * A test case for a successful call to the receive function. This requires
245  * that the context and the command buffer be valid (including the size
246  * field being set appropriately). The result should be an RC indicating
247  * success and the size parameter be updated to reflect the size of the
248  * data received.
249  */
250 static void
tcti_device_receive_success(void ** state)251 tcti_device_receive_success (void **state)
252 {
253     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
254     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
255     TSS2_RC rc;
256     /* output buffer for response */
257     uint8_t buf_out [BUF_SIZE + 5] = { 0 };
258     size_t size = BUF_SIZE + 5;
259 
260     /* Keep state machine check in `receive` from returning error. */
261     tcti_common->state = TCTI_STATE_RECEIVE;
262     will_return (__wrap_poll, 1);
263     will_return (__wrap_read, BUF_SIZE);
264     will_return (__wrap_read, tpm2_buf);
265     rc = Tss2_Tcti_Receive (ctx,
266                             &size,
267                             buf_out,
268                             TSS2_TCTI_TIMEOUT_BLOCK);
269     assert_true (rc == TSS2_RC_SUCCESS);
270     assert_int_equal (BUF_SIZE, size);
271     assert_memory_equal (tpm2_buf, buf_out, size);
272 }
273 /*
274  * Ensure that when the 'read' results in an EOF, we get a response code
275  * indicating as much. EOF happens if / when the device driver kills our
276  * connection.
277  */
278 static void
tcti_device_receive_eof_test(void ** state)279 tcti_device_receive_eof_test (void **state)
280 {
281     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
282     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
283     TSS2_RC rc;
284     /* output buffer for response */
285     uint8_t buf_out [BUF_SIZE + 5] = { 0 };
286     size_t size = BUF_SIZE + 5;
287 
288     /* Keep state machine check in `receive` from returning error. */
289     tcti_common->state = TCTI_STATE_RECEIVE;
290     will_return (__wrap_poll, 1);
291     will_return (__wrap_read, 0);
292     will_return (__wrap_read, tpm2_buf);
293     rc = Tss2_Tcti_Receive (ctx,
294                             &size,
295                             buf_out,
296                             TSS2_TCTI_TIMEOUT_BLOCK);
297     assert_int_equal (rc, TSS2_TCTI_RC_NO_CONNECTION);
298 }
299 /*
300  * This is a weird test: The device TCTI can't read the header for the
301  * response buffer separately from the body. This means it can't know the size
302  * of the response before reading the whole thing. In the event that the caller
303  * provides a buffer that isn't large enough to hold the full response the TCTI
304  * will just read as much data as the buffer will hold. Subsequent interactions
305  * with the kernel driver will likely result in an error.
306  */
307 static void
tcti_device_receive_buffer_lt_response(void ** state)308 tcti_device_receive_buffer_lt_response (void **state)
309 {
310     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
311     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
312     TSS2_RC rc;
313     uint8_t buf_out [BUF_SIZE] = { 0 };
314     /* set size to lt the size in the header of the TPM2 response buffer */
315     size_t size = BUF_SIZE - 1;
316 
317     /* Keep state machine check in `receive` from returning error. */
318     tcti_common->state = TCTI_STATE_RECEIVE;
319     will_return (__wrap_poll, 1);
320     will_return (__wrap_read, size);
321     will_return (__wrap_read, tpm2_buf);
322     rc = Tss2_Tcti_Receive (ctx,
323                             &size,
324                             buf_out,
325                             TSS2_TCTI_TIMEOUT_BLOCK);
326     assert_int_equal (rc, TSS2_TCTI_RC_GENERAL_FAILURE);
327 }
328 /*
329  * A test case for a successful call to the transmit function. This requires
330  * that the context and the cmmand buffer be valid. The only indication of
331  * success is the RC.
332  */
333 static void
tcti_device_transmit_success(void ** state)334 tcti_device_transmit_success (void **state)
335 {
336     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
337     TSS2_RC rc;
338     /* output buffer for response */
339     uint8_t buf_out [BUF_SIZE] = { 0 };
340 
341     will_return (__wrap_write, BUF_SIZE);
342     will_return (__wrap_write, buf_out);
343     rc = Tss2_Tcti_Transmit (ctx,
344                              BUF_SIZE,
345                              tpm2_buf);
346     assert_true (rc == TSS2_RC_SUCCESS);
347     assert_memory_equal (tpm2_buf, buf_out, BUF_SIZE);
348 }
349 /*
350  * A test case for a successful poll
351  */
352 static void
tcti_device_poll_success(void ** state)353 tcti_device_poll_success (void **state)
354 {
355     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
356     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
357     TSS2_RC rc;
358     /* output buffer for response */
359     uint8_t buf_out [BUF_SIZE] = { 0 };
360     size_t size = BUF_SIZE;
361 
362     /* Keep state machine check in `receive` from returning error. */
363     tcti_common->state = TCTI_STATE_RECEIVE;
364     will_return (__wrap_poll, 1);
365     will_return (__wrap_read, BUF_SIZE);
366     will_return (__wrap_read, tpm2_buf);
367 
368     rc = Tss2_Tcti_Receive (ctx,
369                             &size,
370                             buf_out,
371                             TSS2_TCTI_TIMEOUT_BLOCK);
372 
373     assert_true (rc == TSS2_RC_SUCCESS);
374     assert_int_equal (BUF_SIZE, size);
375     assert_memory_equal (tpm2_buf, buf_out, size);
376 }
377 /*
378  * A test case for poll timeout
379  */
380 static void
tcti_device_poll_timeout(void ** state)381 tcti_device_poll_timeout (void **state)
382 {
383     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
384     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
385     TSS2_RC rc;
386     /* output buffer for response */
387     uint8_t buf_out [BUF_SIZE] = { 0 };
388     size_t size = BUF_SIZE;
389 
390     /* Keep state machine check in `receive` from returning error. */
391     tcti_common->state = TCTI_STATE_RECEIVE;
392     will_return (__wrap_poll, 0);
393 
394     rc = Tss2_Tcti_Receive (ctx,
395                             &size,
396                             buf_out,
397                             TSS2_TCTI_TIMEOUT_BLOCK);
398 
399     assert_true (rc == TSS2_TCTI_RC_TRY_AGAIN);
400 }
401 /*
402  * A test case for poll io-error
403  */
404 static void
tcti_device_poll_io_error(void ** state)405 tcti_device_poll_io_error (void **state)
406 {
407     TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
408     TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
409     TSS2_RC rc;
410     /* output buffer for response */
411     uint8_t buf_out [BUF_SIZE] = { 0 };
412     size_t size = BUF_SIZE;
413 
414     /* Keep state machine check in `receive` from returning error. */
415     tcti_common->state = TCTI_STATE_RECEIVE;
416     will_return (__wrap_poll, -1);
417 
418     rc = Tss2_Tcti_Receive (ctx,
419                             &size,
420                             buf_out,
421                             TSS2_TCTI_TIMEOUT_BLOCK);
422 
423     assert_true (rc == TSS2_TCTI_RC_IO_ERROR);
424 }
425 
426 int
main(int argc,char * argv[])427 main(int argc, char* argv[])
428 {
429     const struct CMUnitTest tests[] = {
430         cmocka_unit_test (tcti_device_init_all_null_test),
431         cmocka_unit_test(tcti_device_init_size_test),
432         cmocka_unit_test(tcti_device_init_conf_fail),
433         cmocka_unit_test(tcti_device_init_conf_default_fail),
434         cmocka_unit_test(tcti_device_init_conf_default_success),
435         cmocka_unit_test_setup_teardown (tcti_device_get_poll_handles_test,
436                                          tcti_device_setup,
437                                          tcti_device_teardown),
438         cmocka_unit_test_setup_teardown (tcti_device_receive_null_size_test,
439                                          tcti_device_setup,
440                                          tcti_device_teardown),
441         cmocka_unit_test_setup_teardown (tcti_device_receive_success,
442                                          tcti_device_setup,
443                                          tcti_device_teardown),
444         cmocka_unit_test_setup_teardown (tcti_device_receive_eof_test,
445                                          tcti_device_setup,
446                                          tcti_device_teardown),
447         cmocka_unit_test_setup_teardown (tcti_device_receive_buffer_lt_response,
448                                          tcti_device_setup,
449                                          tcti_device_teardown),
450         cmocka_unit_test_setup_teardown (tcti_device_transmit_success,
451                                          tcti_device_setup,
452                                          tcti_device_teardown),
453         cmocka_unit_test_setup_teardown (tcti_device_poll_success,
454                                          tcti_device_setup,
455                                          tcti_device_teardown),
456         cmocka_unit_test_setup_teardown (tcti_device_poll_timeout,
457                                          tcti_device_setup,
458                                          tcti_device_teardown),
459         cmocka_unit_test_setup_teardown (tcti_device_poll_io_error,
460                                          tcti_device_setup,
461                                          tcti_device_teardown),
462     };
463     return cmocka_run_group_tests (tests, NULL, NULL);
464 }
465