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 //! hsd is abbreviation for hash signed data
17 
18 use crate::evp;
19 
20 #[derive(Debug, PartialEq)]
21 pub struct SingleSignedData {
22     name: String,
23     signature: String
24 }
25 
26 #[derive(Debug, PartialEq)]
27 pub struct HashSignedData {
28     data: Vec<SingleSignedData>
29 }
30 
31 impl TryFrom<&str> for SingleSignedData {
32     type Error = String;
try_from(value: &str) -> Result<Self, Self::Error>33     fn try_from(value: &str) -> Result<Self, Self::Error> {
34         const KEY_STR : &str = "Name:";
35         const VALUE_STR : &str = "signed-data:";
36         let res: Vec<&str> = value.split('\n').filter(|&s| !s.is_empty()).collect();
37         if res.len() != 2 || !res[0].starts_with(KEY_STR) || !res[1].starts_with(VALUE_STR) {
38             return Err(format!("format error for single signed data {}", value));
39         }
40         Ok(SingleSignedData { name: res[0][KEY_STR.len()..].trim().to_owned(),
41                 signature: res[1][VALUE_STR.len()..].trim().to_owned()})
42     }
43 }
44 
45 impl TryFrom<&str> for HashSignedData {
46     type Error = String;
try_from(value: &str) -> Result<Self, Self::Error>47     fn try_from(value: &str) -> Result<Self, Self::Error> {
48         if value.is_empty() {
49             return Err("empty value not allowed".to_string());
50         }
51         let all_hash_data: Vec<&str> = value.split("\n\n").filter(|&s| !s.is_empty()).collect();
52         let mut hash_signed_data = Vec::<SingleSignedData>::new();
53         for single_hash_data in all_hash_data {
54             hash_signed_data.push(SingleSignedData::try_from(single_hash_data)?);
55         }
56         Ok(HashSignedData { data: hash_signed_data })
57     }
58 }
59 
60 #[allow(unused)]
61 impl HashSignedData {
get_sig_for_file(&self, file_name: &str) -> Result<Vec<u8>, String>62     pub fn get_sig_for_file(&self, file_name: &str) -> Result<Vec<u8>, String>
63     {
64         match self.data.iter().find(|&single_line| single_line.name == *file_name) {
65             Some(single_data) => {
66                 let single_data = single_data.signature.as_bytes();
67                 evp::evp_decode_block(single_data)
68             },
69             None => {
70                 Err(format!("file name {} invalid, please check your input", file_name))
71             }
72         }
73     }
74 }
75