payload_generation_config_android.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. //
  2. // Copyright (C) 2018 The Android Open Source Project
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "update_engine/payload_generator/payload_generation_config.h"
  17. #include <base/logging.h>
  18. #include <base/strings/string_number_conversions.h>
  19. #include <base/strings/string_split.h>
  20. #include <brillo/secure_blob.h>
  21. #include <fec/io.h>
  22. #include <libavb/libavb.h>
  23. #include <verity/hash_tree_builder.h>
  24. #include "update_engine/common/utils.h"
  25. #include "update_engine/payload_consumer/verity_writer_android.h"
  26. #include "update_engine/payload_generator/extent_ranges.h"
  27. namespace chromeos_update_engine {
  28. namespace {
  29. bool AvbDescriptorCallback(const AvbDescriptor* descriptor, void* user_data) {
  30. PartitionConfig* part = static_cast<PartitionConfig*>(user_data);
  31. AvbDescriptor desc;
  32. TEST_AND_RETURN_FALSE(
  33. avb_descriptor_validate_and_byteswap(descriptor, &desc));
  34. if (desc.tag != AVB_DESCRIPTOR_TAG_HASHTREE)
  35. return true;
  36. AvbHashtreeDescriptor hashtree;
  37. TEST_AND_RETURN_FALSE(avb_hashtree_descriptor_validate_and_byteswap(
  38. reinterpret_cast<const AvbHashtreeDescriptor*>(descriptor), &hashtree));
  39. // We only support version 1 right now, will need to introduce a new
  40. // payload minor version to support new dm verity version.
  41. TEST_AND_RETURN_FALSE(hashtree.dm_verity_version == 1);
  42. part->verity.hash_tree_algorithm =
  43. reinterpret_cast<const char*>(hashtree.hash_algorithm);
  44. const uint8_t* salt = reinterpret_cast<const uint8_t*>(descriptor) +
  45. sizeof(AvbHashtreeDescriptor) +
  46. hashtree.partition_name_len;
  47. part->verity.hash_tree_salt.assign(salt, salt + hashtree.salt_len);
  48. TEST_AND_RETURN_FALSE(hashtree.data_block_size ==
  49. part->fs_interface->GetBlockSize());
  50. part->verity.hash_tree_data_extent =
  51. ExtentForBytes(hashtree.data_block_size, 0, hashtree.image_size);
  52. TEST_AND_RETURN_FALSE(hashtree.hash_block_size ==
  53. part->fs_interface->GetBlockSize());
  54. part->verity.hash_tree_extent = ExtentForBytes(
  55. hashtree.hash_block_size, hashtree.tree_offset, hashtree.tree_size);
  56. part->verity.fec_data_extent =
  57. ExtentForBytes(hashtree.data_block_size, 0, hashtree.fec_offset);
  58. part->verity.fec_extent = ExtentForBytes(
  59. hashtree.data_block_size, hashtree.fec_offset, hashtree.fec_size);
  60. part->verity.fec_roots = hashtree.fec_num_roots;
  61. return true;
  62. }
  63. // Generate hash tree and FEC based on the verity config and verify that it
  64. // matches the hash tree and FEC stored in the image.
  65. bool VerifyVerityConfig(const PartitionConfig& part) {
  66. const size_t block_size = part.fs_interface->GetBlockSize();
  67. if (part.verity.hash_tree_extent.num_blocks() != 0) {
  68. auto hash_function =
  69. HashTreeBuilder::HashFunction(part.verity.hash_tree_algorithm);
  70. TEST_AND_RETURN_FALSE(hash_function != nullptr);
  71. HashTreeBuilder hash_tree_builder(block_size, hash_function);
  72. uint64_t data_size =
  73. part.verity.hash_tree_data_extent.num_blocks() * block_size;
  74. uint64_t tree_size = hash_tree_builder.CalculateSize(data_size);
  75. TEST_AND_RETURN_FALSE(
  76. tree_size == part.verity.hash_tree_extent.num_blocks() * block_size);
  77. TEST_AND_RETURN_FALSE(
  78. hash_tree_builder.Initialize(data_size, part.verity.hash_tree_salt));
  79. brillo::Blob buffer;
  80. for (uint64_t offset = part.verity.hash_tree_data_extent.start_block() *
  81. block_size,
  82. data_end = offset + data_size;
  83. offset < data_end;) {
  84. constexpr uint64_t kBufferSize = 1024 * 1024;
  85. size_t bytes_to_read = std::min(kBufferSize, data_end - offset);
  86. TEST_AND_RETURN_FALSE(
  87. utils::ReadFileChunk(part.path, offset, bytes_to_read, &buffer));
  88. TEST_AND_RETURN_FALSE(
  89. hash_tree_builder.Update(buffer.data(), buffer.size()));
  90. offset += buffer.size();
  91. buffer.clear();
  92. }
  93. TEST_AND_RETURN_FALSE(hash_tree_builder.BuildHashTree());
  94. TEST_AND_RETURN_FALSE(utils::ReadFileChunk(
  95. part.path,
  96. part.verity.hash_tree_extent.start_block() * block_size,
  97. tree_size,
  98. &buffer));
  99. TEST_AND_RETURN_FALSE(hash_tree_builder.CheckHashTree(buffer));
  100. }
  101. if (part.verity.fec_extent.num_blocks() != 0) {
  102. TEST_AND_RETURN_FALSE(VerityWriterAndroid::EncodeFEC(
  103. part.path,
  104. part.verity.fec_data_extent.start_block() * block_size,
  105. part.verity.fec_data_extent.num_blocks() * block_size,
  106. part.verity.fec_extent.start_block() * block_size,
  107. part.verity.fec_extent.num_blocks() * block_size,
  108. part.verity.fec_roots,
  109. block_size,
  110. true /* verify_mode */));
  111. }
  112. return true;
  113. }
  114. } // namespace
  115. bool ImageConfig::LoadVerityConfig() {
  116. for (PartitionConfig& part : partitions) {
  117. // Parse AVB devices.
  118. if (part.size > sizeof(AvbFooter)) {
  119. uint64_t footer_offset = part.size - sizeof(AvbFooter);
  120. brillo::Blob buffer;
  121. TEST_AND_RETURN_FALSE(utils::ReadFileChunk(
  122. part.path, footer_offset, sizeof(AvbFooter), &buffer));
  123. if (memcmp(buffer.data(), AVB_FOOTER_MAGIC, AVB_FOOTER_MAGIC_LEN) == 0) {
  124. LOG(INFO) << "Parsing verity config from AVB footer for " << part.name;
  125. AvbFooter footer;
  126. TEST_AND_RETURN_FALSE(avb_footer_validate_and_byteswap(
  127. reinterpret_cast<const AvbFooter*>(buffer.data()), &footer));
  128. buffer.clear();
  129. TEST_AND_RETURN_FALSE(
  130. footer.vbmeta_offset + sizeof(AvbVBMetaImageHeader) <= part.size);
  131. TEST_AND_RETURN_FALSE(utils::ReadFileChunk(
  132. part.path, footer.vbmeta_offset, footer.vbmeta_size, &buffer));
  133. TEST_AND_RETURN_FALSE(avb_descriptor_foreach(
  134. buffer.data(), buffer.size(), AvbDescriptorCallback, &part));
  135. }
  136. }
  137. // Parse VB1.0 devices with FEC metadata, devices with hash tree without
  138. // FEC will be skipped for now.
  139. if (part.verity.IsEmpty() && part.size > FEC_BLOCKSIZE) {
  140. brillo::Blob fec_metadata;
  141. TEST_AND_RETURN_FALSE(utils::ReadFileChunk(part.path,
  142. part.size - FEC_BLOCKSIZE,
  143. sizeof(fec_header),
  144. &fec_metadata));
  145. const fec_header* header =
  146. reinterpret_cast<const fec_header*>(fec_metadata.data());
  147. if (header->magic == FEC_MAGIC) {
  148. LOG(INFO)
  149. << "Parsing verity config from Verified Boot 1.0 metadata for "
  150. << part.name;
  151. const size_t block_size = part.fs_interface->GetBlockSize();
  152. // FEC_VERITY_DISABLE skips verifying verity hash tree, because we will
  153. // verify it ourselves later.
  154. fec::io fh(part.path, O_RDONLY, FEC_VERITY_DISABLE);
  155. TEST_AND_RETURN_FALSE(fh);
  156. fec_verity_metadata verity_data;
  157. if (fh.get_verity_metadata(verity_data)) {
  158. auto verity_table = base::SplitString(verity_data.table,
  159. " ",
  160. base::KEEP_WHITESPACE,
  161. base::SPLIT_WANT_ALL);
  162. TEST_AND_RETURN_FALSE(verity_table.size() == 10);
  163. size_t data_block_size = 0;
  164. TEST_AND_RETURN_FALSE(
  165. base::StringToSizeT(verity_table[3], &data_block_size));
  166. TEST_AND_RETURN_FALSE(block_size == data_block_size);
  167. size_t hash_block_size = 0;
  168. TEST_AND_RETURN_FALSE(
  169. base::StringToSizeT(verity_table[4], &hash_block_size));
  170. TEST_AND_RETURN_FALSE(block_size == hash_block_size);
  171. uint64_t num_data_blocks = 0;
  172. TEST_AND_RETURN_FALSE(
  173. base::StringToUint64(verity_table[5], &num_data_blocks));
  174. part.verity.hash_tree_data_extent =
  175. ExtentForRange(0, num_data_blocks);
  176. uint64_t hash_start_block = 0;
  177. TEST_AND_RETURN_FALSE(
  178. base::StringToUint64(verity_table[6], &hash_start_block));
  179. part.verity.hash_tree_algorithm = verity_table[7];
  180. TEST_AND_RETURN_FALSE(base::HexStringToBytes(
  181. verity_table[9], &part.verity.hash_tree_salt));
  182. auto hash_function =
  183. HashTreeBuilder::HashFunction(part.verity.hash_tree_algorithm);
  184. TEST_AND_RETURN_FALSE(hash_function != nullptr);
  185. HashTreeBuilder hash_tree_builder(block_size, hash_function);
  186. uint64_t tree_size =
  187. hash_tree_builder.CalculateSize(num_data_blocks * block_size);
  188. part.verity.hash_tree_extent =
  189. ExtentForRange(hash_start_block, tree_size / block_size);
  190. }
  191. fec_ecc_metadata ecc_data;
  192. if (fh.get_ecc_metadata(ecc_data) && ecc_data.valid) {
  193. TEST_AND_RETURN_FALSE(block_size == FEC_BLOCKSIZE);
  194. part.verity.fec_data_extent = ExtentForRange(0, ecc_data.blocks);
  195. part.verity.fec_extent =
  196. ExtentForBytes(block_size, ecc_data.start, header->fec_size);
  197. part.verity.fec_roots = ecc_data.roots;
  198. }
  199. }
  200. }
  201. if (!part.verity.IsEmpty()) {
  202. TEST_AND_RETURN_FALSE(VerifyVerityConfig(part));
  203. }
  204. }
  205. return true;
  206. }
  207. } // namespace chromeos_update_engine