xref: /aosp_15_r20/external/avb/rust/src/verify.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 //! Verification APIs.
16*d289c2baSAndroid Build Coastguard Worker //!
17*d289c2baSAndroid Build Coastguard Worker //! This module is responsible for all the conversions required to pass information between
18*d289c2baSAndroid Build Coastguard Worker //! libavb and Rust for verifying images.
19*d289c2baSAndroid Build Coastguard Worker 
20*d289c2baSAndroid Build Coastguard Worker extern crate alloc;
21*d289c2baSAndroid Build Coastguard Worker 
22*d289c2baSAndroid Build Coastguard Worker use crate::{
23*d289c2baSAndroid Build Coastguard Worker     descriptor::{get_descriptors, Descriptor, DescriptorResult},
24*d289c2baSAndroid Build Coastguard Worker     error::{
25*d289c2baSAndroid Build Coastguard Worker         slot_verify_enum_to_result, vbmeta_verify_enum_to_result, SlotVerifyError,
26*d289c2baSAndroid Build Coastguard Worker         SlotVerifyNoDataResult, SlotVerifyResult, VbmetaVerifyResult,
27*d289c2baSAndroid Build Coastguard Worker     },
28*d289c2baSAndroid Build Coastguard Worker     ops, Ops,
29*d289c2baSAndroid Build Coastguard Worker };
30*d289c2baSAndroid Build Coastguard Worker use alloc::vec::Vec;
31*d289c2baSAndroid Build Coastguard Worker use avb_bindgen::{
32*d289c2baSAndroid Build Coastguard Worker     avb_slot_verify, avb_slot_verify_data_free, AvbPartitionData, AvbSlotVerifyData, AvbVBMetaData,
33*d289c2baSAndroid Build Coastguard Worker };
34*d289c2baSAndroid Build Coastguard Worker use core::{
35*d289c2baSAndroid Build Coastguard Worker     ffi::{c_char, CStr},
36*d289c2baSAndroid Build Coastguard Worker     fmt,
37*d289c2baSAndroid Build Coastguard Worker     marker::PhantomData,
38*d289c2baSAndroid Build Coastguard Worker     pin::pin,
39*d289c2baSAndroid Build Coastguard Worker     ptr::{self, null, null_mut, NonNull},
40*d289c2baSAndroid Build Coastguard Worker     slice,
41*d289c2baSAndroid Build Coastguard Worker };
42*d289c2baSAndroid Build Coastguard Worker 
43*d289c2baSAndroid Build Coastguard Worker /// `AvbHashtreeErrorMode`; see libavb docs for descriptions of each mode.
44*d289c2baSAndroid Build Coastguard Worker pub use avb_bindgen::AvbHashtreeErrorMode as HashtreeErrorMode;
45*d289c2baSAndroid Build Coastguard Worker /// `AvbSlotVerifyFlags`; see libavb docs for descriptions of each flag.
46*d289c2baSAndroid Build Coastguard Worker pub use avb_bindgen::AvbSlotVerifyFlags as SlotVerifyFlags;
47*d289c2baSAndroid Build Coastguard Worker 
48*d289c2baSAndroid Build Coastguard Worker /// Returns `Err(SlotVerifyError::Internal)` if the given pointer is `NULL`.
check_nonnull<T>(ptr: *const T) -> SlotVerifyNoDataResult<()>49*d289c2baSAndroid Build Coastguard Worker fn check_nonnull<T>(ptr: *const T) -> SlotVerifyNoDataResult<()> {
50*d289c2baSAndroid Build Coastguard Worker     match ptr.is_null() {
51*d289c2baSAndroid Build Coastguard Worker         true => Err(SlotVerifyError::Internal),
52*d289c2baSAndroid Build Coastguard Worker         false => Ok(()),
53*d289c2baSAndroid Build Coastguard Worker     }
54*d289c2baSAndroid Build Coastguard Worker }
55*d289c2baSAndroid Build Coastguard Worker 
56*d289c2baSAndroid Build Coastguard Worker /// Wraps a raw C `AvbVBMetaData` struct.
57*d289c2baSAndroid Build Coastguard Worker ///
58*d289c2baSAndroid Build Coastguard Worker /// This provides a Rust safe view over the raw data; no copies are made.
59*d289c2baSAndroid Build Coastguard Worker //
60*d289c2baSAndroid Build Coastguard Worker // `repr(transparent)` guarantees that size and alignment match the underlying type exactly, so that
61*d289c2baSAndroid Build Coastguard Worker // we can cast the array of `AvbVBMetaData` structs directly into a slice of `VbmetaData` wrappers
62*d289c2baSAndroid Build Coastguard Worker // without allocating any additional memory.
63*d289c2baSAndroid Build Coastguard Worker #[repr(transparent)]
64*d289c2baSAndroid Build Coastguard Worker pub struct VbmetaData(AvbVBMetaData);
65*d289c2baSAndroid Build Coastguard Worker 
66*d289c2baSAndroid Build Coastguard Worker impl VbmetaData {
67*d289c2baSAndroid Build Coastguard Worker     /// Validates the internal data so the accessors can be fail-free. This should be called on all
68*d289c2baSAndroid Build Coastguard Worker     /// `VbmetaData` objects before they are handed to the user.
69*d289c2baSAndroid Build Coastguard Worker     ///
70*d289c2baSAndroid Build Coastguard Worker     /// Normally this would be done in a `new()` function but we never instantiate `VbmetaData`
71*d289c2baSAndroid Build Coastguard Worker     /// objects ourselves, we just cast them from the C structs provided by libavb.
72*d289c2baSAndroid Build Coastguard Worker     ///
73*d289c2baSAndroid Build Coastguard Worker     /// Returns `Err(SlotVerifyError::Internal)` on failure.
validate(&self) -> SlotVerifyNoDataResult<()>74*d289c2baSAndroid Build Coastguard Worker     fn validate(&self) -> SlotVerifyNoDataResult<()> {
75*d289c2baSAndroid Build Coastguard Worker         check_nonnull(self.0.partition_name)?;
76*d289c2baSAndroid Build Coastguard Worker         check_nonnull(self.0.vbmeta_data)?;
77*d289c2baSAndroid Build Coastguard Worker         Ok(())
78*d289c2baSAndroid Build Coastguard Worker     }
79*d289c2baSAndroid Build Coastguard Worker 
80*d289c2baSAndroid Build Coastguard Worker     /// Returns the name of the partition this vbmeta image was loaded from.
partition_name(&self) -> &CStr81*d289c2baSAndroid Build Coastguard Worker     pub fn partition_name(&self) -> &CStr {
82*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
83*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated and nul-terminated string.
84*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
85*d289c2baSAndroid Build Coastguard Worker         unsafe { CStr::from_ptr(self.0.partition_name) }
86*d289c2baSAndroid Build Coastguard Worker     }
87*d289c2baSAndroid Build Coastguard Worker 
88*d289c2baSAndroid Build Coastguard Worker     /// Returns the vbmeta image contents.
data(&self) -> &[u8]89*d289c2baSAndroid Build Coastguard Worker     pub fn data(&self) -> &[u8] {
90*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
91*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated byte array.
92*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
93*d289c2baSAndroid Build Coastguard Worker         unsafe { slice::from_raw_parts(self.0.vbmeta_data, self.0.vbmeta_size) }
94*d289c2baSAndroid Build Coastguard Worker     }
95*d289c2baSAndroid Build Coastguard Worker 
96*d289c2baSAndroid Build Coastguard Worker     /// Returns the vbmeta verification result.
verify_result(&self) -> VbmetaVerifyResult<()>97*d289c2baSAndroid Build Coastguard Worker     pub fn verify_result(&self) -> VbmetaVerifyResult<()> {
98*d289c2baSAndroid Build Coastguard Worker         vbmeta_verify_enum_to_result(self.0.verify_result)
99*d289c2baSAndroid Build Coastguard Worker     }
100*d289c2baSAndroid Build Coastguard Worker 
101*d289c2baSAndroid Build Coastguard Worker     /// Extracts the descriptors from the vbmeta image.
102*d289c2baSAndroid Build Coastguard Worker     ///
103*d289c2baSAndroid Build Coastguard Worker     /// Note that this function allocates memory to hold the `Descriptor` objects.
104*d289c2baSAndroid Build Coastguard Worker     ///
105*d289c2baSAndroid Build Coastguard Worker     /// # Returns
106*d289c2baSAndroid Build Coastguard Worker     /// A vector of descriptors, or `DescriptorError` on failure.
descriptors(&self) -> DescriptorResult<Vec<Descriptor>>107*d289c2baSAndroid Build Coastguard Worker     pub fn descriptors(&self) -> DescriptorResult<Vec<Descriptor>> {
108*d289c2baSAndroid Build Coastguard Worker         // SAFETY: the only way to get a `VbmetaData` object is via the return value of
109*d289c2baSAndroid Build Coastguard Worker         // `slot_verify()`, so we know we have been properly validated.
110*d289c2baSAndroid Build Coastguard Worker         unsafe { get_descriptors(self) }
111*d289c2baSAndroid Build Coastguard Worker     }
112*d289c2baSAndroid Build Coastguard Worker 
113*d289c2baSAndroid Build Coastguard Worker     /// Gets a property from the vbmeta image for the given key
114*d289c2baSAndroid Build Coastguard Worker     ///
115*d289c2baSAndroid Build Coastguard Worker     /// This function re-implements the libavb avb_property_lookup logic.
116*d289c2baSAndroid Build Coastguard Worker     ///
117*d289c2baSAndroid Build Coastguard Worker     /// # Returns
118*d289c2baSAndroid Build Coastguard Worker     /// Byte array with property data or None in case property not found or failure.
get_property_value(&self, key: &str) -> Option<&[u8]>119*d289c2baSAndroid Build Coastguard Worker     pub fn get_property_value(&self, key: &str) -> Option<&[u8]> {
120*d289c2baSAndroid Build Coastguard Worker         self.descriptors().ok()?.iter().find_map(|d| match d {
121*d289c2baSAndroid Build Coastguard Worker             Descriptor::Property(p) if p.key == key => Some(p.value),
122*d289c2baSAndroid Build Coastguard Worker             _ => None,
123*d289c2baSAndroid Build Coastguard Worker         })
124*d289c2baSAndroid Build Coastguard Worker     }
125*d289c2baSAndroid Build Coastguard Worker }
126*d289c2baSAndroid Build Coastguard Worker 
127*d289c2baSAndroid Build Coastguard Worker impl fmt::Display for VbmetaData {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result128*d289c2baSAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
129*d289c2baSAndroid Build Coastguard Worker         write!(f, "{:?}: {:?}", self.partition_name(), self.verify_result())
130*d289c2baSAndroid Build Coastguard Worker     }
131*d289c2baSAndroid Build Coastguard Worker }
132*d289c2baSAndroid Build Coastguard Worker 
133*d289c2baSAndroid Build Coastguard Worker /// Forwards to `Display` formatting; the default `Debug` formatting implementation isn't very
134*d289c2baSAndroid Build Coastguard Worker /// useful as it's mostly raw pointer addresses.
135*d289c2baSAndroid Build Coastguard Worker impl fmt::Debug for VbmetaData {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result136*d289c2baSAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137*d289c2baSAndroid Build Coastguard Worker         fmt::Display::fmt(self, f)
138*d289c2baSAndroid Build Coastguard Worker     }
139*d289c2baSAndroid Build Coastguard Worker }
140*d289c2baSAndroid Build Coastguard Worker 
141*d289c2baSAndroid Build Coastguard Worker /// Wraps a raw C `AvbPartitionData` struct.
142*d289c2baSAndroid Build Coastguard Worker ///
143*d289c2baSAndroid Build Coastguard Worker /// This provides a Rust safe view over the raw data; no copies are made.
144*d289c2baSAndroid Build Coastguard Worker #[repr(transparent)]
145*d289c2baSAndroid Build Coastguard Worker pub struct PartitionData(AvbPartitionData);
146*d289c2baSAndroid Build Coastguard Worker 
147*d289c2baSAndroid Build Coastguard Worker impl PartitionData {
148*d289c2baSAndroid Build Coastguard Worker     /// Validates the internal data so the accessors can be fail-free. This should be called on all
149*d289c2baSAndroid Build Coastguard Worker     /// `PartitionData` objects before they are handed to the user.
150*d289c2baSAndroid Build Coastguard Worker     ///
151*d289c2baSAndroid Build Coastguard Worker     /// Normally this would be done in a `new()` function but we never instantiate `PartitionData`
152*d289c2baSAndroid Build Coastguard Worker     /// objects ourselves, we just cast them from the C structs provided by libavb.
153*d289c2baSAndroid Build Coastguard Worker     ///
154*d289c2baSAndroid Build Coastguard Worker     /// Returns `Err(SlotVerifyError::Internal)` on failure.
validate(&self) -> SlotVerifyNoDataResult<()>155*d289c2baSAndroid Build Coastguard Worker     fn validate(&self) -> SlotVerifyNoDataResult<()> {
156*d289c2baSAndroid Build Coastguard Worker         check_nonnull(self.0.partition_name)?;
157*d289c2baSAndroid Build Coastguard Worker         check_nonnull(self.0.data)?;
158*d289c2baSAndroid Build Coastguard Worker         Ok(())
159*d289c2baSAndroid Build Coastguard Worker     }
160*d289c2baSAndroid Build Coastguard Worker 
161*d289c2baSAndroid Build Coastguard Worker     /// Returns the name of the partition this image was loaded from.
partition_name(&self) -> &CStr162*d289c2baSAndroid Build Coastguard Worker     pub fn partition_name(&self) -> &CStr {
163*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
164*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated and nul-terminated string.
165*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
166*d289c2baSAndroid Build Coastguard Worker         unsafe { CStr::from_ptr(self.0.partition_name) }
167*d289c2baSAndroid Build Coastguard Worker     }
168*d289c2baSAndroid Build Coastguard Worker 
169*d289c2baSAndroid Build Coastguard Worker     /// Returns the image contents.
data(&self) -> &[u8]170*d289c2baSAndroid Build Coastguard Worker     pub fn data(&self) -> &[u8] {
171*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
172*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated byte array.
173*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
174*d289c2baSAndroid Build Coastguard Worker         unsafe { slice::from_raw_parts(self.0.data, self.0.data_size) }
175*d289c2baSAndroid Build Coastguard Worker     }
176*d289c2baSAndroid Build Coastguard Worker 
177*d289c2baSAndroid Build Coastguard Worker     /// Returns whether this partition was preloaded via `get_preloaded_partition()`.
preloaded(&self) -> bool178*d289c2baSAndroid Build Coastguard Worker     pub fn preloaded(&self) -> bool {
179*d289c2baSAndroid Build Coastguard Worker         self.0.preloaded
180*d289c2baSAndroid Build Coastguard Worker     }
181*d289c2baSAndroid Build Coastguard Worker 
182*d289c2baSAndroid Build Coastguard Worker     /// Returns the verification result for this partition.
183*d289c2baSAndroid Build Coastguard Worker     ///
184*d289c2baSAndroid Build Coastguard Worker     /// Only top-level `Verification` errors will contain valid `SlotVerifyData` objects, if this
185*d289c2baSAndroid Build Coastguard Worker     /// individual partition returns a `Verification` error the error will always contain `None`.
verify_result(&self) -> SlotVerifyNoDataResult<()>186*d289c2baSAndroid Build Coastguard Worker     pub fn verify_result(&self) -> SlotVerifyNoDataResult<()> {
187*d289c2baSAndroid Build Coastguard Worker         slot_verify_enum_to_result(self.0.verify_result)
188*d289c2baSAndroid Build Coastguard Worker     }
189*d289c2baSAndroid Build Coastguard Worker }
190*d289c2baSAndroid Build Coastguard Worker 
191*d289c2baSAndroid Build Coastguard Worker /// A "(p)" after the partition name indicates a preloaded partition.
192*d289c2baSAndroid Build Coastguard Worker impl fmt::Display for PartitionData {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result193*d289c2baSAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194*d289c2baSAndroid Build Coastguard Worker         write!(
195*d289c2baSAndroid Build Coastguard Worker             f,
196*d289c2baSAndroid Build Coastguard Worker             "{:?}{}: {:?}",
197*d289c2baSAndroid Build Coastguard Worker             self.partition_name(),
198*d289c2baSAndroid Build Coastguard Worker             match self.preloaded() {
199*d289c2baSAndroid Build Coastguard Worker                 true => "(p)",
200*d289c2baSAndroid Build Coastguard Worker                 false => "",
201*d289c2baSAndroid Build Coastguard Worker             },
202*d289c2baSAndroid Build Coastguard Worker             self.verify_result()
203*d289c2baSAndroid Build Coastguard Worker         )
204*d289c2baSAndroid Build Coastguard Worker     }
205*d289c2baSAndroid Build Coastguard Worker }
206*d289c2baSAndroid Build Coastguard Worker 
207*d289c2baSAndroid Build Coastguard Worker /// Forwards to `Display` formatting; the default `Debug` formatting implementation isn't very
208*d289c2baSAndroid Build Coastguard Worker /// useful as it's mostly raw pointer addresses.
209*d289c2baSAndroid Build Coastguard Worker impl fmt::Debug for PartitionData {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result210*d289c2baSAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
211*d289c2baSAndroid Build Coastguard Worker         fmt::Display::fmt(self, f)
212*d289c2baSAndroid Build Coastguard Worker     }
213*d289c2baSAndroid Build Coastguard Worker }
214*d289c2baSAndroid Build Coastguard Worker 
215*d289c2baSAndroid Build Coastguard Worker /// Wraps a raw C `AvbSlotVerifyData` struct.
216*d289c2baSAndroid Build Coastguard Worker ///
217*d289c2baSAndroid Build Coastguard Worker /// This provides a Rust safe view over the raw data; no copies are made.
218*d289c2baSAndroid Build Coastguard Worker ///
219*d289c2baSAndroid Build Coastguard Worker /// # Lifetimes
220*d289c2baSAndroid Build Coastguard Worker /// * `'a`: the lifetime of any preloaded partition data borrowed from an `Ops<'a>` object.
221*d289c2baSAndroid Build Coastguard Worker ///
222*d289c2baSAndroid Build Coastguard Worker /// If the `Ops` doesn't provide any preloaded data, `SlotVerifyData` doesn't borrow anything
223*d289c2baSAndroid Build Coastguard Worker /// and instead allocates and owns all data internally, freeing it accordingly on `Drop`. In this
224*d289c2baSAndroid Build Coastguard Worker /// case, `'a` can be `'static` which imposes no lifetime restrictions on `SlotVerifyData`.
225*d289c2baSAndroid Build Coastguard Worker pub struct SlotVerifyData<'a> {
226*d289c2baSAndroid Build Coastguard Worker     /// Internally owns the underlying data and deletes it on drop.
227*d289c2baSAndroid Build Coastguard Worker     raw_data: NonNull<AvbSlotVerifyData>,
228*d289c2baSAndroid Build Coastguard Worker 
229*d289c2baSAndroid Build Coastguard Worker     /// This provides the necessary lifetimes so the compiler can make sure that the preloaded
230*d289c2baSAndroid Build Coastguard Worker     /// partition data stays alive at least as long as we do, since the underlying
231*d289c2baSAndroid Build Coastguard Worker     /// `AvbSlotVerifyData` may wrap this data rather than making a copy.
232*d289c2baSAndroid Build Coastguard Worker     //
233*d289c2baSAndroid Build Coastguard Worker     // We do not want to actually borrow an `Ops` here, since in some cases `Ops` is just a
234*d289c2baSAndroid Build Coastguard Worker     // temporary object and may go out of scope before us. The only shared data is the preloaded
235*d289c2baSAndroid Build Coastguard Worker     // partition contents, not the entire `Ops` object.
236*d289c2baSAndroid Build Coastguard Worker     _preloaded: PhantomData<&'a [u8]>,
237*d289c2baSAndroid Build Coastguard Worker }
238*d289c2baSAndroid Build Coastguard Worker 
239*d289c2baSAndroid Build Coastguard Worker // Useful so that `SlotVerifyError`, which may hold a `SlotVerifyData`, can derive `PartialEq`.
240*d289c2baSAndroid Build Coastguard Worker impl<'a> PartialEq for SlotVerifyData<'a> {
eq(&self, other: &Self) -> bool241*d289c2baSAndroid Build Coastguard Worker     fn eq(&self, other: &Self) -> bool {
242*d289c2baSAndroid Build Coastguard Worker         // A `SlotVerifyData` uniquely owns the underlying data so is only equal to itself.
243*d289c2baSAndroid Build Coastguard Worker         ptr::eq(self, other)
244*d289c2baSAndroid Build Coastguard Worker     }
245*d289c2baSAndroid Build Coastguard Worker }
246*d289c2baSAndroid Build Coastguard Worker 
247*d289c2baSAndroid Build Coastguard Worker impl<'a> Eq for SlotVerifyData<'a> {}
248*d289c2baSAndroid Build Coastguard Worker 
249*d289c2baSAndroid Build Coastguard Worker impl<'a> SlotVerifyData<'a> {
250*d289c2baSAndroid Build Coastguard Worker     /// Creates a `SlotVerifyData` wrapping the given raw `AvbSlotVerifyData`.
251*d289c2baSAndroid Build Coastguard Worker     ///
252*d289c2baSAndroid Build Coastguard Worker     /// The returned `SlotVerifyData` will take ownership of the given `AvbSlotVerifyData` and
253*d289c2baSAndroid Build Coastguard Worker     /// properly release the allocated memory when it drops.
254*d289c2baSAndroid Build Coastguard Worker     ///
255*d289c2baSAndroid Build Coastguard Worker     /// If `ops` provided any preloaded data, the returned `SlotVerifyData` also borrows the data to
256*d289c2baSAndroid Build Coastguard Worker     /// account for the underlying `AvbSlotVerifyData` holding a pointer to it. If there was no
257*d289c2baSAndroid Build Coastguard Worker     /// preloaded data, then `SlotVerifyData` owns all its data.
258*d289c2baSAndroid Build Coastguard Worker     ///
259*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
260*d289c2baSAndroid Build Coastguard Worker     /// * `data`: a `AvbSlotVerifyData` object created by libavb using `ops`.
261*d289c2baSAndroid Build Coastguard Worker     /// * `ops`: the user-provided `Ops` object that was used for verification; only used here to
262*d289c2baSAndroid Build Coastguard Worker     ///          grab the preloaded data lifetime.
263*d289c2baSAndroid Build Coastguard Worker     ///
264*d289c2baSAndroid Build Coastguard Worker     /// # Returns
265*d289c2baSAndroid Build Coastguard Worker     /// The new object, or `Err(SlotVerifyError::Internal)` if the data looks invalid.
266*d289c2baSAndroid Build Coastguard Worker     ///
267*d289c2baSAndroid Build Coastguard Worker     /// # Safety
268*d289c2baSAndroid Build Coastguard Worker     /// * `data` must be a valid `AvbSlotVerifyData` object created by libavb using `ops`.
269*d289c2baSAndroid Build Coastguard Worker     /// * after calling this function, do not access `data` except through the returned object
new( data: *mut AvbSlotVerifyData, _ops: &dyn Ops<'a>, ) -> SlotVerifyNoDataResult<Self>270*d289c2baSAndroid Build Coastguard Worker     unsafe fn new(
271*d289c2baSAndroid Build Coastguard Worker         data: *mut AvbSlotVerifyData,
272*d289c2baSAndroid Build Coastguard Worker         _ops: &dyn Ops<'a>,
273*d289c2baSAndroid Build Coastguard Worker     ) -> SlotVerifyNoDataResult<Self> {
274*d289c2baSAndroid Build Coastguard Worker         let ret = Self {
275*d289c2baSAndroid Build Coastguard Worker             raw_data: NonNull::new(data).ok_or(SlotVerifyError::Internal)?,
276*d289c2baSAndroid Build Coastguard Worker             _preloaded: PhantomData,
277*d289c2baSAndroid Build Coastguard Worker         };
278*d289c2baSAndroid Build Coastguard Worker 
279*d289c2baSAndroid Build Coastguard Worker         // Validate all the contained data here so accessors will never fail.
280*d289c2baSAndroid Build Coastguard Worker         // SAFETY: `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
281*d289c2baSAndroid Build Coastguard Worker         let data = unsafe { ret.raw_data.as_ref() };
282*d289c2baSAndroid Build Coastguard Worker         check_nonnull(data.ab_suffix)?;
283*d289c2baSAndroid Build Coastguard Worker         check_nonnull(data.vbmeta_images)?;
284*d289c2baSAndroid Build Coastguard Worker         check_nonnull(data.loaded_partitions)?;
285*d289c2baSAndroid Build Coastguard Worker         check_nonnull(data.cmdline)?;
286*d289c2baSAndroid Build Coastguard Worker         ret.vbmeta_data().iter().try_for_each(|v| v.validate())?;
287*d289c2baSAndroid Build Coastguard Worker         ret.partition_data().iter().try_for_each(|i| i.validate())?;
288*d289c2baSAndroid Build Coastguard Worker 
289*d289c2baSAndroid Build Coastguard Worker         Ok(ret)
290*d289c2baSAndroid Build Coastguard Worker     }
291*d289c2baSAndroid Build Coastguard Worker 
292*d289c2baSAndroid Build Coastguard Worker     /// Returns the slot suffix string.
ab_suffix(&self) -> &CStr293*d289c2baSAndroid Build Coastguard Worker     pub fn ab_suffix(&self) -> &CStr {
294*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
295*d289c2baSAndroid Build Coastguard Worker         // * `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
296*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated and nul-terminated string.
297*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
298*d289c2baSAndroid Build Coastguard Worker         unsafe { CStr::from_ptr(self.raw_data.as_ref().ab_suffix) }
299*d289c2baSAndroid Build Coastguard Worker     }
300*d289c2baSAndroid Build Coastguard Worker 
301*d289c2baSAndroid Build Coastguard Worker     /// Returns the `VbmetaData` structs.
vbmeta_data(&self) -> &[VbmetaData]302*d289c2baSAndroid Build Coastguard Worker     pub fn vbmeta_data(&self) -> &[VbmetaData] {
303*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
304*d289c2baSAndroid Build Coastguard Worker         // * `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
305*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated array of structs.
306*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
307*d289c2baSAndroid Build Coastguard Worker         unsafe {
308*d289c2baSAndroid Build Coastguard Worker             slice::from_raw_parts(
309*d289c2baSAndroid Build Coastguard Worker                 // `repr(transparent)` means we can cast between these types.
310*d289c2baSAndroid Build Coastguard Worker                 self.raw_data.as_ref().vbmeta_images as *const VbmetaData,
311*d289c2baSAndroid Build Coastguard Worker                 self.raw_data.as_ref().num_vbmeta_images,
312*d289c2baSAndroid Build Coastguard Worker             )
313*d289c2baSAndroid Build Coastguard Worker         }
314*d289c2baSAndroid Build Coastguard Worker     }
315*d289c2baSAndroid Build Coastguard Worker 
316*d289c2baSAndroid Build Coastguard Worker     /// Returns the `PartitionData` structs.
partition_data(&self) -> &[PartitionData]317*d289c2baSAndroid Build Coastguard Worker     pub fn partition_data(&self) -> &[PartitionData] {
318*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
319*d289c2baSAndroid Build Coastguard Worker         // * `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
320*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated array of structs.
321*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
322*d289c2baSAndroid Build Coastguard Worker         unsafe {
323*d289c2baSAndroid Build Coastguard Worker             slice::from_raw_parts(
324*d289c2baSAndroid Build Coastguard Worker                 // `repr(transparent)` means we can cast between these types.
325*d289c2baSAndroid Build Coastguard Worker                 self.raw_data.as_ref().loaded_partitions as *const PartitionData,
326*d289c2baSAndroid Build Coastguard Worker                 self.raw_data.as_ref().num_loaded_partitions,
327*d289c2baSAndroid Build Coastguard Worker             )
328*d289c2baSAndroid Build Coastguard Worker         }
329*d289c2baSAndroid Build Coastguard Worker     }
330*d289c2baSAndroid Build Coastguard Worker 
331*d289c2baSAndroid Build Coastguard Worker     /// Returns the kernel commandline.
cmdline(&self) -> &CStr332*d289c2baSAndroid Build Coastguard Worker     pub fn cmdline(&self) -> &CStr {
333*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
334*d289c2baSAndroid Build Coastguard Worker         // * `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
335*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated and nul-terminated string.
336*d289c2baSAndroid Build Coastguard Worker         // * the returned contents remain valid and unmodified while we exist.
337*d289c2baSAndroid Build Coastguard Worker         unsafe { CStr::from_ptr(self.raw_data.as_ref().cmdline) }
338*d289c2baSAndroid Build Coastguard Worker     }
339*d289c2baSAndroid Build Coastguard Worker 
340*d289c2baSAndroid Build Coastguard Worker     /// Returns the rollback indices.
rollback_indexes(&self) -> &[u64]341*d289c2baSAndroid Build Coastguard Worker     pub fn rollback_indexes(&self) -> &[u64] {
342*d289c2baSAndroid Build Coastguard Worker         // SAFETY: `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
343*d289c2baSAndroid Build Coastguard Worker         &unsafe { self.raw_data.as_ref() }.rollback_indexes[..]
344*d289c2baSAndroid Build Coastguard Worker     }
345*d289c2baSAndroid Build Coastguard Worker 
346*d289c2baSAndroid Build Coastguard Worker     /// Returns the resolved hashtree error mode.
resolved_hashtree_error_mode(&self) -> HashtreeErrorMode347*d289c2baSAndroid Build Coastguard Worker     pub fn resolved_hashtree_error_mode(&self) -> HashtreeErrorMode {
348*d289c2baSAndroid Build Coastguard Worker         // SAFETY: `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
349*d289c2baSAndroid Build Coastguard Worker         unsafe { self.raw_data.as_ref() }.resolved_hashtree_error_mode
350*d289c2baSAndroid Build Coastguard Worker     }
351*d289c2baSAndroid Build Coastguard Worker }
352*d289c2baSAndroid Build Coastguard Worker 
353*d289c2baSAndroid Build Coastguard Worker /// Frees any internally-allocated and owned data.
354*d289c2baSAndroid Build Coastguard Worker impl<'a> Drop for SlotVerifyData<'a> {
drop(&mut self)355*d289c2baSAndroid Build Coastguard Worker     fn drop(&mut self) {
356*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
357*d289c2baSAndroid Build Coastguard Worker         // * `raw_data` points to a valid `AvbSlotVerifyData` object owned by us.
358*d289c2baSAndroid Build Coastguard Worker         // * libavb created the object and requires us to free it by calling this function.
359*d289c2baSAndroid Build Coastguard Worker         unsafe { avb_slot_verify_data_free(self.raw_data.as_ptr()) };
360*d289c2baSAndroid Build Coastguard Worker     }
361*d289c2baSAndroid Build Coastguard Worker }
362*d289c2baSAndroid Build Coastguard Worker 
363*d289c2baSAndroid Build Coastguard Worker /// Implements `Display` to make it easy to print some basic information.
364*d289c2baSAndroid Build Coastguard Worker ///
365*d289c2baSAndroid Build Coastguard Worker /// This implementation will print the slot, partition name, and verification status for all
366*d289c2baSAndroid Build Coastguard Worker /// vbmetadata and images.
367*d289c2baSAndroid Build Coastguard Worker impl<'a> fmt::Display for SlotVerifyData<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result368*d289c2baSAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369*d289c2baSAndroid Build Coastguard Worker         write!(
370*d289c2baSAndroid Build Coastguard Worker             f,
371*d289c2baSAndroid Build Coastguard Worker             "slot: {:?}, vbmeta: {:?}, images: {:?}",
372*d289c2baSAndroid Build Coastguard Worker             self.ab_suffix(),
373*d289c2baSAndroid Build Coastguard Worker             self.vbmeta_data(),
374*d289c2baSAndroid Build Coastguard Worker             self.partition_data()
375*d289c2baSAndroid Build Coastguard Worker         )
376*d289c2baSAndroid Build Coastguard Worker     }
377*d289c2baSAndroid Build Coastguard Worker }
378*d289c2baSAndroid Build Coastguard Worker 
379*d289c2baSAndroid Build Coastguard Worker /// Forwards to `Display` formatting; the default `Debug` formatting implementation isn't very
380*d289c2baSAndroid Build Coastguard Worker /// useful as it's mostly raw pointer addresses.
381*d289c2baSAndroid Build Coastguard Worker impl<'a> fmt::Debug for SlotVerifyData<'a> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result382*d289c2baSAndroid Build Coastguard Worker     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
383*d289c2baSAndroid Build Coastguard Worker         fmt::Display::fmt(self, f)
384*d289c2baSAndroid Build Coastguard Worker     }
385*d289c2baSAndroid Build Coastguard Worker }
386*d289c2baSAndroid Build Coastguard Worker 
387*d289c2baSAndroid Build Coastguard Worker /// Performs verification of the requested images.
388*d289c2baSAndroid Build Coastguard Worker ///
389*d289c2baSAndroid Build Coastguard Worker /// This wraps `avb_slot_verify()` for Rust, see the original docs for more details.
390*d289c2baSAndroid Build Coastguard Worker ///
391*d289c2baSAndroid Build Coastguard Worker /// # Arguments
392*d289c2baSAndroid Build Coastguard Worker /// * `ops`: implementation of the required verification callbacks.
393*d289c2baSAndroid Build Coastguard Worker /// * `requested_partition`: the set of partition names to verify.
394*d289c2baSAndroid Build Coastguard Worker /// * `ab_suffix`: the slot suffix to append to the partition names, or None.
395*d289c2baSAndroid Build Coastguard Worker /// * `flags`: flags to configure verification.
396*d289c2baSAndroid Build Coastguard Worker /// * `hashtree_error_mode`: desired error handling behavior.
397*d289c2baSAndroid Build Coastguard Worker ///
398*d289c2baSAndroid Build Coastguard Worker /// # Returns
399*d289c2baSAndroid Build Coastguard Worker /// `Ok` if verification completed successfully, the verification error otherwise. `SlotVerifyData`
400*d289c2baSAndroid Build Coastguard Worker /// will be returned in two cases:
401*d289c2baSAndroid Build Coastguard Worker ///
402*d289c2baSAndroid Build Coastguard Worker /// 1. always returned on verification success
403*d289c2baSAndroid Build Coastguard Worker /// 2. if `AllowVerificationError` is given in `flags`, it will also be returned on verification
404*d289c2baSAndroid Build Coastguard Worker ///    failure
405*d289c2baSAndroid Build Coastguard Worker ///
406*d289c2baSAndroid Build Coastguard Worker /// A returned `SlotVerifyData` will also borrow any preloaded data provided by `ops`. The `ops`
407*d289c2baSAndroid Build Coastguard Worker /// object itself can go out of scope, but any preloaded data it could provide must outlive the
408*d289c2baSAndroid Build Coastguard Worker /// returned object.
slot_verify<'a>( ops: &mut dyn Ops<'a>, requested_partitions: &[&CStr], ab_suffix: Option<&CStr>, flags: SlotVerifyFlags, hashtree_error_mode: HashtreeErrorMode, ) -> SlotVerifyResult<'a, SlotVerifyData<'a>>409*d289c2baSAndroid Build Coastguard Worker pub fn slot_verify<'a>(
410*d289c2baSAndroid Build Coastguard Worker     ops: &mut dyn Ops<'a>,
411*d289c2baSAndroid Build Coastguard Worker     requested_partitions: &[&CStr],
412*d289c2baSAndroid Build Coastguard Worker     ab_suffix: Option<&CStr>,
413*d289c2baSAndroid Build Coastguard Worker     flags: SlotVerifyFlags,
414*d289c2baSAndroid Build Coastguard Worker     hashtree_error_mode: HashtreeErrorMode,
415*d289c2baSAndroid Build Coastguard Worker ) -> SlotVerifyResult<'a, SlotVerifyData<'a>> {
416*d289c2baSAndroid Build Coastguard Worker     // libavb detects the size of the `requested_partitions` array by NULL termination. Expecting
417*d289c2baSAndroid Build Coastguard Worker     // the Rust caller to do this would make the API much more awkward, so we populate a
418*d289c2baSAndroid Build Coastguard Worker     // NULL-terminated array of c-string pointers ourselves. For now we use a fixed-sized array
419*d289c2baSAndroid Build Coastguard Worker     // rather than dynamically allocating, 8 should be more than enough.
420*d289c2baSAndroid Build Coastguard Worker     const MAX_PARTITION_ARRAY_SIZE: usize = 8 + 1; // Max 8 partition names + 1 for NULL terminator.
421*d289c2baSAndroid Build Coastguard Worker     if requested_partitions.len() >= MAX_PARTITION_ARRAY_SIZE {
422*d289c2baSAndroid Build Coastguard Worker         return Err(SlotVerifyError::Internal);
423*d289c2baSAndroid Build Coastguard Worker     }
424*d289c2baSAndroid Build Coastguard Worker     let mut partitions_array = [null() as *const c_char; MAX_PARTITION_ARRAY_SIZE];
425*d289c2baSAndroid Build Coastguard Worker     for (source, dest) in requested_partitions.iter().zip(partitions_array.iter_mut()) {
426*d289c2baSAndroid Build Coastguard Worker         *dest = source.as_ptr();
427*d289c2baSAndroid Build Coastguard Worker     }
428*d289c2baSAndroid Build Coastguard Worker 
429*d289c2baSAndroid Build Coastguard Worker     // To be more Rust idiomatic we allow `ab_suffix` to be `None`, but libavb requires a valid
430*d289c2baSAndroid Build Coastguard Worker     // pointer to an empty string in this case, not NULL.
431*d289c2baSAndroid Build Coastguard Worker     let ab_suffix = ab_suffix.unwrap_or(CStr::from_bytes_with_nul(b"\0").unwrap());
432*d289c2baSAndroid Build Coastguard Worker 
433*d289c2baSAndroid Build Coastguard Worker     let ops_bridge = pin!(ops::OpsBridge::new(ops));
434*d289c2baSAndroid Build Coastguard Worker     let mut out_data: *mut AvbSlotVerifyData = null_mut();
435*d289c2baSAndroid Build Coastguard Worker 
436*d289c2baSAndroid Build Coastguard Worker     // Call the libavb verification function.
437*d289c2baSAndroid Build Coastguard Worker     //
438*d289c2baSAndroid Build Coastguard Worker     // Note: do not use the `?` operator to return-early here; in some cases `out_data` will be
439*d289c2baSAndroid Build Coastguard Worker     // allocated and returned even on verification failure, and we need to take ownership of it
440*d289c2baSAndroid Build Coastguard Worker     // or else the memory will leak.
441*d289c2baSAndroid Build Coastguard Worker     //
442*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
443*d289c2baSAndroid Build Coastguard Worker     // * `ops_bridge.init_and_get_c_ops()` gives us a valid `AvbOps`.
444*d289c2baSAndroid Build Coastguard Worker     // * we've properly initialized all objects passed into libavb.
445*d289c2baSAndroid Build Coastguard Worker     // * if `out_data` is non-null on return, we take ownership via `SlotVerifyData`.
446*d289c2baSAndroid Build Coastguard Worker     let result = slot_verify_enum_to_result(unsafe {
447*d289c2baSAndroid Build Coastguard Worker         avb_slot_verify(
448*d289c2baSAndroid Build Coastguard Worker             ops_bridge.init_and_get_c_ops(),
449*d289c2baSAndroid Build Coastguard Worker             partitions_array.as_ptr(),
450*d289c2baSAndroid Build Coastguard Worker             ab_suffix.as_ptr(),
451*d289c2baSAndroid Build Coastguard Worker             flags,
452*d289c2baSAndroid Build Coastguard Worker             hashtree_error_mode,
453*d289c2baSAndroid Build Coastguard Worker             &mut out_data,
454*d289c2baSAndroid Build Coastguard Worker         )
455*d289c2baSAndroid Build Coastguard Worker     });
456*d289c2baSAndroid Build Coastguard Worker 
457*d289c2baSAndroid Build Coastguard Worker     // If `out_data` is non-null, take ownership so memory gets released on drop.
458*d289c2baSAndroid Build Coastguard Worker     let data = match out_data.is_null() {
459*d289c2baSAndroid Build Coastguard Worker         true => None,
460*d289c2baSAndroid Build Coastguard Worker         // SAFETY: `out_data` was properly allocated by libavb and ownership has passed to us.
461*d289c2baSAndroid Build Coastguard Worker         false => Some(unsafe { SlotVerifyData::new(out_data, ops)? }),
462*d289c2baSAndroid Build Coastguard Worker     };
463*d289c2baSAndroid Build Coastguard Worker 
464*d289c2baSAndroid Build Coastguard Worker     // Fold the verify data into the result.
465*d289c2baSAndroid Build Coastguard Worker     match result {
466*d289c2baSAndroid Build Coastguard Worker         // libavb will always provide verification data on success.
467*d289c2baSAndroid Build Coastguard Worker         Ok(()) => Ok(data.unwrap()),
468*d289c2baSAndroid Build Coastguard Worker         // Data may also be provided on verification failure, fold it into the error.
469*d289c2baSAndroid Build Coastguard Worker         Err(SlotVerifyError::Verification(None)) => Err(SlotVerifyError::Verification(data)),
470*d289c2baSAndroid Build Coastguard Worker         // No other error provides verification data.
471*d289c2baSAndroid Build Coastguard Worker         Err(e) => Err(e),
472*d289c2baSAndroid Build Coastguard Worker     }
473*d289c2baSAndroid Build Coastguard Worker }
474