tpm_lite_stub.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * Stub implementations of utility functions which call their linux-specific
  6. * equivalents.
  7. */
  8. #include <stdint.h>
  9. #include "2sysincludes.h"
  10. #include "2common.h"
  11. #include "tlcl.h"
  12. #include "tlcl_internal.h"
  13. #include "utility.h"
  14. #include "vboot_api.h"
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <stdarg.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <sys/time.h>
  22. #include <sys/types.h>
  23. #include <sys/stat.h>
  24. #include <time.h>
  25. #include <unistd.h>
  26. #define TPM_DEVICE_PATH "/dev/tpm0"
  27. /* Retry failed open()s for 5 seconds in 10ms polling intervals. */
  28. #define OPEN_RETRY_DELAY_NS (10 * 1000 * 1000)
  29. #define OPEN_RETRY_MAX_NUM 500
  30. /* TODO: these functions should pass errors back rather than returning void */
  31. /* TODO: if the only callers to these are just wrappers, should just
  32. * remove the wrappers and call us directly. */
  33. /* The file descriptor for the TPM device.
  34. */
  35. static int tpm_fd = -1;
  36. /* If the library should exit during an OS-level TPM failure.
  37. */
  38. static int exit_on_failure = 1;
  39. /* Similar to VbExError, only handle the non-exit case.
  40. */
  41. static VbError_t DoError(VbError_t result, const char* format, ...)
  42. {
  43. va_list ap;
  44. va_start(ap, format);
  45. fprintf(stderr, "ERROR: ");
  46. vfprintf(stderr, format, ap);
  47. va_end(ap);
  48. if (exit_on_failure)
  49. exit(1);
  50. return result;
  51. }
  52. /* Print |n| bytes from array |a| to stderr, with newlines.
  53. */
  54. __attribute__((unused)) static void DbgPrintBytes(const uint8_t* a, int n)
  55. {
  56. int i;
  57. fprintf(stderr, "DEBUG: ");
  58. for (i = 0; i < n; i++) {
  59. if (i && i % 16 == 0)
  60. fprintf(stderr, "\nDEBUG: ");
  61. fprintf(stderr, "%02x ", a[i]);
  62. }
  63. fprintf(stderr, "\n");
  64. }
  65. /* Executes a command on the TPM.
  66. */
  67. static VbError_t TpmExecute(const uint8_t *in, const uint32_t in_len,
  68. uint8_t *out, uint32_t *pout_len)
  69. {
  70. uint8_t response[TPM_MAX_COMMAND_SIZE];
  71. if (in_len <= 0) {
  72. return DoError(TPM_E_INPUT_TOO_SMALL,
  73. "invalid command length %d for command 0x%x\n",
  74. in_len, in[9]);
  75. } else if (tpm_fd < 0) {
  76. return DoError(TPM_E_NO_DEVICE,
  77. "the TPM device was not opened. " \
  78. "Forgot to call TlclLibInit?\n");
  79. } else {
  80. int n = write(tpm_fd, in, in_len);
  81. if (n != in_len) {
  82. return DoError(TPM_E_WRITE_FAILURE,
  83. "write failure to TPM device: %s\n",
  84. strerror(errno));
  85. }
  86. n = read(tpm_fd, response, sizeof(response));
  87. if (n == 0) {
  88. return DoError(TPM_E_READ_EMPTY,
  89. "null read from TPM device\n");
  90. } else if (n < 0) {
  91. return DoError(TPM_E_READ_FAILURE,
  92. "read failure from TPM device: %s\n",
  93. strerror(errno));
  94. } else {
  95. if (n > *pout_len) {
  96. return DoError(TPM_E_RESPONSE_TOO_LARGE,
  97. "TPM response too long for "
  98. "output buffer\n");
  99. } else {
  100. *pout_len = n;
  101. memcpy(out, response, n);
  102. }
  103. }
  104. }
  105. return VBERROR_SUCCESS;
  106. }
  107. /* Gets the tag field of a TPM command.
  108. */
  109. __attribute__((unused))
  110. static inline int TpmTag(const uint8_t* buffer)
  111. {
  112. uint16_t tag;
  113. FromTpmUint16(buffer, &tag);
  114. return (int) tag;
  115. }
  116. /* Gets the size field of a TPM command.
  117. */
  118. __attribute__((unused))
  119. static inline int TpmResponseSize(const uint8_t* buffer)
  120. {
  121. uint32_t size;
  122. FromTpmUint32(buffer + sizeof(uint16_t), &size);
  123. return (int) size;
  124. }
  125. VbError_t VbExTpmInit(void)
  126. {
  127. char *no_exit = getenv("TPM_NO_EXIT");
  128. if (no_exit)
  129. exit_on_failure = !atoi(no_exit);
  130. return VbExTpmOpen();
  131. }
  132. VbError_t VbExTpmClose(void)
  133. {
  134. if (tpm_fd != -1) {
  135. close(tpm_fd);
  136. tpm_fd = -1;
  137. }
  138. return VBERROR_SUCCESS;
  139. }
  140. VbError_t VbExTpmOpen(void)
  141. {
  142. char* device_path;
  143. struct timespec delay;
  144. int retries, saved_errno;
  145. if (tpm_fd >= 0)
  146. return VBERROR_SUCCESS; /* Already open */
  147. device_path = getenv("TPM_DEVICE_PATH");
  148. if (device_path == NULL) {
  149. device_path = TPM_DEVICE_PATH;
  150. }
  151. /* Retry TPM opens on EBUSY failures. */
  152. for (retries = 0; retries < OPEN_RETRY_MAX_NUM; ++ retries) {
  153. errno = 0;
  154. tpm_fd = open(device_path, O_RDWR);
  155. saved_errno = errno;
  156. if (tpm_fd >= 0)
  157. return VBERROR_SUCCESS;
  158. if (saved_errno != EBUSY)
  159. break;
  160. VB2_DEBUG("TPM: retrying %s: %s\n",
  161. device_path, strerror(errno));
  162. /* Stall until TPM comes back. */
  163. delay.tv_sec = 0;
  164. delay.tv_nsec = OPEN_RETRY_DELAY_NS;
  165. nanosleep(&delay, NULL);
  166. }
  167. return DoError(TPM_E_NO_DEVICE, "TPM: Cannot open TPM device %s: %s\n",
  168. device_path, strerror(saved_errno));
  169. }
  170. VbError_t VbExTpmSendReceive(const uint8_t* request, uint32_t request_length,
  171. uint8_t* response, uint32_t* response_length)
  172. {
  173. /*
  174. * In a real firmware implementation, this function should contain
  175. * the equivalent API call for the firmware TPM driver which takes a
  176. * raw sequence of bytes as input command and a pointer to the
  177. * output buffer for putting in the results.
  178. *
  179. * For EFI firmwares, this can make use of the EFI TPM driver as
  180. * follows (based on page 16, of TCG EFI Protocol Specs Version 1.20
  181. * availaible from the TCG website):
  182. *
  183. * EFI_STATUS status;
  184. * status = TcgProtocol->EFI_TCG_PASS_THROUGH_TO_TPM(
  185. * TpmCommandSize(request),
  186. * request,
  187. * max_length,
  188. * response);
  189. * // Error checking depending on the value of the status above
  190. */
  191. #ifndef NDEBUG
  192. int tag, response_tag;
  193. #endif
  194. VbError_t result;
  195. #ifdef VBOOT_DEBUG
  196. struct timeval before, after;
  197. VB2_DEBUG("request (%d bytes):\n", request_length);
  198. DbgPrintBytes(request, request_length);
  199. gettimeofday(&before, NULL);
  200. #endif
  201. result = TpmExecute(request, request_length, response, response_length);
  202. if (result != VBERROR_SUCCESS)
  203. return result;
  204. #ifdef VBOOT_DEBUG
  205. gettimeofday(&after, NULL);
  206. VB2_DEBUG("response (%d bytes):\n", *response_length);
  207. DbgPrintBytes(response, *response_length);
  208. VB2_DEBUG("execution time: %dms\n",
  209. (int) ((after.tv_sec - before.tv_sec) * 1000 +
  210. (after.tv_usec - before.tv_usec) / 1000));
  211. #endif
  212. #ifndef NDEBUG
  213. /* sanity checks */
  214. tag = TpmTag(request);
  215. response_tag = TpmTag(response);
  216. assert(
  217. (tag == TPM_TAG_RQU_COMMAND &&
  218. response_tag == TPM_TAG_RSP_COMMAND) ||
  219. (tag == TPM_TAG_RQU_AUTH1_COMMAND &&
  220. response_tag == TPM_TAG_RSP_AUTH1_COMMAND) ||
  221. (tag == TPM_TAG_RQU_AUTH2_COMMAND &&
  222. response_tag == TPM_TAG_RSP_AUTH2_COMMAND));
  223. assert(*response_length == TpmResponseSize(response));
  224. #endif
  225. return VBERROR_SUCCESS;
  226. }