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 
GetAVBPartition()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:
SetUp()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   ScopedTempFile temp_file_{"PayloadGenerationConfigAndroidTest.XXXXXX"};
142 };
143 
TEST_F(PayloadGenerationConfigAndroidTest,LoadVerityConfigSimpleTest)144 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigSimpleTest) {
145   brillo::Blob part = GetAVBPartition();
146   test_utils::WriteFileVector(temp_file_.path(), part);
147   EXPECT_TRUE(image_config_.LoadImageSize());
148   EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem());
149   EXPECT_TRUE(image_config_.LoadVerityConfig());
150   const VerityConfig& verity = image_config_.partitions[0].verity;
151   EXPECT_FALSE(verity.IsEmpty());
152   EXPECT_EQ(ExtentForRange(0, 2), verity.hash_tree_data_extent);
153   EXPECT_EQ(ExtentForRange(2, 1), verity.hash_tree_extent);
154   EXPECT_EQ("sha1", verity.hash_tree_algorithm);
155   brillo::Blob salt(kHashTreeSalt, std::end(kHashTreeSalt));
156   EXPECT_EQ(salt, verity.hash_tree_salt);
157   EXPECT_EQ(ExtentForRange(0, 3), verity.fec_data_extent);
158   EXPECT_EQ(ExtentForRange(3, 2), verity.fec_extent);
159   EXPECT_EQ(2u, verity.fec_roots);
160 }
161 
TEST_F(PayloadGenerationConfigAndroidTest,LoadVerityConfigDisableFecTest)162 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigDisableFecTest) {
163   brillo::Blob part = GetAVBPartition();
164   test_utils::WriteFileVector(temp_file_.path(), part);
165   image_config_.partitions[0].disable_fec_computation = true;
166   EXPECT_TRUE(image_config_.LoadImageSize());
167   EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem());
168   EXPECT_TRUE(image_config_.LoadVerityConfig());
169   const VerityConfig& verity = image_config_.partitions[0].verity;
170   EXPECT_FALSE(verity.IsEmpty());
171   EXPECT_EQ(ExtentForRange(0, 2), verity.hash_tree_data_extent);
172   EXPECT_EQ(ExtentForRange(2, 1), verity.hash_tree_extent);
173   EXPECT_EQ("sha1", verity.hash_tree_algorithm);
174   brillo::Blob salt(kHashTreeSalt, std::end(kHashTreeSalt));
175   EXPECT_EQ(salt, verity.hash_tree_salt);
176   EXPECT_EQ(0u, verity.fec_data_extent.num_blocks());
177   EXPECT_EQ(0u, verity.fec_extent.num_blocks());
178 }
179 
TEST_F(PayloadGenerationConfigAndroidTest,LoadVerityConfigInvalidHashTreeTest)180 TEST_F(PayloadGenerationConfigAndroidTest,
181        LoadVerityConfigInvalidHashTreeTest) {
182   brillo::Blob part = GetAVBPartition();
183   part[kHashTreeOffset] ^= 1;  // flip one bit
184   test_utils::WriteFileVector(temp_file_.path(), part);
185   EXPECT_TRUE(image_config_.LoadImageSize());
186   EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem());
187   EXPECT_FALSE(image_config_.LoadVerityConfig());
188 }
189 
TEST_F(PayloadGenerationConfigAndroidTest,LoadVerityConfigInvalidFECTest)190 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigInvalidFECTest) {
191   brillo::Blob part = GetAVBPartition();
192   part[kFECOffset] ^= 1;  // flip one bit
193   test_utils::WriteFileVector(temp_file_.path(), part);
194   EXPECT_TRUE(image_config_.LoadImageSize());
195   EXPECT_TRUE(image_config_.partitions[0].OpenFilesystem());
196   EXPECT_FALSE(image_config_.LoadVerityConfig());
197 }
198 
TEST_F(PayloadGenerationConfigAndroidTest,LoadVerityConfigEmptyImageTest)199 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigEmptyImageTest) {
200   brillo::Blob part(kImageSize);
201   test_utils::WriteFileVector(temp_file_.path(), part);
202   EXPECT_TRUE(image_config_.LoadImageSize());
203   EXPECT_TRUE(image_config_.LoadVerityConfig());
204   EXPECT_TRUE(image_config_.partitions[0].verity.IsEmpty());
205 }
206 
TEST_F(PayloadGenerationConfigAndroidTest,LoadVerityConfigTinyImageTest)207 TEST_F(PayloadGenerationConfigAndroidTest, LoadVerityConfigTinyImageTest) {
208   test_utils::WriteFileString(temp_file_.path(), "tiny");
209   EXPECT_TRUE(image_config_.LoadImageSize());
210   EXPECT_TRUE(image_config_.LoadVerityConfig());
211   EXPECT_TRUE(image_config_.partitions[0].verity.IsEmpty());
212 }
213 
214 }  // namespace chromeos_update_engine
215