hre.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2013
  4. * Reinhard Pfau, Guntermann & Drunck GmbH, reinhard.pfau@gdsys.cc
  5. */
  6. #include <common.h>
  7. #include <malloc.h>
  8. #include <fs.h>
  9. #include <i2c.h>
  10. #include <mmc.h>
  11. #include <tpm-v1.h>
  12. #include <u-boot/crc.h>
  13. #include <u-boot/sha1.h>
  14. #include <asm/byteorder.h>
  15. #include <asm/unaligned.h>
  16. #include <pca9698.h>
  17. #include "hre.h"
  18. /* other constants */
  19. enum {
  20. ESDHC_BOOT_IMAGE_SIG_OFS = 0x40,
  21. ESDHC_BOOT_IMAGE_SIZE_OFS = 0x48,
  22. ESDHC_BOOT_IMAGE_ADDR_OFS = 0x50,
  23. ESDHC_BOOT_IMAGE_TARGET_OFS = 0x58,
  24. ESDHC_BOOT_IMAGE_ENTRY_OFS = 0x60,
  25. };
  26. enum {
  27. I2C_SOC_0 = 0,
  28. I2C_SOC_1 = 1,
  29. };
  30. enum access_mode {
  31. HREG_NONE = 0,
  32. HREG_RD = 1,
  33. HREG_WR = 2,
  34. HREG_RDWR = 3,
  35. };
  36. /* register constants */
  37. enum {
  38. FIX_HREG_DEVICE_ID_HASH = 0,
  39. FIX_HREG_UNUSED1 = 1,
  40. FIX_HREG_UNUSED2 = 2,
  41. FIX_HREG_VENDOR = 3,
  42. COUNT_FIX_HREGS
  43. };
  44. static struct h_reg pcr_hregs[24];
  45. static struct h_reg fix_hregs[COUNT_FIX_HREGS];
  46. static struct h_reg var_hregs[8];
  47. /* hre opcodes */
  48. enum {
  49. /* opcodes w/o data */
  50. HRE_NOP = 0x00,
  51. HRE_SYNC = HRE_NOP,
  52. HRE_CHECK0 = 0x01,
  53. /* opcodes w/o data, w/ sync dst */
  54. /* opcodes w/ data */
  55. HRE_LOAD = 0x81,
  56. /* opcodes w/data, w/sync dst */
  57. HRE_XOR = 0xC1,
  58. HRE_AND = 0xC2,
  59. HRE_OR = 0xC3,
  60. HRE_EXTEND = 0xC4,
  61. HRE_LOADKEY = 0xC5,
  62. };
  63. /* hre errors */
  64. enum {
  65. HRE_E_OK = 0,
  66. HRE_E_TPM_FAILURE,
  67. HRE_E_INVALID_HREG,
  68. };
  69. static uint64_t device_id;
  70. static uint64_t device_cl;
  71. static uint64_t device_type;
  72. static uint32_t platform_key_handle;
  73. static uint32_t hre_tpm_err;
  74. static int hre_err = HRE_E_OK;
  75. #define IS_PCR_HREG(spec) ((spec) & 0x20)
  76. #define IS_FIX_HREG(spec) (((spec) & 0x38) == 0x08)
  77. #define IS_VAR_HREG(spec) (((spec) & 0x38) == 0x10)
  78. #define HREG_IDX(spec) ((spec) & (IS_PCR_HREG(spec) ? 0x1f : 0x7))
  79. static const uint8_t vendor[] = "Guntermann & Drunck";
  80. /**
  81. * @brief get the size of a given (TPM) NV area
  82. * @param tpm TPM device
  83. * @param index NV index of the area to get size for
  84. * @param size pointer to the size
  85. * @return 0 on success, != 0 on error
  86. */
  87. static int get_tpm_nv_size(struct udevice *tpm, uint32_t index, uint32_t *size)
  88. {
  89. uint32_t err;
  90. uint8_t info[72];
  91. uint8_t *ptr;
  92. uint16_t v16;
  93. err = tpm_get_capability(tpm, TPM_CAP_NV_INDEX, index,
  94. info, sizeof(info));
  95. if (err) {
  96. printf("tpm_get_capability(CAP_NV_INDEX, %08x) failed: %u\n",
  97. index, err);
  98. return 1;
  99. }
  100. /* skip tag and nvIndex */
  101. ptr = info + 6;
  102. /* skip 2 pcr info fields */
  103. v16 = get_unaligned_be16(ptr);
  104. ptr += 2 + v16 + 1 + 20;
  105. v16 = get_unaligned_be16(ptr);
  106. ptr += 2 + v16 + 1 + 20;
  107. /* skip permission and flags */
  108. ptr += 6 + 3;
  109. *size = get_unaligned_be32(ptr);
  110. return 0;
  111. }
  112. /**
  113. * @brief search for a key by usage auth and pub key hash.
  114. * @param tpm TPM device
  115. * @param auth usage auth of the key to search for
  116. * @param pubkey_digest (SHA1) hash of the pub key structure of the key
  117. * @param[out] handle the handle of the key iff found
  118. * @return 0 if key was found in TPM; != 0 if not.
  119. */
  120. static int find_key(struct udevice *tpm, const uint8_t auth[20],
  121. const uint8_t pubkey_digest[20], uint32_t *handle)
  122. {
  123. uint16_t key_count;
  124. uint32_t key_handles[10];
  125. uint8_t buf[288];
  126. uint8_t *ptr;
  127. uint32_t err;
  128. uint8_t digest[20];
  129. size_t buf_len;
  130. unsigned int i;
  131. /* fetch list of already loaded keys in the TPM */
  132. err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
  133. sizeof(buf));
  134. if (err)
  135. return -1;
  136. key_count = get_unaligned_be16(buf);
  137. ptr = buf + 2;
  138. for (i = 0; i < key_count; ++i, ptr += 4)
  139. key_handles[i] = get_unaligned_be32(ptr);
  140. /* now search a(/ the) key which we can access with the given auth */
  141. for (i = 0; i < key_count; ++i) {
  142. buf_len = sizeof(buf);
  143. err = tpm_get_pub_key_oiap(tpm, key_handles[i], auth, buf,
  144. &buf_len);
  145. if (err && err != TPM_AUTHFAIL)
  146. return -1;
  147. if (err)
  148. continue;
  149. sha1_csum(buf, buf_len, digest);
  150. if (!memcmp(digest, pubkey_digest, 20)) {
  151. *handle = key_handles[i];
  152. return 0;
  153. }
  154. }
  155. return 1;
  156. }
  157. /**
  158. * @brief read CCDM common data from TPM NV
  159. * @param tpm TPM device
  160. * @return 0 if CCDM common data was found and read, !=0 if something failed.
  161. */
  162. static int read_common_data(struct udevice *tpm)
  163. {
  164. uint32_t size = 0;
  165. uint32_t err;
  166. uint8_t buf[256];
  167. sha1_context ctx;
  168. if (get_tpm_nv_size(tpm, NV_COMMON_DATA_INDEX, &size) ||
  169. size < NV_COMMON_DATA_MIN_SIZE)
  170. return 1;
  171. err = tpm_nv_read_value(tpm, NV_COMMON_DATA_INDEX,
  172. buf, min(sizeof(buf), size));
  173. if (err) {
  174. printf("tpm_nv_read_value() failed: %u\n", err);
  175. return 1;
  176. }
  177. device_id = get_unaligned_be64(buf);
  178. device_cl = get_unaligned_be64(buf + 8);
  179. device_type = get_unaligned_be64(buf + 16);
  180. sha1_starts(&ctx);
  181. sha1_update(&ctx, buf, 24);
  182. sha1_finish(&ctx, fix_hregs[FIX_HREG_DEVICE_ID_HASH].digest);
  183. fix_hregs[FIX_HREG_DEVICE_ID_HASH].valid = true;
  184. platform_key_handle = get_unaligned_be32(buf + 24);
  185. return 0;
  186. }
  187. /**
  188. * @brief get pointer to hash register by specification
  189. * @param spec specification of a hash register
  190. * @return pointer to hash register or NULL if @a spec does not qualify a
  191. * valid hash register; NULL else.
  192. */
  193. static struct h_reg *get_hreg(uint8_t spec)
  194. {
  195. uint8_t idx;
  196. idx = HREG_IDX(spec);
  197. if (IS_FIX_HREG(spec)) {
  198. if (idx < ARRAY_SIZE(fix_hregs))
  199. return fix_hregs + idx;
  200. hre_err = HRE_E_INVALID_HREG;
  201. } else if (IS_PCR_HREG(spec)) {
  202. if (idx < ARRAY_SIZE(pcr_hregs))
  203. return pcr_hregs + idx;
  204. hre_err = HRE_E_INVALID_HREG;
  205. } else if (IS_VAR_HREG(spec)) {
  206. if (idx < ARRAY_SIZE(var_hregs))
  207. return var_hregs + idx;
  208. hre_err = HRE_E_INVALID_HREG;
  209. }
  210. return NULL;
  211. }
  212. /**
  213. * @brief get pointer of a hash register by specification and usage.
  214. * @param tpm TPM device
  215. * @param spec specification of a hash register
  216. * @param mode access mode (read or write or read/write)
  217. * @return pointer to hash register if found and valid; NULL else.
  218. *
  219. * This func uses @a get_reg() to determine the hash register for a given spec.
  220. * If a register is found it is validated according to the desired access mode.
  221. * The value of automatic registers (PCR register and fixed registers) is
  222. * loaded or computed on read access.
  223. */
  224. static struct h_reg *access_hreg(struct udevice *tpm, uint8_t spec,
  225. enum access_mode mode)
  226. {
  227. struct h_reg *result;
  228. result = get_hreg(spec);
  229. if (!result)
  230. return NULL;
  231. if (mode & HREG_WR) {
  232. if (IS_FIX_HREG(spec)) {
  233. hre_err = HRE_E_INVALID_HREG;
  234. return NULL;
  235. }
  236. }
  237. if (mode & HREG_RD) {
  238. if (!result->valid) {
  239. if (IS_PCR_HREG(spec)) {
  240. hre_tpm_err = tpm_pcr_read(tpm, HREG_IDX(spec),
  241. result->digest, 20);
  242. result->valid = (hre_tpm_err == TPM_SUCCESS);
  243. } else if (IS_FIX_HREG(spec)) {
  244. switch (HREG_IDX(spec)) {
  245. case FIX_HREG_DEVICE_ID_HASH:
  246. read_common_data(tpm);
  247. break;
  248. case FIX_HREG_VENDOR:
  249. memcpy(result->digest, vendor, 20);
  250. result->valid = true;
  251. break;
  252. }
  253. } else {
  254. result->valid = true;
  255. }
  256. }
  257. if (!result->valid) {
  258. hre_err = HRE_E_INVALID_HREG;
  259. return NULL;
  260. }
  261. }
  262. return result;
  263. }
  264. static void *compute_and(void *_dst, const void *_src, size_t n)
  265. {
  266. uint8_t *dst = _dst;
  267. const uint8_t *src = _src;
  268. size_t i;
  269. for (i = n; i-- > 0; )
  270. *dst++ &= *src++;
  271. return _dst;
  272. }
  273. static void *compute_or(void *_dst, const void *_src, size_t n)
  274. {
  275. uint8_t *dst = _dst;
  276. const uint8_t *src = _src;
  277. size_t i;
  278. for (i = n; i-- > 0; )
  279. *dst++ |= *src++;
  280. return _dst;
  281. }
  282. static void *compute_xor(void *_dst, const void *_src, size_t n)
  283. {
  284. uint8_t *dst = _dst;
  285. const uint8_t *src = _src;
  286. size_t i;
  287. for (i = n; i-- > 0; )
  288. *dst++ ^= *src++;
  289. return _dst;
  290. }
  291. static void *compute_extend(void *_dst, const void *_src, size_t n)
  292. {
  293. uint8_t digest[20];
  294. sha1_context ctx;
  295. sha1_starts(&ctx);
  296. sha1_update(&ctx, _dst, n);
  297. sha1_update(&ctx, _src, n);
  298. sha1_finish(&ctx, digest);
  299. memcpy(_dst, digest, min(n, sizeof(digest)));
  300. return _dst;
  301. }
  302. static int hre_op_loadkey(struct udevice *tpm, struct h_reg *src_reg,
  303. struct h_reg *dst_reg, const void *key,
  304. size_t key_size)
  305. {
  306. uint32_t parent_handle;
  307. uint32_t key_handle;
  308. if (!src_reg || !dst_reg || !src_reg->valid || !dst_reg->valid)
  309. return -1;
  310. if (find_key(tpm, src_reg->digest, dst_reg->digest, &parent_handle))
  311. return -1;
  312. hre_tpm_err = tpm_load_key2_oiap(tpm, parent_handle, key, key_size,
  313. src_reg->digest, &key_handle);
  314. if (hre_tpm_err) {
  315. hre_err = HRE_E_TPM_FAILURE;
  316. return -1;
  317. }
  318. return 0;
  319. }
  320. /**
  321. * @brief executes the next opcode on the hash register engine.
  322. * @param tpm TPM device
  323. * @param[in,out] ip pointer to the opcode (instruction pointer)
  324. * @param[in,out] code_size (remaining) size of the code
  325. * @return new instruction pointer on success, NULL on error.
  326. */
  327. static const uint8_t *hre_execute_op(struct udevice *tpm, const uint8_t **ip,
  328. size_t *code_size)
  329. {
  330. bool dst_modified = false;
  331. uint32_t ins;
  332. uint8_t opcode;
  333. uint8_t src_spec;
  334. uint8_t dst_spec;
  335. uint16_t data_size;
  336. struct h_reg *src_reg, *dst_reg;
  337. uint8_t buf[20];
  338. const uint8_t *src_buf, *data;
  339. uint8_t *ptr;
  340. int i;
  341. void * (*bin_func)(void *, const void *, size_t);
  342. if (*code_size < 4)
  343. return NULL;
  344. ins = get_unaligned_be32(*ip);
  345. opcode = **ip;
  346. data = *ip + 4;
  347. src_spec = (ins >> 18) & 0x3f;
  348. dst_spec = (ins >> 12) & 0x3f;
  349. data_size = (ins & 0x7ff);
  350. debug("HRE: ins=%08x (op=%02x, s=%02x, d=%02x, L=%d)\n", ins,
  351. opcode, src_spec, dst_spec, data_size);
  352. if ((opcode & 0x80) && (data_size + 4) > *code_size)
  353. return NULL;
  354. src_reg = access_hreg(tpm, src_spec, HREG_RD);
  355. if (hre_err || hre_tpm_err)
  356. return NULL;
  357. dst_reg = access_hreg(tpm, dst_spec,
  358. (opcode & 0x40) ? HREG_RDWR : HREG_WR);
  359. if (hre_err || hre_tpm_err)
  360. return NULL;
  361. switch (opcode) {
  362. case HRE_NOP:
  363. goto end;
  364. case HRE_CHECK0:
  365. if (src_reg) {
  366. for (i = 0; i < 20; ++i) {
  367. if (src_reg->digest[i])
  368. return NULL;
  369. }
  370. }
  371. break;
  372. case HRE_LOAD:
  373. bin_func = memcpy;
  374. goto do_bin_func;
  375. case HRE_XOR:
  376. bin_func = compute_xor;
  377. goto do_bin_func;
  378. case HRE_AND:
  379. bin_func = compute_and;
  380. goto do_bin_func;
  381. case HRE_OR:
  382. bin_func = compute_or;
  383. goto do_bin_func;
  384. case HRE_EXTEND:
  385. bin_func = compute_extend;
  386. do_bin_func:
  387. if (!dst_reg)
  388. return NULL;
  389. if (src_reg) {
  390. src_buf = src_reg->digest;
  391. } else {
  392. if (!data_size) {
  393. memset(buf, 0, 20);
  394. src_buf = buf;
  395. } else if (data_size == 1) {
  396. memset(buf, *data, 20);
  397. src_buf = buf;
  398. } else if (data_size >= 20) {
  399. src_buf = data;
  400. } else {
  401. src_buf = buf;
  402. for (ptr = (uint8_t *)src_buf, i = 20; i > 0;
  403. i -= data_size, ptr += data_size)
  404. memcpy(ptr, data,
  405. min_t(size_t, i, data_size));
  406. }
  407. }
  408. bin_func(dst_reg->digest, src_buf, 20);
  409. dst_reg->valid = true;
  410. dst_modified = true;
  411. break;
  412. case HRE_LOADKEY:
  413. if (hre_op_loadkey(tpm, src_reg, dst_reg, data, data_size))
  414. return NULL;
  415. break;
  416. default:
  417. return NULL;
  418. }
  419. if (dst_reg && dst_modified && IS_PCR_HREG(dst_spec)) {
  420. hre_tpm_err = tpm_extend(tpm, HREG_IDX(dst_spec),
  421. dst_reg->digest, dst_reg->digest);
  422. if (hre_tpm_err) {
  423. hre_err = HRE_E_TPM_FAILURE;
  424. return NULL;
  425. }
  426. }
  427. end:
  428. *ip += 4;
  429. *code_size -= 4;
  430. if (opcode & 0x80) {
  431. *ip += data_size;
  432. *code_size -= data_size;
  433. }
  434. return *ip;
  435. }
  436. /**
  437. * @brief runs a program on the hash register engine.
  438. * @param tpm TPM device
  439. * @param code pointer to the (HRE) code.
  440. * @param code_size size of the code (in bytes).
  441. * @return 0 on success, != 0 on failure.
  442. */
  443. int hre_run_program(struct udevice *tpm, const uint8_t *code, size_t code_size)
  444. {
  445. size_t code_left;
  446. const uint8_t *ip = code;
  447. code_left = code_size;
  448. hre_tpm_err = 0;
  449. hre_err = HRE_E_OK;
  450. while (code_left > 0)
  451. if (!hre_execute_op(tpm, &ip, &code_left))
  452. return -1;
  453. return hre_err;
  454. }
  455. int hre_verify_program(struct key_program *prg)
  456. {
  457. uint32_t crc;
  458. crc = crc32(0, prg->code, prg->code_size);
  459. if (crc != prg->code_crc) {
  460. printf("HRC crc mismatch: %08x != %08x\n",
  461. crc, prg->code_crc);
  462. return 1;
  463. }
  464. return 0;
  465. }