vb20_verify_fw.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
  2. * Use of this source code is governed by a BSD-style license that can be
  3. * found in the LICENSE file.
  4. *
  5. * Routines for verifying a firmware image's signature.
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "2sysincludes.h"
  11. #include "2api.h"
  12. const char *gbb_fname;
  13. const char *vblock_fname;
  14. const char *body_fname;
  15. /**
  16. * Local implementation which reads resources from individual files. Could be
  17. * more elegant and read from bios.bin, if we understood the fmap.
  18. */
  19. int vb2ex_read_resource(struct vb2_context *ctx,
  20. enum vb2_resource_index index,
  21. uint32_t offset,
  22. void *buf,
  23. uint32_t size)
  24. {
  25. const char *fname;
  26. FILE *f;
  27. int got_size;
  28. /* Get the filename for the resource */
  29. switch (index) {
  30. case VB2_RES_GBB:
  31. fname = gbb_fname;
  32. break;
  33. case VB2_RES_FW_VBLOCK:
  34. fname = vblock_fname;
  35. break;
  36. default:
  37. return VB2_ERROR_UNKNOWN;
  38. }
  39. /* Open file and seek to the requested offset */
  40. f = fopen(fname, "rb");
  41. if (!f)
  42. return VB2_ERROR_UNKNOWN;
  43. if (fseek(f, offset, SEEK_SET)) {
  44. fclose(f);
  45. return VB2_ERROR_UNKNOWN;
  46. }
  47. /* Read data and close file */
  48. got_size = fread(buf, 1, size, f);
  49. fclose(f);
  50. /* Return success if we read everything */
  51. return got_size == size ? VB2_SUCCESS : VB2_ERROR_UNKNOWN;
  52. }
  53. int vb2ex_tpm_clear_owner(struct vb2_context *ctx)
  54. {
  55. // TODO: implement
  56. return VB2_SUCCESS;
  57. }
  58. /**
  59. * Save non-volatile and/or secure data if needed.
  60. */
  61. static void save_if_needed(struct vb2_context *ctx)
  62. {
  63. if (ctx->flags & VB2_CONTEXT_NVDATA_CHANGED) {
  64. // TODO: implement
  65. ctx->flags &= ~VB2_CONTEXT_NVDATA_CHANGED;
  66. }
  67. if (ctx->flags & VB2_CONTEXT_SECDATA_CHANGED) {
  68. // TODO: implement
  69. ctx->flags &= ~VB2_CONTEXT_SECDATA_CHANGED;
  70. }
  71. }
  72. /**
  73. * Verify firmware body
  74. */
  75. static int hash_body(struct vb2_context *ctx)
  76. {
  77. uint32_t expect_size;
  78. uint8_t block[8192];
  79. uint32_t size;
  80. FILE *f;
  81. int rv;
  82. /* Open the body data */
  83. f = fopen(body_fname, "rb");
  84. if (!f)
  85. return VB2_ERROR_TEST_INPUT_FILE;
  86. /* Start the body hash */
  87. rv = vb2api_init_hash(ctx, VB2_HASH_TAG_FW_BODY, &expect_size);
  88. if (rv) {
  89. fclose(f);
  90. return rv;
  91. }
  92. printf("Expect %d bytes of body...\n", expect_size);
  93. /* Extend over the body */
  94. while (expect_size) {
  95. size = sizeof(block);
  96. if (size > expect_size)
  97. size = expect_size;
  98. /* Read next body block */
  99. size = fread(block, 1, size, f);
  100. if (size <= 0)
  101. break;
  102. /* Hash it */
  103. rv = vb2api_extend_hash(ctx, block, size);
  104. if (rv) {
  105. fclose(f);
  106. return rv;
  107. }
  108. expect_size -= size;
  109. }
  110. fclose(f);
  111. /* Check the result */
  112. rv = vb2api_check_hash(ctx);
  113. if (rv)
  114. return rv;
  115. return VB2_SUCCESS;
  116. }
  117. static void print_help(const char *progname)
  118. {
  119. printf("Usage: %s <gbb> <vblock> <body>\n", progname);
  120. }
  121. int main(int argc, char *argv[])
  122. {
  123. struct vb2_context ctx;
  124. uint8_t workbuf[16384] __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
  125. int rv;
  126. if (argc < 4) {
  127. print_help(argv[0]);
  128. return 1;
  129. }
  130. /* Save filenames */
  131. gbb_fname = argv[1];
  132. vblock_fname = argv[2];
  133. body_fname = argv[3];
  134. /* Set up context */
  135. memset(&ctx, 0, sizeof(ctx));
  136. ctx.workbuf = workbuf;
  137. ctx.workbuf_size = sizeof(workbuf);
  138. /* Initialize secure context */
  139. rv = vb2api_secdata_create(&ctx);
  140. if (rv) {
  141. fprintf(stderr,
  142. "error: vb2api_secdata_create() failed (%d)\n", rv);
  143. return 1;
  144. }
  145. // TODO: optional args to set contents for nvdata, secdata?
  146. /* Do early init */
  147. printf("Phase 1...\n");
  148. rv = vb2api_fw_phase1(&ctx);
  149. if (rv) {
  150. printf("Phase 1 wants recovery mode.\n");
  151. save_if_needed(&ctx);
  152. return rv;
  153. }
  154. /* Determine which firmware slot to boot */
  155. printf("Phase 2...\n");
  156. rv = vb2api_fw_phase2(&ctx);
  157. if (rv) {
  158. printf("Phase 2 wants reboot.\n");
  159. save_if_needed(&ctx);
  160. return rv;
  161. }
  162. /* Try that slot */
  163. printf("Phase 3...\n");
  164. rv = vb2api_fw_phase3(&ctx);
  165. if (rv) {
  166. printf("Phase 3 wants reboot.\n");
  167. save_if_needed(&ctx);
  168. return rv;
  169. }
  170. /* Verify body */
  171. printf("Hash body...\n");
  172. rv = hash_body(&ctx);
  173. save_if_needed(&ctx);
  174. if (rv) {
  175. printf("Phase 4 wants reboot.\n");
  176. return rv;
  177. }
  178. printf("Yaay!\n");
  179. printf("Workbuf used = %d bytes\n", ctx.workbuf_used);
  180. return 0;
  181. }