123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- /* SPDX-License-Identifier: BSD-2-Clause */
- /***********************************************************************
- * Copyright (c) 2017-2018, Intel Corporation
- *
- * All rights reserved.
- ***********************************************************************/
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <inttypes.h>
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <string.h>
- #include <poll.h>
- #include <setjmp.h>
- #include <cmocka.h>
- #include "tss2_mu.h"
- #include "tss2_tcti_device.h"
- #include "tss2-tcti/tcti-common.h"
- #include "tss2-tcti/tcti-device.h"
- /*
- * Size of the TPM2 buffer used in these tests. In some cases this will be
- * the command sent (transmit tests) and in others it's used as the response
- * buffer returned by the TCTI. The only field used by the TCTI is the size
- * field.
- */
- #define BUF_SIZE 20
- static uint8_t tpm2_buf [BUF_SIZE] = {
- 0x80, 0x02, /* TAG */
- 0x00, 0x00, 0x00, 0x14, /* size (BUF_SIZE) */
- 0x00, 0x00, 0x00, 0x00, /* rc (success) */
- 0xde, 0xad, 0xbe, 0xef, /* junk data */
- 0xca, 0xfe, 0xba, 0xbe,
- 0xfe, 0xef
- };
- int
- __real_open(const char *pathname, int flags, ...);
- /* wrap function for open required to test init */
- int
- __wrap_open(const char *pathname, int flags, ...)
- {
- const char* pathname_prefix_dev = "/dev";
- if (strncmp(pathname, pathname_prefix_dev, strlen(pathname_prefix_dev)) == 0) {
- return mock_type (int);
- } else {
- /* only mock opening of device files as the open() syscall is needed
- for code coverage reports as well */
- return __real_open(pathname, flags);
- }
- }
- /**
- * When passed all NULL values ensure that we get back the expected RC
- * indicating bad values.
- */
- static void
- tcti_device_init_all_null_test (void **state)
- {
- TSS2_RC rc;
- rc = Tss2_Tcti_Device_Init (NULL, NULL, NULL);
- assert_int_equal (rc, TSS2_TCTI_RC_BAD_VALUE);
- }
- /* Determine the size of a TCTI context structure. Requires calling the
- * initialization function for the device TCTI with the first parameter
- * (the TCTI context) NULL.
- */
- static void
- tcti_device_init_size_test (void **state)
- {
- size_t tcti_size = 0;
- TSS2_RC ret = TSS2_RC_SUCCESS;
- ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
- assert_int_equal (ret, TSS2_RC_SUCCESS);
- }
- /* Test the failure of opening a specified device file */
- static void
- tcti_device_init_conf_fail (void **state)
- {
- size_t tcti_size = 0;
- TSS2_RC ret = TSS2_RC_SUCCESS;
- TSS2_TCTI_CONTEXT *ctx = NULL;
- ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
- assert_true (ret == TSS2_RC_SUCCESS);
- ctx = calloc (1, tcti_size);
- assert_non_null (ctx);
- errno = ENOENT; /* No such file or directory */
- will_return (__wrap_open, -1);
- ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, "/dev/nonexistent");
- assert_true (ret == TSS2_TCTI_RC_IO_ERROR);
- free(ctx);
- }
- /* Test the device file recognition if no config string was specified */
- static void
- tcti_device_init_conf_default_fail (void **state)
- {
- size_t tcti_size = 0;
- TSS2_RC ret = TSS2_RC_SUCCESS;
- TSS2_TCTI_CONTEXT *ctx = NULL;
- ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
- assert_true (ret == TSS2_RC_SUCCESS);
- ctx = calloc (1, tcti_size);
- assert_non_null (ctx);
- errno = EACCES; /* Permission denied */
- will_return (__wrap_open, -1);
- will_return (__wrap_open, -1);
- ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, NULL);
- assert_true (ret == TSS2_TCTI_RC_IO_ERROR);
- free(ctx);
- }
- /* Test the device file recognition if no config string was specified */
- static void
- tcti_device_init_conf_default_success (void **state)
- {
- size_t tcti_size = 0;
- TSS2_RC ret = TSS2_RC_SUCCESS;
- TSS2_TCTI_CONTEXT *ctx = NULL;
- ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
- assert_true (ret == TSS2_RC_SUCCESS);
- ctx = calloc (1, tcti_size);
- assert_non_null (ctx);
- will_return (__wrap_open, 3);
- will_return (__wrap_write, 12);
- will_return (__wrap_write, tpm2_buf);
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, 10);
- will_return (__wrap_read, tpm2_buf);
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, 8);
- will_return (__wrap_read, tpm2_buf);
- ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, NULL);
- assert_true (ret == TSS2_RC_SUCCESS);
- free(ctx);
- }
- /* wrap functions for read & write required to test receive / transmit */
- ssize_t
- __wrap_read (int fd, void *buf, size_t count)
- {
- ssize_t ret = mock_type (ssize_t);
- uint8_t *buf_in = mock_type (uint8_t*);
- memcpy (buf, buf_in, ret);
- return ret;
- }
- ssize_t
- __wrap_write (int fd, const void *buffer, size_t buffer_size)
- {
- ssize_t ret = mock_type (ssize_t);
- uint8_t *buf_out = mock_type (uint8_t*);
- memcpy (buf_out, buffer, ret);
- return ret;
- }
- int
- __wrap_poll (struct pollfd *fds, nfds_t nfds, int timeout)
- {
- int ret = mock_type (int);
- fds->revents = fds->events;
- return ret;
- }
- /* Setup functions to create the context for the device TCTI */
- static int
- tcti_device_setup (void **state)
- {
- size_t tcti_size = 0;
- TSS2_RC ret = TSS2_RC_SUCCESS;
- TSS2_TCTI_CONTEXT *ctx = NULL;
- ret = Tss2_Tcti_Device_Init (NULL, &tcti_size, NULL);
- assert_true (ret == TSS2_RC_SUCCESS);
- ctx = calloc (1, tcti_size);
- assert_non_null (ctx);
- will_return (__wrap_open, 3);
- will_return (__wrap_write, 12);
- will_return (__wrap_write, tpm2_buf);
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, 10);
- will_return (__wrap_read, tpm2_buf);
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, 0);
- will_return (__wrap_read, tpm2_buf);
- will_return (__wrap_open, 3);
- ret = Tss2_Tcti_Device_Init (ctx, &tcti_size, "/dev/null");
- assert_true (ret == TSS2_RC_SUCCESS);
- *state = ctx;
- return 0;
- }
- static int
- tcti_device_teardown (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- Tss2_Tcti_Finalize (ctx);
- free (ctx);
- return 0;
- }
- /*
- * This test ensures that the GetPollHandles function in the device TCTI
- * returns the expected value. Since this TCTI does not support async I/O
- * on account of limitations in the kernel it just returns the
- * NOT_IMPLEMENTED response code.
- */
- static void
- tcti_device_get_poll_handles_test (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- size_t num_handles = 5;
- TSS2_TCTI_POLL_HANDLE handles [5] = { 0 };
- TSS2_RC rc;
- rc = Tss2_Tcti_GetPollHandles (ctx, handles, &num_handles);
- assert_int_equal (rc, TSS2_RC_SUCCESS);
- assert_int_equal (num_handles, 1);
- }
- /*
- */
- static void
- tcti_device_receive_null_size_test (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- rc = Tss2_Tcti_Receive (ctx,
- NULL, /* NULL 'size' parameter */
- NULL,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_int_equal (rc, TSS2_TCTI_RC_BAD_REFERENCE);
- rc = Tss2_Tcti_Receive (ctx,
- NULL, /* NULL 'size' parameter */
- (uint8_t*)1, /* non-NULL buffer */
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_int_equal (rc, TSS2_TCTI_RC_BAD_REFERENCE);
- }
- /*
- * A test case for a successful call to the receive function. This requires
- * that the context and the command buffer be valid (including the size
- * field being set appropriately). The result should be an RC indicating
- * success and the size parameter be updated to reflect the size of the
- * data received.
- */
- static void
- tcti_device_receive_success (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- /* output buffer for response */
- uint8_t buf_out [BUF_SIZE + 5] = { 0 };
- size_t size = BUF_SIZE + 5;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, BUF_SIZE);
- will_return (__wrap_read, tpm2_buf);
- rc = Tss2_Tcti_Receive (ctx,
- &size,
- buf_out,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_true (rc == TSS2_RC_SUCCESS);
- assert_int_equal (BUF_SIZE, size);
- assert_memory_equal (tpm2_buf, buf_out, size);
- }
- /*
- * Ensure that when the 'read' results in an EOF, we get a response code
- * indicating as much. EOF happens if / when the device driver kills our
- * connection.
- */
- static void
- tcti_device_receive_eof_test (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- /* output buffer for response */
- uint8_t buf_out [BUF_SIZE + 5] = { 0 };
- size_t size = BUF_SIZE + 5;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, 0);
- will_return (__wrap_read, tpm2_buf);
- rc = Tss2_Tcti_Receive (ctx,
- &size,
- buf_out,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_int_equal (rc, TSS2_TCTI_RC_NO_CONNECTION);
- }
- /*
- * This is a weird test: The device TCTI can't read the header for the
- * response buffer separately from the body. This means it can't know the size
- * of the response before reading the whole thing. In the event that the caller
- * provides a buffer that isn't large enough to hold the full response the TCTI
- * will just read as much data as the buffer will hold. Subsequent interactions
- * with the kernel driver will likely result in an error.
- */
- static void
- tcti_device_receive_buffer_lt_response (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- uint8_t buf_out [BUF_SIZE] = { 0 };
- /* set size to lt the size in the header of the TPM2 response buffer */
- size_t size = BUF_SIZE - 1;
- size_t small_size = TPM_HEADER_SIZE + 1;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, size);
- will_return (__wrap_read, tpm2_buf);
- rc = Tss2_Tcti_Receive (ctx,
- &small_size,
- buf_out,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_int_equal (rc, TSS2_TCTI_RC_GENERAL_FAILURE);
- }
- /*
- * A test case for a successful call to the transmit function. This requires
- * that the context and the cmmand buffer be valid. The only indication of
- * success is the RC.
- */
- static void
- tcti_device_transmit_success (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_RC rc;
- /* output buffer for response */
- uint8_t buf_out [BUF_SIZE] = { 0 };
- will_return (__wrap_write, BUF_SIZE);
- will_return (__wrap_write, buf_out);
- rc = Tss2_Tcti_Transmit (ctx,
- BUF_SIZE,
- tpm2_buf);
- assert_true (rc == TSS2_RC_SUCCESS);
- assert_memory_equal (tpm2_buf, buf_out, BUF_SIZE);
- }
- /*
- * A test case for a successful poll
- */
- static void
- tcti_device_poll_success (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- /* output buffer for response */
- uint8_t buf_out [BUF_SIZE] = { 0 };
- size_t size = BUF_SIZE;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- will_return (__wrap_poll, 1);
- will_return (__wrap_read, BUF_SIZE);
- will_return (__wrap_read, tpm2_buf);
- rc = Tss2_Tcti_Receive (ctx,
- &size,
- buf_out,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_true (rc == TSS2_RC_SUCCESS);
- assert_int_equal (BUF_SIZE, size);
- assert_memory_equal (tpm2_buf, buf_out, size);
- }
- /*
- * A test case for poll timeout
- */
- static void
- tcti_device_poll_timeout (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- /* output buffer for response */
- uint8_t buf_out [BUF_SIZE] = { 0 };
- size_t size = BUF_SIZE;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- will_return (__wrap_poll, 0);
- rc = Tss2_Tcti_Receive (ctx,
- &size,
- buf_out,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_true (rc == TSS2_TCTI_RC_TRY_AGAIN);
- }
- /*
- * A test case for poll io-error
- */
- static void
- tcti_device_poll_io_error (void **state)
- {
- TSS2_TCTI_CONTEXT *ctx = (TSS2_TCTI_CONTEXT*)*state;
- TSS2_TCTI_COMMON_CONTEXT *tcti_common = tcti_common_context_cast (ctx);
- TSS2_RC rc;
- /* output buffer for response */
- uint8_t buf_out [BUF_SIZE] = { 0 };
- size_t size = BUF_SIZE;
- /* Keep state machine check in `receive` from returning error. */
- tcti_common->state = TCTI_STATE_RECEIVE;
- will_return (__wrap_poll, -1);
- rc = Tss2_Tcti_Receive (ctx,
- &size,
- buf_out,
- TSS2_TCTI_TIMEOUT_BLOCK);
- assert_true (rc == TSS2_TCTI_RC_IO_ERROR);
- }
- int
- main(int argc, char* argv[])
- {
- const struct CMUnitTest tests[] = {
- cmocka_unit_test (tcti_device_init_all_null_test),
- cmocka_unit_test(tcti_device_init_size_test),
- cmocka_unit_test(tcti_device_init_conf_fail),
- cmocka_unit_test(tcti_device_init_conf_default_fail),
- cmocka_unit_test(tcti_device_init_conf_default_success),
- cmocka_unit_test_setup_teardown (tcti_device_get_poll_handles_test,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_receive_null_size_test,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_receive_success,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_receive_eof_test,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_receive_buffer_lt_response,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_transmit_success,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_poll_success,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_poll_timeout,
- tcti_device_setup,
- tcti_device_teardown),
- cmocka_unit_test_setup_teardown (tcti_device_poll_io_error,
- tcti_device_setup,
- tcti_device_teardown),
- };
- return cmocka_run_group_tests (tests, NULL, NULL);
- }
|