1 /*
2  * Copyright (c) 2023-2024 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 lazy_static::lazy_static;
17 use super::cert_chain_utils::PemCollection;
18 use super::cert_path_utils::{
19     add_cert_path_info, remove_cert_path_info, common_format_fabricate_name,
20     DebugCertPathType, ReleaseCertPathType, TrustCertPath,
21 };
22 use super::cs_hisysevent::report_parse_profile_err;
23 use super::file_utils::{
24     create_file_path, delete_file_path, file_exists, fmt_store_path,
25     load_bytes_from_file, write_bytes_to_file, change_default_mode_file, change_default_mode_directory
26 };
27 use hilog_rust::{error, info, hilog, HiLogLabel, LogType};
28 use openssl::pkcs7::{Pkcs7, Pkcs7Flags};
29 use openssl::stack::Stack;
30 use openssl::x509::store::{X509Store, X509StoreBuilder};
31 use openssl::x509::{X509NameRef, X509};
32 use std::error::Error;
33 use std::ffi::{c_char, CStr, CString};
34 use std::fs::read_dir;
35 use ylong_json::JsonValue;
36 
37 const ERROR_CODE: i32 = -1;
38 const SUCCESS_CODE: i32 = 0;
39 const LOG_LABEL: HiLogLabel = HiLogLabel {
40     log_type: LogType::LogCore,
41     domain: 0xd005a06, // security domain
42     tag: "CODE_SIGN",
43 };
44 const PROFILE_STORE_EL0_PREFIX: &str = "/data/service/el0/profiles/developer";
45 const PROFILE_STORE_EL1_PREFIX: &str = "/data/service/el1/profiles/release";
46 const PROFILE_STORE_EL1_PUBLIC_PREFIX: &str = "/data/service/el1/public/profiles/release";
47 const DEBUG_PROFILE_STORE_EL0_PREFIX: &str = "/data/service/el0/profiles/debug";
48 const DEBUG_PROFILE_STORE_EL1_PREFIX: &str = "/data/service/el1/profiles/debug";
49 const DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX: &str = "/data/service/el1/public/profiles/debug";
50 const PROFILE_STORE_TAIL: &str = "profile.p7b";
51 const PROFILE_TYPE_KEY: &str = "type";
52 const PROFILE_DEVICE_ID_TYPE_KEY: &str = "device-id-type";
53 const PROFILE_DEBUG_INFO_KEY: &str = "debug-info";
54 const PROFILE_DEVICE_IDS_KEY: &str = "device-ids";
55 const PROFILE_BUNDLE_INFO_KEY: &str = "bundle-info";
56 const PROFILE_BUNDLE_INFO_RELEASE_KEY: &str = "distribution-certificate";
57 const PROFILE_BUNDLE_INFO_DEBUG_KEY: &str = "development-certificate";
58 const PROFILE_APP_DISTRIBUTION_TYPE_KEY: &str = "app-distribution-type";
59 const APP_DISTRIBUTION_TYPE_INTERNALTESTING: &str = "internaltesting";
60 const APP_DISTRIBUTION_TYPE_ENTERPRISE: &str = "enterprise";
61 const APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL: &str = "enterprise_normal";
62 const APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM: &str = "enterprise_mdm";
63 const DEFAULT_MAX_CERT_PATH_LEN: u32 = 3;
64 const PROFILE_RELEASE_TYPE: &str = "release";
65 const PROFILE_DEBUG_TYPE: &str = "debug";
66 
67 /// profile error
68 pub enum ProfileError {
69     /// add cert path error
70     AddCertPathError,
71 }
72 /// profile error report to hisysevent
73 pub enum HisyseventProfileError {
74     /// release platform code
75     VerifySigner = 1,
76     /// release authed code
77     ParsePkcs7 = 2,
78     /// release developer code
79     AddCertPath = 3,
80 }
81 
82 extern "C" {
83     /// if developer state on return true
IsDeveloperModeOn() -> bool84     pub fn IsDeveloperModeOn() -> bool;
CodeSignGetUdid(udid: *mut u8) -> i3285     fn CodeSignGetUdid(udid: *mut u8) -> i32;
IsRdDevice() -> bool86     fn IsRdDevice() -> bool;
87 }
88 
89 #[no_mangle]
90 /// the interface to enable key in profile
EnableKeyInProfileByRust( bundle_name: *const c_char, profile: *const u8, profile_size: u32, ) -> i3291 pub extern "C" fn EnableKeyInProfileByRust(
92     bundle_name: *const c_char,
93     profile: *const u8,
94     profile_size: u32,
95 ) -> i32 {
96     match enable_key_in_profile_internal(bundle_name, profile, profile_size) {
97         Ok(_) => SUCCESS_CODE,
98         Err(_) => ERROR_CODE,
99     }
100 }
101 
102 #[no_mangle]
103 /// the interface remove key in profile
RemoveKeyInProfileByRust(bundle_name: *const c_char) -> i32104 pub extern "C" fn RemoveKeyInProfileByRust(bundle_name: *const c_char) -> i32 {
105     match remove_key_in_profile_internal(bundle_name) {
106         Ok(_) => SUCCESS_CODE,
107         Err(_) => ERROR_CODE,
108     }
109 }
110 
parse_pkcs7_data( pkcs7: &Pkcs7, root_store: &X509Store, flags: Pkcs7Flags, check_udid: bool, ) -> Result<(String, String, u32), Box<dyn Error>>111 fn parse_pkcs7_data(
112     pkcs7: &Pkcs7,
113     root_store: &X509Store,
114     flags: Pkcs7Flags,
115     check_udid: bool,
116 ) -> Result<(String, String, u32), Box<dyn Error>> {
117     let profile = verify_pkcs7_signature(pkcs7, root_store, flags)?;
118     let profile_json = parse_and_validate_profile(profile, check_udid)?;
119     get_cert_details(&profile_json)
120 }
121 
verify_pkcs7_signature( pkcs7: &Pkcs7, root_store: &X509Store, flags: Pkcs7Flags, ) -> Result<Vec<u8>, Box<dyn Error>>122 fn verify_pkcs7_signature(
123     pkcs7: &Pkcs7,
124     root_store: &X509Store,
125     flags: Pkcs7Flags,
126 ) -> Result<Vec<u8>, Box<dyn Error>> {
127     let stack_of_certs = Stack::<X509>::new()?;
128     let mut profile = Vec::new();
129     pkcs7.verify(&stack_of_certs, root_store, None, Some(&mut profile), flags)?;
130     Ok(profile)
131 }
132 
133 /// validate bundle info and debug info
validate_bundle_and_distribution_type( profile_json: &JsonValue, check_udid: bool, ) -> Result<(), Box<dyn Error>>134 pub fn validate_bundle_and_distribution_type(
135     profile_json: &JsonValue,
136     check_udid: bool,
137 ) -> Result<(), Box<dyn Error>> {
138     let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str();
139     match bundle_type {
140         PROFILE_DEBUG_TYPE => {
141             if check_udid && verify_udid(profile_json).is_err() {
142                 return Err("Invalid UDID.".into());
143             }
144         },
145         PROFILE_RELEASE_TYPE => {
146             let distribution_type = profile_json[PROFILE_APP_DISTRIBUTION_TYPE_KEY].try_as_string()?.as_str();
147             match distribution_type {
148                 APP_DISTRIBUTION_TYPE_INTERNALTESTING => {
149                     if check_udid && verify_udid(profile_json).is_err() {
150                         return Err("Invalid UDID.".into());
151                     }
152                 },
153                 APP_DISTRIBUTION_TYPE_ENTERPRISE |
154                 APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL |
155                 APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM => {
156                 },
157                 _ => {
158                     return Err("Invalid app distribution type.".into());
159                 }
160             }
161         }
162         _ => {
163             return Err("Invalid bundle type.".into());
164         },
165     }
166     Ok(())
167 }
168 
parse_and_validate_profile( profile: Vec<u8>, check_udid: bool, ) -> Result<JsonValue, Box<dyn Error>>169 fn parse_and_validate_profile(
170     profile: Vec<u8>,
171     check_udid: bool,
172 ) -> Result<JsonValue, Box<dyn Error>> {
173     let profile_json = JsonValue::from_text(profile)?;
174     validate_bundle_and_distribution_type(&profile_json, check_udid)?;
175     Ok(profile_json)
176 }
177 
get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32), Box<dyn Error>>178 fn get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32), Box<dyn Error>> {
179     let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str();
180     let profile_type = match bundle_type {
181         PROFILE_DEBUG_TYPE => DebugCertPathType::Developer as u32,
182         PROFILE_RELEASE_TYPE => ReleaseCertPathType::Developer as u32,
183         _ => return Err("Invalid bundle type.".into()),
184     };
185     let signed_cert = match bundle_type {
186         PROFILE_DEBUG_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_DEBUG_KEY].try_as_string()?,
187         PROFILE_RELEASE_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_RELEASE_KEY].try_as_string()?,
188         _ => return Err("Invalid bundle type.".into()),
189     };
190     let signed_pem = X509::from_pem(signed_cert.as_bytes())?;
191     let subject = format_x509_fabricate_name(signed_pem.subject_name());
192     let issuer = format_x509_fabricate_name(signed_pem.issuer_name());
193     Ok((subject, issuer, profile_type))
194 }
195 
196 lazy_static! {
197     /// global udid
198     pub static ref UDID: Result<String, String> = init_udid();
199 }
200 
init_udid() -> Result<String, String>201 fn init_udid() -> Result<String, String> {
202     let mut udid: Vec<u8> = vec![0; 128];
203     let result = unsafe { CodeSignGetUdid(udid.as_mut_ptr()) };
204 
205     if result != 0 {
206         return Err("Failed to get UDID".to_string());
207     }
208 
209     if let Some(first_zero_index) = udid.iter().position(|&x| x == 0) {
210         udid.truncate(first_zero_index);
211     }
212 
213     match String::from_utf8(udid) {
214         Ok(s) => Ok(s),
215         Err(_) => Err("UDID is not valid UTF-8".to_string()),
216     }
217 }
218 
219 /// get device udid
get_udid() -> Result<String, String>220 pub fn get_udid() -> Result<String, String> {
221     UDID.clone()
222 }
223 
224 
verify_signers( pkcs7: &Pkcs7, profile_signer: &[(&String, &String)], ) -> Result<(), Box<dyn Error>>225 fn verify_signers(
226     pkcs7: &Pkcs7,
227     profile_signer: &[(&String, &String)],
228 ) -> Result<(), Box<dyn Error>> {
229     let stack_of_certs = Stack::<X509>::new()?;
230     let signers_result = pkcs7.signers(&stack_of_certs, Pkcs7Flags::empty())?;
231     for signer in signers_result {
232         let subject_name = format_x509name_to_string(signer.subject_name());
233         let issuer_name = format_x509name_to_string(signer.issuer_name());
234         if !profile_signer.contains(&(&subject_name, &issuer_name)) {
235             return Err("Verification failed.".into());
236         }
237     }
238     Ok(())
239 }
240 
format_x509name_to_string(name: &X509NameRef) -> String241 fn format_x509name_to_string(name: &X509NameRef) -> String {
242     let mut parts = Vec::new();
243 
244     for entry in name.entries() {
245         let tag = match entry.object().nid() {
246             openssl::nid::Nid::COMMONNAME => "CN",
247             openssl::nid::Nid::COUNTRYNAME => "C",
248             openssl::nid::Nid::ORGANIZATIONNAME => "O",
249             openssl::nid::Nid::ORGANIZATIONALUNITNAME => "OU",
250             _ => continue,
251         };
252         let value = entry.data().as_utf8().unwrap();
253         parts.push(format!("{}={}", tag, value));
254     }
255     parts.join(", ")
256 }
257 
format_x509_fabricate_name(name: &X509NameRef) -> String258 fn format_x509_fabricate_name(name: &X509NameRef) -> String {
259     let mut common_name = String::new();
260     let mut organization = String::new();
261     let mut email = String::new();
262 
263     for entry in name.entries() {
264         let entry_nid = entry.object().nid();
265         if let Ok(value) = entry.data().as_utf8() {
266             match entry_nid {
267                 openssl::nid::Nid::COMMONNAME => common_name = value.to_string(),
268                 openssl::nid::Nid::ORGANIZATIONNAME => organization = value.to_string(),
269                 openssl::nid::Nid::PKCS9_EMAILADDRESS => email = value.to_string(),
270                 _ => continue,
271             };
272         }
273     }
274     let ret = common_format_fabricate_name(&common_name, &organization, &email);
275     ret
276 }
277 
get_profile_paths(is_debug: bool) -> Vec<String>278 fn get_profile_paths(is_debug: bool) -> Vec<String> {
279     let mut paths = Vec::new();
280     let profile_prefixes = match is_debug {
281         false => vec![PROFILE_STORE_EL0_PREFIX, PROFILE_STORE_EL1_PREFIX, PROFILE_STORE_EL1_PUBLIC_PREFIX],
282         true => vec![DEBUG_PROFILE_STORE_EL0_PREFIX, DEBUG_PROFILE_STORE_EL1_PREFIX, DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX],
283     };
284     for profile_prefix in profile_prefixes {
285         paths.extend(get_paths_from_prefix(profile_prefix));
286     }
287     paths
288 }
289 
get_paths_from_prefix(prefix: &str) -> Vec<String>290 fn get_paths_from_prefix(prefix: &str) -> Vec<String> {
291     let mut paths = Vec::new();
292     if let Ok(entries) = read_dir(prefix) {
293         for entry in entries.filter_map(Result::ok) {
294             let path = entry.path();
295             let filename = fmt_store_path(&path.to_string_lossy(), PROFILE_STORE_TAIL);
296             if file_exists(&filename) {
297                 paths.push(filename);
298             }
299         }
300     }
301     paths
302 }
303 
304 /// add profile cert path data
add_profile_cert_path( root_cert: &PemCollection, cert_paths: &TrustCertPath, ) -> Result<(), ProfileError>305 pub fn add_profile_cert_path(
306     root_cert: &PemCollection,
307     cert_paths: &TrustCertPath,
308 ) -> Result<(), ProfileError> {
309     let x509_store = root_cert.to_x509_store().unwrap();
310     if process_profile(false, &x509_store, cert_paths.get_profile_info().as_slice()).is_err() {
311         return Err(ProfileError::AddCertPathError);
312     }
313     if process_profile(true, &x509_store, cert_paths.get_debug_profile_info().as_slice()).is_err() {
314         return Err(ProfileError::AddCertPathError);
315     }
316     Ok(())
317 }
318 
process_profile( is_debug: bool, x509_store: &X509Store, profile_info: &[(&String, &String)], ) -> Result<(), ProfileError>319 fn process_profile(
320     is_debug: bool,
321     x509_store: &X509Store,
322     profile_info: &[(&String, &String)],
323 ) -> Result<(), ProfileError> {
324     let profiles_paths = get_profile_paths(is_debug);
325     for path in profiles_paths {
326         let mut pkcs7_data = Vec::new();
327         if load_bytes_from_file(&path, &mut pkcs7_data).is_err() {
328             info!(LOG_LABEL, "load profile failed {}!", @public(path));
329             continue;
330         }
331         info!(LOG_LABEL, "load profile success {}!", @public(path));
332         let pkcs7 = match Pkcs7::from_der(&pkcs7_data) {
333             Ok(pk7) => pk7,
334             Err(_) => {
335                 error!(LOG_LABEL, "load profile to pkcs7 obj failed {}!", @public(path));
336                 continue;
337             }
338         };
339         if verify_signers(&pkcs7, profile_info).is_err() {
340             error!(LOG_LABEL, "Invalid signer profile file {}", @public(path));
341             report_parse_profile_err(&path, HisyseventProfileError::VerifySigner as i32);
342             continue;
343         }
344         let check_udid = unsafe { !IsRdDevice() };
345         let (subject, issuer, profile_type) =
346             match parse_pkcs7_data(&pkcs7, x509_store, Pkcs7Flags::empty(), check_udid) {
347                 Ok(tuple) => tuple,
348                 Err(e) => {
349                     error!(LOG_LABEL, "Error parsing PKCS7 data: {}, profile file {}",
350                         @public(e), @public(path));
351                     report_parse_profile_err(&path, HisyseventProfileError::ParsePkcs7 as i32);
352                     continue;
353                 }
354             };
355         if add_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() {
356             error!(
357                 LOG_LABEL,
358                 "Failed to add profile cert path info into ioctl for {}", @public(path)
359             );
360             report_parse_profile_err(&path, HisyseventProfileError::AddCertPath as i32);
361             continue;
362         }
363     }
364     Ok(())
365 }
366 
verify_udid(profile_json: &JsonValue) -> Result<(), String>367 fn verify_udid(profile_json: &JsonValue) -> Result<(), String> {
368     let device_udid = get_udid()?;
369     info!(LOG_LABEL, "get device udid {}!", device_udid);
370     let device_id_type = &profile_json[PROFILE_DEBUG_INFO_KEY][PROFILE_DEVICE_ID_TYPE_KEY];
371 
372     if let JsonValue::String(id_type) = device_id_type {
373         if id_type != "udid" {
374             return Err("Invalid device ID type".to_string());
375         }
376     } else {
377         return Err("Device ID type is not a string".to_string());
378     }
379     match &profile_json[PROFILE_DEBUG_INFO_KEY][PROFILE_DEVICE_IDS_KEY] {
380         JsonValue::Array(arr) => {
381             if arr.iter().any(|item| match item {
382                 JsonValue::String(s) => s == &device_udid,
383                 _ => false,
384             }) {
385                 Ok(())
386             } else {
387                 Err("UDID not found in the list".to_string())
388             }
389         }
390         _ => Err("Device IDs are not in an array format".to_string()),
391     }
392 }
393 
validate_and_convert_inputs( bundle_name: *const c_char, profile: *const u8, profile_size: u32, ) -> Result<(String, Vec<u8>), ()>394 fn validate_and_convert_inputs(
395     bundle_name: *const c_char,
396     profile: *const u8,
397     profile_size: u32,
398 ) -> Result<(String, Vec<u8>), ()> {
399     let _bundle_name = c_char_to_string(bundle_name);
400     if _bundle_name.is_empty() {
401         error!(LOG_LABEL, "invalid profile bundle name!");
402         return Err(());
403     }
404     let profile_data = cbyte_buffer_to_vec(profile, profile_size);
405     Ok((_bundle_name, profile_data))
406 }
407 
process_data(profile_data: &[u8]) -> Result<(String, String, u32), ()>408 fn process_data(profile_data: &[u8]) -> Result<(String, String, u32), ()> {
409     let store = match X509StoreBuilder::new() {
410         Ok(store) => store.build(),
411         Err(_) => {
412             error!(LOG_LABEL, "Failed to build X509 store");
413             return Err(());
414         }
415     };
416 
417     let pkcs7 = match Pkcs7::from_der(profile_data) {
418         Ok(pk7) => pk7,
419         Err(_) => {
420             error!(LOG_LABEL, "load profile to pkcs7 obj failed");
421             return Err(());
422         }
423     };
424 
425     match parse_pkcs7_data(&pkcs7, &store, Pkcs7Flags::NOVERIFY, false) {
426         Ok(tuple) => Ok(tuple),
427         Err(_) => {
428             error!(LOG_LABEL, "parse pkcs7 data error");
429             Err(())
430         }
431     }
432 }
433 
create_bundle_path(bundle_name: &str, profile_type: u32) -> Result<String, ()>434 fn create_bundle_path(bundle_name: &str, profile_type: u32) -> Result<String, ()> {
435     let bundle_path = match profile_type {
436         value if value == DebugCertPathType::Developer as u32 => {
437             fmt_store_path(DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX, bundle_name)
438         }
439         value if value == ReleaseCertPathType::Developer as u32 => {
440             fmt_store_path(PROFILE_STORE_EL1_PUBLIC_PREFIX, bundle_name)
441         }
442         _ => {
443             error!(LOG_LABEL, "invalid profile type");
444             return Err(());
445         }
446     };
447     Ok(bundle_path)
448 }
449 
enable_key_in_profile_internal( bundle_name: *const c_char, profile: *const u8, profile_size: u32, ) -> Result<(), ()>450 fn enable_key_in_profile_internal(
451     bundle_name: *const c_char,
452     profile: *const u8,
453     profile_size: u32,
454 ) -> Result<(), ()> {
455     let (_bundle_name, profile_data) = validate_and_convert_inputs(bundle_name, profile, profile_size)?;
456     let (subject, issuer, profile_type) = process_data(&profile_data)?;
457     let bundle_path = create_bundle_path(&_bundle_name, profile_type)?;
458     info!(LOG_LABEL, "create bundle_path path {}!", @public(bundle_path));
459     if !file_exists(&bundle_path) && create_file_path(&bundle_path).is_err() {
460         error!(LOG_LABEL, "create bundle_path path {} failed!", @public(bundle_path));
461         return Err(());
462     }
463     if change_default_mode_directory(&bundle_path).is_err() {
464         error!(LOG_LABEL, "change bundle_path mode error!");
465         return Err(());
466     }
467     let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL);
468     if write_bytes_to_file(&filename, &profile_data).is_err() {
469         error!(LOG_LABEL, "dump profile data error!");
470         return Err(());
471     }
472     if change_default_mode_file(&filename).is_err() {
473         error!(LOG_LABEL, "change profile mode error!");
474         return Err(());
475     }
476     if add_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() {
477         error!(LOG_LABEL, "add profile data error!");
478         return Err(());
479     }
480     info!(LOG_LABEL, "finish add cert path in ioctl!");
481     Ok(())
482 }
483 
process_remove_bundle( prefix: &str, bundle_name: &str, ) -> Result<(), ()>484 fn process_remove_bundle(
485     prefix: &str,
486     bundle_name: &str,
487 ) -> Result<(), ()> {
488     let bundle_path = fmt_store_path(prefix, bundle_name);
489 
490     if !file_exists(&bundle_path) {
491         return Err(());
492     }
493 
494     let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL);
495     let mut profile_data = Vec::new();
496     if load_bytes_from_file(&filename, &mut profile_data).is_err() {
497         error!(LOG_LABEL, "load profile data error!");
498         return Err(());
499     }
500 
501     let (subject, issuer, profile_type) = process_data(&profile_data)?;
502     if delete_file_path(&bundle_path).is_err() {
503         error!(LOG_LABEL, "remove profile data error!");
504         return Err(());
505     }
506 
507     info!(LOG_LABEL, "remove bundle_path path {}!", @public(bundle_path));
508 
509     if remove_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() {
510         error!(LOG_LABEL, "remove profile data error!");
511         return Err(());
512     }
513 
514     info!(LOG_LABEL, "finish remove cert path in ioctl!");
515     Ok(())
516 }
517 
remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()>518 fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> {
519     let _bundle_name = c_char_to_string(bundle_name);
520     if _bundle_name.is_empty() {
521         error!(LOG_LABEL, "Invalid bundle name");
522         return Err(());
523     }
524 
525     let profile_prefix = vec![
526         DEBUG_PROFILE_STORE_EL0_PREFIX,
527         PROFILE_STORE_EL0_PREFIX,
528         DEBUG_PROFILE_STORE_EL1_PREFIX,
529         PROFILE_STORE_EL1_PREFIX,
530         DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX,
531         PROFILE_STORE_EL1_PUBLIC_PREFIX,
532     ];
533 
534     let mut rm_succ = false;
535     for prefix in profile_prefix {
536         if process_remove_bundle(prefix, &_bundle_name).is_ok() {
537             rm_succ = true;
538         }
539     }
540     if rm_succ {
541         Ok(())
542     } else {
543         error!(LOG_LABEL, "Failed to remove bundle profile info, bundleName: {}.", @public(_bundle_name));
544         Err(())
545     }
546 }
547 
c_char_to_string(c_str: *const c_char) -> String548 fn c_char_to_string(c_str: *const c_char) -> String {
549     unsafe {
550         if c_str.is_null() {
551             return String::new();
552         }
553         let c_str = CStr::from_ptr(c_str);
554         c_str.to_string_lossy().to_string()
555     }
556 }
557 
cbyte_buffer_to_vec(data: *const u8, size: u32) -> Vec<u8>558 fn cbyte_buffer_to_vec(data: *const u8, size: u32) -> Vec<u8> {
559     unsafe {
560         if data.is_null() {
561             return Vec::new();
562         }
563         let data_slice = std::slice::from_raw_parts(data, size as usize);
564         let mut result = Vec::with_capacity(size as usize);
565         result.extend_from_slice(data_slice);
566         result
567     }
568 }
569