tpm2_util.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #include <ctype.h>
  3. #include <dlfcn.h>
  4. #include <inttypes.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include "files.h"
  9. #include "log.h"
  10. #include "tool_rc.h"
  11. #include "tpm2.h"
  12. #include "tpm2_alg_util.h"
  13. #include "tpm2_attr_util.h"
  14. #include "tpm2_convert.h"
  15. #include "tpm2_openssl.h"
  16. #include "tpm2_session.h"
  17. #include "tpm2_tool.h"
  18. #include "tpm2_util.h"
  19. // verify that the quote digest equals the digest we calculated
  20. bool tpm2_util_verify_digests(TPM2B_DIGEST *quoteDigest,
  21. TPM2B_DIGEST *pcr_digest) {
  22. // Sanity check -- they should at least be same size!
  23. if (quoteDigest->size != pcr_digest->size) {
  24. LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!");
  25. return false;
  26. }
  27. // Compare running digest with quote's digest
  28. int k;
  29. for (k = 0; k < quoteDigest->size; k++) {
  30. if (quoteDigest->buffer[k] != pcr_digest->buffer[k]) {
  31. LOG_ERR("FATAL ERROR: PCR values failed to match quote's digest!");
  32. return false;
  33. }
  34. }
  35. return true;
  36. }
  37. bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append) {
  38. if (!result || !append) {
  39. return false;
  40. }
  41. if (((UINT32)result->size + append->size) > TPM2_MAX_DIGEST_BUFFER) {
  42. return false;
  43. }
  44. memcpy(&result->buffer[result->size], append->buffer, append->size);
  45. result->size += append->size;
  46. return true;
  47. }
  48. bool tpm2_util_string_to_uint8(const char *str, uint8_t *value) {
  49. uint32_t tmp;
  50. bool result = tpm2_util_string_to_uint32(str, &tmp);
  51. if (!result) {
  52. return false;
  53. }
  54. /* overflow on 8 bits? */
  55. if (tmp > UINT8_MAX) {
  56. return false;
  57. }
  58. *value = (uint8_t) tmp;
  59. return true;
  60. }
  61. bool tpm2_util_string_to_uint16(const char *str, uint16_t *value) {
  62. uint32_t tmp;
  63. bool result = tpm2_util_string_to_uint32(str, &tmp);
  64. if (!result) {
  65. return false;
  66. }
  67. /* overflow on 16 bits? */
  68. if (tmp > UINT16_MAX) {
  69. return false;
  70. }
  71. *value = (uint16_t) tmp;
  72. return true;
  73. }
  74. bool tpm2_util_string_to_uint32(const char *str, uint32_t *value) {
  75. char *endptr;
  76. if (str == NULL || *str == '\0') {
  77. return false;
  78. }
  79. /* clear errno before the call, should be 0 afterwards */
  80. errno = 0;
  81. unsigned long int tmp = strtoul(str, &endptr, 0);
  82. if (errno || tmp > UINT32_MAX) {
  83. return false;
  84. }
  85. /*
  86. * The entire string should be able to be converted or fail
  87. * We already checked that str starts with a null byte, so no
  88. * need to check that again per the man page.
  89. */
  90. if (*endptr != '\0') {
  91. return false;
  92. }
  93. *value = (uint32_t) tmp;
  94. return true;
  95. }
  96. bool tpm2_util_string_to_uint64(const char *str, uint64_t *value) {
  97. char *endptr;
  98. if (str == NULL || *str == '\0') {
  99. return false;
  100. }
  101. /* clear errno before the call, should be 0 afterwards */
  102. errno = 0;
  103. /*
  104. * unsigned long long is at least 64 bits, although commonly just 64 bits even on 64 bit systems
  105. * however, ensure that on some weird system it isn't greater than 64 bits since it is allowed by
  106. * the standard.
  107. */
  108. unsigned long long int tmp = strtoull(str, &endptr, 0);
  109. if (errno || tmp > UINT64_MAX) {
  110. return false;
  111. }
  112. /*
  113. * The entire string should be able to be converted or fail
  114. * We already checked that str starts with a null byte, so no
  115. * need to check that again per the man page.
  116. */
  117. if (*endptr != '\0') {
  118. return false;
  119. }
  120. *value = (uint64_t) tmp;
  121. return true;
  122. }
  123. bool tpm2_util_string_to_int32(const char *str, int32_t *value) {
  124. char *endptr;
  125. if (str == NULL || *str == '\0') {
  126. return false;
  127. }
  128. /* clear errno before the call, should be 0 afterwards */
  129. errno = 0;
  130. signed long int tmp = strtol(str, &endptr, 0);
  131. if (errno || tmp > INT32_MAX) {
  132. return false;
  133. }
  134. /*
  135. * The entire string should be able to be converted or fail
  136. * We already checked that str starts with a null byte, so no
  137. * need to check that again per the man page.
  138. */
  139. if (*endptr != '\0') {
  140. return false;
  141. }
  142. *value = (int32_t) tmp;
  143. return true;
  144. }
  145. int tpm2_util_hex_to_byte_structure(const char *input_string, UINT16 *byte_length,
  146. BYTE *byte_buffer) {
  147. int str_length; //if the input_string likes "1a2b...", no prefix "0x"
  148. int i = 0;
  149. if (input_string == NULL || byte_length == NULL || byte_buffer == NULL)
  150. return -1;
  151. str_length = strlen(input_string);
  152. if (str_length % 2)
  153. return -2;
  154. for (i = 0; i < str_length; i++) {
  155. if (!isxdigit(input_string[i]))
  156. return -3;
  157. }
  158. if (*byte_length < str_length / 2)
  159. return -4;
  160. *byte_length = str_length / 2;
  161. for (i = 0; i < *byte_length; i++) {
  162. char tmp_str[4] = { 0 };
  163. tmp_str[0] = input_string[i * 2];
  164. tmp_str[1] = input_string[i * 2 + 1];
  165. byte_buffer[i] = strtol(tmp_str, NULL, 16);
  166. }
  167. return 0;
  168. }
  169. bool tpm2_util_bin_from_hex_or_file(const char *input, UINT16 *len, BYTE *buffer) {
  170. bool result = false;
  171. FILE *f = fopen(input, "rb");
  172. if (!f) {
  173. result = tpm2_util_hex_to_byte_structure(input, len, buffer) == 0;
  174. goto out;
  175. }
  176. result = file_read_bytes_from_file(f, buffer, len, input);
  177. fclose(f);
  178. out:
  179. if (!result) {
  180. LOG_ERR("Could not convert \"%s\". Neither a file path nor hex string.",
  181. input);
  182. }
  183. return result;
  184. }
  185. void tpm2_util_hexdump2(FILE *f, const BYTE *data, size_t len) {
  186. size_t i;
  187. for (i = 0; i < len; i++) {
  188. fprintf(f, "%02x", data[i]);
  189. }
  190. }
  191. void tpm2_util_hexdump(const BYTE *data, size_t len) {
  192. if (!output_enabled) {
  193. return;
  194. }
  195. tpm2_util_hexdump2(stdout, data, len);
  196. }
  197. bool tpm2_util_is_big_endian(void) {
  198. uint32_t test_word;
  199. uint8_t *test_byte;
  200. test_word = 0xFF000000;
  201. test_byte = (uint8_t *) (&test_word);
  202. return test_byte[0] == 0xFF;
  203. }
  204. #define STRING_BYTES_ENDIAN_CONVERT(size) \
  205. UINT##size tpm2_util_endian_swap_##size(UINT##size data) { \
  206. \
  207. UINT##size converted; \
  208. UINT8 *bytes = (UINT8 *)&data; \
  209. UINT8 *tmp = (UINT8 *)&converted; \
  210. \
  211. size_t i; \
  212. for(i=0; i < sizeof(UINT##size); i ++) { \
  213. tmp[i] = bytes[sizeof(UINT##size) - i - 1]; \
  214. } \
  215. \
  216. return converted; \
  217. }
  218. STRING_BYTES_ENDIAN_CONVERT(16)
  219. STRING_BYTES_ENDIAN_CONVERT(32)
  220. STRING_BYTES_ENDIAN_CONVERT(64)
  221. #define STRING_BYTES_ENDIAN_HTON(size) \
  222. UINT##size tpm2_util_hton_##size(UINT##size data) { \
  223. \
  224. bool is_big_endian = tpm2_util_is_big_endian(); \
  225. if (is_big_endian) { \
  226. return data; \
  227. } \
  228. \
  229. return tpm2_util_endian_swap_##size(data); \
  230. }
  231. STRING_BYTES_ENDIAN_HTON(16)
  232. STRING_BYTES_ENDIAN_HTON(32)
  233. STRING_BYTES_ENDIAN_HTON(64)
  234. /*
  235. * Converting from host-to-network (hton) or network-to-host (ntoh) is
  236. * the same operation: if endianess differs between host and data, swap
  237. * endianess. Thus we can just call the hton routines, but have some nice
  238. * names for folks.
  239. */
  240. UINT16 tpm2_util_ntoh_16(UINT16 data) {
  241. return tpm2_util_hton_16(data);
  242. }
  243. UINT32 tpm2_util_ntoh_32(UINT32 data) {
  244. return tpm2_util_hton_32(data);
  245. }
  246. UINT64 tpm2_util_ntoh_64(UINT64 data) {
  247. return tpm2_util_hton_64(data);
  248. }
  249. UINT32 tpm2_util_pop_count(UINT32 data) {
  250. static const UINT8 bits_per_nibble[] =
  251. {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
  252. UINT8 count = 0;
  253. UINT8 *d = (UINT8 *) &data;
  254. size_t i;
  255. for (i = 0; i < sizeof(data); i++) {
  256. count += bits_per_nibble[d[i] & 0x0f];
  257. count += bits_per_nibble[d[i] >> 4];
  258. }
  259. return count;
  260. }
  261. #define TPM2_UTIL_KEYDATA_INIT { .len = 0 };
  262. typedef struct tpm2_util_keydata tpm2_util_keydata;
  263. struct tpm2_util_keydata {
  264. UINT16 len;
  265. struct {
  266. const char *name;
  267. TPM2B *value;
  268. } entries[2];
  269. };
  270. static void tpm2_util_public_to_keydata(TPMT_PUBLIC *public,
  271. tpm2_util_keydata *keydata) {
  272. switch (public->type) {
  273. case TPM2_ALG_RSA:
  274. keydata->len = 1;
  275. keydata->entries[0].name = tpm2_alg_util_algtostr(
  276. public->type, tpm2_alg_util_flags_any);
  277. keydata->entries[0].value = (TPM2B *) &public->unique.rsa;
  278. return;
  279. case TPM2_ALG_KEYEDHASH:
  280. keydata->len = 1;
  281. keydata->entries[0].name = tpm2_alg_util_algtostr(
  282. public->type, tpm2_alg_util_flags_any);
  283. keydata->entries[0].value =
  284. (TPM2B *) &public->unique.keyedHash;
  285. return;
  286. case TPM2_ALG_SYMCIPHER:
  287. keydata->len = 1;
  288. keydata->entries[0].name = tpm2_alg_util_algtostr(
  289. public->type, tpm2_alg_util_flags_any);
  290. keydata->entries[0].value = (TPM2B *) &public->unique.sym;
  291. return;
  292. case TPM2_ALG_ECC:
  293. keydata->len = 2;
  294. keydata->entries[0].name = "x";
  295. keydata->entries[0].value = (TPM2B *) &public->unique.ecc.x;
  296. keydata->entries[1].name = "y";
  297. keydata->entries[1].value = (TPM2B *) &public->unique.ecc.y;
  298. return;
  299. default:
  300. LOG_WARN("The algorithm type(0x%4.4x) is not supported",
  301. public->type);
  302. }
  303. return;
  304. }
  305. void print_yaml_indent(size_t indent_count) {
  306. while (indent_count--) {
  307. tpm2_tool_output(" ");
  308. }
  309. }
  310. void tpm2_util_tpma_object_to_yaml(TPMA_OBJECT obj, char *indent) {
  311. if (!indent) {
  312. indent = "";
  313. }
  314. char *attrs = tpm2_attr_util_obj_attrtostr(obj);
  315. tpm2_tool_output("%sattributes:\n", indent);
  316. tpm2_tool_output("%s value: %s\n", indent, attrs);
  317. tpm2_tool_output("%s raw: 0x%x\n", indent, obj);
  318. free(attrs);
  319. }
  320. static void print_alg_raw(const char *name, TPM2_ALG_ID alg, const char *indent) {
  321. tpm2_tool_output("%s%s:\n", indent, name);
  322. tpm2_tool_output("%s value: %s\n", indent,
  323. tpm2_alg_util_algtostr(alg, tpm2_alg_util_flags_any));
  324. tpm2_tool_output("%s raw: 0x%x\n", indent, alg);
  325. }
  326. static void print_scheme_common(TPMI_ALG_RSA_SCHEME scheme, const char *indent) {
  327. print_alg_raw("scheme", scheme, indent);
  328. }
  329. static void print_sym(TPMT_SYM_DEF_OBJECT *sym, const char *indent) {
  330. print_alg_raw("sym-alg", sym->algorithm, indent);
  331. print_alg_raw("sym-mode", sym->mode.sym, indent);
  332. tpm2_tool_output("%ssym-keybits: %u\n", indent, sym->keyBits.sym);
  333. }
  334. static void print_rsa_scheme(TPMT_RSA_SCHEME *scheme, const char *indent) {
  335. print_scheme_common(scheme->scheme, indent);
  336. /*
  337. * everything is a union on a hash algorithm except for RSAES which
  338. * has nothing. So on RSAES skip the hash algorithm printing
  339. */
  340. if (scheme->scheme != TPM2_ALG_RSAES) {
  341. print_alg_raw("scheme-halg", scheme->details.oaep.hashAlg, indent);
  342. }
  343. }
  344. static void print_ecc_scheme(TPMT_ECC_SCHEME *scheme, const char *indent) {
  345. print_scheme_common(scheme->scheme, indent);
  346. /*
  347. * everything but ecdaa uses only hash alg
  348. * in a union, so we only need to do things differently
  349. * for ecdaa.
  350. */
  351. print_alg_raw("scheme-halg", scheme->details.oaep.hashAlg, indent);
  352. if (scheme->scheme == TPM2_ALG_ECDAA) {
  353. tpm2_tool_output("%sscheme-count: %u\n", indent,
  354. scheme->details.ecdaa.count);
  355. }
  356. }
  357. static void print_kdf_scheme(TPMT_KDF_SCHEME *kdf, const char *indent) {
  358. print_alg_raw("kdfa-alg", kdf->scheme, indent);
  359. /*
  360. * The hash algorithm for the KDFA is in a union, just grab one of them.
  361. */
  362. print_alg_raw("kdfa-halg", kdf->details.mgf1.hashAlg, indent);
  363. }
  364. void tpm2_util_tpmt_public_to_yaml(TPMT_PUBLIC *public, char *indent) {
  365. if (!indent) {
  366. indent = "";
  367. }
  368. tpm2_tool_output("%sname-alg:\n", indent);
  369. tpm2_tool_output("%s value: %s\n", indent,
  370. tpm2_alg_util_algtostr(public->nameAlg,
  371. tpm2_alg_util_flags_any));
  372. tpm2_tool_output("%s raw: 0x%x\n", indent, public->nameAlg);
  373. tpm2_util_tpma_object_to_yaml(public->objectAttributes, indent);
  374. tpm2_tool_output("%stype:\n", indent);
  375. tpm2_tool_output("%s value: %s\n", indent,
  376. tpm2_alg_util_algtostr(public->type,
  377. tpm2_alg_util_flags_any));
  378. tpm2_tool_output("%s raw: 0x%x\n", indent, public->type);
  379. switch (public->type) {
  380. case TPM2_ALG_SYMCIPHER: {
  381. TPMS_SYMCIPHER_PARMS *s = &public->parameters.symDetail;
  382. print_sym(&s->sym, indent);
  383. }
  384. break;
  385. case TPM2_ALG_KEYEDHASH: {
  386. TPMS_KEYEDHASH_PARMS *k = &public->parameters.keyedHashDetail;
  387. tpm2_tool_output("%salgorithm: \n", indent);
  388. tpm2_tool_output("%s value: %s\n", indent,
  389. tpm2_alg_util_algtostr(k->scheme.scheme,
  390. tpm2_alg_util_flags_any));
  391. tpm2_tool_output("%s raw: 0x%x\n", indent, k->scheme.scheme);
  392. if (k->scheme.scheme == TPM2_ALG_HMAC) {
  393. tpm2_tool_output("%shash-alg:\n", indent);
  394. tpm2_tool_output("%s value: %s\n", indent,
  395. tpm2_alg_util_algtostr(k->scheme.details.hmac.hashAlg,
  396. tpm2_alg_util_flags_any));
  397. tpm2_tool_output("%s raw: 0x%x\n", indent,
  398. k->scheme.details.hmac.hashAlg);
  399. } else if (k->scheme.scheme == TPM2_ALG_XOR) {
  400. tpm2_tool_output("%shash-alg:\n", indent);
  401. tpm2_tool_output("%s value: %s\n", indent,
  402. tpm2_alg_util_algtostr(
  403. k->scheme.details.exclusiveOr.hashAlg,
  404. tpm2_alg_util_flags_any));
  405. tpm2_tool_output("%s raw: 0x%x\n", indent,
  406. k->scheme.details.exclusiveOr.hashAlg);
  407. tpm2_tool_output("%skdfa-alg:\n", indent);
  408. tpm2_tool_output("%s value: %s\n", indent,
  409. tpm2_alg_util_algtostr(k->scheme.details.exclusiveOr.kdf,
  410. tpm2_alg_util_flags_any));
  411. tpm2_tool_output("%s raw: 0x%x\n", indent,
  412. k->scheme.details.exclusiveOr.kdf);
  413. }
  414. }
  415. break;
  416. case TPM2_ALG_RSA: {
  417. TPMS_RSA_PARMS *r = &public->parameters.rsaDetail;
  418. tpm2_tool_output("%sexponent: %u\n", indent, r->exponent ? r->exponent : 65537);
  419. tpm2_tool_output("%sbits: %u\n", indent, r->keyBits);
  420. print_rsa_scheme(&r->scheme, indent);
  421. print_sym(&r->symmetric, indent);
  422. }
  423. break;
  424. case TPM2_ALG_ECC: {
  425. TPMS_ECC_PARMS *e = &public->parameters.eccDetail;
  426. tpm2_tool_output("%scurve-id:\n", indent);
  427. tpm2_tool_output("%s value: %s\n", indent,
  428. tpm2_alg_util_ecc_to_str(e->curveID));
  429. tpm2_tool_output("%s raw: 0x%x\n", indent, e->curveID);
  430. print_kdf_scheme(&e->kdf, indent);
  431. print_ecc_scheme(&e->scheme, indent);
  432. print_sym(&e->symmetric, indent);
  433. }
  434. break;
  435. }
  436. tpm2_util_keydata keydata = TPM2_UTIL_KEYDATA_INIT
  437. ;
  438. tpm2_util_public_to_keydata(public, &keydata);
  439. UINT16 i;
  440. /* if no keydata len will be 0 and it wont print */
  441. for (i = 0; i < keydata.len; i++) {
  442. tpm2_tool_output("%s%s: ", indent, keydata.entries[i].name);
  443. tpm2_util_print_tpm2b(keydata.entries[i].value);
  444. tpm2_tool_output("%s\n", indent);
  445. }
  446. if (public->authPolicy.size) {
  447. tpm2_tool_output("%sauthorization policy: ", indent);
  448. tpm2_util_hexdump(public->authPolicy.buffer,
  449. public->authPolicy.size);
  450. tpm2_tool_output("%s\n", indent);
  451. }
  452. }
  453. void tpm2_util_public_to_yaml(TPM2B_PUBLIC *public, char *indent) {
  454. tpm2_util_tpmt_public_to_yaml(&public->publicArea, indent);
  455. }
  456. bool tpm2_util_calc_unique(TPMI_ALG_HASH name_alg,
  457. TPM2B_PRIVATE_VENDOR_SPECIFIC *key, TPM2B_DIGEST *seed,
  458. TPM2B_DIGEST *unique_data) {
  459. TPM2B_MAX_BUFFER buf = { .size = key->size + seed->size };
  460. if (buf.size > sizeof(buf.buffer)) {
  461. LOG_ERR("Seed and key size are too big");
  462. return false;
  463. }
  464. memcpy(buf.buffer, seed->buffer, seed->size);
  465. memcpy(&buf.buffer[seed->size], key->buffer, key->size);
  466. digester d = tpm2_openssl_halg_to_digester(name_alg);
  467. if (!d) {
  468. return false;
  469. }
  470. unique_data->size = tpm2_alg_util_get_hash_size(name_alg);
  471. d(buf.buffer, buf.size, unique_data->buffer);
  472. return true;
  473. }
  474. ESYS_TR tpm2_tpmi_hierarchy_to_esys_tr(TPMI_RH_PROVISION inh) {
  475. switch (inh) {
  476. case TPM2_RH_OWNER:
  477. return ESYS_TR_RH_OWNER;
  478. case TPM2_RH_PLATFORM:
  479. return ESYS_TR_RH_PLATFORM;
  480. case TPM2_RH_ENDORSEMENT:
  481. return ESYS_TR_RH_ENDORSEMENT;
  482. case TPM2_RH_NULL:
  483. return ESYS_TR_RH_NULL;
  484. case TPM2_RH_LOCKOUT:
  485. return ESYS_TR_RH_LOCKOUT;
  486. }
  487. return ESYS_TR_NONE;
  488. }
  489. tool_rc tpm2_util_sys_handle_to_esys_handle(ESYS_CONTEXT *context,
  490. TPM2_HANDLE sys_handle, ESYS_TR *esys_handle) {
  491. ESYS_TR h = tpm2_tpmi_hierarchy_to_esys_tr(sys_handle);
  492. if (h != ESYS_TR_NONE) {
  493. *esys_handle = h;
  494. return tool_rc_success;
  495. }
  496. return tpm2_from_tpm_public(context, sys_handle, ESYS_TR_NONE, ESYS_TR_NONE,
  497. ESYS_TR_NONE, esys_handle);
  498. }
  499. char *tpm2_util_getenv(const char *name) {
  500. return getenv(name);
  501. }
  502. /**
  503. * Parses a hierarchy value from an option argument.
  504. * @param value
  505. * The string to parse, which can be a numerical string as
  506. * understood by strtoul() with a base of 0, or an:
  507. * - o - Owner hierarchy
  508. * - p - Platform hierarchy
  509. * - e - Endorsement hierarchy
  510. * - n - Null hierarchy
  511. * @param hierarchy
  512. * The parsed hierarchy as output.
  513. * @param flags
  514. * What hierarchies should be supported by
  515. * the parsing.
  516. * @return
  517. * True on success, False otherwise.
  518. */
  519. static bool filter_hierarchy_handles(TPMI_RH_PROVISION hierarchy,
  520. tpm2_handle_flags flags) {
  521. switch (hierarchy) {
  522. case TPM2_RH_OWNER:
  523. if (!(flags & TPM2_HANDLE_FLAGS_O)) {
  524. LOG_ERR("Unexpected handle - TPM2_RH_OWNER");
  525. return false;
  526. }
  527. break;
  528. case TPM2_RH_PLATFORM:
  529. if (!(flags & TPM2_HANDLE_FLAGS_P)) {
  530. LOG_ERR("Unexpected handle - TPM2_RH_PLATFORM");
  531. return false;
  532. }
  533. break;
  534. case TPM2_RH_ENDORSEMENT:
  535. if (!(flags & TPM2_HANDLE_FLAGS_E)) {
  536. LOG_ERR("Unexpected handle - TPM2_RH_ENDORSEMENT");
  537. return false;
  538. }
  539. break;
  540. case TPM2_RH_NULL:
  541. if (!(flags & TPM2_HANDLE_FLAGS_N)) {
  542. LOG_ERR("Unexpected handle - TPM2_RH_NULL");
  543. return false;
  544. }
  545. break;
  546. case TPM2_RH_LOCKOUT:
  547. if (!(flags & TPM2_HANDLE_FLAGS_L)) {
  548. LOG_ERR("Unexpected handle - TPM2_RH_LOCKOUT");
  549. return false;
  550. }
  551. break;
  552. default: //If specified a random offset to the permanent handle range
  553. if (flags == TPM2_HANDLE_ALL_W_NV || flags == TPM2_HANDLE_FLAGS_NONE) {
  554. return true;
  555. }
  556. return false;
  557. }
  558. return true;
  559. }
  560. static bool filter_handles(TPMI_RH_PROVISION *hierarchy,
  561. tpm2_handle_flags flags) {
  562. TPM2_RH range = *hierarchy & TPM2_HR_RANGE_MASK;
  563. /*
  564. * if their is no range, then it could be NV or PCR, use flags
  565. * to figure out what it is.
  566. */
  567. if (range == 0) {
  568. if (flags & TPM2_HANDLE_FLAGS_NV) {
  569. *hierarchy += TPM2_HR_NV_INDEX;
  570. range = *hierarchy & TPM2_HR_RANGE_MASK;
  571. } else if (flags & TPM2_HANDLE_FLAGS_PCR) {
  572. *hierarchy += TPM2_HR_PCR;
  573. range = *hierarchy & TPM2_HR_RANGE_MASK;
  574. } else {
  575. LOG_ERR("Implicit indices are not supported.");
  576. return false;
  577. }
  578. }
  579. /* now that we have fixed up any non-ranged handles, check them */
  580. if (range == TPM2_HR_NV_INDEX) {
  581. if (!(flags & TPM2_HANDLE_FLAGS_NV)) {
  582. LOG_ERR("NV-Index handles are not supported by this command.");
  583. return false;
  584. }
  585. if (*hierarchy < TPM2_NV_INDEX_FIRST
  586. || *hierarchy > TPM2_NV_INDEX_LAST) {
  587. LOG_ERR("NV-Index handle is out of range.");
  588. return false;
  589. }
  590. return true;
  591. } else if (range == TPM2_HR_PCR) {
  592. if (!(flags & TPM2_HANDLE_FLAGS_PCR)) {
  593. LOG_ERR("PCR handles are not supported by this command.");
  594. return false;
  595. }
  596. /* first is 0 so no possible way unsigned is less than 0, thus no check */
  597. if (*hierarchy > TPM2_PCR_LAST) {
  598. LOG_ERR("PCR handle out of range.");
  599. return false;
  600. }
  601. return true;
  602. } else if (range == TPM2_HR_TRANSIENT) {
  603. if (!(flags & TPM2_HANDLES_FLAGS_TRANSIENT)) {
  604. LOG_ERR("Transient handles are not supported by this command.");
  605. return false;
  606. }
  607. return true;
  608. } else if (range == TPM2_HR_PERMANENT) {
  609. return filter_hierarchy_handles(*hierarchy, flags);
  610. } else if (range == TPM2_HR_PERSISTENT) {
  611. if (!(flags & TPM2_HANDLES_FLAGS_PERSISTENT)) {
  612. LOG_ERR("Persistent handles are not supported by this command.");
  613. return false;
  614. }
  615. if (*hierarchy < TPM2_PERSISTENT_FIRST
  616. || *hierarchy > TPM2_PERSISTENT_LAST) {
  617. LOG_ERR("Persistent handle out of range.");
  618. return false;
  619. }
  620. return true;
  621. }
  622. /* else its a session flag and shouldn't use this interface */
  623. return false;
  624. }
  625. bool tpm2_util_handle_from_optarg(const char *value,
  626. TPMI_RH_PROVISION *hierarchy, tpm2_handle_flags flags) {
  627. if (!value || !value[0]) {
  628. return false;
  629. }
  630. if ((flags & TPM2_HANDLE_FLAGS_NV) && (flags & TPM2_HANDLE_FLAGS_PCR)) {
  631. LOG_ERR("Cannot specify NV and PCR index together");
  632. return false;
  633. }
  634. *hierarchy = 0;
  635. bool is_o = !strncmp(value, "owner", strlen(value));
  636. if (is_o) {
  637. *hierarchy = TPM2_RH_OWNER;
  638. }
  639. bool is_p = !strncmp(value, "platform", strlen(value));
  640. if (is_p) {
  641. *hierarchy = TPM2_RH_PLATFORM;
  642. }
  643. bool is_e = !strncmp(value, "endorsement", strlen(value));
  644. if (is_e) {
  645. *hierarchy = TPM2_RH_ENDORSEMENT;
  646. }
  647. bool is_n = !strncmp(value, "null", strlen(value));
  648. if (is_n) {
  649. *hierarchy = TPM2_RH_NULL;
  650. }
  651. bool is_l = !strncmp(value, "lockout", strlen(value));
  652. if (is_l) {
  653. *hierarchy = TPM2_RH_LOCKOUT;
  654. }
  655. bool result = true;
  656. if (!*hierarchy) {
  657. /*
  658. * This branch is executed when hierarchy is specified as a hex handle.
  659. * The raw hex returned may be a generic (non hierarchy) TPM2_HANDLE.
  660. */
  661. result = tpm2_util_string_to_uint32(value, hierarchy);
  662. }
  663. if (!result) {
  664. char msg[256] = { 0 };
  665. char print_flags[32] = { '[', '\0' };
  666. if (flags & TPM2_HANDLE_FLAGS_O) {
  667. strncat(print_flags, "o|",
  668. sizeof(print_flags) - strlen(print_flags) - 1);
  669. }
  670. if (flags & TPM2_HANDLE_FLAGS_P) {
  671. strncat(print_flags, "p|",
  672. sizeof(print_flags) - strlen(print_flags) - 1);
  673. }
  674. if (flags & TPM2_HANDLE_FLAGS_E) {
  675. strncat(print_flags, "e|",
  676. sizeof(print_flags) - strlen(print_flags) - 1);
  677. }
  678. if (flags & TPM2_HANDLE_FLAGS_N) {
  679. strncat(print_flags, "n|",
  680. sizeof(print_flags) - strlen(print_flags) - 1);
  681. }
  682. if (flags & TPM2_HANDLE_FLAGS_L) {
  683. strncat(print_flags, "l|",
  684. sizeof(print_flags) - strlen(print_flags) - 1);
  685. }
  686. size_t len = strlen(print_flags);
  687. if (print_flags[len - 1] == '|') {
  688. len--;
  689. print_flags[len] = '\0';
  690. }
  691. strncat(print_flags, "]",
  692. sizeof(print_flags) - strlen(print_flags) - 1);
  693. len++;
  694. bool has_print_flags = len > 2;
  695. if (has_print_flags) {
  696. snprintf(msg, sizeof(msg), "expected %s or ", print_flags);
  697. }
  698. strncat(msg, "a handle number", sizeof(msg) - strlen(msg) - 1);
  699. LOG_ERR("Incorrect handle value, got: \"%s\", expected %s", value, msg);
  700. return false;
  701. }
  702. /*
  703. * If the caller specifies the expected valid hierarchies, either as string,
  704. * or hex handles, they are additionally filtered here.
  705. */
  706. bool res = filter_handles(hierarchy, flags);
  707. if (!res) {
  708. LOG_ERR("Unknown or unsupported handle, got: \"%s\"", value);
  709. }
  710. return res;
  711. }
  712. bool tpm2_util_get_label(const char *value, TPM2B_DATA *label) {
  713. if (!value) {
  714. label->size = 0;
  715. return true;
  716. }
  717. FILE *f = fopen(value, "rb");
  718. if (f) {
  719. /* set size one smaller for NUL byte */
  720. label->size = sizeof(label->buffer) - 1;
  721. size_t cnt = fread(label->buffer, 1, label->size, f);
  722. if (!feof(f)) {
  723. LOG_ERR("label file \"%s\" larger than expected. Expected %u",
  724. value, label->size);
  725. fclose(f);
  726. return false;
  727. }
  728. if (ferror(f)) {
  729. LOG_ERR("reading label file \"%s\" error: %s", value,
  730. strerror(errno));
  731. fclose(f);
  732. return false;
  733. }
  734. fclose(f);
  735. label->size = cnt;
  736. /* Set NUL byte and increment */
  737. label->buffer[label->size++] = '\0';
  738. return true;
  739. }
  740. size_t len = strlen(value);
  741. if (len > sizeof(label->buffer) - 1) {
  742. LOG_ERR("label file \"%s\" larger than expected. Expected %zu", value,
  743. sizeof(label->buffer) - 1);
  744. return false;
  745. }
  746. memcpy(label->buffer, value, len);
  747. label->size = len;
  748. /* Set NUL byte and increment */
  749. label->buffer[label->size++] = '\0';
  750. return true;
  751. }
  752. void tpm2_util_print_time(const TPMS_TIME_INFO *current_time) {
  753. tpm2_tool_output("time: %"PRIu64"\n", current_time->time);
  754. tpm2_tool_output("clock_info:\n");
  755. tpm2_tool_output(" clock: %"PRIu64"\n",
  756. current_time->clockInfo.clock);
  757. tpm2_tool_output(" reset_count: %"PRIu32"\n",
  758. current_time->clockInfo.resetCount);
  759. tpm2_tool_output(" restart_count: %"PRIu32"\n",
  760. current_time->clockInfo.restartCount);
  761. tpm2_tool_output(" safe: %s\n",
  762. current_time->clockInfo.safe ? "yes" : "no");
  763. }
  764. bool tpm2_calq_qname(TPM2B_NAME *pqname,
  765. TPMI_ALG_HASH halg, TPM2B_NAME *name, TPM2B_NAME *qname) {
  766. // QNB ≔ HB (QNA || NAMEB)
  767. bool result = false;
  768. const EVP_MD *md = tpm2_openssl_halg_from_tpmhalg(halg);
  769. EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
  770. if (!mdctx) {
  771. LOG_ERR("%s", tpm2_openssl_get_err());
  772. return false;
  773. }
  774. int rc = EVP_DigestInit_ex(mdctx, md, NULL);
  775. if (!rc) {
  776. LOG_ERR("%s", tpm2_openssl_get_err());
  777. goto out;
  778. }
  779. size_t offset = sizeof(halg);
  780. rc = EVP_DigestUpdate(mdctx, pqname->name, pqname->size);
  781. if (!rc) {
  782. LOG_ERR("%s", tpm2_openssl_get_err());
  783. goto out;
  784. }
  785. rc = EVP_DigestUpdate(mdctx, name->name, name->size);
  786. if (!rc) {
  787. LOG_ERR("%s", tpm2_openssl_get_err());
  788. goto out;
  789. }
  790. unsigned size = EVP_MD_size(md);
  791. rc = EVP_DigestFinal_ex(mdctx, &qname->name[offset], &size);
  792. if (!rc) {
  793. LOG_ERR("%s", tpm2_openssl_get_err());
  794. goto out;
  795. }
  796. /* hash sizes are not bigger than 16 bits, safe truncate */
  797. qname->size = (UINT16)size;
  798. /* put the hash alg on the front, since name already has it in marshalled
  799. * proper form just use it.
  800. */
  801. memcpy(qname->name, name->name, offset);
  802. qname->size += offset;
  803. result = true;
  804. out:
  805. EVP_MD_CTX_destroy(mdctx);
  806. return result;
  807. }
  808. bool tpm2_safe_read_from_stdin(int length, char *data) {
  809. int rc;
  810. char *buf = malloc(length);
  811. char *read_data = malloc(length);
  812. if (buf == fgets(buf, length, stdin)) {
  813. rc = sscanf(buf, "%s", read_data);
  814. if (rc != 1) {
  815. free(buf);
  816. free(read_data);
  817. return false;
  818. }
  819. }
  820. else {
  821. free(buf);
  822. free(read_data);
  823. return false;
  824. }
  825. strcpy(data, read_data);
  826. free(buf);
  827. free(read_data);
  828. return true;
  829. }
  830. bool tpm2_pem_encoded_key_to_fingerprint(const char *pem_encoded_key,
  831. char *fingerprint) {
  832. bool is_pemkey_len_valid = strlen(pem_encoded_key) > 1024 ? false : true;
  833. if (!is_pemkey_len_valid) {
  834. return false;
  835. }
  836. char str[1024] = "";
  837. strcpy(str, pem_encoded_key);
  838. /* walk through other tokens */
  839. char base64[1024] = "";
  840. char *token = strtok(str, "\n");
  841. while ( token != NULL ) {
  842. if (!strstr(token, "-----")) {
  843. bool is_base64_overrun = (strlen(base64) + strlen(token)) > 1024 ?
  844. true : false;
  845. if (is_base64_overrun) {
  846. return false;
  847. }
  848. strcat(base64, token);
  849. }
  850. token = strtok(NULL, "\n");
  851. }
  852. BYTE buffer[1024];
  853. size_t buffer_length = 0;
  854. int rc = tpm2_base64_decode(base64, buffer, &buffer_length);
  855. if(!rc){
  856. LOG_ERR("%s", "tpm2_base64_decode");
  857. return false;
  858. }
  859. TPM2B_DIGEST digest;
  860. rc = tpm2_openssl_hash_compute_data(TPM2_ALG_SHA256, buffer,
  861. buffer_length, &digest);
  862. if(!rc){
  863. LOG_ERR("%s", "tpm2_openssl_hash_compute_data");
  864. return false;
  865. }
  866. rc = tpm2_base64_encode(buffer, buffer_length, base64);
  867. if(!rc){
  868. LOG_ERR("%s", "tpm2_base64_decode");
  869. return false;
  870. }
  871. strcpy(fingerprint, "SHA256:");
  872. strcat(fingerprint, base64);
  873. fingerprint[strlen(fingerprint)-1] = 0; // remove trailing \n
  874. return true;
  875. }
  876. #define MAX_SESSION_CNT 3
  877. tool_rc tpm2_util_aux_sessions_setup(ESYS_CONTEXT *ectx, uint8_t session_cnt,
  878. const char **session_path, ESYS_TR *session_handle,
  879. tpm2_session **session) {
  880. /*
  881. * If no aux sessions were specified, simply return.
  882. */
  883. if (!session_cnt) {
  884. return tool_rc_success;
  885. }
  886. if (session_cnt > MAX_SESSION_CNT) {
  887. LOG_ERR("A max of 3 sessions allowed");
  888. return tool_rc_general_error;
  889. }
  890. uint8_t session_idx = 0;
  891. for (session_idx = 0; session_idx < (session_cnt); session_idx++) {
  892. if (session_path[session_idx]) {
  893. tool_rc rc = tpm2_session_restore(ectx,
  894. session_path[session_idx], false, &session[session_idx]);
  895. if (rc != tool_rc_success) {
  896. LOG_ERR("Could not restore aux-session #%s",
  897. session_path[session_idx]);
  898. return rc;
  899. }
  900. session_handle[session_idx] =
  901. tpm2_session_get_handle(session[session_idx]);
  902. }
  903. }
  904. return tool_rc_success;
  905. }
  906. static TPMI_ALG_HASH calc_phash_alg_from_phash_path(const char **phash_path) {
  907. if (!*phash_path) {
  908. return TPM2_ALG_ERROR;
  909. }
  910. /*
  911. * Expecting single token, so tokenize just once.
  912. */
  913. char *str = malloc(strlen(*phash_path) + 1);
  914. strcpy(str, *phash_path);
  915. char *token = strtok(str, ":");
  916. TPMI_ALG_HASH hashalg = tpm2_alg_util_from_optarg(
  917. token, tpm2_alg_util_flags_hash);
  918. /*
  919. * Adjust the pHash path to skip the <halg>:
  920. */
  921. if (hashalg != TPM2_ALG_ERROR) {
  922. *phash_path += strlen(token) + 1;
  923. }
  924. free(str);
  925. return hashalg;
  926. }
  927. static TPMI_ALG_HASH tpm2_util_calc_phash_algorithm_from_session_types(
  928. ESYS_CONTEXT *ectx, tpm2_session **sessions) {
  929. TPMI_ALG_HASH rethash = TPM2_ALG_SHA256;
  930. size_t session_idx = 0;
  931. for (session_idx = 0; session_idx < MAX_SESSION_CNT; session_idx++) {
  932. if(!sessions[session_idx]) {
  933. continue;
  934. }
  935. TPM2_SE session_type = tpm2_session_get_type(sessions[session_idx]);
  936. if (session_type != TPM2_SE_HMAC && session_type != TPM2_SE_POLICY) {
  937. continue;
  938. }
  939. /*
  940. * If this is an audit session, use that session halg.
  941. * Note: Audit sessions are always HMAC type.
  942. */
  943. if (session_type == TPM2_SE_HMAC) {
  944. TPMA_SESSION attrs = 0;
  945. ESYS_TR session_handle = tpm2_session_get_handle(
  946. sessions[session_idx]);
  947. tool_rc tmp_rc = tpm2_sess_get_attributes(ectx, session_handle,
  948. &attrs);
  949. UNUSED(tmp_rc);
  950. if (attrs & TPMA_SESSION_AUDIT) {
  951. rethash = tpm2_session_get_authhash(sessions[session_idx]);
  952. break;
  953. }
  954. }
  955. /*
  956. * If no other sessions remain, simply use this sessions halg.
  957. */
  958. rethash = tpm2_session_get_authhash(sessions[session_idx]);
  959. }
  960. return rethash;
  961. }
  962. /*
  963. * It should be noted that the auths aren't checked when calculating the pHash,
  964. * instead the sessions are consumed to determine the pHash algorithm.
  965. *
  966. * 1. If phash_path is preceded with <halg>: use that as phash-halg return
  967. * Otherwise
  968. *
  969. * Consume session only if it is a policy-session or an hmac-session
  970. * 1. If only hmac or policy session is specified, return that session's halg
  971. * 2. If hmac-session with audit is specified, return that session's halg
  972. * 3. If policy-session, then return policy-session's halg
  973. *
  974. * Otherwise
  975. * return SHA256
  976. *
  977. */
  978. TPMI_ALG_HASH tpm2_util_calculate_phash_algorithm(ESYS_CONTEXT *ectx,
  979. const char **cphash_path, TPM2B_DIGEST *cp_hash, const char **rphash_path,
  980. TPM2B_DIGEST *rp_hash, tpm2_session **sessions) {
  981. if (!cphash_path && !rphash_path) {
  982. return TPM2_ALG_ERROR;
  983. }
  984. TPMI_ALG_HASH cphash_alg = cphash_path ? calc_phash_alg_from_phash_path(
  985. cphash_path) : TPM2_ALG_ERROR;
  986. TPMI_ALG_HASH rphash_alg = rphash_path ? calc_phash_alg_from_phash_path(
  987. rphash_path) : TPM2_ALG_ERROR;
  988. /*
  989. * Default to cphash_alg if both are specified.
  990. * This removes the conflict if cphash_alg and rphash_alg don't match.
  991. * This also sets the cphash_alg if only rphash_alg is specified and vice
  992. * versa.
  993. */
  994. TPMI_ALG_HASH phash_alg = cphash_alg != TPM2_ALG_ERROR ? cphash_alg :
  995. (rphash_alg != TPM2_ALG_ERROR ? rphash_alg : TPM2_ALG_ERROR);
  996. /*
  997. * pHash was enforced with <halg>:phash_path
  998. */
  999. if (phash_alg != TPM2_ALG_ERROR) {
  1000. goto out;
  1001. }
  1002. phash_alg = tpm2_util_calc_phash_algorithm_from_session_types(ectx,
  1003. sessions);
  1004. out:
  1005. /*
  1006. * Calculate size here because with pHash_path information there is no
  1007. * confusion on whether or not to set cp or rp sizes or both.
  1008. */
  1009. if (cphash_path) {
  1010. cp_hash->size = tpm2_alg_util_get_hash_size(phash_alg);
  1011. }
  1012. if (rphash_path) {
  1013. rp_hash->size = tpm2_alg_util_get_hash_size(phash_alg);
  1014. }
  1015. return phash_alg;
  1016. }