xref: /aosp_15_r20/external/avb/rust/tests/verify_tests.rs (revision d289c2ba6de359471b23d594623b906876bc48a0)
1*d289c2baSAndroid Build Coastguard Worker // Copyright 2023, The Android Open Source Project
2*d289c2baSAndroid Build Coastguard Worker //
3*d289c2baSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*d289c2baSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*d289c2baSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*d289c2baSAndroid Build Coastguard Worker //
7*d289c2baSAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*d289c2baSAndroid Build Coastguard Worker //
9*d289c2baSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*d289c2baSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*d289c2baSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*d289c2baSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*d289c2baSAndroid Build Coastguard Worker // limitations under the License.
14*d289c2baSAndroid Build Coastguard Worker 
15*d289c2baSAndroid Build Coastguard Worker //! libavb_rs verification tests.
16*d289c2baSAndroid Build Coastguard Worker 
17*d289c2baSAndroid Build Coastguard Worker use crate::{
18*d289c2baSAndroid Build Coastguard Worker     build_test_ops_one_image_one_vbmeta,
19*d289c2baSAndroid Build Coastguard Worker     test_data::*,
20*d289c2baSAndroid Build Coastguard Worker     test_ops::{FakeVbmetaKey, TestOps},
21*d289c2baSAndroid Build Coastguard Worker     verify_one_image_one_vbmeta,
22*d289c2baSAndroid Build Coastguard Worker };
23*d289c2baSAndroid Build Coastguard Worker use avb::{
24*d289c2baSAndroid Build Coastguard Worker     slot_verify, ChainPartitionDescriptor, ChainPartitionDescriptorFlags, Descriptor,
25*d289c2baSAndroid Build Coastguard Worker     HashDescriptor, HashDescriptorFlags, HashtreeDescriptor, HashtreeDescriptorFlags,
26*d289c2baSAndroid Build Coastguard Worker     HashtreeErrorMode, IoError, KernelCommandlineDescriptor, KernelCommandlineDescriptorFlags,
27*d289c2baSAndroid Build Coastguard Worker     PropertyDescriptor, SlotVerifyData, SlotVerifyError, SlotVerifyFlags, SlotVerifyResult,
28*d289c2baSAndroid Build Coastguard Worker };
29*d289c2baSAndroid Build Coastguard Worker use hex::decode;
30*d289c2baSAndroid Build Coastguard Worker use std::{ffi::CString, fs};
31*d289c2baSAndroid Build Coastguard Worker #[cfg(feature = "uuid")]
32*d289c2baSAndroid Build Coastguard Worker use uuid::uuid;
33*d289c2baSAndroid Build Coastguard Worker 
34*d289c2baSAndroid Build Coastguard Worker /// Initializes a `TestOps` object such that verification will succeed on `TEST_PARTITION_NAME` and
35*d289c2baSAndroid Build Coastguard Worker /// `TEST_PARTITION_2_NAME`.
build_test_ops_two_images_one_vbmeta<'a>() -> TestOps<'a>36*d289c2baSAndroid Build Coastguard Worker fn build_test_ops_two_images_one_vbmeta<'a>() -> TestOps<'a> {
37*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
38*d289c2baSAndroid Build Coastguard Worker     // Add in the contents of the second partition and overwrite the vbmeta partition to
39*d289c2baSAndroid Build Coastguard Worker     // include both partition descriptors.
40*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(TEST_PARTITION_2_NAME, fs::read(TEST_IMAGE_PATH).unwrap());
41*d289c2baSAndroid Build Coastguard Worker     ops.add_partition("vbmeta", fs::read(TEST_VBMETA_2_PARTITIONS_PATH).unwrap());
42*d289c2baSAndroid Build Coastguard Worker     ops
43*d289c2baSAndroid Build Coastguard Worker }
44*d289c2baSAndroid Build Coastguard Worker 
45*d289c2baSAndroid Build Coastguard Worker /// Calls `slot_verify()` for both test partitions.
verify_two_images<'a>(ops: &mut TestOps<'a>) -> SlotVerifyResult<'a, SlotVerifyData<'a>>46*d289c2baSAndroid Build Coastguard Worker fn verify_two_images<'a>(ops: &mut TestOps<'a>) -> SlotVerifyResult<'a, SlotVerifyData<'a>> {
47*d289c2baSAndroid Build Coastguard Worker     slot_verify(
48*d289c2baSAndroid Build Coastguard Worker         ops,
49*d289c2baSAndroid Build Coastguard Worker         &[
50*d289c2baSAndroid Build Coastguard Worker             &CString::new(TEST_PARTITION_NAME).unwrap(),
51*d289c2baSAndroid Build Coastguard Worker             &CString::new(TEST_PARTITION_2_NAME).unwrap(),
52*d289c2baSAndroid Build Coastguard Worker         ],
53*d289c2baSAndroid Build Coastguard Worker         None,
54*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_NONE,
55*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
56*d289c2baSAndroid Build Coastguard Worker     )
57*d289c2baSAndroid Build Coastguard Worker }
58*d289c2baSAndroid Build Coastguard Worker 
59*d289c2baSAndroid Build Coastguard Worker /// Initializes a `TestOps` object such that verification will succeed on the `boot` partition with
60*d289c2baSAndroid Build Coastguard Worker /// a combined image + vbmeta.
build_test_ops_boot_partition<'a>() -> TestOps<'a>61*d289c2baSAndroid Build Coastguard Worker fn build_test_ops_boot_partition<'a>() -> TestOps<'a> {
62*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
63*d289c2baSAndroid Build Coastguard Worker     ops.partitions.clear();
64*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(
65*d289c2baSAndroid Build Coastguard Worker         "boot",
66*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_IMAGE_WITH_VBMETA_FOOTER_FOR_BOOT_PATH).unwrap(),
67*d289c2baSAndroid Build Coastguard Worker     );
68*d289c2baSAndroid Build Coastguard Worker     ops
69*d289c2baSAndroid Build Coastguard Worker }
70*d289c2baSAndroid Build Coastguard Worker 
71*d289c2baSAndroid Build Coastguard Worker /// Calls `slot_verify()` using standard args for `build_test_ops_boot_partition()` setup.
verify_boot_partition<'a>(ops: &mut TestOps<'a>) -> SlotVerifyResult<'a, SlotVerifyData<'a>>72*d289c2baSAndroid Build Coastguard Worker fn verify_boot_partition<'a>(ops: &mut TestOps<'a>) -> SlotVerifyResult<'a, SlotVerifyData<'a>> {
73*d289c2baSAndroid Build Coastguard Worker     slot_verify(
74*d289c2baSAndroid Build Coastguard Worker         ops,
75*d289c2baSAndroid Build Coastguard Worker         &[&CString::new("boot").unwrap()],
76*d289c2baSAndroid Build Coastguard Worker         None,
77*d289c2baSAndroid Build Coastguard Worker         // libavb has some special-case handling to automatically detect a combined image + vbmeta
78*d289c2baSAndroid Build Coastguard Worker         // in the `boot` partition; don't pass the `AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION` flag
79*d289c2baSAndroid Build Coastguard Worker         // so we can test this behavior.
80*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_NONE,
81*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
82*d289c2baSAndroid Build Coastguard Worker     )
83*d289c2baSAndroid Build Coastguard Worker }
84*d289c2baSAndroid Build Coastguard Worker 
85*d289c2baSAndroid Build Coastguard Worker /// Initializes a `TestOps` object such that verification will succeed on
86*d289c2baSAndroid Build Coastguard Worker /// `TEST_PARTITION_PERSISTENT_DIGEST_NAME`.
build_test_ops_persistent_digest<'a>(image: Vec<u8>) -> TestOps<'a>87*d289c2baSAndroid Build Coastguard Worker fn build_test_ops_persistent_digest<'a>(image: Vec<u8>) -> TestOps<'a> {
88*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
89*d289c2baSAndroid Build Coastguard Worker     ops.partitions.clear();
90*d289c2baSAndroid Build Coastguard Worker     // Use the vbmeta image with the persistent digest descriptor.
91*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(
92*d289c2baSAndroid Build Coastguard Worker         "vbmeta",
93*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_VBMETA_PERSISTENT_DIGEST_PATH).unwrap(),
94*d289c2baSAndroid Build Coastguard Worker     );
95*d289c2baSAndroid Build Coastguard Worker     // Register the image contents to be stored via persistent digest.
96*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(TEST_PARTITION_PERSISTENT_DIGEST_NAME, image);
97*d289c2baSAndroid Build Coastguard Worker     ops
98*d289c2baSAndroid Build Coastguard Worker }
99*d289c2baSAndroid Build Coastguard Worker 
100*d289c2baSAndroid Build Coastguard Worker /// Calls `slot_verify()` using standard args for `build_test_ops_persistent_digest()` setup.
verify_persistent_digest<'a>(ops: &mut TestOps<'a>) -> SlotVerifyResult<'a, SlotVerifyData<'a>>101*d289c2baSAndroid Build Coastguard Worker fn verify_persistent_digest<'a>(ops: &mut TestOps<'a>) -> SlotVerifyResult<'a, SlotVerifyData<'a>> {
102*d289c2baSAndroid Build Coastguard Worker     slot_verify(
103*d289c2baSAndroid Build Coastguard Worker         ops,
104*d289c2baSAndroid Build Coastguard Worker         &[&CString::new(TEST_PARTITION_PERSISTENT_DIGEST_NAME).unwrap()],
105*d289c2baSAndroid Build Coastguard Worker         None,
106*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_NONE,
107*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
108*d289c2baSAndroid Build Coastguard Worker     )
109*d289c2baSAndroid Build Coastguard Worker }
110*d289c2baSAndroid Build Coastguard Worker 
111*d289c2baSAndroid Build Coastguard Worker /// Modifies the partition contents by flipping a bit.
modify_partition_contents(ops: &mut TestOps, partition: &str)112*d289c2baSAndroid Build Coastguard Worker fn modify_partition_contents(ops: &mut TestOps, partition: &str) {
113*d289c2baSAndroid Build Coastguard Worker     ops.partitions
114*d289c2baSAndroid Build Coastguard Worker         .get_mut(partition)
115*d289c2baSAndroid Build Coastguard Worker         .unwrap()
116*d289c2baSAndroid Build Coastguard Worker         .contents
117*d289c2baSAndroid Build Coastguard Worker         .as_mut_vec()[0] ^= 0x01;
118*d289c2baSAndroid Build Coastguard Worker }
119*d289c2baSAndroid Build Coastguard Worker 
120*d289c2baSAndroid Build Coastguard Worker /// Returns the persistent value name for `TEST_PARTITION_PERSISTENT_DIGEST_NAME`.
persistent_digest_value_name() -> String121*d289c2baSAndroid Build Coastguard Worker fn persistent_digest_value_name() -> String {
122*d289c2baSAndroid Build Coastguard Worker     // This exact format is a libavb implementation detail but is unlikely to change. If it does
123*d289c2baSAndroid Build Coastguard Worker     // just update this format to match.
124*d289c2baSAndroid Build Coastguard Worker     format!("avb.persistent_digest.{TEST_PARTITION_PERSISTENT_DIGEST_NAME}")
125*d289c2baSAndroid Build Coastguard Worker }
126*d289c2baSAndroid Build Coastguard Worker 
127*d289c2baSAndroid Build Coastguard Worker #[test]
one_image_one_vbmeta_passes_verification_with_correct_data()128*d289c2baSAndroid Build Coastguard Worker fn one_image_one_vbmeta_passes_verification_with_correct_data() {
129*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
130*d289c2baSAndroid Build Coastguard Worker 
131*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
132*d289c2baSAndroid Build Coastguard Worker 
133*d289c2baSAndroid Build Coastguard Worker     // Make sure the resulting `SlotVerifyData` looks correct.
134*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
135*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.ab_suffix().to_bytes(), b"");
136*d289c2baSAndroid Build Coastguard Worker     // We don't care about the exact commandline, just search for a substring we know will
137*d289c2baSAndroid Build Coastguard Worker     // exist to make sure the commandline is being provided to the caller correctly.
138*d289c2baSAndroid Build Coastguard Worker     assert!(data
139*d289c2baSAndroid Build Coastguard Worker         .cmdline()
140*d289c2baSAndroid Build Coastguard Worker         .to_str()
141*d289c2baSAndroid Build Coastguard Worker         .unwrap()
142*d289c2baSAndroid Build Coastguard Worker         .contains("androidboot.vbmeta.device_state=locked"));
143*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.rollback_indexes(), &[0; 32]);
144*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
145*d289c2baSAndroid Build Coastguard Worker         data.resolved_hashtree_error_mode(),
146*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO
147*d289c2baSAndroid Build Coastguard Worker     );
148*d289c2baSAndroid Build Coastguard Worker 
149*d289c2baSAndroid Build Coastguard Worker     // Check the `VbmetaData` struct looks correct.
150*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data().len(), 1);
151*d289c2baSAndroid Build Coastguard Worker     let vbmeta_data = &data.vbmeta_data()[0];
152*d289c2baSAndroid Build Coastguard Worker     assert_eq!(vbmeta_data.partition_name().to_str().unwrap(), "vbmeta");
153*d289c2baSAndroid Build Coastguard Worker     assert_eq!(vbmeta_data.data(), fs::read(TEST_VBMETA_PATH).unwrap());
154*d289c2baSAndroid Build Coastguard Worker     assert_eq!(vbmeta_data.verify_result(), Ok(()));
155*d289c2baSAndroid Build Coastguard Worker 
156*d289c2baSAndroid Build Coastguard Worker     // Check the `PartitionData` struct looks correct.
157*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.partition_data().len(), 1);
158*d289c2baSAndroid Build Coastguard Worker     let partition_data = &data.partition_data()[0];
159*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
160*d289c2baSAndroid Build Coastguard Worker         partition_data.partition_name().to_str().unwrap(),
161*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_NAME
162*d289c2baSAndroid Build Coastguard Worker     );
163*d289c2baSAndroid Build Coastguard Worker     assert_eq!(partition_data.data(), fs::read(TEST_IMAGE_PATH).unwrap());
164*d289c2baSAndroid Build Coastguard Worker     assert!(!partition_data.preloaded());
165*d289c2baSAndroid Build Coastguard Worker     assert!(partition_data.verify_result().is_ok());
166*d289c2baSAndroid Build Coastguard Worker }
167*d289c2baSAndroid Build Coastguard Worker 
168*d289c2baSAndroid Build Coastguard Worker #[test]
preloaded_image_passes_verification()169*d289c2baSAndroid Build Coastguard Worker fn preloaded_image_passes_verification() {
170*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
171*d289c2baSAndroid Build Coastguard Worker     // Use preloaded data instead for the test partition.
172*d289c2baSAndroid Build Coastguard Worker     let preloaded = fs::read(TEST_IMAGE_PATH).unwrap();
173*d289c2baSAndroid Build Coastguard Worker     ops.add_preloaded_partition(TEST_PARTITION_NAME, &preloaded);
174*d289c2baSAndroid Build Coastguard Worker 
175*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
176*d289c2baSAndroid Build Coastguard Worker 
177*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
178*d289c2baSAndroid Build Coastguard Worker     let partition_data = &data.partition_data()[0];
179*d289c2baSAndroid Build Coastguard Worker     assert!(partition_data.preloaded());
180*d289c2baSAndroid Build Coastguard Worker }
181*d289c2baSAndroid Build Coastguard Worker 
182*d289c2baSAndroid Build Coastguard Worker // When all images are loaded from disk (rather than preloaded), libavb allocates memory itself for
183*d289c2baSAndroid Build Coastguard Worker // the data, so there is no shared ownership; the returned verification data owns the image data
184*d289c2baSAndroid Build Coastguard Worker // and can hold onto it even after the `ops` goes away.
185*d289c2baSAndroid Build Coastguard Worker #[test]
verification_data_from_disk_can_outlive_ops()186*d289c2baSAndroid Build Coastguard Worker fn verification_data_from_disk_can_outlive_ops() {
187*d289c2baSAndroid Build Coastguard Worker     let result = {
188*d289c2baSAndroid Build Coastguard Worker         let mut ops = build_test_ops_one_image_one_vbmeta();
189*d289c2baSAndroid Build Coastguard Worker         verify_one_image_one_vbmeta(&mut ops)
190*d289c2baSAndroid Build Coastguard Worker     };
191*d289c2baSAndroid Build Coastguard Worker 
192*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
193*d289c2baSAndroid Build Coastguard Worker 
194*d289c2baSAndroid Build Coastguard Worker     // The verification data owns the images and we can still access them.
195*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
196*d289c2baSAndroid Build Coastguard Worker         data.partition_data()[0].data(),
197*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_IMAGE_PATH).unwrap()
198*d289c2baSAndroid Build Coastguard Worker     );
199*d289c2baSAndroid Build Coastguard Worker }
200*d289c2baSAndroid Build Coastguard Worker 
201*d289c2baSAndroid Build Coastguard Worker // When preloaded data is passed into ops but outlives it, we can also continue to access it from
202*d289c2baSAndroid Build Coastguard Worker // the verification data after the ops goes away. The ops was only borrowing it, and now the
203*d289c2baSAndroid Build Coastguard Worker // verification data continues to borrow it.
204*d289c2baSAndroid Build Coastguard Worker #[test]
verification_data_preloaded_can_outlive_ops()205*d289c2baSAndroid Build Coastguard Worker fn verification_data_preloaded_can_outlive_ops() {
206*d289c2baSAndroid Build Coastguard Worker     let preloaded = fs::read(TEST_IMAGE_PATH).unwrap();
207*d289c2baSAndroid Build Coastguard Worker 
208*d289c2baSAndroid Build Coastguard Worker     let result = {
209*d289c2baSAndroid Build Coastguard Worker         let mut ops = build_test_ops_one_image_one_vbmeta();
210*d289c2baSAndroid Build Coastguard Worker         ops.add_preloaded_partition(TEST_PARTITION_NAME, &preloaded);
211*d289c2baSAndroid Build Coastguard Worker         verify_one_image_one_vbmeta(&mut ops)
212*d289c2baSAndroid Build Coastguard Worker     };
213*d289c2baSAndroid Build Coastguard Worker 
214*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
215*d289c2baSAndroid Build Coastguard Worker 
216*d289c2baSAndroid Build Coastguard Worker     // The verification data is borrowing the preloaded images and we can still access them.
217*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.partition_data()[0].data(), preloaded);
218*d289c2baSAndroid Build Coastguard Worker }
219*d289c2baSAndroid Build Coastguard Worker 
220*d289c2baSAndroid Build Coastguard Worker // When preloaded data is passed into ops but also goes out of scope, the verification data loses
221*d289c2baSAndroid Build Coastguard Worker // access to it, violating lifetime rules.
222*d289c2baSAndroid Build Coastguard Worker //
223*d289c2baSAndroid Build Coastguard Worker // Our lifetimes *must* be configured such that this does not compile, since `result` is borrowing
224*d289c2baSAndroid Build Coastguard Worker // `preloaded` which has gone out of scope.
225*d289c2baSAndroid Build Coastguard Worker //
226*d289c2baSAndroid Build Coastguard Worker // TODO: figure out how to make a compile-fail test; for now we just have to manually test by
227*d289c2baSAndroid Build Coastguard Worker // un-commenting the code.
228*d289c2baSAndroid Build Coastguard Worker // #[test]
229*d289c2baSAndroid Build Coastguard Worker // fn verification_data_preloaded_cannot_outlive_result() {
230*d289c2baSAndroid Build Coastguard Worker //     let result = {
231*d289c2baSAndroid Build Coastguard Worker //         let preloaded = fs::read(TEST_IMAGE_PATH).unwrap();
232*d289c2baSAndroid Build Coastguard Worker //         let mut ops = build_test_ops_one_image_one_vbmeta();
233*d289c2baSAndroid Build Coastguard Worker //         ops.add_preloaded_partition(TEST_PARTITION_NAME, &preloaded);
234*d289c2baSAndroid Build Coastguard Worker //         verify_one_image_one_vbmeta(&mut ops)
235*d289c2baSAndroid Build Coastguard Worker //     };
236*d289c2baSAndroid Build Coastguard Worker //     result.unwrap();
237*d289c2baSAndroid Build Coastguard Worker // }
238*d289c2baSAndroid Build Coastguard Worker 
239*d289c2baSAndroid Build Coastguard Worker #[test]
slotted_partition_passes_verification()240*d289c2baSAndroid Build Coastguard Worker fn slotted_partition_passes_verification() {
241*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
242*d289c2baSAndroid Build Coastguard Worker     // Move the partitions to a "_c" slot.
243*d289c2baSAndroid Build Coastguard Worker     ops.partitions.clear();
244*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(
245*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_SLOT_C_NAME,
246*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_IMAGE_PATH).unwrap(),
247*d289c2baSAndroid Build Coastguard Worker     );
248*d289c2baSAndroid Build Coastguard Worker     ops.add_partition("vbmeta_c", fs::read(TEST_VBMETA_PATH).unwrap());
249*d289c2baSAndroid Build Coastguard Worker 
250*d289c2baSAndroid Build Coastguard Worker     let result = slot_verify(
251*d289c2baSAndroid Build Coastguard Worker         &mut ops,
252*d289c2baSAndroid Build Coastguard Worker         &[&CString::new(TEST_PARTITION_NAME).unwrap()],
253*d289c2baSAndroid Build Coastguard Worker         Some(&CString::new("_c").unwrap()),
254*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_NONE,
255*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
256*d289c2baSAndroid Build Coastguard Worker     );
257*d289c2baSAndroid Build Coastguard Worker 
258*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
259*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.ab_suffix().to_bytes(), b"_c");
260*d289c2baSAndroid Build Coastguard Worker }
261*d289c2baSAndroid Build Coastguard Worker 
262*d289c2baSAndroid Build Coastguard Worker #[test]
two_images_one_vbmeta_passes_verification()263*d289c2baSAndroid Build Coastguard Worker fn two_images_one_vbmeta_passes_verification() {
264*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_two_images_one_vbmeta();
265*d289c2baSAndroid Build Coastguard Worker 
266*d289c2baSAndroid Build Coastguard Worker     let result = verify_two_images(&mut ops);
267*d289c2baSAndroid Build Coastguard Worker 
268*d289c2baSAndroid Build Coastguard Worker     // We should still only have 1 `VbmetaData` since we only used 1 vbmeta image, but it
269*d289c2baSAndroid Build Coastguard Worker     // signed 2 partitions so we should have 2 `PartitionData` objects.
270*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
271*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data().len(), 1);
272*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.partition_data().len(), 2);
273*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
274*d289c2baSAndroid Build Coastguard Worker         data.partition_data()[0].partition_name().to_str().unwrap(),
275*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_NAME
276*d289c2baSAndroid Build Coastguard Worker     );
277*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
278*d289c2baSAndroid Build Coastguard Worker         data.partition_data()[1].partition_name().to_str().unwrap(),
279*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_2_NAME
280*d289c2baSAndroid Build Coastguard Worker     );
281*d289c2baSAndroid Build Coastguard Worker }
282*d289c2baSAndroid Build Coastguard Worker 
283*d289c2baSAndroid Build Coastguard Worker #[test]
combined_image_vbmeta_partition_passes_verification()284*d289c2baSAndroid Build Coastguard Worker fn combined_image_vbmeta_partition_passes_verification() {
285*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
286*d289c2baSAndroid Build Coastguard Worker     ops.partitions.clear();
287*d289c2baSAndroid Build Coastguard Worker     // Register the single combined image + vbmeta in `TEST_PARTITION_NAME`.
288*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(
289*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_NAME,
290*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_IMAGE_WITH_VBMETA_FOOTER_PATH).unwrap(),
291*d289c2baSAndroid Build Coastguard Worker     );
292*d289c2baSAndroid Build Coastguard Worker     // For a combined image it should not attempt to use the default "vbmeta" key, instead we
293*d289c2baSAndroid Build Coastguard Worker     // register the public key specifically for this partition.
294*d289c2baSAndroid Build Coastguard Worker     ops.default_vbmeta_key = None;
295*d289c2baSAndroid Build Coastguard Worker     ops.vbmeta_keys_for_partition.insert(
296*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_NAME,
297*d289c2baSAndroid Build Coastguard Worker         (
298*d289c2baSAndroid Build Coastguard Worker             FakeVbmetaKey::Avb {
299*d289c2baSAndroid Build Coastguard Worker                 public_key: fs::read(TEST_PUBLIC_KEY_PATH).unwrap(),
300*d289c2baSAndroid Build Coastguard Worker                 public_key_metadata: None,
301*d289c2baSAndroid Build Coastguard Worker             },
302*d289c2baSAndroid Build Coastguard Worker             TEST_VBMETA_ROLLBACK_LOCATION as u32,
303*d289c2baSAndroid Build Coastguard Worker         ),
304*d289c2baSAndroid Build Coastguard Worker     );
305*d289c2baSAndroid Build Coastguard Worker 
306*d289c2baSAndroid Build Coastguard Worker     let result = slot_verify(
307*d289c2baSAndroid Build Coastguard Worker         &mut ops,
308*d289c2baSAndroid Build Coastguard Worker         &[&CString::new(TEST_PARTITION_NAME).unwrap()],
309*d289c2baSAndroid Build Coastguard Worker         None,
310*d289c2baSAndroid Build Coastguard Worker         // Tell libavb that the vbmeta image is embedded, not in its own partition.
311*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_NO_VBMETA_PARTITION,
312*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
313*d289c2baSAndroid Build Coastguard Worker     );
314*d289c2baSAndroid Build Coastguard Worker 
315*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
316*d289c2baSAndroid Build Coastguard Worker 
317*d289c2baSAndroid Build Coastguard Worker     // Vbmeta should indicate that it came from `TEST_PARTITION_NAME`.
318*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data().len(), 1);
319*d289c2baSAndroid Build Coastguard Worker     let vbmeta_data = &data.vbmeta_data()[0];
320*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
321*d289c2baSAndroid Build Coastguard Worker         vbmeta_data.partition_name().to_str().unwrap(),
322*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_NAME
323*d289c2baSAndroid Build Coastguard Worker     );
324*d289c2baSAndroid Build Coastguard Worker 
325*d289c2baSAndroid Build Coastguard Worker     // Partition should indicate that it came from `TEST_PARTITION_NAME`, but only contain the
326*d289c2baSAndroid Build Coastguard Worker     // image contents.
327*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.partition_data().len(), 1);
328*d289c2baSAndroid Build Coastguard Worker     let partition_data = &data.partition_data()[0];
329*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
330*d289c2baSAndroid Build Coastguard Worker         partition_data.partition_name().to_str().unwrap(),
331*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_NAME
332*d289c2baSAndroid Build Coastguard Worker     );
333*d289c2baSAndroid Build Coastguard Worker     assert_eq!(partition_data.data(), fs::read(TEST_IMAGE_PATH).unwrap());
334*d289c2baSAndroid Build Coastguard Worker }
335*d289c2baSAndroid Build Coastguard Worker 
336*d289c2baSAndroid Build Coastguard Worker // Validate the custom behavior if the combined image + vbmeta live in the `boot` partition.
337*d289c2baSAndroid Build Coastguard Worker #[test]
vbmeta_with_boot_partition_passes_verification()338*d289c2baSAndroid Build Coastguard Worker fn vbmeta_with_boot_partition_passes_verification() {
339*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_boot_partition();
340*d289c2baSAndroid Build Coastguard Worker 
341*d289c2baSAndroid Build Coastguard Worker     let result = verify_boot_partition(&mut ops);
342*d289c2baSAndroid Build Coastguard Worker 
343*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
344*d289c2baSAndroid Build Coastguard Worker 
345*d289c2baSAndroid Build Coastguard Worker     // Vbmeta should indicate that it came from `boot`.
346*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data().len(), 1);
347*d289c2baSAndroid Build Coastguard Worker     let vbmeta_data = &data.vbmeta_data()[0];
348*d289c2baSAndroid Build Coastguard Worker     assert_eq!(vbmeta_data.partition_name().to_str().unwrap(), "boot");
349*d289c2baSAndroid Build Coastguard Worker 
350*d289c2baSAndroid Build Coastguard Worker     // Partition should indicate that it came from `boot`, but only contain the image contents.
351*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.partition_data().len(), 1);
352*d289c2baSAndroid Build Coastguard Worker     let partition_data = &data.partition_data()[0];
353*d289c2baSAndroid Build Coastguard Worker     assert_eq!(partition_data.partition_name().to_str().unwrap(), "boot");
354*d289c2baSAndroid Build Coastguard Worker     assert_eq!(partition_data.data(), fs::read(TEST_IMAGE_PATH).unwrap());
355*d289c2baSAndroid Build Coastguard Worker }
356*d289c2baSAndroid Build Coastguard Worker 
357*d289c2baSAndroid Build Coastguard Worker #[test]
persistent_digest_verification_updates_persistent_value()358*d289c2baSAndroid Build Coastguard Worker fn persistent_digest_verification_updates_persistent_value() {
359*d289c2baSAndroid Build Coastguard Worker     // With persistent digests, the image hash isn't stored in the descriptor, but is instead
360*d289c2baSAndroid Build Coastguard Worker     // calculated on-demand and stored into a named persistent value. So our test image can contain
361*d289c2baSAndroid Build Coastguard Worker     // anything, but does have to match the size indicated by the descriptor.
362*d289c2baSAndroid Build Coastguard Worker     let image_contents = vec![0xAAu8; TEST_IMAGE_SIZE];
363*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_persistent_digest(image_contents.clone());
364*d289c2baSAndroid Build Coastguard Worker 
365*d289c2baSAndroid Build Coastguard Worker     {
366*d289c2baSAndroid Build Coastguard Worker         let result = verify_persistent_digest(&mut ops);
367*d289c2baSAndroid Build Coastguard Worker         let data = result.unwrap();
368*d289c2baSAndroid Build Coastguard Worker         assert_eq!(data.partition_data()[0].data(), image_contents);
369*d289c2baSAndroid Build Coastguard Worker     } // Drop `result` here so it releases `ops` and we can use it again.
370*d289c2baSAndroid Build Coastguard Worker 
371*d289c2baSAndroid Build Coastguard Worker     assert!(ops
372*d289c2baSAndroid Build Coastguard Worker         .persistent_values
373*d289c2baSAndroid Build Coastguard Worker         .contains_key(&persistent_digest_value_name()));
374*d289c2baSAndroid Build Coastguard Worker }
375*d289c2baSAndroid Build Coastguard Worker 
376*d289c2baSAndroid Build Coastguard Worker #[cfg(feature = "uuid")]
377*d289c2baSAndroid Build Coastguard Worker #[test]
successful_verification_substitutes_partition_guid()378*d289c2baSAndroid Build Coastguard Worker fn successful_verification_substitutes_partition_guid() {
379*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
380*d289c2baSAndroid Build Coastguard Worker     ops.partitions.get_mut("vbmeta").unwrap().uuid = uuid!("01234567-89ab-cdef-0123-456789abcdef");
381*d289c2baSAndroid Build Coastguard Worker 
382*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
383*d289c2baSAndroid Build Coastguard Worker 
384*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
385*d289c2baSAndroid Build Coastguard Worker     assert!(data
386*d289c2baSAndroid Build Coastguard Worker         .cmdline()
387*d289c2baSAndroid Build Coastguard Worker         .to_str()
388*d289c2baSAndroid Build Coastguard Worker         .unwrap()
389*d289c2baSAndroid Build Coastguard Worker         .contains("androidboot.vbmeta.device=PARTUUID=01234567-89ab-cdef-0123-456789abcdef"));
390*d289c2baSAndroid Build Coastguard Worker }
391*d289c2baSAndroid Build Coastguard Worker 
392*d289c2baSAndroid Build Coastguard Worker #[cfg(feature = "uuid")]
393*d289c2baSAndroid Build Coastguard Worker #[test]
successful_verification_substitutes_boot_partition_guid()394*d289c2baSAndroid Build Coastguard Worker fn successful_verification_substitutes_boot_partition_guid() {
395*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_boot_partition();
396*d289c2baSAndroid Build Coastguard Worker     ops.partitions.get_mut("boot").unwrap().uuid = uuid!("01234567-89ab-cdef-0123-456789abcdef");
397*d289c2baSAndroid Build Coastguard Worker 
398*d289c2baSAndroid Build Coastguard Worker     let result = verify_boot_partition(&mut ops);
399*d289c2baSAndroid Build Coastguard Worker 
400*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
401*d289c2baSAndroid Build Coastguard Worker     // In this case libavb substitutes the `boot` partition GUID in for `vbmeta`.
402*d289c2baSAndroid Build Coastguard Worker     assert!(data
403*d289c2baSAndroid Build Coastguard Worker         .cmdline()
404*d289c2baSAndroid Build Coastguard Worker         .to_str()
405*d289c2baSAndroid Build Coastguard Worker         .unwrap()
406*d289c2baSAndroid Build Coastguard Worker         .contains("androidboot.vbmeta.device=PARTUUID=01234567-89ab-cdef-0123-456789abcdef"));
407*d289c2baSAndroid Build Coastguard Worker }
408*d289c2baSAndroid Build Coastguard Worker 
409*d289c2baSAndroid Build Coastguard Worker #[test]
corrupted_image_fails_verification()410*d289c2baSAndroid Build Coastguard Worker fn corrupted_image_fails_verification() {
411*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
412*d289c2baSAndroid Build Coastguard Worker     modify_partition_contents(&mut ops, TEST_PARTITION_NAME);
413*d289c2baSAndroid Build Coastguard Worker 
414*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
415*d289c2baSAndroid Build Coastguard Worker 
416*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
417*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Verification(None)));
418*d289c2baSAndroid Build Coastguard Worker }
419*d289c2baSAndroid Build Coastguard Worker 
420*d289c2baSAndroid Build Coastguard Worker #[test]
read_partition_callback_error_fails_verification()421*d289c2baSAndroid Build Coastguard Worker fn read_partition_callback_error_fails_verification() {
422*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
423*d289c2baSAndroid Build Coastguard Worker     ops.partitions.remove(TEST_PARTITION_NAME);
424*d289c2baSAndroid Build Coastguard Worker 
425*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
426*d289c2baSAndroid Build Coastguard Worker 
427*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
428*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Io));
429*d289c2baSAndroid Build Coastguard Worker }
430*d289c2baSAndroid Build Coastguard Worker 
431*d289c2baSAndroid Build Coastguard Worker #[test]
undersized_partition_fails_verification()432*d289c2baSAndroid Build Coastguard Worker fn undersized_partition_fails_verification() {
433*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
434*d289c2baSAndroid Build Coastguard Worker     ops.partitions
435*d289c2baSAndroid Build Coastguard Worker         .get_mut(TEST_PARTITION_NAME)
436*d289c2baSAndroid Build Coastguard Worker         .unwrap()
437*d289c2baSAndroid Build Coastguard Worker         .contents
438*d289c2baSAndroid Build Coastguard Worker         .as_mut_vec()
439*d289c2baSAndroid Build Coastguard Worker         .pop();
440*d289c2baSAndroid Build Coastguard Worker 
441*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
442*d289c2baSAndroid Build Coastguard Worker 
443*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
444*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Io));
445*d289c2baSAndroid Build Coastguard Worker }
446*d289c2baSAndroid Build Coastguard Worker 
447*d289c2baSAndroid Build Coastguard Worker #[test]
corrupted_vbmeta_fails_verification()448*d289c2baSAndroid Build Coastguard Worker fn corrupted_vbmeta_fails_verification() {
449*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
450*d289c2baSAndroid Build Coastguard Worker     modify_partition_contents(&mut ops, "vbmeta");
451*d289c2baSAndroid Build Coastguard Worker 
452*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
453*d289c2baSAndroid Build Coastguard Worker 
454*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
455*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::InvalidMetadata));
456*d289c2baSAndroid Build Coastguard Worker }
457*d289c2baSAndroid Build Coastguard Worker 
458*d289c2baSAndroid Build Coastguard Worker #[test]
rollback_violation_fails_verification()459*d289c2baSAndroid Build Coastguard Worker fn rollback_violation_fails_verification() {
460*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
461*d289c2baSAndroid Build Coastguard Worker     // Device with rollback = 1 should refuse to boot image with rollback = 0.
462*d289c2baSAndroid Build Coastguard Worker     ops.rollbacks.insert(TEST_VBMETA_ROLLBACK_LOCATION, Ok(1));
463*d289c2baSAndroid Build Coastguard Worker 
464*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
465*d289c2baSAndroid Build Coastguard Worker 
466*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
467*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::RollbackIndex));
468*d289c2baSAndroid Build Coastguard Worker }
469*d289c2baSAndroid Build Coastguard Worker 
470*d289c2baSAndroid Build Coastguard Worker #[test]
rollback_callback_error_fails_verification()471*d289c2baSAndroid Build Coastguard Worker fn rollback_callback_error_fails_verification() {
472*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
473*d289c2baSAndroid Build Coastguard Worker     ops.rollbacks.clear();
474*d289c2baSAndroid Build Coastguard Worker 
475*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
476*d289c2baSAndroid Build Coastguard Worker 
477*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
478*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Io));
479*d289c2baSAndroid Build Coastguard Worker }
480*d289c2baSAndroid Build Coastguard Worker 
481*d289c2baSAndroid Build Coastguard Worker #[test]
untrusted_vbmeta_keys_fails_verification()482*d289c2baSAndroid Build Coastguard Worker fn untrusted_vbmeta_keys_fails_verification() {
483*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
484*d289c2baSAndroid Build Coastguard Worker     ops.default_vbmeta_key = Some(FakeVbmetaKey::Avb {
485*d289c2baSAndroid Build Coastguard Worker         public_key: b"not_the_key".into(),
486*d289c2baSAndroid Build Coastguard Worker         public_key_metadata: None,
487*d289c2baSAndroid Build Coastguard Worker     });
488*d289c2baSAndroid Build Coastguard Worker 
489*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
490*d289c2baSAndroid Build Coastguard Worker 
491*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
492*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::PublicKeyRejected));
493*d289c2baSAndroid Build Coastguard Worker }
494*d289c2baSAndroid Build Coastguard Worker 
495*d289c2baSAndroid Build Coastguard Worker #[test]
vbmeta_keys_callback_error_fails_verification()496*d289c2baSAndroid Build Coastguard Worker fn vbmeta_keys_callback_error_fails_verification() {
497*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
498*d289c2baSAndroid Build Coastguard Worker     ops.default_vbmeta_key = None;
499*d289c2baSAndroid Build Coastguard Worker 
500*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
501*d289c2baSAndroid Build Coastguard Worker 
502*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
503*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Io));
504*d289c2baSAndroid Build Coastguard Worker }
505*d289c2baSAndroid Build Coastguard Worker 
506*d289c2baSAndroid Build Coastguard Worker #[test]
unlock_state_callback_error_fails_verification()507*d289c2baSAndroid Build Coastguard Worker fn unlock_state_callback_error_fails_verification() {
508*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
509*d289c2baSAndroid Build Coastguard Worker     ops.unlock_state = Err(IoError::Io);
510*d289c2baSAndroid Build Coastguard Worker 
511*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
512*d289c2baSAndroid Build Coastguard Worker 
513*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
514*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Io));
515*d289c2baSAndroid Build Coastguard Worker }
516*d289c2baSAndroid Build Coastguard Worker 
517*d289c2baSAndroid Build Coastguard Worker #[test]
persistent_digest_mismatch_fails_verification()518*d289c2baSAndroid Build Coastguard Worker fn persistent_digest_mismatch_fails_verification() {
519*d289c2baSAndroid Build Coastguard Worker     let image_contents = vec![0xAAu8; TEST_IMAGE_SIZE];
520*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_persistent_digest(image_contents.clone());
521*d289c2baSAndroid Build Coastguard Worker     // Put in an incorrect persistent digest; `slot_verify()` should detect the mismatch and fail.
522*d289c2baSAndroid Build Coastguard Worker     ops.add_persistent_value(&persistent_digest_value_name(), Ok(b"incorrect_digest"));
523*d289c2baSAndroid Build Coastguard Worker     // Make a copy so we can verify the persistent values don't change on failure.
524*d289c2baSAndroid Build Coastguard Worker     let original_persistent_values = ops.persistent_values.clone();
525*d289c2baSAndroid Build Coastguard Worker 
526*d289c2baSAndroid Build Coastguard Worker     assert!(verify_persistent_digest(&mut ops).is_err());
527*d289c2baSAndroid Build Coastguard Worker 
528*d289c2baSAndroid Build Coastguard Worker     // Persistent value should be unchanged.
529*d289c2baSAndroid Build Coastguard Worker     assert_eq!(ops.persistent_values, original_persistent_values);
530*d289c2baSAndroid Build Coastguard Worker }
531*d289c2baSAndroid Build Coastguard Worker 
532*d289c2baSAndroid Build Coastguard Worker #[test]
persistent_digest_callback_error_fails_verification()533*d289c2baSAndroid Build Coastguard Worker fn persistent_digest_callback_error_fails_verification() {
534*d289c2baSAndroid Build Coastguard Worker     let image_contents = vec![0xAAu8; TEST_IMAGE_SIZE];
535*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_persistent_digest(image_contents.clone());
536*d289c2baSAndroid Build Coastguard Worker     ops.add_persistent_value(&persistent_digest_value_name(), Err(IoError::NoSuchValue));
537*d289c2baSAndroid Build Coastguard Worker 
538*d289c2baSAndroid Build Coastguard Worker     let result = verify_persistent_digest(&mut ops);
539*d289c2baSAndroid Build Coastguard Worker 
540*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
541*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(error, SlotVerifyError::Io));
542*d289c2baSAndroid Build Coastguard Worker }
543*d289c2baSAndroid Build Coastguard Worker 
544*d289c2baSAndroid Build Coastguard Worker #[test]
corrupted_image_with_allow_verification_error_flag_fails_verification_with_data()545*d289c2baSAndroid Build Coastguard Worker fn corrupted_image_with_allow_verification_error_flag_fails_verification_with_data() {
546*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
547*d289c2baSAndroid Build Coastguard Worker     modify_partition_contents(&mut ops, TEST_PARTITION_NAME);
548*d289c2baSAndroid Build Coastguard Worker 
549*d289c2baSAndroid Build Coastguard Worker     let result = slot_verify(
550*d289c2baSAndroid Build Coastguard Worker         &mut ops,
551*d289c2baSAndroid Build Coastguard Worker         &[&CString::new(TEST_PARTITION_NAME).unwrap()],
552*d289c2baSAndroid Build Coastguard Worker         None,
553*d289c2baSAndroid Build Coastguard Worker         // Pass the flag to allow verification errors.
554*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
555*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
556*d289c2baSAndroid Build Coastguard Worker     );
557*d289c2baSAndroid Build Coastguard Worker 
558*d289c2baSAndroid Build Coastguard Worker     // Verification should fail, but with the `AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR` flag
559*d289c2baSAndroid Build Coastguard Worker     // it should give us back the verification data.
560*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
561*d289c2baSAndroid Build Coastguard Worker     let data = match error {
562*d289c2baSAndroid Build Coastguard Worker         SlotVerifyError::Verification(Some(data)) => data,
563*d289c2baSAndroid Build Coastguard Worker         _ => panic!("Expected verification data to exist"),
564*d289c2baSAndroid Build Coastguard Worker     };
565*d289c2baSAndroid Build Coastguard Worker 
566*d289c2baSAndroid Build Coastguard Worker     // vbmeta verification should have succeeded since that image was still correct.
567*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data().len(), 1);
568*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data()[0].verify_result(), Ok(()));
569*d289c2baSAndroid Build Coastguard Worker     // Partition verification should have failed since we modified the image.
570*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.partition_data().len(), 1);
571*d289c2baSAndroid Build Coastguard Worker     assert!(matches!(
572*d289c2baSAndroid Build Coastguard Worker         data.partition_data()[0].verify_result(),
573*d289c2baSAndroid Build Coastguard Worker         Err(SlotVerifyError::Verification(None))
574*d289c2baSAndroid Build Coastguard Worker     ));
575*d289c2baSAndroid Build Coastguard Worker }
576*d289c2baSAndroid Build Coastguard Worker 
577*d289c2baSAndroid Build Coastguard Worker #[test]
one_image_one_vbmeta_verification_data_display()578*d289c2baSAndroid Build Coastguard Worker fn one_image_one_vbmeta_verification_data_display() {
579*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
580*d289c2baSAndroid Build Coastguard Worker 
581*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
582*d289c2baSAndroid Build Coastguard Worker 
583*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
584*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
585*d289c2baSAndroid Build Coastguard Worker         format!("{data}"),
586*d289c2baSAndroid Build Coastguard Worker         r#"slot: "", vbmeta: ["vbmeta": Ok(())], images: ["test_part": Ok(())]"#
587*d289c2baSAndroid Build Coastguard Worker     );
588*d289c2baSAndroid Build Coastguard Worker }
589*d289c2baSAndroid Build Coastguard Worker 
590*d289c2baSAndroid Build Coastguard Worker #[test]
preloaded_image_verification_data_display()591*d289c2baSAndroid Build Coastguard Worker fn preloaded_image_verification_data_display() {
592*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
593*d289c2baSAndroid Build Coastguard Worker     let preloaded = fs::read(TEST_IMAGE_PATH).unwrap();
594*d289c2baSAndroid Build Coastguard Worker     ops.add_preloaded_partition(TEST_PARTITION_NAME, &preloaded);
595*d289c2baSAndroid Build Coastguard Worker 
596*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
597*d289c2baSAndroid Build Coastguard Worker 
598*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
599*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
600*d289c2baSAndroid Build Coastguard Worker         format!("{data}"),
601*d289c2baSAndroid Build Coastguard Worker         r#"slot: "", vbmeta: ["vbmeta": Ok(())], images: ["test_part"(p): Ok(())]"#
602*d289c2baSAndroid Build Coastguard Worker     );
603*d289c2baSAndroid Build Coastguard Worker }
604*d289c2baSAndroid Build Coastguard Worker 
605*d289c2baSAndroid Build Coastguard Worker #[test]
two_images_one_vbmeta_verification_data_display()606*d289c2baSAndroid Build Coastguard Worker fn two_images_one_vbmeta_verification_data_display() {
607*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_two_images_one_vbmeta();
608*d289c2baSAndroid Build Coastguard Worker 
609*d289c2baSAndroid Build Coastguard Worker     let result = verify_two_images(&mut ops);
610*d289c2baSAndroid Build Coastguard Worker 
611*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
612*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
613*d289c2baSAndroid Build Coastguard Worker         format!("{data}"),
614*d289c2baSAndroid Build Coastguard Worker         r#"slot: "", vbmeta: ["vbmeta": Ok(())], images: ["test_part": Ok(()), "test_part_2": Ok(())]"#
615*d289c2baSAndroid Build Coastguard Worker     );
616*d289c2baSAndroid Build Coastguard Worker }
617*d289c2baSAndroid Build Coastguard Worker 
618*d289c2baSAndroid Build Coastguard Worker #[test]
corrupted_image_verification_data_display()619*d289c2baSAndroid Build Coastguard Worker fn corrupted_image_verification_data_display() {
620*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
621*d289c2baSAndroid Build Coastguard Worker     modify_partition_contents(&mut ops, TEST_PARTITION_NAME);
622*d289c2baSAndroid Build Coastguard Worker 
623*d289c2baSAndroid Build Coastguard Worker     let result = slot_verify(
624*d289c2baSAndroid Build Coastguard Worker         &mut ops,
625*d289c2baSAndroid Build Coastguard Worker         &[&CString::new(TEST_PARTITION_NAME).unwrap()],
626*d289c2baSAndroid Build Coastguard Worker         None,
627*d289c2baSAndroid Build Coastguard Worker         SlotVerifyFlags::AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR,
628*d289c2baSAndroid Build Coastguard Worker         HashtreeErrorMode::AVB_HASHTREE_ERROR_MODE_EIO,
629*d289c2baSAndroid Build Coastguard Worker     );
630*d289c2baSAndroid Build Coastguard Worker 
631*d289c2baSAndroid Build Coastguard Worker     let error = result.unwrap_err();
632*d289c2baSAndroid Build Coastguard Worker     let data = match error {
633*d289c2baSAndroid Build Coastguard Worker         SlotVerifyError::Verification(Some(data)) => data,
634*d289c2baSAndroid Build Coastguard Worker         _ => panic!("Expected verification data to exist"),
635*d289c2baSAndroid Build Coastguard Worker     };
636*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
637*d289c2baSAndroid Build Coastguard Worker         format!("{data}"),
638*d289c2baSAndroid Build Coastguard Worker         r#"slot: "", vbmeta: ["vbmeta": Ok(())], images: ["test_part": Err(Verification(None))]"#
639*d289c2baSAndroid Build Coastguard Worker     );
640*d289c2baSAndroid Build Coastguard Worker }
641*d289c2baSAndroid Build Coastguard Worker 
642*d289c2baSAndroid Build Coastguard Worker #[test]
one_image_gives_single_descriptor()643*d289c2baSAndroid Build Coastguard Worker fn one_image_gives_single_descriptor() {
644*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
645*d289c2baSAndroid Build Coastguard Worker 
646*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
647*d289c2baSAndroid Build Coastguard Worker 
648*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
649*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data()[0].descriptors().unwrap().len(), 1);
650*d289c2baSAndroid Build Coastguard Worker }
651*d289c2baSAndroid Build Coastguard Worker 
652*d289c2baSAndroid Build Coastguard Worker #[test]
two_images_gives_two_descriptors()653*d289c2baSAndroid Build Coastguard Worker fn two_images_gives_two_descriptors() {
654*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_two_images_one_vbmeta();
655*d289c2baSAndroid Build Coastguard Worker 
656*d289c2baSAndroid Build Coastguard Worker     let result = verify_two_images(&mut ops);
657*d289c2baSAndroid Build Coastguard Worker 
658*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
659*d289c2baSAndroid Build Coastguard Worker     assert_eq!(data.vbmeta_data()[0].descriptors().unwrap().len(), 2);
660*d289c2baSAndroid Build Coastguard Worker }
661*d289c2baSAndroid Build Coastguard Worker 
662*d289c2baSAndroid Build Coastguard Worker /// Runs verification on the given contents and checks for a resulting descriptor.
663*d289c2baSAndroid Build Coastguard Worker ///
664*d289c2baSAndroid Build Coastguard Worker /// This test helper performs the following steps:
665*d289c2baSAndroid Build Coastguard Worker ///
666*d289c2baSAndroid Build Coastguard Worker /// 1. set up a `TestOps` for the default test image/vbmeta
667*d289c2baSAndroid Build Coastguard Worker /// 2. replace the vbmeta image with the contents at `vbmeta_path`
668*d289c2baSAndroid Build Coastguard Worker /// 3. run verification
669*d289c2baSAndroid Build Coastguard Worker /// 4. check that the given `descriptor` exists in the verification data
verify_and_find_descriptor(vbmeta_path: &str, expected_descriptor: &Descriptor)670*d289c2baSAndroid Build Coastguard Worker fn verify_and_find_descriptor(vbmeta_path: &str, expected_descriptor: &Descriptor) {
671*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
672*d289c2baSAndroid Build Coastguard Worker 
673*d289c2baSAndroid Build Coastguard Worker     // Replace the vbmeta image with the requested variation.
674*d289c2baSAndroid Build Coastguard Worker     ops.add_partition("vbmeta", fs::read(vbmeta_path).unwrap());
675*d289c2baSAndroid Build Coastguard Worker 
676*d289c2baSAndroid Build Coastguard Worker     let result = verify_one_image_one_vbmeta(&mut ops);
677*d289c2baSAndroid Build Coastguard Worker 
678*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
679*d289c2baSAndroid Build Coastguard Worker     let descriptors = &data.vbmeta_data()[0].descriptors().unwrap();
680*d289c2baSAndroid Build Coastguard Worker     assert!(descriptors.contains(expected_descriptor));
681*d289c2baSAndroid Build Coastguard Worker }
682*d289c2baSAndroid Build Coastguard Worker 
683*d289c2baSAndroid Build Coastguard Worker #[test]
verify_hash_descriptor()684*d289c2baSAndroid Build Coastguard Worker fn verify_hash_descriptor() {
685*d289c2baSAndroid Build Coastguard Worker     verify_and_find_descriptor(
686*d289c2baSAndroid Build Coastguard Worker         // The standard vbmeta image should contain the hash descriptor.
687*d289c2baSAndroid Build Coastguard Worker         TEST_VBMETA_PATH,
688*d289c2baSAndroid Build Coastguard Worker         &Descriptor::Hash(HashDescriptor {
689*d289c2baSAndroid Build Coastguard Worker             image_size: TEST_IMAGE_SIZE as u64,
690*d289c2baSAndroid Build Coastguard Worker             hash_algorithm: TEST_IMAGE_HASH_ALGO,
691*d289c2baSAndroid Build Coastguard Worker             flags: HashDescriptorFlags(0),
692*d289c2baSAndroid Build Coastguard Worker             partition_name: TEST_PARTITION_NAME,
693*d289c2baSAndroid Build Coastguard Worker             salt: &decode(TEST_IMAGE_SALT_HEX).unwrap(),
694*d289c2baSAndroid Build Coastguard Worker             digest: &decode(TEST_IMAGE_DIGEST_HEX).unwrap(),
695*d289c2baSAndroid Build Coastguard Worker         }),
696*d289c2baSAndroid Build Coastguard Worker     );
697*d289c2baSAndroid Build Coastguard Worker }
698*d289c2baSAndroid Build Coastguard Worker 
699*d289c2baSAndroid Build Coastguard Worker #[test]
verify_property_descriptor()700*d289c2baSAndroid Build Coastguard Worker fn verify_property_descriptor() {
701*d289c2baSAndroid Build Coastguard Worker     verify_and_find_descriptor(
702*d289c2baSAndroid Build Coastguard Worker         TEST_VBMETA_WITH_PROPERTY_PATH,
703*d289c2baSAndroid Build Coastguard Worker         &Descriptor::Property(PropertyDescriptor {
704*d289c2baSAndroid Build Coastguard Worker             key: TEST_PROPERTY_KEY,
705*d289c2baSAndroid Build Coastguard Worker             value: TEST_PROPERTY_VALUE,
706*d289c2baSAndroid Build Coastguard Worker         }),
707*d289c2baSAndroid Build Coastguard Worker     );
708*d289c2baSAndroid Build Coastguard Worker }
709*d289c2baSAndroid Build Coastguard Worker 
710*d289c2baSAndroid Build Coastguard Worker #[test]
verify_hashtree_descriptor()711*d289c2baSAndroid Build Coastguard Worker fn verify_hashtree_descriptor() {
712*d289c2baSAndroid Build Coastguard Worker     verify_and_find_descriptor(
713*d289c2baSAndroid Build Coastguard Worker         TEST_VBMETA_WITH_HASHTREE_PATH,
714*d289c2baSAndroid Build Coastguard Worker         &Descriptor::Hashtree(HashtreeDescriptor {
715*d289c2baSAndroid Build Coastguard Worker             dm_verity_version: 1,
716*d289c2baSAndroid Build Coastguard Worker             image_size: TEST_IMAGE_SIZE as u64,
717*d289c2baSAndroid Build Coastguard Worker             tree_offset: TEST_IMAGE_SIZE as u64,
718*d289c2baSAndroid Build Coastguard Worker             tree_size: 4096,
719*d289c2baSAndroid Build Coastguard Worker             data_block_size: 4096,
720*d289c2baSAndroid Build Coastguard Worker             hash_block_size: 4096,
721*d289c2baSAndroid Build Coastguard Worker             fec_num_roots: 0,
722*d289c2baSAndroid Build Coastguard Worker             fec_offset: 0,
723*d289c2baSAndroid Build Coastguard Worker             fec_size: 0,
724*d289c2baSAndroid Build Coastguard Worker             hash_algorithm: TEST_HASHTREE_ALGORITHM,
725*d289c2baSAndroid Build Coastguard Worker             flags: HashtreeDescriptorFlags(0),
726*d289c2baSAndroid Build Coastguard Worker             partition_name: TEST_PARTITION_HASH_TREE_NAME,
727*d289c2baSAndroid Build Coastguard Worker             salt: &decode(TEST_HASHTREE_SALT_HEX).unwrap(),
728*d289c2baSAndroid Build Coastguard Worker             root_digest: &decode(TEST_HASHTREE_DIGEST_HEX).unwrap(),
729*d289c2baSAndroid Build Coastguard Worker         }),
730*d289c2baSAndroid Build Coastguard Worker     );
731*d289c2baSAndroid Build Coastguard Worker }
732*d289c2baSAndroid Build Coastguard Worker 
733*d289c2baSAndroid Build Coastguard Worker #[test]
verify_kernel_commandline_descriptor()734*d289c2baSAndroid Build Coastguard Worker fn verify_kernel_commandline_descriptor() {
735*d289c2baSAndroid Build Coastguard Worker     verify_and_find_descriptor(
736*d289c2baSAndroid Build Coastguard Worker         TEST_VBMETA_WITH_COMMANDLINE_PATH,
737*d289c2baSAndroid Build Coastguard Worker         &Descriptor::KernelCommandline(KernelCommandlineDescriptor {
738*d289c2baSAndroid Build Coastguard Worker             flags: KernelCommandlineDescriptorFlags(0),
739*d289c2baSAndroid Build Coastguard Worker             commandline: TEST_KERNEL_COMMANDLINE,
740*d289c2baSAndroid Build Coastguard Worker         }),
741*d289c2baSAndroid Build Coastguard Worker     );
742*d289c2baSAndroid Build Coastguard Worker }
743*d289c2baSAndroid Build Coastguard Worker 
744*d289c2baSAndroid Build Coastguard Worker #[test]
verify_chain_partition_descriptor()745*d289c2baSAndroid Build Coastguard Worker fn verify_chain_partition_descriptor() {
746*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_two_images_one_vbmeta();
747*d289c2baSAndroid Build Coastguard Worker 
748*d289c2baSAndroid Build Coastguard Worker     // Set up the fake ops to contain:
749*d289c2baSAndroid Build Coastguard Worker     // * the default test image in TEST_PARTITION_NAME
750*d289c2baSAndroid Build Coastguard Worker     // * a signed test image with vbmeta footer in TEST_PARTITION_2_NAME
751*d289c2baSAndroid Build Coastguard Worker     // * a vbmeta image in "vbmeta" which:
752*d289c2baSAndroid Build Coastguard Worker     //   * signs the default TEST_PARTITION_NAME image
753*d289c2baSAndroid Build Coastguard Worker     //   * chains to TEST_PARTITION_2_NAME
754*d289c2baSAndroid Build Coastguard Worker     //
755*d289c2baSAndroid Build Coastguard Worker     // Since this is an unusual configuration, it's simpler to just set it up manually here
756*d289c2baSAndroid Build Coastguard Worker     // rather than try to adapt `verify_and_find_descriptor()` for this one case.
757*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(
758*d289c2baSAndroid Build Coastguard Worker         "vbmeta",
759*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_VBMETA_WITH_CHAINED_PARTITION_PATH).unwrap(),
760*d289c2baSAndroid Build Coastguard Worker     );
761*d289c2baSAndroid Build Coastguard Worker     // Replace the chained partition with the combined image + vbmeta footer.
762*d289c2baSAndroid Build Coastguard Worker     ops.add_partition(
763*d289c2baSAndroid Build Coastguard Worker         TEST_PARTITION_2_NAME,
764*d289c2baSAndroid Build Coastguard Worker         fs::read(TEST_IMAGE_WITH_VBMETA_FOOTER_FOR_TEST_PART_2).unwrap(),
765*d289c2baSAndroid Build Coastguard Worker     );
766*d289c2baSAndroid Build Coastguard Worker     // Add the rollback index for the chained partition's location.
767*d289c2baSAndroid Build Coastguard Worker     ops.rollbacks.insert(
768*d289c2baSAndroid Build Coastguard Worker         TEST_CHAINED_PARTITION_ROLLBACK_LOCATION,
769*d289c2baSAndroid Build Coastguard Worker         Ok(TEST_CHAINED_PARTITION_ROLLBACK_INDEX),
770*d289c2baSAndroid Build Coastguard Worker     );
771*d289c2baSAndroid Build Coastguard Worker 
772*d289c2baSAndroid Build Coastguard Worker     let result = verify_two_images(&mut ops);
773*d289c2baSAndroid Build Coastguard Worker 
774*d289c2baSAndroid Build Coastguard Worker     let data = result.unwrap();
775*d289c2baSAndroid Build Coastguard Worker     // We should have two vbmeta images - one from the "vbmeta" partition, the other embedded
776*d289c2baSAndroid Build Coastguard Worker     // in the footer of TEST_PARTITION_2_NAME.
777*d289c2baSAndroid Build Coastguard Worker     let vbmetas = data.vbmeta_data();
778*d289c2baSAndroid Build Coastguard Worker     assert_eq!(vbmetas.len(), 2);
779*d289c2baSAndroid Build Coastguard Worker     // Search for the main vbmeta so we don't assume any particular order.
780*d289c2baSAndroid Build Coastguard Worker     let main_vbmeta = vbmetas
781*d289c2baSAndroid Build Coastguard Worker         .iter()
782*d289c2baSAndroid Build Coastguard Worker         .find(|v| v.partition_name().to_str().unwrap() == "vbmeta")
783*d289c2baSAndroid Build Coastguard Worker         .unwrap();
784*d289c2baSAndroid Build Coastguard Worker 
785*d289c2baSAndroid Build Coastguard Worker     // The main vbmeta should contain the chain descriptor.
786*d289c2baSAndroid Build Coastguard Worker     let expected = ChainPartitionDescriptor {
787*d289c2baSAndroid Build Coastguard Worker         rollback_index_location: TEST_CHAINED_PARTITION_ROLLBACK_LOCATION as u32,
788*d289c2baSAndroid Build Coastguard Worker         partition_name: TEST_PARTITION_2_NAME,
789*d289c2baSAndroid Build Coastguard Worker         public_key: &fs::read(TEST_PUBLIC_KEY_RSA8192_PATH).unwrap(),
790*d289c2baSAndroid Build Coastguard Worker         flags: ChainPartitionDescriptorFlags(0),
791*d289c2baSAndroid Build Coastguard Worker     };
792*d289c2baSAndroid Build Coastguard Worker     assert!(main_vbmeta
793*d289c2baSAndroid Build Coastguard Worker         .descriptors()
794*d289c2baSAndroid Build Coastguard Worker         .unwrap()
795*d289c2baSAndroid Build Coastguard Worker         .contains(&Descriptor::ChainPartition(expected)));
796*d289c2baSAndroid Build Coastguard Worker }
797*d289c2baSAndroid Build Coastguard Worker 
798*d289c2baSAndroid Build Coastguard Worker #[test]
verify_get_property_value()799*d289c2baSAndroid Build Coastguard Worker fn verify_get_property_value() {
800*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
801*d289c2baSAndroid Build Coastguard Worker     ops.add_partition("vbmeta", fs::read(TEST_VBMETA_WITH_PROPERTY_PATH).unwrap());
802*d289c2baSAndroid Build Coastguard Worker 
803*d289c2baSAndroid Build Coastguard Worker     let data = verify_one_image_one_vbmeta(&mut ops).unwrap();
804*d289c2baSAndroid Build Coastguard Worker 
805*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
806*d289c2baSAndroid Build Coastguard Worker         data.vbmeta_data()[0].get_property_value(TEST_PROPERTY_KEY),
807*d289c2baSAndroid Build Coastguard Worker         Some(TEST_PROPERTY_VALUE),
808*d289c2baSAndroid Build Coastguard Worker         "Expected valid buffer for the given key"
809*d289c2baSAndroid Build Coastguard Worker     );
810*d289c2baSAndroid Build Coastguard Worker }
811*d289c2baSAndroid Build Coastguard Worker 
812*d289c2baSAndroid Build Coastguard Worker #[test]
verify_get_property_value_not_found()813*d289c2baSAndroid Build Coastguard Worker fn verify_get_property_value_not_found() {
814*d289c2baSAndroid Build Coastguard Worker     let mut ops = build_test_ops_one_image_one_vbmeta();
815*d289c2baSAndroid Build Coastguard Worker     ops.add_partition("vbmeta", fs::read(TEST_VBMETA_WITH_PROPERTY_PATH).unwrap());
816*d289c2baSAndroid Build Coastguard Worker 
817*d289c2baSAndroid Build Coastguard Worker     let data = verify_one_image_one_vbmeta(&mut ops).unwrap();
818*d289c2baSAndroid Build Coastguard Worker 
819*d289c2baSAndroid Build Coastguard Worker     assert_eq!(
820*d289c2baSAndroid Build Coastguard Worker         data.vbmeta_data()[0].get_property_value("test_prop_doesnt_exist"),
821*d289c2baSAndroid Build Coastguard Worker         None,
822*d289c2baSAndroid Build Coastguard Worker         "Expected property not found for not existing key"
823*d289c2baSAndroid Build Coastguard Worker     );
824*d289c2baSAndroid Build Coastguard Worker }
825