1 /*
2 * Copyright (C) 2021 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 <vector>
18
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <android-base/properties.h>
22 #include <android-base/unique_fd.h>
23 #include <android/api-level.h>
24 #include <bootimg.h>
25 #include <fs_avb/fs_avb_util.h>
26 #include <gtest/gtest.h>
27 #include <libavb/libavb.h>
28 #include <storage_literals/storage_literals.h>
29 #include <vintf/VintfObject.h>
30 #include <vintf/parse_string.h>
31
32 #include "gsi_validation_utils.h"
33
34 using namespace std::literals;
35 using namespace android::storage_literals;
36
37 namespace {
38
GetBlockDevicePath(const std::string & name)39 std::string GetBlockDevicePath(const std::string &name) {
40 return "/dev/block/by-name/" + name + fs_mgr_get_slot_suffix();
41 }
42
43 class GkiBootImage {
44 public:
GkiBootImage(const uint8_t * data,size_t size)45 GkiBootImage(const uint8_t *data, size_t size) : data_(data, data + size) {}
46
GetBootHeaderVersion(const void * data)47 static uint32_t GetBootHeaderVersion(const void *data) {
48 return static_cast<const boot_img_hdr_v0 *>(data)->header_version;
49 }
50
header_version() const51 uint32_t header_version() const { return GetBootHeaderVersion(data()); }
52
kernel_pages() const53 uint32_t kernel_pages() const { return GetNumberOfPages(kernel_size()); }
54
ramdisk_pages() const55 uint32_t ramdisk_pages() const { return GetNumberOfPages(ramdisk_size()); }
56
kernel_offset() const57 uint32_t kernel_offset() const {
58 // The first page must be the boot image header.
59 return page_size();
60 }
61
ramdisk_offset() const62 uint32_t ramdisk_offset() const {
63 return kernel_offset() + kernel_pages() * page_size();
64 }
65
66 virtual uint32_t page_size() const = 0;
67 virtual uint32_t os_version() const = 0;
68 virtual uint32_t kernel_size() const = 0;
69 virtual uint32_t ramdisk_size() const = 0;
70 virtual uint32_t signature_size() const = 0;
71 virtual uint32_t signature_offset() const = 0;
72
GetNumberOfPages(uint32_t value) const73 uint32_t GetNumberOfPages(uint32_t value) const {
74 return (value + page_size() - 1) / page_size();
75 }
76
GetKernel() const77 std::vector<uint8_t> GetKernel() const {
78 return Slice(kernel_offset(), kernel_size());
79 }
80
81 // Get "effective" boot image. The pure boot image without any boot signature.
GetBootImage() const82 std::vector<uint8_t> GetBootImage() const {
83 return Slice(0, signature_offset());
84 }
85
86 // Parse a vector of vbmeta image from the boot signature section.
GetBootSignatures() const87 std::vector<android::fs_mgr::VBMetaData> GetBootSignatures() const {
88 const auto begin_offset = std::clamp<size_t>(signature_offset(), 0, size());
89 const uint8_t *buffer = data() + begin_offset;
90 // begin_offset + remaining_bytes <= size() because boot_signature must be
91 // the last section.
92 size_t remaining_bytes =
93 std::clamp<size_t>(signature_size(), 0, size() - begin_offset);
94 // In case boot_signature is misaligned, shift to the first AVB magic, and
95 // treat it as the actual beginning of boot signature.
96 while (remaining_bytes >= AVB_MAGIC_LEN) {
97 if (!memcmp(buffer, AVB_MAGIC, AVB_MAGIC_LEN)) {
98 break;
99 }
100 ++buffer;
101 --remaining_bytes;
102 }
103 std::vector<android::fs_mgr::VBMetaData> vbmeta_images;
104 while (remaining_bytes >= sizeof(AvbVBMetaImageHeader)) {
105 if (memcmp(buffer, AVB_MAGIC, AVB_MAGIC_LEN) != 0) {
106 break;
107 }
108 // Extract only the header to calculate the vbmeta image size.
109 android::fs_mgr::VBMetaData vbmeta_header(
110 buffer, sizeof(AvbVBMetaImageHeader), "boot_signature");
111 if (!vbmeta_header.GetVBMetaHeader(/* update_vbmeta_size */ true)) {
112 GTEST_LOG_(ERROR) << __FUNCTION__
113 << "(): VBMetaData::GetVBMetaHeader() failed.";
114 return {};
115 }
116 const auto vbmeta_image_size = vbmeta_header.size();
117 GTEST_LOG_(INFO) << __FUNCTION__ << "(): Found vbmeta image with size "
118 << vbmeta_image_size;
119 if (vbmeta_image_size < sizeof(AvbVBMetaImageHeader)) {
120 GTEST_LOG_(ERROR) << __FUNCTION__
121 << "(): Impossible-sized vbmeta image: "
122 << vbmeta_image_size;
123 return {};
124 }
125
126 if (vbmeta_image_size > remaining_bytes) {
127 GTEST_LOG_(ERROR)
128 << __FUNCTION__
129 << "(): Premature EOF when parsing GKI boot signature.";
130 return {};
131 }
132
133 vbmeta_images.emplace_back(buffer, vbmeta_image_size, "boot_signature");
134 buffer += vbmeta_image_size;
135 remaining_bytes -= vbmeta_image_size;
136 }
137 return vbmeta_images;
138 }
139
140 virtual ~GkiBootImage() = default;
141
142 protected:
data() const143 const uint8_t *data() const { return data_.data(); }
144
size() const145 size_t size() const { return data_.size(); }
146
Slice(size_t offset,size_t length) const147 std::vector<uint8_t> Slice(size_t offset, size_t length) const {
148 const auto begin_offset = std::clamp<size_t>(offset, 0, size());
149 const auto end_offset =
150 std::clamp<size_t>(begin_offset + length, begin_offset, size());
151 const auto begin = data() + begin_offset;
152 const auto end = data() + end_offset;
153 return {begin, end};
154 }
155
156 private:
157 std::vector<uint8_t> data_;
158 };
159
160 class GkiBootImageV2 : public GkiBootImage {
161 public:
GkiBootImageV2(const uint8_t * data,size_t size)162 GkiBootImageV2(const uint8_t *data, size_t size) : GkiBootImage(data, size) {}
163
boot_header() const164 const boot_img_hdr_v2 *boot_header() const {
165 return reinterpret_cast<const boot_img_hdr_v2 *>(data());
166 }
167
page_size() const168 uint32_t page_size() const override { return boot_header()->page_size; }
169
os_version() const170 uint32_t os_version() const override { return boot_header()->os_version; }
171
kernel_size() const172 uint32_t kernel_size() const override { return boot_header()->kernel_size; }
173
ramdisk_size() const174 uint32_t ramdisk_size() const override { return boot_header()->ramdisk_size; }
175
signature_size() const176 uint32_t signature_size() const override {
177 // The last 16K bytes are by definition the GKI boot signature.
178 static constexpr uint32_t kBootSignatureSize = 16_KiB;
179 return kBootSignatureSize;
180 }
181
signature_offset() const182 uint32_t signature_offset() const override {
183 if (size() < signature_size()) {
184 return 0;
185 }
186 return size() - signature_size();
187 }
188
recovery_dtbo_size() const189 uint32_t recovery_dtbo_size() const {
190 return boot_header()->recovery_dtbo_size;
191 }
192
recovery_dtbo_offset() const193 uint64_t recovery_dtbo_offset() const {
194 return boot_header()->recovery_dtbo_offset;
195 }
196 };
197
198 class GkiBootImageV4 : public GkiBootImage {
199 public:
GkiBootImageV4(const uint8_t * data,size_t size)200 GkiBootImageV4(const uint8_t *data, size_t size) : GkiBootImage(data, size) {}
201
boot_header() const202 const boot_img_hdr_v4 *boot_header() const {
203 return reinterpret_cast<const boot_img_hdr_v4 *>(data());
204 }
205
page_size() const206 uint32_t page_size() const override {
207 static constexpr uint32_t kPageSize = 4096;
208 return kPageSize;
209 }
210
os_version() const211 uint32_t os_version() const override { return boot_header()->os_version; }
212
kernel_size() const213 uint32_t kernel_size() const override { return boot_header()->kernel_size; }
214
ramdisk_size() const215 uint32_t ramdisk_size() const override { return boot_header()->ramdisk_size; }
216
signature_size() const217 uint32_t signature_size() const override {
218 // For Android12 GKI, the |.signature_size| field is respected.
219 // For Android13+ GKI, the |.signature_size| field must be zero, and the
220 // last 16K bytes are by definition the GKI boot signature.
221 static constexpr uint32_t kBootSignatureSize = 16_KiB;
222 const uint32_t value = boot_header()->signature_size;
223 return value ? value : kBootSignatureSize;
224 }
225
signature_offset() const226 uint32_t signature_offset() const override {
227 return ramdisk_offset() + ramdisk_pages() * page_size();
228 }
229 };
230
GetAvbProperty(const std::string & name,const std::vector<android::fs_mgr::VBMetaData> & vbmeta_images)231 std::string GetAvbProperty(
232 const std::string &name,
233 const std::vector<android::fs_mgr::VBMetaData> &vbmeta_images) {
234 const std::string prop_name = "com.android.build." + name;
235 return android::fs_mgr::GetAvbPropertyDescriptor(prop_name, vbmeta_images);
236 }
237
LoadAndVerifyGkiBootImage(std::vector<android::fs_mgr::VBMetaData> * boot_signature_images)238 std::unique_ptr<GkiBootImage> LoadAndVerifyGkiBootImage(
239 std::vector<android::fs_mgr::VBMetaData> *boot_signature_images) {
240 const std::string block_device_path = GetBlockDevicePath("boot");
241 const std::string TAG = __FUNCTION__ + "("s + block_device_path + ")";
242 SCOPED_TRACE(TAG);
243
244 std::string block_device_data;
245 if (!android::base::ReadFileToString(block_device_path, &block_device_data,
246 /* follow_symlinks */ true)) {
247 ADD_FAILURE() << "Failed to read '" << block_device_path
248 << "': " << strerror(errno);
249 return nullptr;
250 }
251 if (block_device_data.size() <= 4096) {
252 ADD_FAILURE() << "Size of '" << block_device_path
253 << "' is impossibly small: " << block_device_data.size();
254 return nullptr;
255 }
256
257 if (block_device_data.substr(0, BOOT_MAGIC_SIZE) != BOOT_MAGIC) {
258 ADD_FAILURE() << "Device has invalid boot magic: " << block_device_path;
259 return nullptr;
260 }
261
262 // Remove the AVB footer and chained vbmeta image if there is any.
263 if (block_device_data.size() > AVB_FOOTER_SIZE) {
264 const uint8_t *footer_address =
265 reinterpret_cast<const uint8_t *>(block_device_data.data()) +
266 block_device_data.size() - AVB_FOOTER_SIZE;
267 AvbFooter vbmeta_footer;
268 if (avb_footer_validate_and_byteswap(
269 reinterpret_cast<const AvbFooter *>(footer_address),
270 &vbmeta_footer)) {
271 block_device_data.resize(vbmeta_footer.original_image_size);
272 }
273 }
274
275 std::unique_ptr<GkiBootImage> boot_image;
276 const auto boot_header_version =
277 GkiBootImage::GetBootHeaderVersion(block_device_data.data());
278 if (boot_header_version == 4) {
279 boot_image = std::make_unique<GkiBootImageV4>(
280 reinterpret_cast<const uint8_t *>(block_device_data.data()),
281 block_device_data.size());
282 } else if (boot_header_version == 2) {
283 boot_image = std::make_unique<GkiBootImageV2>(
284 reinterpret_cast<const uint8_t *>(block_device_data.data()),
285 block_device_data.size());
286 } else {
287 ADD_FAILURE() << "Unexpected boot header version: " << boot_header_version;
288 return nullptr;
289 }
290
291 *boot_signature_images = boot_image->GetBootSignatures();
292 if (boot_signature_images->empty()) {
293 ADD_FAILURE() << "Failed to load the boot signature.";
294 return nullptr;
295 }
296
297 // Verify that the vbmeta images in boot_signature are certified.
298 for (const auto &vbmeta_image : *boot_signature_images) {
299 size_t pk_len;
300 const uint8_t *pk_data;
301 const auto vbmeta_verify_result = avb_vbmeta_image_verify(
302 vbmeta_image.data(), vbmeta_image.size(), &pk_data, &pk_len);
303 if (vbmeta_verify_result != AVB_VBMETA_VERIFY_RESULT_OK) {
304 ADD_FAILURE() << "Failed to verify boot_signature: "
305 << avb_vbmeta_verify_result_to_string(vbmeta_verify_result);
306 return nullptr;
307 }
308 const std::string out_public_key_data(
309 reinterpret_cast<const char *>(pk_data), pk_len);
310 if (out_public_key_data.empty()) {
311 ADD_FAILURE() << "The GKI image descriptor is not signed.";
312 continue;
313 }
314 if (!ValidatePublicKeyBlob(out_public_key_data)) {
315 ADD_FAILURE()
316 << "The GKI image descriptor is not signed by an official key.";
317 continue;
318 }
319 }
320
321 GTEST_LOG_(INFO) << TAG << ": boot.fingerprint: "
322 << GetAvbProperty("boot.fingerprint",
323 *boot_signature_images);
324 GTEST_LOG_(INFO) << TAG
325 << ": header version: " << boot_image->header_version()
326 << ", kernel size: " << boot_image->kernel_size()
327 << ", ramdisk size: " << boot_image->ramdisk_size()
328 << ", signature size: " << boot_image->signature_size();
329
330 return boot_image;
331 }
332
333 // Verify image data integrity with an AVB hash descriptor.
VerifyImageDescriptor(const std::vector<uint8_t> & image,const android::fs_mgr::FsAvbHashDescriptor & descriptor)334 void VerifyImageDescriptor(
335 const std::vector<uint8_t> &image,
336 const android::fs_mgr::FsAvbHashDescriptor &descriptor) {
337 const std::string TAG = __FUNCTION__ + "("s + descriptor.partition_name + ")";
338 SCOPED_TRACE(TAG);
339
340 ASSERT_EQ(image.size(), descriptor.image_size);
341
342 const std::string &salt_str = descriptor.salt;
343 const std::string &expected_digest_str = descriptor.digest;
344
345 const std::string hash_algorithm(
346 reinterpret_cast<const char *>(descriptor.hash_algorithm));
347 GTEST_LOG_(INFO) << TAG << ": hash_algorithm = " << hash_algorithm;
348
349 std::unique_ptr<ShaHasher> hasher = CreateShaHasher(hash_algorithm);
350 ASSERT_NE(nullptr, hasher);
351
352 std::vector<uint8_t> salt, expected_digest, out_digest;
353
354 ASSERT_TRUE(HexToBytes(salt_str, &salt))
355 << "Invalid salt in descriptor: " << salt_str;
356 ASSERT_TRUE(HexToBytes(expected_digest_str, &expected_digest))
357 << "Invalid digest in descriptor: " << expected_digest_str;
358
359 ASSERT_EQ(expected_digest.size(), hasher->GetDigestSize());
360 out_digest.resize(hasher->GetDigestSize());
361
362 ASSERT_TRUE(hasher->CalculateDigest(image.data(), image.size(), salt.data(),
363 descriptor.salt_len, out_digest.data()))
364 << "Unable to calculate image digest.";
365
366 ASSERT_EQ(out_digest.size(), expected_digest.size())
367 << "Calculated digest size does not match expected digest size.";
368
369 ASSERT_EQ(out_digest, expected_digest)
370 << "Calculated digest does not match expected digest.";
371 }
372
373 // Returns true iff the device has the specified feature.
DeviceSupportsFeature(const char * feature)374 bool DeviceSupportsFeature(const char *feature) {
375 bool device_supports_feature = false;
376 FILE *p = popen("pm list features", "re");
377 if (p) {
378 char *line = NULL;
379 size_t len = 0;
380 while (getline(&line, &len, p) > 0) {
381 if (strstr(line, feature)) {
382 device_supports_feature = true;
383 break;
384 }
385 }
386 pclose(p);
387 }
388 return device_supports_feature;
389 }
390
391 } // namespace
392
393 class GkiComplianceTest : public testing::Test {
394 protected:
SetUp()395 void SetUp() override {
396 // Fetch device runtime information.
397 runtime_info = android::vintf::VintfObject::GetRuntimeInfo();
398 ASSERT_NE(nullptr, runtime_info);
399
400 product_first_api_level = GetProductFirstApiLevel();
401
402 /* Skip for non-arm64 kernels that do not mandate GKI yet. */
403 if (runtime_info->hardwareId() != "aarch64" &&
404 runtime_info->hardwareId() != "armv8l") {
405 GTEST_SKIP() << "Exempt from GKI test on non-arm64 kernel devices";
406 }
407
408 /* Skip for form factors that do not mandate GKI yet */
409 const static bool tv_device =
410 DeviceSupportsFeature("android.software.leanback");
411 const static bool auto_device =
412 DeviceSupportsFeature("android.hardware.type.automotive");
413 if (tv_device || auto_device) {
414 GTEST_SKIP() << "Exempt from GKI test on TV/Auto devices";
415 }
416
417 GTEST_LOG_(INFO) << runtime_info->osName() << " "
418 << runtime_info->osRelease();
419 GTEST_LOG_(INFO) << "Product first API level: " << product_first_api_level;
420 }
421
422 bool ShouldSkipGkiComplianceV2();
423
424 std::shared_ptr<const android::vintf::RuntimeInfo> runtime_info;
425 int product_first_api_level;
426 };
427
ShouldSkipGkiComplianceV2()428 bool GkiComplianceTest::ShouldSkipGkiComplianceV2() {
429 /* Skip for devices if the kernel version is not >= 5.10. */
430 if (runtime_info->kernelVersion().dropMinor() <
431 android::vintf::Version{5, 10}) {
432 GTEST_LOG_(INFO) << "Exempt from GKI 2.0 test on kernel version: "
433 << runtime_info->kernelVersion();
434 return true;
435 }
436 /* Skip for devices launched before Android S. */
437 if (product_first_api_level < __ANDROID_API_S__) {
438 GTEST_LOG_(INFO) << "Exempt from GKI 2.0 test on pre-S launched devices";
439 return true;
440 }
441 return false;
442 }
443
TEST_F(GkiComplianceTest,GkiComplianceV1)444 TEST_F(GkiComplianceTest, GkiComplianceV1) {
445 if (product_first_api_level < __ANDROID_API_R__) {
446 GTEST_SKIP() << "Exempt from GKI 1.0 test: product first API level ("
447 << product_first_api_level << ") < " << __ANDROID_API_R__;
448 }
449 /* Skip for devices if the kernel version is not 5.4. */
450 if (runtime_info->kernelVersion().dropMinor() !=
451 android::vintf::Version{5, 4}) {
452 GTEST_SKIP() << "Exempt from GKI 1.0 test on kernel version: "
453 << runtime_info->kernelVersion();
454 }
455
456 /* load vbmeta struct from boot, verify struct integrity */
457 std::string out_public_key_data;
458 android::fs_mgr::VBMetaVerifyResult out_verify_result;
459 const std::string boot_path = GetBlockDevicePath("boot");
460 std::unique_ptr<android::fs_mgr::VBMetaData> vbmeta =
461 android::fs_mgr::LoadAndVerifyVbmetaByPath(
462 boot_path, "boot", "" /* expected_key_blob */,
463 true /* allow verification error */, false /* rollback_protection */,
464 false /* is_chained_vbmeta */, &out_public_key_data,
465 nullptr /* out_verification_disabled */, &out_verify_result);
466
467 ASSERT_TRUE(vbmeta) << "Verification of GKI vbmeta fails.";
468 ASSERT_FALSE(out_public_key_data.empty()) << "The GKI image is not signed.";
469 EXPECT_TRUE(ValidatePublicKeyBlob(out_public_key_data))
470 << "The GKI image is not signed by an official key.";
471 EXPECT_EQ(out_verify_result, android::fs_mgr::VBMetaVerifyResult::kSuccess)
472 << "Verification of the GKI vbmeta structure failed.";
473
474 /* verify boot partition according to vbmeta structure */
475 std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor> descriptor =
476 android::fs_mgr::GetHashDescriptor("boot", std::move(*vbmeta));
477 ASSERT_TRUE(descriptor)
478 << "Failed to load hash descriptor from boot.img vbmeta";
479
480 android::base::unique_fd fd(open(boot_path.c_str(), O_RDONLY));
481 ASSERT_TRUE(fd.ok()) << "Fail to open boot partition. Try 'adb root'.";
482
483 std::vector<uint8_t> boot_partition_vector;
484 boot_partition_vector.resize(descriptor->image_size);
485 ASSERT_TRUE(android::base::ReadFully(fd, boot_partition_vector.data(),
486 descriptor->image_size))
487 << "Could not read boot partition to vector.";
488
489 ASSERT_NO_FATAL_FAILURE(
490 VerifyImageDescriptor(boot_partition_vector, *descriptor));
491 }
492
493 // Verify the entire boot image.
TEST_F(GkiComplianceTest,GkiComplianceV2)494 TEST_F(GkiComplianceTest, GkiComplianceV2) {
495 if (ShouldSkipGkiComplianceV2()) {
496 GTEST_SKIP() << "Skipping GkiComplianceV2 test";
497 }
498
499 // GKI 2.0 ensures getKernelLevel() to return valid value.
500 std::string error_msg;
501 const auto kernel_level =
502 android::vintf::VintfObject::GetInstance()->getKernelLevel(&error_msg);
503 ASSERT_NE(android::vintf::Level::UNSPECIFIED, kernel_level) << error_msg;
504
505 std::vector<android::fs_mgr::VBMetaData> boot_signature_images;
506 std::unique_ptr<GkiBootImage> boot_image =
507 LoadAndVerifyGkiBootImage(&boot_signature_images);
508 ASSERT_NE(nullptr, boot_image);
509 ASSERT_LE(1, boot_signature_images.size());
510 EXPECT_EQ(4, boot_image->header_version());
511
512 if (kernel_level >= android::vintf::Level::T) {
513 GTEST_LOG_(INFO)
514 << "Android T+ verification scheme. The GKI boot.img must contain only "
515 "the generic kernel but not the generic ramdisk.";
516 EXPECT_EQ(0, boot_image->ramdisk_size())
517 << "'boot' partition mustn't include a ramdisk image.";
518 EXPECT_EQ(0, boot_image->os_version())
519 << "OS version and security patch level should be defined in the "
520 "chained vbmeta image instead.";
521 }
522
523 std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor> boot_descriptor =
524 android::fs_mgr::GetHashDescriptor("boot", boot_signature_images);
525 ASSERT_NE(nullptr, boot_descriptor)
526 << "Failed to load the 'boot' hash descriptor.";
527 ASSERT_NO_FATAL_FAILURE(
528 VerifyImageDescriptor(boot_image->GetBootImage(), *boot_descriptor));
529 }
530
531 // Verify only the 'generic_kernel' descriptor.
TEST_F(GkiComplianceTest,GkiComplianceV2_kernel)532 TEST_F(GkiComplianceTest, GkiComplianceV2_kernel) {
533 if (ShouldSkipGkiComplianceV2()) {
534 GTEST_SKIP() << "Skipping GkiComplianceV2 test";
535 }
536
537 // GKI 2.0 ensures getKernelLevel() to return valid value.
538 std::string error_msg;
539 const auto kernel_level =
540 android::vintf::VintfObject::GetInstance()->getKernelLevel(&error_msg);
541 ASSERT_NE(android::vintf::Level::UNSPECIFIED, kernel_level) << error_msg;
542 if (kernel_level < android::vintf::Level::T) {
543 GTEST_SKIP() << "Skip for kernel level (" << kernel_level << ") < T ("
544 << android::vintf::Level::T << ")";
545 }
546
547 std::vector<android::fs_mgr::VBMetaData> boot_signature_images;
548 std::unique_ptr<GkiBootImage> boot_image =
549 LoadAndVerifyGkiBootImage(&boot_signature_images);
550 ASSERT_NE(nullptr, boot_image);
551 ASSERT_LE(1, boot_signature_images.size());
552
553 std::unique_ptr<android::fs_mgr::FsAvbHashDescriptor>
554 generic_kernel_descriptor = android::fs_mgr::GetHashDescriptor(
555 "generic_kernel", boot_signature_images);
556 ASSERT_NE(nullptr, generic_kernel_descriptor)
557 << "Failed to load the 'generic_kernel' hash descriptor.";
558 ASSERT_NO_FATAL_FAILURE(VerifyImageDescriptor(boot_image->GetKernel(),
559 *generic_kernel_descriptor));
560 }
561
main(int argc,char * argv[])562 int main(int argc, char *argv[]) {
563 ::testing::InitGoogleTest(&argc, argv);
564 android::base::InitLogging(argv, android::base::StderrLogger);
565 return RUN_ALL_TESTS();
566 }
567