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