tlcl.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. * Copyright 2016 The Chromium OS Authors. All rights reserved.
  3. * Use of this source code is governed by a BSD-style license that can be
  4. * found in the LICENSE file.
  5. *
  6. * Some TPM constants and type definitions for standalone compilation for use
  7. * in the firmware
  8. */
  9. #include "2sysincludes.h"
  10. #include "2common.h"
  11. #include "rollback_index.h"
  12. #include "tpm2_marshaling.h"
  13. #include "utility.h"
  14. #include "tlcl.h"
  15. static struct tpm2_response *tpm_process_command(TPM_CC command,
  16. void *command_body)
  17. {
  18. /* Command/response buffer. */
  19. static uint8_t cr_buffer[TPM_BUFFER_SIZE];
  20. uint32_t out_size, in_size;
  21. struct tpm2_response *response;
  22. out_size = tpm_marshal_command(command, command_body,
  23. cr_buffer, sizeof(cr_buffer));
  24. if (out_size < 0) {
  25. VB2_DEBUG("command %#x, cr size %d\n", command, out_size);
  26. return NULL;
  27. }
  28. in_size = sizeof(cr_buffer);
  29. if (VbExTpmSendReceive(cr_buffer, out_size,
  30. cr_buffer, &in_size) != TPM_SUCCESS) {
  31. VB2_DEBUG("tpm transaction failed for %#x\n", command);
  32. return NULL;
  33. }
  34. response = tpm_unmarshal_response(command, cr_buffer, in_size);
  35. VB2_DEBUG("command %#x, return code %#x\n", command,
  36. response ? response->hdr.tpm_code : -1);
  37. return response;
  38. }
  39. static uint32_t tlcl_read_ph_disabled(void)
  40. {
  41. uint32_t rv;
  42. TPM_STCLEAR_FLAGS flags;
  43. rv = TlclGetSTClearFlags(&flags);
  44. if (rv != TPM_SUCCESS)
  45. return rv;
  46. tpm_set_ph_disabled(!flags.phEnable);
  47. return TPM_SUCCESS;
  48. }
  49. uint32_t TlclLibInit(void)
  50. {
  51. uint32_t rv;
  52. rv = VbExTpmInit();
  53. if (rv != TPM_SUCCESS)
  54. return rv;
  55. rv = tlcl_read_ph_disabled();
  56. if (rv != TPM_SUCCESS) {
  57. TlclLibClose();
  58. return rv;
  59. }
  60. return TPM_SUCCESS;
  61. }
  62. uint32_t TlclLibClose(void)
  63. {
  64. return VbExTpmClose();
  65. }
  66. uint32_t TlclSendReceive(const uint8_t *request, uint8_t *response,
  67. int max_length)
  68. {
  69. uint32_t rv, resp_size;
  70. resp_size = max_length;
  71. rv = VbExTpmSendReceive(request, tpm_get_packet_size(request),
  72. response, &resp_size);
  73. return rv ? rv : tpm_get_packet_response_code(response);
  74. }
  75. int TlclPacketSize(const uint8_t *packet)
  76. {
  77. return tpm_get_packet_size(packet);
  78. }
  79. uint32_t TlclStartup(void)
  80. {
  81. struct tpm2_response *response;
  82. struct tpm2_startup_cmd startup;
  83. startup.startup_type = TPM_SU_CLEAR;
  84. response = tpm_process_command(TPM2_Startup, &startup);
  85. if (!response || response->hdr.tpm_code)
  86. return TPM_E_IOERROR;
  87. return TPM_SUCCESS;
  88. }
  89. uint32_t TlclSaveState(void)
  90. {
  91. struct tpm2_response *response;
  92. struct tpm2_shutdown_cmd shutdown;
  93. shutdown.shutdown_type = TPM_SU_STATE;
  94. response = tpm_process_command(TPM2_Shutdown, &shutdown);
  95. if (!response || response->hdr.tpm_code)
  96. return TPM_E_IOERROR;
  97. return TPM_SUCCESS;
  98. }
  99. uint32_t TlclResume(void)
  100. {
  101. struct tpm2_response *response;
  102. struct tpm2_startup_cmd startup;
  103. startup.startup_type = TPM_SU_STATE;
  104. response = tpm_process_command(TPM2_Startup, &startup);
  105. if (!response || response->hdr.tpm_code)
  106. return TPM_E_IOERROR;
  107. return TPM_SUCCESS;
  108. }
  109. uint32_t TlclSelfTestFull(void)
  110. {
  111. struct tpm2_response *response;
  112. struct tpm2_self_test_cmd self_test;
  113. self_test.full_test = 1;
  114. response = tpm_process_command(TPM2_SelfTest, &self_test);
  115. if (!response || response->hdr.tpm_code)
  116. return TPM_E_IOERROR;
  117. return TPM_SUCCESS;
  118. }
  119. uint32_t TlclContinueSelfTest(void)
  120. {
  121. struct tpm2_response *response;
  122. struct tpm2_self_test_cmd self_test;
  123. self_test.full_test = 0;
  124. response = tpm_process_command(TPM2_SelfTest, &self_test);
  125. if (!response || response->hdr.tpm_code)
  126. return TPM_E_IOERROR;
  127. return TPM_SUCCESS;
  128. }
  129. uint32_t TlclDefineSpace(uint32_t index, uint32_t perm, uint32_t size)
  130. {
  131. struct tpm2_response *response;
  132. struct tpm2_nv_define_space_cmd define_space;
  133. /* For backwards-compatibility, if no READ or WRITE permissions are set,
  134. * assume readable/writeable with empty auth value.
  135. */
  136. if (!(perm & TPMA_NV_MASK_WRITE))
  137. perm |= TPMA_NV_AUTHWRITE;
  138. if (!(perm & TPMA_NV_MASK_READ))
  139. perm |= TPMA_NV_AUTHREAD;
  140. memset(&define_space, 0, sizeof(define_space));
  141. define_space.publicInfo.nvIndex = HR_NV_INDEX + index;
  142. define_space.publicInfo.dataSize = size;
  143. define_space.publicInfo.attributes = perm;
  144. define_space.publicInfo.nameAlg = TPM_ALG_SHA256;
  145. response = tpm_process_command(TPM2_NV_DefineSpace, &define_space);
  146. if (!response || response->hdr.tpm_code)
  147. return TPM_E_IOERROR;
  148. return TPM_SUCCESS;
  149. }
  150. /**
  151. * Issue a ForceClear. The TPM error code is returned.
  152. */
  153. uint32_t TlclForceClear(void)
  154. {
  155. struct tpm2_response *response;
  156. response = tpm_process_command(TPM2_Clear, NULL);
  157. if (!response || response->hdr.tpm_code)
  158. return TPM_E_IOERROR;
  159. return TPM_SUCCESS;
  160. }
  161. uint32_t TlclSetDeactivated(uint8_t flag)
  162. {
  163. VB2_DEBUG("NOT YET IMPLEMENTED\n");
  164. return TPM_SUCCESS;
  165. }
  166. uint32_t TlclSetEnable(void)
  167. {
  168. VB2_DEBUG("NOT YET IMPLEMENTED\n");
  169. return TPM_SUCCESS;
  170. }
  171. uint32_t TlclGetFlags(uint8_t* disable,
  172. uint8_t* deactivated,
  173. uint8_t *nvlocked)
  174. {
  175. /* For TPM2 the flags are always the same */
  176. if (disable)
  177. *disable = 0;
  178. if (deactivated)
  179. *deactivated = 0;
  180. if (nvlocked)
  181. *nvlocked = 1;
  182. return TPM_SUCCESS;
  183. }
  184. int TlclIsOwned(void)
  185. {
  186. VB2_DEBUG("NOT YET IMPLEMENTED\n");
  187. return 0;
  188. }
  189. uint32_t TlclExtend(int pcr_num, const uint8_t *in_digest, uint8_t *out_digest)
  190. {
  191. VB2_DEBUG("NOT YET IMPLEMENTED\n");
  192. return TPM_SUCCESS;
  193. }
  194. static uint32_t tlcl_nv_read_public(uint32_t index,
  195. struct nv_read_public_response **presp)
  196. {
  197. struct tpm2_response *response;
  198. struct tpm2_nv_read_public_cmd read_pub;
  199. memset(&read_pub, 0, sizeof(read_pub));
  200. read_pub.nvIndex = HR_NV_INDEX + index;
  201. response = tpm_process_command(TPM2_NV_ReadPublic, &read_pub);
  202. if (!response || response->hdr.tpm_code)
  203. return TPM_E_IOERROR;
  204. *presp = &response->nv_read_public;
  205. return TPM_SUCCESS;
  206. }
  207. /**
  208. * Get the permission bits for the NVRAM space with |index|.
  209. */
  210. uint32_t TlclGetPermissions(uint32_t index, uint32_t *permissions)
  211. {
  212. uint32_t rv;
  213. struct nv_read_public_response *resp;
  214. rv = tlcl_nv_read_public(index, &resp);
  215. if (rv != TPM_SUCCESS)
  216. return rv;
  217. *permissions = resp->nvPublic.attributes;
  218. return TPM_SUCCESS;
  219. }
  220. static uint32_t tlcl_get_capability(TPM_CAP cap, TPM_PT property,
  221. struct get_capability_response **presp)
  222. {
  223. struct tpm2_response *response;
  224. struct tpm2_get_capability_cmd getcap;
  225. getcap.capability = cap;
  226. getcap.property = property;
  227. getcap.property_count = 1;
  228. response = tpm_process_command(TPM2_GetCapability, &getcap);
  229. if (!response || response->hdr.tpm_code)
  230. return TPM_E_IOERROR;
  231. *presp = &response->cap;
  232. return TPM_SUCCESS;
  233. }
  234. static uint32_t tlcl_get_tpm_property(TPM_PT property, uint32_t *pvalue)
  235. {
  236. uint32_t rv;
  237. struct get_capability_response *resp;
  238. TPML_TAGGED_TPM_PROPERTY *tpm_prop;
  239. rv = tlcl_get_capability(TPM_CAP_TPM_PROPERTIES, property, &resp);
  240. if (rv != TPM_SUCCESS)
  241. return rv;
  242. if (resp->capability_data.capability != TPM_CAP_TPM_PROPERTIES)
  243. return TPM_E_IOERROR;
  244. tpm_prop = &resp->capability_data.data.tpm_properties;
  245. if ((tpm_prop->count != 1) ||
  246. (tpm_prop->tpm_property[0].property != property))
  247. return TPM_E_IOERROR;
  248. *pvalue = tpm_prop->tpm_property[0].value;
  249. return TPM_SUCCESS;
  250. }
  251. uint32_t TlclGetPermanentFlags(TPM_PERMANENT_FLAGS *pflags)
  252. {
  253. return tlcl_get_tpm_property(TPM_PT_PERMANENT,
  254. (uint32_t *)pflags);
  255. }
  256. uint32_t TlclGetSTClearFlags(TPM_STCLEAR_FLAGS *pflags)
  257. {
  258. return tlcl_get_tpm_property(TPM_PT_STARTUP_CLEAR,
  259. (uint32_t *)pflags);
  260. }
  261. uint32_t TlclGetOwnership(uint8_t *owned)
  262. {
  263. uint32_t rv;
  264. TPM_PERMANENT_FLAGS flags;
  265. *owned = 0;
  266. rv = TlclGetPermanentFlags(&flags);
  267. if (rv != TPM_SUCCESS)
  268. return rv;
  269. *owned = flags.ownerAuthSet;
  270. return TPM_SUCCESS;
  271. }
  272. static uint32_t tlcl_lock_nv_write(uint32_t index)
  273. {
  274. struct tpm2_response *response;
  275. struct tpm2_nv_write_lock_cmd nv_wl;
  276. nv_wl.nvIndex = HR_NV_INDEX + index;
  277. response = tpm_process_command(TPM2_NV_WriteLock, &nv_wl);
  278. if (!response || response->hdr.tpm_code)
  279. return TPM_E_INTERNAL_INCONSISTENCY;
  280. return TPM_SUCCESS;
  281. }
  282. static uint32_t tlcl_disable_platform_hierarchy(void)
  283. {
  284. struct tpm2_response *response;
  285. struct tpm2_hierarchy_control_cmd hc;
  286. hc.enable = TPM_RH_PLATFORM;
  287. hc.state = 0;
  288. response = tpm_process_command(TPM2_Hierarchy_Control, &hc);
  289. if (!response || response->hdr.tpm_code)
  290. return TPM_E_INTERNAL_INCONSISTENCY;
  291. tpm_set_ph_disabled(1);
  292. return TPM_SUCCESS;
  293. }
  294. /**
  295. * The name of the function was kept to maintain the existing TPM API, but
  296. * TPM2.0 does not use the global lock to protect the FW rollback counter.
  297. * Instead it calls WriteLock for the FW NVRAM index to prevent future
  298. * writes to it.
  299. *
  300. * It first checks if the platform hierarchy is already disabled, and does
  301. * nothing, if so. Otherwise, WriteLock for the index obviously fails.
  302. */
  303. uint32_t TlclSetGlobalLock(void)
  304. {
  305. if (tpm_is_ph_disabled())
  306. return TPM_SUCCESS;
  307. else
  308. return tlcl_lock_nv_write(FIRMWARE_NV_INDEX);
  309. }
  310. /**
  311. * Turn off physical presence and locks it off until next reboot. The TPM
  312. * error code is returned.
  313. *
  314. * The name of the function was kept to maintain the existing TPM API, but
  315. * TPM2.0 does not have to use the Physical Presence concept. Instead it just
  316. * removes platform authorization - this makes sure that firmware and kernel
  317. * rollback counter spaces can not be modified.
  318. *
  319. * It also explicitly locks the kernel rollback counter space (the FW rollback
  320. * counter space was locked before RW firmware started.)
  321. */
  322. uint32_t TlclLockPhysicalPresence(void)
  323. {
  324. if (tpm_is_ph_disabled())
  325. return TPM_SUCCESS;
  326. return tlcl_disable_platform_hierarchy();
  327. }
  328. uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
  329. {
  330. struct tpm2_nv_read_cmd nv_readc;
  331. struct tpm2_response *response;
  332. memset(&nv_readc, 0, sizeof(nv_readc));
  333. nv_readc.nvIndex = HR_NV_INDEX + index;
  334. nv_readc.size = length;
  335. response = tpm_process_command(TPM2_NV_Read, &nv_readc);
  336. /* Need to map tpm error codes into internal values. */
  337. if (!response)
  338. return TPM_E_READ_FAILURE;
  339. switch (response->hdr.tpm_code) {
  340. case 0:
  341. break;
  342. case 0x28b:
  343. return TPM_E_BADINDEX;
  344. default:
  345. return TPM_E_READ_FAILURE;
  346. }
  347. if (length > response->nvr.buffer.t.size)
  348. return TPM_E_RESPONSE_TOO_LARGE;
  349. if (length < response->nvr.buffer.t.size)
  350. return TPM_E_READ_EMPTY;
  351. memcpy(data, response->nvr.buffer.t.buffer, length);
  352. return TPM_SUCCESS;
  353. }
  354. uint32_t TlclWrite(uint32_t index, const void *data, uint32_t length)
  355. {
  356. struct tpm2_nv_write_cmd nv_writec;
  357. struct tpm2_response *response;
  358. memset(&nv_writec, 0, sizeof(nv_writec));
  359. nv_writec.nvIndex = HR_NV_INDEX + index;
  360. nv_writec.data.t.size = length;
  361. nv_writec.data.t.buffer = data;
  362. response = tpm_process_command(TPM2_NV_Write, &nv_writec);
  363. /* Need to map tpm error codes into internal values. */
  364. if (!response || response->hdr.tpm_code)
  365. return TPM_E_WRITE_FAILURE;
  366. return TPM_SUCCESS;
  367. }
  368. uint32_t TlclPCRRead(uint32_t index, void *data, uint32_t length)
  369. {
  370. VB2_DEBUG("NOT YET IMPLEMENTED\n");
  371. return TPM_SUCCESS;
  372. }
  373. uint32_t TlclWriteLock(uint32_t index)
  374. {
  375. struct tpm2_nv_write_lock_cmd nv_writelockc;
  376. struct tpm2_response *response;
  377. memset(&nv_writelockc, 0, sizeof(nv_writelockc));
  378. nv_writelockc.nvIndex = HR_NV_INDEX | index;
  379. response = tpm_process_command(TPM2_NV_WriteLock, &nv_writelockc);
  380. /* Need to map tpm error codes into internal values. */
  381. if (!response || response->hdr.tpm_code)
  382. return TPM_E_WRITE_FAILURE;
  383. return TPM_SUCCESS;
  384. }
  385. uint32_t TlclReadLock(uint32_t index)
  386. {
  387. struct tpm2_nv_read_lock_cmd nv_readlockc;
  388. struct tpm2_response *response;
  389. memset(&nv_readlockc, 0, sizeof(nv_readlockc));
  390. nv_readlockc.nvIndex = HR_NV_INDEX | index;
  391. response = tpm_process_command(TPM2_NV_ReadLock, &nv_readlockc);
  392. /* Need to map tpm error codes into internal values. */
  393. if (!response || response->hdr.tpm_code)
  394. return TPM_E_READ_FAILURE;
  395. return TPM_SUCCESS;
  396. }
  397. uint32_t TlclGetRandom(uint8_t *data, uint32_t length, uint32_t *size)
  398. {
  399. *size = 0;
  400. VB2_DEBUG("NOT YET IMPLEMENTED\n");
  401. return TPM_E_IOERROR;
  402. }