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