2
0

tpm-emu.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * Minimal TPM emulator for TPM test cases
  3. *
  4. * Copyright (c) 2018 Red Hat, Inc.
  5. *
  6. * Authors:
  7. * Marc-André Lureau <marcandre.lureau@redhat.com>
  8. *
  9. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  10. * See the COPYING file in the top-level directory.
  11. */
  12. #include "qemu/osdep.h"
  13. #include <glib/gstdio.h>
  14. #include "hw/tpm/tpm_ioctl.h"
  15. #include "io/channel-socket.h"
  16. #include "qapi/error.h"
  17. #include "tpm-emu.h"
  18. void tpm_emu_test_wait_cond(TestState *s)
  19. {
  20. gint64 end_time = g_get_monotonic_time() + 5 * G_TIME_SPAN_SECOND;
  21. g_mutex_lock(&s->data_mutex);
  22. if (!s->data_cond_signal &&
  23. !g_cond_wait_until(&s->data_cond, &s->data_mutex, end_time)) {
  24. g_assert_not_reached();
  25. }
  26. s->data_cond_signal = false;
  27. g_mutex_unlock(&s->data_mutex);
  28. }
  29. static void *tpm_emu_tpm_thread(void *data)
  30. {
  31. TestState *s = data;
  32. QIOChannel *ioc = s->tpm_ioc;
  33. s->tpm_msg = g_new(struct tpm_hdr, 1);
  34. while (true) {
  35. int minhlen = sizeof(s->tpm_msg->tag) + sizeof(s->tpm_msg->len);
  36. if (!qio_channel_read(ioc, (char *)s->tpm_msg, minhlen, &error_abort)) {
  37. break;
  38. }
  39. s->tpm_msg->tag = be16_to_cpu(s->tpm_msg->tag);
  40. s->tpm_msg->len = be32_to_cpu(s->tpm_msg->len);
  41. g_assert_cmpint(s->tpm_msg->len, >=, minhlen);
  42. g_assert_cmpint(s->tpm_msg->tag, ==, TPM2_ST_NO_SESSIONS);
  43. s->tpm_msg = g_realloc(s->tpm_msg, s->tpm_msg->len);
  44. qio_channel_read(ioc, (char *)&s->tpm_msg->code,
  45. s->tpm_msg->len - minhlen, &error_abort);
  46. s->tpm_msg->code = be32_to_cpu(s->tpm_msg->code);
  47. /* reply error */
  48. s->tpm_msg->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
  49. s->tpm_msg->len = cpu_to_be32(sizeof(struct tpm_hdr));
  50. s->tpm_msg->code = cpu_to_be32(TPM_RC_FAILURE);
  51. qio_channel_write(ioc, (char *)s->tpm_msg, be32_to_cpu(s->tpm_msg->len),
  52. &error_abort);
  53. }
  54. g_free(s->tpm_msg);
  55. s->tpm_msg = NULL;
  56. object_unref(OBJECT(s->tpm_ioc));
  57. return NULL;
  58. }
  59. void *tpm_emu_ctrl_thread(void *data)
  60. {
  61. TestState *s = data;
  62. QIOChannelSocket *lioc = qio_channel_socket_new();
  63. QIOChannel *ioc;
  64. qio_channel_socket_listen_sync(lioc, s->addr, 1, &error_abort);
  65. g_mutex_lock(&s->data_mutex);
  66. s->data_cond_signal = true;
  67. g_mutex_unlock(&s->data_mutex);
  68. g_cond_signal(&s->data_cond);
  69. qio_channel_wait(QIO_CHANNEL(lioc), G_IO_IN);
  70. ioc = QIO_CHANNEL(qio_channel_socket_accept(lioc, &error_abort));
  71. g_assert(ioc);
  72. {
  73. uint32_t cmd = 0;
  74. struct iovec iov = { .iov_base = &cmd, .iov_len = sizeof(cmd) };
  75. int *pfd = NULL;
  76. size_t nfd = 0;
  77. qio_channel_readv_full(ioc, &iov, 1, &pfd, &nfd, &error_abort);
  78. cmd = be32_to_cpu(cmd);
  79. g_assert_cmpint(cmd, ==, CMD_SET_DATAFD);
  80. g_assert_cmpint(nfd, ==, 1);
  81. s->tpm_ioc = QIO_CHANNEL(qio_channel_socket_new_fd(*pfd, &error_abort));
  82. g_free(pfd);
  83. cmd = 0;
  84. qio_channel_write(ioc, (char *)&cmd, sizeof(cmd), &error_abort);
  85. s->emu_tpm_thread = g_thread_new(NULL, tpm_emu_tpm_thread, s);
  86. }
  87. while (true) {
  88. uint32_t cmd;
  89. ssize_t ret;
  90. ret = qio_channel_read(ioc, (char *)&cmd, sizeof(cmd), NULL);
  91. if (ret <= 0) {
  92. break;
  93. }
  94. cmd = be32_to_cpu(cmd);
  95. switch (cmd) {
  96. case CMD_GET_CAPABILITY: {
  97. ptm_cap cap = cpu_to_be64(0x3fff);
  98. qio_channel_write(ioc, (char *)&cap, sizeof(cap), &error_abort);
  99. break;
  100. }
  101. case CMD_INIT: {
  102. ptm_init init;
  103. qio_channel_read(ioc, (char *)&init.u.req, sizeof(init.u.req),
  104. &error_abort);
  105. init.u.resp.tpm_result = 0;
  106. qio_channel_write(ioc, (char *)&init.u.resp, sizeof(init.u.resp),
  107. &error_abort);
  108. break;
  109. }
  110. case CMD_SHUTDOWN: {
  111. ptm_res res = 0;
  112. qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort);
  113. /* the tpm data thread is expected to finish now */
  114. g_thread_join(s->emu_tpm_thread);
  115. break;
  116. }
  117. case CMD_STOP: {
  118. ptm_res res = 0;
  119. qio_channel_write(ioc, (char *)&res, sizeof(res), &error_abort);
  120. break;
  121. }
  122. case CMD_SET_BUFFERSIZE: {
  123. ptm_setbuffersize sbs;
  124. qio_channel_read(ioc, (char *)&sbs.u.req, sizeof(sbs.u.req),
  125. &error_abort);
  126. sbs.u.resp.buffersize = sbs.u.req.buffersize ?: cpu_to_be32(4096);
  127. sbs.u.resp.tpm_result = 0;
  128. sbs.u.resp.minsize = cpu_to_be32(128);
  129. sbs.u.resp.maxsize = cpu_to_be32(4096);
  130. qio_channel_write(ioc, (char *)&sbs.u.resp, sizeof(sbs.u.resp),
  131. &error_abort);
  132. break;
  133. }
  134. case CMD_SET_LOCALITY: {
  135. ptm_loc loc;
  136. /* Note: this time it's not u.req / u.resp... */
  137. qio_channel_read(ioc, (char *)&loc, sizeof(loc), &error_abort);
  138. g_assert_cmpint(loc.u.req.loc, ==, 0);
  139. loc.u.resp.tpm_result = 0;
  140. qio_channel_write(ioc, (char *)&loc, sizeof(loc), &error_abort);
  141. break;
  142. }
  143. case CMD_GET_TPMESTABLISHED: {
  144. ptm_est est = {
  145. .u.resp.bit = 0,
  146. };
  147. qio_channel_write(ioc, (char *)&est, sizeof(est), &error_abort);
  148. break;
  149. }
  150. default:
  151. g_debug("unimplemented %u", cmd);
  152. g_assert_not_reached();
  153. }
  154. }
  155. object_unref(OBJECT(ioc));
  156. object_unref(OBJECT(lioc));
  157. return NULL;
  158. }