main-esys.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /* SPDX-License-Identifier: BSD-2-Clause */
  2. /*******************************************************************************
  3. * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
  4. * All rights reserved.
  5. *******************************************************************************/
  6. #ifdef HAVE_CONFIG_H
  7. #include <config.h>
  8. #endif
  9. #include <stdbool.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include "tss2_esys.h"
  13. #include "test-esys.h"
  14. #include "test-options.h"
  15. #include "context-util.h"
  16. #include "tss2-esys/esys_int.h"
  17. #define LOGMODULE test
  18. #include "util/log.h"
  19. /** Define a proxy tcti that returns yielded on every second invocation
  20. * thus the corresponding handling code in ESYS can be tested.
  21. * The first invocation will be Tss2_Sys_StartUp.
  22. */
  23. TSS2_RC
  24. (*transmit_hook) (const uint8_t *command_buffer, size_t command_size) = NULL;
  25. #define TCTI_PROXY_MAGIC 0x5250584f0a000000ULL /* 'PROXY\0\0\0' */
  26. #define TCTI_PROXY_VERSION 0x1
  27. enum state {
  28. forwarding,
  29. intercepting
  30. };
  31. typedef struct {
  32. uint64_t magic;
  33. uint32_t version;
  34. TSS2_TCTI_TRANSMIT_FCN transmit;
  35. TSS2_TCTI_RECEIVE_FCN receive;
  36. TSS2_RC (*finalize) (TSS2_TCTI_CONTEXT *tctiContext);
  37. TSS2_RC (*cancel) (TSS2_TCTI_CONTEXT *tctiContext);
  38. TSS2_RC (*getPollHandles) (TSS2_TCTI_CONTEXT *tctiContext,
  39. TSS2_TCTI_POLL_HANDLE *handles, size_t *num_handles);
  40. TSS2_RC (*setLocality) (TSS2_TCTI_CONTEXT *tctiContext, uint8_t locality);
  41. TSS2_TCTI_CONTEXT *tctiInner;
  42. enum state state;
  43. } TSS2_TCTI_CONTEXT_PROXY;
  44. static TSS2_TCTI_CONTEXT_PROXY*
  45. tcti_proxy_cast (TSS2_TCTI_CONTEXT *ctx)
  46. {
  47. TSS2_TCTI_CONTEXT_PROXY *ctxi = (TSS2_TCTI_CONTEXT_PROXY*)ctx;
  48. if (ctxi == NULL || ctxi->magic != TCTI_PROXY_MAGIC) {
  49. LOG_ERROR("Bad tcti passed.");
  50. return NULL;
  51. }
  52. return ctxi;
  53. }
  54. static TSS2_RC
  55. tcti_proxy_transmit(
  56. TSS2_TCTI_CONTEXT *tctiContext,
  57. size_t command_size,
  58. const uint8_t *command_buffer
  59. )
  60. {
  61. TSS2_RC rval;
  62. TSS2_TCTI_CONTEXT_PROXY *tcti_proxy = tcti_proxy_cast(tctiContext);
  63. if (tcti_proxy->state == intercepting) {
  64. return TSS2_RC_SUCCESS;
  65. }
  66. if (transmit_hook != NULL) {
  67. rval = transmit_hook(command_buffer, command_size);
  68. if (rval != TSS2_RC_SUCCESS) {
  69. LOG_ERROR("transmit hook requested error");
  70. return rval;
  71. }
  72. }
  73. rval = Tss2_Tcti_Transmit(tcti_proxy->tctiInner, command_size,
  74. command_buffer);
  75. if (rval != TSS2_RC_SUCCESS) {
  76. LOG_ERROR("Calling TCTI Transmit");
  77. return rval;
  78. }
  79. return rval;
  80. }
  81. uint8_t yielded_response[] = {
  82. 0x80, 0x01, /* TPM_ST_NO_SESSION */
  83. 0x00, 0x00, 0x00, 0x0A, /* Response Size 10 */
  84. 0x00, 0x00, 0x09, 0x08 /* TPM_RC_YIELDED */
  85. };
  86. static TSS2_RC
  87. tcti_proxy_receive(
  88. TSS2_TCTI_CONTEXT *tctiContext,
  89. size_t *response_size,
  90. uint8_t *response_buffer,
  91. int32_t timeout
  92. )
  93. {
  94. TSS2_RC rval;
  95. TSS2_TCTI_CONTEXT_PROXY *tcti_proxy = tcti_proxy_cast(tctiContext);
  96. if (tcti_proxy->state == intercepting) {
  97. *response_size = sizeof(yielded_response);
  98. if (response_buffer != NULL) {
  99. memcpy(response_buffer, &yielded_response[0], sizeof(yielded_response));
  100. tcti_proxy->state = forwarding;
  101. }
  102. return TSS2_RC_SUCCESS;
  103. }
  104. rval = Tss2_Tcti_Receive(tcti_proxy->tctiInner, response_size,
  105. response_buffer, timeout);
  106. if (rval != TSS2_RC_SUCCESS) {
  107. LOG_ERROR("Calling TCTI Transmit");
  108. return rval;
  109. }
  110. /* First read with response buffer == NULL is to get the size of the
  111. * response. The subsequent read needs to be forwarded also */
  112. if (response_buffer != NULL)
  113. tcti_proxy->state = intercepting;
  114. return rval;
  115. }
  116. static void
  117. tcti_proxy_finalize(
  118. TSS2_TCTI_CONTEXT *tctiContext)
  119. {
  120. memset(tctiContext, 0, sizeof(TSS2_TCTI_CONTEXT_PROXY));
  121. }
  122. static TSS2_RC
  123. tcti_proxy_initialize(
  124. TSS2_TCTI_CONTEXT *tctiContext,
  125. size_t *contextSize,
  126. TSS2_TCTI_CONTEXT *tctiInner)
  127. {
  128. TSS2_TCTI_CONTEXT_PROXY *tcti_proxy =
  129. (TSS2_TCTI_CONTEXT_PROXY*) tctiContext;
  130. if (tctiContext == NULL && contextSize == NULL) {
  131. return TSS2_TCTI_RC_BAD_VALUE;
  132. } else if (tctiContext == NULL) {
  133. *contextSize = sizeof(*tcti_proxy);
  134. return TSS2_RC_SUCCESS;
  135. }
  136. /* Init TCTI context */
  137. memset(tcti_proxy, 0, sizeof(*tcti_proxy));
  138. TSS2_TCTI_MAGIC (tctiContext) = TCTI_PROXY_MAGIC;
  139. TSS2_TCTI_VERSION (tctiContext) = TCTI_PROXY_VERSION;
  140. TSS2_TCTI_TRANSMIT (tctiContext) = tcti_proxy_transmit;
  141. TSS2_TCTI_RECEIVE (tctiContext) = tcti_proxy_receive;
  142. TSS2_TCTI_FINALIZE (tctiContext) = tcti_proxy_finalize;
  143. TSS2_TCTI_CANCEL (tctiContext) = NULL;
  144. TSS2_TCTI_GET_POLL_HANDLES (tctiContext) = NULL;
  145. TSS2_TCTI_SET_LOCALITY (tctiContext) = NULL;
  146. tcti_proxy->tctiInner = tctiInner;
  147. tcti_proxy->state = forwarding;
  148. return TSS2_RC_SUCCESS;
  149. }
  150. /**
  151. * This program is a template for integration tests (ones that use the TCTI
  152. * and the ESYS contexts / API directly). It does nothing more than parsing
  153. * command line options that allow the caller (likely a script) to specify
  154. * which TCTI to use for the test.
  155. */
  156. int
  157. main(int argc, char *argv[])
  158. {
  159. TSS2_RC rc;
  160. size_t tcti_size;
  161. TSS2_TCTI_CONTEXT *tcti_context;
  162. TSS2_TCTI_CONTEXT *tcti_inner;
  163. ESYS_CONTEXT *esys_context;
  164. TSS2_ABI_VERSION abiVersion =
  165. { TSSWG_INTEROP, TSS_SAPI_FIRST_FAMILY, TSS_SAPI_FIRST_LEVEL,
  166. TSS_SAPI_FIRST_VERSION };
  167. int ret;
  168. test_opts_t opts = {
  169. .tcti_type = TCTI_DEFAULT,
  170. .device_file = DEVICE_PATH_DEFAULT,
  171. .socket_address = HOSTNAME_DEFAULT,
  172. .socket_port = PORT_DEFAULT,
  173. };
  174. get_test_opts_from_env(&opts);
  175. if (sanity_check_test_opts(&opts) != 0) {
  176. LOG_ERROR("TPM Startup FAILED! Error in sanity check");
  177. exit(1);
  178. }
  179. tcti_inner = tcti_init_from_opts(&opts);
  180. if (tcti_inner == NULL) {
  181. LOG_ERROR("TPM Startup FAILED! Error tcti init");
  182. exit(1);
  183. }
  184. rc = tcti_proxy_initialize(NULL, &tcti_size, tcti_inner);
  185. if (rc != TSS2_RC_SUCCESS) {
  186. LOG_ERROR("tcti initialization FAILED! Response Code : 0x%x", rc);
  187. return 1;
  188. }
  189. tcti_context = calloc(1, tcti_size);
  190. if (tcti_inner == NULL) {
  191. LOG_ERROR("TPM Startup FAILED! Error tcti init");
  192. exit(1);
  193. }
  194. rc = tcti_proxy_initialize(tcti_context, &tcti_size, tcti_inner);
  195. if (rc != TSS2_RC_SUCCESS) {
  196. LOG_ERROR("tcti initialization FAILED! Response Code : 0x%x", rc);
  197. return 1;
  198. }
  199. rc = Esys_Initialize(&esys_context, tcti_context, &abiVersion);
  200. if (rc != TSS2_RC_SUCCESS) {
  201. LOG_ERROR("Esys_Initialize FAILED! Response Code : 0x%x", rc);
  202. return 1;
  203. }
  204. rc = Esys_Startup(esys_context, TPM2_SU_CLEAR);
  205. if (rc != TSS2_RC_SUCCESS && rc != TPM2_RC_INITIALIZE) {
  206. LOG_ERROR("Esys_Startup FAILED! Response Code : 0x%x", rc);
  207. return 1;
  208. }
  209. rc = Esys_SetTimeout(esys_context, TSS2_TCTI_TIMEOUT_BLOCK);
  210. if (rc != TSS2_RC_SUCCESS) {
  211. LOG_ERROR("Esys_SetTimeout FAILED! Response Code : 0x%x", rc);
  212. return 1;
  213. }
  214. ret = test_invoke_esys(esys_context);
  215. Esys_Finalize(&esys_context);
  216. tcti_teardown(tcti_inner);
  217. tcti_teardown(tcti_context);
  218. return ret;
  219. }