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 use hilog_rust::{error, hilog, HiLogLabel, LogType};
16 use openssl::x509::store::{X509Store, X509StoreBuilder};
17 use openssl::x509::X509PurposeId;
18 use openssl::x509::verify::X509VerifyFlags;
19 use openssl::x509::X509;
20 use std::ffi::{c_char, CString};
21 use ylong_json::JsonValue;
22 
23 const LOG_LABEL: HiLogLabel = HiLogLabel {
24     log_type: LogType::LogCore,
25     domain: 0xd005a06,
26     tag: "CODE_SIGN",
27 };
28 /// collection to contain pem data
29 pub struct PemCollection {
30     /// vector to store pem data
31     pub pem_data: Vec<String>,
32 }
33 impl Default for PemCollection {
default() -> Self34     fn default() -> Self {
35         Self::new()
36     }
37 }
38 impl PemCollection {
39     /// init object
new() -> Self40     pub fn new() -> Self {
41         PemCollection {
42             pem_data: Vec::new(),
43         }
44     }
45     /// add pem string into self.pem_data
add(&mut self, data: String)46     pub fn add(&mut self, data: String) {
47         self.pem_data.push(data);
48     }
pem_to_x509(&self, pem: &str) -> Result<X509, openssl::error::ErrorStack>49     fn pem_to_x509(&self, pem: &str) -> Result<X509, openssl::error::ErrorStack> {
50         X509::from_pem(pem.as_bytes())
51     }
52     /// convert pem data to X509 object
to_x509(&self) -> Result<Vec<X509>, openssl::error::ErrorStack>53     pub fn to_x509(&self) -> Result<Vec<X509>, openssl::error::ErrorStack> {
54         self.pem_data
55             .iter()
56             .map(|pem| self.pem_to_x509(pem))
57             .collect()
58     }
59     /// convert pem data to X509 store
to_x509_store(&self) -> Result<X509Store, openssl::error::ErrorStack>60     pub fn to_x509_store(&self) -> Result<X509Store, openssl::error::ErrorStack> {
61         let x509_certs = self.to_x509()?;
62         let mut store_builder = X509StoreBuilder::new()?;
63         for cert in x509_certs {
64             store_builder.add_cert(cert).unwrap();
65         }
66         store_builder.set_flags(X509VerifyFlags::NO_CHECK_TIME)?;
67         store_builder.set_purpose(X509PurposeId::ANY)?;
68         Ok(store_builder.build())
69     }
70     /// convert pem data to der data
to_der(&self) -> Result<Vec<Vec<u8>>, openssl::error::ErrorStack>71     pub fn to_der(&self) -> Result<Vec<Vec<u8>>, openssl::error::ErrorStack> {
72         let x509_certs = self.to_x509()?;
73         x509_certs.iter().map(|cert| cert.to_der()).collect()
74     }
75     /// load pem certs from json file
load_pem_certs_from_json_file( &mut self, file_path: &str, member_names: &[&str] )76     pub fn load_pem_certs_from_json_file(
77         &mut self,
78         file_path: &str,
79         member_names: &[&str]
80     ) {
81         let value = match JsonValue::from_file(file_path) {
82             Ok(v) => v,
83             Err(e) => {
84                 error!(
85                     LOG_LABEL,
86                     "Error loading JSON from file {}: {}", file_path, e
87                 );
88                 return;
89             }
90         };
91         for &subject in member_names.iter() {
92             if let Ok(cert_str) = value[subject].try_as_string() {
93                 self.add(cert_str.to_string());
94             }
95         }
96     }
97 }
98 
99