xref: /aosp_15_r20/external/avb/rust/src/ops.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 //! User callback APIs.
16*d289c2baSAndroid Build Coastguard Worker //!
17*d289c2baSAndroid Build Coastguard Worker //! This module is responsible for bridging the user-implemented callbacks so that they can be
18*d289c2baSAndroid Build Coastguard Worker //! written in safe Rust but libavb can call them from C.
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::{error::result_to_io_enum, CertOps, IoError, IoResult, SHA256_DIGEST_SIZE};
23*d289c2baSAndroid Build Coastguard Worker use avb_bindgen::{AvbCertOps, AvbCertPermanentAttributes, AvbIOResult, AvbOps};
24*d289c2baSAndroid Build Coastguard Worker use core::{
25*d289c2baSAndroid Build Coastguard Worker     cmp::min,
26*d289c2baSAndroid Build Coastguard Worker     ffi::{c_char, c_void, CStr},
27*d289c2baSAndroid Build Coastguard Worker     marker::PhantomPinned,
28*d289c2baSAndroid Build Coastguard Worker     pin::Pin,
29*d289c2baSAndroid Build Coastguard Worker     ptr, slice,
30*d289c2baSAndroid Build Coastguard Worker };
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 /// Base implementation-provided callbacks for verification.
35*d289c2baSAndroid Build Coastguard Worker ///
36*d289c2baSAndroid Build Coastguard Worker /// See libavb `AvbOps` for more complete documentation.
37*d289c2baSAndroid Build Coastguard Worker ///
38*d289c2baSAndroid Build Coastguard Worker /// # Lifetimes
39*d289c2baSAndroid Build Coastguard Worker /// The trait lifetime `'a` indicates the lifetime of any preloaded partition data.
40*d289c2baSAndroid Build Coastguard Worker ///
41*d289c2baSAndroid Build Coastguard Worker /// Preloading partitions is an optional feature which allows libavb to use data already loaded to
42*d289c2baSAndroid Build Coastguard Worker /// RAM rather than allocating memory itself and loading data from disk. Preloading changes the
43*d289c2baSAndroid Build Coastguard Worker /// data ownership model so that the verification result borrows this existing data rather than
44*d289c2baSAndroid Build Coastguard Worker /// allocating and owning the data itself. Because of this borrow, we need the lifetime here to
45*d289c2baSAndroid Build Coastguard Worker /// ensure that the underlying data outlives the verification result object.
46*d289c2baSAndroid Build Coastguard Worker ///
47*d289c2baSAndroid Build Coastguard Worker /// If `get_preloaded_partition()` is left unimplemented, all data is loaded and owned by the
48*d289c2baSAndroid Build Coastguard Worker /// verification result rather than borrowed, and this trait lifetime can be `'static`.
49*d289c2baSAndroid Build Coastguard Worker pub trait Ops<'a> {
50*d289c2baSAndroid Build Coastguard Worker     /// Reads data from the requested partition on disk.
51*d289c2baSAndroid Build Coastguard Worker     ///
52*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
53*d289c2baSAndroid Build Coastguard Worker     /// * `partition`: partition name to read from.
54*d289c2baSAndroid Build Coastguard Worker     /// * `offset`: offset in bytes within the partition to read from; a positive value indicates an
55*d289c2baSAndroid Build Coastguard Worker     ///             offset from the partition start, a negative value indicates a backwards offset
56*d289c2baSAndroid Build Coastguard Worker     ///             from the partition end.
57*d289c2baSAndroid Build Coastguard Worker     /// * `buffer`: buffer to read data into.
58*d289c2baSAndroid Build Coastguard Worker     ///
59*d289c2baSAndroid Build Coastguard Worker     /// # Returns
60*d289c2baSAndroid Build Coastguard Worker     /// The number of bytes actually read into `buffer` or an `IoError`. Reading less than
61*d289c2baSAndroid Build Coastguard Worker     /// `buffer.len()` bytes is only allowed if the end of the partition was reached.
read_from_partition( &mut self, partition: &CStr, offset: i64, buffer: &mut [u8], ) -> IoResult<usize>62*d289c2baSAndroid Build Coastguard Worker     fn read_from_partition(
63*d289c2baSAndroid Build Coastguard Worker         &mut self,
64*d289c2baSAndroid Build Coastguard Worker         partition: &CStr,
65*d289c2baSAndroid Build Coastguard Worker         offset: i64,
66*d289c2baSAndroid Build Coastguard Worker         buffer: &mut [u8],
67*d289c2baSAndroid Build Coastguard Worker     ) -> IoResult<usize>;
68*d289c2baSAndroid Build Coastguard Worker 
69*d289c2baSAndroid Build Coastguard Worker     /// Returns a reference to preloaded partition contents.
70*d289c2baSAndroid Build Coastguard Worker     ///
71*d289c2baSAndroid Build Coastguard Worker     /// This is an optional optimization if a partition has already been loaded to provide libavb
72*d289c2baSAndroid Build Coastguard Worker     /// with a reference to the data rather than copying it as `read_from_partition()` would.
73*d289c2baSAndroid Build Coastguard Worker     ///
74*d289c2baSAndroid Build Coastguard Worker     /// May be left unimplemented if preloaded partitions are not used.
75*d289c2baSAndroid Build Coastguard Worker     ///
76*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
77*d289c2baSAndroid Build Coastguard Worker     /// * `partition`: partition name to read from.
78*d289c2baSAndroid Build Coastguard Worker     ///
79*d289c2baSAndroid Build Coastguard Worker     /// # Returns
80*d289c2baSAndroid Build Coastguard Worker     /// * A reference to the entire partition contents if the partition has been preloaded.
81*d289c2baSAndroid Build Coastguard Worker     /// * `Err<IoError::NotImplemented>` if the requested partition has not been preloaded;
82*d289c2baSAndroid Build Coastguard Worker     ///   verification will next attempt to load the partition via `read_from_partition()`.
83*d289c2baSAndroid Build Coastguard Worker     /// * Any other `Err<IoError>` if an error occurred; verification will exit immediately.
get_preloaded_partition(&mut self, _partition: &CStr) -> IoResult<&'a [u8]>84*d289c2baSAndroid Build Coastguard Worker     fn get_preloaded_partition(&mut self, _partition: &CStr) -> IoResult<&'a [u8]> {
85*d289c2baSAndroid Build Coastguard Worker         Err(IoError::NotImplemented)
86*d289c2baSAndroid Build Coastguard Worker     }
87*d289c2baSAndroid Build Coastguard Worker 
88*d289c2baSAndroid Build Coastguard Worker     /// Checks if the given public key is valid for vbmeta image signing.
89*d289c2baSAndroid Build Coastguard Worker     ///
90*d289c2baSAndroid Build Coastguard Worker     /// If using libavb_cert, this should forward to `cert_validate_vbmeta_public_key()`.
91*d289c2baSAndroid Build Coastguard Worker     ///
92*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
93*d289c2baSAndroid Build Coastguard Worker     /// * `public_key`: the public key.
94*d289c2baSAndroid Build Coastguard Worker     /// * `public_key_metadata`: public key metadata set by the `--public_key_metadata` arg in
95*d289c2baSAndroid Build Coastguard Worker     ///                          `avbtool`, or None if no metadata was provided.
96*d289c2baSAndroid Build Coastguard Worker     ///
97*d289c2baSAndroid Build Coastguard Worker     /// # Returns
98*d289c2baSAndroid Build Coastguard Worker     /// True if the given key is valid, false if it is not, `IoError` on error.
validate_vbmeta_public_key( &mut self, public_key: &[u8], public_key_metadata: Option<&[u8]>, ) -> IoResult<bool>99*d289c2baSAndroid Build Coastguard Worker     fn validate_vbmeta_public_key(
100*d289c2baSAndroid Build Coastguard Worker         &mut self,
101*d289c2baSAndroid Build Coastguard Worker         public_key: &[u8],
102*d289c2baSAndroid Build Coastguard Worker         public_key_metadata: Option<&[u8]>,
103*d289c2baSAndroid Build Coastguard Worker     ) -> IoResult<bool>;
104*d289c2baSAndroid Build Coastguard Worker 
105*d289c2baSAndroid Build Coastguard Worker     /// Reads the rollback index at the given location.
106*d289c2baSAndroid Build Coastguard Worker     ///
107*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
108*d289c2baSAndroid Build Coastguard Worker     /// * `rollback_index_location`: the rollback location.
109*d289c2baSAndroid Build Coastguard Worker     ///
110*d289c2baSAndroid Build Coastguard Worker     /// # Returns
111*d289c2baSAndroid Build Coastguard Worker     /// The rollback index at this location or `IoError` on error.
read_rollback_index(&mut self, rollback_index_location: usize) -> IoResult<u64>112*d289c2baSAndroid Build Coastguard Worker     fn read_rollback_index(&mut self, rollback_index_location: usize) -> IoResult<u64>;
113*d289c2baSAndroid Build Coastguard Worker 
114*d289c2baSAndroid Build Coastguard Worker     /// Writes the rollback index at the given location.
115*d289c2baSAndroid Build Coastguard Worker     ///
116*d289c2baSAndroid Build Coastguard Worker     /// This API is never actually used by libavb; the purpose of having it here is to group it
117*d289c2baSAndroid Build Coastguard Worker     /// with `read_rollback_index()` and indicate to the implementation that it is responsible
118*d289c2baSAndroid Build Coastguard Worker     /// for providing this functionality. However, it's up to the implementation to call this
119*d289c2baSAndroid Build Coastguard Worker     /// function at the proper time after verification, which is a device-specific decision that
120*d289c2baSAndroid Build Coastguard Worker     /// depends on things like the A/B strategy. See the libavb documentation for more information.
121*d289c2baSAndroid Build Coastguard Worker     ///
122*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
123*d289c2baSAndroid Build Coastguard Worker     /// * `rollback_index_location`: the rollback location.
124*d289c2baSAndroid Build Coastguard Worker     /// * `index`: the rollback index to write.
125*d289c2baSAndroid Build Coastguard Worker     ///
126*d289c2baSAndroid Build Coastguard Worker     /// # Returns
127*d289c2baSAndroid Build Coastguard Worker     /// Unit on success or `IoError` on error.
write_rollback_index(&mut self, rollback_index_location: usize, index: u64) -> IoResult<()>128*d289c2baSAndroid Build Coastguard Worker     fn write_rollback_index(&mut self, rollback_index_location: usize, index: u64) -> IoResult<()>;
129*d289c2baSAndroid Build Coastguard Worker 
130*d289c2baSAndroid Build Coastguard Worker     /// Returns the device unlock state.
131*d289c2baSAndroid Build Coastguard Worker     ///
132*d289c2baSAndroid Build Coastguard Worker     /// # Returns
133*d289c2baSAndroid Build Coastguard Worker     /// True if the device is unlocked, false if locked, `IoError` on error.
read_is_device_unlocked(&mut self) -> IoResult<bool>134*d289c2baSAndroid Build Coastguard Worker     fn read_is_device_unlocked(&mut self) -> IoResult<bool>;
135*d289c2baSAndroid Build Coastguard Worker 
136*d289c2baSAndroid Build Coastguard Worker     /// Returns the GUID of the requested partition.
137*d289c2baSAndroid Build Coastguard Worker     ///
138*d289c2baSAndroid Build Coastguard Worker     /// This is only necessary if the kernel commandline requires GUID substitution, and is omitted
139*d289c2baSAndroid Build Coastguard Worker     /// from the library by default to avoid unnecessary dependencies. To implement:
140*d289c2baSAndroid Build Coastguard Worker     /// 1. Enable the `uuid` feature during compilation
141*d289c2baSAndroid Build Coastguard Worker     /// 2. Provide the [`uuid` crate](https://docs.rs/uuid/latest/uuid/) dependency
142*d289c2baSAndroid Build Coastguard Worker     ///
143*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
144*d289c2baSAndroid Build Coastguard Worker     /// * `partition`: partition name.
145*d289c2baSAndroid Build Coastguard Worker     ///
146*d289c2baSAndroid Build Coastguard Worker     /// # Returns
147*d289c2baSAndroid Build Coastguard Worker     /// The partition GUID or `IoError` on error.
148*d289c2baSAndroid Build Coastguard Worker     #[cfg(feature = "uuid")]
get_unique_guid_for_partition(&mut self, partition: &CStr) -> IoResult<Uuid>149*d289c2baSAndroid Build Coastguard Worker     fn get_unique_guid_for_partition(&mut self, partition: &CStr) -> IoResult<Uuid>;
150*d289c2baSAndroid Build Coastguard Worker 
151*d289c2baSAndroid Build Coastguard Worker     /// Returns the size of the requested partition.
152*d289c2baSAndroid Build Coastguard Worker     ///
153*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
154*d289c2baSAndroid Build Coastguard Worker     /// * `partition`: partition name.
155*d289c2baSAndroid Build Coastguard Worker     ///
156*d289c2baSAndroid Build Coastguard Worker     /// # Returns
157*d289c2baSAndroid Build Coastguard Worker     /// The partition size in bytes or `IoError` on error.
get_size_of_partition(&mut self, partition: &CStr) -> IoResult<u64>158*d289c2baSAndroid Build Coastguard Worker     fn get_size_of_partition(&mut self, partition: &CStr) -> IoResult<u64>;
159*d289c2baSAndroid Build Coastguard Worker 
160*d289c2baSAndroid Build Coastguard Worker     /// Reads the requested persistent value.
161*d289c2baSAndroid Build Coastguard Worker     ///
162*d289c2baSAndroid Build Coastguard Worker     /// This is only necessary if using persistent digests or the "managed restart and EIO"
163*d289c2baSAndroid Build Coastguard Worker     /// hashtree verification mode; if verification is not using these features, this function will
164*d289c2baSAndroid Build Coastguard Worker     /// never be called.
165*d289c2baSAndroid Build Coastguard Worker     ///
166*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
167*d289c2baSAndroid Build Coastguard Worker     /// * `name`: persistent value name.
168*d289c2baSAndroid Build Coastguard Worker     /// * `value`: buffer to read persistent value into; if too small to hold the persistent value,
169*d289c2baSAndroid Build Coastguard Worker     ///            `IoError::InsufficientSpace` should be returned and this function will be called
170*d289c2baSAndroid Build Coastguard Worker     ///            again with an appropriately-sized buffer. This may be an empty slice if the
171*d289c2baSAndroid Build Coastguard Worker     ///            caller only wants to query the persistent value size.
172*d289c2baSAndroid Build Coastguard Worker     ///
173*d289c2baSAndroid Build Coastguard Worker     /// # Returns
174*d289c2baSAndroid Build Coastguard Worker     /// * The number of bytes written into `value` on success.
175*d289c2baSAndroid Build Coastguard Worker     /// * `IoError::NoSuchValue` if `name` is not a known persistent value.
176*d289c2baSAndroid Build Coastguard Worker     /// * `IoError::InsufficientSpace` with the required size if the `value` buffer is too small.
177*d289c2baSAndroid Build Coastguard Worker     /// * Any other `IoError` on failure.
read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> IoResult<usize>178*d289c2baSAndroid Build Coastguard Worker     fn read_persistent_value(&mut self, name: &CStr, value: &mut [u8]) -> IoResult<usize>;
179*d289c2baSAndroid Build Coastguard Worker 
180*d289c2baSAndroid Build Coastguard Worker     /// Writes the requested persistent value.
181*d289c2baSAndroid Build Coastguard Worker     ///
182*d289c2baSAndroid Build Coastguard Worker     /// This is only necessary if using persistent digests or the "managed restart and EIO"
183*d289c2baSAndroid Build Coastguard Worker     /// hashtree verification mode; if verification is not using these features, this function will
184*d289c2baSAndroid Build Coastguard Worker     /// never be called.
185*d289c2baSAndroid Build Coastguard Worker     ///
186*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
187*d289c2baSAndroid Build Coastguard Worker     /// * `name`: persistent value name.
188*d289c2baSAndroid Build Coastguard Worker     /// * `value`: bytes to write as the new value.
189*d289c2baSAndroid Build Coastguard Worker     ///
190*d289c2baSAndroid Build Coastguard Worker     /// # Returns
191*d289c2baSAndroid Build Coastguard Worker     /// * Unit on success.
192*d289c2baSAndroid Build Coastguard Worker     /// * `IoError::NoSuchValue` if `name` is not a supported persistent value.
193*d289c2baSAndroid Build Coastguard Worker     /// * `IoError::InvalidValueSize` if `value` is too large to save as a persistent value.
194*d289c2baSAndroid Build Coastguard Worker     /// * Any other `IoError` on failure.
write_persistent_value(&mut self, name: &CStr, value: &[u8]) -> IoResult<()>195*d289c2baSAndroid Build Coastguard Worker     fn write_persistent_value(&mut self, name: &CStr, value: &[u8]) -> IoResult<()>;
196*d289c2baSAndroid Build Coastguard Worker 
197*d289c2baSAndroid Build Coastguard Worker     /// Erases the requested persistent value.
198*d289c2baSAndroid Build Coastguard Worker     ///
199*d289c2baSAndroid Build Coastguard Worker     /// This is only necessary if using persistent digests or the "managed restart and EIO"
200*d289c2baSAndroid Build Coastguard Worker     /// hashtree verification mode; if verification is not using these features, this function will
201*d289c2baSAndroid Build Coastguard Worker     /// never be called.
202*d289c2baSAndroid Build Coastguard Worker     ///
203*d289c2baSAndroid Build Coastguard Worker     /// If the requested persistent value is already erased, this function is a no-op and should
204*d289c2baSAndroid Build Coastguard Worker     /// return `Ok(())`.
205*d289c2baSAndroid Build Coastguard Worker     ///
206*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
207*d289c2baSAndroid Build Coastguard Worker     /// * `name`: persistent value name.
208*d289c2baSAndroid Build Coastguard Worker     ///
209*d289c2baSAndroid Build Coastguard Worker     /// # Returns
210*d289c2baSAndroid Build Coastguard Worker     /// * Unit on success.
211*d289c2baSAndroid Build Coastguard Worker     /// * `IoError::NoSuchValue` if `name` is not a supported persistent value.
212*d289c2baSAndroid Build Coastguard Worker     /// * Any other `IoError` on failure.
erase_persistent_value(&mut self, name: &CStr) -> IoResult<()>213*d289c2baSAndroid Build Coastguard Worker     fn erase_persistent_value(&mut self, name: &CStr) -> IoResult<()>;
214*d289c2baSAndroid Build Coastguard Worker 
215*d289c2baSAndroid Build Coastguard Worker     /// Checks if the given public key is valid for the given partition.
216*d289c2baSAndroid Build Coastguard Worker     ///
217*d289c2baSAndroid Build Coastguard Worker     /// This is only used if the "no vbmeta" verification flag is passed, meaning the partitions
218*d289c2baSAndroid Build Coastguard Worker     /// to verify have an embedded vbmeta image rather than locating it in a separate vbmeta
219*d289c2baSAndroid Build Coastguard Worker     /// partition. If this flag is not used, the `validate_vbmeta_public_key()` callback is used
220*d289c2baSAndroid Build Coastguard Worker     /// instead, and this function will never be called.
221*d289c2baSAndroid Build Coastguard Worker     ///
222*d289c2baSAndroid Build Coastguard Worker     /// If using libavb_cert for `partition`, this should forward to
223*d289c2baSAndroid Build Coastguard Worker     /// `cert_validate_vbmeta_public_key()`.
224*d289c2baSAndroid Build Coastguard Worker     ///
225*d289c2baSAndroid Build Coastguard Worker     /// # Arguments
226*d289c2baSAndroid Build Coastguard Worker     /// * `partition`: partition name.
227*d289c2baSAndroid Build Coastguard Worker     /// * `public_key`: the public key.
228*d289c2baSAndroid Build Coastguard Worker     /// * `public_key_metadata`: public key metadata set by the `--public_key_metadata` arg in
229*d289c2baSAndroid Build Coastguard Worker     ///                          `avbtool`, or None if no metadata was provided.
230*d289c2baSAndroid Build Coastguard Worker     ///
231*d289c2baSAndroid Build Coastguard Worker     /// # Returns
232*d289c2baSAndroid Build Coastguard Worker     /// On success, returns a `PublicKeyForPartitionInfo` object indicating whether the given
233*d289c2baSAndroid Build Coastguard Worker     /// key is trusted and its rollback index location.
234*d289c2baSAndroid Build Coastguard Worker     ///
235*d289c2baSAndroid Build Coastguard Worker     /// On failure, returns an error.
validate_public_key_for_partition( &mut self, partition: &CStr, public_key: &[u8], public_key_metadata: Option<&[u8]>, ) -> IoResult<PublicKeyForPartitionInfo>236*d289c2baSAndroid Build Coastguard Worker     fn validate_public_key_for_partition(
237*d289c2baSAndroid Build Coastguard Worker         &mut self,
238*d289c2baSAndroid Build Coastguard Worker         partition: &CStr,
239*d289c2baSAndroid Build Coastguard Worker         public_key: &[u8],
240*d289c2baSAndroid Build Coastguard Worker         public_key_metadata: Option<&[u8]>,
241*d289c2baSAndroid Build Coastguard Worker     ) -> IoResult<PublicKeyForPartitionInfo>;
242*d289c2baSAndroid Build Coastguard Worker 
243*d289c2baSAndroid Build Coastguard Worker     /// Returns the libavb_cert certificate ops if supported.
244*d289c2baSAndroid Build Coastguard Worker     ///
245*d289c2baSAndroid Build Coastguard Worker     /// The libavb_cert extension provides some additional key management and authentication support
246*d289c2baSAndroid Build Coastguard Worker     /// APIs, see the cert module documentation for more info.
247*d289c2baSAndroid Build Coastguard Worker     ///
248*d289c2baSAndroid Build Coastguard Worker     /// The default implementation returns `None` to disable cert APIs.
249*d289c2baSAndroid Build Coastguard Worker     ///
250*d289c2baSAndroid Build Coastguard Worker     /// Commonly when using certs the same struct will implement both `Ops` and `CertOps`, in which
251*d289c2baSAndroid Build Coastguard Worker     /// case this can just return `Some(self)`.
252*d289c2baSAndroid Build Coastguard Worker     ///
253*d289c2baSAndroid Build Coastguard Worker     /// Note: changing this return value in the middle of a libavb operation (e.g. from another
254*d289c2baSAndroid Build Coastguard Worker     /// callback) is not recommended; it may cause runtime errors or a panic later on in the
255*d289c2baSAndroid Build Coastguard Worker     /// operation. It's fine to change this return value outside of libavb operations.
256*d289c2baSAndroid Build Coastguard Worker     ///
257*d289c2baSAndroid Build Coastguard Worker     /// # Returns
258*d289c2baSAndroid Build Coastguard Worker     /// The `CertOps` object, or `None` if not supported.
cert_ops(&mut self) -> Option<&mut dyn CertOps>259*d289c2baSAndroid Build Coastguard Worker     fn cert_ops(&mut self) -> Option<&mut dyn CertOps> {
260*d289c2baSAndroid Build Coastguard Worker         None
261*d289c2baSAndroid Build Coastguard Worker     }
262*d289c2baSAndroid Build Coastguard Worker }
263*d289c2baSAndroid Build Coastguard Worker 
264*d289c2baSAndroid Build Coastguard Worker /// Info returned from `validate_public_key_for_partition()`.
265*d289c2baSAndroid Build Coastguard Worker #[derive(Clone, Copy, Debug)]
266*d289c2baSAndroid Build Coastguard Worker pub struct PublicKeyForPartitionInfo {
267*d289c2baSAndroid Build Coastguard Worker     /// Whether the key is trusted for the given partition..
268*d289c2baSAndroid Build Coastguard Worker     pub trusted: bool,
269*d289c2baSAndroid Build Coastguard Worker     /// The rollback index to use for the given partition.
270*d289c2baSAndroid Build Coastguard Worker     pub rollback_index_location: u32,
271*d289c2baSAndroid Build Coastguard Worker }
272*d289c2baSAndroid Build Coastguard Worker 
273*d289c2baSAndroid Build Coastguard Worker /// Provides the logic to bridge between the libavb C ops and our Rust ops.
274*d289c2baSAndroid Build Coastguard Worker ///
275*d289c2baSAndroid Build Coastguard Worker /// This struct internally owns the C ops structs, and borrows ownership of the Rust `Ops`. This
276*d289c2baSAndroid Build Coastguard Worker /// allows us to translate in both directions, from Rust -> C to call into libavb and then back
277*d289c2baSAndroid Build Coastguard Worker /// from C -> Rust when servicing the callbacks.
278*d289c2baSAndroid Build Coastguard Worker ///
279*d289c2baSAndroid Build Coastguard Worker /// The general control flow look like this:
280*d289c2baSAndroid Build Coastguard Worker ///
281*d289c2baSAndroid Build Coastguard Worker /// ```ignore
282*d289c2baSAndroid Build Coastguard Worker /// user calls a Rust API with their `Ops` {
283*d289c2baSAndroid Build Coastguard Worker ///     we create `OpsBridge` wrapping `Ops` and the C structs
284*d289c2baSAndroid Build Coastguard Worker ///     we call into C libavb API {
285*d289c2baSAndroid Build Coastguard Worker ///         libavb makes C ops callback {
286*d289c2baSAndroid Build Coastguard Worker ///             we retrieve `OpsBridge` from the callback `user_data` param
287*d289c2baSAndroid Build Coastguard Worker ///             we make the corresponding Rust `Ops` callback
288*d289c2baSAndroid Build Coastguard Worker ///         }
289*d289c2baSAndroid Build Coastguard Worker ///         ... libavb makes more callbacks as needed ...
290*d289c2baSAndroid Build Coastguard Worker ///     }
291*d289c2baSAndroid Build Coastguard Worker /// }
292*d289c2baSAndroid Build Coastguard Worker /// ```
293*d289c2baSAndroid Build Coastguard Worker ///
294*d289c2baSAndroid Build Coastguard Worker /// # Lifetimes
295*d289c2baSAndroid Build Coastguard Worker /// * `'o`: lifetime of the `Ops` object
296*d289c2baSAndroid Build Coastguard Worker /// * `'p`: lifetime of any preloaded data provided by `Ops`
297*d289c2baSAndroid Build Coastguard Worker pub(crate) struct OpsBridge<'o, 'p> {
298*d289c2baSAndroid Build Coastguard Worker     /// C `AvbOps` holds a raw pointer to the `OpsBridge` so we can retrieve it during callbacks.
299*d289c2baSAndroid Build Coastguard Worker     avb_ops: AvbOps,
300*d289c2baSAndroid Build Coastguard Worker     /// When using libavb_cert, C `AvbOps`/`AvbCertOps` hold circular pointers to each other.
301*d289c2baSAndroid Build Coastguard Worker     cert_ops: AvbCertOps,
302*d289c2baSAndroid Build Coastguard Worker     /// Rust `Ops` implementation, which may also provide Rust `CertOps`.
303*d289c2baSAndroid Build Coastguard Worker     rust_ops: &'o mut dyn Ops<'p>,
304*d289c2baSAndroid Build Coastguard Worker     /// Remove the `Unpin` trait to indicate this type has address-sensitive state.
305*d289c2baSAndroid Build Coastguard Worker     _pin: PhantomPinned,
306*d289c2baSAndroid Build Coastguard Worker }
307*d289c2baSAndroid Build Coastguard Worker 
308*d289c2baSAndroid Build Coastguard Worker impl<'o, 'p> OpsBridge<'o, 'p> {
new(ops: &'o mut dyn Ops<'p>) -> Self309*d289c2baSAndroid Build Coastguard Worker     pub(crate) fn new(ops: &'o mut dyn Ops<'p>) -> Self {
310*d289c2baSAndroid Build Coastguard Worker         Self {
311*d289c2baSAndroid Build Coastguard Worker             avb_ops: AvbOps {
312*d289c2baSAndroid Build Coastguard Worker                 user_data: ptr::null_mut(), // Set at the time of use.
313*d289c2baSAndroid Build Coastguard Worker                 ab_ops: ptr::null_mut(),    // Deprecated, no need to support.
314*d289c2baSAndroid Build Coastguard Worker                 cert_ops: ptr::null_mut(),  // Set at the time of use.
315*d289c2baSAndroid Build Coastguard Worker                 read_from_partition: Some(read_from_partition),
316*d289c2baSAndroid Build Coastguard Worker                 get_preloaded_partition: Some(get_preloaded_partition),
317*d289c2baSAndroid Build Coastguard Worker                 write_to_partition: None, // Not needed, only used for deprecated A/B.
318*d289c2baSAndroid Build Coastguard Worker                 validate_vbmeta_public_key: Some(validate_vbmeta_public_key),
319*d289c2baSAndroid Build Coastguard Worker                 read_rollback_index: Some(read_rollback_index),
320*d289c2baSAndroid Build Coastguard Worker                 write_rollback_index: Some(write_rollback_index),
321*d289c2baSAndroid Build Coastguard Worker                 read_is_device_unlocked: Some(read_is_device_unlocked),
322*d289c2baSAndroid Build Coastguard Worker                 get_unique_guid_for_partition: Some(get_unique_guid_for_partition),
323*d289c2baSAndroid Build Coastguard Worker                 get_size_of_partition: Some(get_size_of_partition),
324*d289c2baSAndroid Build Coastguard Worker                 read_persistent_value: Some(read_persistent_value),
325*d289c2baSAndroid Build Coastguard Worker                 write_persistent_value: Some(write_persistent_value),
326*d289c2baSAndroid Build Coastguard Worker                 validate_public_key_for_partition: Some(validate_public_key_for_partition),
327*d289c2baSAndroid Build Coastguard Worker             },
328*d289c2baSAndroid Build Coastguard Worker             cert_ops: AvbCertOps {
329*d289c2baSAndroid Build Coastguard Worker                 ops: ptr::null_mut(), // Set at the time of use.
330*d289c2baSAndroid Build Coastguard Worker                 read_permanent_attributes: Some(read_permanent_attributes),
331*d289c2baSAndroid Build Coastguard Worker                 read_permanent_attributes_hash: Some(read_permanent_attributes_hash),
332*d289c2baSAndroid Build Coastguard Worker                 set_key_version: Some(set_key_version),
333*d289c2baSAndroid Build Coastguard Worker                 get_random: Some(get_random),
334*d289c2baSAndroid Build Coastguard Worker             },
335*d289c2baSAndroid Build Coastguard Worker             rust_ops: ops,
336*d289c2baSAndroid Build Coastguard Worker             _pin: PhantomPinned,
337*d289c2baSAndroid Build Coastguard Worker         }
338*d289c2baSAndroid Build Coastguard Worker     }
339*d289c2baSAndroid Build Coastguard Worker 
340*d289c2baSAndroid Build Coastguard Worker     /// Initializes and returns the C `AvbOps` structure from an `OpsBridge`.
341*d289c2baSAndroid Build Coastguard Worker     ///
342*d289c2baSAndroid Build Coastguard Worker     /// If the contained `Ops` supports `CertOps`, the returned `AvbOps` will also be configured
343*d289c2baSAndroid Build Coastguard Worker     /// properly for libavb_cert.
344*d289c2baSAndroid Build Coastguard Worker     ///
345*d289c2baSAndroid Build Coastguard Worker     /// Pinning is necessary here because the returned `AvbOps` contains pointers into `self`, so
346*d289c2baSAndroid Build Coastguard Worker     /// we cannot allow `self` to subsequently move or else the pointers would become invalid.
347*d289c2baSAndroid Build Coastguard Worker     ///
348*d289c2baSAndroid Build Coastguard Worker     /// # Returns
349*d289c2baSAndroid Build Coastguard Worker     /// The C `AvbOps` struct to make libavb calls with.
init_and_get_c_ops<'a>(self: Pin<&'a mut Self>) -> &'a mut AvbOps350*d289c2baSAndroid Build Coastguard Worker     pub(crate) fn init_and_get_c_ops<'a>(self: Pin<&'a mut Self>) -> &'a mut AvbOps {
351*d289c2baSAndroid Build Coastguard Worker         // SAFETY: we do not move out of `self_mut`, but only set pointers to pinned addresses.
352*d289c2baSAndroid Build Coastguard Worker         let self_mut = unsafe { self.get_unchecked_mut() };
353*d289c2baSAndroid Build Coastguard Worker 
354*d289c2baSAndroid Build Coastguard Worker         // Set the C `user_data` to point back to us so we can retrieve ourself in callbacks.
355*d289c2baSAndroid Build Coastguard Worker         self_mut.avb_ops.user_data = self_mut as *mut _ as *mut _;
356*d289c2baSAndroid Build Coastguard Worker 
357*d289c2baSAndroid Build Coastguard Worker         // If the `Ops` supports certs, set up the necessary additional pointer tracking.
358*d289c2baSAndroid Build Coastguard Worker         if self_mut.rust_ops.cert_ops().is_some() {
359*d289c2baSAndroid Build Coastguard Worker             self_mut.avb_ops.cert_ops = &mut self_mut.cert_ops;
360*d289c2baSAndroid Build Coastguard Worker             self_mut.cert_ops.ops = &mut self_mut.avb_ops;
361*d289c2baSAndroid Build Coastguard Worker         }
362*d289c2baSAndroid Build Coastguard Worker 
363*d289c2baSAndroid Build Coastguard Worker         &mut self_mut.avb_ops
364*d289c2baSAndroid Build Coastguard Worker     }
365*d289c2baSAndroid Build Coastguard Worker }
366*d289c2baSAndroid Build Coastguard Worker 
367*d289c2baSAndroid Build Coastguard Worker /// Extracts the user-provided `Ops` from a raw `AvbOps`.
368*d289c2baSAndroid Build Coastguard Worker ///
369*d289c2baSAndroid Build Coastguard Worker /// This function is used in libavb callbacks to bridge libavb's raw C `AvbOps` struct to our Rust
370*d289c2baSAndroid Build Coastguard Worker /// implementation.
371*d289c2baSAndroid Build Coastguard Worker ///
372*d289c2baSAndroid Build Coastguard Worker /// # Arguments
373*d289c2baSAndroid Build Coastguard Worker /// * `avb_ops`: The raw `AvbOps` pointer used by libavb.
374*d289c2baSAndroid Build Coastguard Worker ///
375*d289c2baSAndroid Build Coastguard Worker /// # Returns
376*d289c2baSAndroid Build Coastguard Worker /// The Rust `Ops` extracted from `avb_ops.user_data`.
377*d289c2baSAndroid Build Coastguard Worker ///
378*d289c2baSAndroid Build Coastguard Worker /// # Safety
379*d289c2baSAndroid Build Coastguard Worker /// * only call this function on an `AvbOps` created via `OpsBridge`
380*d289c2baSAndroid Build Coastguard Worker /// * drop all references to the returned `Ops` and preloaded data before returning control to
381*d289c2baSAndroid Build Coastguard Worker ///   libavb or calling this function again
382*d289c2baSAndroid Build Coastguard Worker ///
383*d289c2baSAndroid Build Coastguard Worker /// In practice, these conditions are met since we call this at most once in each callback
384*d289c2baSAndroid Build Coastguard Worker /// to extract the `Ops`, and drop the references at callback completion.
385*d289c2baSAndroid Build Coastguard Worker ///
386*d289c2baSAndroid Build Coastguard Worker /// # Lifetimes
387*d289c2baSAndroid Build Coastguard Worker /// * `'o`: lifetime of the `Ops` object
388*d289c2baSAndroid Build Coastguard Worker /// * `'p`: lifetime of any preloaded data provided by `Ops`
389*d289c2baSAndroid Build Coastguard Worker ///
390*d289c2baSAndroid Build Coastguard Worker /// It's difficult to accurately provide the lifetimes when calling this function, since we are in
391*d289c2baSAndroid Build Coastguard Worker /// a C callback which provides no lifetime information in the args. We solve this in the safety
392*d289c2baSAndroid Build Coastguard Worker /// requirements by requiring the caller to drop both references before returning, which is always
393*d289c2baSAndroid Build Coastguard Worker /// a subset of the actual object lifetimes as the objects must remain valid while libavb is
394*d289c2baSAndroid Build Coastguard Worker /// actively using them:
395*d289c2baSAndroid Build Coastguard Worker ///
396*d289c2baSAndroid Build Coastguard Worker /// ```ignore
397*d289c2baSAndroid Build Coastguard Worker /// ops/preloaded lifetime {  // Actual 'o/'p start
398*d289c2baSAndroid Build Coastguard Worker ///   call into libavb {
399*d289c2baSAndroid Build Coastguard Worker ///     libavb callbacks {
400*d289c2baSAndroid Build Coastguard Worker ///       as_ops()            // as_ops() 'o/'p start
401*d289c2baSAndroid Build Coastguard Worker ///     }                     // as_ops() 'o/'p end
402*d289c2baSAndroid Build Coastguard Worker ///   }
403*d289c2baSAndroid Build Coastguard Worker /// }                         // Actual 'o/'p end
404*d289c2baSAndroid Build Coastguard Worker /// ```
as_ops<'o, 'p>(avb_ops: *mut AvbOps) -> IoResult<&'o mut dyn Ops<'p>>405*d289c2baSAndroid Build Coastguard Worker unsafe fn as_ops<'o, 'p>(avb_ops: *mut AvbOps) -> IoResult<&'o mut dyn Ops<'p>> {
406*d289c2baSAndroid Build Coastguard Worker     // SAFETY: we created this AvbOps object and passed it to libavb so we know it meets all
407*d289c2baSAndroid Build Coastguard Worker     // the criteria for `as_mut()`.
408*d289c2baSAndroid Build Coastguard Worker     let avb_ops = unsafe { avb_ops.as_mut() }.ok_or(IoError::Io)?;
409*d289c2baSAndroid Build Coastguard Worker     // Cast the void* `user_data` back to a OpsBridge*.
410*d289c2baSAndroid Build Coastguard Worker     let bridge = avb_ops.user_data as *mut OpsBridge;
411*d289c2baSAndroid Build Coastguard Worker     // SAFETY: we created this OpsBridge object and passed it to libavb so we know it meets all
412*d289c2baSAndroid Build Coastguard Worker     // the criteria for `as_mut()`.
413*d289c2baSAndroid Build Coastguard Worker     Ok(unsafe { bridge.as_mut() }.ok_or(IoError::Io)?.rust_ops)
414*d289c2baSAndroid Build Coastguard Worker }
415*d289c2baSAndroid Build Coastguard Worker 
416*d289c2baSAndroid Build Coastguard Worker /// Similar to `as_ops()`, but for `CertOps`.
417*d289c2baSAndroid Build Coastguard Worker ///
418*d289c2baSAndroid Build Coastguard Worker /// # Safety
419*d289c2baSAndroid Build Coastguard Worker /// Same as `as_ops()`.
as_cert_ops<'o>(cert_ops: *mut AvbCertOps) -> IoResult<&'o mut dyn CertOps>420*d289c2baSAndroid Build Coastguard Worker unsafe fn as_cert_ops<'o>(cert_ops: *mut AvbCertOps) -> IoResult<&'o mut dyn CertOps> {
421*d289c2baSAndroid Build Coastguard Worker     // SAFETY: we created this `CertOps` object and passed it to libavb so we know it meets all
422*d289c2baSAndroid Build Coastguard Worker     // the criteria for `as_mut()`.
423*d289c2baSAndroid Build Coastguard Worker     let cert_ops = unsafe { cert_ops.as_mut() }.ok_or(IoError::Io)?;
424*d289c2baSAndroid Build Coastguard Worker 
425*d289c2baSAndroid Build Coastguard Worker     // SAFETY: caller must adhere to `as_ops()` safety requirements.
426*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(cert_ops.ops) }?;
427*d289c2baSAndroid Build Coastguard Worker 
428*d289c2baSAndroid Build Coastguard Worker     // Return the `CertOps` implementation. If it doesn't exist here, it indicates an internal error
429*d289c2baSAndroid Build Coastguard Worker     // in this library; somewhere we accepted a non-cert `Ops` into a function that requires cert.
430*d289c2baSAndroid Build Coastguard Worker     ops.cert_ops().ok_or(IoError::NotImplemented)
431*d289c2baSAndroid Build Coastguard Worker }
432*d289c2baSAndroid Build Coastguard Worker 
433*d289c2baSAndroid Build Coastguard Worker /// Converts a non-NULL `ptr` to `()`, NULL to `Err(IoError::Io)`.
check_nonnull<T>(ptr: *const T) -> IoResult<()>434*d289c2baSAndroid Build Coastguard Worker fn check_nonnull<T>(ptr: *const T) -> IoResult<()> {
435*d289c2baSAndroid Build Coastguard Worker     match ptr.is_null() {
436*d289c2baSAndroid Build Coastguard Worker         true => Err(IoError::Io),
437*d289c2baSAndroid Build Coastguard Worker         false => Ok(()),
438*d289c2baSAndroid Build Coastguard Worker     }
439*d289c2baSAndroid Build Coastguard Worker }
440*d289c2baSAndroid Build Coastguard Worker 
441*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
442*d289c2baSAndroid Build Coastguard Worker ///
443*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
read_from_partition( ops: *mut AvbOps, partition: *const c_char, offset: i64, num_bytes: usize, buffer: *mut c_void, out_num_read: *mut usize, ) -> AvbIOResult444*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn read_from_partition(
445*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
446*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
447*d289c2baSAndroid Build Coastguard Worker     offset: i64,
448*d289c2baSAndroid Build Coastguard Worker     num_bytes: usize,
449*d289c2baSAndroid Build Coastguard Worker     buffer: *mut c_void,
450*d289c2baSAndroid Build Coastguard Worker     out_num_read: *mut usize,
451*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
452*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
453*d289c2baSAndroid Build Coastguard Worker     unsafe {
454*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_read_from_partition(
455*d289c2baSAndroid Build Coastguard Worker             ops,
456*d289c2baSAndroid Build Coastguard Worker             partition,
457*d289c2baSAndroid Build Coastguard Worker             offset,
458*d289c2baSAndroid Build Coastguard Worker             num_bytes,
459*d289c2baSAndroid Build Coastguard Worker             buffer,
460*d289c2baSAndroid Build Coastguard Worker             out_num_read,
461*d289c2baSAndroid Build Coastguard Worker         ))
462*d289c2baSAndroid Build Coastguard Worker     }
463*d289c2baSAndroid Build Coastguard Worker }
464*d289c2baSAndroid Build Coastguard Worker 
465*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
466*d289c2baSAndroid Build Coastguard Worker ///
467*d289c2baSAndroid Build Coastguard Worker /// # Safety
468*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
469*d289c2baSAndroid Build Coastguard Worker /// * `partition` must adhere to the requirements of `CStr::from_ptr()`.
470*d289c2baSAndroid Build Coastguard Worker /// * `buffer` must adhere to the requirements of `slice::from_raw_parts_mut()`.
471*d289c2baSAndroid Build Coastguard Worker /// * `out_num_read` must adhere to the requirements of `ptr::write()`.
try_read_from_partition( ops: *mut AvbOps, partition: *const c_char, offset: i64, num_bytes: usize, buffer: *mut c_void, out_num_read: *mut usize, ) -> IoResult<()>472*d289c2baSAndroid Build Coastguard Worker unsafe fn try_read_from_partition(
473*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
474*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
475*d289c2baSAndroid Build Coastguard Worker     offset: i64,
476*d289c2baSAndroid Build Coastguard Worker     num_bytes: usize,
477*d289c2baSAndroid Build Coastguard Worker     buffer: *mut c_void,
478*d289c2baSAndroid Build Coastguard Worker     out_num_read: *mut usize,
479*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
480*d289c2baSAndroid Build Coastguard Worker     check_nonnull(partition)?;
481*d289c2baSAndroid Build Coastguard Worker     check_nonnull(buffer)?;
482*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_num_read)?;
483*d289c2baSAndroid Build Coastguard Worker 
484*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
485*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
486*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
487*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_num_read`.
488*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_num_read, 0) };
489*d289c2baSAndroid Build Coastguard Worker 
490*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
491*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
492*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
493*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
494*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
495*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
496*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated and nul-terminated `partition`.
497*d289c2baSAndroid Build Coastguard Worker     // * the string contents are not modified while the returned `&CStr` exists.
498*d289c2baSAndroid Build Coastguard Worker     // * the returned `&CStr` is not held past the scope of this callback.
499*d289c2baSAndroid Build Coastguard Worker     let partition = unsafe { CStr::from_ptr(partition) };
500*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
501*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
502*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `buffer` with size `num_bytes`.
503*d289c2baSAndroid Build Coastguard Worker     // * we only access the contents via the returned slice.
504*d289c2baSAndroid Build Coastguard Worker     // * the returned slice is not held past the scope of this callback.
505*d289c2baSAndroid Build Coastguard Worker     let buffer = unsafe { slice::from_raw_parts_mut(buffer as *mut u8, num_bytes) };
506*d289c2baSAndroid Build Coastguard Worker 
507*d289c2baSAndroid Build Coastguard Worker     let bytes_read = ops.read_from_partition(partition, offset, buffer)?;
508*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
509*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
510*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_num_read`.
511*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_num_read, bytes_read) };
512*d289c2baSAndroid Build Coastguard Worker     Ok(())
513*d289c2baSAndroid Build Coastguard Worker }
514*d289c2baSAndroid Build Coastguard Worker 
515*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
516*d289c2baSAndroid Build Coastguard Worker ///
517*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
get_preloaded_partition( ops: *mut AvbOps, partition: *const c_char, num_bytes: usize, out_pointer: *mut *mut u8, out_num_bytes_preloaded: *mut usize, ) -> AvbIOResult518*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn get_preloaded_partition(
519*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
520*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
521*d289c2baSAndroid Build Coastguard Worker     num_bytes: usize,
522*d289c2baSAndroid Build Coastguard Worker     out_pointer: *mut *mut u8,
523*d289c2baSAndroid Build Coastguard Worker     out_num_bytes_preloaded: *mut usize,
524*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
525*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
526*d289c2baSAndroid Build Coastguard Worker     unsafe {
527*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_get_preloaded_partition(
528*d289c2baSAndroid Build Coastguard Worker             ops,
529*d289c2baSAndroid Build Coastguard Worker             partition,
530*d289c2baSAndroid Build Coastguard Worker             num_bytes,
531*d289c2baSAndroid Build Coastguard Worker             out_pointer,
532*d289c2baSAndroid Build Coastguard Worker             out_num_bytes_preloaded,
533*d289c2baSAndroid Build Coastguard Worker         ))
534*d289c2baSAndroid Build Coastguard Worker     }
535*d289c2baSAndroid Build Coastguard Worker }
536*d289c2baSAndroid Build Coastguard Worker 
537*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
538*d289c2baSAndroid Build Coastguard Worker ///
539*d289c2baSAndroid Build Coastguard Worker /// # Safety
540*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
541*d289c2baSAndroid Build Coastguard Worker /// * `partition` must adhere to the requirements of `CStr::from_ptr()`.
542*d289c2baSAndroid Build Coastguard Worker /// * `out_pointer` and `out_num_bytes_preloaded` must adhere to the requirements of `ptr::write()`.
543*d289c2baSAndroid Build Coastguard Worker /// * `out_pointer` will become an alias to the `ops` preloaded partition data, so the preloaded
544*d289c2baSAndroid Build Coastguard Worker ///   data must remain valid and unmodified while `out_pointer` exists.
try_get_preloaded_partition( ops: *mut AvbOps, partition: *const c_char, num_bytes: usize, out_pointer: *mut *mut u8, out_num_bytes_preloaded: *mut usize, ) -> IoResult<()>545*d289c2baSAndroid Build Coastguard Worker unsafe fn try_get_preloaded_partition(
546*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
547*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
548*d289c2baSAndroid Build Coastguard Worker     num_bytes: usize,
549*d289c2baSAndroid Build Coastguard Worker     out_pointer: *mut *mut u8,
550*d289c2baSAndroid Build Coastguard Worker     out_num_bytes_preloaded: *mut usize,
551*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
552*d289c2baSAndroid Build Coastguard Worker     check_nonnull(partition)?;
553*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_pointer)?;
554*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_num_bytes_preloaded)?;
555*d289c2baSAndroid Build Coastguard Worker 
556*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
557*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
558*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointers are non-NULL.
559*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us properly-aligned and sized `out` vars.
560*d289c2baSAndroid Build Coastguard Worker     unsafe {
561*d289c2baSAndroid Build Coastguard Worker         ptr::write(out_pointer, ptr::null_mut());
562*d289c2baSAndroid Build Coastguard Worker         ptr::write(out_num_bytes_preloaded, 0);
563*d289c2baSAndroid Build Coastguard Worker     }
564*d289c2baSAndroid Build Coastguard Worker 
565*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
566*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
567*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
568*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
569*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
570*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
571*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated and nul-terminated `partition`.
572*d289c2baSAndroid Build Coastguard Worker     // * the string contents are not modified while the returned `&CStr` exists.
573*d289c2baSAndroid Build Coastguard Worker     // * the returned `&CStr` is not held past the scope of this callback.
574*d289c2baSAndroid Build Coastguard Worker     let partition = unsafe { CStr::from_ptr(partition) };
575*d289c2baSAndroid Build Coastguard Worker 
576*d289c2baSAndroid Build Coastguard Worker     match ops.get_preloaded_partition(partition) {
577*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
578*d289c2baSAndroid Build Coastguard Worker         // * we've checked that the pointers are non-NULL.
579*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us properly-aligned and sized `out` vars.
580*d289c2baSAndroid Build Coastguard Worker         Ok(contents) => unsafe {
581*d289c2baSAndroid Build Coastguard Worker             ptr::write(
582*d289c2baSAndroid Build Coastguard Worker                 out_pointer,
583*d289c2baSAndroid Build Coastguard Worker                 // Warning: we are casting an immutable &[u8] to a mutable *u8. If libavb actually
584*d289c2baSAndroid Build Coastguard Worker                 // modified these contents this could cause undefined behavior, but it just reads.
585*d289c2baSAndroid Build Coastguard Worker                 // TODO: can we change the libavb API to take a const*?
586*d289c2baSAndroid Build Coastguard Worker                 contents.as_ptr() as *mut u8,
587*d289c2baSAndroid Build Coastguard Worker             );
588*d289c2baSAndroid Build Coastguard Worker             ptr::write(
589*d289c2baSAndroid Build Coastguard Worker                 out_num_bytes_preloaded,
590*d289c2baSAndroid Build Coastguard Worker                 // Truncate here if necessary, we may have more preloaded data than libavb needs.
591*d289c2baSAndroid Build Coastguard Worker                 min(contents.len(), num_bytes),
592*d289c2baSAndroid Build Coastguard Worker             );
593*d289c2baSAndroid Build Coastguard Worker         },
594*d289c2baSAndroid Build Coastguard Worker         // No-op if this partition is not preloaded, we've already reset the out variables to
595*d289c2baSAndroid Build Coastguard Worker         // indicate preloaded data is not available.
596*d289c2baSAndroid Build Coastguard Worker         Err(IoError::NotImplemented) => (),
597*d289c2baSAndroid Build Coastguard Worker         Err(e) => return Err(e),
598*d289c2baSAndroid Build Coastguard Worker     };
599*d289c2baSAndroid Build Coastguard Worker     Ok(())
600*d289c2baSAndroid Build Coastguard Worker }
601*d289c2baSAndroid Build Coastguard Worker 
602*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
603*d289c2baSAndroid Build Coastguard Worker ///
604*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
validate_vbmeta_public_key( ops: *mut AvbOps, public_key_data: *const u8, public_key_length: usize, public_key_metadata: *const u8, public_key_metadata_length: usize, out_is_trusted: *mut bool, ) -> AvbIOResult605*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn validate_vbmeta_public_key(
606*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
607*d289c2baSAndroid Build Coastguard Worker     public_key_data: *const u8,
608*d289c2baSAndroid Build Coastguard Worker     public_key_length: usize,
609*d289c2baSAndroid Build Coastguard Worker     public_key_metadata: *const u8,
610*d289c2baSAndroid Build Coastguard Worker     public_key_metadata_length: usize,
611*d289c2baSAndroid Build Coastguard Worker     out_is_trusted: *mut bool,
612*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
613*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
614*d289c2baSAndroid Build Coastguard Worker     unsafe {
615*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_validate_vbmeta_public_key(
616*d289c2baSAndroid Build Coastguard Worker             ops,
617*d289c2baSAndroid Build Coastguard Worker             public_key_data,
618*d289c2baSAndroid Build Coastguard Worker             public_key_length,
619*d289c2baSAndroid Build Coastguard Worker             public_key_metadata,
620*d289c2baSAndroid Build Coastguard Worker             public_key_metadata_length,
621*d289c2baSAndroid Build Coastguard Worker             out_is_trusted,
622*d289c2baSAndroid Build Coastguard Worker         ))
623*d289c2baSAndroid Build Coastguard Worker     }
624*d289c2baSAndroid Build Coastguard Worker }
625*d289c2baSAndroid Build Coastguard Worker 
626*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
627*d289c2baSAndroid Build Coastguard Worker ///
628*d289c2baSAndroid Build Coastguard Worker /// # Safety
629*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
630*d289c2baSAndroid Build Coastguard Worker /// * `public_key_*` args must adhere to the requirements of `slice::from_raw_parts()`.
631*d289c2baSAndroid Build Coastguard Worker /// * `out_is_trusted` must adhere to the requirements of `ptr::write()`.
try_validate_vbmeta_public_key( ops: *mut AvbOps, public_key_data: *const u8, public_key_length: usize, public_key_metadata: *const u8, public_key_metadata_length: usize, out_is_trusted: *mut bool, ) -> IoResult<()>632*d289c2baSAndroid Build Coastguard Worker unsafe fn try_validate_vbmeta_public_key(
633*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
634*d289c2baSAndroid Build Coastguard Worker     public_key_data: *const u8,
635*d289c2baSAndroid Build Coastguard Worker     public_key_length: usize,
636*d289c2baSAndroid Build Coastguard Worker     public_key_metadata: *const u8,
637*d289c2baSAndroid Build Coastguard Worker     public_key_metadata_length: usize,
638*d289c2baSAndroid Build Coastguard Worker     out_is_trusted: *mut bool,
639*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
640*d289c2baSAndroid Build Coastguard Worker     check_nonnull(public_key_data)?;
641*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_is_trusted)?;
642*d289c2baSAndroid Build Coastguard Worker 
643*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
644*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
645*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
646*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_is_trusted`.
647*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_is_trusted, false) };
648*d289c2baSAndroid Build Coastguard Worker 
649*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
650*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
651*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
652*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
653*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
654*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
655*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `public_key_data` with size `public_key_length`.
656*d289c2baSAndroid Build Coastguard Worker     // * we only access the contents via the returned slice.
657*d289c2baSAndroid Build Coastguard Worker     // * the returned slice is not held past the scope of this callback.
658*d289c2baSAndroid Build Coastguard Worker     let public_key = unsafe { slice::from_raw_parts(public_key_data, public_key_length) };
659*d289c2baSAndroid Build Coastguard Worker     let metadata = check_nonnull(public_key_metadata).ok().map(
660*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
661*d289c2baSAndroid Build Coastguard Worker         // * we've checked that the pointer is non-NULL.
662*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated `public_key_metadata` with size
663*d289c2baSAndroid Build Coastguard Worker         //   `public_key_metadata_length`.
664*d289c2baSAndroid Build Coastguard Worker         // * we only access the contents via the returned slice.
665*d289c2baSAndroid Build Coastguard Worker         // * the returned slice is not held past the scope of this callback.
666*d289c2baSAndroid Build Coastguard Worker         |_| unsafe { slice::from_raw_parts(public_key_metadata, public_key_metadata_length) },
667*d289c2baSAndroid Build Coastguard Worker     );
668*d289c2baSAndroid Build Coastguard Worker 
669*d289c2baSAndroid Build Coastguard Worker     let trusted = ops.validate_vbmeta_public_key(public_key, metadata)?;
670*d289c2baSAndroid Build Coastguard Worker 
671*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
672*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
673*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_is_trusted`.
674*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_is_trusted, trusted) };
675*d289c2baSAndroid Build Coastguard Worker     Ok(())
676*d289c2baSAndroid Build Coastguard Worker }
677*d289c2baSAndroid Build Coastguard Worker 
678*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
679*d289c2baSAndroid Build Coastguard Worker ///
680*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
read_rollback_index( ops: *mut AvbOps, rollback_index_location: usize, out_rollback_index: *mut u64, ) -> AvbIOResult681*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn read_rollback_index(
682*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
683*d289c2baSAndroid Build Coastguard Worker     rollback_index_location: usize,
684*d289c2baSAndroid Build Coastguard Worker     out_rollback_index: *mut u64,
685*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
686*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
687*d289c2baSAndroid Build Coastguard Worker     unsafe {
688*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_read_rollback_index(
689*d289c2baSAndroid Build Coastguard Worker             ops,
690*d289c2baSAndroid Build Coastguard Worker             rollback_index_location,
691*d289c2baSAndroid Build Coastguard Worker             out_rollback_index,
692*d289c2baSAndroid Build Coastguard Worker         ))
693*d289c2baSAndroid Build Coastguard Worker     }
694*d289c2baSAndroid Build Coastguard Worker }
695*d289c2baSAndroid Build Coastguard Worker 
696*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
697*d289c2baSAndroid Build Coastguard Worker ///
698*d289c2baSAndroid Build Coastguard Worker /// # Safety
699*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
700*d289c2baSAndroid Build Coastguard Worker /// * `out_rollback_index` must adhere to the requirements of `ptr::write()`.
try_read_rollback_index( ops: *mut AvbOps, rollback_index_location: usize, out_rollback_index: *mut u64, ) -> IoResult<()>701*d289c2baSAndroid Build Coastguard Worker unsafe fn try_read_rollback_index(
702*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
703*d289c2baSAndroid Build Coastguard Worker     rollback_index_location: usize,
704*d289c2baSAndroid Build Coastguard Worker     out_rollback_index: *mut u64,
705*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
706*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_rollback_index)?;
707*d289c2baSAndroid Build Coastguard Worker 
708*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
709*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
710*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
711*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_rollback_index`.
712*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_rollback_index, 0) };
713*d289c2baSAndroid Build Coastguard Worker 
714*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
715*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
716*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
717*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
718*d289c2baSAndroid Build Coastguard Worker     let index = ops.read_rollback_index(rollback_index_location)?;
719*d289c2baSAndroid Build Coastguard Worker 
720*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
721*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
722*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_rollback_index`.
723*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_rollback_index, index) };
724*d289c2baSAndroid Build Coastguard Worker     Ok(())
725*d289c2baSAndroid Build Coastguard Worker }
726*d289c2baSAndroid Build Coastguard Worker 
727*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
728*d289c2baSAndroid Build Coastguard Worker ///
729*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
write_rollback_index( ops: *mut AvbOps, rollback_index_location: usize, rollback_index: u64, ) -> AvbIOResult730*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn write_rollback_index(
731*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
732*d289c2baSAndroid Build Coastguard Worker     rollback_index_location: usize,
733*d289c2baSAndroid Build Coastguard Worker     rollback_index: u64,
734*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
735*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
736*d289c2baSAndroid Build Coastguard Worker     unsafe {
737*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_write_rollback_index(
738*d289c2baSAndroid Build Coastguard Worker             ops,
739*d289c2baSAndroid Build Coastguard Worker             rollback_index_location,
740*d289c2baSAndroid Build Coastguard Worker             rollback_index,
741*d289c2baSAndroid Build Coastguard Worker         ))
742*d289c2baSAndroid Build Coastguard Worker     }
743*d289c2baSAndroid Build Coastguard Worker }
744*d289c2baSAndroid Build Coastguard Worker 
745*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
746*d289c2baSAndroid Build Coastguard Worker ///
747*d289c2baSAndroid Build Coastguard Worker /// # Safety
748*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
try_write_rollback_index( ops: *mut AvbOps, rollback_index_location: usize, rollback_index: u64, ) -> IoResult<()>749*d289c2baSAndroid Build Coastguard Worker unsafe fn try_write_rollback_index(
750*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
751*d289c2baSAndroid Build Coastguard Worker     rollback_index_location: usize,
752*d289c2baSAndroid Build Coastguard Worker     rollback_index: u64,
753*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
754*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
755*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
756*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
757*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
758*d289c2baSAndroid Build Coastguard Worker     ops.write_rollback_index(rollback_index_location, rollback_index)
759*d289c2baSAndroid Build Coastguard Worker }
760*d289c2baSAndroid Build Coastguard Worker 
761*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
762*d289c2baSAndroid Build Coastguard Worker ///
763*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
read_is_device_unlocked( ops: *mut AvbOps, out_is_unlocked: *mut bool, ) -> AvbIOResult764*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn read_is_device_unlocked(
765*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
766*d289c2baSAndroid Build Coastguard Worker     out_is_unlocked: *mut bool,
767*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
768*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
769*d289c2baSAndroid Build Coastguard Worker     unsafe { result_to_io_enum(try_read_is_device_unlocked(ops, out_is_unlocked)) }
770*d289c2baSAndroid Build Coastguard Worker }
771*d289c2baSAndroid Build Coastguard Worker 
772*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
773*d289c2baSAndroid Build Coastguard Worker ///
774*d289c2baSAndroid Build Coastguard Worker /// # Safety
775*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
776*d289c2baSAndroid Build Coastguard Worker /// * `out_is_unlocked` must adhere to the requirements of `ptr::write()`.
try_read_is_device_unlocked( ops: *mut AvbOps, out_is_unlocked: *mut bool, ) -> IoResult<()>777*d289c2baSAndroid Build Coastguard Worker unsafe fn try_read_is_device_unlocked(
778*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
779*d289c2baSAndroid Build Coastguard Worker     out_is_unlocked: *mut bool,
780*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
781*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_is_unlocked)?;
782*d289c2baSAndroid Build Coastguard Worker 
783*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
784*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
785*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
786*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_is_unlocked`.
787*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_is_unlocked, false) };
788*d289c2baSAndroid Build Coastguard Worker 
789*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
790*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
791*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
792*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
793*d289c2baSAndroid Build Coastguard Worker     let unlocked = ops.read_is_device_unlocked()?;
794*d289c2baSAndroid Build Coastguard Worker 
795*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
796*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
797*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_is_unlocked`.
798*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_is_unlocked, unlocked) };
799*d289c2baSAndroid Build Coastguard Worker     Ok(())
800*d289c2baSAndroid Build Coastguard Worker }
801*d289c2baSAndroid Build Coastguard Worker 
802*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
803*d289c2baSAndroid Build Coastguard Worker ///
804*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
get_unique_guid_for_partition( ops: *mut AvbOps, partition: *const c_char, guid_buf: *mut c_char, guid_buf_size: usize, ) -> AvbIOResult805*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn get_unique_guid_for_partition(
806*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
807*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
808*d289c2baSAndroid Build Coastguard Worker     guid_buf: *mut c_char,
809*d289c2baSAndroid Build Coastguard Worker     guid_buf_size: usize,
810*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
811*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
812*d289c2baSAndroid Build Coastguard Worker     unsafe {
813*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_get_unique_guid_for_partition(
814*d289c2baSAndroid Build Coastguard Worker             ops,
815*d289c2baSAndroid Build Coastguard Worker             partition,
816*d289c2baSAndroid Build Coastguard Worker             guid_buf,
817*d289c2baSAndroid Build Coastguard Worker             guid_buf_size,
818*d289c2baSAndroid Build Coastguard Worker         ))
819*d289c2baSAndroid Build Coastguard Worker     }
820*d289c2baSAndroid Build Coastguard Worker }
821*d289c2baSAndroid Build Coastguard Worker 
822*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
823*d289c2baSAndroid Build Coastguard Worker ///
824*d289c2baSAndroid Build Coastguard Worker /// When the `uuid` feature is not enabled, this doesn't call into the user ops at all and instead
825*d289c2baSAndroid Build Coastguard Worker /// gives the empty string for all partitions.
826*d289c2baSAndroid Build Coastguard Worker ///
827*d289c2baSAndroid Build Coastguard Worker /// # Safety
828*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
829*d289c2baSAndroid Build Coastguard Worker /// * `partition` must adhere to the requirements of `CStr::from_ptr()`.
830*d289c2baSAndroid Build Coastguard Worker /// * `guid_buf` must adhere to the requirements of `slice::from_raw_parts_mut()`.
try_get_unique_guid_for_partition( #[allow(unused_variables)] ops: *mut AvbOps, #[allow(unused_variables)] partition: *const c_char, guid_buf: *mut c_char, guid_buf_size: usize, ) -> IoResult<()>831*d289c2baSAndroid Build Coastguard Worker unsafe fn try_get_unique_guid_for_partition(
832*d289c2baSAndroid Build Coastguard Worker     #[allow(unused_variables)] ops: *mut AvbOps,
833*d289c2baSAndroid Build Coastguard Worker     #[allow(unused_variables)] partition: *const c_char,
834*d289c2baSAndroid Build Coastguard Worker     guid_buf: *mut c_char,
835*d289c2baSAndroid Build Coastguard Worker     guid_buf_size: usize,
836*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
837*d289c2baSAndroid Build Coastguard Worker     check_nonnull(guid_buf)?;
838*d289c2baSAndroid Build Coastguard Worker 
839*d289c2baSAndroid Build Coastguard Worker     // On some architectures `c_char` is `u8`, and on others `i8`. We make sure it's `u8` here
840*d289c2baSAndroid Build Coastguard Worker     // since that's what `CStr::to_bytes_with_nul()` always provides.
841*d289c2baSAndroid Build Coastguard Worker     #[allow(clippy::unnecessary_cast)]
842*d289c2baSAndroid Build Coastguard Worker     let guid_buf = guid_buf as *mut u8;
843*d289c2baSAndroid Build Coastguard Worker 
844*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
845*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
846*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `guid_buf` with size `guid_buf_size`.
847*d289c2baSAndroid Build Coastguard Worker     // * we only access the contents via the returned slice.
848*d289c2baSAndroid Build Coastguard Worker     // * the returned slice is not held past the scope of this callback.
849*d289c2baSAndroid Build Coastguard Worker     let buffer = unsafe { slice::from_raw_parts_mut(guid_buf, guid_buf_size) };
850*d289c2baSAndroid Build Coastguard Worker 
851*d289c2baSAndroid Build Coastguard Worker     // Initialize the output buffer to the empty string.
852*d289c2baSAndroid Build Coastguard Worker     //
853*d289c2baSAndroid Build Coastguard Worker     // When the `uuid` feature is not selected, the user doesn't need commandline GUIDs but libavb
854*d289c2baSAndroid Build Coastguard Worker     // may still attempt to inject the `vmbeta` or `boot` partition GUIDs into the commandline,
855*d289c2baSAndroid Build Coastguard Worker     // depending on the verification settings. In order to satisfy libavb's requirements we must:
856*d289c2baSAndroid Build Coastguard Worker     // * write a nul-terminated string to avoid undefined behavior (empty string is sufficient)
857*d289c2baSAndroid Build Coastguard Worker     // * return `Ok(())` or verification will fail
858*d289c2baSAndroid Build Coastguard Worker     if buffer.is_empty() {
859*d289c2baSAndroid Build Coastguard Worker         return Err(IoError::Oom);
860*d289c2baSAndroid Build Coastguard Worker     }
861*d289c2baSAndroid Build Coastguard Worker     buffer[0] = b'\0';
862*d289c2baSAndroid Build Coastguard Worker 
863*d289c2baSAndroid Build Coastguard Worker     #[cfg(feature = "uuid")]
864*d289c2baSAndroid Build Coastguard Worker     {
865*d289c2baSAndroid Build Coastguard Worker         check_nonnull(partition)?;
866*d289c2baSAndroid Build Coastguard Worker 
867*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
868*d289c2baSAndroid Build Coastguard Worker         // * we've checked that the pointer is non-NULL.
869*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated and nul-terminated `partition`.
870*d289c2baSAndroid Build Coastguard Worker         // * the string contents are not modified while the returned `&CStr` exists.
871*d289c2baSAndroid Build Coastguard Worker         // * the returned `&CStr` is not held past the scope of this callback.
872*d289c2baSAndroid Build Coastguard Worker         let partition = unsafe { CStr::from_ptr(partition) };
873*d289c2baSAndroid Build Coastguard Worker 
874*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
875*d289c2baSAndroid Build Coastguard Worker         // * we only use `ops` objects created via `OpsBridge` as required.
876*d289c2baSAndroid Build Coastguard Worker         // * `ops` is only extracted once and is dropped at the end of the callback.
877*d289c2baSAndroid Build Coastguard Worker         let ops = unsafe { as_ops(ops) }?;
878*d289c2baSAndroid Build Coastguard Worker         let guid = ops.get_unique_guid_for_partition(partition)?;
879*d289c2baSAndroid Build Coastguard Worker 
880*d289c2baSAndroid Build Coastguard Worker         // Write the UUID string to a uuid buffer which is guaranteed to be large enough, then use
881*d289c2baSAndroid Build Coastguard Worker         // `CString` to apply nul-termination.
882*d289c2baSAndroid Build Coastguard Worker         // This does allocate memory, but it's short-lived and discarded as soon as we copy the
883*d289c2baSAndroid Build Coastguard Worker         // properly-terminated string back to the buffer.
884*d289c2baSAndroid Build Coastguard Worker         let mut encode_buffer = Uuid::encode_buffer();
885*d289c2baSAndroid Build Coastguard Worker         let guid_str = guid.as_hyphenated().encode_lower(&mut encode_buffer);
886*d289c2baSAndroid Build Coastguard Worker         let guid_cstring = alloc::ffi::CString::new(guid_str.as_bytes()).or(Err(IoError::Io))?;
887*d289c2baSAndroid Build Coastguard Worker         let guid_bytes = guid_cstring.to_bytes_with_nul();
888*d289c2baSAndroid Build Coastguard Worker 
889*d289c2baSAndroid Build Coastguard Worker         if buffer.len() < guid_bytes.len() {
890*d289c2baSAndroid Build Coastguard Worker             // This would indicate some internal error - the uuid library needs more
891*d289c2baSAndroid Build Coastguard Worker             // space to print the UUID string than libavb provided.
892*d289c2baSAndroid Build Coastguard Worker             return Err(IoError::Oom);
893*d289c2baSAndroid Build Coastguard Worker         }
894*d289c2baSAndroid Build Coastguard Worker         buffer[..guid_bytes.len()].copy_from_slice(guid_bytes);
895*d289c2baSAndroid Build Coastguard Worker     }
896*d289c2baSAndroid Build Coastguard Worker 
897*d289c2baSAndroid Build Coastguard Worker     Ok(())
898*d289c2baSAndroid Build Coastguard Worker }
899*d289c2baSAndroid Build Coastguard Worker 
900*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
901*d289c2baSAndroid Build Coastguard Worker ///
902*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
get_size_of_partition( ops: *mut AvbOps, partition: *const c_char, out_size_num_bytes: *mut u64, ) -> AvbIOResult903*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn get_size_of_partition(
904*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
905*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
906*d289c2baSAndroid Build Coastguard Worker     out_size_num_bytes: *mut u64,
907*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
908*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
909*d289c2baSAndroid Build Coastguard Worker     unsafe {
910*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_get_size_of_partition(
911*d289c2baSAndroid Build Coastguard Worker             ops,
912*d289c2baSAndroid Build Coastguard Worker             partition,
913*d289c2baSAndroid Build Coastguard Worker             out_size_num_bytes,
914*d289c2baSAndroid Build Coastguard Worker         ))
915*d289c2baSAndroid Build Coastguard Worker     }
916*d289c2baSAndroid Build Coastguard Worker }
917*d289c2baSAndroid Build Coastguard Worker 
918*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
919*d289c2baSAndroid Build Coastguard Worker ///
920*d289c2baSAndroid Build Coastguard Worker /// # Safety
921*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
922*d289c2baSAndroid Build Coastguard Worker /// * `partition` must adhere to the requirements of `CStr::from_ptr()`.
923*d289c2baSAndroid Build Coastguard Worker /// * `out_size_num_bytes` must adhere to the requirements of `ptr::write()`.
try_get_size_of_partition( ops: *mut AvbOps, partition: *const c_char, out_size_num_bytes: *mut u64, ) -> IoResult<()>924*d289c2baSAndroid Build Coastguard Worker unsafe fn try_get_size_of_partition(
925*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
926*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
927*d289c2baSAndroid Build Coastguard Worker     out_size_num_bytes: *mut u64,
928*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
929*d289c2baSAndroid Build Coastguard Worker     check_nonnull(partition)?;
930*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_size_num_bytes)?;
931*d289c2baSAndroid Build Coastguard Worker 
932*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
933*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
934*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
935*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_size_num_bytes`.
936*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_size_num_bytes, 0) };
937*d289c2baSAndroid Build Coastguard Worker 
938*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
939*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
940*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
941*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
942*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
943*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
944*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated and nul-terminated `partition`.
945*d289c2baSAndroid Build Coastguard Worker     // * the string contents are not modified while the returned `&CStr` exists.
946*d289c2baSAndroid Build Coastguard Worker     // * the returned `&CStr` is not held past the scope of this callback.
947*d289c2baSAndroid Build Coastguard Worker     let partition = unsafe { CStr::from_ptr(partition) };
948*d289c2baSAndroid Build Coastguard Worker     let size = ops.get_size_of_partition(partition)?;
949*d289c2baSAndroid Build Coastguard Worker 
950*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
951*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
952*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_size_num_bytes`.
953*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_size_num_bytes, size) };
954*d289c2baSAndroid Build Coastguard Worker     Ok(())
955*d289c2baSAndroid Build Coastguard Worker }
956*d289c2baSAndroid Build Coastguard Worker 
957*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
958*d289c2baSAndroid Build Coastguard Worker ///
959*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
read_persistent_value( ops: *mut AvbOps, name: *const c_char, buffer_size: usize, out_buffer: *mut u8, out_num_bytes_read: *mut usize, ) -> AvbIOResult960*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn read_persistent_value(
961*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
962*d289c2baSAndroid Build Coastguard Worker     name: *const c_char,
963*d289c2baSAndroid Build Coastguard Worker     buffer_size: usize,
964*d289c2baSAndroid Build Coastguard Worker     out_buffer: *mut u8,
965*d289c2baSAndroid Build Coastguard Worker     out_num_bytes_read: *mut usize,
966*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
967*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
968*d289c2baSAndroid Build Coastguard Worker     unsafe {
969*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_read_persistent_value(
970*d289c2baSAndroid Build Coastguard Worker             ops,
971*d289c2baSAndroid Build Coastguard Worker             name,
972*d289c2baSAndroid Build Coastguard Worker             buffer_size,
973*d289c2baSAndroid Build Coastguard Worker             out_buffer,
974*d289c2baSAndroid Build Coastguard Worker             out_num_bytes_read,
975*d289c2baSAndroid Build Coastguard Worker         ))
976*d289c2baSAndroid Build Coastguard Worker     }
977*d289c2baSAndroid Build Coastguard Worker }
978*d289c2baSAndroid Build Coastguard Worker 
979*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
980*d289c2baSAndroid Build Coastguard Worker ///
981*d289c2baSAndroid Build Coastguard Worker /// # Safety
982*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
983*d289c2baSAndroid Build Coastguard Worker /// * `name` must adhere to the requirements of `CStr::from_ptr()`.
984*d289c2baSAndroid Build Coastguard Worker /// * `out_buffer` must adhere to the requirements of `slice::from_raw_parts_mut()`.
985*d289c2baSAndroid Build Coastguard Worker /// * `out_num_bytes_read` must adhere to the requirements of `ptr::write()`.
try_read_persistent_value( ops: *mut AvbOps, name: *const c_char, buffer_size: usize, out_buffer: *mut u8, out_num_bytes_read: *mut usize, ) -> IoResult<()>986*d289c2baSAndroid Build Coastguard Worker unsafe fn try_read_persistent_value(
987*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
988*d289c2baSAndroid Build Coastguard Worker     name: *const c_char,
989*d289c2baSAndroid Build Coastguard Worker     buffer_size: usize,
990*d289c2baSAndroid Build Coastguard Worker     out_buffer: *mut u8,
991*d289c2baSAndroid Build Coastguard Worker     out_num_bytes_read: *mut usize,
992*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
993*d289c2baSAndroid Build Coastguard Worker     check_nonnull(name)?;
994*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_num_bytes_read)?;
995*d289c2baSAndroid Build Coastguard Worker 
996*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
997*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
998*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
999*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_num_bytes_read`.
1000*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::write(out_num_bytes_read, 0) };
1001*d289c2baSAndroid Build Coastguard Worker 
1002*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1003*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
1004*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
1005*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
1006*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1007*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
1008*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated and nul-terminated `name`.
1009*d289c2baSAndroid Build Coastguard Worker     // * the string contents are not modified while the returned `&CStr` exists.
1010*d289c2baSAndroid Build Coastguard Worker     // * the returned `&CStr` is not held past the scope of this callback.
1011*d289c2baSAndroid Build Coastguard Worker     let name = unsafe { CStr::from_ptr(name) };
1012*d289c2baSAndroid Build Coastguard Worker     let mut empty: [u8; 0] = [];
1013*d289c2baSAndroid Build Coastguard Worker     let value = match out_buffer.is_null() {
1014*d289c2baSAndroid Build Coastguard Worker         // NULL buffer => empty slice, used to just query the value size.
1015*d289c2baSAndroid Build Coastguard Worker         true => &mut empty,
1016*d289c2baSAndroid Build Coastguard Worker         false => {
1017*d289c2baSAndroid Build Coastguard Worker             // SAFETY:
1018*d289c2baSAndroid Build Coastguard Worker             // * we've checked that the pointer is non-NULL.
1019*d289c2baSAndroid Build Coastguard Worker             // * libavb gives us a properly-allocated `out_buffer` with size `buffer_size`.
1020*d289c2baSAndroid Build Coastguard Worker             // * we only access the contents via the returned slice.
1021*d289c2baSAndroid Build Coastguard Worker             // * the returned slice is not held past the scope of this callback.
1022*d289c2baSAndroid Build Coastguard Worker             unsafe { slice::from_raw_parts_mut(out_buffer, buffer_size) }
1023*d289c2baSAndroid Build Coastguard Worker         }
1024*d289c2baSAndroid Build Coastguard Worker     };
1025*d289c2baSAndroid Build Coastguard Worker 
1026*d289c2baSAndroid Build Coastguard Worker     let result = ops.read_persistent_value(name, value);
1027*d289c2baSAndroid Build Coastguard Worker     // On success or insufficient space we need to write the property size back.
1028*d289c2baSAndroid Build Coastguard Worker     if let Ok(size) | Err(IoError::InsufficientSpace(size)) = result {
1029*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
1030*d289c2baSAndroid Build Coastguard Worker         // * we've checked that the pointer is non-NULL.
1031*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated `out_num_bytes_read`.
1032*d289c2baSAndroid Build Coastguard Worker         unsafe { ptr::write(out_num_bytes_read, size) };
1033*d289c2baSAndroid Build Coastguard Worker     };
1034*d289c2baSAndroid Build Coastguard Worker     // We've written the size back and can drop it now.
1035*d289c2baSAndroid Build Coastguard Worker     result.map(|_| ())
1036*d289c2baSAndroid Build Coastguard Worker }
1037*d289c2baSAndroid Build Coastguard Worker 
1038*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
1039*d289c2baSAndroid Build Coastguard Worker ///
1040*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
write_persistent_value( ops: *mut AvbOps, name: *const c_char, value_size: usize, value: *const u8, ) -> AvbIOResult1041*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn write_persistent_value(
1042*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
1043*d289c2baSAndroid Build Coastguard Worker     name: *const c_char,
1044*d289c2baSAndroid Build Coastguard Worker     value_size: usize,
1045*d289c2baSAndroid Build Coastguard Worker     value: *const u8,
1046*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
1047*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
1048*d289c2baSAndroid Build Coastguard Worker     unsafe { result_to_io_enum(try_write_persistent_value(ops, name, value_size, value)) }
1049*d289c2baSAndroid Build Coastguard Worker }
1050*d289c2baSAndroid Build Coastguard Worker 
1051*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
1052*d289c2baSAndroid Build Coastguard Worker ///
1053*d289c2baSAndroid Build Coastguard Worker /// # Safety
1054*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
1055*d289c2baSAndroid Build Coastguard Worker /// * `name` must adhere to the requirements of `CStr::from_ptr()`.
1056*d289c2baSAndroid Build Coastguard Worker /// * `out_buffer` must adhere to the requirements of `slice::from_raw_parts()`.
try_write_persistent_value( ops: *mut AvbOps, name: *const c_char, value_size: usize, value: *const u8, ) -> IoResult<()>1057*d289c2baSAndroid Build Coastguard Worker unsafe fn try_write_persistent_value(
1058*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
1059*d289c2baSAndroid Build Coastguard Worker     name: *const c_char,
1060*d289c2baSAndroid Build Coastguard Worker     value_size: usize,
1061*d289c2baSAndroid Build Coastguard Worker     value: *const u8,
1062*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
1063*d289c2baSAndroid Build Coastguard Worker     check_nonnull(name)?;
1064*d289c2baSAndroid Build Coastguard Worker 
1065*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1066*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
1067*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
1068*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
1069*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1070*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
1071*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated and nul-terminated `name`.
1072*d289c2baSAndroid Build Coastguard Worker     // * the string contents are not modified while the returned `&CStr` exists.
1073*d289c2baSAndroid Build Coastguard Worker     // * the returned `&CStr` is not held past the scope of this callback.
1074*d289c2baSAndroid Build Coastguard Worker     let name = unsafe { CStr::from_ptr(name) };
1075*d289c2baSAndroid Build Coastguard Worker 
1076*d289c2baSAndroid Build Coastguard Worker     if value_size == 0 {
1077*d289c2baSAndroid Build Coastguard Worker         ops.erase_persistent_value(name)
1078*d289c2baSAndroid Build Coastguard Worker     } else {
1079*d289c2baSAndroid Build Coastguard Worker         check_nonnull(value)?;
1080*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
1081*d289c2baSAndroid Build Coastguard Worker         // * we've checked that the pointer is non-NULL.
1082*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated `value` with size `value_size`.
1083*d289c2baSAndroid Build Coastguard Worker         // * we only access the contents via the returned slice.
1084*d289c2baSAndroid Build Coastguard Worker         // * the returned slice is not held past the scope of this callback.
1085*d289c2baSAndroid Build Coastguard Worker         let value = unsafe { slice::from_raw_parts(value, value_size) };
1086*d289c2baSAndroid Build Coastguard Worker         ops.write_persistent_value(name, value)
1087*d289c2baSAndroid Build Coastguard Worker     }
1088*d289c2baSAndroid Build Coastguard Worker }
1089*d289c2baSAndroid Build Coastguard Worker 
1090*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
1091*d289c2baSAndroid Build Coastguard Worker ///
1092*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
validate_public_key_for_partition( ops: *mut AvbOps, partition: *const c_char, public_key_data: *const u8, public_key_length: usize, public_key_metadata: *const u8, public_key_metadata_length: usize, out_is_trusted: *mut bool, out_rollback_index_location: *mut u32, ) -> AvbIOResult1093*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn validate_public_key_for_partition(
1094*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
1095*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
1096*d289c2baSAndroid Build Coastguard Worker     public_key_data: *const u8,
1097*d289c2baSAndroid Build Coastguard Worker     public_key_length: usize,
1098*d289c2baSAndroid Build Coastguard Worker     public_key_metadata: *const u8,
1099*d289c2baSAndroid Build Coastguard Worker     public_key_metadata_length: usize,
1100*d289c2baSAndroid Build Coastguard Worker     out_is_trusted: *mut bool,
1101*d289c2baSAndroid Build Coastguard Worker     out_rollback_index_location: *mut u32,
1102*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
1103*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
1104*d289c2baSAndroid Build Coastguard Worker     unsafe {
1105*d289c2baSAndroid Build Coastguard Worker         result_to_io_enum(try_validate_public_key_for_partition(
1106*d289c2baSAndroid Build Coastguard Worker             ops,
1107*d289c2baSAndroid Build Coastguard Worker             partition,
1108*d289c2baSAndroid Build Coastguard Worker             public_key_data,
1109*d289c2baSAndroid Build Coastguard Worker             public_key_length,
1110*d289c2baSAndroid Build Coastguard Worker             public_key_metadata,
1111*d289c2baSAndroid Build Coastguard Worker             public_key_metadata_length,
1112*d289c2baSAndroid Build Coastguard Worker             out_is_trusted,
1113*d289c2baSAndroid Build Coastguard Worker             out_rollback_index_location,
1114*d289c2baSAndroid Build Coastguard Worker         ))
1115*d289c2baSAndroid Build Coastguard Worker     }
1116*d289c2baSAndroid Build Coastguard Worker }
1117*d289c2baSAndroid Build Coastguard Worker 
1118*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
1119*d289c2baSAndroid Build Coastguard Worker ///
1120*d289c2baSAndroid Build Coastguard Worker /// # Safety
1121*d289c2baSAndroid Build Coastguard Worker /// * `ops` must have been created via `OpsBridge`.
1122*d289c2baSAndroid Build Coastguard Worker /// * `partition` must adhere to the requirements of `CStr::from_ptr()`.
1123*d289c2baSAndroid Build Coastguard Worker /// * `public_key_*` args must adhere to the requirements of `slice::from_raw_parts()`.
1124*d289c2baSAndroid Build Coastguard Worker /// * `out_*` must adhere to the requirements of `ptr::write()`.
1125*d289c2baSAndroid Build Coastguard Worker #[allow(clippy::too_many_arguments)] // Mirroring libavb C API.
try_validate_public_key_for_partition( ops: *mut AvbOps, partition: *const c_char, public_key_data: *const u8, public_key_length: usize, public_key_metadata: *const u8, public_key_metadata_length: usize, out_is_trusted: *mut bool, out_rollback_index_location: *mut u32, ) -> IoResult<()>1126*d289c2baSAndroid Build Coastguard Worker unsafe fn try_validate_public_key_for_partition(
1127*d289c2baSAndroid Build Coastguard Worker     ops: *mut AvbOps,
1128*d289c2baSAndroid Build Coastguard Worker     partition: *const c_char,
1129*d289c2baSAndroid Build Coastguard Worker     public_key_data: *const u8,
1130*d289c2baSAndroid Build Coastguard Worker     public_key_length: usize,
1131*d289c2baSAndroid Build Coastguard Worker     public_key_metadata: *const u8,
1132*d289c2baSAndroid Build Coastguard Worker     public_key_metadata_length: usize,
1133*d289c2baSAndroid Build Coastguard Worker     out_is_trusted: *mut bool,
1134*d289c2baSAndroid Build Coastguard Worker     out_rollback_index_location: *mut u32,
1135*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
1136*d289c2baSAndroid Build Coastguard Worker     check_nonnull(partition)?;
1137*d289c2baSAndroid Build Coastguard Worker     check_nonnull(public_key_data)?;
1138*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_is_trusted)?;
1139*d289c2baSAndroid Build Coastguard Worker     check_nonnull(out_rollback_index_location)?;
1140*d289c2baSAndroid Build Coastguard Worker 
1141*d289c2baSAndroid Build Coastguard Worker     // Initialize the output variables first in case something fails.
1142*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1143*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointers are non-NULL.
1144*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_*`.
1145*d289c2baSAndroid Build Coastguard Worker     unsafe {
1146*d289c2baSAndroid Build Coastguard Worker         ptr::write(out_is_trusted, false);
1147*d289c2baSAndroid Build Coastguard Worker         ptr::write(out_rollback_index_location, 0);
1148*d289c2baSAndroid Build Coastguard Worker     }
1149*d289c2baSAndroid Build Coastguard Worker 
1150*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1151*d289c2baSAndroid Build Coastguard Worker     // * we only use `ops` objects created via `OpsBridge` as required.
1152*d289c2baSAndroid Build Coastguard Worker     // * `ops` is only extracted once and is dropped at the end of the callback.
1153*d289c2baSAndroid Build Coastguard Worker     let ops = unsafe { as_ops(ops) }?;
1154*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1155*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
1156*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated and nul-terminated `partition`.
1157*d289c2baSAndroid Build Coastguard Worker     // * the string contents are not modified while the returned `&CStr` exists.
1158*d289c2baSAndroid Build Coastguard Worker     // * the returned `&CStr` is not held past the scope of this callback.
1159*d289c2baSAndroid Build Coastguard Worker     let partition = unsafe { CStr::from_ptr(partition) };
1160*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1161*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
1162*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `public_key_data` with size `public_key_length`.
1163*d289c2baSAndroid Build Coastguard Worker     // * we only access the contents via the returned slice.
1164*d289c2baSAndroid Build Coastguard Worker     // * the returned slice is not held past the scope of this callback.
1165*d289c2baSAndroid Build Coastguard Worker     let public_key = unsafe { slice::from_raw_parts(public_key_data, public_key_length) };
1166*d289c2baSAndroid Build Coastguard Worker     let metadata = check_nonnull(public_key_metadata).ok().map(
1167*d289c2baSAndroid Build Coastguard Worker         // SAFETY:
1168*d289c2baSAndroid Build Coastguard Worker         // * we've checked that the pointer is non-NULL.
1169*d289c2baSAndroid Build Coastguard Worker         // * libavb gives us a properly-allocated `public_key_metadata` with size
1170*d289c2baSAndroid Build Coastguard Worker         //   `public_key_metadata_length`.
1171*d289c2baSAndroid Build Coastguard Worker         // * we only access the contents via the returned slice.
1172*d289c2baSAndroid Build Coastguard Worker         // * the returned slice is not held past the scope of this callback.
1173*d289c2baSAndroid Build Coastguard Worker         |_| unsafe { slice::from_raw_parts(public_key_metadata, public_key_metadata_length) },
1174*d289c2baSAndroid Build Coastguard Worker     );
1175*d289c2baSAndroid Build Coastguard Worker 
1176*d289c2baSAndroid Build Coastguard Worker     let key_info = ops.validate_public_key_for_partition(partition, public_key, metadata)?;
1177*d289c2baSAndroid Build Coastguard Worker 
1178*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1179*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointers are non-NULL.
1180*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `out_*`.
1181*d289c2baSAndroid Build Coastguard Worker     unsafe {
1182*d289c2baSAndroid Build Coastguard Worker         ptr::write(out_is_trusted, key_info.trusted);
1183*d289c2baSAndroid Build Coastguard Worker         ptr::write(
1184*d289c2baSAndroid Build Coastguard Worker             out_rollback_index_location,
1185*d289c2baSAndroid Build Coastguard Worker             key_info.rollback_index_location,
1186*d289c2baSAndroid Build Coastguard Worker         );
1187*d289c2baSAndroid Build Coastguard Worker     }
1188*d289c2baSAndroid Build Coastguard Worker     Ok(())
1189*d289c2baSAndroid Build Coastguard Worker }
1190*d289c2baSAndroid Build Coastguard Worker 
1191*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
1192*d289c2baSAndroid Build Coastguard Worker ///
1193*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
read_permanent_attributes( cert_ops: *mut AvbCertOps, attributes: *mut AvbCertPermanentAttributes, ) -> AvbIOResult1194*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn read_permanent_attributes(
1195*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1196*d289c2baSAndroid Build Coastguard Worker     attributes: *mut AvbCertPermanentAttributes,
1197*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
1198*d289c2baSAndroid Build Coastguard Worker     result_to_io_enum(
1199*d289c2baSAndroid Build Coastguard Worker         // SAFETY: see corresponding `try_*` function safety documentation.
1200*d289c2baSAndroid Build Coastguard Worker         unsafe { try_read_permanent_attributes(cert_ops, attributes) },
1201*d289c2baSAndroid Build Coastguard Worker     )
1202*d289c2baSAndroid Build Coastguard Worker }
1203*d289c2baSAndroid Build Coastguard Worker 
1204*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
1205*d289c2baSAndroid Build Coastguard Worker ///
1206*d289c2baSAndroid Build Coastguard Worker /// # Safety
1207*d289c2baSAndroid Build Coastguard Worker /// * `cert_ops` must have been created via `ScopedAvbOps`.
1208*d289c2baSAndroid Build Coastguard Worker /// * `attributes` must be a valid `AvbCertPermanentAttributes` that we have exclusive access to.
try_read_permanent_attributes( cert_ops: *mut AvbCertOps, attributes: *mut AvbCertPermanentAttributes, ) -> IoResult<()>1209*d289c2baSAndroid Build Coastguard Worker unsafe fn try_read_permanent_attributes(
1210*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1211*d289c2baSAndroid Build Coastguard Worker     attributes: *mut AvbCertPermanentAttributes,
1212*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
1213*d289c2baSAndroid Build Coastguard Worker     // SAFETY: `attributes` is a valid object provided by libavb that we have exclusive access to.
1214*d289c2baSAndroid Build Coastguard Worker     let attributes = unsafe { attributes.as_mut() }.ok_or(IoError::Io)?;
1215*d289c2baSAndroid Build Coastguard Worker 
1216*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1217*d289c2baSAndroid Build Coastguard Worker     // * we only use `cert_ops` objects created via `ScopedAvbOps` as required.
1218*d289c2baSAndroid Build Coastguard Worker     // * `cert_ops` is only extracted once and is dropped at the end of the callback.
1219*d289c2baSAndroid Build Coastguard Worker     let cert_ops = unsafe { as_cert_ops(cert_ops) }?;
1220*d289c2baSAndroid Build Coastguard Worker     cert_ops.read_permanent_attributes(attributes)
1221*d289c2baSAndroid Build Coastguard Worker }
1222*d289c2baSAndroid Build Coastguard Worker 
1223*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to raw `AvbIOResult` for libavb.
1224*d289c2baSAndroid Build Coastguard Worker ///
1225*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
read_permanent_attributes_hash( cert_ops: *mut AvbCertOps, hash: *mut u8, ) -> AvbIOResult1226*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn read_permanent_attributes_hash(
1227*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1228*d289c2baSAndroid Build Coastguard Worker     hash: *mut u8,
1229*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
1230*d289c2baSAndroid Build Coastguard Worker     result_to_io_enum(
1231*d289c2baSAndroid Build Coastguard Worker         // SAFETY: see corresponding `try_*` function safety documentation.
1232*d289c2baSAndroid Build Coastguard Worker         unsafe { try_read_permanent_attributes_hash(cert_ops, hash) },
1233*d289c2baSAndroid Build Coastguard Worker     )
1234*d289c2baSAndroid Build Coastguard Worker }
1235*d289c2baSAndroid Build Coastguard Worker 
1236*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
1237*d289c2baSAndroid Build Coastguard Worker ///
1238*d289c2baSAndroid Build Coastguard Worker /// # Safety
1239*d289c2baSAndroid Build Coastguard Worker /// * `cert_ops` must have been created via `ScopedAvbOps`.
1240*d289c2baSAndroid Build Coastguard Worker /// * `hash` must point to a valid buffer of size `SHA256_DIGEST_SIZE` that we have exclusive
1241*d289c2baSAndroid Build Coastguard Worker ///   access to.
try_read_permanent_attributes_hash( cert_ops: *mut AvbCertOps, hash: *mut u8, ) -> IoResult<()>1242*d289c2baSAndroid Build Coastguard Worker unsafe fn try_read_permanent_attributes_hash(
1243*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1244*d289c2baSAndroid Build Coastguard Worker     hash: *mut u8,
1245*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
1246*d289c2baSAndroid Build Coastguard Worker     check_nonnull(hash)?;
1247*d289c2baSAndroid Build Coastguard Worker 
1248*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1249*d289c2baSAndroid Build Coastguard Worker     // * we only use `cert_ops` objects created via `ScopedAvbOps` as required.
1250*d289c2baSAndroid Build Coastguard Worker     // * `cert_ops` is only extracted once and is dropped at the end of the callback.
1251*d289c2baSAndroid Build Coastguard Worker     let cert_ops = unsafe { as_cert_ops(cert_ops) }?;
1252*d289c2baSAndroid Build Coastguard Worker     let provided_hash = cert_ops.read_permanent_attributes_hash()?;
1253*d289c2baSAndroid Build Coastguard Worker 
1254*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1255*d289c2baSAndroid Build Coastguard Worker     // * `provided_hash` is a valid `[u8]` with size `SHA256_DIGEST_SIZE`.
1256*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `hash` with size `SHA256_DIGEST_SIZE`.
1257*d289c2baSAndroid Build Coastguard Worker     // * the arrays are independent objects and cannot overlap.
1258*d289c2baSAndroid Build Coastguard Worker     unsafe { ptr::copy_nonoverlapping(provided_hash.as_ptr(), hash, SHA256_DIGEST_SIZE) };
1259*d289c2baSAndroid Build Coastguard Worker 
1260*d289c2baSAndroid Build Coastguard Worker     Ok(())
1261*d289c2baSAndroid Build Coastguard Worker }
1262*d289c2baSAndroid Build Coastguard Worker 
1263*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to `None` for libavb.
1264*d289c2baSAndroid Build Coastguard Worker ///
1265*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
set_key_version( cert_ops: *mut AvbCertOps, rollback_index_location: usize, key_version: u64, )1266*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn set_key_version(
1267*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1268*d289c2baSAndroid Build Coastguard Worker     rollback_index_location: usize,
1269*d289c2baSAndroid Build Coastguard Worker     key_version: u64,
1270*d289c2baSAndroid Build Coastguard Worker ) {
1271*d289c2baSAndroid Build Coastguard Worker     // SAFETY: see corresponding `try_*` function safety documentation.
1272*d289c2baSAndroid Build Coastguard Worker     let result = unsafe { try_set_key_version(cert_ops, rollback_index_location, key_version) };
1273*d289c2baSAndroid Build Coastguard Worker 
1274*d289c2baSAndroid Build Coastguard Worker     // `set_key_version()` is unique in that it has no return value, and therefore cannot fail.
1275*d289c2baSAndroid Build Coastguard Worker     // However, our internal C -> Rust logic does have some potential failure points when we unwrap
1276*d289c2baSAndroid Build Coastguard Worker     // the C pointers to extract our Rust objects.
1277*d289c2baSAndroid Build Coastguard Worker     //
1278*d289c2baSAndroid Build Coastguard Worker     // Ignoring the error could be a security risk, as it would silently prevent the device from
1279*d289c2baSAndroid Build Coastguard Worker     // updating key rollback versions, so instead we panic here.
1280*d289c2baSAndroid Build Coastguard Worker     if let Err(e) = result {
1281*d289c2baSAndroid Build Coastguard Worker         panic!("Fatal error in set_key_version(): {:?}", e);
1282*d289c2baSAndroid Build Coastguard Worker     }
1283*d289c2baSAndroid Build Coastguard Worker }
1284*d289c2baSAndroid Build Coastguard Worker 
1285*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
1286*d289c2baSAndroid Build Coastguard Worker ///
1287*d289c2baSAndroid Build Coastguard Worker /// # Safety
1288*d289c2baSAndroid Build Coastguard Worker /// `cert_ops` must have been created via `ScopedAvbOps`.
try_set_key_version( cert_ops: *mut AvbCertOps, rollback_index_location: usize, key_version: u64, ) -> IoResult<()>1289*d289c2baSAndroid Build Coastguard Worker unsafe fn try_set_key_version(
1290*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1291*d289c2baSAndroid Build Coastguard Worker     rollback_index_location: usize,
1292*d289c2baSAndroid Build Coastguard Worker     key_version: u64,
1293*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
1294*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1295*d289c2baSAndroid Build Coastguard Worker     // * we only use `cert_ops` objects created via `ScopedAvbOps` as required.
1296*d289c2baSAndroid Build Coastguard Worker     // * `cert_ops` is only extracted once and is dropped at the end of the callback.
1297*d289c2baSAndroid Build Coastguard Worker     let cert_ops = unsafe { as_cert_ops(cert_ops) }?;
1298*d289c2baSAndroid Build Coastguard Worker     cert_ops.set_key_version(rollback_index_location, key_version);
1299*d289c2baSAndroid Build Coastguard Worker     Ok(())
1300*d289c2baSAndroid Build Coastguard Worker }
1301*d289c2baSAndroid Build Coastguard Worker 
1302*d289c2baSAndroid Build Coastguard Worker /// Wraps a callback to convert the given `IoResult<>` to `None` for libavb.
1303*d289c2baSAndroid Build Coastguard Worker ///
1304*d289c2baSAndroid Build Coastguard Worker /// See corresponding `try_*` function docs.
get_random( cert_ops: *mut AvbCertOps, num_bytes: usize, output: *mut u8, ) -> AvbIOResult1305*d289c2baSAndroid Build Coastguard Worker unsafe extern "C" fn get_random(
1306*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1307*d289c2baSAndroid Build Coastguard Worker     num_bytes: usize,
1308*d289c2baSAndroid Build Coastguard Worker     output: *mut u8,
1309*d289c2baSAndroid Build Coastguard Worker ) -> AvbIOResult {
1310*d289c2baSAndroid Build Coastguard Worker     result_to_io_enum(
1311*d289c2baSAndroid Build Coastguard Worker         // SAFETY: see corresponding `try_*` function safety documentation.
1312*d289c2baSAndroid Build Coastguard Worker         unsafe { try_get_random(cert_ops, num_bytes, output) },
1313*d289c2baSAndroid Build Coastguard Worker     )
1314*d289c2baSAndroid Build Coastguard Worker }
1315*d289c2baSAndroid Build Coastguard Worker 
1316*d289c2baSAndroid Build Coastguard Worker /// Bounces the C callback into the user-provided Rust implementation.
1317*d289c2baSAndroid Build Coastguard Worker ///
1318*d289c2baSAndroid Build Coastguard Worker /// # Safety
1319*d289c2baSAndroid Build Coastguard Worker /// * `cert_ops` must have been created via `ScopedAvbOps`.
1320*d289c2baSAndroid Build Coastguard Worker /// * `output` must point to a valid buffer of size `num_bytes` that we have exclusive access to.
try_get_random( cert_ops: *mut AvbCertOps, num_bytes: usize, output: *mut u8, ) -> IoResult<()>1321*d289c2baSAndroid Build Coastguard Worker unsafe fn try_get_random(
1322*d289c2baSAndroid Build Coastguard Worker     cert_ops: *mut AvbCertOps,
1323*d289c2baSAndroid Build Coastguard Worker     num_bytes: usize,
1324*d289c2baSAndroid Build Coastguard Worker     output: *mut u8,
1325*d289c2baSAndroid Build Coastguard Worker ) -> IoResult<()> {
1326*d289c2baSAndroid Build Coastguard Worker     check_nonnull(output)?;
1327*d289c2baSAndroid Build Coastguard Worker     if num_bytes == 0 {
1328*d289c2baSAndroid Build Coastguard Worker         return Ok(());
1329*d289c2baSAndroid Build Coastguard Worker     }
1330*d289c2baSAndroid Build Coastguard Worker 
1331*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1332*d289c2baSAndroid Build Coastguard Worker     // * we've checked that the pointer is non-NULL.
1333*d289c2baSAndroid Build Coastguard Worker     // * libavb gives us a properly-allocated `output` with size `num_bytes`.
1334*d289c2baSAndroid Build Coastguard Worker     // * we only access the contents via the returned slice.
1335*d289c2baSAndroid Build Coastguard Worker     // * the returned slice is not held past the scope of this callback.
1336*d289c2baSAndroid Build Coastguard Worker     let output = unsafe { slice::from_raw_parts_mut(output, num_bytes) };
1337*d289c2baSAndroid Build Coastguard Worker 
1338*d289c2baSAndroid Build Coastguard Worker     // SAFETY:
1339*d289c2baSAndroid Build Coastguard Worker     // * we only use `cert_ops` objects created via `ScopedAvbOps` as required.
1340*d289c2baSAndroid Build Coastguard Worker     // * `cert_ops` is only extracted once and is dropped at the end of the callback.
1341*d289c2baSAndroid Build Coastguard Worker     let cert_ops = unsafe { as_cert_ops(cert_ops) }?;
1342*d289c2baSAndroid Build Coastguard Worker     cert_ops.get_random(output)
1343*d289c2baSAndroid Build Coastguard Worker }
1344