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