tpm2_flushcontext.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <stdlib.h>
  3. #include "log.h"
  4. #include "object.h"
  5. #include "tpm2.h"
  6. #include "tpm2_tool.h"
  7. #include "tpm2_capability.h"
  8. #include "tpm2_options.h"
  9. struct tpm_flush_context_ctx {
  10. TPM2_HANDLE property;
  11. char *context_arg;
  12. unsigned encountered_option;
  13. };
  14. static struct tpm_flush_context_ctx ctx;
  15. static const char *get_property_name(TPM2_HANDLE handle) {
  16. switch (handle & TPM2_HR_RANGE_MASK) {
  17. case TPM2_HR_TRANSIENT:
  18. return "transient";
  19. case TPM2_HT_LOADED_SESSION << TPM2_HR_SHIFT:
  20. return "loaded session";
  21. case TPM2_HT_SAVED_SESSION << TPM2_HR_SHIFT:
  22. return "saved session";
  23. }
  24. return "invalid";
  25. }
  26. static tool_rc flush_contexts_tpm2(ESYS_CONTEXT *ectx, TPM2_HANDLE handles[],
  27. UINT32 count) {
  28. UINT32 i;
  29. for (i = 0; i < count; ++i) {
  30. ESYS_TR handle;
  31. tool_rc rc = tpm2_util_sys_handle_to_esys_handle(ectx, handles[i],
  32. &handle);
  33. if (rc != tool_rc_success) {
  34. return rc;
  35. }
  36. rc = tpm2_flush_context(ectx, handle);
  37. if (rc != tool_rc_success) {
  38. LOG_ERR("Failed Flush Context for %s handle 0x%x",
  39. get_property_name(handles[i]), handles[i]);
  40. return rc;
  41. }
  42. }
  43. return tool_rc_success;
  44. }
  45. static bool flush_contexts_tr(ESYS_CONTEXT *ectx, ESYS_TR handles[],
  46. UINT32 count) {
  47. UINT32 i;
  48. for (i = 0; i < count; ++i) {
  49. tool_rc rc = tpm2_flush_context(ectx, handles[i]);
  50. if (rc != tool_rc_success) {
  51. return rc;
  52. }
  53. }
  54. return tool_rc_success;
  55. }
  56. static bool on_option(char key, char *value) {
  57. UNUSED(value);
  58. if (ctx.encountered_option) {
  59. LOG_ERR("Options -t, -l and -s are mutually exclusive");
  60. return false;
  61. }
  62. ctx.encountered_option = true;
  63. switch (key) {
  64. case 't':
  65. ctx.property = TPM2_TRANSIENT_FIRST;
  66. break;
  67. case 'l':
  68. ctx.property = TPM2_LOADED_SESSION_FIRST;
  69. break;
  70. case 's':
  71. ctx.property = TPM2_ACTIVE_SESSION_FIRST;
  72. break;
  73. }
  74. return true;
  75. }
  76. static bool on_arg(int argc, char *argv[]) {
  77. if (ctx.encountered_option && argc != 0) {
  78. LOG_ERR("Options are mutually exclusive of an argument");
  79. return false;
  80. }
  81. ctx.context_arg = argv[0];
  82. return true;
  83. }
  84. static bool tpm2_tool_onstart(tpm2_options **opts) {
  85. static const struct option topts[] = {
  86. { "transient-object", no_argument, NULL, 't' },
  87. { "loaded-session", no_argument, NULL, 'l' },
  88. { "saved-session", no_argument, NULL, 's' },
  89. };
  90. *opts = tpm2_options_new("tls", ARRAY_LEN(topts), topts, on_option, on_arg,
  91. 0);
  92. return *opts != NULL;
  93. }
  94. static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
  95. UNUSED(flags);
  96. if (ctx.property) {
  97. TPMS_CAPABILITY_DATA *capability_data;
  98. tool_rc rc = tpm2_capability_get(ectx, TPM2_CAP_HANDLES, ctx.property,
  99. TPM2_MAX_CAP_HANDLES, &capability_data);
  100. if (rc != tool_rc_success) {
  101. return rc;
  102. }
  103. TPML_HANDLE *handles = &capability_data->data.handles;
  104. rc = flush_contexts_tpm2(ectx, handles->handle, handles->count);
  105. free(capability_data);
  106. return rc;
  107. }
  108. if (!ctx.context_arg) {
  109. LOG_ERR("Specify options to evict handles or a session context.");
  110. return tool_rc_option_error;
  111. }
  112. TPM2_HANDLE handle;
  113. bool result = tpm2_util_string_to_uint32(ctx.context_arg, &handle);
  114. if (!result) {
  115. /* hmm not a handle, try a session */
  116. tpm2_session *s = NULL;
  117. tool_rc rc = tpm2_session_restore(ectx, ctx.context_arg, true, &s);
  118. if (rc != tool_rc_success) {
  119. return rc;
  120. }
  121. tpm2_session_close(&s);
  122. return tool_rc_success;
  123. }
  124. /* its a handle, call flush */
  125. ESYS_TR tr_handle = ESYS_TR_NONE;
  126. tool_rc rc = tpm2_util_sys_handle_to_esys_handle(ectx, handle, &tr_handle);
  127. if (rc != tool_rc_success) {
  128. return rc;
  129. }
  130. return flush_contexts_tr(ectx, &tr_handle, 1);
  131. }
  132. // Register this tool with tpm2_tool.c
  133. TPM2_TOOL_REGISTER("flushcontext", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL)