tpm2_ecephemeral.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include "files.h"
  3. #include "log.h"
  4. #include "tpm2.h"
  5. #include "tpm2_tool.h"
  6. #include "tpm2_alg_util.h"
  7. #include "tpm2_options.h"
  8. typedef struct tpm_ecephemeral_ctx tpm_ecephemeral_ctx;
  9. struct tpm_ecephemeral_ctx {
  10. TPMI_ECC_CURVE curve_id;
  11. uint16_t counter;
  12. TPM2B_ECC_POINT *Q;
  13. char *commit_counter_path;
  14. char *ephemeral_pub_key_path;
  15. };
  16. static tpm_ecephemeral_ctx ctx = {
  17. .curve_id = TPM2_ECC_NONE,
  18. };
  19. static bool on_option(char key, char *value) {
  20. switch (key) {
  21. case 'u':
  22. ctx.ephemeral_pub_key_path = value;
  23. break;
  24. case 't':
  25. ctx.commit_counter_path = value;
  26. break;
  27. };
  28. return true;
  29. }
  30. static bool on_args(int argc, char **argv) {
  31. if (argc > 1) {
  32. LOG_ERR("Specify a single argument for curveID");
  33. return false;
  34. }
  35. bool result = true;
  36. TPM2B_PUBLIC algorithm = { 0 };
  37. if (!tpm2_alg_util_handle_ext_alg(argv[0], &algorithm)) {
  38. result = false;
  39. }
  40. if (algorithm.publicArea.type != TPM2_ALG_ECC) {
  41. result = false;
  42. }
  43. if (algorithm.publicArea.parameters.eccDetail.curveID > TPM2_ECC_NIST_P521) {
  44. result = false;
  45. }
  46. if (!result) {
  47. LOG_ERR("Invalid/unsupported ECC curve: %s", argv[0]);
  48. return false;
  49. }
  50. ctx.curve_id = algorithm.publicArea.parameters.eccDetail.curveID;
  51. return true;
  52. }
  53. static bool tpm2_tool_onstart(tpm2_options **opts) {
  54. static struct option topts[] = {
  55. { "public", required_argument, NULL, 'u' },
  56. { "counter", required_argument, NULL, 't' },
  57. };
  58. *opts = tpm2_options_new("u:t:", ARRAY_LEN(topts), topts,
  59. on_option, on_args, 0);
  60. return *opts != NULL;
  61. }
  62. static tool_rc check_options(void) {
  63. if (!ctx.ephemeral_pub_key_path) {
  64. LOG_ERR("Invalid path specified for saving the ephemeral public key");
  65. return tool_rc_option_error;
  66. }
  67. if (!ctx.commit_counter_path) {
  68. LOG_ERR("Invalid path specified for saving the commit counter");
  69. return tool_rc_option_error;
  70. }
  71. if (ctx.curve_id == TPM2_ECC_NONE) {
  72. LOG_ERR("Invalid/ unspecified ECC curve");
  73. return tool_rc_option_error;
  74. }
  75. return tool_rc_success;
  76. }
  77. static tool_rc process_outputs(void) {
  78. FILE *fp = fopen(ctx.commit_counter_path, "wb");
  79. bool result = files_write_16(fp, ctx.counter);
  80. fclose(fp);
  81. if (!result) {
  82. LOG_ERR("Failed to write out the ECC commit count");
  83. return tool_rc_general_error;
  84. }
  85. result = files_save_ecc_point(ctx.Q, ctx.ephemeral_pub_key_path);
  86. if (!result) {
  87. LOG_ERR("Failed to write out the ECC pub key");
  88. return tool_rc_general_error;
  89. }
  90. return tool_rc_success;
  91. }
  92. static tool_rc tpm2_tool_onrun(ESYS_CONTEXT *ectx, tpm2_option_flags flags) {
  93. UNUSED(flags);
  94. // Check input options and arguments
  95. tool_rc rc = check_options();
  96. if (rc != tool_rc_success) {
  97. return rc;
  98. }
  99. // ESAPI call
  100. rc = tpm2_ecephemeral(ectx, ctx.curve_id, &ctx.Q, &ctx.counter);
  101. if (rc != tool_rc_success) {
  102. return rc;
  103. }
  104. // Process outputs
  105. rc = process_outputs();
  106. Esys_Free(ctx.Q);
  107. return rc;
  108. }
  109. // Register this tool with tpm2_tool.c
  110. TPM2_TOOL_REGISTER("ecephemeral", tpm2_tool_onstart, tpm2_tool_onrun, NULL, NULL)