• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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::collections::HashMap;
17 use crate::updaterlog;
18 
19 const TLV_SIZE:usize = 6;
20 const HASH_INFO_SIZE: usize = 16;
21 const HASH_HEADER_SIZE: usize = 38;
22 
23 #[derive(Debug)]
24 struct HashInfo {
25     tlv_type: u16,
26     tlv_len: u32,
27     algorithm: u16,
28     algo_size: u16,
29     component_count: u16,
30     block_size: u32
31 }
32 
33 #[derive(Debug)]
34 struct HashHeader {
35     image_name: String,
36     hash_num: u16,
37     img_size: u32
38 }
39 
40 #[repr(C)]
41 #[derive(Debug)]
42 struct HashData {
43     addr_star: u32,
44     addr_end: u32,
45     hash_data: Vec<u8>
46 }
47 
48 #[derive(Debug)]
49 struct HashSign {
50     tlv_type: u16,
51     tlv_len: u32,
52     sign_data: Vec<u8>
53 }
54 
55 #[derive(Debug, PartialEq)]
56 pub struct ImgHashData {
57     data: HashMap<String, HashMap<(u32, u32), Vec<u8>>>
58 }
59 
60 trait TLVStruct {
new() -> Self61     fn new() -> Self;
62 
read_from_le_bytes(&mut self, buffer: &[u8]) -> bool63     fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool;
64 }
65 
66 impl TLVStruct for HashInfo {
new() -> HashInfo67     fn new() -> HashInfo {
68         HashInfo {tlv_type: 0, tlv_len: 0, algorithm: 0, algo_size: 0, component_count: 0, block_size: 0}
69     }
70 
read_from_le_bytes(&mut self, buffer: &[u8]) -> bool71     fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool {
72         if buffer.len() < HASH_INFO_SIZE {
73             updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len());
74             return false;
75         }
76 
77         self.tlv_type = u16::from_le_bytes(buffer[0..2].try_into().unwrap());
78         self.tlv_len = u32::from_le_bytes(buffer[2..6].try_into().unwrap());
79         self.algorithm = u16::from_le_bytes(buffer[6..8].try_into().unwrap());
80         self.algo_size = u16::from_le_bytes(buffer[8..10].try_into().unwrap());
81         self.component_count = u16::from_le_bytes(buffer[10..12].try_into().unwrap());
82         self.block_size = u32::from_le_bytes(buffer[12..16].try_into().unwrap());
83         true
84     }
85 }
86 
87 impl TLVStruct for HashHeader {
new() -> HashHeader88     fn new() -> HashHeader {
89         HashHeader {image_name: String::new(), hash_num: 0, img_size: 0}
90     }
91 
read_from_le_bytes(&mut self, buffer: &[u8]) -> bool92     fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool {
93         if buffer.len() < TLV_SIZE {
94             updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len());
95             return false;
96         }
97 
98         self.image_name = String::from_utf8(Vec::from(&buffer[0..32])).unwrap().trim_end_matches('\0').to_owned();
99         updaterlog!(INFO, "HashHeader  read_from_le_bytes image_name {}", self.image_name);
100         self.hash_num = u16::from_le_bytes(buffer[32..34].try_into().unwrap());
101         self.img_size = u32::from_le_bytes(buffer[34..].try_into().unwrap());
102         true
103     }
104 }
105 
106 impl TLVStruct for HashData {
new() -> HashData107     fn new() -> HashData {
108         HashData {addr_star: 0, addr_end: 0, hash_data: vec![]}
109     }
110 
read_from_le_bytes(&mut self, buffer: &[u8]) -> bool111     fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool {
112         if buffer.len() < TLV_SIZE {
113             updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len());
114             return false;
115         }
116 
117         self.addr_star = u32::from_le_bytes(buffer[0..4].try_into().unwrap());
118         self.addr_end = u32::from_le_bytes(buffer[4..8].try_into().unwrap());
119         self.hash_data = Vec::from(&buffer[8..]);
120         true
121     }
122 }
123 
124 impl TLVStruct for HashSign {
new() -> HashSign125     fn new() -> HashSign {
126         HashSign {tlv_type: 0, tlv_len: 0, sign_data: vec![]}
127     }
128 
read_from_le_bytes(&mut self, buffer: &[u8]) -> bool129     fn read_from_le_bytes(&mut self, buffer: &[u8]) -> bool {
130         if buffer.len() < TLV_SIZE {
131             updaterlog!(ERROR, "{} buffer is too small. {}", line!(), buffer.len());
132             return false;
133         }
134 
135         self.tlv_type = u16::from_le_bytes(buffer[0..2].try_into().unwrap());
136         self.tlv_len = u32::from_le_bytes(buffer[2..6].try_into().unwrap());
137         self.sign_data = Vec::from(&buffer[6..]);
138         true
139     }
140 }
141 
142 #[allow(unused)]
143 impl ImgHashData {
load_img_hash_data(buffer: &[u8]) -> Result<Self, String>144     pub fn load_img_hash_data(buffer: &[u8]) -> Result<Self, String> {
145         let mut offset = 0usize;
146         let mut hash_info = HashInfo::new();
147         hash_info.read_from_le_bytes( &buffer[..HASH_INFO_SIZE]);
148 
149         offset = HASH_INFO_SIZE + 2;
150         let hash_data_len = u32::from_le_bytes(buffer[offset..4 + offset].try_into().unwrap());
151 
152         offset += 4;
153         if buffer.len() < hash_data_len as usize {
154             return Err(format!("{} buffer is too small. {}", line!(), buffer.len()));
155         }
156 
157         let mut hash_data_map: HashMap<String, HashMap<(u32, u32), Vec<u8>>> = HashMap::new();
158         while offset < hash_data_len as usize {
159             let mut hash_header = HashHeader::new();
160             hash_header.read_from_le_bytes(&buffer[offset..(HASH_HEADER_SIZE + offset)]);
161             offset += HASH_HEADER_SIZE;
162 
163             let mut single_data: HashMap<(u32, u32), Vec<u8>> = HashMap::new();
164             for i in 0..hash_header.hash_num {
165                 let mut hash_data = HashData::new();
166                 hash_data.read_from_le_bytes(&buffer[offset.. (offset + 8 + hash_info.algo_size as usize)]);
167                 single_data.insert((hash_data.addr_star, hash_data.addr_end), hash_data.hash_data);
168                 offset += (8 + hash_info.algo_size) as usize;
169             }
170             hash_data_map.insert(hash_header.image_name, single_data);
171         }
172         Ok(ImgHashData { data: hash_data_map })
173     }
174 
check_img_hash(&self, img_name: String, start: u32, end: u32, hash_value: &[u8]) -> bool175     pub fn check_img_hash(&self, img_name: String, start: u32, end: u32, hash_value: &[u8]) -> bool
176     {
177         let img_hash_map = match self.data.get(&img_name) {
178             Some(img_hash_map)=> img_hash_map,
179             _ => {
180                 updaterlog!(ERROR, "nothing found {}", img_name);
181                 return false;
182             }
183         };
184 
185         let hash_data = match img_hash_map.get(&(start, end)) {
186             Some(hash_data)=> hash_data,
187             _ => {
188                 updaterlog!(ERROR, "nothing found start: {}, end: {}", start, end);
189                 return false;
190             }
191         };
192 
193         if hash_data.len() != hash_value.len() {
194             updaterlog!(ERROR, "hash value len is invalid {}", hash_value.len());
195             return false;
196         }
197 
198         for i in 0..hash_data.len() {
199             if hash_data[i] != hash_value[i] {
200                 updaterlog!(ERROR, "hash value check fail");
201                 return false;
202             }
203         }
204         true
205     }
206 }
207