tpm_tis_sandbox.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright (c) 2013 Google, Inc
  4. */
  5. #include <common.h>
  6. #include <dm.h>
  7. #include <tpm-v1.h>
  8. #include <asm/state.h>
  9. #include <asm/unaligned.h>
  10. #include <u-boot/crc.h>
  11. #include "sandbox_common.h"
  12. #define NV_DATA_PUBLIC_PERMISSIONS_OFFSET 60
  13. /*
  14. * Information about our TPM emulation. This is preserved in the sandbox
  15. * state file if enabled.
  16. */
  17. static struct tpm_state {
  18. bool valid;
  19. struct nvdata_state nvdata[NV_SEQ_COUNT];
  20. } s_state, *g_state;
  21. /**
  22. * sandbox_tpm_read_state() - read the sandbox EC state from the state file
  23. *
  24. * If data is available, then blob and node will provide access to it. If
  25. * not this function sets up an empty TPM.
  26. *
  27. * @blob: Pointer to device tree blob, or NULL if no data to read
  28. * @node: Node offset to read from
  29. */
  30. static int sandbox_tpm_read_state(const void *blob, int node)
  31. {
  32. struct tpm_state *state = &s_state;
  33. const char *prop;
  34. int len;
  35. int i;
  36. if (!blob)
  37. return 0;
  38. for (i = 0; i < NV_SEQ_COUNT; i++) {
  39. struct nvdata_state *nvd = &state->nvdata[i];
  40. char prop_name[20];
  41. sprintf(prop_name, "nvdata%d", i);
  42. prop = fdt_getprop(blob, node, prop_name, &len);
  43. if (len >= NV_DATA_SIZE)
  44. return log_msg_ret("nvd", -E2BIG);
  45. if (prop) {
  46. memcpy(nvd->data, prop, len);
  47. nvd->length = len;
  48. nvd->present = true;
  49. }
  50. }
  51. s_state.valid = true;
  52. return 0;
  53. }
  54. /**
  55. * sandbox_tpm_write_state() - Write out our state to the state file
  56. *
  57. * The caller will ensure that there is a node ready for the state. The node
  58. * may already contain the old state, in which case it is overridden.
  59. *
  60. * @blob: Device tree blob holding state
  61. * @node: Node to write our state into
  62. */
  63. static int sandbox_tpm_write_state(void *blob, int node)
  64. {
  65. const struct tpm_state *state = g_state;
  66. int i;
  67. if (!state)
  68. return 0;
  69. /*
  70. * We are guaranteed enough space to write basic properties.
  71. * We could use fdt_add_subnode() to put each set of data in its
  72. * own node - perhaps useful if we add access informaiton to each.
  73. */
  74. for (i = 0; i < NV_SEQ_COUNT; i++) {
  75. const struct nvdata_state *nvd = &state->nvdata[i];
  76. char prop_name[20];
  77. if (nvd->present) {
  78. snprintf(prop_name, sizeof(prop_name), "nvdata%d", i);
  79. fdt_setprop(blob, node, prop_name, nvd->data,
  80. nvd->length);
  81. }
  82. }
  83. return 0;
  84. }
  85. SANDBOX_STATE_IO(sandbox_tpm, "google,sandbox-tpm", sandbox_tpm_read_state,
  86. sandbox_tpm_write_state);
  87. static void handle_cap_flag_space(u8 **datap, uint index)
  88. {
  89. struct tpm_nv_data_public pub;
  90. /* TPM_NV_PER_PPWRITE */
  91. memset(&pub, '\0', sizeof(pub));
  92. pub.nv_index = __cpu_to_be32(index);
  93. pub.pcr_info_read.pcr_selection.size_of_select = __cpu_to_be16(
  94. sizeof(pub.pcr_info_read.pcr_selection.pcr_select));
  95. pub.permission.attributes = __cpu_to_be32(1);
  96. pub.pcr_info_write = pub.pcr_info_read;
  97. memcpy(*datap, &pub, sizeof(pub));
  98. *datap += sizeof(pub);
  99. }
  100. static int sandbox_tpm_xfer(struct udevice *dev, const uint8_t *sendbuf,
  101. size_t send_size, uint8_t *recvbuf,
  102. size_t *recv_len)
  103. {
  104. struct tpm_state *tpm = dev_get_priv(dev);
  105. uint32_t code, index, length, type;
  106. uint8_t *data;
  107. int seq;
  108. code = get_unaligned_be32(sendbuf + sizeof(uint16_t) +
  109. sizeof(uint32_t));
  110. #ifdef DEBUG
  111. printf("tpm: %zd bytes, recv_len %zd, cmd = %x\n", send_size,
  112. *recv_len, code);
  113. print_buffer(0, sendbuf, 1, send_size, 0);
  114. #endif
  115. switch (code) {
  116. case TPM_CMD_GET_CAPABILITY:
  117. type = get_unaligned_be32(sendbuf + 14);
  118. switch (type) {
  119. case TPM_CAP_FLAG:
  120. index = get_unaligned_be32(sendbuf + 18);
  121. printf("Get flags index %#02x\n", index);
  122. *recv_len = 22;
  123. memset(recvbuf, '\0', *recv_len);
  124. data = recvbuf + TPM_HDR_LEN + sizeof(uint32_t);
  125. switch (index) {
  126. case FIRMWARE_NV_INDEX:
  127. break;
  128. case KERNEL_NV_INDEX:
  129. handle_cap_flag_space(&data, index);
  130. *recv_len = data - recvbuf;
  131. break;
  132. case TPM_CAP_FLAG_PERMANENT: {
  133. struct tpm_permanent_flags *pflags;
  134. pflags = (struct tpm_permanent_flags *)data;
  135. memset(pflags, '\0', sizeof(*pflags));
  136. put_unaligned_be32(TPM_TAG_PERMANENT_FLAGS,
  137. &pflags->tag);
  138. *recv_len = TPM_HEADER_SIZE + 4 +
  139. sizeof(*pflags);
  140. break;
  141. }
  142. default:
  143. printf(" ** Unknown flags index %x\n", index);
  144. return -ENOSYS;
  145. }
  146. put_unaligned_be32(*recv_len, recvbuf + TPM_HDR_LEN);
  147. break;
  148. case TPM_CAP_NV_INDEX:
  149. index = get_unaligned_be32(sendbuf + 18);
  150. printf("Get cap nv index %#02x\n", index);
  151. put_unaligned_be32(22, recvbuf + TPM_HDR_LEN);
  152. break;
  153. default:
  154. printf(" ** Unknown 0x65 command type %#02x\n",
  155. type);
  156. return -ENOSYS;
  157. }
  158. break;
  159. case TPM_CMD_NV_WRITE_VALUE:
  160. index = get_unaligned_be32(sendbuf + 10);
  161. length = get_unaligned_be32(sendbuf + 18);
  162. seq = sb_tpm_index_to_seq(index);
  163. if (seq < 0)
  164. return -EINVAL;
  165. printf("tpm: nvwrite index=%#02x, len=%#02x\n", index, length);
  166. sb_tpm_write_data(tpm->nvdata, seq, sendbuf, 22, length);
  167. break;
  168. case TPM_CMD_NV_READ_VALUE: /* nvread */
  169. index = get_unaligned_be32(sendbuf + 10);
  170. length = get_unaligned_be32(sendbuf + 18);
  171. seq = sb_tpm_index_to_seq(index);
  172. if (seq < 0)
  173. return -EINVAL;
  174. printf("tpm: nvread index=%#02x, len=%#02x, seq=%#02x\n", index,
  175. length, seq);
  176. *recv_len = TPM_HDR_LEN + sizeof(uint32_t) + length;
  177. memset(recvbuf, '\0', *recv_len);
  178. put_unaligned_be32(length, recvbuf + TPM_HDR_LEN);
  179. sb_tpm_read_data(tpm->nvdata, seq, recvbuf, TPM_HDR_LEN + 4,
  180. length);
  181. break;
  182. case TPM_CMD_EXTEND:
  183. *recv_len = 30;
  184. memset(recvbuf, '\0', *recv_len);
  185. break;
  186. case TPM_CMD_NV_DEFINE_SPACE:
  187. index = get_unaligned_be32(sendbuf + 12);
  188. length = get_unaligned_be32(sendbuf + 77);
  189. seq = sb_tpm_index_to_seq(index);
  190. if (seq < 0)
  191. return -EINVAL;
  192. printf("tpm: define_space index=%#02x, len=%#02x, seq=%#02x\n",
  193. index, length, seq);
  194. sb_tpm_define_data(tpm->nvdata, seq, length);
  195. *recv_len = 12;
  196. memset(recvbuf, '\0', *recv_len);
  197. break;
  198. case 0x15: /* pcr read */
  199. case 0x5d: /* force clear */
  200. case 0x6f: /* physical enable */
  201. case 0x72: /* physical set deactivated */
  202. case 0x99: /* startup */
  203. case 0x50: /* self test full */
  204. case 0x4000000a: /* assert physical presence */
  205. *recv_len = 12;
  206. memset(recvbuf, '\0', *recv_len);
  207. break;
  208. default:
  209. printf("Unknown tpm command %02x\n", code);
  210. return -ENOSYS;
  211. }
  212. #ifdef DEBUG
  213. printf("tpm: rx recv_len %zd\n", *recv_len);
  214. print_buffer(0, recvbuf, 1, *recv_len, 0);
  215. #endif
  216. return 0;
  217. }
  218. static int sandbox_tpm_get_desc(struct udevice *dev, char *buf, int size)
  219. {
  220. if (size < 15)
  221. return -ENOSPC;
  222. return snprintf(buf, size, "sandbox TPM");
  223. }
  224. static int sandbox_tpm_probe(struct udevice *dev)
  225. {
  226. struct tpm_state *tpm = dev_get_priv(dev);
  227. if (s_state.valid)
  228. memcpy(tpm, &s_state, sizeof(*tpm));
  229. g_state = tpm;
  230. return 0;
  231. }
  232. static int sandbox_tpm_open(struct udevice *dev)
  233. {
  234. return 0;
  235. }
  236. static int sandbox_tpm_close(struct udevice *dev)
  237. {
  238. return 0;
  239. }
  240. static const struct tpm_ops sandbox_tpm_ops = {
  241. .open = sandbox_tpm_open,
  242. .close = sandbox_tpm_close,
  243. .get_desc = sandbox_tpm_get_desc,
  244. .xfer = sandbox_tpm_xfer,
  245. };
  246. static const struct udevice_id sandbox_tpm_ids[] = {
  247. { .compatible = "google,sandbox-tpm" },
  248. { }
  249. };
  250. U_BOOT_DRIVER(google_sandbox_tpm) = {
  251. .name = "google_sandbox_tpm",
  252. .id = UCLASS_TPM,
  253. .of_match = sandbox_tpm_ids,
  254. .ops = &sandbox_tpm_ops,
  255. .probe = sandbox_tpm_probe,
  256. .priv_auto = sizeof(struct tpm_state),
  257. };