file_type_rwsig.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. * Copyright 2015 The Chromium OS Authors. All rights reserved.
  3. * Use of this source code is governed by a BSD-style license that can be
  4. * found in the LICENSE file.
  5. */
  6. /*
  7. * Some instances of the Chrome OS embedded controller firmware can't do a
  8. * normal software sync handshake at boot, but will verify their own RW images
  9. * instead. This is typically done by putting a struct vb2_packed_key in the RO
  10. * image and a corresponding struct vb21_signature in the RW image.
  11. *
  12. * This file provides the basic implementation for that approach.
  13. */
  14. #include <stdint.h>
  15. #include <stdio.h>
  16. #include <unistd.h>
  17. #include "2sysincludes.h"
  18. #include "2common.h"
  19. #include "2rsa.h"
  20. #include "2sha.h"
  21. #include "file_type.h"
  22. #include "futility.h"
  23. #include "futility_options.h"
  24. #include "vb21_common.h"
  25. #include "host_common.h"
  26. #include "host_key2.h"
  27. #include "host_signature2.h"
  28. #include "util_misc.h"
  29. #define SIGNATURE_RSVD_SIZE 1024
  30. static inline void vb2_print_bytes(const void *ptr, uint32_t len)
  31. {
  32. const uint8_t *buf = (const uint8_t *)ptr;
  33. int i;
  34. for (i = 0; i < len; i++)
  35. printf("%02x", *buf++);
  36. }
  37. static void show_sig(const char *name, const struct vb21_signature *sig)
  38. {
  39. printf("Signature: %s\n", name);
  40. printf(" Vboot API: 2.1\n");
  41. printf(" Desc: \"%s\"\n", vb21_common_desc(sig));
  42. printf(" Signature Algorithm: %d %s\n", sig->sig_alg,
  43. vb2_get_sig_algorithm_name(sig->sig_alg));
  44. printf(" Hash Algorithm: %d %s\n", sig->hash_alg,
  45. vb2_get_hash_algorithm_name(sig->hash_alg));
  46. printf(" Total size: 0x%x (%d)\n", sig->c.total_size,
  47. sig->c.total_size);
  48. printf(" ID: ");
  49. vb2_print_bytes(&sig->id, sizeof(sig->id));
  50. printf("\n");
  51. printf(" Data size: 0x%x (%d)\n", sig->data_size,
  52. sig->data_size);
  53. }
  54. int ft_show_rwsig(const char *name, uint8_t *buf, uint32_t len, void *nuthin)
  55. {
  56. const struct vb21_signature *sig = 0;
  57. struct vb2_public_key key;
  58. uint8_t workbuf[VB2_VERIFY_DATA_WORKBUF_BYTES]
  59. __attribute__ ((aligned (VB2_WORKBUF_ALIGN)));
  60. struct vb2_workbuf wb;
  61. uint32_t data_size, sig_size = SIGNATURE_RSVD_SIZE;
  62. uint8_t *data;
  63. Debug("%s(): name %s\n", __func__, name);
  64. Debug("%s(): len 0x%08x (%d)\n", __func__, len, len);
  65. /* Am I just looking at a signature file? */
  66. Debug("Looking for signature at 0x0\n");
  67. sig = (const struct vb21_signature *)buf;
  68. if (VB2_SUCCESS == vb21_verify_signature(sig, len)) {
  69. show_sig(name, sig);
  70. if (!show_option.fv) {
  71. printf("No data available to verify\n");
  72. return show_option.strict;
  73. }
  74. data = show_option.fv;
  75. data_size = show_option.fv_size;
  76. } else {
  77. /* Where would it be? */
  78. if (show_option.sig_size)
  79. sig_size = show_option.sig_size;
  80. Debug("Looking for signature at 0x%x\n", len - sig_size);
  81. if (len < sig_size) {
  82. Debug("File is too small\n");
  83. return 1;
  84. }
  85. sig = (const struct vb21_signature *)(buf + len - sig_size);
  86. if (VB2_SUCCESS == vb21_verify_signature(sig, sig_size)) {
  87. show_sig(name, sig);
  88. data = buf;
  89. data_size = sig->data_size;
  90. } else {
  91. return 1;
  92. }
  93. }
  94. if (!show_option.pkey) {
  95. printf("No public key available to verify with\n");
  96. return show_option.strict;
  97. }
  98. /* We already did this once, so it should work again */
  99. if (vb21_unpack_key(&key,
  100. (const uint8_t *)show_option.pkey,
  101. show_option.pkey->c.total_size)) {
  102. Debug("Can't unpack pubkey\n");
  103. return 1;
  104. }
  105. /* The sig is destroyed by the verify operation, so make a copy */
  106. {
  107. uint8_t sigbuf[sig->c.total_size];
  108. memcpy(sigbuf, sig, sizeof(sigbuf));
  109. vb2_workbuf_init(&wb, workbuf, sizeof(workbuf));
  110. if (vb21_verify_data(data, data_size,
  111. (struct vb21_signature *)sigbuf,
  112. (const struct vb2_public_key *)&key,
  113. &wb)) {
  114. printf("Signature verification failed\n");
  115. return 1;
  116. }
  117. }
  118. printf("Signature verification succeeded.\n");
  119. return 0;
  120. }
  121. int ft_sign_rwsig(const char *name, uint8_t *buf, uint32_t len, void *data)
  122. {
  123. struct vb21_signature *sig = 0;
  124. uint32_t r, data_size = len, sig_size = SIGNATURE_RSVD_SIZE;
  125. int retval = 1;
  126. Debug("%s(): name %s\n", __func__, name);
  127. Debug("%s(): len 0x%08x (%d)\n", __func__, len, len);
  128. /* If we don't have a distinct OUTFILE, look for an existing sig */
  129. if (sign_option.inout_file_count < 2) {
  130. const struct vb21_signature *old_sig;
  131. /* Where would it be? */
  132. if (sign_option.sig_size)
  133. sig_size = sign_option.sig_size;
  134. Debug("Looking for old signature at 0x%x\n", len - sig_size);
  135. if (len < sig_size) {
  136. fprintf(stderr, "File is too small\n");
  137. return 1;
  138. }
  139. /* Take a look */
  140. old_sig = (const struct vb21_signature *)(buf + len - sig_size);
  141. if (vb21_verify_signature(old_sig, sig_size)) {
  142. fprintf(stderr, "Can't find a valid signature\n");
  143. return 1;
  144. }
  145. /* Use the same exent again */
  146. data_size = old_sig->data_size;
  147. Debug("Found sig: data_size is 0x%x (%d)\n", data_size,
  148. data_size);
  149. }
  150. /* Unless overridden */
  151. if (sign_option.data_size)
  152. data_size = sign_option.data_size;
  153. /* Sign the blob */
  154. r = vb21_sign_data(&sig, buf, data_size, sign_option.prikey, 0);
  155. if (r) {
  156. fprintf(stderr,
  157. "Unable to sign data (error 0x%08x, if that helps)\n",
  158. r);
  159. goto done;
  160. }
  161. if (sign_option.inout_file_count < 2) {
  162. /* Overwrite the old signature */
  163. if (sig->c.total_size > sig_size) {
  164. fprintf(stderr, "New sig is too large (%d > %d)\n",
  165. sig->c.total_size, sig_size);
  166. goto done;
  167. }
  168. memset(buf + len - sig_size, 0xff, sig_size);
  169. memcpy(buf + len - sig_size, sig, sig->c.total_size);
  170. } else {
  171. /* Write the signature to a new file */
  172. r = vb21_write_object(sign_option.outfile, sig);
  173. if (r) {
  174. fprintf(stderr, "Unable to write sig"
  175. " (error 0x%08x, if that helps)\n", r);
  176. goto done;
  177. }
  178. }
  179. /* Finally */
  180. retval = 0;
  181. done:
  182. if (sig)
  183. free(sig);
  184. if (sign_option.prikey)
  185. vb2_private_key_free(sign_option.prikey);
  186. return retval;
  187. }
  188. enum futil_file_type ft_recognize_rwsig(uint8_t *buf, uint32_t len)
  189. {
  190. if (!vb21_verify_signature((const struct vb21_signature *)buf, len))
  191. return FILE_TYPE_RWSIG;
  192. if (len >= SIGNATURE_RSVD_SIZE &&
  193. !vb21_verify_signature((const struct vb21_signature *)
  194. (buf + len - SIGNATURE_RSVD_SIZE),
  195. SIGNATURE_RSVD_SIZE))
  196. return FILE_TYPE_RWSIG;
  197. return FILE_TYPE_UNKNOWN;
  198. }