1 // Copyright 2022, The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 use avb_bindgen::{ 16 avb_descriptor_foreach, avb_descriptor_validate_and_byteswap, 17 avb_hashtree_descriptor_validate_and_byteswap, AvbDescriptor, AvbHashtreeDescriptor, 18 }; 19 use std::ffi::c_void; 20 use std::mem::{size_of, MaybeUninit}; 21 use std::slice; 22 23 use super::VbMetaImageParseError; 24 25 // TODO: import these with bindgen 26 const AVB_DESCRIPTOR_TAG_PROPERTY: u64 = 0; 27 const AVB_DESCRIPTOR_TAG_HASHTREE: u64 = 1; 28 const AVB_DESCRIPTOR_TAG_HASH: u64 = 2; 29 const AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE: u64 = 3; 30 const AVB_DESCRIPTOR_TAG_CHAIN_PARTITION: u64 = 4; 31 32 /// The descriptors from a VBMeta image. 33 pub struct Descriptors<'a> { 34 descriptors: Vec<Descriptor<'a>>, 35 } 36 37 /// Enumeration of the possible descriptors. 38 #[allow(missing_docs)] 39 pub enum Descriptor<'a> { 40 Property(&'a [u8]), 41 Hashtree(&'a [u8]), 42 Hash(&'a [u8]), 43 KernelCmdline(&'a [u8]), 44 ChainPartition(&'a [u8]), 45 Unknown, 46 } 47 48 /// A hashtree descriptor. 49 pub struct HashtreeDescriptor<'a> { 50 descriptor: AvbHashtreeDescriptor, 51 data: &'a [u8], 52 } 53 54 impl Descriptors<'_> { 55 /// Find the descriptors in a well-formed VBMeta image. from_image(data: &[u8]) -> Result<Descriptors<'_>, VbMetaImageParseError>56 pub(super) fn from_image(data: &[u8]) -> Result<Descriptors<'_>, VbMetaImageParseError> { 57 extern "C" fn desc_cb(descriptor: *const AvbDescriptor, user_data: *mut c_void) -> bool { 58 // SAFETY: libavb gives a good pointer for us to work with. 59 let desc = unsafe { 60 let mut desc = MaybeUninit::uninit(); 61 if !avb_descriptor_validate_and_byteswap(descriptor, desc.as_mut_ptr()) { 62 return false; 63 } 64 desc.assume_init() 65 }; 66 // SAFETY: the descriptor has been validated so it is contained within the image. 67 let data = unsafe { 68 slice::from_raw_parts( 69 descriptor as *const _ as *const u8, 70 size_of::<AvbDescriptor>() + desc.num_bytes_following as usize, 71 ) 72 }; 73 // SAFETY: this cast gets a reference to the Vec passed as the user_data below. 74 let descriptors = unsafe { &mut *(user_data as *mut Vec<Descriptor>) }; 75 descriptors.push(match desc.tag { 76 AVB_DESCRIPTOR_TAG_PROPERTY => Descriptor::Property(data), 77 AVB_DESCRIPTOR_TAG_HASHTREE => Descriptor::Hashtree(data), 78 AVB_DESCRIPTOR_TAG_HASH => Descriptor::Hash(data), 79 AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE => Descriptor::KernelCmdline(data), 80 AVB_DESCRIPTOR_TAG_CHAIN_PARTITION => Descriptor::ChainPartition(data), 81 _ => Descriptor::Unknown, 82 }); 83 true 84 } 85 86 let mut descriptors = Vec::new(); 87 // SAFETY: the function only reads from the provided data and passes the Vec pointer to the 88 // callback function, treating it as an opaque handle. The descriptors added to the Vec are 89 // contained within the provided data so the lifetime is bound accordingly. 90 if unsafe { 91 let desc = &mut descriptors as *mut _ as *mut c_void; 92 avb_descriptor_foreach(data.as_ptr(), data.len(), Some(desc_cb), desc) 93 } { 94 Ok(Descriptors { descriptors }) 95 } else { 96 Err(VbMetaImageParseError::InvalidDescriptor) 97 } 98 } 99 100 /// Get an iterator over the descriptors. iter(&self) -> slice::Iter<Descriptor>101 pub fn iter(&self) -> slice::Iter<Descriptor> { 102 self.descriptors.iter() 103 } 104 } 105 106 impl<'a> IntoIterator for Descriptors<'a> { 107 type Item = Descriptor<'a>; 108 type IntoIter = std::vec::IntoIter<Self::Item>; 109 into_iter(self) -> Self::IntoIter110 fn into_iter(self) -> Self::IntoIter { 111 self.descriptors.into_iter() 112 } 113 } 114 115 impl Descriptor<'_> { 116 /// Parse the descriptor as a hashtree descriptor. to_hashtree(&self) -> Result<HashtreeDescriptor, VbMetaImageParseError>117 pub fn to_hashtree(&self) -> Result<HashtreeDescriptor, VbMetaImageParseError> { 118 match self { 119 Self::Hashtree(data) => { 120 // SAFETY: data contains the entire descriptor. 121 let descriptor = unsafe { 122 let mut desc = MaybeUninit::uninit(); 123 let src = data.as_ptr() as *const _ as *const AvbHashtreeDescriptor; 124 if !avb_hashtree_descriptor_validate_and_byteswap(src, desc.as_mut_ptr()) { 125 return Err(VbMetaImageParseError::InvalidDescriptor); 126 } 127 desc.assume_init() 128 }; 129 Ok(HashtreeDescriptor { descriptor, data }) 130 } 131 _ => Err(VbMetaImageParseError::InvalidDescriptor), 132 } 133 } 134 135 // TODO: handle other descriptor type as required 136 } 137 138 impl HashtreeDescriptor<'_> { 139 /// Get the root digest of the hashtree. root_digest(&self) -> &[u8]140 pub fn root_digest(&self) -> &[u8] { 141 let begin = size_of::<AvbHashtreeDescriptor>() 142 + self.descriptor.partition_name_len as usize 143 + self.descriptor.salt_len as usize; 144 let end = begin + self.descriptor.root_digest_len as usize; 145 &self.data[begin..end] 146 } 147 148 // TODO: expose other fields as required 149 } 150