avb_user_verification.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /*
  2. * Copyright (C) 2017 The Android Open Source Project
  3. *
  4. * Permission is hereby granted, free of charge, to any person
  5. * obtaining a copy of this software and associated documentation
  6. * files (the "Software"), to deal in the Software without
  7. * restriction, including without limitation the rights to use, copy,
  8. * modify, merge, publish, distribute, sublicense, and/or sell copies
  9. * of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be
  13. * included in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19. * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20. * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. */
  24. #include "avb_user_verification.h"
  25. /* Maximum allow length (in bytes) of a partition name, including
  26. * ab_suffix.
  27. */
  28. #define AVB_PART_NAME_MAX_SIZE 32
  29. /* Loads the toplevel AvbVBMetaImageHeader from the slot denoted by
  30. * |ab_suffix| into |vbmeta_image|. No validation, verification, or
  31. * byteswapping is performed.
  32. *
  33. * If successful, |true| is returned and the partition it was loaded
  34. * from is returned in |out_partition_name| and the offset on said
  35. * partition is returned in |out_vbmeta_offset|.
  36. */
  37. static bool load_top_level_vbmeta_header(
  38. AvbOps* ops,
  39. const char* ab_suffix,
  40. uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE],
  41. char out_partition_name[AVB_PART_NAME_MAX_SIZE],
  42. uint64_t* out_vbmeta_offset) {
  43. uint64_t vbmeta_offset = 0;
  44. size_t num_read;
  45. bool ret = false;
  46. AvbIOResult io_res;
  47. /* Construct full partition name. */
  48. if (!avb_str_concat(out_partition_name,
  49. AVB_PART_NAME_MAX_SIZE,
  50. "vbmeta",
  51. 6,
  52. ab_suffix,
  53. avb_strlen(ab_suffix))) {
  54. avb_error("Partition name and suffix does not fit.\n");
  55. goto out;
  56. }
  57. /* Only read the header, not the entire struct. */
  58. io_res = ops->read_from_partition(ops,
  59. out_partition_name,
  60. vbmeta_offset,
  61. AVB_VBMETA_IMAGE_HEADER_SIZE,
  62. vbmeta_image,
  63. &num_read);
  64. if (io_res == AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION) {
  65. AvbFooter footer;
  66. /* Try looking for the vbmeta struct in 'boot' via the footer. */
  67. if (!avb_str_concat(out_partition_name,
  68. AVB_PART_NAME_MAX_SIZE,
  69. "boot",
  70. 4,
  71. ab_suffix,
  72. avb_strlen(ab_suffix))) {
  73. avb_error("Partition name and suffix does not fit.\n");
  74. goto out;
  75. }
  76. io_res = ops->read_from_partition(ops,
  77. out_partition_name,
  78. -AVB_FOOTER_SIZE,
  79. AVB_FOOTER_SIZE,
  80. &footer,
  81. &num_read);
  82. if (io_res != AVB_IO_RESULT_OK) {
  83. avb_errorv("Error loading footer from partition '",
  84. out_partition_name,
  85. "'\n",
  86. NULL);
  87. goto out;
  88. }
  89. if (avb_memcmp(footer.magic, AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) != 0) {
  90. avb_errorv("Data from '",
  91. out_partition_name,
  92. "' does not look like a vbmeta footer.\n",
  93. NULL);
  94. goto out;
  95. }
  96. vbmeta_offset = avb_be64toh(footer.vbmeta_offset);
  97. io_res = ops->read_from_partition(ops,
  98. out_partition_name,
  99. vbmeta_offset,
  100. AVB_VBMETA_IMAGE_HEADER_SIZE,
  101. vbmeta_image,
  102. &num_read);
  103. }
  104. if (io_res != AVB_IO_RESULT_OK) {
  105. avb_errorv(
  106. "Error loading from partition '", out_partition_name, "'\n", NULL);
  107. goto out;
  108. }
  109. if (out_vbmeta_offset != NULL) {
  110. *out_vbmeta_offset = vbmeta_offset;
  111. }
  112. ret = true;
  113. out:
  114. return ret;
  115. }
  116. bool avb_user_verification_get(AvbOps* ops,
  117. const char* ab_suffix,
  118. bool* out_verification_enabled) {
  119. uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
  120. char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
  121. AvbVBMetaImageHeader* header;
  122. uint32_t flags;
  123. bool ret = false;
  124. if (!load_top_level_vbmeta_header(
  125. ops, ab_suffix, vbmeta_image, partition_name, NULL)) {
  126. goto out;
  127. }
  128. if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
  129. avb_errorv("Data from '",
  130. partition_name,
  131. "' does not look like a vbmeta header.\n",
  132. NULL);
  133. goto out;
  134. }
  135. /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
  136. header = (AvbVBMetaImageHeader*)vbmeta_image;
  137. flags = avb_be32toh(header->flags);
  138. if (out_verification_enabled != NULL) {
  139. *out_verification_enabled =
  140. !(flags & AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
  141. } else
  142. return false;
  143. ret = true;
  144. out:
  145. return ret;
  146. }
  147. bool avb_user_verification_set(AvbOps* ops,
  148. const char* ab_suffix,
  149. bool enable_verification) {
  150. uint8_t vbmeta_image[AVB_VBMETA_IMAGE_HEADER_SIZE]; /* 256 bytes. */
  151. char partition_name[AVB_PART_NAME_MAX_SIZE]; /* 32 bytes. */
  152. uint64_t vbmeta_offset;
  153. AvbIOResult io_res;
  154. AvbVBMetaImageHeader* header;
  155. uint32_t flags;
  156. bool ret = false;
  157. if (!load_top_level_vbmeta_header(
  158. ops, ab_suffix, vbmeta_image, partition_name, &vbmeta_offset)) {
  159. goto out;
  160. }
  161. if (avb_memcmp(vbmeta_image, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
  162. avb_errorv("Data from '",
  163. partition_name,
  164. "' does not look like a vbmeta header.\n",
  165. NULL);
  166. goto out;
  167. }
  168. /* Set/clear the VERIFICATION_DISABLED bit, as requested. */
  169. header = (AvbVBMetaImageHeader*)vbmeta_image;
  170. flags = avb_be32toh(header->flags);
  171. flags &= ~AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
  172. if (!enable_verification) {
  173. flags |= AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED;
  174. }
  175. header->flags = avb_htobe32(flags);
  176. /* Write the header. */
  177. io_res = ops->write_to_partition(ops,
  178. partition_name,
  179. vbmeta_offset,
  180. AVB_VBMETA_IMAGE_HEADER_SIZE,
  181. vbmeta_image);
  182. if (io_res != AVB_IO_RESULT_OK) {
  183. avb_errorv("Error writing to partition '", partition_name, "'\n", NULL);
  184. goto out;
  185. }
  186. ret = true;
  187. out:
  188. return ret;
  189. }