tpm2_pcrread.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "log.h"
  6. #include "pcr.h"
  7. #include "tpm2_alg_util.h"
  8. #include "tpm2_tool.h"
  9. typedef struct listpcr_context listpcr_context;
  10. struct listpcr_context {
  11. char *output_file_path;
  12. FILE *output_file;
  13. tpm2_algorithm algs;
  14. tpm2_pcrs pcrs;
  15. TPML_PCR_SELECTION pcr_selections;
  16. TPMI_ALG_HASH selected_algorithm;
  17. };
  18. static listpcr_context ctx;
  19. // show all PCR banks according to g_pcrSelection & g_pcrs->
  20. static bool print_pcr_values(void) {
  21. UINT32 vi = 0, di = 0, i;
  22. for (i = 0; i < ctx.pcr_selections.count; i++) {
  23. const char *alg_name = tpm2_alg_util_algtostr(
  24. ctx.pcr_selections.pcrSelections[i].hash,
  25. tpm2_alg_util_flags_hash);
  26. tpm2_tool_output("%s:\n", alg_name);
  27. unsigned int pcr_id;
  28. for (pcr_id = 0;
  29. pcr_id < ctx.pcr_selections.pcrSelections[i].sizeofSelect * 8u;
  30. pcr_id++) {
  31. if (!tpm2_util_is_pcr_select_bit_set(
  32. &ctx.pcr_selections.pcrSelections[i], pcr_id)) {
  33. continue;
  34. }
  35. if (vi >= ctx.pcrs.count || di >= ctx.pcrs.pcr_values[vi].count) {
  36. LOG_ERR("Something wrong, trying to print but nothing more");
  37. return false;
  38. }
  39. tpm2_tool_output(" %-2d: 0x", pcr_id);
  40. int k;
  41. for (k = 0; k < ctx.pcrs.pcr_values[vi].digests[di].size; k++) {
  42. tpm2_tool_output("%02X",
  43. ctx.pcrs.pcr_values[vi].digests[di].buffer[k]);
  44. }
  45. tpm2_tool_output("\n");
  46. if (ctx.output_file != NULL
  47. && fwrite(ctx.pcrs.pcr_values[vi].digests[di].buffer,
  48. ctx.pcrs.pcr_values[vi].digests[di].size,
  49. required_argument, ctx.output_file) != 1) {
  50. LOG_ERR("write to output file failed: %s", strerror(errno));
  51. return false;
  52. }
  53. if (++di < ctx.pcrs.pcr_values[vi].count) {
  54. continue;
  55. }
  56. di = 0;
  57. if (++vi < ctx.pcrs.count) {
  58. continue;
  59. }
  60. }
  61. }
  62. return true;
  63. }
  64. static tool_rc show_pcr_list_selected_values(ESYS_CONTEXT *esys_context,
  65. TPMS_CAPABILITY_DATA *capdata,
  66. bool check) {
  67. if (check && !pcr_check_pcr_selection(capdata, &ctx.pcr_selections)) {
  68. return tool_rc_general_error;
  69. }
  70. tool_rc rc = pcr_read_pcr_values(esys_context, &ctx.pcr_selections,
  71. &ctx.pcrs);
  72. if (rc != tool_rc_success) {
  73. return rc;
  74. }
  75. return print_pcr_values() ? tool_rc_success : tool_rc_general_error;
  76. }
  77. static tool_rc show_pcr_alg_or_all_values(ESYS_CONTEXT *esys_context,
  78. TPMS_CAPABILITY_DATA *capdata) {
  79. bool res = pcr_init_pcr_selection(capdata, &ctx.pcr_selections,
  80. ctx.selected_algorithm);
  81. if (!res) {
  82. return tool_rc_general_error;
  83. }
  84. return show_pcr_list_selected_values(esys_context, capdata, false);
  85. }
  86. static bool on_option(char key, char *value) {
  87. switch (key) {
  88. case 'o':
  89. ctx.output_file_path = value;
  90. break;
  91. /* no default */
  92. }
  93. return true;
  94. }
  95. static bool on_arg(int argc, char *argv[]) {
  96. if (argc != 1) {
  97. LOG_ERR("Expected PCR list or algorithm selection");
  98. return false;
  99. }
  100. ctx.selected_algorithm = tpm2_alg_util_from_optarg(argv[0],
  101. tpm2_alg_util_flags_hash);
  102. if (ctx.selected_algorithm == TPM2_ALG_ERROR) {
  103. bool res = pcr_parse_selections(argv[0], &ctx.pcr_selections);
  104. if (!res) {
  105. LOG_ERR("Neither algorithm nor pcr list, got: \"%s\"", argv[0]);
  106. return false;
  107. }
  108. }
  109. return true;
  110. }
  111. static bool tpm2_tool_onstart(tpm2_options **opts) {
  112. static struct option topts[] = {
  113. { "output", required_argument, NULL, 'o' },
  114. };
  115. *opts = tpm2_options_new("o:", ARRAY_LEN(topts), topts, on_option, on_arg,
  116. 0);
  117. return *opts != NULL;
  118. }
  119. static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *esys_context, tpm2_option_flags flags) {
  120. UNUSED(flags);
  121. if (ctx.output_file_path) {
  122. ctx.output_file = fopen(ctx.output_file_path, "wb+");
  123. if (!ctx.output_file) {
  124. LOG_ERR("Could not open output file \"%s\" error: \"%s\"",
  125. ctx.output_file_path, strerror(errno));
  126. return tool_rc_general_error;
  127. }
  128. }
  129. TPMS_CAPABILITY_DATA capdata;
  130. tool_rc rc = pcr_get_banks(esys_context, &capdata, &ctx.algs);
  131. if (rc != tool_rc_success) {
  132. return rc;
  133. }
  134. if (ctx.pcr_selections.count > 0) {
  135. return show_pcr_list_selected_values(esys_context, &capdata, true);
  136. }
  137. return show_pcr_alg_or_all_values(esys_context, &capdata);
  138. }
  139. static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *esys_context) {
  140. UNUSED(esys_context);
  141. if (ctx.output_file) {
  142. fclose(ctx.output_file);
  143. }
  144. return tool_rc_success;
  145. }
  146. // Register this tool with tpm2_tool.c
  147. TPM2_TOOL_REGISTER("pcrread", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL)