1 // Copyright (C) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 use std::sync::{Arc, RwLock};
15 use std::time::Duration;
16
17 use ylong_http_client::Certificate;
18
19 use crate::utils::runtime_spawn;
20
21 const UPDATE_SYSTEM_CERT_INTERVAL_IN_SECS: u64 = 60 * 60;
22
23 #[derive(Clone)]
24 pub(crate) struct CertManager {
25 info: Arc<RwLock<CertInfo>>,
26 }
27
28 impl CertManager {
init() -> Self29 pub(crate) fn init() -> Self {
30 let info = Arc::new(RwLock::new(CertInfo::default()));
31 runtime_spawn(run(info.clone()));
32 Self { info }
33 }
34
certificate(&self) -> Option<Vec<Certificate>>35 pub(crate) fn certificate(&self) -> Option<Vec<Certificate>> {
36 self.info.read().unwrap().cert.clone()
37 }
38
force_update(&self)39 pub(crate) fn force_update(&self) {
40 update_system_cert(&self.info);
41 }
42 }
43
44 #[derive(Default)]
45 struct CertInfo {
46 cert: Option<Vec<Certificate>>,
47 }
48
run(info: Arc<RwLock<CertInfo>>)49 async fn run(info: Arc<RwLock<CertInfo>>) {
50 loop {
51 update_system_cert(&info);
52 ylong_runtime::time::sleep(Duration::from_secs(UPDATE_SYSTEM_CERT_INTERVAL_IN_SECS)).await;
53 }
54 }
55
56 // Try use `async` func to read file.
update_system_cert(info: &Arc<RwLock<CertInfo>>)57 fn update_system_cert(info: &Arc<RwLock<CertInfo>>) {
58 let mut info = info.write().unwrap();
59
60 let mut certificates = Vec::new();
61
62 let c_certs_ptr = unsafe { GetUserCertsData() };
63 if !c_certs_ptr.is_null() {
64 info!("GetUserCertsData valid");
65 let certs = unsafe { &*c_certs_ptr };
66 let c_cert_list_ptr =
67 unsafe { std::slice::from_raw_parts(certs.cert_data_list, certs.len as usize) };
68 for item in c_cert_list_ptr.iter() {
69 let cert = unsafe { &**item };
70 let cert_slice = unsafe { std::slice::from_raw_parts(cert.data, cert.size as usize) };
71 match Certificate::from_pem(cert_slice) {
72 Ok(cert) => {
73 certificates.push(cert);
74 }
75 Err(e) => {
76 error!("parse security cert path failed, error is {:?}", e);
77 return;
78 }
79 };
80 }
81 unsafe { FreeCertDataList(c_certs_ptr) };
82 }
83
84 match Certificate::from_path("/system/etc/security/certificates/") {
85 Ok(cert) => {
86 certificates.push(cert);
87 }
88 Err(e) => {
89 error!("parse security cert path failed, error is {:?}", e);
90 return;
91 }
92 };
93
94 *info = CertInfo {
95 cert: Some(certificates),
96 };
97 }
98
99 #[cfg(feature = "oh")]
100 extern "C" {
GetUserCertsData() -> *const CRequestCerts101 pub(crate) fn GetUserCertsData() -> *const CRequestCerts;
FreeCertDataList(certs: *const CRequestCerts)102 pub(crate) fn FreeCertDataList(certs: *const CRequestCerts);
103 }
104
105 #[repr(C)]
106 pub(crate) struct CRequestCert {
107 pub(crate) size: u32,
108 pub(crate) data: *const u8,
109 }
110
111 #[repr(C)]
112 pub(crate) struct CRequestCerts {
113 pub(crate) cert_data_list: *const *const CRequestCert,
114 pub(crate) len: u32,
115 }
116
117 #[cfg(feature = "oh")]
118 #[cfg(test)]
119 mod test {
120 use super::*;
121 use crate::tests::test_init;
122
123 #[test]
test_cert_manager()124 fn test_cert_manager() {
125 test_init();
126 let cert_manager = CertManager::init();
127 let cert = cert_manager.certificate();
128 if cert.is_none() {
129 cert_manager.force_update();
130 }
131 assert!(cert_manager.certificate().is_some());
132 }
133 }
134