main-fapi.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /* SPDX-License-Identifier: BSD-2-Clause */
  2. /*******************************************************************************
  3. * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG
  4. * All rights reserved.
  5. *******************************************************************************/
  6. #ifdef HAVE_CONFIG_H
  7. #include <config.h>
  8. #endif
  9. #include <stdio.h>
  10. #include <stdbool.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <sys/stat.h>
  14. #include <json-c/json_util.h>
  15. #include <json-c/json_tokener.h>
  16. #include "tss2_esys.h"
  17. #include "tss2_fapi.h"
  18. #include "test-fapi.h"
  19. #define LOGDEFAULT LOGLEVEL_INFO
  20. #define LOGMODULE test
  21. #include "util/log.h"
  22. #include "util/aux_util.h"
  23. #ifndef FAPI_PROFILE
  24. #define FAPI_PROFILE "P_ECC"
  25. #endif /* FAPI_PROFILE */
  26. char *fapi_profile = NULL;
  27. char *tmpdir = NULL;
  28. char *config = NULL;
  29. char *config_path = NULL;
  30. char *config_env = NULL;
  31. char *remove_cmd = NULL;
  32. char *system_dir = NULL;
  33. FAPI_CONTEXT *global_fapi_context = NULL;
  34. bool file_exists (char *path) {
  35. struct stat buffer;
  36. return (stat (path, &buffer) == 0);
  37. }
  38. /* Determine integer number from json object. */
  39. static int64_t
  40. get_number(json_object *jso) {
  41. const char* token;
  42. int itoken = 0;
  43. int pos = 0;
  44. int64_t num;
  45. token = json_object_get_string(jso);
  46. if (strncmp(token, "0x", 2) == 0) {
  47. itoken = 2;
  48. sscanf(&token[itoken], "%"PRIx64"%n", &num, &pos);
  49. } else {
  50. sscanf(&token[itoken], "%"PRId64"%n", &num, &pos);
  51. }
  52. return num;
  53. }
  54. /* Determin number of fields in a json objecd. */
  55. size_t nmb_of_fields(json_object *jso) {
  56. size_t n = 0;
  57. json_object_object_foreach(jso, key, val) {
  58. UNUSED(val);
  59. UNUSED(key);
  60. n++;
  61. }
  62. return n;
  63. }
  64. /* Compare two json objects.
  65. *
  66. * Only strings, integers, array and json objects are supported.
  67. */
  68. bool cmp_jso(json_object *jso1, json_object *jso2) {
  69. enum json_type type1, type2;
  70. size_t i, size;
  71. type1 = json_object_get_type(jso1);
  72. type2 = json_object_get_type(jso2);
  73. if (type1 != type2) {
  74. return false;
  75. }
  76. if (type1 == json_type_object) {
  77. if (nmb_of_fields(jso1) != nmb_of_fields(jso2)) {
  78. return false;
  79. }
  80. json_object_object_foreach(jso1, key1, jso_sub1) {
  81. json_object *jso_sub2;
  82. if (!json_object_object_get_ex(jso2, key1, &jso_sub2)) {
  83. return false;
  84. }
  85. if (!cmp_jso(jso_sub1, jso_sub2)) {
  86. return false;
  87. }
  88. }
  89. return true;
  90. } else if (type1 == json_type_int) {
  91. return (get_number(jso1) == get_number(jso2));
  92. } else if (type1 == json_type_array) {
  93. size = json_object_array_length(jso1);
  94. /* Cast to size_t due to change in json-c API.
  95. older versions use result type int */
  96. if (size != (size_t)json_object_array_length(jso2)) {
  97. return false;
  98. }
  99. for (i = 0; i < size; i++) {
  100. if (!cmp_jso(json_object_array_get_idx(jso1, i),
  101. json_object_array_get_idx(jso2, i))) {
  102. return false;
  103. }
  104. }
  105. return true;
  106. } else if (type1 == json_type_string) {
  107. return (strcmp(json_object_get_string(jso1),
  108. json_object_get_string(jso2)) == 0);
  109. } else {
  110. return false;
  111. }
  112. }
  113. /* Compare two delimter sparated token lists. */
  114. bool cmp_strtokens(char* string1, char *string2, char *delimiter) {
  115. bool found = false;
  116. char *token1 = NULL;
  117. char *token2 = NULL;
  118. char *end_token1;
  119. char *end_token2;
  120. char *string2_copy;
  121. string1 = strdup(string1);
  122. ASSERT(string1);
  123. token1 = strtok_r(string1, delimiter, &end_token1);
  124. while(token1 != NULL) {
  125. found = false;
  126. string2_copy = strdup(string2);
  127. ASSERT(string2_copy);
  128. token2 = strtok_r(string2_copy, delimiter, &end_token2);
  129. while (token2 != NULL) {
  130. if (strcmp(token1, token2) == 0) {
  131. found = true;
  132. break;
  133. }
  134. token2 = strtok_r(NULL, delimiter, &end_token2);
  135. }
  136. free(string2_copy);
  137. if (!found) {
  138. break;
  139. }
  140. token1 = strtok_r(NULL, delimiter, &end_token1);
  141. }
  142. free(string1);
  143. return found;
  144. error:
  145. SAFE_FREE(string1);
  146. return false;
  147. }
  148. TSS2_RC
  149. pcr_reset(FAPI_CONTEXT *context, UINT32 pcr)
  150. {
  151. TSS2_RC r;
  152. TSS2_TCTI_CONTEXT *tcti;
  153. ESYS_CONTEXT *esys;
  154. r = Fapi_GetTcti(context, &tcti);
  155. goto_if_error(r, "Error Fapi_GetTcti", error);
  156. r = Esys_Initialize(&esys, tcti, NULL);
  157. goto_if_error(r, "Error Fapi_GetTcti", error);
  158. r = Esys_PCR_Reset(esys, pcr,
  159. ESYS_TR_PASSWORD, ESYS_TR_NONE, ESYS_TR_NONE);
  160. Esys_Finalize(&esys);
  161. goto_if_error(r, "Error Eys_PCR_Reset", error);
  162. error:
  163. return r;
  164. }
  165. int init_fapi(char *profile, FAPI_CONTEXT **fapi_context)
  166. {
  167. TSS2_RC rc;
  168. int ret, size;
  169. SAFE_FREE(config);
  170. SAFE_FREE(config_path);
  171. SAFE_FREE(config_env);
  172. SAFE_FREE(remove_cmd);
  173. SAFE_FREE(system_dir);
  174. FILE *config_file;
  175. fapi_profile = profile;
  176. /* First we construct a fapi config file */
  177. #if defined(FAPI_NONTPM)
  178. size = asprintf(&config, "{\n"
  179. " \"profile_name\": \"%s\",\n"
  180. " \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
  181. " \"user_dir\": \"%s/user/dir\",\n"
  182. " \"system_dir\": \"%s/system_dir\",\n"
  183. " \"system_pcrs\" : [],\n"
  184. " \"log_dir\" : \"%s\",\n"
  185. " \"tcti\": \"none\",\n"
  186. "}\n",
  187. profile, tmpdir, tmpdir, tmpdir);
  188. #elif defined(FAPI_TEST_FINGERPRINT)
  189. size = asprintf(&config, "{\n"
  190. " \"profile_name\": \"%s\",\n"
  191. " \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
  192. " \"user_dir\": \"%s/user/dir\",\n"
  193. " \"system_dir\": \"%s/system_dir\",\n"
  194. " \"system_pcrs\" : [],\n"
  195. " \"log_dir\" : \"%s\",\n"
  196. " \"tcti\": \"%s\",\n"
  197. #if defined(FAPI_TEST_EK_CERT_LESS)
  198. " \"ek_cert_less\": \"yes\",\n"
  199. #else
  200. " \"ek_fingerprint\": %s,\n"
  201. #endif
  202. "}\n",
  203. profile, tmpdir, tmpdir, tmpdir,
  204. getenv("TPM20TEST_TCTI")
  205. #if !defined(FAPI_TEST_EK_CERT_LESS)
  206. , getenv("FAPI_TEST_FINGERPRINT")
  207. #endif
  208. );
  209. #elif defined(FAPI_TEST_CERTIFICATE)
  210. size = asprintf(&config, "{\n"
  211. " \"profile_name\": \"%s\",\n"
  212. " \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
  213. " \"user_dir\": \"%s/user/dir\",\n"
  214. " \"system_dir\": \"%s/system_dir\",\n"
  215. " \"system_pcrs\" : [],\n"
  216. " \"log_dir\" : \"%s\",\n"
  217. " \"tcti\": \"%s\",\n"
  218. #if defined(FAPI_TEST_EK_CERT_LESS)
  219. " \"ek_cert_less\": \"yes\",\n"
  220. #else
  221. " \"ek_cert_file\": \"%s\",\n"
  222. #endif
  223. "}\n",
  224. profile, tmpdir, tmpdir, tmpdir,
  225. getenv("TPM20TEST_TCTI")
  226. #if !defined(FAPI_TEST_EK_CERT_LESS)
  227. , getenv("FAPI_TEST_CERTIFICATE")
  228. #endif
  229. );
  230. #elif defined(FAPI_TEST_FINGERPRINT_ECC)
  231. size = asprintf(&config, "{\n"
  232. " \"profile_name\": \"%s\",\n"
  233. " \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
  234. " \"user_dir\": \"%s/user/dir\",\n"
  235. " \"system_dir\": \"%s/system_dir\",\n"
  236. " \"system_pcrs\" : [],\n"
  237. " \"log_dir\" : \"%s\",\n"
  238. " \"tcti\": \"%s\",\n"
  239. #if defined(FAPI_TEST_EK_CERT_LESS)
  240. " \"ek_cert_less\": \"yes\",\n"
  241. #else
  242. " \"ek_fingerprint\": %s,\n"
  243. #endif
  244. "}\n",
  245. profile, tmpdir, tmpdir, tmpdir,
  246. getenv("TPM20TEST_TCTI")
  247. #if !defined(FAPI_TEST_EK_CERT_LESS)
  248. , getenv("FAPI_TEST_FINGERPRINT_ECC")
  249. #endif
  250. );
  251. #elif defined(FAPI_TEST_CERTIFICATE_ECC)
  252. size = asprintf(&config, "{\n"
  253. " \"profile_name\": \"%s\",\n"
  254. " \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
  255. " \"user_dir\": \"%s/user/dir\",\n"
  256. " \"system_dir\": \"%s/system_dir\",\n"
  257. " \"system_pcrs\" : [],\n"
  258. " \"log_dir\" : \"%s\",\n"
  259. " \"tcti\": \"%s\",\n"
  260. #if defined(FAPI_TEST_EK_CERT_LESS)
  261. " \"ek_cert_less\": \"yes\",\n"
  262. #else
  263. " \"ek_cert_file\": \"%s\",\n"
  264. #endif
  265. "}\n",
  266. profile, tmpdir, tmpdir, tmpdir,
  267. getenv("TPM20TEST_TCTI")
  268. #if defined(FAPI_TEST_EK_CERT_LESS)
  269. #else
  270. , getenv("FAPI_TEST_CERTIFICATE_ECC")
  271. #endif
  272. );
  273. #else /* FAPI_NONTPM */
  274. size = asprintf(&config, "{\n"
  275. " \"profile_name\": \"%s\",\n"
  276. " \"profile_dir\": \"" TOP_SOURCEDIR "/test/data/fapi/\",\n"
  277. " \"user_dir\": \"%s/user/dir\",\n"
  278. " \"system_dir\": \"%s/system_dir\",\n"
  279. " \"system_pcrs\" : [],\n"
  280. " \"log_dir\" : \"%s\",\n"
  281. " \"tcti\": \"%s\",\n"
  282. #if defined(FAPI_TEST_EK_CERT_LESS)
  283. " \"ek_cert_less\": \"yes\",\n"
  284. #endif
  285. "}\n",
  286. profile, tmpdir, tmpdir, tmpdir,
  287. getenv("TPM20TEST_TCTI"));
  288. #endif /* FAPI_NONTPM */
  289. if (size < 0) {
  290. LOG_ERROR("Out of memory");
  291. ret = EXIT_ERROR;
  292. goto error;
  293. }
  294. size = asprintf(&system_dir, "%s/system_dir/", tmpdir);
  295. if (size < 0) {
  296. LOG_ERROR("Out of memory");
  297. ret = EXIT_ERROR;
  298. goto error;
  299. }
  300. if (!file_exists(system_dir)) {
  301. int rc_mkdir = mkdir(system_dir, 0777);
  302. if (rc_mkdir != 0) {
  303. LOG_ERROR("mkdir not possible: %i %s", rc_mkdir, system_dir);
  304. ret = EXIT_ERROR;
  305. goto error;
  306. }
  307. }
  308. if (size < 0) {
  309. LOG_ERROR("Out of memory");
  310. ret = EXIT_ERROR;
  311. goto error;
  312. }
  313. LOG_INFO("Using config:\n%s", config);
  314. /* We construct the path for the config file */
  315. size = asprintf(&config_path, "%s/fapi-config.json", tmpdir);
  316. if (size < 0) {
  317. LOG_ERROR("Out of memory");
  318. ret = EXIT_ERROR;
  319. goto error;
  320. }
  321. /* We write the config file to disk */
  322. config_file = fopen(config_path, "w");
  323. if (!config_file) {
  324. LOG_ERROR("Opening config file for writing");
  325. perror(config_path);
  326. ret = EXIT_ERROR;
  327. goto error;
  328. }
  329. size = fprintf(config_file, "%s", config);
  330. fclose(config_file);
  331. if (size < 0) {
  332. LOG_ERROR("Writing config file");
  333. perror(config_path);
  334. ret = EXIT_ERROR;
  335. goto error;
  336. }
  337. /* We set the environment variable for FAPI to consume the config file */
  338. size = asprintf(&config_env, "TSS2_FAPICONF=%s", config_path);
  339. if (size < 0) {
  340. LOG_ERROR("Out of memory");
  341. ret = EXIT_ERROR;
  342. goto error;
  343. }
  344. putenv(config_env);
  345. /***********
  346. * Call FAPI
  347. ***********/
  348. rc = Fapi_Initialize(fapi_context, NULL);
  349. if (rc != TSS2_RC_SUCCESS) {
  350. LOG_ERROR("Esys_Initialize FAILED! Response Code : 0x%x", rc);
  351. ret = EXIT_FAILURE;
  352. goto error;
  353. }
  354. global_fapi_context = *fapi_context;
  355. return 0;
  356. error:
  357. Fapi_Finalize(fapi_context);
  358. if (system_dir) free(system_dir);
  359. if (config) free(config);
  360. if (config_path) free(config_path);
  361. if (config_env) free(config_env);
  362. if (remove_cmd) free(remove_cmd);
  363. return ret;
  364. }
  365. /**
  366. * This program is a template for integration tests (ones that use the TCTI,
  367. * the ESAPI, and FAPI contexts / API directly). It does nothing more than
  368. * parsing command line options that allow the caller (likely a script)
  369. * to specifywhich TCTI to use for the test using getenv("TPM20TEST_TCTI").
  370. */
  371. int
  372. main(int argc, char *argv[])
  373. {
  374. int ret, size;
  375. char *config = NULL;
  376. char *config_path = NULL;
  377. char *config_env = NULL;
  378. char *remove_cmd = NULL;
  379. char *system_dir = NULL;
  380. char template[] = "/tmp/fapi_tmpdir.XXXXXX";
  381. tmpdir = mkdtemp(template);
  382. if (!tmpdir) {
  383. LOG_ERROR("No temp dir created");
  384. return EXIT_ERROR;
  385. }
  386. ret = init_fapi(FAPI_PROFILE, &global_fapi_context);
  387. if (ret)
  388. goto error;
  389. ret = test_invoke_fapi(global_fapi_context);
  390. LOG_INFO("Test returned %i", ret);
  391. if (ret) goto error;
  392. size = asprintf(&remove_cmd, "rm -r -f %s", tmpdir);
  393. if (size < 0) {
  394. LOG_ERROR("Out of memory");
  395. ret = EXIT_ERROR;
  396. goto error;
  397. }
  398. if (system(remove_cmd) != 0) {
  399. LOG_ERROR("Directory %s can't be deleted.", tmpdir);
  400. ret = EXIT_ERROR;
  401. goto error;
  402. }
  403. error:
  404. Fapi_Finalize(&global_fapi_context);
  405. if (system_dir) free(system_dir);
  406. if (config) free(config);
  407. if (config_path) free(config_path);
  408. if (config_env) free(config_env);
  409. if (remove_cmd) free(remove_cmd);
  410. return ret;
  411. }