tpm2_eventlog.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  1. #include <inttypes.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <tss2/tss2_tpm2_types.h>
  5. #include "log.h"
  6. #include "efi_event.h"
  7. #include "tpm2_alg_util.h"
  8. #include "tpm2_eventlog.h"
  9. #include "tpm2_openssl.h"
  10. bool digest2_accumulator_callback(TCG_DIGEST2 const *digest, size_t size,
  11. void *data){
  12. if (digest == NULL || data == NULL) {
  13. LOG_ERR("neither parameter may be NULL");
  14. return false;
  15. }
  16. size_t *accumulator = (size_t*)data;
  17. *accumulator += sizeof(*digest) + size;
  18. return true;
  19. }
  20. /*
  21. * Invoke callback function for each TCG_DIGEST2 structure in the provided
  22. * TCG_EVENT_HEADER2. The callback function is only invoked if this function
  23. * is first able to determine that the provided buffer is large enough to
  24. * hold the digest. The size of the digest is passed to the callback in the
  25. * 'size' parameter.
  26. */
  27. bool foreach_digest2(tpm2_eventlog_context *ctx, unsigned pcr_index, TCG_DIGEST2 const *digest, size_t count, size_t size) {
  28. if (digest == NULL) {
  29. LOG_ERR("digest cannot be NULL");
  30. return false;
  31. }
  32. /* Because pcr_index is used for array indexing and bit-shift operations it
  33. is 1 less than the max value */
  34. if (pcr_index > (TPM2_MAX_PCRS - 1)) {
  35. LOG_ERR("PCR Index %d is out of bounds for max available PCRS %d",
  36. pcr_index, TPM2_MAX_PCRS);
  37. return false;
  38. }
  39. bool ret = true;
  40. size_t i;
  41. for (i = 0; i < count; ++i) {
  42. if (size < sizeof(*digest)) {
  43. LOG_ERR("insufficient size for digest header");
  44. return false;
  45. }
  46. const TPMI_ALG_HASH alg = digest->AlgorithmId;
  47. const size_t alg_size = tpm2_alg_util_get_hash_size(alg);
  48. if (size < sizeof(*digest) + alg_size) {
  49. LOG_ERR("insufficient size for digest buffer");
  50. return false;
  51. }
  52. uint8_t *pcr = NULL;
  53. if (alg == TPM2_ALG_SHA1) {
  54. pcr = ctx->sha1_pcrs[pcr_index];
  55. ctx->sha1_used |= (1 << pcr_index);
  56. } else if (alg == TPM2_ALG_SHA256) {
  57. pcr = ctx->sha256_pcrs[pcr_index];
  58. ctx->sha256_used |= (1 << pcr_index);
  59. } else if (alg == TPM2_ALG_SHA384) {
  60. pcr = ctx->sha384_pcrs[pcr_index];
  61. ctx->sha384_used |= (1 << pcr_index);
  62. } else if (alg == TPM2_ALG_SHA512) {
  63. pcr = ctx->sha512_pcrs[pcr_index];
  64. ctx->sha512_used |= (1 << pcr_index);
  65. } else if (alg == TPM2_ALG_SM3_256) {
  66. pcr = ctx->sm3_256_pcrs[pcr_index];
  67. ctx->sm3_256_used |= (1 << pcr_index);
  68. } else {
  69. LOG_WARN("PCR%d algorithm %d unsupported", pcr_index, alg);
  70. }
  71. if (pcr && !tpm2_openssl_pcr_extend(alg, pcr, digest->Digest, alg_size)) {
  72. LOG_ERR("PCR%d extend failed", pcr_index);
  73. return false;
  74. }
  75. if (ctx->digest2_cb != NULL) {
  76. ret = ctx->digest2_cb(digest, alg_size, ctx->data);
  77. if (!ret) {
  78. LOG_ERR("callback failed for digest at %p with size %zu", digest, alg_size);
  79. break;
  80. }
  81. }
  82. size -= sizeof(*digest) + alg_size;
  83. digest = (TCG_DIGEST2*)((uintptr_t)digest->Digest + alg_size);
  84. }
  85. return ret;
  86. }
  87. /*
  88. * given the provided event type, parse event to ensure the structure / data
  89. * in the buffer doesn't exceed the buffer size
  90. */
  91. bool parse_event2body(TCG_EVENT2 const *event, UINT32 type) {
  92. switch (type) {
  93. /* TCG PC Client FPF section 9.2.6 */
  94. case EV_EFI_VARIABLE_DRIVER_CONFIG:
  95. case EV_EFI_VARIABLE_BOOT:
  96. case EV_EFI_VARIABLE_AUTHORITY:
  97. {
  98. UEFI_VARIABLE_DATA *data = (UEFI_VARIABLE_DATA*)event->Event;
  99. if (event->EventSize < sizeof(*data)) {
  100. LOG_ERR("size is insufficient for UEFI variable data");
  101. return false;
  102. }
  103. if (event->EventSize < sizeof(*data) + data->UnicodeNameLength *
  104. sizeof(char16_t) + data->VariableDataLength)
  105. {
  106. LOG_ERR("size is insufficient for UEFI variable data");
  107. return false;
  108. }
  109. }
  110. break;
  111. /* TCG PC Client FPF section 2.3.4.1 and 9.4.1 */
  112. case EV_POST_CODE:
  113. // the event is a string, so there are no length requirements.
  114. break;
  115. /* TCG PC Client FPF section 9.2.5 */
  116. case EV_S_CRTM_CONTENTS:
  117. case EV_EFI_PLATFORM_FIRMWARE_BLOB:
  118. {
  119. UEFI_PLATFORM_FIRMWARE_BLOB *data =
  120. (UEFI_PLATFORM_FIRMWARE_BLOB*)event->Event;
  121. UNUSED(data);
  122. if (event->EventSize < sizeof(*data)) {
  123. LOG_ERR("size is insufficient for UEFI FW blob data");
  124. return false;
  125. }
  126. }
  127. break;
  128. case EV_EFI_BOOT_SERVICES_APPLICATION:
  129. case EV_EFI_BOOT_SERVICES_DRIVER:
  130. case EV_EFI_RUNTIME_SERVICES_DRIVER:
  131. {
  132. UEFI_IMAGE_LOAD_EVENT *data = (UEFI_IMAGE_LOAD_EVENT*)event->Event;
  133. UNUSED(data);
  134. if (event->EventSize < sizeof(*data)) {
  135. LOG_ERR("size is insufficient for UEFI image load event");
  136. return false;
  137. }
  138. /* what about the device path? */
  139. }
  140. break;
  141. }
  142. return true;
  143. }
  144. /*
  145. * parse event structure, including header, digests and event buffer ensuring
  146. * it all fits within the provided buffer (buf_size).
  147. */
  148. bool parse_event2(TCG_EVENT_HEADER2 const *eventhdr, size_t buf_size,
  149. size_t *event_size, size_t *digests_size) {
  150. bool ret;
  151. if (buf_size < sizeof(*eventhdr)) {
  152. LOG_ERR("corrupted log, insufficient size for event header: %zu", buf_size);
  153. return false;
  154. }
  155. *event_size = sizeof(*eventhdr);
  156. tpm2_eventlog_context ctx = {
  157. .data = digests_size,
  158. .digest2_cb = digest2_accumulator_callback,
  159. };
  160. ret = foreach_digest2(&ctx, eventhdr->PCRIndex,
  161. eventhdr->Digests, eventhdr->DigestCount,
  162. buf_size - sizeof(*eventhdr));
  163. if (ret != true) {
  164. return false;
  165. }
  166. *event_size += *digests_size;
  167. TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)eventhdr + *event_size);
  168. if (buf_size < *event_size + sizeof(*event)) {
  169. LOG_ERR("corrupted log: size insufficient for EventSize");
  170. return false;
  171. }
  172. *event_size += sizeof(*event);
  173. if (buf_size < *event_size + event->EventSize) {
  174. LOG_ERR("size insufficient for event data");
  175. return false;
  176. }
  177. *event_size += event->EventSize;
  178. return true;
  179. }
  180. bool parse_sha1_log_event(tpm2_eventlog_context *ctx, TCG_EVENT const *event, size_t size,
  181. size_t *event_size) {
  182. uint8_t *pcr = NULL;
  183. /* enough size for the 1.2 event structure */
  184. if (size < sizeof(*event)) {
  185. LOG_ERR("insufficient size for SpecID event header");
  186. return false;
  187. }
  188. *event_size = sizeof(*event);
  189. pcr = ctx->sha1_pcrs[ event->pcrIndex];
  190. if (pcr) {
  191. tpm2_openssl_pcr_extend(TPM2_ALG_SHA1, pcr, &event->digest[0], 20);
  192. ctx->sha1_used |= (1 << event->pcrIndex);
  193. }
  194. /* buffer size must be sufficient to hold event and event data */
  195. if (size < sizeof(*event) + (sizeof(event->event[0]) *
  196. event->eventDataSize)) {
  197. LOG_ERR("insufficient size for SpecID event data");
  198. return false;
  199. }
  200. *event_size += event->eventDataSize;
  201. return true;
  202. }
  203. bool foreach_sha1_log_event(tpm2_eventlog_context *ctx, TCG_EVENT const *eventhdr_start, size_t size) {
  204. if (eventhdr_start == NULL) {
  205. LOG_ERR("invalid parameter");
  206. return false;
  207. }
  208. if (size == 0) {
  209. return true;
  210. }
  211. TCG_EVENT const *eventhdr;
  212. size_t event_size;
  213. bool ret;
  214. for (eventhdr = eventhdr_start, event_size = 0;
  215. size > 0;
  216. eventhdr = (TCG_EVENT*)((uintptr_t)eventhdr + event_size),
  217. size -= event_size) {
  218. ret = parse_sha1_log_event(ctx, eventhdr, size, &event_size);
  219. if (!ret) {
  220. return ret;
  221. }
  222. TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)&eventhdr->eventDataSize);
  223. /* event header callback */
  224. if (ctx->log_eventhdr_cb != NULL) {
  225. ret = ctx->log_eventhdr_cb(eventhdr, event_size, ctx->data);
  226. if (ret != true) {
  227. return false;
  228. }
  229. }
  230. ret = parse_event2body(event, eventhdr->eventType);
  231. if (ret != true) {
  232. return ret;
  233. }
  234. /* event data callback */
  235. if (ctx->event2_cb != NULL) {
  236. ret = ctx->event2_cb(event, eventhdr->eventType, ctx->data,
  237. ctx->eventlog_version);
  238. if (ret != true) {
  239. return false;
  240. }
  241. }
  242. }
  243. return true;
  244. }
  245. /*
  246. * For event types where digest can be verified from their event payload,
  247. * perform verification to ensure event payload was not tempered
  248. */
  249. bool verify_digests(size_t eventnum, TCG_EVENT_HEADER2 const *eventhdr, TCG_EVENT2 *event) {
  250. size_t i;
  251. TCG_DIGEST2 const *digest = eventhdr->Digests;
  252. UINT32 digest_count = eventhdr->DigestCount;
  253. UINT32 event_type = eventhdr->EventType;
  254. switch (event_type) {
  255. /* Digests of these event types are calculated directly from event->Event, thus can be verified */
  256. case EV_S_CRTM_VERSION:
  257. case EV_SEPARATOR:
  258. case EV_EFI_VARIABLE_DRIVER_CONFIG:
  259. case EV_EFI_GPT_EVENT:
  260. for (i = 0; i < digest_count; i++) {
  261. TPMI_ALG_HASH alg = digest->AlgorithmId;
  262. TPM2B_DIGEST calc_digest;
  263. bool result = tpm2_openssl_hash_compute_data(alg, event->Event,
  264. event->EventSize, &calc_digest);
  265. if (!result) {
  266. LOG_WARN("Event %zu: Cannot calculate hash value from data", eventnum - 1);
  267. return false;
  268. }
  269. size_t alg_size = tpm2_alg_util_get_hash_size(alg);
  270. if (memcmp(calc_digest.buffer, digest->Digest, alg_size) != 0) {
  271. LOG_WARN("Event %zu's digest does not match its payload", eventnum - 1);
  272. return false;
  273. }
  274. digest = (TCG_DIGEST2*)((uintptr_t)digest->Digest + alg_size);
  275. }
  276. break;
  277. /* Shim and grub use this event type for various tasks */
  278. case EV_IPL:
  279. /* PCR9: used to measure loaded kernel and initramfs images which cannot
  280. be verified from eventlog alone */
  281. if (eventhdr->PCRIndex == 9) {
  282. return true;
  283. }
  284. /* PCR14: used to measure MokList, MokListX, and MokSBState which cannot
  285. be verified from eventlog alone */
  286. if (eventhdr->PCRIndex == 14) {
  287. return true;
  288. }
  289. /* PCR8: used to measure grub and kernel command line */
  290. if (eventhdr->PCRIndex != 8) {
  291. LOG_WARN("Event %zu is unexpectedly not extending either PCR 8, 9, or 14", eventnum - 1);
  292. return false;
  293. }
  294. /* Digest is applied on the string between "^[a-zA-Z_]+:? " and EOL,
  295. * including or excluding the trailing NULL character */
  296. for (i = 0; i < digest_count; i++) {
  297. size_t j;
  298. for (j = 0; j < event->EventSize; j++) {
  299. if (event->Event[j] == ' ')
  300. break;
  301. }
  302. if (j + 1 >= event->EventSize || event->Event[event->EventSize - 1] != '\0') {
  303. LOG_WARN("Event %zu's event data is in unexpected format", eventnum - 1);
  304. return false;
  305. }
  306. TPM2B_DIGEST calc_digest;
  307. TPMI_ALG_HASH alg = digest->AlgorithmId;
  308. /* First try to calculate the hash excluding the trailing \0 */
  309. bool result = tpm2_openssl_hash_compute_data(alg,
  310. event->Event + (j + 1), event->EventSize - (j + 2), &calc_digest);
  311. if (!result) {
  312. LOG_WARN("Event %zu: Cannot calculate hash value from data", eventnum - 1);
  313. return false;
  314. }
  315. size_t alg_size = tpm2_alg_util_get_hash_size(alg);
  316. if (memcmp(calc_digest.buffer, digest->Digest, alg_size) != 0) {
  317. /* Next try to calculate the hash including the trailing \0 */
  318. bool result = tpm2_openssl_hash_compute_data(alg,
  319. event->Event + (j + 1), event->EventSize - (j + 1), &calc_digest);
  320. if (!result) {
  321. LOG_WARN("Event %zu: Cannot calculate hash value from data", eventnum - 1);
  322. return false;
  323. }
  324. if (memcmp(calc_digest.buffer, digest->Digest, alg_size) != 0) {
  325. LOG_WARN("Event %zu's digest does not match its payload", eventnum - 1);
  326. return false;
  327. }
  328. }
  329. digest = (TCG_DIGEST2*)((uintptr_t)digest->Digest + alg_size);
  330. }
  331. break;
  332. }
  333. return true;
  334. }
  335. bool foreach_event2(tpm2_eventlog_context *ctx, TCG_EVENT_HEADER2 const *eventhdr_start, size_t size) {
  336. if (eventhdr_start == NULL) {
  337. LOG_ERR("invalid parameter");
  338. return false;
  339. }
  340. if (size == 0) {
  341. return true;
  342. }
  343. TCG_EVENT_HEADER2 const *eventhdr;
  344. size_t event_size;
  345. bool ret;
  346. for (eventhdr = eventhdr_start, event_size = 0;
  347. size > 0;
  348. eventhdr = (TCG_EVENT_HEADER2*)((uintptr_t)eventhdr + event_size),
  349. size -= event_size) {
  350. size_t digests_size = 0;
  351. ret = parse_event2(eventhdr, size, &event_size, &digests_size);
  352. if (!ret) {
  353. return ret;
  354. }
  355. TCG_EVENT2 *event = (TCG_EVENT2*)((uintptr_t)eventhdr->Digests + digests_size);
  356. /* event header callback */
  357. if (ctx->event2hdr_cb != NULL) {
  358. ret = ctx->event2hdr_cb(eventhdr, event_size, ctx->data);
  359. if (ret != true) {
  360. return false;
  361. }
  362. }
  363. /* digest callback foreach digest */
  364. ret = foreach_digest2(ctx, eventhdr->PCRIndex, eventhdr->Digests, eventhdr->DigestCount, digests_size);
  365. if (ret != true) {
  366. return false;
  367. }
  368. ret = parse_event2body(event, eventhdr->EventType);
  369. if (ret != true) {
  370. return ret;
  371. }
  372. /* digest verification */
  373. if (ctx->data != 0) {
  374. verify_digests(*(size_t*)ctx->data, eventhdr, event);
  375. }
  376. /* event data callback */
  377. if (ctx->event2_cb != NULL) {
  378. ret = ctx->event2_cb(event, eventhdr->EventType, ctx->data, ctx->eventlog_version);
  379. if (ret != true) {
  380. return false;
  381. }
  382. }
  383. }
  384. return true;
  385. }
  386. bool specid_event(TCG_EVENT const *event, size_t size,
  387. TCG_EVENT_HEADER2 **next) {
  388. /* enough size for the 1.2 event structure */
  389. if (size < sizeof(*event)) {
  390. LOG_ERR("insufficient size for SpecID event header");
  391. return false;
  392. }
  393. if (event->eventType != EV_NO_ACTION) {
  394. LOG_ERR("SpecID eventType must be EV_NO_ACTION");
  395. return false;
  396. }
  397. if (event->pcrIndex != 0) {
  398. LOG_ERR("bad pcrIndex for EV_NO_ACTION event");
  399. return false;
  400. }
  401. size_t i;
  402. for (i = 0; i < sizeof(event->digest); ++i) {
  403. if (event->digest[i] != 0) {
  404. LOG_ERR("SpecID digest data malformed");
  405. return false;
  406. }
  407. }
  408. /* eventDataSize must be sufficient to hold the specid event */
  409. if (event->eventDataSize < sizeof(TCG_SPECID_EVENT)) {
  410. LOG_ERR("invalid eventDataSize in specid event");
  411. return false;
  412. }
  413. /* buffer size must be sufficient to hold event and event data */
  414. if (size < sizeof(*event) + (sizeof(event->event[0]) *
  415. event->eventDataSize)) {
  416. LOG_ERR("insufficient size for SpecID event data");
  417. return false;
  418. }
  419. /* specid event must have 1 or more algorithms */
  420. TCG_SPECID_EVENT *event_specid = (TCG_SPECID_EVENT*)event->event;
  421. if (event_specid->numberOfAlgorithms == 0) {
  422. LOG_ERR("numberOfAlgorithms is invalid, may not be 0");
  423. return false;
  424. }
  425. /* buffer size must be sufficient to hold event, specid event & algs */
  426. if (size < sizeof(*event) + sizeof(*event_specid) +
  427. sizeof(event_specid->digestSizes[0]) *
  428. event_specid->numberOfAlgorithms) {
  429. LOG_ERR("insufficient size for SpecID algorithms");
  430. return false;
  431. }
  432. /* size must be sufficient for event, specid, algs & vendor stuff */
  433. if (size < sizeof(*event) + sizeof(*event_specid) +
  434. sizeof(event_specid->digestSizes[0]) *
  435. event_specid->numberOfAlgorithms + sizeof(TCG_VENDOR_INFO)) {
  436. LOG_ERR("insufficient size for VendorStuff");
  437. return false;
  438. }
  439. TCG_VENDOR_INFO *vendor = (TCG_VENDOR_INFO*)((uintptr_t)event_specid->digestSizes +
  440. sizeof(*event_specid->digestSizes) *
  441. event_specid->numberOfAlgorithms);
  442. /* size must be sufficient for vendorInfo */
  443. if (size < sizeof(*event) + sizeof(*event_specid) +
  444. sizeof(event_specid->digestSizes[0]) *
  445. event_specid->numberOfAlgorithms + sizeof(*vendor) +
  446. vendor->vendorInfoSize) {
  447. LOG_ERR("insufficient size for VendorStuff data");
  448. return false;
  449. }
  450. *next = (TCG_EVENT_HEADER2*)((uintptr_t)vendor->vendorInfo + vendor->vendorInfoSize);
  451. return true;
  452. }
  453. bool parse_eventlog(tpm2_eventlog_context *ctx, BYTE const *eventlog, size_t size) {
  454. if(!eventlog) {
  455. return false;
  456. }
  457. if(size < sizeof(TCG_EVENT)) {
  458. return false;
  459. }
  460. TCG_EVENT *event = (TCG_EVENT*)eventlog;
  461. if (event->eventType == EV_NO_ACTION) {
  462. TCG_EVENT_HEADER2 *next;
  463. bool ret = specid_event(event, size, &next);
  464. if (!ret) {
  465. return false;
  466. }
  467. size -= (uintptr_t)next - (uintptr_t)eventlog;
  468. if (ctx->specid_cb) {
  469. ret = ctx->specid_cb(event, ctx->data);
  470. if (!ret) {
  471. return false;
  472. }
  473. }
  474. return foreach_event2(ctx, next, size);
  475. }
  476. /* No specid event found. sha1 log format will be parsed. */
  477. return foreach_sha1_log_event(ctx, event, size);
  478. }