tpm2_hierarchycontrol.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <string.h>
  3. #include <log.h>
  4. #include <tpm2.h>
  5. #include "tpm2_tool.h"
  6. #include "files.h"
  7. typedef struct hierarchycontrol_ctx hierarchycontrol_ctx;
  8. struct hierarchycontrol_ctx {
  9. struct {
  10. const char *ctx_path;
  11. const char *auth_str;
  12. tpm2_loaded_object object;
  13. } auth_hierarchy;
  14. TPMI_RH_ENABLES enable;
  15. TPMI_YES_NO state;
  16. char *cp_hash_path;
  17. };
  18. static hierarchycontrol_ctx ctx = {
  19. .auth_hierarchy.ctx_path = "p",
  20. };
  21. static tool_rc hierarchycontrol(ESYS_CONTEXT *ectx) {
  22. if (ctx.cp_hash_path) {
  23. TPM2B_DIGEST cp_hash = { .size = 0 };
  24. tool_rc rc = tpm2_hierarchycontrol(ectx, &ctx.auth_hierarchy.object,
  25. ctx.enable, ctx.state, &cp_hash);
  26. if (rc == tool_rc_success) {
  27. bool result = files_save_digest(&cp_hash, ctx.cp_hash_path);
  28. if (!result) {
  29. LOG_ERR("Failed to save cp hash");
  30. rc = tool_rc_general_error;
  31. }
  32. }
  33. return rc;
  34. }
  35. LOG_INFO ("Using hierarchy %s to \'%s\' TPMA_STARTUP_CLEAR bit (%s)",
  36. ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_OWNER ? "TPM2_RH_OWNER" :
  37. ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_ENDORSEMENT ? "TPM2_RH_ENDORSEMENT" :
  38. ctx.auth_hierarchy.object.tr_handle == ESYS_TR_RH_PLATFORM ? "TPM2_RH_PLATFORM" : "TPM2_RH_PLATFORM_NV",
  39. ctx.enable == TPM2_RH_PLATFORM ? "phEnable" :
  40. ctx.enable == TPM2_RH_OWNER ? "shEnable" :
  41. ctx.enable == TPM2_RH_ENDORSEMENT ? "ehEnable" : "phEnableNV",
  42. ctx.state ? "SET" : "CLEAR");
  43. tool_rc rc = tpm2_hierarchycontrol(ectx, &ctx.auth_hierarchy.object,
  44. ctx.enable, ctx.state, NULL);
  45. if (rc != tool_rc_success) {
  46. LOG_ERR("Failed hierarchycontrol operation.");
  47. }
  48. return rc;
  49. }
  50. static bool on_arg(int argc, char **argv) {
  51. switch (argc) {
  52. case 2:
  53. break;
  54. default:
  55. return false;
  56. }
  57. if (!strcmp(argv[0], "phEnable")) {
  58. ctx.enable = TPM2_RH_PLATFORM;
  59. } else if (!strcmp(argv[0], "shEnable")) {
  60. ctx.enable = TPM2_RH_OWNER;
  61. } else if (!strcmp(argv[0], "ehEnable")) {
  62. ctx.enable = TPM2_RH_ENDORSEMENT;
  63. } else if (!strcmp(argv[0], "phEnableNV")) {
  64. ctx.enable = TPM2_RH_PLATFORM_NV;
  65. } else {
  66. LOG_ERR("Incorrect property, got: \"%s\", expected "
  67. "[phEnable|shEnable|ehEnable|phEnableNV]", argv[0]);
  68. return false;
  69. }
  70. if (!strcmp(argv[1], "set")) {
  71. ctx.state = TPM2_YES;
  72. } else if (!strcmp(argv[1], "clear")) {
  73. ctx.state = TPM2_NO;
  74. } else {
  75. LOG_ERR("Incorrect operation, got: \"%s\", expected [set|clear].",
  76. argv[1]);
  77. return false;
  78. }
  79. return true;
  80. }
  81. static bool on_option(char key, char *value) {
  82. switch (key) {
  83. case 'C':
  84. ctx.auth_hierarchy.ctx_path = value;
  85. break;
  86. case 'P':
  87. ctx.auth_hierarchy.auth_str = value;
  88. break;
  89. case 0:
  90. ctx.cp_hash_path = value;
  91. break;
  92. }
  93. return true;
  94. }
  95. static bool tpm2_tool_onstart(tpm2_options **opts) {
  96. const struct option topts[] = {
  97. { "hierarchy", required_argument, NULL, 'C' },
  98. { "hierarchy-auth", required_argument, NULL, 'P' },
  99. { "cphash", required_argument, NULL, 0 },
  100. };
  101. *opts = tpm2_options_new("C:P:", ARRAY_LEN(topts), topts, on_option, on_arg,
  102. 0);
  103. return *opts != NULL;
  104. }
  105. static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
  106. UNUSED(flags);
  107. tool_rc rc = tpm2_util_object_load_auth(ectx, ctx.auth_hierarchy.ctx_path,
  108. ctx.auth_hierarchy.auth_str, &ctx.auth_hierarchy.object, false,
  109. TPM2_HANDLE_FLAGS_P | TPM2_HANDLE_FLAGS_O | TPM2_HANDLE_FLAGS_E);
  110. if (rc != tool_rc_success) {
  111. LOG_ERR("Invalid authorization");
  112. return rc;
  113. }
  114. if (ctx.state == TPM2_YES) {
  115. switch (ctx.enable) {
  116. case TPM2_RH_PLATFORM:
  117. LOG_ERR("phEnable may not be SET using this command");
  118. return tool_rc_tcti_error;
  119. case TPM2_RH_OWNER:
  120. case TPM2_RH_ENDORSEMENT:
  121. case TPM2_RH_PLATFORM_NV:
  122. if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) {
  123. LOG_ERR("Only platform hierarchy handle can be specified for "
  124. "SET \'%s\' bit",
  125. ctx.enable == TPM2_RH_OWNER ? "shEnable" :
  126. ctx.enable == TPM2_RH_ENDORSEMENT ? "ehEnable" :
  127. ctx.enable == TPM2_RH_PLATFORM_NV ?
  128. "phEnableNV" : "NONE");
  129. return tool_rc_auth_error;
  130. }
  131. break;
  132. default:
  133. LOG_ERR("Unknown permanent handle, got: \"0x%x\"", ctx.enable);
  134. return tool_rc_unsupported;
  135. }
  136. } else {
  137. switch (ctx.enable) {
  138. case TPM2_RH_PLATFORM:
  139. if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM) {
  140. LOG_ERR("Only platform hierarchy handle can be specified for "
  141. "CLEAR \'phEnable\' bit");
  142. return tool_rc_general_error;
  143. }
  144. break;
  145. case TPM2_RH_OWNER:
  146. if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_OWNER
  147. && ctx.auth_hierarchy.object.tr_handle
  148. != ESYS_TR_RH_PLATFORM) {
  149. LOG_ERR("Only platform and owner hierarchy handle can be "
  150. "specified for CLEAR \'shEnable\' bit");
  151. return tool_rc_auth_error;
  152. }
  153. break;
  154. case TPM2_RH_ENDORSEMENT:
  155. if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_ENDORSEMENT
  156. && ctx.auth_hierarchy.object.tr_handle
  157. != ESYS_TR_RH_PLATFORM) {
  158. LOG_ERR(
  159. "Only platform and endorsement hierarchy handle can be "
  160. "specified for CLEAR \'ehEnable\' bit");
  161. return tool_rc_auth_error;
  162. }
  163. break;
  164. case TPM2_RH_PLATFORM_NV:
  165. if (ctx.auth_hierarchy.object.tr_handle != ESYS_TR_RH_PLATFORM_NV
  166. && ctx.auth_hierarchy.object.tr_handle
  167. != ESYS_TR_RH_PLATFORM) {
  168. LOG_ERR(
  169. "Only platform hierarchy handle can be specified for "
  170. "CLEAR \'phEnableNV\' bit");
  171. return tool_rc_auth_error;
  172. }
  173. break;
  174. default:
  175. LOG_ERR("Unknown permanent handle, got: \"0x%x\"", ctx.enable);
  176. return tool_rc_unsupported;
  177. }
  178. }
  179. return hierarchycontrol(ectx);
  180. }
  181. static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) {
  182. UNUSED(ectx);
  183. return tpm2_session_close(&ctx.auth_hierarchy.object.session);
  184. }
  185. // Register this tool with tpm2_tool.c
  186. TPM2_TOOL_REGISTER("hierarchycontrol", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL)