tpm2_util.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /* SPDX-License-Identifier: BSD-3-Clause */
  2. #ifndef STRING_BYTES_H
  3. #define STRING_BYTES_H
  4. #include <stdbool.h>
  5. #include <stdint.h>
  6. #include <stdio.h>
  7. #include <tss2/tss2_esys.h>
  8. #include "tpm2_session.h"
  9. #if defined (__GNUC__)
  10. #define COMPILER_ATTR(...) __attribute__((__VA_ARGS__))
  11. #else
  12. #define COMPILER_ATTR(...)
  13. #endif
  14. #define xstr(s) str(s)
  15. #define str(s) #s
  16. #define UNUSED(x) (void)x
  17. #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
  18. #define PSTR(x) x ? x : "(null)"
  19. #define BUFFER_SIZE(type, field) (sizeof((((type *)NULL)->field)))
  20. #define TSS2_APP_RC_LAYER TSS2_RC_LAYER(5)
  21. #define TPM2B_TYPE_INIT(type, field) { .size = BUFFER_SIZE(type, field), }
  22. #define TPM2B_INIT(xsize) { .size = xsize, }
  23. #define TPM2B_EMPTY_INIT TPM2B_INIT(0)
  24. #define TPM2B_SENSITIVE_CREATE_EMPTY_INIT { \
  25. .sensitive = { \
  26. .data = { \
  27. .size = 0 \
  28. }, \
  29. .userAuth = { \
  30. .size = 0 \
  31. } \
  32. } \
  33. }
  34. #define TPMT_TK_CREATION_EMPTY_INIT { \
  35. .tag = 0, \
  36. .hierarchy = 0, \
  37. .digest = TPM2B_EMPTY_INIT \
  38. }
  39. #define TPML_PCR_SELECTION_EMPTY_INIT { \
  40. .count = 0, \
  41. } //ignore pcrSelections since count is 0.
  42. #define TPMS_CAPABILITY_DATA_EMPTY_INIT { \
  43. .capability = 0, \
  44. } // ignore data since capability is 0.
  45. #define TPMT_TK_HASHCHECK_EMPTY_INIT { \
  46. .tag = 0, \
  47. .hierarchy = 0, \
  48. .digest = TPM2B_EMPTY_INIT \
  49. }
  50. #define TSS2L_SYS_AUTH_COMMAND_INIT(cnt, array) { \
  51. .count = cnt, \
  52. .auths = array, \
  53. }
  54. /*
  55. * This macro is useful as a wrapper around SAPI functions to automatically
  56. * retry function calls when the RC is TPM2_RC_RETRY.
  57. */
  58. #define TSS2_RETRY_EXP(expression) \
  59. ({ \
  60. TSS2_RC __result = 0; \
  61. do { \
  62. __result = (expression); \
  63. } while (tpm2_error_get(__result) == TPM2_RC_RETRY); \
  64. __result; \
  65. })
  66. typedef struct {
  67. UINT16 size;
  68. BYTE buffer[0];
  69. } TPM2B;
  70. int tpm2_util_hex_to_byte_structure(const char *in_str, UINT16 *byte_length,
  71. BYTE *byte_buffer);
  72. /**
  73. * Compares two digests to ensure they are equal (for validation).
  74. * @param quote_digest
  75. * The digest from the quote.
  76. * @param pcr_digest
  77. * The digest calculated off-TMP from the PCRs.
  78. * @return
  79. * True on success, false otherwise.
  80. */
  81. bool tpm2_util_verify_digests(TPM2B_DIGEST *quote_digest,
  82. TPM2B_DIGEST *pcr_digest);
  83. /**
  84. * Appends a TPM2B buffer to a MAX buffer.
  85. * @param result
  86. * The MAX buffer to append to
  87. * @param append
  88. * The buffer to append to result.
  89. * @return
  90. * true on success, false otherwise.
  91. */
  92. bool tpm2_util_concat_buffer(TPM2B_MAX_BUFFER *result, TPM2B *append);
  93. /**
  94. * Converts a numerical string into a int32_t value.
  95. * @param str
  96. * The numerical string to convert.
  97. * @param value
  98. * The value to store the conversion into.
  99. * @return
  100. * true on success, false otherwise.
  101. */
  102. bool tpm2_util_string_to_int32(const char *str, int32_t *value);
  103. /**
  104. * Converts a numerical string into a uint32 value.
  105. * @param str
  106. * The numerical string to convert.
  107. * @param value
  108. * The value to store the conversion into.
  109. * @return
  110. * true on success, false otherwise.
  111. */
  112. bool tpm2_util_string_to_uint32(const char *str, uint32_t *value);
  113. /**
  114. * Converts a numerical string into a uint64 value.
  115. * @param str
  116. * The numerical string to convert.
  117. * @param value
  118. * The value to store the conversion into.
  119. * @return
  120. * true on success, false otherwise.
  121. */
  122. bool tpm2_util_string_to_uint64(const char *str, uint64_t *value);
  123. /**
  124. * Converts a numerical string into a uint16 value.
  125. * @param str
  126. * The numerical string to convert.
  127. * @param value
  128. * The value to store the conversion into.
  129. * @return
  130. * true on success, false otherwise.
  131. */
  132. bool tpm2_util_string_to_uint16(const char *str, uint16_t *value);
  133. /**
  134. * Converts a numerical string into a uint8 value.
  135. * @param str
  136. * The numerical string to convert.
  137. * @param value
  138. * The value to store the conversion into.
  139. * @return
  140. * true on success, false otherwise.
  141. */
  142. bool tpm2_util_string_to_uint8(const char *str, uint8_t *value);
  143. /**
  144. * Prints an xxd compatible hexdump to stdout if output is enabled,
  145. * ie no -Q option.
  146. *
  147. * @param data
  148. * The data to print.
  149. * @param len
  150. * The length of the data.
  151. */
  152. void tpm2_util_hexdump(const BYTE *data, size_t len);
  153. /**
  154. * Similar to tpm2_util_hexdump(), but:
  155. * - does NOT respect the -Q option
  156. * - allows specification of the output stream.
  157. * @param f
  158. * The FILE output stream.
  159. * @param data
  160. * The data to convert to hex.
  161. * @param len
  162. * The length of the data.
  163. */
  164. void tpm2_util_hexdump2(FILE *f, const BYTE *data, size_t len);
  165. /**
  166. * Read a hex string converting it to binary or a binary file and
  167. * store into a binary buffer.
  168. * @param input
  169. * Either a hex string or a file path.
  170. * @param len
  171. * The maximum length of the buffer.
  172. * @param buffer
  173. * The buffer to read into.
  174. * @return
  175. * True on success, False otherwise.
  176. */
  177. bool tpm2_util_bin_from_hex_or_file(const char *input, UINT16 *len, BYTE *buffer);
  178. /**
  179. * Prints a TPM2B as a hex dump respecting the -Q option
  180. * to stdout.
  181. *
  182. * @param buffer the TPM2B to print.
  183. */
  184. #define tpm2_util_print_tpm2b(b) _tpm2_util_print_tpm2b((TPM2B *)b)
  185. static inline void _tpm2_util_print_tpm2b(TPM2B *buffer) {
  186. return tpm2_util_hexdump(buffer->buffer, buffer->size);
  187. }
  188. /**
  189. * Prints a TPM2B as a hex dump to the FILE specified. Does NOT
  190. * respect -Q like tpm2_util_print_tpm2b().
  191. *
  192. * @param out
  193. * The output FILE.
  194. * @param
  195. * buffer the TPM2B to print.
  196. */
  197. #define tpm2_util_print_tpm2b2(o, b) _tpm2_util_print_tpm2b2(o, (TPM2B *)b)
  198. static inline void _tpm2_util_print_tpm2b2(FILE *out, const TPM2B *buffer) {
  199. return tpm2_util_hexdump2(out, buffer->buffer, buffer->size);
  200. }
  201. /**
  202. * Determines if given PCR value is selected in TPMS_PCR_SELECTION structure.
  203. * @param pcr_selection the TPMS_PCR_SELECTION structure to check pcr against.
  204. * @param pcr the PCR ID to check selection status of.
  205. */
  206. static inline bool tpm2_util_is_pcr_select_bit_set(
  207. const TPMS_PCR_SELECTION *pcr_selection, UINT32 pcr) {
  208. return (pcr_selection->pcrSelect[((pcr) / 8)] & (1 << ((pcr) % 8)));
  209. }
  210. /**
  211. * Checks if the host is big endian
  212. * @return
  213. * True of the host is big endian false otherwise.
  214. */
  215. bool tpm2_util_is_big_endian(void);
  216. /**
  217. * Swaps the endianess of 16 bit value.
  218. * @param data
  219. * A 16 bit value to swap the endianess on.
  220. * @return
  221. * The 16 bit value with the endianess swapped.
  222. */
  223. UINT16 tpm2_util_endian_swap_16(UINT16 data);
  224. /**
  225. * Just like string_bytes_endian_convert_16 but for 32 bit values.
  226. */
  227. UINT32 tpm2_util_endian_swap_32(UINT32 data);
  228. /**
  229. * Just like string_bytes_endian_convert_16 but for 64 bit values.
  230. */
  231. UINT64 tpm2_util_endian_swap_64(UINT64 data);
  232. /**
  233. * Converts a 16 bit value from host endianess to network endianess.
  234. * @param data
  235. * The data to possibly swap endianess.
  236. * @return
  237. * The swapped data.
  238. */
  239. UINT16 tpm2_util_hton_16(UINT16 data);
  240. /**
  241. * Just like string_bytes_endian_hton_16 but for 32 bit values.
  242. */
  243. UINT32 tpm2_util_hton_32(UINT32 data);
  244. /**
  245. * Just like string_bytes_endian_hton_16 but for 64 bit values.
  246. */
  247. UINT64 tpm2_util_hton_64(UINT64 data);
  248. /**
  249. * Converts a 16 bit value from network endianess to host endianess.
  250. * @param data
  251. * The data to possibly swap endianess.
  252. * @return
  253. * The swapped data.
  254. */
  255. UINT16 tpm2_util_ntoh_16(UINT16 data);
  256. /**
  257. * Just like string_bytes_endian_ntoh_16 but for 32 bit values.
  258. */
  259. UINT32 tpm2_util_ntoh_32(UINT32 data);
  260. /**
  261. * Just like string_bytes_endian_ntoh_16 but for 64 bit values.
  262. */
  263. UINT64 tpm2_util_ntoh_64(UINT64 data);
  264. /**
  265. * Counts the number of set bits aka a population count.
  266. * @param data
  267. * The data to count set bits in.
  268. * @return
  269. * The number of set bits or population count.
  270. */
  271. UINT32 tpm2_util_pop_count(UINT32 data);
  272. /**
  273. * Prints whitespace indention for yaml output.
  274. * @param indent_count
  275. * Number of times to indent
  276. */
  277. void print_yaml_indent(size_t indent_count);
  278. /**
  279. * Convert a TPM2B_PUBLIC into a yaml format and output if not quiet.
  280. * @param public
  281. * The TPM2B_PUBLIC to output in YAML format.
  282. * @param indent
  283. * The level of indentation, can be NULL
  284. */
  285. void tpm2_util_public_to_yaml(TPM2B_PUBLIC *public, char *indent);
  286. void tpm2_util_tpmt_public_to_yaml(TPMT_PUBLIC *public, char *indent);
  287. /**
  288. * Convert a TPMA_OBJECT to a yaml format and output if not quiet.
  289. * @param obj
  290. * The TPMA_OBJECT attributes to print.
  291. * @param indent
  292. * The level of indentation, can be NULL
  293. */
  294. void tpm2_util_tpma_object_to_yaml(TPMA_OBJECT obj, char *indent);
  295. /**
  296. * Calculates the unique public field. The unique public field is the digest, based on name algorithm
  297. * of the key + protection seed (concatenated).
  298. *
  299. * @param namealg
  300. * The name algorithm of the object, from the public portion.
  301. * @param key
  302. * The key bytes themselves. It seems odd that the type is TPM2B_PRIVATE_VENDOR_SPECIFIC
  303. * but this for access to the ANY field.
  304. * @param seed
  305. * The seed, from the sensitive portion.
  306. * @param unique
  307. * The result, a generated unique value for the public portion.
  308. * @return
  309. * True on success, false otherwise.
  310. */
  311. bool tpm2_util_calc_unique(TPMI_ALG_HASH name_alg,
  312. TPM2B_PRIVATE_VENDOR_SPECIFIC *key, TPM2B_DIGEST *seed,
  313. TPM2B_DIGEST *unique);
  314. /**
  315. * Uses TR_FromTPMPublic() to construct the ESYS_TR object corresponding
  316. * to the passed TPM2_HANDLE.
  317. * @param context
  318. * an ESAPI context
  319. * @param sys_handle
  320. * the TPM2_HANDLE to construct an ESYS_TR handle for
  321. * @param esys_handle
  322. * pointer to an ESYS_TR handle to output the found handle into
  323. * @return
  324. * A tool_rc indicating status.
  325. */
  326. tool_rc tpm2_util_sys_handle_to_esys_handle(ESYS_CONTEXT *context,
  327. TPM2_HANDLE sys_handle, ESYS_TR *esys_handle);
  328. /**
  329. * Map a TPMI_RH_PROVISION to the corresponding ESYS_TR constant
  330. * @param inh
  331. * The hierarchy to map
  332. */
  333. ESYS_TR tpm2_tpmi_hierarchy_to_esys_tr(TPMI_RH_PROVISION inh);
  334. char *tpm2_util_getenv(const char *name);
  335. typedef enum tpm2_handle_flags tpm2_handle_flags;
  336. enum tpm2_handle_flags {
  337. TPM2_HANDLE_FLAGS_NONE = 0,
  338. TPM2_HANDLE_FLAGS_O = 1 << 0,
  339. TPM2_HANDLE_FLAGS_P = 1 << 1,
  340. TPM2_HANDLE_FLAGS_E = 1 << 2,
  341. TPM2_HANDLE_FLAGS_N = 1 << 3,
  342. TPM2_HANDLE_FLAGS_L = 1 << 4,
  343. TPM2_HANDLE_FLAGS_ALL_HIERACHIES = 0x1F,
  344. TPM2_HANDLES_FLAGS_TRANSIENT = 1 << 5,
  345. TPM2_HANDLES_FLAGS_PERSISTENT = 1 << 6,
  346. /* bits 7 and 8 are mutually exclusive */
  347. TPM2_HANDLE_FLAGS_NV = 1 << 7,
  348. TPM2_HANDLE_ALL_W_NV = 0xFF,
  349. TPM2_HANDLE_FLAGS_PCR = 1 << 8,
  350. TPM2_HANDLE_ALL_W_PCR = 0x17F,
  351. };
  352. /**
  353. * Converts an option from the command line into a valid TPM handle, checking
  354. * for errors and if the tool supports it based on flags settings.
  355. * @param value
  356. * The command line value to convert.
  357. * @param handle
  358. * The output handle.
  359. * @param flags
  360. * The flags indicating what is supported by the tool.
  361. * @return
  362. * true on success, false otherwise.
  363. */
  364. bool tpm2_util_handle_from_optarg(const char *value,
  365. TPMI_RH_PROVISION *hierarchy, tpm2_handle_flags flags);
  366. bool tpm2_util_get_label(const char *value, TPM2B_DATA *label);
  367. /**
  368. * Prints a TPMS_TIME_INFO in a YAML compliant format to stdout.
  369. * @param current_time
  370. * The time structure to print
  371. */
  372. void tpm2_util_print_time(const TPMS_TIME_INFO *current_time);
  373. /**
  374. * Given the parent qualified name and the name of an object, computes
  375. * that objects qualified name.
  376. *
  377. * The qualified name is defined as:
  378. * QNB ≔ HB (QNA || NAMEB)
  379. *
  380. * Where:
  381. * - QNB is the qualified name of the object.
  382. * - HB is the name hash algorithm of the object.
  383. * - QNA is the qualified name of the parent object.
  384. * - NAMEB is the name of the object.
  385. *
  386. * @param pqname
  387. * The parent qualified name.
  388. * @param halg
  389. * The name hash algorithm of the object.
  390. * @param name
  391. * The name of the object.
  392. * @param qname
  393. * The output qname, valid on success.
  394. * @return
  395. * True on success, false otherwise.
  396. */
  397. bool tpm2_calq_qname(TPM2B_NAME *pqname,
  398. TPMI_ALG_HASH halg, TPM2B_NAME *name, TPM2B_NAME *qname);
  399. /**
  400. * Reads safely from stdin.
  401. *
  402. * @param length
  403. * Maximum length to read.
  404. * @param data
  405. * The output data that was read, valid on success.
  406. * @return
  407. * True on success, false otherwise.
  408. */
  409. bool tpm2_safe_read_from_stdin(int length, char *data);
  410. /**
  411. * Converts a PEM-encoded public key to its sha256 representation (fingerprint).
  412. * The resulting Base64-encoded fingerprint format is based on the SSH:
  413. * '''
  414. * ssh-keygen -lf id_ecdsa.pub
  415. * 256 SHA256:wTUOtZnoSGKwq36mPIN20rCK0Fc1y0zCvHxI2eAvVxU
  416. * '''
  417. *
  418. * @param pem_encoded_key
  419. * The PEM-encoded public key.
  420. * @param fingerprint
  421. * The resulting fingerprint, valid on success.
  422. * @return
  423. * True on success, false otherwise.
  424. */
  425. bool tpm2_pem_encoded_key_to_fingerprint(const char* pem_encoded_key, char*
  426. fingerprint);
  427. /**
  428. * Restores session handles to be used as auxilary sessions in addition to the
  429. * possible authorization sessions with a command.
  430. *
  431. * @param ectx
  432. * The ESAPI context
  433. * @param session_cnt
  434. * Total number of sessions to restore
  435. * @param session_path
  436. * An array of string data specifying the individual session file path
  437. * @param session_handle
  438. * An array of session handles updated as a result resuming sessions
  439. * @param session
  440. * An array of session structures updated as a result of resuming sessions
  441. * @return
  442. * Success: tool_rc_success, Faiure: tool_rc_general_error
  443. */
  444. tool_rc tpm2_util_aux_sessions_setup( ESYS_CONTEXT *ectx,
  445. uint8_t session_cnt, const char **session_path, ESYS_TR *session_handle,
  446. tpm2_session **session);
  447. TPMI_ALG_HASH tpm2_util_calculate_phash_algorithm(ESYS_CONTEXT *ectx,
  448. const char **cphash_path, TPM2B_DIGEST *cp_hash, const char **rphash_path,
  449. TPM2B_DIGEST *rp_hash, tpm2_session **sessions);
  450. #endif /* STRING_BYTES_H */