tpm_tis_sandbox.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. /*
  2. * Copyright (c) 2013 Google, Inc
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <asm/state.h>
  8. #include <asm/unaligned.h>
  9. #include <linux/crc8.h>
  10. /* TPM NVRAM location indices. */
  11. #define FIRMWARE_NV_INDEX 0x1007
  12. #define KERNEL_NV_INDEX 0x1008
  13. #define NV_DATA_PUBLIC_PERMISSIONS_OFFSET 60
  14. /* Kernel TPM space - KERNEL_NV_INDEX, locked with physical presence */
  15. #define ROLLBACK_SPACE_KERNEL_VERSION 2
  16. #define ROLLBACK_SPACE_KERNEL_UID 0x4752574C /* 'GRWL' */
  17. struct rollback_space_kernel {
  18. /* Struct version, for backwards compatibility */
  19. uint8_t struct_version;
  20. /* Unique ID to detect space redefinition */
  21. uint32_t uid;
  22. /* Kernel versions */
  23. uint32_t kernel_versions;
  24. /* Reserved for future expansion */
  25. uint8_t reserved[3];
  26. /* Checksum (v2 and later only) */
  27. uint8_t crc8;
  28. } __packed rollback_space_kernel;
  29. /*
  30. * These numbers derive from adding the sizes of command fields as shown in
  31. * the TPM commands manual.
  32. */
  33. #define TPM_REQUEST_HEADER_LENGTH 10
  34. #define TPM_RESPONSE_HEADER_LENGTH 10
  35. /* These are the different non-volatile spaces that we emulate */
  36. enum {
  37. NV_GLOBAL_LOCK,
  38. NV_SEQ_FIRMWARE,
  39. NV_SEQ_KERNEL,
  40. NV_SEQ_COUNT,
  41. };
  42. /* Size of each non-volatile space */
  43. #define NV_DATA_SIZE 0x20
  44. /*
  45. * Information about our TPM emulation. This is preserved in the sandbox
  46. * state file if enabled.
  47. */
  48. static struct tpm_state {
  49. uint8_t nvdata[NV_SEQ_COUNT][NV_DATA_SIZE];
  50. } state;
  51. /**
  52. * sandbox_tpm_read_state() - read the sandbox EC state from the state file
  53. *
  54. * If data is available, then blob and node will provide access to it. If
  55. * not this function sets up an empty TPM.
  56. *
  57. * @blob: Pointer to device tree blob, or NULL if no data to read
  58. * @node: Node offset to read from
  59. */
  60. static int sandbox_tpm_read_state(const void *blob, int node)
  61. {
  62. const char *prop;
  63. int len;
  64. int i;
  65. if (!blob)
  66. return 0;
  67. for (i = 0; i < NV_SEQ_COUNT; i++) {
  68. char prop_name[20];
  69. sprintf(prop_name, "nvdata%d", i);
  70. prop = fdt_getprop(blob, node, prop_name, &len);
  71. if (prop && len == NV_DATA_SIZE)
  72. memcpy(state.nvdata[i], prop, NV_DATA_SIZE);
  73. }
  74. return 0;
  75. }
  76. /**
  77. * cros_ec_write_state() - Write out our state to the state file
  78. *
  79. * The caller will ensure that there is a node ready for the state. The node
  80. * may already contain the old state, in which case it is overridden.
  81. *
  82. * @blob: Device tree blob holding state
  83. * @node: Node to write our state into
  84. */
  85. static int sandbox_tpm_write_state(void *blob, int node)
  86. {
  87. int i;
  88. /*
  89. * We are guaranteed enough space to write basic properties.
  90. * We could use fdt_add_subnode() to put each set of data in its
  91. * own node - perhaps useful if we add access informaiton to each.
  92. */
  93. for (i = 0; i < NV_SEQ_COUNT; i++) {
  94. char prop_name[20];
  95. sprintf(prop_name, "nvdata%d", i);
  96. fdt_setprop(blob, node, prop_name, state.nvdata[i],
  97. NV_DATA_SIZE);
  98. }
  99. return 0;
  100. }
  101. SANDBOX_STATE_IO(sandbox_tpm, "google,sandbox-tpm", sandbox_tpm_read_state,
  102. sandbox_tpm_write_state);
  103. static int index_to_seq(uint32_t index)
  104. {
  105. switch (index) {
  106. case FIRMWARE_NV_INDEX:
  107. return NV_SEQ_FIRMWARE;
  108. case KERNEL_NV_INDEX:
  109. return NV_SEQ_KERNEL;
  110. case 0:
  111. return NV_GLOBAL_LOCK;
  112. }
  113. printf("Invalid nv index %#x\n", index);
  114. return -1;
  115. }
  116. int tis_sendrecv(const u8 *sendbuf, size_t send_size,
  117. u8 *recvbuf, size_t *recv_len)
  118. {
  119. struct tpm_state *tpm = &state;
  120. uint32_t code, index, length, type;
  121. uint8_t *data;
  122. int seq;
  123. code = get_unaligned_be32(sendbuf + sizeof(uint16_t) +
  124. sizeof(uint32_t));
  125. printf("tpm: %zd bytes, recv_len %zd, cmd = %x\n", send_size,
  126. *recv_len, code);
  127. print_buffer(0, sendbuf, 1, send_size, 0);
  128. switch (code) {
  129. case 0x65: /* get flags */
  130. type = get_unaligned_be32(sendbuf + 14);
  131. switch (type) {
  132. case 4:
  133. index = get_unaligned_be32(sendbuf + 18);
  134. printf("Get flags index %#02x\n", index);
  135. *recv_len = 22;
  136. memset(recvbuf, '\0', *recv_len);
  137. put_unaligned_be32(22, recvbuf +
  138. TPM_RESPONSE_HEADER_LENGTH);
  139. data = recvbuf + TPM_RESPONSE_HEADER_LENGTH +
  140. sizeof(uint32_t);
  141. switch (index) {
  142. case FIRMWARE_NV_INDEX:
  143. break;
  144. case KERNEL_NV_INDEX:
  145. /* TPM_NV_PER_PPWRITE */
  146. put_unaligned_be32(1, data +
  147. NV_DATA_PUBLIC_PERMISSIONS_OFFSET);
  148. break;
  149. }
  150. break;
  151. case 0x11: /* TPM_CAP_NV_INDEX */
  152. index = get_unaligned_be32(sendbuf + 18);
  153. printf("Get cap nv index %#02x\n", index);
  154. put_unaligned_be32(22, recvbuf +
  155. TPM_RESPONSE_HEADER_LENGTH);
  156. break;
  157. default:
  158. printf(" ** Unknown 0x65 command type %#02x\n",
  159. type);
  160. return -1;
  161. }
  162. break;
  163. case 0xcd: /* nvwrite */
  164. index = get_unaligned_be32(sendbuf + 10);
  165. length = get_unaligned_be32(sendbuf + 18);
  166. seq = index_to_seq(index);
  167. if (seq < 0)
  168. return -1;
  169. printf("tpm: nvwrite index=%#02x, len=%#02x\n", index, length);
  170. memcpy(&tpm->nvdata[seq], sendbuf + 22, length);
  171. *recv_len = 12;
  172. memset(recvbuf, '\0', *recv_len);
  173. break;
  174. case 0xcf: /* nvread */
  175. index = get_unaligned_be32(sendbuf + 10);
  176. length = get_unaligned_be32(sendbuf + 18);
  177. seq = index_to_seq(index);
  178. if (seq < 0)
  179. return -1;
  180. printf("tpm: nvread index=%#02x, len=%#02x\n", index, length);
  181. *recv_len = TPM_RESPONSE_HEADER_LENGTH + sizeof(uint32_t) +
  182. length;
  183. memset(recvbuf, '\0', *recv_len);
  184. put_unaligned_be32(length, recvbuf +
  185. TPM_RESPONSE_HEADER_LENGTH);
  186. if (seq == NV_SEQ_KERNEL) {
  187. struct rollback_space_kernel rsk;
  188. data = recvbuf + TPM_RESPONSE_HEADER_LENGTH +
  189. sizeof(uint32_t);
  190. rsk.struct_version = 2;
  191. rsk.uid = ROLLBACK_SPACE_KERNEL_UID;
  192. rsk.kernel_versions = 0;
  193. rsk.crc8 = crc8((unsigned char *)&rsk,
  194. offsetof(struct rollback_space_kernel,
  195. crc8));
  196. memcpy(data, &rsk, sizeof(rsk));
  197. } else {
  198. memcpy(recvbuf + TPM_RESPONSE_HEADER_LENGTH +
  199. sizeof(uint32_t), &tpm->nvdata[seq], length);
  200. }
  201. break;
  202. case 0x14: /* tpm extend */
  203. case 0x15: /* pcr read */
  204. case 0x5d: /* force clear */
  205. case 0x6f: /* physical enable */
  206. case 0x72: /* physical set deactivated */
  207. case 0x99: /* startup */
  208. case 0x4000000a: /* assert physical presence */
  209. *recv_len = 12;
  210. memset(recvbuf, '\0', *recv_len);
  211. break;
  212. default:
  213. printf("Unknown tpm command %02x\n", code);
  214. return -1;
  215. }
  216. return 0;
  217. }
  218. int tis_open(void)
  219. {
  220. printf("%s\n", __func__);
  221. return 0;
  222. }
  223. int tis_close(void)
  224. {
  225. printf("%s\n", __func__);
  226. return 0;
  227. }
  228. int tis_init(void)
  229. {
  230. printf("%s\n", __func__);
  231. return 0;
  232. }