1 /*
2 * Copyright (C) 2019 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 <endian.h>
18 #include <stdlib.h>
19
20 #include <android-base/file.h>
21 #include <base/files/file_util.h>
22 #include <base/strings/string_util.h>
23 #include <fs_avb/fs_avb.h>
24 #include <libavb/libavb.h>
25
26 #include "fs_avb_test_util.h"
27
28 // Target classes or functions to test:
29 using android::fs_mgr::AvbHandle;
30 using android::fs_mgr::AvbHandleStatus;
31 using android::fs_mgr::HashAlgorithm;
32
33 namespace fs_avb_host_test {
34
35 class PublicFsAvbTest : public BaseFsAvbTest {
36 public:
PublicFsAvbTest()37 PublicFsAvbTest(){};
38
39 protected:
~PublicFsAvbTest()40 ~PublicFsAvbTest(){};
41 // Modifies |flags| field in the vbmeta header in an Avb image.
42 // e.g., AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED.
43 void ModifyVBMetaHeaderFlags(const base::FilePath& vbmeta_image_path, uint32_t flags);
44 };
45
ModifyVBMetaHeaderFlags(const base::FilePath & vbmeta_image_path,uint32_t flags)46 void PublicFsAvbTest::ModifyVBMetaHeaderFlags(const base::FilePath& vbmeta_image_path,
47 uint32_t flags) {
48 if (!base::PathExists(vbmeta_image_path)) return;
49
50 // Only support modifying the flags in vbmeta*.img.
51 std::string image_file_name = vbmeta_image_path.RemoveExtension().BaseName().value();
52 ASSERT_TRUE(base::StartsWith(image_file_name, "vbmeta", base::CompareCase::INSENSITIVE_ASCII));
53
54 android::base::unique_fd fd(open(vbmeta_image_path.value().c_str(), O_RDWR | O_CLOEXEC));
55 EXPECT_TRUE(fd > 0);
56
57 auto flags_offset = offsetof(AvbVBMetaImageHeader, flags);
58 uint32_t flags_data = htobe32(flags);
59 EXPECT_EQ(flags_offset, lseek64(fd, flags_offset, SEEK_SET));
60 EXPECT_EQ(sizeof flags_data, write(fd, &flags_data, sizeof flags_data));
61 }
62
TEST_F(PublicFsAvbTest,LoadAndVerifyVbmeta)63 TEST_F(PublicFsAvbTest, LoadAndVerifyVbmeta) {
64 // Generates a raw boot.img
65 const size_t boot_image_size = 5 * 1024 * 1024;
66 const size_t boot_partition_size = 10 * 1024 * 1024;
67 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
68
69 // Adds AVB Hash Footer.
70 AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
71 data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
72 "--internal_release_string \"unit test\"");
73
74 // Generates a raw system.img, use a smaller size to speed-up unit test.
75 const size_t system_image_size = 10 * 1024 * 1024;
76 const size_t system_partition_size = 15 * 1024 * 1024;
77 base::FilePath system_path = GenerateImage("system.img", system_image_size);
78 // Adds AVB Hashtree Footer.
79 AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
80 data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
81 "--internal_release_string \"unit test\"");
82
83 // Generates chain partition descriptors.
84 base::FilePath rsa2048_public_key =
85 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
86 base::FilePath rsa4096_public_key =
87 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
88
89 // Makes a vbmeta image includeing 'boot' and 'system' chained descriptors.
90 auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
91 data_dir_.Append("testkey_rsa8192.pem"),
92 {}, /* include_descriptor_image_paths */
93 {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
94 {"system", 2, rsa4096_public_key}},
95 "--internal_release_string \"unit test\"");
96
97 // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
98 EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
99 CalcVBMetaDigest("vbmeta.img", "sha256"));
100
101 // Invokes the public API from fs_avb.h.
102 auto vbmeta_image_path = [this](const std::string& partition_name) {
103 return test_dir_.Append(partition_name + ".img").value();
104 };
105 auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(
106 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
107 "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
108 false /* allow_verification_error */, true /* load_chained_vbmeta */,
109 true /* rollback_protection */, vbmeta_image_path);
110 EXPECT_NE(nullptr, avb_handle);
111 EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
112
113 // Checks the summary info for all vbmeta images.
114 // Checks the digest matches the value calculated by CalcVBMetaDigest().
115 EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
116 avb_handle->vbmeta_info().digest);
117 EXPECT_EQ(8576UL, avb_handle->vbmeta_info().total_size);
118 EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
119
120 // Skip loading chained vbmeta.
121 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
122 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
123 "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
124 false /* allow_verification_error */, false /* load_chained_vbmeta */,
125 true /* rollback_protection */, vbmeta_image_path);
126 EXPECT_NE(nullptr, avb_handle);
127 EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
128 EXPECT_EQ("5c31197992b3c72a854ec7dc0eb9609ffebcffab7917ffd381a99ecee328f09c",
129 avb_handle->vbmeta_info().digest);
130 EXPECT_EQ(5184UL, avb_handle->vbmeta_info().total_size);
131 EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
132 }
133
TEST_F(PublicFsAvbTest,LoadAndVerifyVbmetaWithModifications)134 TEST_F(PublicFsAvbTest, LoadAndVerifyVbmetaWithModifications) {
135 // Generates a raw boot.img
136 const size_t boot_image_size = 5 * 1024 * 1024;
137 const size_t boot_partition_size = 10 * 1024 * 1024;
138 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
139
140 // Adds AVB Hash Footer.
141 AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
142 data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
143 "--internal_release_string \"unit test\"");
144
145 // Generates a raw system.img, use a smaller size to speed-up unit test.
146 const size_t system_image_size = 10 * 1024 * 1024;
147 const size_t system_partition_size = 15 * 1024 * 1024;
148 base::FilePath system_path = GenerateImage("system.img", system_image_size);
149 // Adds AVB Hashtree Footer.
150 AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
151 data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
152 "--internal_release_string \"unit test\"");
153
154 // Generates chain partition descriptors.
155 base::FilePath rsa2048_public_key =
156 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
157 base::FilePath rsa4096_public_key =
158 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
159
160 // Makes a vbmeta image includeing 'boot' and 'system' chained descriptors.
161 auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
162 data_dir_.Append("testkey_rsa8192.pem"),
163 {}, /* include_descriptor_image_paths */
164 {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
165 {"system", 2, rsa4096_public_key}},
166 "--internal_release_string \"unit test\"");
167
168 // Calculates the digest of all chained partitions, to ensure the chained is formed properly.
169 EXPECT_EQ("abbe11b316901f3336e26630f64c4732dadbe14532186ac8640e4141a403721f",
170 CalcVBMetaDigest("vbmeta.img", "sha256"));
171
172 // Sets AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED in the vbmeta.img.
173 ModifyVBMetaHeaderFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
174
175 auto vbmeta_image_path = [this](const std::string& partition_name) {
176 return test_dir_.Append(partition_name + ".img").value();
177 };
178 auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(
179 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
180 "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
181 false /* allow_verification_error */, true /* load_chained_vbmeta */,
182 true /* rollback_protection */, vbmeta_image_path);
183 // Returns a null handler because allow_verification is not True.
184 EXPECT_EQ(nullptr, avb_handle);
185
186 // Try again with allow_verification_error set to true.
187 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
188 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
189 "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
190 true /* allow_verification_error */, true /* load_chained_vbmeta */,
191 true /* rollback_protection */, vbmeta_image_path);
192 EXPECT_NE(nullptr, avb_handle);
193 EXPECT_EQ(AvbHandleStatus::kHashtreeDisabled, avb_handle->status());
194
195 // Checks the summary info for all vbmeta images.
196 // Checks the digest matches the value calculated by CalcVBMetaDigest().
197 EXPECT_EQ("ae8f7ad95cbb7ce4f0feeeedc2a0a39824af5cd29dad4d028597cab4b8c2e83c",
198 CalcVBMetaDigest("vbmeta.img", "sha256"));
199 EXPECT_EQ("ae8f7ad95cbb7ce4f0feeeedc2a0a39824af5cd29dad4d028597cab4b8c2e83c",
200 avb_handle->vbmeta_info().digest);
201 EXPECT_EQ(8576UL, avb_handle->vbmeta_info().total_size);
202 EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
203
204 // Sets AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED in the vbmeta.img.
205 ModifyVBMetaHeaderFlags(vbmeta_path, AVB_VBMETA_IMAGE_FLAGS_VERIFICATION_DISABLED);
206 // Loads the vbmeta with allow_verification_error set to true.
207 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
208 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
209 "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
210 true /* allow_verification_error */, true /* load_chained_vbmeta */,
211 true /* rollback_protection */, vbmeta_image_path);
212 EXPECT_NE(nullptr, avb_handle);
213 EXPECT_EQ(AvbHandleStatus::kVerificationDisabled, avb_handle->status());
214 // Only the top-level vbmeta.img is loaded, when VERIFICATION_DISABLED is set.
215 // However, CalcVBMetaDigest() reads all vbmeta structs to calculate the digest,
216 // including vbmeta.img, boot.img and syste.img. So we don't compare the digest here.
217 EXPECT_EQ(5184UL, avb_handle->vbmeta_info().total_size);
218
219 // Sets a unknown flag in the vbmeta.imgm and expects to get
220 // AvbHandleStatus::kVerificationError.
221 ModifyVBMetaHeaderFlags(vbmeta_path, 0x10000000);
222 // Loads the vbmeta with allow_verification_error set to true.
223 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
224 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
225 "" /* expected_public_key_blob*/, HashAlgorithm::kSHA256,
226 true /* allow_verification_error */, true /* load_chained_vbmeta */,
227 true /* rollback_protection */, vbmeta_image_path);
228 EXPECT_NE(nullptr, avb_handle);
229 EXPECT_EQ(AvbHandleStatus::kVerificationError, avb_handle->status());
230 // Checks the digest matches the value calculated by CalcVBMetaDigest().
231 EXPECT_EQ("8fb99c4f54500053c3582df5eaf04e9a533137398879188aad9968ec19a664f1",
232 CalcVBMetaDigest("vbmeta.img", "sha256"));
233 EXPECT_EQ("8fb99c4f54500053c3582df5eaf04e9a533137398879188aad9968ec19a664f1",
234 avb_handle->vbmeta_info().digest);
235 EXPECT_EQ(8576UL, avb_handle->vbmeta_info().total_size);
236 EXPECT_EQ(HashAlgorithm::kSHA256, avb_handle->vbmeta_info().hash_algorithm);
237 }
238
TEST_F(PublicFsAvbTest,LoadAndVerifyVbmetaWithPublicKeys)239 TEST_F(PublicFsAvbTest, LoadAndVerifyVbmetaWithPublicKeys) {
240 // Generates a raw boot.img
241 const size_t boot_image_size = 5 * 1024 * 1024;
242 const size_t boot_partition_size = 10 * 1024 * 1024;
243 base::FilePath boot_path = GenerateImage("boot.img", boot_image_size);
244
245 // Adds AVB Hash Footer.
246 AddAvbFooter(boot_path, "hash", "boot", boot_partition_size, "SHA256_RSA2048", 10,
247 data_dir_.Append("testkey_rsa2048.pem"), "d00df00d",
248 "--internal_release_string \"unit test\"");
249
250 // Generates a raw system.img, use a smaller size to speed-up unit test.
251 const size_t system_image_size = 10 * 1024 * 1024;
252 const size_t system_partition_size = 15 * 1024 * 1024;
253 base::FilePath system_path = GenerateImage("system.img", system_image_size);
254 // Adds AVB Hashtree Footer.
255 AddAvbFooter(system_path, "hashtree", "system", system_partition_size, "SHA512_RSA4096", 20,
256 data_dir_.Append("testkey_rsa4096.pem"), "d00df00d",
257 "--internal_release_string \"unit test\"");
258
259 // Generates chain partition descriptors.
260 base::FilePath rsa2048_public_key =
261 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa2048.pem"));
262 base::FilePath rsa4096_public_key =
263 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa4096.pem"));
264 base::FilePath rsa8192_public_key =
265 ExtractPublicKeyAvb(data_dir_.Append("testkey_rsa8192.pem"));
266
267 // Makes a vbmeta image includeing 'boot' and 'vbmeta_system' chained descriptors.
268 auto vbmeta_path = GenerateVBMetaImage("vbmeta.img", "SHA256_RSA8192", 0,
269 data_dir_.Append("testkey_rsa8192.pem"),
270 {}, /* include_descriptor_image_paths */
271 {{"boot", 1, rsa2048_public_key}, /* chain_partitions */
272 {"system", 2, rsa4096_public_key}},
273 "--internal_release_string \"unit test\"");
274
275 auto vbmeta_image_path = [this](const std::string& partition_name) {
276 return test_dir_.Append(partition_name + ".img").value();
277 };
278 std::vector<VBMetaData> vbmeta_images;
279 // Uses the correct expected public key.
280 auto avb_handle = AvbHandle::LoadAndVerifyVbmeta(
281 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
282 rsa8192_public_key.value(), HashAlgorithm::kSHA256, true /* allow_verification_error */,
283 true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path);
284 EXPECT_NE(nullptr, avb_handle);
285 EXPECT_EQ(AvbHandleStatus::kSuccess, avb_handle->status());
286
287 // Uses a non-existed public key.
288 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
289 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
290 "/path/to/non-existed/key", HashAlgorithm::kSHA256, true /* allow_verification_error */,
291 true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path);
292 EXPECT_EQ(nullptr, avb_handle);
293
294 // Uses an incorrect public key, with allow_verification_error false.
295 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
296 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
297 rsa4096_public_key.value(), HashAlgorithm::kSHA256,
298 false /* allow_verification_error */, true /* load_chained_vbmeta */,
299 true /* rollback_protection */, vbmeta_image_path);
300 EXPECT_EQ(nullptr, avb_handle);
301
302 // Uses an incorrect public key, with allow_verification_error true.
303 avb_handle = AvbHandle::LoadAndVerifyVbmeta(
304 "vbmeta" /* partition_name */, "" /* ab_suffix */, "" /* other_suffix */,
305 rsa4096_public_key.value(), HashAlgorithm::kSHA256, true /* allow_verification_error */,
306 true /* load_chained_vbmeta */, true /* rollback_protection */, vbmeta_image_path);
307 EXPECT_NE(nullptr, avb_handle);
308 EXPECT_EQ(AvbHandleStatus::kVerificationError, avb_handle->status());
309 }
310
311 } // namespace fs_avb_host_test
312