blob: caf1356ac7438757d7534425e7606a53725e1ca8 [file] [log] [blame]
Andrew Scull38127252022-06-13 13:11:00 +00001// 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
15use avb_bindgen::{
16 avb_descriptor_foreach, avb_descriptor_validate_and_byteswap,
Alice Wangb2de8c32023-05-17 08:10:52 +000017 avb_hashtree_descriptor_validate_and_byteswap, AvbDescriptor, AvbDescriptorTag,
18 AvbHashtreeDescriptor,
Andrew Scull38127252022-06-13 13:11:00 +000019};
20use std::ffi::c_void;
21use std::mem::{size_of, MaybeUninit};
22use std::slice;
23
24use super::VbMetaImageParseError;
25
Andrew Scull38127252022-06-13 13:11:00 +000026/// The descriptors from a VBMeta image.
27pub struct Descriptors<'a> {
28 descriptors: Vec<Descriptor<'a>>,
29}
30
31/// Enumeration of the possible descriptors.
32#[allow(missing_docs)]
33pub 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.
43pub struct HashtreeDescriptor<'a> {
44 descriptor: AvbHashtreeDescriptor,
45 data: &'a [u8],
46}
47
48impl Descriptors<'_> {
49 /// Find the descriptors in a well-formed VBMeta image.
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>) };
Alice Wangb2de8c32023-05-17 08:10:52 +000069 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 }
Andrew Scull38127252022-06-13 13:11:00 +000079 _ => 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.
99 pub fn iter(&self) -> slice::Iter<Descriptor> {
100 self.descriptors.iter()
101 }
102}
103
104impl<'a> IntoIterator for Descriptors<'a> {
105 type Item = Descriptor<'a>;
106 type IntoIter = std::vec::IntoIter<Self::Item>;
107
108 fn into_iter(self) -> Self::IntoIter {
109 self.descriptors.into_iter()
110 }
111}
112
113impl Descriptor<'_> {
114 /// Parse the descriptor as a hashtree descriptor.
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
136impl HashtreeDescriptor<'_> {
137 /// Get the root digest of the hashtree.
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}