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, AvbDescriptorTag, 18 AvbHashtreeDescriptor, 19 }; 20 use std::ffi::c_void; 21 use std::mem::{size_of, MaybeUninit}; 22 use std::slice; 23 24 use super::VbMetaImageParseError; 25 26 /// The descriptors from a VBMeta image. 27 pub struct Descriptors<'a> { 28 descriptors: Vec<Descriptor<'a>>, 29 } 30 31 /// Enumeration of the possible descriptors. 32 #[allow(missing_docs)] 33 pub enum Descriptor<'a> { 34 Property(&'a [u8]), 35 Hashtree(&'a [u8]), 36 Hash(&'a [u8]), 37 KernelCmdline(&'a [u8]), 38 ChainPartition(&'a [u8]), 39 Unknown, 40 } 41 42 /// A hashtree descriptor. 43 pub struct HashtreeDescriptor<'a> { 44 descriptor: AvbHashtreeDescriptor, 45 data: &'a [u8], 46 } 47 48 impl Descriptors<'_> { 49 /// Find the descriptors in a well-formed VBMeta image. from_image(data: &[u8]) -> Result<Descriptors<'_>, VbMetaImageParseError>50 pub(super) fn from_image(data: &[u8]) -> Result<Descriptors<'_>, VbMetaImageParseError> { 51 extern "C" fn desc_cb(descriptor: *const AvbDescriptor, user_data: *mut c_void) -> bool { 52 // SAFETY: libavb gives a good pointer for us to work with. 53 let desc = unsafe { 54 let mut desc = MaybeUninit::uninit(); 55 if !avb_descriptor_validate_and_byteswap(descriptor, desc.as_mut_ptr()) { 56 return false; 57 } 58 desc.assume_init() 59 }; 60 // SAFETY: the descriptor has been validated so it is contained within the image. 61 let data = unsafe { 62 slice::from_raw_parts( 63 descriptor as *const _ as *const u8, 64 size_of::<AvbDescriptor>() + desc.num_bytes_following as usize, 65 ) 66 }; 67 // SAFETY: this cast gets a reference to the Vec passed as the user_data below. 68 let descriptors = unsafe { &mut *(user_data as *mut Vec<Descriptor>) }; 69 descriptors.push(match desc.tag.try_into() { 70 Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_PROPERTY) => Descriptor::Property(data), 71 Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_HASHTREE) => Descriptor::Hashtree(data), 72 Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_HASH) => Descriptor::Hash(data), 73 Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_KERNEL_CMDLINE) => { 74 Descriptor::KernelCmdline(data) 75 } 76 Ok(AvbDescriptorTag::AVB_DESCRIPTOR_TAG_CHAIN_PARTITION) => { 77 Descriptor::ChainPartition(data) 78 } 79 _ => Descriptor::Unknown, 80 }); 81 true 82 } 83 84 let mut descriptors = Vec::new(); 85 // SAFETY: the function only reads from the provided data and passes the Vec pointer to the 86 // callback function, treating it as an opaque handle. The descriptors added to the Vec are 87 // contained within the provided data so the lifetime is bound accordingly. 88 if unsafe { 89 let desc = &mut descriptors as *mut _ as *mut c_void; 90 avb_descriptor_foreach(data.as_ptr(), data.len(), Some(desc_cb), desc) 91 } { 92 Ok(Descriptors { descriptors }) 93 } else { 94 Err(VbMetaImageParseError::InvalidDescriptor) 95 } 96 } 97 98 /// Get an iterator over the descriptors. iter(&self) -> slice::Iter<Descriptor>99 pub fn iter(&self) -> slice::Iter<Descriptor> { 100 self.descriptors.iter() 101 } 102 } 103 104 impl<'a> IntoIterator for Descriptors<'a> { 105 type Item = Descriptor<'a>; 106 type IntoIter = std::vec::IntoIter<Self::Item>; 107 into_iter(self) -> Self::IntoIter108 fn into_iter(self) -> Self::IntoIter { 109 self.descriptors.into_iter() 110 } 111 } 112 113 impl Descriptor<'_> { 114 /// Parse the descriptor as a hashtree descriptor. to_hashtree(&self) -> Result<HashtreeDescriptor, VbMetaImageParseError>115 pub fn to_hashtree(&self) -> Result<HashtreeDescriptor, VbMetaImageParseError> { 116 match self { 117 Self::Hashtree(data) => { 118 // SAFETY: data contains the entire descriptor. 119 let descriptor = unsafe { 120 let mut desc = MaybeUninit::uninit(); 121 let src = data.as_ptr() as *const _ as *const AvbHashtreeDescriptor; 122 if !avb_hashtree_descriptor_validate_and_byteswap(src, desc.as_mut_ptr()) { 123 return Err(VbMetaImageParseError::InvalidDescriptor); 124 } 125 desc.assume_init() 126 }; 127 Ok(HashtreeDescriptor { descriptor, data }) 128 } 129 _ => Err(VbMetaImageParseError::InvalidDescriptor), 130 } 131 } 132 133 // TODO: handle other descriptor type as required 134 } 135 136 impl HashtreeDescriptor<'_> { 137 /// Get the root digest of the hashtree. root_digest(&self) -> &[u8]138 pub fn root_digest(&self) -> &[u8] { 139 let begin = size_of::<AvbHashtreeDescriptor>() 140 + self.descriptor.partition_name_len as usize 141 + self.descriptor.salt_len as usize; 142 let end = begin + self.descriptor.root_digest_len as usize; 143 &self.data[begin..end] 144 } 145 146 // TODO: expose other fields as required 147 } 148