1 /* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 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 16 use std::default::Default; 17 use std::collections::HashMap; 18 use std::hash::Hash; 19 use std::cmp::Eq; 20 use std::cmp::PartialEq; 21 use std::mem::size_of; 22 use crate::updaterlog; 23 24 const TLV_SIZE: usize = 6; 25 const HASH_INFO_SIZE: usize = 16; 26 const IMG_NAME_SIZE: usize = 32; 27 28 #[derive(Debug)] 29 struct HashInfo { 30 tlv_type: u16, 31 tlv_len: u32, 32 algorithm: u16, 33 algo_size: u16, 34 component_count: u16, 35 block_size: u32 36 } 37 38 pub trait ReadLeBytes { read_le_bytes(buffer: &[u8]) -> Self39 fn read_le_bytes(buffer: &[u8]) -> Self; 40 } 41 42 impl ReadLeBytes for u32 { read_le_bytes(buffer: &[u8]) -> Self43 fn read_le_bytes(buffer: &[u8]) -> Self { 44 u32::from_le_bytes(buffer[..].try_into().unwrap()) 45 } 46 } 47 48 impl ReadLeBytes for u64 { read_le_bytes(buffer: &[u8]) -> Self49 fn read_le_bytes(buffer: &[u8]) -> Self { 50 u64::from_le_bytes(buffer[..].try_into().unwrap()) 51 } 52 } 53 54 #[derive(Debug)] 55 struct HashHeader<T: ReadLeBytes> { 56 image_name: String, 57 hash_num: u16, 58 img_size: T 59 } 60 61 #[repr(C)] 62 #[derive(Debug)] 63 struct HashData<T: ReadLeBytes> { 64 addr_star: T, 65 addr_end: T, 66 hash_data: Vec<u8> 67 } 68 69 #[derive(Debug)] 70 struct HashSign { 71 tlv_type: u16, 72 tlv_len: u32, 73 sign_data: Vec<u8> 74 } 75 76 #[derive(Hash, Eq, PartialEq, Debug)] 77 struct Tuple<T> (T, T); 78 79 /// PartialEq 80 #[derive(Debug)] 81 pub struct ImgHashData<T: Hash + Eq + PartialEq> { 82 data: HashMap<String, HashMap<Tuple<T>, Vec<u8>>> 83 } 84 85 trait TLVStruct { new() -> Self86 fn new() -> Self; 87 read_from_le_bytes(&mut self, buffer: &[u8]) -> bool88 fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool; 89 } 90 91 impl TLVStruct for HashInfo { new() -> HashInfo92 fn new() -> HashInfo { 93 HashInfo {tlv_type: 0, tlv_len: 0, algorithm: 0, algo_size: 0, component_count: 0, block_size: 0} 94 } 95 read_from_le_bytes(&mut self, buffer: &[u8]) -> bool96 fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool { 97 if buffer.len() < HASH_INFO_SIZE { 98 updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len()); 99 return false; 100 } 101 102 self.tlv_type = u16::from_le_bytes(buffer[0..2].try_into().unwrap()); 103 self.tlv_len = u32::from_le_bytes(buffer[2..6].try_into().unwrap()); 104 self.algorithm = u16::from_le_bytes(buffer[6..8].try_into().unwrap()); 105 self.algo_size = u16::from_le_bytes(buffer[8..10].try_into().unwrap()); 106 self.component_count = u16::from_le_bytes(buffer[10..12].try_into().unwrap()); 107 self.block_size = u32::from_le_bytes(buffer[12..16].try_into().unwrap()); 108 true 109 } 110 } 111 112 impl<T: Default + ReadLeBytes> TLVStruct for HashHeader<T> { new() -> HashHeader<T>113 fn new() -> HashHeader<T> { 114 HashHeader {image_name: String::new(), hash_num: 0, img_size: Default::default()} 115 } 116 read_from_le_bytes(&mut self, buffer: &[u8]) -> bool117 fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool { 118 if buffer.len() < TLV_SIZE { 119 updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len()); 120 return false; 121 } 122 123 self.image_name = String::from_utf8(Vec::from(&buffer[0..32])).unwrap().trim_end_matches('\0').to_owned(); 124 updaterlog!(INFO, "HashHeader read_from_le_bytes image_name {}", self.image_name); 125 self.hash_num = u16::from_le_bytes(buffer[32..34].try_into().unwrap()); 126 self.img_size = T::read_le_bytes(&buffer[34..]); 127 true 128 } 129 } 130 131 impl<T: Default + ReadLeBytes> TLVStruct for HashData<T> { new() -> HashData<T>132 fn new() -> HashData<T> { 133 HashData {addr_star: Default::default(), addr_end: Default::default(), hash_data: vec![]} 134 } 135 read_from_le_bytes(&mut self, buffer: &[u8]) -> bool136 fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool { 137 if buffer.len() < TLV_SIZE { 138 updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len()); 139 return false; 140 } 141 142 self.addr_star = T::read_le_bytes(&buffer[0..size_of::<T>()]); 143 self.addr_end = T::read_le_bytes(&buffer[size_of::<T>()..(2*size_of::<T>())]); 144 self.hash_data = Vec::from(&buffer[(2*size_of::<T>())..]); 145 true 146 } 147 } 148 149 impl TLVStruct for HashSign { new() -> HashSign150 fn new() -> HashSign { 151 HashSign {tlv_type: 0, tlv_len: 0, sign_data: vec![]} 152 } 153 read_from_le_bytes(&mut self, buffer: &[u8]) -> bool154 fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool { 155 if buffer.len() < TLV_SIZE { 156 updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len()); 157 return false; 158 } 159 160 self.tlv_type = u16::from_le_bytes(buffer[0..2].try_into().unwrap()); 161 self.tlv_len = u32::from_le_bytes(buffer[2..6].try_into().unwrap()); 162 self.sign_data = Vec::from(&buffer[6..]); 163 true 164 } 165 } 166 167 #[allow(unused)] 168 impl<T: Default + ReadLeBytes + Hash + Eq + PartialEq> ImgHashData<T> { load_img_hash_data(buffer: &[u8]) -> Result<Self, String>169 pub fn load_img_hash_data(buffer: &[u8]) -> Result<Self, String> { 170 let mut offset = 0usize; 171 let mut hash_info = HashInfo::new(); 172 hash_info.read_from_le_bytes( &buffer[..HASH_INFO_SIZE]); 173 174 offset = HASH_INFO_SIZE + 2; 175 let hash_data_len = u32::from_le_bytes(buffer[offset..4 + offset].try_into().unwrap()); 176 177 offset += 4; 178 if buffer.len() < hash_data_len as usize { 179 return Err(format!("{} buffer is too small. {}", line!(), buffer.len())); 180 } 181 182 let mut hash_data_map: HashMap<String, HashMap<Tuple<T>, Vec<u8>>> = HashMap::new(); 183 let hash_header_size: usize = IMG_NAME_SIZE + size_of::<u16>() + size_of::<T>(); 184 updaterlog!(INFO, "HashHeader read_from_le_bytes hash_header_size {}", hash_header_size); 185 while offset < hash_data_len as usize { 186 let mut hash_header: HashHeader<T> = HashHeader::new(); 187 hash_header.read_from_le_bytes(&buffer[offset..(hash_header_size + offset)]); 188 offset += hash_header_size; 189 190 let mut single_data: HashMap<Tuple<T>, Vec<u8>> = HashMap::new(); 191 for i in 0..hash_header.hash_num { 192 let mut hash_data = HashData::new(); 193 hash_data.read_from_le_bytes(&buffer[offset.. (offset + (2*size_of::<T>()) + hash_info.algo_size as usize)]); 194 let mut addr_tuple = Tuple(hash_data.addr_star, hash_data.addr_end); 195 single_data.insert(addr_tuple, hash_data.hash_data); 196 offset += 2*size_of::<T>() + (hash_info.algo_size) as usize; 197 } 198 hash_data_map.insert(hash_header.image_name, single_data); 199 } 200 Ok(ImgHashData { data: hash_data_map }) 201 } 202 check_img_hash(&self, img_name: String, start: T, end: T, hash_value: &[u8]) -> bool where T: std::cmp::Eq, T: std::cmp::PartialEq, T: std::fmt::Display203 pub fn check_img_hash(&self, img_name: String, start: T, end: T, hash_value: &[u8]) -> bool 204 where T: std::cmp::Eq, T: std::cmp::PartialEq, T: std::fmt::Display 205 { 206 let img_hash_map = match self.data.get(&img_name) { 207 Some(img_hash_map)=> img_hash_map, 208 _ => { 209 updaterlog!(ERROR, "nothing found {}", img_name); 210 return false; 211 } 212 }; 213 214 let mut addr_tuple = Tuple(start, end); 215 let hash_data = match img_hash_map.get(&addr_tuple) { 216 Some(hash_data)=> hash_data, 217 _ => { 218 updaterlog!(ERROR, "nothing found start: {}, end: {}", addr_tuple.0, addr_tuple.1); 219 return false; 220 } 221 }; 222 223 if hash_data.len() != hash_value.len() { 224 updaterlog!(ERROR, "hash value len is invalid {}", hash_value.len()); 225 return false; 226 } 227 228 for i in 0..hash_data.len() { 229 if hash_data[i] != hash_value[i] { 230 updaterlog!(ERROR, "hash value check fail"); 231 return false; 232 } 233 } 234 true 235 } 236 } 237