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 17 #include "update_engine/payload_generator/payload_generation_config.h" 18 19 #include <brillo/secure_blob.h> 20 #include <gtest/gtest.h> 21 22 #include "update_engine/common/test_utils.h" 23 #include "update_engine/payload_generator/extent_ranges.h" 24 #include "update_engine/payload_generator/extent_utils.h" 25 26 namespace chromeos_update_engine { 27 28 namespace { 29 // dd if=/dev/zero of=part bs=4096 count=2 30 // avbtool add_hashtree_footer --image part --partition_size $((24 * 4096)) 31 // --partition_name system 32 constexpr uint64_t kImageSize = 24 * 4096; 33 34 // hexdump -s $((2 * 4096)) -n 64 -v -e '/1 "0x%02x, "' part 35 constexpr uint64_t kHashTreeOffset = 2 * 4096; 36 const uint8_t kHashTree[] = { 37 0x62, 0x4b, 0x5a, 0x4d, 0xa2, 0x97, 0xa0, 0xc8, 0x08, 0x03, 0xa6, 38 0x95, 0x4c, 0x4c, 0x7a, 0x2d, 0xac, 0x50, 0xde, 0x74, 0x00, 0x00, 39 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 40 0x4b, 0x5a, 0x4d, 0xa2, 0x97, 0xa0, 0xc8, 0x08, 0x03, 0xa6, 0x95, 41 0x4c, 0x4c, 0x7a, 0x2d, 0xac, 0x50, 0xde, 0x74, 0x00, 0x00, 0x00, 42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 43 44 // hexdump -s $((3 * 4096)) -n 128 -v -e '/1 "0x%02x, "' part 45 constexpr uint64_t kFECOffset = 3 * 4096; 46 const uint8_t kFEC[] = { 47 0xec, 0x8e, 0x93, 0xd8, 0xf9, 0xa3, 0xd6, 0x9b, 0xa4, 0x06, 0x5f, 0xc8, 48 0x6c, 0xcc, 0x4f, 0x87, 0x07, 0x0f, 0xac, 0xaf, 0x29, 0x8f, 0x97, 0x02, 49 0xb2, 0xfe, 0xb2, 0xfe, 0xe5, 0x9f, 0xf2, 0xdf, 0xe6, 0x4a, 0x36, 0x66, 50 0x04, 0xda, 0xa7, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 0x00, 0x00, 0x00, 0x00, 0xec, 0x8e, 0x93, 0xd8, 0xf9, 0xa3, 0xd6, 0x9b, 53 0xa4, 0x06, 0x5f, 0xc8, 0x6c, 0xcc, 0x4f, 0x87, 0x07, 0x0f, 0xac, 0xaf, 54 0x29, 0x8f, 0x97, 0x02, 0xb2, 0xfe, 0xb2, 0xfe, 0xe5, 0x9f, 0xf2, 0xdf, 55 0xe6, 0x4a, 0x36, 0x66, 0x04, 0xda, 0xa7, 0xd3, 0x00, 0x00, 0x00, 0x00, 56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 58 59 // hexdump -s $((5 * 4096)) -n 512 -v -e '/1 "0x%02x, "' part 60 constexpr uint64_t kVBMetaImageOffset = 5 * 4096; 61 const uint8_t kVBMetaImage[] = { 62 0x41, 0x56, 0x42, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 64 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 0x00, 0x00, 0x00, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x76, 0x62, 0x74, 73 0x6f, 0x6f, 0x6c, 0x20, 0x31, 0x2e, 0x31, 0x2e, 0x30, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 81 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 84 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x01, 85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 86 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 87 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x02, 88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 89 0x00, 0x00, 0x20, 0x00, 0x73, 0x68, 0x61, 0x31, 0x00, 0x00, 0x00, 0x00, 90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 0x00, 0x00, 0x00, 0x00, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x1f, 0xab, 99 0x7a, 0x6b, 0xf6, 0xb1, 0x3a, 0x1f, 0xdb, 0x34, 0xa3, 0xfc, 0xc8, 0x73, 100 0x0b, 0x23, 0x61, 0xb3, 0x04, 0xe2, 0x4f, 0x6c, 0xd0, 0x1e, 0x39, 0x9d, 101 0xaa, 0x73, 0x35, 0x53, 0xa7, 0x74, 0x1f, 0x81, 0xd0, 0xa6, 0xa9, 0x5f, 102 0x19, 0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 105 106 // hexdump -s $((24 * 4096 - 64)) -n 64 -v -e '/1 "0x%02x, "' part 107 constexpr uint64_t kAVBFooterOffset = 24 * 4096 - 64; 108 const uint8_t kAVBFooter[] = { 109 0x41, 0x56, 0x42, 0x66, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 111 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 112 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 113 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 115 116 // avbtool info_image --image part | grep Salt | cut -d':' -f 2 | xxd -r -p | 117 // hexdump -v -e '/1 "0x%02x, "' 118 const uint8_t kHashTreeSalt[] = {0x1f, 0xab, 0x7a, 0x6b, 0xf6, 0xb1, 0x3a, 119 0x1f, 0xdb, 0x34, 0xa3, 0xfc, 0xc8, 0x73, 120 0x0b, 0x23, 0x61, 0xb3, 0x04, 0xe2}; 121 122 brillo::Blob GetAVBPartition() { 123 brillo::Blob part(kImageSize); 124 memcpy(part.data() + kHashTreeOffset, kHashTree, sizeof(kHashTree)); 125 memcpy(part.data() + kFECOffset, kFEC, sizeof(kFEC)); 126 memcpy(part.data() + kVBMetaImageOffset, kVBMetaImage, sizeof(kVBMetaImage)); 127 memcpy(part.data() + kAVBFooterOffset, kAVBFooter, sizeof(kAVBFooter)); 128 return part; 129 } 130 131 } // namespace 132 133 class PayloadGenerationConfigAndroidTest : public ::testing::Test { 134 protected: 135 void SetUp() override { 136 image_config_.partitions.emplace_back("system"); 137 image_config_.partitions[0].path = temp_file_.path(); 138 } 139 140 ImageConfig image_config_; 141 test_utils::ScopedTempFile temp_file_{ 142 "PayloadGenerationConfigAndroidTest.XXXXXX"}; 143 }; 144 145 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigSimpleTest) { 146 brillo::Blob part = GetAVBPartition(); 147 test_utils::WriteFileVector(temp_file_.path(), part); 148 EXPECT_TRUE(image_config_.LoadImageSize()); 149 EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem()); 150 EXPECT_TRUE(image_config_.LoadVerityConfig()); 151 const VerityConfig& verity = image_config_.partitions[0].verity; 152 EXPECT_FALSE(verity.IsEmpty()); 153 EXPECT_EQ(ExtentForRange(0, 2), verity.hash_tree_data_extent); 154 EXPECT_EQ(ExtentForRange(2, 1), verity.hash_tree_extent); 155 EXPECT_EQ("sha1", verity.hash_tree_algorithm); 156 brillo::Blob salt(kHashTreeSalt, std::end(kHashTreeSalt)); 157 EXPECT_EQ(salt, verity.hash_tree_salt); 158 EXPECT_EQ(ExtentForRange(0, 3), verity.fec_data_extent); 159 EXPECT_EQ(ExtentForRange(3, 2), verity.fec_extent); 160 EXPECT_EQ(2u, verity.fec_roots); 161 } 162 163 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigDisableFecTest) { 164 brillo::Blob part = GetAVBPartition(); 165 test_utils::WriteFileVector(temp_file_.path(), part); 166 image_config_.partitions[0].disable_fec_computation = true; 167 EXPECT_TRUE(image_config_.LoadImageSize()); 168 EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem()); 169 EXPECT_TRUE(image_config_.LoadVerityConfig()); 170 const VerityConfig& verity = image_config_.partitions[0].verity; 171 EXPECT_FALSE(verity.IsEmpty()); 172 EXPECT_EQ(ExtentForRange(0, 2), verity.hash_tree_data_extent); 173 EXPECT_EQ(ExtentForRange(2, 1), verity.hash_tree_extent); 174 EXPECT_EQ("sha1", verity.hash_tree_algorithm); 175 brillo::Blob salt(kHashTreeSalt, std::end(kHashTreeSalt)); 176 EXPECT_EQ(salt, verity.hash_tree_salt); 177 EXPECT_EQ(0u, verity.fec_data_extent.num_blocks()); 178 EXPECT_EQ(0u, verity.fec_extent.num_blocks()); 179 } 180 181 TEST_F(PayloadGenerationConfigAndroidTest, 182 LoadVerityConfigInvalidHashTreeTest) { 183 brillo::Blob part = GetAVBPartition(); 184 part[kHashTreeOffset] ^= 1; // flip one bit 185 test_utils::WriteFileVector(temp_file_.path(), part); 186 EXPECT_TRUE(image_config_.LoadImageSize()); 187 EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem()); 188 EXPECT_FALSE(image_config_.LoadVerityConfig()); 189 } 190 191 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigInvalidFECTest) { 192 brillo::Blob part = GetAVBPartition(); 193 part[kFECOffset] ^= 1; // flip one bit 194 test_utils::WriteFileVector(temp_file_.path(), part); 195 EXPECT_TRUE(image_config_.LoadImageSize()); 196 EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem()); 197 EXPECT_FALSE(image_config_.LoadVerityConfig()); 198 } 199 200 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigEmptyImageTest) { 201 brillo::Blob part(kImageSize); 202 test_utils::WriteFileVector(temp_file_.path(), part); 203 EXPECT_TRUE(image_config_.LoadImageSize()); 204 EXPECT_TRUE(image_config_.LoadVerityConfig()); 205 EXPECT_TRUE(image_config_.partitions[0].verity.IsEmpty()); 206 } 207 208 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigTinyImageTest) { 209 test_utils::WriteFileString(temp_file_.path(), "tiny"); 210 EXPECT_TRUE(image_config_.LoadImageSize()); 211 EXPECT_TRUE(image_config_.LoadVerityConfig()); 212 EXPECT_TRUE(image_config_.partitions[0].verity.IsEmpty()); 213 } 214 215 } // namespace chromeos_update_engine 216