rollback_index.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /* Copyright (c) 2013 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. * Functions for querying, manipulating and locking rollback indices
  6. * stored in the TPM NVRAM.
  7. */
  8. #include "2sysincludes.h"
  9. #include "2common.h"
  10. #include "2crc8.h"
  11. #include "sysincludes.h"
  12. #include "rollback_index.h"
  13. #include "tlcl.h"
  14. #include "tss_constants.h"
  15. #include "utility.h"
  16. #include "vboot_api.h"
  17. #ifndef offsetof
  18. #define offsetof(A,B) __builtin_offsetof(A,B)
  19. #endif
  20. /*
  21. * Provide protoypes for functions not in the header file. These prototypes
  22. * fix -Wmissing-prototypes warnings.
  23. */
  24. uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf);
  25. uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf);
  26. uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk);
  27. uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk);
  28. #ifdef FOR_TEST
  29. /*
  30. * Compiling for unit test, so we need the real implementations of
  31. * rollback functions. The unit test mocks the underlying tlcl
  32. * functions, so this is ok to run on the host.
  33. */
  34. #undef CHROMEOS_ENVIRONMENT
  35. #undef DISABLE_ROLLBACK_TPM
  36. #endif
  37. #define RETURN_ON_FAILURE(tpm_command) do { \
  38. uint32_t result_; \
  39. if ((result_ = (tpm_command)) != TPM_SUCCESS) { \
  40. VB2_DEBUG("Rollback: %08x returned by " #tpm_command \
  41. "\n", (int)result_); \
  42. return result_; \
  43. } \
  44. } while (0)
  45. uint32_t TPMClearAndReenable(void)
  46. {
  47. VB2_DEBUG("TPM: Clear and re-enable\n");
  48. RETURN_ON_FAILURE(TlclForceClear());
  49. RETURN_ON_FAILURE(TlclSetEnable());
  50. RETURN_ON_FAILURE(TlclSetDeactivated(0));
  51. return TPM_SUCCESS;
  52. }
  53. uint32_t SafeWrite(uint32_t index, const void *data, uint32_t length)
  54. {
  55. uint32_t result = TlclWrite(index, data, length);
  56. if (result == TPM_E_MAXNVWRITES) {
  57. RETURN_ON_FAILURE(TPMClearAndReenable());
  58. return TlclWrite(index, data, length);
  59. } else {
  60. return result;
  61. }
  62. }
  63. /* Functions to read and write firmware and kernel spaces. */
  64. uint32_t ReadSpaceFirmware(RollbackSpaceFirmware *rsf)
  65. {
  66. uint32_t r;
  67. int attempts = 3;
  68. while (attempts--) {
  69. r = TlclRead(FIRMWARE_NV_INDEX, rsf,
  70. sizeof(RollbackSpaceFirmware));
  71. if (r != TPM_SUCCESS)
  72. return r;
  73. /*
  74. * No CRC in this version, so we'll create one when we write
  75. * it. Note that we're marking this as version 2, not
  76. * ROLLBACK_SPACE_FIRMWARE_VERSION, because version 2 just
  77. * added the CRC. Later versions will need to set default
  78. * values for any extra fields explicitly (probably here).
  79. */
  80. if (rsf->struct_version < 2) {
  81. /* Danger Will Robinson! Danger! */
  82. rsf->struct_version = 2;
  83. return TPM_SUCCESS;
  84. }
  85. /*
  86. * If the CRC is good, we're done. If it's bad, try a couple
  87. * more times to see if it gets better before we give up. It
  88. * could just be noise.
  89. */
  90. if (rsf->crc8 == vb2_crc8(rsf,
  91. offsetof(RollbackSpaceFirmware, crc8)))
  92. return TPM_SUCCESS;
  93. VB2_DEBUG("TPM: bad CRC\n");
  94. }
  95. VB2_DEBUG("TPM: too many bad CRCs, giving up\n");
  96. return TPM_E_CORRUPTED_STATE;
  97. }
  98. uint32_t WriteSpaceFirmware(RollbackSpaceFirmware *rsf)
  99. {
  100. RollbackSpaceFirmware rsf2;
  101. uint32_t r;
  102. int attempts = 3;
  103. /* All writes should use struct_version 2 or greater. */
  104. if (rsf->struct_version < 2)
  105. rsf->struct_version = 2;
  106. rsf->crc8 = vb2_crc8(rsf, offsetof(RollbackSpaceFirmware, crc8));
  107. while (attempts--) {
  108. r = SafeWrite(FIRMWARE_NV_INDEX, rsf,
  109. sizeof(RollbackSpaceFirmware));
  110. /* Can't write, not gonna try again */
  111. if (r != TPM_SUCCESS)
  112. return r;
  113. /* Read it back to be sure it got the right values. */
  114. r = ReadSpaceFirmware(&rsf2); /* This checks the CRC */
  115. if (r == TPM_SUCCESS)
  116. return r;
  117. VB2_DEBUG("TPM: bad CRC\n");
  118. /* Try writing it again. Maybe it was garbled on the way out. */
  119. }
  120. VB2_DEBUG("TPM: too many bad CRCs, giving up\n");
  121. return TPM_E_CORRUPTED_STATE;
  122. }
  123. uint32_t SetVirtualDevMode(int val)
  124. {
  125. RollbackSpaceFirmware rsf;
  126. VB2_DEBUG("TPM: Entering");
  127. if (TPM_SUCCESS != ReadSpaceFirmware(&rsf))
  128. return VBERROR_TPM_FIRMWARE_SETUP;
  129. VB2_DEBUG("TPM: flags were 0x%02x\n", rsf.flags);
  130. if (val)
  131. rsf.flags |= FLAG_VIRTUAL_DEV_MODE_ON;
  132. else
  133. rsf.flags &= ~FLAG_VIRTUAL_DEV_MODE_ON;
  134. /*
  135. * NOTE: This doesn't update the FLAG_LAST_BOOT_DEVELOPER bit. That
  136. * will be done on the next boot.
  137. */
  138. VB2_DEBUG("TPM: flags are now 0x%02x\n", rsf.flags);
  139. if (TPM_SUCCESS != WriteSpaceFirmware(&rsf))
  140. return VBERROR_TPM_SET_BOOT_MODE_STATE;
  141. VB2_DEBUG("TPM: Leaving\n");
  142. return VBERROR_SUCCESS;
  143. }
  144. uint32_t ReadSpaceKernel(RollbackSpaceKernel *rsk)
  145. {
  146. uint32_t r;
  147. int attempts = 3;
  148. while (attempts--) {
  149. r = TlclRead(KERNEL_NV_INDEX, rsk, sizeof(RollbackSpaceKernel));
  150. if (r != TPM_SUCCESS)
  151. return r;
  152. /*
  153. * No CRC in this version, so we'll create one when we write
  154. * it. Note that we're marking this as version 2, not
  155. * ROLLBACK_SPACE_KERNEL_VERSION, because version 2 just added
  156. * the CRC. Later versions will need to set default values for
  157. * any extra fields explicitly (probably here).
  158. */
  159. if (rsk->struct_version < 2) {
  160. /* Danger Will Robinson! Danger! */
  161. rsk->struct_version = 2;
  162. return TPM_SUCCESS;
  163. }
  164. /*
  165. * If the CRC is good, we're done. If it's bad, try a couple
  166. * more times to see if it gets better before we give up. It
  167. * could just be noise.
  168. */
  169. if (rsk->crc8 ==
  170. vb2_crc8(rsk, offsetof(RollbackSpaceKernel, crc8)))
  171. return TPM_SUCCESS;
  172. VB2_DEBUG("TPM: bad CRC\n");
  173. }
  174. VB2_DEBUG("TPM: too many bad CRCs, giving up\n");
  175. return TPM_E_CORRUPTED_STATE;
  176. }
  177. uint32_t WriteSpaceKernel(RollbackSpaceKernel *rsk)
  178. {
  179. RollbackSpaceKernel rsk2;
  180. uint32_t r;
  181. int attempts = 3;
  182. /* All writes should use struct_version 2 or greater. */
  183. if (rsk->struct_version < 2)
  184. rsk->struct_version = 2;
  185. rsk->crc8 = vb2_crc8(rsk, offsetof(RollbackSpaceKernel, crc8));
  186. while (attempts--) {
  187. r = SafeWrite(KERNEL_NV_INDEX, rsk,
  188. sizeof(RollbackSpaceKernel));
  189. /* Can't write, not gonna try again */
  190. if (r != TPM_SUCCESS)
  191. return r;
  192. /* Read it back to be sure it got the right values. */
  193. r = ReadSpaceKernel(&rsk2); /* This checks the CRC */
  194. if (r == TPM_SUCCESS)
  195. return r;
  196. VB2_DEBUG("TPM: bad CRC\n");
  197. /* Try writing it again. Maybe it was garbled on the way out. */
  198. }
  199. VB2_DEBUG("TPM: too many bad CRCs, giving up\n");
  200. return TPM_E_CORRUPTED_STATE;
  201. }
  202. #ifdef DISABLE_ROLLBACK_TPM
  203. /* Dummy implementations which don't support TPM rollback protection */
  204. uint32_t RollbackKernelRead(uint32_t* version)
  205. {
  206. *version = 0;
  207. return TPM_SUCCESS;
  208. }
  209. uint32_t RollbackKernelWrite(uint32_t version)
  210. {
  211. return TPM_SUCCESS;
  212. }
  213. uint32_t RollbackKernelLock(int recovery_mode)
  214. {
  215. return TPM_SUCCESS;
  216. }
  217. uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
  218. {
  219. memset(fwmp, 0, sizeof(*fwmp));
  220. return TPM_SUCCESS;
  221. }
  222. #else
  223. uint32_t RollbackKernelRead(uint32_t* version)
  224. {
  225. RollbackSpaceKernel rsk;
  226. /*
  227. * Read the kernel space and verify its permissions. If the kernel
  228. * space has the wrong permission, or it doesn't contain the right
  229. * identifier, we give up. This will need to be fixed by the
  230. * recovery kernel. We have to worry about this because at any time
  231. * (even with PP turned off) the TPM owner can remove and redefine a
  232. * PP-protected space (but not write to it).
  233. */
  234. RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
  235. #ifndef TPM2_MODE
  236. /*
  237. * TODO(vbendeb): restore this when it is defined how the kernel space
  238. * gets protected.
  239. */
  240. {
  241. uint32_t perms, uid;
  242. RETURN_ON_FAILURE(TlclGetPermissions(KERNEL_NV_INDEX, &perms));
  243. memcpy(&uid, &rsk.uid, sizeof(uid));
  244. if (TPM_NV_PER_PPWRITE != perms ||
  245. ROLLBACK_SPACE_KERNEL_UID != uid)
  246. return TPM_E_CORRUPTED_STATE;
  247. }
  248. #endif
  249. memcpy(version, &rsk.kernel_versions, sizeof(*version));
  250. VB2_DEBUG("TPM: RollbackKernelRead %x\n", (int)*version);
  251. return TPM_SUCCESS;
  252. }
  253. uint32_t RollbackKernelWrite(uint32_t version)
  254. {
  255. RollbackSpaceKernel rsk;
  256. uint32_t old_version;
  257. RETURN_ON_FAILURE(ReadSpaceKernel(&rsk));
  258. memcpy(&old_version, &rsk.kernel_versions, sizeof(old_version));
  259. VB2_DEBUG("TPM: RollbackKernelWrite %x --> %x\n",
  260. (int)old_version, (int)version);
  261. memcpy(&rsk.kernel_versions, &version, sizeof(version));
  262. return WriteSpaceKernel(&rsk);
  263. }
  264. uint32_t RollbackKernelLock(int recovery_mode)
  265. {
  266. static int kernel_locked = 0;
  267. uint32_t r;
  268. if (recovery_mode || kernel_locked)
  269. return TPM_SUCCESS;
  270. r = TlclLockPhysicalPresence();
  271. if (TPM_SUCCESS == r)
  272. kernel_locked = 1;
  273. return r;
  274. }
  275. uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
  276. {
  277. union {
  278. /*
  279. * Use a union for buf and bf, rather than making bf a pointer
  280. * to a bare uint8_t[] buffer. This ensures bf will be aligned
  281. * if necesssary for the target platform.
  282. */
  283. uint8_t buf[FWMP_NV_MAX_SIZE];
  284. struct RollbackSpaceFwmp bf;
  285. } u;
  286. uint32_t r;
  287. int attempts = 3;
  288. /* Clear destination in case error or FWMP not present */
  289. memset(fwmp, 0, sizeof(*fwmp));
  290. while (attempts--) {
  291. /* Try to read entire 1.0 struct */
  292. r = TlclRead(FWMP_NV_INDEX, u.buf, sizeof(u.bf));
  293. if (r == TPM_E_BADINDEX) {
  294. /* Missing space is not an error; use defaults */
  295. VB2_DEBUG("TPM: no FWMP space\n");
  296. return TPM_SUCCESS;
  297. } else if (r != TPM_SUCCESS) {
  298. VB2_DEBUG("TPM: read returned 0x%x\n", r);
  299. return r;
  300. }
  301. /*
  302. * Struct must be at least big enough for 1.0, but not bigger
  303. * than our buffer size.
  304. */
  305. if (u.bf.struct_size < sizeof(u.bf) ||
  306. u.bf.struct_size > sizeof(u.buf))
  307. return TPM_E_STRUCT_SIZE;
  308. /*
  309. * If space is bigger than we expect, re-read so we properly
  310. * compute the CRC.
  311. */
  312. if (u.bf.struct_size > sizeof(u.bf)) {
  313. r = TlclRead(FWMP_NV_INDEX, u.buf, u.bf.struct_size);
  314. if (r != TPM_SUCCESS)
  315. return r;
  316. }
  317. /* Verify CRC */
  318. if (u.bf.crc != vb2_crc8(u.buf + 2, u.bf.struct_size - 2)) {
  319. VB2_DEBUG("TPM: bad CRC\n");
  320. continue;
  321. }
  322. /* Verify major version is compatible */
  323. if ((u.bf.struct_version >> 4) !=
  324. (ROLLBACK_SPACE_FWMP_VERSION >> 4))
  325. return TPM_E_STRUCT_VERSION;
  326. /*
  327. * Copy to destination. Note that if the space is bigger than
  328. * we expect (due to a minor version change), we only copy the
  329. * part of the FWMP that we know what to do with.
  330. *
  331. * If this were a 1.1+ reader and the source was a 1.0 struct,
  332. * we would need to take care of initializing the extra fields
  333. * added in 1.1+. But that's not an issue yet.
  334. */
  335. memcpy(fwmp, &u.bf, sizeof(*fwmp));
  336. return TPM_SUCCESS;
  337. }
  338. VB2_DEBUG("TPM: too many bad CRCs, giving up\n");
  339. return TPM_E_CORRUPTED_STATE;
  340. }
  341. #endif /* DISABLE_ROLLBACK_TPM */