tpm2_load.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <stdlib.h>
  3. #include "files.h"
  4. #include "log.h"
  5. #include "tpm2.h"
  6. #include "tpm2_options.h"
  7. #include "tpm2_tool.h"
  8. typedef struct tpm_load_ctx tpm_load_ctx;
  9. struct tpm_load_ctx {
  10. struct {
  11. const char *ctx_path;
  12. const char *auth_str;
  13. tpm2_loaded_object object;
  14. } parent;
  15. struct {
  16. const char *pubpath;
  17. TPM2B_PUBLIC public;
  18. const char *privpath;
  19. TPM2B_PRIVATE private;
  20. ESYS_TR handle;
  21. } object;
  22. const char *namepath;
  23. const char *contextpath;
  24. char *cp_hash_path;
  25. };
  26. static tpm_load_ctx ctx;
  27. static bool on_option(char key, char *value) {
  28. switch (key) {
  29. case 'P':
  30. ctx.parent.auth_str = value;
  31. break;
  32. case 'u':
  33. ctx.object.pubpath = value;
  34. break;
  35. case 'r':
  36. ctx.object.privpath = value;
  37. break;
  38. case 'n':
  39. ctx.namepath = value;
  40. break;
  41. case 'C':
  42. ctx.parent.ctx_path = value;
  43. break;
  44. case 'c':
  45. ctx.contextpath = value;
  46. break;
  47. case 0:
  48. ctx.cp_hash_path = value;
  49. break;
  50. }
  51. return true;
  52. }
  53. static bool tpm2_tool_onstart(tpm2_options **opts) {
  54. const struct option topts[] = {
  55. { "auth", required_argument, NULL, 'P' },
  56. { "public", required_argument, NULL, 'u' },
  57. { "private", required_argument, NULL, 'r' },
  58. { "name", required_argument, NULL, 'n' },
  59. { "key-context", required_argument, NULL, 'c' },
  60. { "parent-context", required_argument, NULL, 'C' },
  61. { "cphash", required_argument, NULL, 0 },
  62. };
  63. *opts = tpm2_options_new("P:u:r:n:C:c:", ARRAY_LEN(topts), topts, on_option,
  64. NULL, 0);
  65. return *opts != NULL;
  66. }
  67. static tool_rc check_opts(void) {
  68. tool_rc rc = tool_rc_success;
  69. if (!ctx.parent.ctx_path) {
  70. LOG_ERR("Expected parent object via -C");
  71. rc = tool_rc_option_error;
  72. }
  73. if (!ctx.object.pubpath) {
  74. LOG_ERR("Expected public object portion via -u");
  75. rc = tool_rc_option_error;
  76. }
  77. if (!ctx.object.privpath) {
  78. LOG_ERR("Expected public object portion via -r");
  79. rc = tool_rc_option_error;
  80. }
  81. if (!ctx.contextpath && !ctx.cp_hash_path) {
  82. LOG_ERR("Expected option -c");
  83. rc = tool_rc_option_error;
  84. }
  85. if (ctx.contextpath && ctx.cp_hash_path) {
  86. LOG_ERR("Cannot output contextpath when calculating cp_hash");
  87. rc = tool_rc_option_error;
  88. }
  89. return rc;
  90. }
  91. static tool_rc init(ESYS_CONTEXT *ectx) {
  92. bool res = files_load_public(ctx.object.pubpath, &ctx.object.public);
  93. if (!res) {
  94. return tool_rc_general_error;
  95. }
  96. res = files_load_private(ctx.object.privpath, &ctx.object.private);
  97. if (!res) {
  98. return tool_rc_general_error;
  99. }
  100. return tpm2_util_object_load_auth(ectx, ctx.parent.ctx_path,
  101. ctx.parent.auth_str, &ctx.parent.object, false,
  102. TPM2_HANDLE_ALL_W_NV);
  103. }
  104. static tool_rc finish(ESYS_CONTEXT *ectx) {
  105. TPM2B_NAME *name;
  106. tool_rc rc = tpm2_tr_get_name(ectx, ctx.object.handle, &name);
  107. if (rc != tool_rc_success) {
  108. return rc;
  109. }
  110. if (ctx.namepath) {
  111. bool result = files_save_bytes_to_file(ctx.namepath, name->name,
  112. name->size);
  113. free(name);
  114. if (!result) {
  115. return tool_rc_general_error;
  116. }
  117. } else {
  118. tpm2_tool_output("name: ");
  119. tpm2_util_print_tpm2b(name);
  120. tpm2_tool_output("\n");
  121. free(name);
  122. }
  123. return files_save_tpm_context_to_path(ectx, ctx.object.handle,
  124. ctx.contextpath);
  125. }
  126. static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
  127. UNUSED(flags);
  128. tool_rc rc = check_opts();
  129. if (rc != tool_rc_success) {
  130. return rc;
  131. }
  132. rc = init(ectx);
  133. if (rc != tool_rc_success) {
  134. return rc;
  135. }
  136. if (!ctx.cp_hash_path) {
  137. rc = tpm2_load(ectx, &ctx.parent.object, &ctx.object.private,
  138. &ctx.object.public, &ctx.object.handle, NULL);
  139. if (rc != tool_rc_success) {
  140. return rc;
  141. }
  142. return finish(ectx);
  143. }
  144. TPM2B_DIGEST cp_hash = { .size = 0 };
  145. rc = tpm2_load(ectx, &ctx.parent.object, &ctx.object.private,
  146. &ctx.object.public, &ctx.object.handle, &cp_hash);
  147. if (rc != tool_rc_success) {
  148. return rc;
  149. }
  150. bool result = files_save_digest(&cp_hash, ctx.cp_hash_path);
  151. if (!result) {
  152. rc = tool_rc_general_error;
  153. }
  154. return rc;
  155. }
  156. static tool_rc tpm2_tool_onstop(ESYS_CONTEXT *ectx) {
  157. UNUSED(ectx);
  158. return tpm2_session_close(&ctx.parent.object.session);
  159. }
  160. // Register this tool with tpm2_tool.c
  161. TPM2_TOOL_REGISTER("load", tpm2_tool_onstart, tpm2_tool_onrun, tpm2_tool_onstop, NULL)