tpm2_policy.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "files.h"
  6. #include "log.h"
  7. #include "tpm2.h"
  8. #include "tpm2_alg_util.h"
  9. #include "tpm2_openssl.h"
  10. #include "tpm2_policy.h"
  11. #include "tpm2_tool.h"
  12. #include "tpm2_util.h"
  13. static bool evaluate_populate_pcr_digests(TPML_PCR_SELECTION *pcr_selections,
  14. const char *raw_pcrs_file, TPML_DIGEST *pcr_values) {
  15. unsigned expected_pcr_input_file_size = 0;
  16. unsigned dgst_cnt = 0;
  17. //Iterating the number of pcr banks selected
  18. UINT32 i;
  19. for (i = 0; i < pcr_selections->count; i++) {
  20. UINT8 total_indices_for_this_alg = 0;
  21. //Looping to check total pcr select bits in the pcr-select-octets for a bank
  22. UINT32 j;
  23. for (j = 0; j < pcr_selections->pcrSelections[i].sizeofSelect; j++) {
  24. UINT8 group_val = pcr_selections->pcrSelections[i].pcrSelect[j];
  25. total_indices_for_this_alg += tpm2_util_pop_count(group_val);
  26. }
  27. if (pcr_values->count
  28. + total_indices_for_this_alg> ARRAY_LEN(pcr_values->digests)) {
  29. LOG_ERR("Number of PCR is limited to %zu",
  30. ARRAY_LEN(pcr_values->digests));
  31. return false;
  32. }
  33. //digest size returned per the hashAlg type
  34. unsigned dgst_size = tpm2_alg_util_get_hash_size(
  35. pcr_selections->pcrSelections[i].hash);
  36. if (!dgst_size) {
  37. return false;
  38. }
  39. expected_pcr_input_file_size +=
  40. (total_indices_for_this_alg * dgst_size);
  41. //Cumulative total of all the pcr indices across banks selected in setlist
  42. pcr_values->count += total_indices_for_this_alg;
  43. /*
  44. * Populating the digest sizes in the PCR digest list per algorithm bank
  45. * Once iterated through all banks, creates an file offsets map for all pcr indices
  46. */
  47. UINT8 k;
  48. for (k = 0; k < total_indices_for_this_alg; k++) {
  49. pcr_values->digests[dgst_cnt].size = dgst_size;
  50. dgst_cnt++;
  51. }
  52. }
  53. //Check if the input pcrs file size is the same size as the pcr selection setlist
  54. if (raw_pcrs_file) {
  55. unsigned long filesize = 0;
  56. bool result = files_get_file_size_path(raw_pcrs_file, &filesize);
  57. if (!result) {
  58. LOG_ERR("Could not retrieve raw_pcrs_file size");
  59. return false;
  60. }
  61. if (filesize != expected_pcr_input_file_size) {
  62. LOG_ERR("pcr-input-file filesize does not match pcr set-list");
  63. return false;
  64. }
  65. }
  66. return true;
  67. }
  68. tool_rc tpm2_policy_build_pcr(ESYS_CONTEXT *ectx, tpm2_session *policy_session,
  69. const char *raw_pcrs_file, TPML_PCR_SELECTION *pcr_selections,
  70. TPM2B_DIGEST *raw_pcr_digest) {
  71. TPML_DIGEST pcr_values = { .count = 0 };
  72. if (!pcr_selections->count) {
  73. LOG_ERR("No pcr selection data specified!");
  74. return tool_rc_general_error;
  75. }
  76. TPM2B_DIGEST pcr_digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer);
  77. TPMI_ALG_HASH auth_hash = tpm2_session_get_authhash(policy_session);
  78. ESYS_TR handle = tpm2_session_get_handle(policy_session);
  79. /*
  80. * If digest of all PCRs is directly given, handle it here.
  81. */
  82. if (raw_pcr_digest &&
  83. raw_pcr_digest->size != tpm2_alg_util_get_hash_size(auth_hash)) {
  84. LOG_ERR("Specified PCR digest length not suitable with the policy session digest");
  85. return tool_rc_general_error;
  86. }
  87. // Call the PolicyPCR command
  88. if (raw_pcr_digest) {
  89. return tpm2_policy_pcr(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE,
  90. ESYS_TR_NONE, raw_pcr_digest, pcr_selections);
  91. }
  92. bool result = evaluate_populate_pcr_digests(pcr_selections, raw_pcrs_file,
  93. &pcr_values);
  94. if (!result) {
  95. return tool_rc_general_error;
  96. }
  97. //If PCR input for policy is from raw pcrs file
  98. if (raw_pcrs_file) {
  99. FILE *fp = fopen(raw_pcrs_file, "rb");
  100. if (fp == NULL) {
  101. LOG_ERR("Cannot open pcr-input-file %s", raw_pcrs_file);
  102. return tool_rc_general_error;
  103. }
  104. // Bank hashAlg values dictates the order of the list of digests
  105. unsigned i;
  106. for (i = 0; i < pcr_values.count; i++) {
  107. size_t sz = fread(&pcr_values.digests[i].buffer, 1,
  108. pcr_values.digests[i].size, fp);
  109. if (sz != pcr_values.digests[i].size) {
  110. const char *msg =
  111. ferror(fp) ? strerror(errno) : "end of file reached";
  112. LOG_ERR("Reading from file \"%s\" failed: %s", raw_pcrs_file,
  113. msg);
  114. fclose(fp);
  115. return tool_rc_general_error;
  116. }
  117. }
  118. fclose(fp);
  119. } else {
  120. UINT32 pcr_update_counter;
  121. TPML_DIGEST *pcr_val = NULL;
  122. // Read PCRs
  123. tool_rc rc = tpm2_pcr_read(ectx, ESYS_TR_NONE, ESYS_TR_NONE,
  124. ESYS_TR_NONE, pcr_selections, &pcr_update_counter,
  125. NULL, &pcr_val);
  126. if (rc != tool_rc_success) {
  127. return rc;
  128. }
  129. UINT32 i;
  130. pcr_val->count = pcr_values.count;
  131. for (i = 0; i < pcr_val->count; i++) {
  132. memcpy(pcr_values.digests[i].buffer, pcr_val->digests[i].buffer,
  133. pcr_val->digests[i].size);
  134. pcr_values.digests[i].size = pcr_val->digests[i].size;
  135. }
  136. free(pcr_val);
  137. }
  138. // Calculate hashes
  139. result = tpm2_openssl_hash_pcr_values(auth_hash, &pcr_values, &pcr_digest);
  140. if (!result) {
  141. LOG_ERR("Could not hash pcr values");
  142. return tool_rc_general_error;
  143. }
  144. // Call the PolicyPCR command
  145. return tpm2_policy_pcr(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE,
  146. ESYS_TR_NONE, &pcr_digest, pcr_selections);
  147. }
  148. tool_rc tpm2_policy_build_policyauthorize(ESYS_CONTEXT *ectx,
  149. tpm2_session *policy_session, const char *policy_digest_path,
  150. const char *qualifying_data,
  151. const char *verifying_pubkey_name_path, const char *ticket_path) {
  152. bool result = true;
  153. TPM2B_DIGEST approved_policy = { .size = 0 };
  154. if (policy_digest_path) {
  155. approved_policy.size = sizeof(TPMU_HA);
  156. result = files_load_bytes_from_path(policy_digest_path,
  157. approved_policy.buffer, &approved_policy.size);
  158. }
  159. if (!result) {
  160. return tool_rc_general_error;
  161. }
  162. /*
  163. * Qualifier data is optional. If not specified default to 0
  164. */
  165. TPM2B_NONCE policy_qualifier = { .size = 0 };
  166. if (qualifying_data) {
  167. policy_qualifier.size = sizeof(policy_qualifier.buffer);
  168. result = tpm2_util_bin_from_hex_or_file(qualifying_data,
  169. &policy_qualifier.size, policy_qualifier.buffer);
  170. if (!result) {
  171. return tool_rc_general_error;
  172. }
  173. }
  174. unsigned long file_size = 0;
  175. result = files_get_file_size_path(verifying_pubkey_name_path, &file_size);
  176. if (!result) {
  177. return tool_rc_general_error;
  178. }
  179. if (!file_size) {
  180. LOG_ERR("Verifying public key name file \"%s\", cannot be empty",
  181. verifying_pubkey_name_path);
  182. return tool_rc_general_error;
  183. }
  184. TPM2B_NAME key_sign = { .size = (uint16_t) file_size };
  185. result = files_load_bytes_from_path(verifying_pubkey_name_path,
  186. key_sign.name, &key_sign.size);
  187. if (!result) {
  188. return tool_rc_general_error;
  189. }
  190. TPMT_TK_VERIFIED check_ticket = { .tag = TPM2_ST_VERIFIED, .hierarchy =
  191. TPM2_RH_OWNER, .digest = { 0 } };
  192. result = tpm2_session_is_trial(policy_session);
  193. if (!result) {
  194. result = files_load_ticket(ticket_path, &check_ticket);
  195. if (!result) {
  196. LOG_ERR("Could not load verification ticket file");
  197. return tool_rc_general_error;
  198. }
  199. }
  200. ESYS_TR sess_handle = tpm2_session_get_handle(policy_session);
  201. return tpm2_policy_authorize(ectx, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE,
  202. ESYS_TR_NONE, &approved_policy, &policy_qualifier, &key_sign,
  203. &check_ticket);
  204. }
  205. tool_rc tpm2_policy_build_policyor(ESYS_CONTEXT *ectx,
  206. tpm2_session *policy_session, TPML_DIGEST *policy_list) {
  207. ESYS_TR sess_handle = tpm2_session_get_handle(policy_session);
  208. return tpm2_policy_or(ectx, sess_handle, ESYS_TR_NONE, ESYS_TR_NONE,
  209. ESYS_TR_NONE, policy_list);
  210. }
  211. tool_rc tpm2_policy_build_policypassword(ESYS_CONTEXT *ectx,
  212. tpm2_session *session) {
  213. ESYS_TR policy_session_handle = tpm2_session_get_handle(session);
  214. return tpm2_policy_password(ectx, policy_session_handle, ESYS_TR_NONE,
  215. ESYS_TR_NONE, ESYS_TR_NONE);
  216. }
  217. tool_rc tpm2_policy_build_policynamehash(ESYS_CONTEXT *ectx,
  218. tpm2_session *session, const TPM2B_DIGEST *name_hash) {
  219. ESYS_TR policy_session_handle = tpm2_session_get_handle(session);
  220. return tpm2_policy_namehash(ectx, policy_session_handle, name_hash);
  221. }
  222. tool_rc tpm2_policy_build_policytemplate(ESYS_CONTEXT *ectx,
  223. tpm2_session *session, const TPM2B_DIGEST *template_hash) {
  224. ESYS_TR policy_session_handle = tpm2_session_get_handle(session);
  225. return tpm2_policy_template(ectx, policy_session_handle, template_hash);
  226. }
  227. tool_rc tpm2_policy_build_policycphash(ESYS_CONTEXT *ectx,
  228. tpm2_session *session, const TPM2B_DIGEST *cphash) {
  229. ESYS_TR policy_session_handle = tpm2_session_get_handle(session);
  230. return tpm2_policy_cphash(ectx, policy_session_handle, cphash);
  231. }
  232. tool_rc tpm2_policy_build_policyauthvalue(ESYS_CONTEXT *ectx,
  233. tpm2_session *session) {
  234. ESYS_TR policy_session_handle = tpm2_session_get_handle(session);
  235. return tpm2_policy_authvalue(ectx, policy_session_handle, ESYS_TR_NONE,
  236. ESYS_TR_NONE, ESYS_TR_NONE);
  237. }
  238. tool_rc tpm2_policy_build_policysecret(ESYS_CONTEXT *ectx,
  239. tpm2_session *policy_session, tpm2_loaded_object *auth_entity_obj,
  240. INT32 expiration, TPMT_TK_AUTH **policy_ticket,
  241. TPM2B_TIMEOUT **timeout, bool is_nonce_tpm,
  242. const char *policy_qualifier_data, TPM2B_DIGEST *cp_hash) {
  243. /*
  244. * Qualifier data is optional. If not specified default to 0
  245. */
  246. TPM2B_NONCE policy_qualifier = TPM2B_EMPTY_INIT;
  247. if (policy_qualifier_data) {
  248. policy_qualifier.size = sizeof(policy_qualifier.buffer);
  249. bool result = tpm2_util_bin_from_hex_or_file(policy_qualifier_data,
  250. &policy_qualifier.size,
  251. policy_qualifier.buffer);
  252. if (!result) {
  253. return tool_rc_general_error;
  254. }
  255. }
  256. ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session);
  257. TPM2B_NONCE *nonce_tpm = NULL;
  258. tool_rc rc = tool_rc_success;
  259. if (is_nonce_tpm) {
  260. rc = tpm2_sess_get_noncetpm(ectx, policy_session_handle, &nonce_tpm);
  261. if (rc != tool_rc_success) {
  262. goto tpm2_policy_build_policysecret_out;
  263. }
  264. }
  265. rc = tpm2_policy_secret(ectx, auth_entity_obj, policy_session_handle,
  266. expiration, policy_ticket, timeout, nonce_tpm, &policy_qualifier,
  267. cp_hash);
  268. tpm2_policy_build_policysecret_out:
  269. Esys_Free(nonce_tpm);
  270. return rc;
  271. }
  272. tool_rc tpm2_policy_build_policyticket(ESYS_CONTEXT *ectx,
  273. tpm2_session *policy_session, char *policy_timeout_path,
  274. const char *qualifier_data, char *policy_ticket_path,
  275. const char *auth_name_path) {
  276. unsigned long file_size = 0;
  277. bool result = files_get_file_size_path(policy_timeout_path, &file_size);
  278. if (!result) {
  279. return tool_rc_general_error;
  280. }
  281. TPM2B_TIMEOUT policy_timeout = { .size = (uint16_t) file_size };
  282. if (policy_timeout.size) {
  283. result = files_load_bytes_from_path(policy_timeout_path,
  284. policy_timeout.buffer, &policy_timeout.size);
  285. if (!result) {
  286. return tool_rc_general_error;
  287. }
  288. }
  289. result = files_get_file_size_path(auth_name_path, &file_size);
  290. if (!result) {
  291. return tool_rc_general_error;
  292. }
  293. TPM2B_NAME auth_name = { .size = (uint16_t) file_size };
  294. if (auth_name.size) {
  295. result = files_load_bytes_from_path(auth_name_path,
  296. auth_name.name, &auth_name.size);
  297. if (!result) {
  298. return tool_rc_general_error;
  299. }
  300. }
  301. TPM2B_NONCE policyref = TPM2B_EMPTY_INIT;
  302. if (qualifier_data) {
  303. policyref.size = sizeof(policyref.buffer);
  304. result = tpm2_util_bin_from_hex_or_file(qualifier_data, &policyref.size,
  305. policyref.buffer);
  306. if (!result) {
  307. return tool_rc_general_error;
  308. }
  309. }
  310. TPMT_TK_AUTH ticket = { 0 };
  311. result = files_load_authorization_ticket(policy_ticket_path, &ticket);
  312. if (!result) {
  313. LOG_ERR("Failed loading authorization ticket.");
  314. return tool_rc_general_error;
  315. }
  316. ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session);
  317. return tpm2_policy_ticket(ectx, policy_session_handle, &policy_timeout,
  318. &policyref, &auth_name, &ticket);
  319. return tool_rc_success;
  320. }
  321. tool_rc tpm2_policy_build_policysigned(ESYS_CONTEXT *ectx,
  322. tpm2_session *policy_session, tpm2_loaded_object *auth_entity_obj,
  323. TPMT_SIGNATURE *signature, INT32 expiration, TPM2B_TIMEOUT **timeout,
  324. TPMT_TK_AUTH **policy_ticket, const char *policy_qualifier_data,
  325. bool is_nonce_tpm, const char *raw_data_path,
  326. const char *cphash_path) {
  327. bool result = true;
  328. /*
  329. * Qualifier data is optional. If not specified default to 0
  330. */
  331. TPM2B_NONCE policy_qualifier = TPM2B_EMPTY_INIT;
  332. if (policy_qualifier_data) {
  333. policy_qualifier.size = sizeof(policy_qualifier.buffer);
  334. result = tpm2_util_bin_from_hex_or_file(policy_qualifier_data,
  335. &policy_qualifier.size,
  336. policy_qualifier.buffer);
  337. if (!result) {
  338. return tool_rc_general_error;
  339. }
  340. }
  341. /*
  342. * CpHashA (digest of command parameters for approved command) optional.
  343. * If not specified default to NULL
  344. */
  345. TPM2B_DIGEST cphash = TPM2B_EMPTY_INIT;
  346. if (cphash_path) {
  347. bool result = files_load_digest(cphash_path, &cphash);
  348. if (!result) {
  349. return tool_rc_general_error;
  350. }
  351. }
  352. ESYS_TR policy_session_handle = tpm2_session_get_handle(policy_session);
  353. TPM2B_NONCE *nonce_tpm = NULL;
  354. tool_rc rc = tool_rc_success;
  355. if (is_nonce_tpm) {
  356. rc = tpm2_sess_get_noncetpm(ectx, policy_session_handle, &nonce_tpm);
  357. if (rc != tool_rc_success) {
  358. goto tpm2_policy_build_policysigned_out;
  359. }
  360. }
  361. /*
  362. * TPM-Rev-2.0-Part-3-Commands-01.38.pdf
  363. * aHash ≔ HauthAlg(nonceTPM || expiration || cpHashA || policyRef)
  364. */
  365. if (raw_data_path) {
  366. uint16_t raw_data_len = (nonce_tpm ? nonce_tpm->size : 0) +
  367. sizeof(INT32) + cphash.size + policy_qualifier.size;
  368. uint8_t *raw_data = malloc(raw_data_len);
  369. if (!raw_data) {
  370. LOG_ERR("oom");
  371. rc = tool_rc_general_error;
  372. goto tpm2_policy_build_policysigned_out;
  373. }
  374. /* nonceTPM */
  375. uint16_t offset = 0;
  376. if (nonce_tpm) {
  377. memcpy(raw_data, nonce_tpm->buffer, nonce_tpm->size);
  378. offset += nonce_tpm->size;
  379. }
  380. /* expiration */
  381. UINT32 endswap_data = tpm2_util_endian_swap_32(expiration);
  382. memcpy(raw_data + offset, (UINT8 *)&endswap_data, sizeof(INT32));
  383. offset += sizeof(INT32);
  384. /* cpHash */
  385. if (cphash_path) {
  386. memcpy(raw_data + offset, cphash.buffer, cphash.size);
  387. offset += cphash.size;
  388. }
  389. /* policyRef */
  390. memcpy(raw_data + offset, policy_qualifier.buffer,
  391. policy_qualifier.size);
  392. bool result = files_save_bytes_to_file(raw_data_path, raw_data,
  393. raw_data_len);
  394. free(raw_data);
  395. if (!result) {
  396. rc = tool_rc_general_error;
  397. }
  398. /*
  399. * We return since we only need to generate the raw signing data
  400. */
  401. goto tpm2_policy_build_policysigned_out;
  402. }
  403. rc = tpm2_policy_signed(ectx, auth_entity_obj, policy_session_handle,
  404. signature, expiration, timeout, policy_ticket, &policy_qualifier,
  405. nonce_tpm, &cphash);
  406. tpm2_policy_build_policysigned_out:
  407. Esys_Free(nonce_tpm);
  408. return rc;
  409. }
  410. tool_rc tpm2_policy_get_digest(ESYS_CONTEXT *ectx, tpm2_session *session,
  411. TPM2B_DIGEST **policy_digest) {
  412. ESYS_TR handle = tpm2_session_get_handle(session);
  413. return tpm2_policy_getdigest(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE,
  414. ESYS_TR_NONE, policy_digest);
  415. }
  416. tool_rc tpm2_policy_build_policycommandcode(ESYS_CONTEXT *ectx,
  417. tpm2_session *session, uint32_t command_code) {
  418. ESYS_TR handle = tpm2_session_get_handle(session);
  419. return tpm2_policy_command_code(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE,
  420. ESYS_TR_NONE, command_code);
  421. }
  422. tool_rc tpm2_policy_build_policynvwritten(ESYS_CONTEXT *ectx,
  423. tpm2_session *session, TPMI_YES_NO written_set) {
  424. ESYS_TR handle = tpm2_session_get_handle(session);
  425. return tpm2_policy_nv_written(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE,
  426. ESYS_TR_NONE, written_set);
  427. }
  428. tool_rc tpm2_policy_build_policylocality(ESYS_CONTEXT *ectx,
  429. tpm2_session *session, TPMA_LOCALITY locality) {
  430. ESYS_TR handle = tpm2_session_get_handle(session);
  431. return tpm2_policy_locality(ectx, handle, ESYS_TR_NONE, ESYS_TR_NONE,
  432. ESYS_TR_NONE, locality);
  433. }
  434. tool_rc tpm2_policy_build_policyduplicationselect(ESYS_CONTEXT *ectx,
  435. tpm2_session *session, const char *obj_name_path,
  436. const char *new_parent_name_path, TPMI_YES_NO is_include_obj) {
  437. TPM2B_NAME obj_name;
  438. bool result = true;
  439. if (obj_name_path) {
  440. obj_name.size = sizeof(obj_name.name);
  441. result = files_load_bytes_from_path(obj_name_path, obj_name.name,
  442. &obj_name.size);
  443. } else {
  444. obj_name.size = 0;
  445. }
  446. if (!result) {
  447. LOG_ERR("Failed to load duplicable object name.");
  448. return tool_rc_general_error;
  449. }
  450. TPM2B_NAME new_parent_name = { .size = sizeof(new_parent_name.name) };
  451. result = files_load_bytes_from_path(new_parent_name_path,
  452. new_parent_name.name, &new_parent_name.size);
  453. if (!result) {
  454. return tool_rc_general_error;
  455. }
  456. ESYS_TR handle = tpm2_session_get_handle(session);
  457. return tpm2_policy_duplication_select(ectx, handle, ESYS_TR_NONE,
  458. ESYS_TR_NONE, ESYS_TR_NONE, &obj_name, &new_parent_name,
  459. is_include_obj);
  460. }
  461. static bool tpm2_policy_populate_digest_list(char *buf,
  462. TPML_DIGEST *policy_list, TPMI_ALG_HASH hash) {
  463. uint8_t hash_len = tpm2_alg_util_get_hash_size(hash);
  464. if (!hash_len) {
  465. return false;
  466. }
  467. unsigned long file_size;
  468. bool retval = files_get_file_size_path(buf, &file_size);
  469. if (!retval) {
  470. return false;
  471. }
  472. if (file_size != hash_len) {
  473. return false;
  474. }
  475. policy_list->digests[policy_list->count].size = hash_len;
  476. /* All policy digests are expected to be of same hash len */
  477. if (policy_list->count > 0
  478. && policy_list->digests[policy_list->count].size
  479. != policy_list->digests[policy_list->count - 1].size) {
  480. return false;
  481. }
  482. uint16_t policy_digest_size = hash_len;
  483. retval = files_load_bytes_from_path(buf,
  484. policy_list->digests[policy_list->count].buffer,
  485. &policy_digest_size);
  486. if (!retval) {
  487. return false;
  488. }
  489. policy_list->count++;
  490. return true;
  491. }
  492. bool tpm2_policy_parse_policy_list(char *str, TPML_DIGEST *policy_list) {
  493. char *str1;
  494. char *str2;
  495. char *token;
  496. char *subtoken;
  497. char *saveptr1;
  498. char *saveptr2;
  499. const char *delimiter1 = ":";
  500. const char *delimiter2 = ",";
  501. unsigned int j;
  502. bool retval;
  503. TPMI_ALG_HASH hash = TPM2_ALG_ERROR;
  504. for (j = 1, str1 = str;; j++, str1 = NULL) {
  505. token = strtok_r(str1, delimiter1, &saveptr1);
  506. if (token == NULL) {
  507. break;
  508. }
  509. for (str2 = token;; str2 = NULL) {
  510. subtoken = strtok_r(str2, delimiter2, &saveptr2);
  511. if (subtoken == NULL) {
  512. break;
  513. }
  514. //Expecting one policy digest of same hash alg type for all policies
  515. if (j == 1) {
  516. hash = tpm2_alg_util_from_optarg(subtoken,
  517. tpm2_alg_util_flags_hash);
  518. if (hash == TPM2_ALG_ERROR) {
  519. LOG_ERR("Invalid/ Unspecified policy digest algorithm.");
  520. return false;
  521. }
  522. }
  523. //Multiple valid policy files
  524. if (j > 1) {
  525. retval = tpm2_policy_populate_digest_list(subtoken, policy_list,
  526. hash);
  527. if (!retval) {
  528. return false;
  529. }
  530. }
  531. }
  532. }
  533. return true;
  534. }
  535. tool_rc tpm2_policy_tool_finish(ESYS_CONTEXT *ectx, tpm2_session *session,
  536. const char *save_path) {
  537. TPM2B_DIGEST *policy_digest = NULL;
  538. tool_rc rc = tpm2_policy_get_digest(ectx, session, &policy_digest);
  539. if (rc != tool_rc_success) {
  540. LOG_ERR("Could not build tpm policy");
  541. return rc;
  542. }
  543. tpm2_util_hexdump(policy_digest->buffer, policy_digest->size);
  544. tpm2_tool_output("\n");
  545. rc = tool_rc_general_error;
  546. if (save_path) {
  547. bool result = files_save_bytes_to_file(save_path, policy_digest->buffer,
  548. policy_digest->size);
  549. if (!result) {
  550. LOG_ERR("Failed to save policy digest into file \"%s\"", save_path);
  551. goto error;
  552. }
  553. }
  554. rc = tool_rc_success;
  555. error:
  556. free(policy_digest);
  557. return rc;
  558. }