tss2_template.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <fcntl.h>
  3. #include <libgen.h>
  4. #include <signal.h>
  5. #include <stdbool.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include <termios.h>
  12. #include <unistd.h>
  13. #include <tss2/tss2_rc.h>
  14. #include <sys/wait.h>
  15. #include <stdarg.h>
  16. #include <errno.h>
  17. #include <sys/types.h>
  18. #include <sys/stat.h>
  19. #include "tools/fapi/tss2_template.h"
  20. #include "lib/config.h"
  21. #include "lib/tpm2_alg_util.h"
  22. #define READ_SIZE 1024
  23. /* needed by tpm2_util and tpm2_option functions */
  24. bool output_enabled = false;
  25. static struct termios old;
  26. /* When the program is interrupted during callbacks,
  27. * restore the old termios state (with ICANON and ECHO) */
  28. static void signal_termio_restore(__attribute__((unused)) int signumber) {
  29. tcsetattr (STDIN_FILENO, TCSANOW, &old);
  30. }
  31. /* adapted from lib/tpm2_options.c for tss2 */
  32. static bool execute_man(char *prog_name, bool show_errors) {
  33. pid_t pid;
  34. int status;
  35. if ((pid = fork()) < 0) {
  36. LOG_ERR("Could not fork process to execute man, error: %s",
  37. strerror(errno));
  38. return false;
  39. }
  40. if (pid == 0) {
  41. if (!show_errors) {
  42. /* redirect manpager errors to stderr */
  43. int fd = open("/dev/null", O_WRONLY);
  44. if (fd < 0) {
  45. LOG_ERR("Could not open /dev/null");
  46. return false;
  47. }
  48. dup2(fd, 2);
  49. close(fd);
  50. }
  51. char *manpage = basename(prog_name);
  52. execlp("man", "man", manpage, NULL);
  53. } else {
  54. if (waitpid(pid, &status, 0) == -1) {
  55. LOG_ERR("Waiting for child process that executes man failed, error:"
  56. " %s", strerror(errno));
  57. return false;
  58. }
  59. return WEXITSTATUS(status) == 0;
  60. }
  61. return true;
  62. }
  63. /* adapted from lib/tpm2_options.c for tss2 */
  64. static tpm2_option_code tss2_handle_options (
  65. int argc,
  66. char **argv,
  67. tpm2_options **tool_opts) {
  68. tpm2_option_code rc = tpm2_option_code_err;
  69. bool show_help = false, manpager = true, explicit_manpager = false;
  70. struct option long_options [] = {
  71. {"help" , optional_argument, NULL, 'h'},
  72. {"version", no_argument, NULL, 'v'}
  73. };
  74. tpm2_options *opts = tpm2_options_new("h::v",
  75. ARRAY_LEN(long_options), long_options, NULL, NULL, 0);
  76. if (!opts) {
  77. return tpm2_option_code_err;
  78. }
  79. /* Get the options from the tool */
  80. if (!*tool_opts || !(*tool_opts)->callbacks.on_opt) {
  81. fprintf (stderr, "Unknown option found\n");
  82. goto out;
  83. }
  84. tpm2_option_handler on_opt = (*tool_opts)->callbacks.on_opt;
  85. tpm2_arg_handler on_arg = (*tool_opts)->callbacks.on_arg;
  86. if (!tpm2_options_cat (tool_opts, opts))
  87. goto out;
  88. (*tool_opts)->callbacks.on_opt = on_opt;
  89. (*tool_opts)->callbacks.on_arg = on_arg;
  90. /* Parse the options, calling the tool callback if unknown */
  91. int c;
  92. while ((c = getopt_long (argc, argv, (*tool_opts)->short_opts,
  93. (*tool_opts)->long_opts, NULL)) != -1) {
  94. switch (c) {
  95. case 'h':
  96. show_help = true;
  97. if (argv[optind]) {
  98. if (!strcmp(argv[optind], "man")) {
  99. manpager = true;
  100. explicit_manpager = true;
  101. optind++;
  102. } else if (!strcmp(argv[optind], "no-man")) {
  103. manpager = false;
  104. optind++;
  105. } else {
  106. show_help=false;
  107. fprintf (stderr, "Unknown help argument, got: \"%s\"\n",
  108. argv[optind]);
  109. }
  110. }
  111. goto out;
  112. break;
  113. case 'v': {
  114. char *prog_name = strdup (argv[0]);
  115. if (!prog_name) {
  116. fprintf (stderr, "Not enough memory\n");
  117. goto out;
  118. }
  119. printf("tool=\"%s\" version=\"%s\"\n", basename (prog_name),
  120. VERSION);
  121. free(prog_name);
  122. }
  123. rc = tpm2_option_code_stop;
  124. goto out;
  125. case '?':
  126. goto out;
  127. default:
  128. if (!(*tool_opts)->callbacks.on_opt(c, optarg))
  129. goto out;
  130. }
  131. }
  132. char **tool_args = &argv[optind];
  133. int tool_argc = argc - optind;
  134. /* have args and no handler, error condition */
  135. if (tool_argc && !(*tool_opts)->callbacks.on_arg) {
  136. char *prog_name = strdup (argv[0]);
  137. if (!prog_name) {
  138. fprintf (stderr, "Not enough memory\n");
  139. goto out;
  140. }
  141. fprintf (stderr, "Got arguments but %s takes no arguments\n",
  142. basename (prog_name));
  143. free (prog_name);
  144. goto out;
  145. } else if (tool_argc && (*tool_opts)->callbacks.on_arg
  146. && !(*tool_opts)->callbacks.on_arg(tool_argc, tool_args)) {
  147. goto out;
  148. }
  149. rc = tpm2_option_code_continue;
  150. out:
  151. /*
  152. * If help output is selected via -h or indicated by an error that help
  153. * output is desirable, show it.
  154. *
  155. * However, 3 conditions are possible:
  156. * 1. Try manpager and success -- done, no need to show short help output.
  157. * 2. Try manpager and failure -- show short help output.
  158. * 3. Do not use manpager -- show short help output.
  159. *
  160. */
  161. if (show_help) {
  162. if (!manpager || !execute_man (argv[0], explicit_manpager)) {
  163. tpm2_print_usage (argv[0], *tool_opts);
  164. }
  165. rc = tpm2_option_code_stop;
  166. }
  167. tpm2_options_free (opts);
  168. return rc;
  169. }
  170. char *password = NULL;
  171. TSS2_RC auth_callback(
  172. #ifdef FAPI_3_0
  173. char const *objectPath,
  174. char const *description,
  175. char const **auth,
  176. void *userdata)
  177. {
  178. #else /* FAPI_3_0 */
  179. __attribute__((unused)) FAPI_CONTEXT *fapi_context,
  180. char const *description,
  181. char **auth,
  182. void *userdata)
  183. {
  184. const char *objectPath = "object";
  185. #endif /* FAPI_3_0 */
  186. if (password != NULL) {
  187. free(password);
  188. password = NULL;
  189. }
  190. struct termios new;
  191. tcgetattr (STDIN_FILENO, &old);
  192. new = old;
  193. new.c_lflag &= ~(ICANON | ECHO);
  194. if (userdata) {
  195. printf("%s:", (const char *) userdata);
  196. } else {
  197. printf ("Authorize %s \"%s\": ", objectPath, description);
  198. }
  199. tcsetattr (STDIN_FILENO, TCSANOW, &new);
  200. size_t input_size = 0;
  201. struct sigaction signal_action;
  202. memset (&signal_action, 0, sizeof signal_action);
  203. signal_action.sa_handler = signal_termio_restore;
  204. sigaction (SIGTERM, &signal_action, NULL);
  205. sigaction (SIGINT, &signal_action, NULL);
  206. ssize_t getline_ret = getline (&password, &input_size, stdin);
  207. /* It is intentional, that auth can contain null bytes, and from
  208. * FAPI’s perspective these terminate the password. */
  209. tcsetattr (STDIN_FILENO, TCSANOW, &old);
  210. signal_action.sa_handler = SIG_DFL;
  211. sigaction (SIGTERM, &signal_action, NULL);
  212. sigaction (SIGINT, &signal_action, NULL);
  213. printf ("\n");
  214. if (getline_ret == -1) {
  215. fprintf (stderr, "getline() failed: %m\n");
  216. free (password);
  217. password = NULL;
  218. return TSS2_TCTI_RC_GENERAL_FAILURE;
  219. }
  220. password[getline_ret - 1] = '\0';
  221. #ifdef FAPI_3_0
  222. *auth = password;
  223. #else /* FAPI_3_0 */
  224. *auth = strdup(password);
  225. #endif /* FAPI_3_0 */
  226. return TSS2_RC_SUCCESS;
  227. }
  228. uint8_t *input_signature = NULL;
  229. TSS2_RC sign_callback(
  230. #ifdef FAPI_3_0
  231. char const *objectPath,
  232. #else /* FAPI_3_0 */
  233. __attribute__((unused)) FAPI_CONTEXT *fapi_context,
  234. #endif /* FAPI_3_0 */
  235. char const *description,
  236. char const *publicKey,
  237. char const *publicKeyHint,
  238. uint32_t hashAlg,
  239. uint8_t const *dataToSign,
  240. size_t dataToSignSize,
  241. #ifdef FAPI_3_0
  242. uint8_t const **signature,
  243. #else /* FAPI_3_0 */
  244. uint8_t **signature,
  245. #endif /* FAPI_3_0 */
  246. size_t *signatureSize,
  247. void *userData)
  248. {
  249. if (input_signature != NULL) {
  250. free(input_signature);
  251. input_signature = NULL;
  252. }
  253. int rc;
  254. char path[READ_SIZE];
  255. char publicKeyHintStr[READ_SIZE];
  256. if (userData) {
  257. printf("%s:", (const char *) userData);
  258. } else {
  259. const char *hashAlgName = tpm2_alg_util_algtostr(hashAlg,
  260. tpm2_alg_util_flags_hash);
  261. int cpy_size = 0;
  262. if (strlen(publicKeyHint) > 0) {
  263. const char* tmp = "the key corresponding to the key hint \"%s\" and";
  264. cpy_size = strlen(tmp) - 2 /* remove replaced %s */ +
  265. strlen(publicKeyHint);
  266. rc = snprintf(publicKeyHintStr, cpy_size+1 /* add \0 */, tmp,
  267. publicKeyHint);
  268. if (rc != cpy_size){
  269. fprintf (stderr, "Command snprintf failed with %d\n", rc);
  270. return TSS2_FAPI_RC_GENERAL_FAILURE;
  271. }
  272. }
  273. else {
  274. const char* tmp = "the key corresponding to the fingerprint \"%s\" and";
  275. char publicKeyHintTmp[READ_SIZE];
  276. rc = tpm2_pem_encoded_key_to_fingerprint(publicKey, publicKeyHintTmp);
  277. if (rc != true){
  278. fprintf (stderr, "Error getting the fingerprint of the "\
  279. "PEM-encoded public key\n");
  280. return TSS2_FAPI_RC_GENERAL_FAILURE;
  281. }
  282. cpy_size = strlen(tmp) - 2 /* remove replaced %s */ +
  283. strlen(publicKeyHintTmp);
  284. rc = snprintf(publicKeyHintStr, cpy_size+1 /* add \0 */, tmp,
  285. publicKeyHintTmp);
  286. if (rc != cpy_size){
  287. fprintf (stderr, "Command snprintf failed with %d\n", rc);
  288. return TSS2_FAPI_RC_GENERAL_FAILURE;
  289. }
  290. }
  291. #ifdef FAPI_3_0
  292. printf("%s: Authorize usage of %s by signing the nonce with %s the hash "\
  293. "algorithm \"%s\".\n", description, objectPath, publicKeyHintStr,
  294. hashAlgName);
  295. #else /* FAPI_3_0 */
  296. printf("%s: Authorize usage of the key by signing the nonce with %s the "\
  297. "hash algorithm \"%s\".\n", description, publicKeyHintStr,
  298. hashAlgName);
  299. #endif /* FAPI_3_0 */
  300. }
  301. printf("Filename for nonce output: ");
  302. rc = tpm2_safe_read_from_stdin(READ_SIZE, path);
  303. if (rc != true){
  304. fprintf (stderr, "Please enter a valid file path\n");
  305. return TSS2_FAPI_RC_GENERAL_FAILURE;
  306. }
  307. rc = open_write_and_close(path, true, dataToSign,
  308. dataToSignSize);
  309. if (rc) {
  310. fprintf (stderr, "Could not write to file: %s\n", path);
  311. return TSS2_FAPI_RC_GENERAL_FAILURE;
  312. }
  313. printf("Filename for signature input: ");
  314. rc = tpm2_safe_read_from_stdin(READ_SIZE, path);
  315. if (rc != true){
  316. fprintf (stderr, "Please enter a valid file path\n");
  317. return TSS2_FAPI_RC_GENERAL_FAILURE;
  318. }
  319. size_t input_signatureSize;
  320. rc = open_read_and_close (path, (void**)&input_signature,
  321. &input_signatureSize);
  322. if (rc) {
  323. fprintf (stderr, "Could not read from file path: %s\n", path);
  324. return TSS2_FAPI_RC_GENERAL_FAILURE;
  325. }
  326. *signature = input_signature;
  327. *signatureSize = input_signatureSize;
  328. return TSS2_RC_SUCCESS;
  329. }
  330. TSS2_RC branch_callback(
  331. #ifdef FAPI_3_0
  332. char const *objectPath,
  333. #else /* FAPI_3_0 */
  334. __attribute__((unused)) FAPI_CONTEXT *fapi_context,
  335. #endif /* FAPI_3_0 */
  336. char const *description,
  337. char const **branchNames,
  338. size_t numBranches,
  339. size_t *selectedBranch,
  340. __attribute__((unused)) void *userData)
  341. {
  342. #ifdef FAPI_3_0
  343. printf ("Select a branch for %s \"%s\"\n", objectPath, description);
  344. #else /* FAPI_3_0 */
  345. printf ("Select a branch for object \"%s\"\n", description);
  346. #endif /* FAPI_3_0 */
  347. for (size_t i = 0; i < numBranches; i++) {
  348. printf ("%4zu %s\n", i + 1, branchNames[i]);
  349. }
  350. while (1) {
  351. printf ("Your choice: ");
  352. if (scanf ("%zu", selectedBranch) != EOF) {
  353. while (getchar () != '\n'); /* Consume all remaining input */
  354. if (*selectedBranch > numBranches || *selectedBranch < 1) {
  355. fprintf (stderr, "The entered integer must be positive and "\
  356. "less than %zu.\n", numBranches + 1);
  357. } else {
  358. (*selectedBranch)--; /* the user display/choice is always +1 */
  359. return TSS2_RC_SUCCESS;
  360. }
  361. } else {
  362. fprintf (stderr, "No number received, but EOF.\n");
  363. return TSS2_FAPI_RC_GENERAL_FAILURE;
  364. }
  365. }
  366. }
  367. static FAPI_CONTEXT* ctx_init(char const * uri) {
  368. FAPI_CONTEXT* ret;
  369. const unsigned int rval = Fapi_Initialize(&ret, uri);
  370. if (rval != TSS2_RC_SUCCESS){
  371. LOG_PERR("Fapi_Initialize", rval);
  372. return NULL;
  373. }
  374. return ret;
  375. }
  376. /*
  377. * Build a list of the TSS2 tools linked into this executable
  378. */
  379. #ifndef TSS2_TOOLS_MAX
  380. #define TSS2_TOOLS_MAX 1024
  381. #endif
  382. static const tss2_tool *tools[TSS2_TOOLS_MAX];
  383. static unsigned tool_count;
  384. void tss2_tool_register(const tss2_tool *tool) {
  385. if (tool_count < TSS2_TOOLS_MAX) {
  386. tools[tool_count++] = tool;
  387. } else {
  388. LOG_ERR("Over tool count");
  389. abort();
  390. }
  391. }
  392. static const char *tss2_tool_name(const char *arg) {
  393. const char *name = rindex(arg, '/');
  394. if (name) {
  395. name++; // skip the '/'
  396. } else {
  397. name = arg; // use the full executable name as is
  398. }
  399. if (strncmp(name, "tss2_", 5) == 0) {
  400. name += 5;
  401. }
  402. return name;
  403. }
  404. static const tss2_tool *tss2_tool_lookup(int *argc, char ***argv)
  405. {
  406. // find the executable name in the path
  407. // and skip "tss2_" prefix if it is present
  408. const char *name = tss2_tool_name((*argv)[0]);
  409. // if this was invoked as 'tss2', then try again with the second argument
  410. if (strcmp(name, "tss2") == 0) {
  411. if (--(*argc) == 0) {
  412. return NULL;
  413. }
  414. (*argv)++;
  415. name = tss2_tool_name((*argv)[0]);
  416. }
  417. // search the tools array for a matching name
  418. for(unsigned i = 0 ; i < tool_count ; i++)
  419. {
  420. const tss2_tool * const tool = tools[i];
  421. if (!tool || !tool->name) {
  422. continue;
  423. }
  424. if (strcmp(name, tool->name) == 0) {
  425. return tool;
  426. }
  427. }
  428. // not found? should print a table of the tools
  429. return NULL;
  430. }
  431. /*
  432. * This program is a template for TPM2 tools that use the FAPI. It does
  433. * nothing more than parsing command line options that allow the caller to
  434. * specify which FAPI function to call.
  435. */
  436. int main(int argc, char *argv[]) {
  437. /* get rid of:
  438. * other write + read + execute (7)
  439. */
  440. umask(0007);
  441. const tss2_tool * const tool = tss2_tool_lookup(&argc, &argv);
  442. if (!tool) {
  443. LOG_ERR("%s: unknown tool. Available tss2 commands:\n", argv[0]);
  444. for(unsigned i = 0 ; i < tool_count ; i++) {
  445. fprintf(stderr, "%s\n", tools[i]->name);
  446. }
  447. return EXIT_FAILURE;
  448. }
  449. tpm2_options *tool_opts = NULL;
  450. if (tool->onstart && !tool->onstart (&tool_opts)) {
  451. fprintf (stderr,"error retrieving tool options\n");
  452. return 1;
  453. }
  454. int ret = 1;
  455. tpm2_option_code rc = tss2_handle_options (argc, argv, &tool_opts);
  456. if (rc != tpm2_option_code_continue) {
  457. ret = rc == tpm2_option_code_err ? 1 : 0;
  458. goto free_opts;
  459. }
  460. FAPI_CONTEXT *fctx = ctx_init (NULL);
  461. if (!fctx)
  462. goto free_opts;
  463. TSS2_RC r = Fapi_SetAuthCB (fctx, auth_callback, NULL);
  464. if (r != TSS2_RC_SUCCESS) {
  465. fprintf (stderr, "Fapi_SetAuthCB returned %u\n", r);
  466. Fapi_Finalize (&fctx);
  467. goto free_opts;
  468. }
  469. r = Fapi_SetSignCB (fctx, sign_callback, NULL);
  470. if (r != TSS2_RC_SUCCESS) {
  471. fprintf (stderr, "Fapi_SetSignCB returned %u\n", r);
  472. Fapi_Finalize (&fctx);
  473. goto free_opts;
  474. }
  475. r = Fapi_SetBranchCB (fctx, branch_callback, NULL);
  476. if (r != TSS2_RC_SUCCESS) {
  477. fprintf (stderr, "Fapi_SetBranchCB returned %u\n", r);
  478. Fapi_Finalize (&fctx);
  479. goto free_opts;
  480. }
  481. /*
  482. * Call the specific tool, all tools implement this function instead of
  483. * 'main'.
  484. * rc 1 = failure
  485. * rc 0 = success
  486. * rc -1 = show usage
  487. */
  488. ret = tool->onrun(fctx);
  489. if (ret < 0) {
  490. tpm2_print_usage(argv[0], tool_opts);
  491. ret = 1;
  492. }
  493. if (tool->onexit) {
  494. tool->onexit();
  495. }
  496. /*
  497. * Cleanup contexts & memory allocated for the modified argument vector
  498. * passed to execute_tool.
  499. */
  500. Fapi_Finalize (&fctx);
  501. free_opts:
  502. if (tool_opts)
  503. tpm2_options_free (tool_opts);
  504. free (password);
  505. if (ret == 0){
  506. free (input_signature);
  507. }
  508. exit(ret);
  509. }
  510. int open_write_and_close(const char* path, bool overwrite, const void *output,
  511. size_t output_len) {
  512. size_t length = 0;
  513. if (output_len){
  514. length = output_len;
  515. }
  516. if (!path || !strcmp(path, "-")) {
  517. if (-1 == write (STDOUT_FILENO, output, length)) {
  518. fprintf (stderr, "write(2) to stdout failed: %m\n");
  519. return 1;
  520. }
  521. return 0;
  522. }
  523. int oflags = O_CREAT | O_WRONLY | O_TRUNC ;
  524. if (!overwrite) {
  525. oflags |= O_EXCL;
  526. }
  527. int fileno = open (path, oflags, S_IWUSR | S_IRUSR);
  528. if (fileno == -1) {
  529. if (errno == EEXIST) {
  530. fprintf (stderr, "open(2) %s failed: %m\n", path);
  531. }
  532. return 1;
  533. }
  534. ssize_t bytes_written = write (fileno, output, length);
  535. if (bytes_written == -1) {
  536. fprintf (stderr, "write(2) %s failed: %m\n", path);
  537. close (fileno);
  538. return 1;
  539. }
  540. if (bytes_written - length) {
  541. fprintf (stderr, "write(2) could not write the whole file, deleting "\
  542. "%s\n", path);
  543. unlink (path);
  544. close (fileno);
  545. return 1;
  546. }
  547. if (close (fileno)) {
  548. fprintf (stderr, "close(2) %s failed: %m\n", path);
  549. return 1;
  550. }
  551. return 0;
  552. }
  553. int open_read_and_close (const char *path, void **input, size_t *size) {
  554. if (!path || !strcmp(path, "-")) {
  555. size_t data_consumed = 0, buffer_size = 1024, data_read;
  556. *input = malloc (buffer_size + 1);
  557. if (!*input) {
  558. fprintf (stderr, "malloc(2) failed: %m\n");
  559. return 1;
  560. }
  561. while ((data_read = read (STDIN_FILENO, *input + data_consumed, 1024))){
  562. data_consumed += data_read;
  563. if (data_read < 1024) /* EOF reached */
  564. break;
  565. buffer_size += 1024;
  566. *input = realloc (*input, buffer_size + 1);
  567. if (!*input) {
  568. fprintf (stderr, "realloc(3) failed: %m\n");
  569. return 1;
  570. }
  571. }
  572. if (size)
  573. *size = data_consumed;
  574. ((char*)(*input))[data_consumed] = 0;
  575. return 0;
  576. }
  577. int fileno = open (path, O_RDONLY);
  578. if (fileno == -1) {
  579. fprintf (stderr, "Opening %s failed: %m\n", path);
  580. return 1;
  581. }
  582. struct stat stat_;
  583. errno = 0;
  584. if (fstat (fileno, &stat_)) {
  585. printf("\nfstat error: [%s]\n",strerror(errno));
  586. close(fileno);
  587. return 1;
  588. }
  589. if (size)
  590. *size = stat_.st_size;
  591. *input = malloc (stat_.st_size + 1);
  592. if (!*input) {
  593. fprintf (stderr, "malloc(2) failed: %m\n");
  594. close (fileno);
  595. return 1;
  596. }
  597. if (-1 == read (fileno, *input, stat_.st_size)) {
  598. fprintf (stderr, "read(2) %s failed with: %m\n", path);
  599. free (*input);
  600. close (fileno);
  601. return 1;
  602. }
  603. ((char*)(*input))[stat_.st_size] = '\0';
  604. if (close (fileno)) {
  605. fprintf (stderr, "Error close(2) %s: %m\n", path);
  606. free (*input);
  607. return 1;
  608. }
  609. return 0;
  610. }
  611. char* ask_for_password() {
  612. #ifdef FAPI_3_0
  613. const char *pw;
  614. #else /* FAPI_3_0 */
  615. char *pw;
  616. #endif /* FAPI_3_0 */
  617. char *ret_pw = NULL;
  618. if (auth_callback (NULL, NULL, &pw, "New password"))
  619. goto error;
  620. #ifdef FAPI_3_0
  621. ret_pw = strdup(pw);
  622. if (!ret_pw) {
  623. fprintf (stderr, "OOM\n");
  624. return NULL;
  625. }
  626. #else /* FAPI_3_0 */
  627. ret_pw = pw;
  628. #endif /* FAPI_3_0 */
  629. if (auth_callback (NULL, NULL, &pw, "Re-enter new password"))
  630. goto error;
  631. bool eq = !strcmp (ret_pw, pw);
  632. #ifndef FAPI_3_0
  633. free(pw);
  634. #endif
  635. if (!eq) {
  636. fprintf (stderr, "Passwords do not match.\n");
  637. goto error;
  638. }
  639. return ret_pw;
  640. error:
  641. if (ret_pw)
  642. free(ret_pw);
  643. return NULL;
  644. }
  645. void LOG_PERR(const char *func, TSS2_RC rc) {
  646. fprintf (stderr, "%s(0x%X) - %s\n", func, rc, Tss2_RC_Decode(rc));
  647. }
  648. void LOG_ERR(const char *format, ...) {
  649. va_list arg;
  650. va_start (arg, format);
  651. vfprintf (stderr, format, arg);
  652. va_end (arg);
  653. }