18e920a95Sopenharmony_ci/*
28e920a95Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd.
38e920a95Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48e920a95Sopenharmony_ci * you may not use this file except in compliance with the License.
58e920a95Sopenharmony_ci * You may obtain a copy of the License at
68e920a95Sopenharmony_ci *
78e920a95Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88e920a95Sopenharmony_ci *
98e920a95Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108e920a95Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118e920a95Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128e920a95Sopenharmony_ci * See the License for the specific language governing permissions and
138e920a95Sopenharmony_ci * limitations under the License.
148e920a95Sopenharmony_ci */
158e920a95Sopenharmony_ci
168e920a95Sopenharmony_ciuse lazy_static::lazy_static;
178e920a95Sopenharmony_ciuse super::cert_chain_utils::PemCollection;
188e920a95Sopenharmony_ciuse super::cert_path_utils::{
198e920a95Sopenharmony_ci    add_cert_path_info, remove_cert_path_info, common_format_fabricate_name,
208e920a95Sopenharmony_ci    DebugCertPathType, ReleaseCertPathType, TrustCertPath,
218e920a95Sopenharmony_ci};
228e920a95Sopenharmony_ciuse super::cs_hisysevent::report_parse_profile_err;
238e920a95Sopenharmony_ciuse super::file_utils::{
248e920a95Sopenharmony_ci    create_file_path, delete_file_path, file_exists, fmt_store_path,
258e920a95Sopenharmony_ci    load_bytes_from_file, write_bytes_to_file, change_default_mode_file, change_default_mode_directory
268e920a95Sopenharmony_ci};
278e920a95Sopenharmony_ciuse hilog_rust::{error, info, hilog, HiLogLabel, LogType};
288e920a95Sopenharmony_ciuse openssl::pkcs7::{Pkcs7, Pkcs7Flags};
298e920a95Sopenharmony_ciuse openssl::stack::Stack;
308e920a95Sopenharmony_ciuse openssl::x509::store::{X509Store, X509StoreBuilder};
318e920a95Sopenharmony_ciuse openssl::x509::{X509NameRef, X509};
328e920a95Sopenharmony_ciuse std::error::Error;
338e920a95Sopenharmony_ciuse std::ffi::{c_char, CStr, CString};
348e920a95Sopenharmony_ciuse std::fs::read_dir;
358e920a95Sopenharmony_ciuse ylong_json::JsonValue;
368e920a95Sopenharmony_ci
378e920a95Sopenharmony_ciconst ERROR_CODE: i32 = -1;
388e920a95Sopenharmony_ciconst SUCCESS_CODE: i32 = 0;
398e920a95Sopenharmony_ciconst LOG_LABEL: HiLogLabel = HiLogLabel {
408e920a95Sopenharmony_ci    log_type: LogType::LogCore,
418e920a95Sopenharmony_ci    domain: 0xd005a06, // security domain
428e920a95Sopenharmony_ci    tag: "CODE_SIGN",
438e920a95Sopenharmony_ci};
448e920a95Sopenharmony_ciconst PROFILE_STORE_EL0_PREFIX: &str = "/data/service/el0/profiles/developer";
458e920a95Sopenharmony_ciconst PROFILE_STORE_EL1_PREFIX: &str = "/data/service/el1/profiles/release";
468e920a95Sopenharmony_ciconst PROFILE_STORE_EL1_PUBLIC_PREFIX: &str = "/data/service/el1/public/profiles/release";
478e920a95Sopenharmony_ciconst DEBUG_PROFILE_STORE_EL0_PREFIX: &str = "/data/service/el0/profiles/debug";
488e920a95Sopenharmony_ciconst DEBUG_PROFILE_STORE_EL1_PREFIX: &str = "/data/service/el1/profiles/debug";
498e920a95Sopenharmony_ciconst DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX: &str = "/data/service/el1/public/profiles/debug";
508e920a95Sopenharmony_ciconst PROFILE_STORE_TAIL: &str = "profile.p7b";
518e920a95Sopenharmony_ciconst PROFILE_TYPE_KEY: &str = "type";
528e920a95Sopenharmony_ciconst PROFILE_DEVICE_ID_TYPE_KEY: &str = "device-id-type";
538e920a95Sopenharmony_ciconst PROFILE_DEBUG_INFO_KEY: &str = "debug-info";
548e920a95Sopenharmony_ciconst PROFILE_DEVICE_IDS_KEY: &str = "device-ids";
558e920a95Sopenharmony_ciconst PROFILE_BUNDLE_INFO_KEY: &str = "bundle-info";
568e920a95Sopenharmony_ciconst PROFILE_BUNDLE_INFO_RELEASE_KEY: &str = "distribution-certificate";
578e920a95Sopenharmony_ciconst PROFILE_BUNDLE_INFO_DEBUG_KEY: &str = "development-certificate";
588e920a95Sopenharmony_ciconst PROFILE_APP_DISTRIBUTION_TYPE_KEY: &str = "app-distribution-type";
598e920a95Sopenharmony_ciconst APP_DISTRIBUTION_TYPE_INTERNALTESTING: &str = "internaltesting";
608e920a95Sopenharmony_ciconst APP_DISTRIBUTION_TYPE_ENTERPRISE: &str = "enterprise";
618e920a95Sopenharmony_ciconst APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL: &str = "enterprise_normal";
628e920a95Sopenharmony_ciconst APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM: &str = "enterprise_mdm";
638e920a95Sopenharmony_ciconst DEFAULT_MAX_CERT_PATH_LEN: u32 = 3;
648e920a95Sopenharmony_ciconst PROFILE_RELEASE_TYPE: &str = "release";
658e920a95Sopenharmony_ciconst PROFILE_DEBUG_TYPE: &str = "debug";
668e920a95Sopenharmony_ci
678e920a95Sopenharmony_ci/// profile error
688e920a95Sopenharmony_cipub enum ProfileError {
698e920a95Sopenharmony_ci    /// add cert path error
708e920a95Sopenharmony_ci    AddCertPathError,
718e920a95Sopenharmony_ci}
728e920a95Sopenharmony_ci/// profile error report to hisysevent
738e920a95Sopenharmony_cipub enum HisyseventProfileError {
748e920a95Sopenharmony_ci    /// release platform code
758e920a95Sopenharmony_ci    VerifySigner = 1,
768e920a95Sopenharmony_ci    /// release authed code
778e920a95Sopenharmony_ci    ParsePkcs7 = 2,
788e920a95Sopenharmony_ci    /// release developer code
798e920a95Sopenharmony_ci    AddCertPath = 3,
808e920a95Sopenharmony_ci}
818e920a95Sopenharmony_ci
828e920a95Sopenharmony_ciextern "C" {
838e920a95Sopenharmony_ci    /// if developer state on return true
848e920a95Sopenharmony_ci    pub fn IsDeveloperModeOn() -> bool;
858e920a95Sopenharmony_ci    fn CodeSignGetUdid(udid: *mut u8) -> i32;
868e920a95Sopenharmony_ci    fn IsRdDevice() -> bool;
878e920a95Sopenharmony_ci}
888e920a95Sopenharmony_ci
898e920a95Sopenharmony_ci#[no_mangle]
908e920a95Sopenharmony_ci/// the interface to enable key in profile
918e920a95Sopenharmony_cipub extern "C" fn EnableKeyInProfileByRust(
928e920a95Sopenharmony_ci    bundle_name: *const c_char,
938e920a95Sopenharmony_ci    profile: *const u8,
948e920a95Sopenharmony_ci    profile_size: u32,
958e920a95Sopenharmony_ci) -> i32 {
968e920a95Sopenharmony_ci    match enable_key_in_profile_internal(bundle_name, profile, profile_size) {
978e920a95Sopenharmony_ci        Ok(_) => SUCCESS_CODE,
988e920a95Sopenharmony_ci        Err(_) => ERROR_CODE,
998e920a95Sopenharmony_ci    }
1008e920a95Sopenharmony_ci}
1018e920a95Sopenharmony_ci
1028e920a95Sopenharmony_ci#[no_mangle]
1038e920a95Sopenharmony_ci/// the interface remove key in profile
1048e920a95Sopenharmony_cipub extern "C" fn RemoveKeyInProfileByRust(bundle_name: *const c_char) -> i32 {
1058e920a95Sopenharmony_ci    match remove_key_in_profile_internal(bundle_name) {
1068e920a95Sopenharmony_ci        Ok(_) => SUCCESS_CODE,
1078e920a95Sopenharmony_ci        Err(_) => ERROR_CODE,
1088e920a95Sopenharmony_ci    }
1098e920a95Sopenharmony_ci}
1108e920a95Sopenharmony_ci
1118e920a95Sopenharmony_cifn parse_pkcs7_data(
1128e920a95Sopenharmony_ci    pkcs7: &Pkcs7,
1138e920a95Sopenharmony_ci    root_store: &X509Store,
1148e920a95Sopenharmony_ci    flags: Pkcs7Flags,
1158e920a95Sopenharmony_ci    check_udid: bool,
1168e920a95Sopenharmony_ci) -> Result<(String, String, u32), Box<dyn Error>> {
1178e920a95Sopenharmony_ci    let profile = verify_pkcs7_signature(pkcs7, root_store, flags)?;
1188e920a95Sopenharmony_ci    let profile_json = parse_and_validate_profile(profile, check_udid)?;
1198e920a95Sopenharmony_ci    get_cert_details(&profile_json)
1208e920a95Sopenharmony_ci}
1218e920a95Sopenharmony_ci
1228e920a95Sopenharmony_cifn verify_pkcs7_signature(
1238e920a95Sopenharmony_ci    pkcs7: &Pkcs7,
1248e920a95Sopenharmony_ci    root_store: &X509Store,
1258e920a95Sopenharmony_ci    flags: Pkcs7Flags,
1268e920a95Sopenharmony_ci) -> Result<Vec<u8>, Box<dyn Error>> {
1278e920a95Sopenharmony_ci    let stack_of_certs = Stack::<X509>::new()?;
1288e920a95Sopenharmony_ci    let mut profile = Vec::new();
1298e920a95Sopenharmony_ci    pkcs7.verify(&stack_of_certs, root_store, None, Some(&mut profile), flags)?;
1308e920a95Sopenharmony_ci    Ok(profile)
1318e920a95Sopenharmony_ci}
1328e920a95Sopenharmony_ci
1338e920a95Sopenharmony_ci/// validate bundle info and debug info
1348e920a95Sopenharmony_cipub fn validate_bundle_and_distribution_type(
1358e920a95Sopenharmony_ci    profile_json: &JsonValue,
1368e920a95Sopenharmony_ci    check_udid: bool,
1378e920a95Sopenharmony_ci) -> Result<(), Box<dyn Error>> {
1388e920a95Sopenharmony_ci    let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str();
1398e920a95Sopenharmony_ci    match bundle_type {
1408e920a95Sopenharmony_ci        PROFILE_DEBUG_TYPE => {
1418e920a95Sopenharmony_ci            if check_udid && verify_udid(profile_json).is_err() {
1428e920a95Sopenharmony_ci                return Err("Invalid UDID.".into());
1438e920a95Sopenharmony_ci            }
1448e920a95Sopenharmony_ci        },
1458e920a95Sopenharmony_ci        PROFILE_RELEASE_TYPE => {
1468e920a95Sopenharmony_ci            let distribution_type = profile_json[PROFILE_APP_DISTRIBUTION_TYPE_KEY].try_as_string()?.as_str();
1478e920a95Sopenharmony_ci            match distribution_type {
1488e920a95Sopenharmony_ci                APP_DISTRIBUTION_TYPE_INTERNALTESTING => {
1498e920a95Sopenharmony_ci                    if check_udid && verify_udid(profile_json).is_err() {
1508e920a95Sopenharmony_ci                        return Err("Invalid UDID.".into());
1518e920a95Sopenharmony_ci                    }
1528e920a95Sopenharmony_ci                },
1538e920a95Sopenharmony_ci                APP_DISTRIBUTION_TYPE_ENTERPRISE |
1548e920a95Sopenharmony_ci                APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL |
1558e920a95Sopenharmony_ci                APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM => {
1568e920a95Sopenharmony_ci                },
1578e920a95Sopenharmony_ci                _ => {
1588e920a95Sopenharmony_ci                    return Err("Invalid app distribution type.".into());
1598e920a95Sopenharmony_ci                }
1608e920a95Sopenharmony_ci            }
1618e920a95Sopenharmony_ci        }
1628e920a95Sopenharmony_ci        _ => {
1638e920a95Sopenharmony_ci            return Err("Invalid bundle type.".into());
1648e920a95Sopenharmony_ci        },
1658e920a95Sopenharmony_ci    }
1668e920a95Sopenharmony_ci    Ok(())
1678e920a95Sopenharmony_ci}
1688e920a95Sopenharmony_ci
1698e920a95Sopenharmony_cifn parse_and_validate_profile(
1708e920a95Sopenharmony_ci    profile: Vec<u8>,
1718e920a95Sopenharmony_ci    check_udid: bool,
1728e920a95Sopenharmony_ci) -> Result<JsonValue, Box<dyn Error>> {
1738e920a95Sopenharmony_ci    let profile_json = JsonValue::from_text(profile)?;
1748e920a95Sopenharmony_ci    validate_bundle_and_distribution_type(&profile_json, check_udid)?;
1758e920a95Sopenharmony_ci    Ok(profile_json)
1768e920a95Sopenharmony_ci}
1778e920a95Sopenharmony_ci
1788e920a95Sopenharmony_cifn get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32), Box<dyn Error>> {
1798e920a95Sopenharmony_ci    let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str();
1808e920a95Sopenharmony_ci    let profile_type = match bundle_type {
1818e920a95Sopenharmony_ci        PROFILE_DEBUG_TYPE => DebugCertPathType::Developer as u32,
1828e920a95Sopenharmony_ci        PROFILE_RELEASE_TYPE => ReleaseCertPathType::Developer as u32,
1838e920a95Sopenharmony_ci        _ => return Err("Invalid bundle type.".into()),
1848e920a95Sopenharmony_ci    };
1858e920a95Sopenharmony_ci    let signed_cert = match bundle_type {
1868e920a95Sopenharmony_ci        PROFILE_DEBUG_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_DEBUG_KEY].try_as_string()?,
1878e920a95Sopenharmony_ci        PROFILE_RELEASE_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_RELEASE_KEY].try_as_string()?,
1888e920a95Sopenharmony_ci        _ => return Err("Invalid bundle type.".into()),
1898e920a95Sopenharmony_ci    };
1908e920a95Sopenharmony_ci    let signed_pem = X509::from_pem(signed_cert.as_bytes())?;
1918e920a95Sopenharmony_ci    let subject = format_x509_fabricate_name(signed_pem.subject_name());
1928e920a95Sopenharmony_ci    let issuer = format_x509_fabricate_name(signed_pem.issuer_name());
1938e920a95Sopenharmony_ci    Ok((subject, issuer, profile_type))
1948e920a95Sopenharmony_ci}
1958e920a95Sopenharmony_ci
1968e920a95Sopenharmony_cilazy_static! {
1978e920a95Sopenharmony_ci    /// global udid
1988e920a95Sopenharmony_ci    pub static ref UDID: Result<String, String> = init_udid();
1998e920a95Sopenharmony_ci}
2008e920a95Sopenharmony_ci
2018e920a95Sopenharmony_cifn init_udid() -> Result<String, String> {
2028e920a95Sopenharmony_ci    let mut udid: Vec<u8> = vec![0; 128];
2038e920a95Sopenharmony_ci    let result = unsafe { CodeSignGetUdid(udid.as_mut_ptr()) };
2048e920a95Sopenharmony_ci
2058e920a95Sopenharmony_ci    if result != 0 {
2068e920a95Sopenharmony_ci        return Err("Failed to get UDID".to_string());
2078e920a95Sopenharmony_ci    }
2088e920a95Sopenharmony_ci
2098e920a95Sopenharmony_ci    if let Some(first_zero_index) = udid.iter().position(|&x| x == 0) {
2108e920a95Sopenharmony_ci        udid.truncate(first_zero_index);
2118e920a95Sopenharmony_ci    }
2128e920a95Sopenharmony_ci
2138e920a95Sopenharmony_ci    match String::from_utf8(udid) {
2148e920a95Sopenharmony_ci        Ok(s) => Ok(s),
2158e920a95Sopenharmony_ci        Err(_) => Err("UDID is not valid UTF-8".to_string()),
2168e920a95Sopenharmony_ci    }
2178e920a95Sopenharmony_ci}
2188e920a95Sopenharmony_ci
2198e920a95Sopenharmony_ci/// get device udid
2208e920a95Sopenharmony_cipub fn get_udid() -> Result<String, String> {
2218e920a95Sopenharmony_ci    UDID.clone()
2228e920a95Sopenharmony_ci}
2238e920a95Sopenharmony_ci
2248e920a95Sopenharmony_ci
2258e920a95Sopenharmony_cifn verify_signers(
2268e920a95Sopenharmony_ci    pkcs7: &Pkcs7,
2278e920a95Sopenharmony_ci    profile_signer: &[(&String, &String)],
2288e920a95Sopenharmony_ci) -> Result<(), Box<dyn Error>> {
2298e920a95Sopenharmony_ci    let stack_of_certs = Stack::<X509>::new()?;
2308e920a95Sopenharmony_ci    let signers_result = pkcs7.signers(&stack_of_certs, Pkcs7Flags::empty())?;
2318e920a95Sopenharmony_ci    for signer in signers_result {
2328e920a95Sopenharmony_ci        let subject_name = format_x509name_to_string(signer.subject_name());
2338e920a95Sopenharmony_ci        let issuer_name = format_x509name_to_string(signer.issuer_name());
2348e920a95Sopenharmony_ci        if !profile_signer.contains(&(&subject_name, &issuer_name)) {
2358e920a95Sopenharmony_ci            return Err("Verification failed.".into());
2368e920a95Sopenharmony_ci        }
2378e920a95Sopenharmony_ci    }
2388e920a95Sopenharmony_ci    Ok(())
2398e920a95Sopenharmony_ci}
2408e920a95Sopenharmony_ci
2418e920a95Sopenharmony_cifn format_x509name_to_string(name: &X509NameRef) -> String {
2428e920a95Sopenharmony_ci    let mut parts = Vec::new();
2438e920a95Sopenharmony_ci
2448e920a95Sopenharmony_ci    for entry in name.entries() {
2458e920a95Sopenharmony_ci        let tag = match entry.object().nid() {
2468e920a95Sopenharmony_ci            openssl::nid::Nid::COMMONNAME => "CN",
2478e920a95Sopenharmony_ci            openssl::nid::Nid::COUNTRYNAME => "C",
2488e920a95Sopenharmony_ci            openssl::nid::Nid::ORGANIZATIONNAME => "O",
2498e920a95Sopenharmony_ci            openssl::nid::Nid::ORGANIZATIONALUNITNAME => "OU",
2508e920a95Sopenharmony_ci            _ => continue,
2518e920a95Sopenharmony_ci        };
2528e920a95Sopenharmony_ci        let value = entry.data().as_utf8().unwrap();
2538e920a95Sopenharmony_ci        parts.push(format!("{}={}", tag, value));
2548e920a95Sopenharmony_ci    }
2558e920a95Sopenharmony_ci    parts.join(", ")
2568e920a95Sopenharmony_ci}
2578e920a95Sopenharmony_ci
2588e920a95Sopenharmony_cifn format_x509_fabricate_name(name: &X509NameRef) -> String {
2598e920a95Sopenharmony_ci    let mut common_name = String::new();
2608e920a95Sopenharmony_ci    let mut organization = String::new();
2618e920a95Sopenharmony_ci    let mut email = String::new();
2628e920a95Sopenharmony_ci
2638e920a95Sopenharmony_ci    for entry in name.entries() {
2648e920a95Sopenharmony_ci        let entry_nid = entry.object().nid();
2658e920a95Sopenharmony_ci        if let Ok(value) = entry.data().as_utf8() {
2668e920a95Sopenharmony_ci            match entry_nid {
2678e920a95Sopenharmony_ci                openssl::nid::Nid::COMMONNAME => common_name = value.to_string(),
2688e920a95Sopenharmony_ci                openssl::nid::Nid::ORGANIZATIONNAME => organization = value.to_string(),
2698e920a95Sopenharmony_ci                openssl::nid::Nid::PKCS9_EMAILADDRESS => email = value.to_string(),
2708e920a95Sopenharmony_ci                _ => continue,
2718e920a95Sopenharmony_ci            };
2728e920a95Sopenharmony_ci        }
2738e920a95Sopenharmony_ci    }
2748e920a95Sopenharmony_ci    let ret = common_format_fabricate_name(&common_name, &organization, &email);
2758e920a95Sopenharmony_ci    ret
2768e920a95Sopenharmony_ci}
2778e920a95Sopenharmony_ci
2788e920a95Sopenharmony_cifn get_profile_paths(is_debug: bool) -> Vec<String> {
2798e920a95Sopenharmony_ci    let mut paths = Vec::new();
2808e920a95Sopenharmony_ci    let profile_prefixes = match is_debug {
2818e920a95Sopenharmony_ci        false => vec![PROFILE_STORE_EL0_PREFIX, PROFILE_STORE_EL1_PREFIX, PROFILE_STORE_EL1_PUBLIC_PREFIX],
2828e920a95Sopenharmony_ci        true => vec![DEBUG_PROFILE_STORE_EL0_PREFIX, DEBUG_PROFILE_STORE_EL1_PREFIX, DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX],
2838e920a95Sopenharmony_ci    };
2848e920a95Sopenharmony_ci    for profile_prefix in profile_prefixes {
2858e920a95Sopenharmony_ci        paths.extend(get_paths_from_prefix(profile_prefix));
2868e920a95Sopenharmony_ci    }
2878e920a95Sopenharmony_ci    paths
2888e920a95Sopenharmony_ci}
2898e920a95Sopenharmony_ci
2908e920a95Sopenharmony_cifn get_paths_from_prefix(prefix: &str) -> Vec<String> {
2918e920a95Sopenharmony_ci    let mut paths = Vec::new();
2928e920a95Sopenharmony_ci    if let Ok(entries) = read_dir(prefix) {
2938e920a95Sopenharmony_ci        for entry in entries.filter_map(Result::ok) {
2948e920a95Sopenharmony_ci            let path = entry.path();
2958e920a95Sopenharmony_ci            let filename = fmt_store_path(&path.to_string_lossy(), PROFILE_STORE_TAIL);
2968e920a95Sopenharmony_ci            if file_exists(&filename) {
2978e920a95Sopenharmony_ci                paths.push(filename);
2988e920a95Sopenharmony_ci            }
2998e920a95Sopenharmony_ci        }
3008e920a95Sopenharmony_ci    }
3018e920a95Sopenharmony_ci    paths
3028e920a95Sopenharmony_ci}
3038e920a95Sopenharmony_ci
3048e920a95Sopenharmony_ci/// add profile cert path data
3058e920a95Sopenharmony_cipub fn add_profile_cert_path(
3068e920a95Sopenharmony_ci    root_cert: &PemCollection,
3078e920a95Sopenharmony_ci    cert_paths: &TrustCertPath,
3088e920a95Sopenharmony_ci) -> Result<(), ProfileError> {
3098e920a95Sopenharmony_ci    let x509_store = root_cert.to_x509_store().unwrap();
3108e920a95Sopenharmony_ci    if process_profile(false, &x509_store, cert_paths.get_profile_info().as_slice()).is_err() {
3118e920a95Sopenharmony_ci        return Err(ProfileError::AddCertPathError);
3128e920a95Sopenharmony_ci    }
3138e920a95Sopenharmony_ci    if process_profile(true, &x509_store, cert_paths.get_debug_profile_info().as_slice()).is_err() {
3148e920a95Sopenharmony_ci        return Err(ProfileError::AddCertPathError);
3158e920a95Sopenharmony_ci    }
3168e920a95Sopenharmony_ci    Ok(())
3178e920a95Sopenharmony_ci}
3188e920a95Sopenharmony_ci
3198e920a95Sopenharmony_cifn process_profile(
3208e920a95Sopenharmony_ci    is_debug: bool,
3218e920a95Sopenharmony_ci    x509_store: &X509Store,
3228e920a95Sopenharmony_ci    profile_info: &[(&String, &String)],
3238e920a95Sopenharmony_ci) -> Result<(), ProfileError> {
3248e920a95Sopenharmony_ci    let profiles_paths = get_profile_paths(is_debug);
3258e920a95Sopenharmony_ci    for path in profiles_paths {
3268e920a95Sopenharmony_ci        let mut pkcs7_data = Vec::new();
3278e920a95Sopenharmony_ci        if load_bytes_from_file(&path, &mut pkcs7_data).is_err() {
3288e920a95Sopenharmony_ci            info!(LOG_LABEL, "load profile failed {}!", @public(path));
3298e920a95Sopenharmony_ci            continue;
3308e920a95Sopenharmony_ci        }
3318e920a95Sopenharmony_ci        info!(LOG_LABEL, "load profile success {}!", @public(path));
3328e920a95Sopenharmony_ci        let pkcs7 = match Pkcs7::from_der(&pkcs7_data) {
3338e920a95Sopenharmony_ci            Ok(pk7) => pk7,
3348e920a95Sopenharmony_ci            Err(_) => {
3358e920a95Sopenharmony_ci                error!(LOG_LABEL, "load profile to pkcs7 obj failed {}!", @public(path));
3368e920a95Sopenharmony_ci                continue;
3378e920a95Sopenharmony_ci            }
3388e920a95Sopenharmony_ci        };
3398e920a95Sopenharmony_ci        if verify_signers(&pkcs7, profile_info).is_err() {
3408e920a95Sopenharmony_ci            error!(LOG_LABEL, "Invalid signer profile file {}", @public(path));
3418e920a95Sopenharmony_ci            report_parse_profile_err(&path, HisyseventProfileError::VerifySigner as i32);
3428e920a95Sopenharmony_ci            continue;
3438e920a95Sopenharmony_ci        }
3448e920a95Sopenharmony_ci        let check_udid = unsafe { !IsRdDevice() };
3458e920a95Sopenharmony_ci        let (subject, issuer, profile_type) =
3468e920a95Sopenharmony_ci            match parse_pkcs7_data(&pkcs7, x509_store, Pkcs7Flags::empty(), check_udid) {
3478e920a95Sopenharmony_ci                Ok(tuple) => tuple,
3488e920a95Sopenharmony_ci                Err(e) => {
3498e920a95Sopenharmony_ci                    error!(LOG_LABEL, "Error parsing PKCS7 data: {}, profile file {}",
3508e920a95Sopenharmony_ci                        @public(e), @public(path));
3518e920a95Sopenharmony_ci                    report_parse_profile_err(&path, HisyseventProfileError::ParsePkcs7 as i32);
3528e920a95Sopenharmony_ci                    continue;
3538e920a95Sopenharmony_ci                }
3548e920a95Sopenharmony_ci            };
3558e920a95Sopenharmony_ci        if add_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() {
3568e920a95Sopenharmony_ci            error!(
3578e920a95Sopenharmony_ci                LOG_LABEL,
3588e920a95Sopenharmony_ci                "Failed to add profile cert path info into ioctl for {}", @public(path)
3598e920a95Sopenharmony_ci            );
3608e920a95Sopenharmony_ci            report_parse_profile_err(&path, HisyseventProfileError::AddCertPath as i32);
3618e920a95Sopenharmony_ci            continue;
3628e920a95Sopenharmony_ci        }
3638e920a95Sopenharmony_ci    }
3648e920a95Sopenharmony_ci    Ok(())
3658e920a95Sopenharmony_ci}
3668e920a95Sopenharmony_ci
3678e920a95Sopenharmony_cifn verify_udid(profile_json: &JsonValue) -> Result<(), String> {
3688e920a95Sopenharmony_ci    let device_udid = get_udid()?;
3698e920a95Sopenharmony_ci    info!(LOG_LABEL, "get device udid {}!", device_udid);
3708e920a95Sopenharmony_ci    let device_id_type = &profile_json[PROFILE_DEBUG_INFO_KEY][PROFILE_DEVICE_ID_TYPE_KEY];
3718e920a95Sopenharmony_ci
3728e920a95Sopenharmony_ci    if let JsonValue::String(id_type) = device_id_type {
3738e920a95Sopenharmony_ci        if id_type != "udid" {
3748e920a95Sopenharmony_ci            return Err("Invalid device ID type".to_string());
3758e920a95Sopenharmony_ci        }
3768e920a95Sopenharmony_ci    } else {
3778e920a95Sopenharmony_ci        return Err("Device ID type is not a string".to_string());
3788e920a95Sopenharmony_ci    }
3798e920a95Sopenharmony_ci    match &profile_json[PROFILE_DEBUG_INFO_KEY][PROFILE_DEVICE_IDS_KEY] {
3808e920a95Sopenharmony_ci        JsonValue::Array(arr) => {
3818e920a95Sopenharmony_ci            if arr.iter().any(|item| match item {
3828e920a95Sopenharmony_ci                JsonValue::String(s) => s == &device_udid,
3838e920a95Sopenharmony_ci                _ => false,
3848e920a95Sopenharmony_ci            }) {
3858e920a95Sopenharmony_ci                Ok(())
3868e920a95Sopenharmony_ci            } else {
3878e920a95Sopenharmony_ci                Err("UDID not found in the list".to_string())
3888e920a95Sopenharmony_ci            }
3898e920a95Sopenharmony_ci        }
3908e920a95Sopenharmony_ci        _ => Err("Device IDs are not in an array format".to_string()),
3918e920a95Sopenharmony_ci    }
3928e920a95Sopenharmony_ci}
3938e920a95Sopenharmony_ci
3948e920a95Sopenharmony_cifn validate_and_convert_inputs(
3958e920a95Sopenharmony_ci    bundle_name: *const c_char,
3968e920a95Sopenharmony_ci    profile: *const u8,
3978e920a95Sopenharmony_ci    profile_size: u32,
3988e920a95Sopenharmony_ci) -> Result<(String, Vec<u8>), ()> {
3998e920a95Sopenharmony_ci    let _bundle_name = c_char_to_string(bundle_name);
4008e920a95Sopenharmony_ci    if _bundle_name.is_empty() {
4018e920a95Sopenharmony_ci        error!(LOG_LABEL, "invalid profile bundle name!");
4028e920a95Sopenharmony_ci        return Err(());
4038e920a95Sopenharmony_ci    }
4048e920a95Sopenharmony_ci    let profile_data = cbyte_buffer_to_vec(profile, profile_size);
4058e920a95Sopenharmony_ci    Ok((_bundle_name, profile_data))
4068e920a95Sopenharmony_ci}
4078e920a95Sopenharmony_ci
4088e920a95Sopenharmony_cifn process_data(profile_data: &[u8]) -> Result<(String, String, u32), ()> {
4098e920a95Sopenharmony_ci    let store = match X509StoreBuilder::new() {
4108e920a95Sopenharmony_ci        Ok(store) => store.build(),
4118e920a95Sopenharmony_ci        Err(_) => {
4128e920a95Sopenharmony_ci            error!(LOG_LABEL, "Failed to build X509 store");
4138e920a95Sopenharmony_ci            return Err(());
4148e920a95Sopenharmony_ci        }
4158e920a95Sopenharmony_ci    };
4168e920a95Sopenharmony_ci
4178e920a95Sopenharmony_ci    let pkcs7 = match Pkcs7::from_der(profile_data) {
4188e920a95Sopenharmony_ci        Ok(pk7) => pk7,
4198e920a95Sopenharmony_ci        Err(_) => {
4208e920a95Sopenharmony_ci            error!(LOG_LABEL, "load profile to pkcs7 obj failed");
4218e920a95Sopenharmony_ci            return Err(());
4228e920a95Sopenharmony_ci        }
4238e920a95Sopenharmony_ci    };
4248e920a95Sopenharmony_ci
4258e920a95Sopenharmony_ci    match parse_pkcs7_data(&pkcs7, &store, Pkcs7Flags::NOVERIFY, false) {
4268e920a95Sopenharmony_ci        Ok(tuple) => Ok(tuple),
4278e920a95Sopenharmony_ci        Err(_) => {
4288e920a95Sopenharmony_ci            error!(LOG_LABEL, "parse pkcs7 data error");
4298e920a95Sopenharmony_ci            Err(())
4308e920a95Sopenharmony_ci        }
4318e920a95Sopenharmony_ci    }
4328e920a95Sopenharmony_ci}
4338e920a95Sopenharmony_ci
4348e920a95Sopenharmony_cifn create_bundle_path(bundle_name: &str, profile_type: u32) -> Result<String, ()> {
4358e920a95Sopenharmony_ci    let bundle_path = match profile_type {
4368e920a95Sopenharmony_ci        value if value == DebugCertPathType::Developer as u32 => {
4378e920a95Sopenharmony_ci            fmt_store_path(DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX, bundle_name)
4388e920a95Sopenharmony_ci        }
4398e920a95Sopenharmony_ci        value if value == ReleaseCertPathType::Developer as u32 => {
4408e920a95Sopenharmony_ci            fmt_store_path(PROFILE_STORE_EL1_PUBLIC_PREFIX, bundle_name)
4418e920a95Sopenharmony_ci        }
4428e920a95Sopenharmony_ci        _ => {
4438e920a95Sopenharmony_ci            error!(LOG_LABEL, "invalid profile type");
4448e920a95Sopenharmony_ci            return Err(());
4458e920a95Sopenharmony_ci        }
4468e920a95Sopenharmony_ci    };
4478e920a95Sopenharmony_ci    Ok(bundle_path)
4488e920a95Sopenharmony_ci}
4498e920a95Sopenharmony_ci
4508e920a95Sopenharmony_cifn enable_key_in_profile_internal(
4518e920a95Sopenharmony_ci    bundle_name: *const c_char,
4528e920a95Sopenharmony_ci    profile: *const u8,
4538e920a95Sopenharmony_ci    profile_size: u32,
4548e920a95Sopenharmony_ci) -> Result<(), ()> {
4558e920a95Sopenharmony_ci    let (_bundle_name, profile_data) = validate_and_convert_inputs(bundle_name, profile, profile_size)?;
4568e920a95Sopenharmony_ci    let (subject, issuer, profile_type) = process_data(&profile_data)?;
4578e920a95Sopenharmony_ci    let bundle_path = create_bundle_path(&_bundle_name, profile_type)?;
4588e920a95Sopenharmony_ci    info!(LOG_LABEL, "create bundle_path path {}!", @public(bundle_path));
4598e920a95Sopenharmony_ci    if !file_exists(&bundle_path) && create_file_path(&bundle_path).is_err() {
4608e920a95Sopenharmony_ci        error!(LOG_LABEL, "create bundle_path path {} failed!", @public(bundle_path));
4618e920a95Sopenharmony_ci        return Err(());
4628e920a95Sopenharmony_ci    }
4638e920a95Sopenharmony_ci    if change_default_mode_directory(&bundle_path).is_err() {
4648e920a95Sopenharmony_ci        error!(LOG_LABEL, "change bundle_path mode error!");
4658e920a95Sopenharmony_ci        return Err(());
4668e920a95Sopenharmony_ci    }
4678e920a95Sopenharmony_ci    let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL);
4688e920a95Sopenharmony_ci    if write_bytes_to_file(&filename, &profile_data).is_err() {
4698e920a95Sopenharmony_ci        error!(LOG_LABEL, "dump profile data error!");
4708e920a95Sopenharmony_ci        return Err(());
4718e920a95Sopenharmony_ci    }
4728e920a95Sopenharmony_ci    if change_default_mode_file(&filename).is_err() {
4738e920a95Sopenharmony_ci        error!(LOG_LABEL, "change profile mode error!");
4748e920a95Sopenharmony_ci        return Err(());
4758e920a95Sopenharmony_ci    }
4768e920a95Sopenharmony_ci    if add_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() {
4778e920a95Sopenharmony_ci        error!(LOG_LABEL, "add profile data error!");
4788e920a95Sopenharmony_ci        return Err(());
4798e920a95Sopenharmony_ci    }
4808e920a95Sopenharmony_ci    info!(LOG_LABEL, "finish add cert path in ioctl!");
4818e920a95Sopenharmony_ci    Ok(())
4828e920a95Sopenharmony_ci}
4838e920a95Sopenharmony_ci
4848e920a95Sopenharmony_cifn process_remove_bundle(
4858e920a95Sopenharmony_ci    prefix: &str,
4868e920a95Sopenharmony_ci    bundle_name: &str,
4878e920a95Sopenharmony_ci) -> Result<(), ()> {
4888e920a95Sopenharmony_ci    let bundle_path = fmt_store_path(prefix, bundle_name);
4898e920a95Sopenharmony_ci
4908e920a95Sopenharmony_ci    if !file_exists(&bundle_path) {
4918e920a95Sopenharmony_ci        return Err(());
4928e920a95Sopenharmony_ci    }
4938e920a95Sopenharmony_ci
4948e920a95Sopenharmony_ci    let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL);
4958e920a95Sopenharmony_ci    let mut profile_data = Vec::new();
4968e920a95Sopenharmony_ci    if load_bytes_from_file(&filename, &mut profile_data).is_err() {
4978e920a95Sopenharmony_ci        error!(LOG_LABEL, "load profile data error!");
4988e920a95Sopenharmony_ci        return Err(());
4998e920a95Sopenharmony_ci    }
5008e920a95Sopenharmony_ci
5018e920a95Sopenharmony_ci    let (subject, issuer, profile_type) = process_data(&profile_data)?;
5028e920a95Sopenharmony_ci    if delete_file_path(&bundle_path).is_err() {
5038e920a95Sopenharmony_ci        error!(LOG_LABEL, "remove profile data error!");
5048e920a95Sopenharmony_ci        return Err(());
5058e920a95Sopenharmony_ci    }
5068e920a95Sopenharmony_ci
5078e920a95Sopenharmony_ci    info!(LOG_LABEL, "remove bundle_path path {}!", @public(bundle_path));
5088e920a95Sopenharmony_ci
5098e920a95Sopenharmony_ci    if remove_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() {
5108e920a95Sopenharmony_ci        error!(LOG_LABEL, "remove profile data error!");
5118e920a95Sopenharmony_ci        return Err(());
5128e920a95Sopenharmony_ci    }
5138e920a95Sopenharmony_ci
5148e920a95Sopenharmony_ci    info!(LOG_LABEL, "finish remove cert path in ioctl!");
5158e920a95Sopenharmony_ci    Ok(())
5168e920a95Sopenharmony_ci}
5178e920a95Sopenharmony_ci
5188e920a95Sopenharmony_cifn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> {
5198e920a95Sopenharmony_ci    let _bundle_name = c_char_to_string(bundle_name);
5208e920a95Sopenharmony_ci    if _bundle_name.is_empty() {
5218e920a95Sopenharmony_ci        error!(LOG_LABEL, "Invalid bundle name");
5228e920a95Sopenharmony_ci        return Err(());
5238e920a95Sopenharmony_ci    }
5248e920a95Sopenharmony_ci
5258e920a95Sopenharmony_ci    let profile_prefix = vec![
5268e920a95Sopenharmony_ci        DEBUG_PROFILE_STORE_EL0_PREFIX,
5278e920a95Sopenharmony_ci        PROFILE_STORE_EL0_PREFIX,
5288e920a95Sopenharmony_ci        DEBUG_PROFILE_STORE_EL1_PREFIX,
5298e920a95Sopenharmony_ci        PROFILE_STORE_EL1_PREFIX,
5308e920a95Sopenharmony_ci        DEBUG_PROFILE_STORE_EL1_PUBLIC_PREFIX,
5318e920a95Sopenharmony_ci        PROFILE_STORE_EL1_PUBLIC_PREFIX,
5328e920a95Sopenharmony_ci    ];
5338e920a95Sopenharmony_ci
5348e920a95Sopenharmony_ci    let mut rm_succ = false;
5358e920a95Sopenharmony_ci    for prefix in profile_prefix {
5368e920a95Sopenharmony_ci        if process_remove_bundle(prefix, &_bundle_name).is_ok() {
5378e920a95Sopenharmony_ci            rm_succ = true;
5388e920a95Sopenharmony_ci        }
5398e920a95Sopenharmony_ci    }
5408e920a95Sopenharmony_ci    if rm_succ {
5418e920a95Sopenharmony_ci        Ok(())
5428e920a95Sopenharmony_ci    } else {
5438e920a95Sopenharmony_ci        error!(LOG_LABEL, "Failed to remove bundle profile info, bundleName: {}.", @public(_bundle_name));
5448e920a95Sopenharmony_ci        Err(())
5458e920a95Sopenharmony_ci    }
5468e920a95Sopenharmony_ci}
5478e920a95Sopenharmony_ci
5488e920a95Sopenharmony_cifn c_char_to_string(c_str: *const c_char) -> String {
5498e920a95Sopenharmony_ci    unsafe {
5508e920a95Sopenharmony_ci        if c_str.is_null() {
5518e920a95Sopenharmony_ci            return String::new();
5528e920a95Sopenharmony_ci        }
5538e920a95Sopenharmony_ci        let c_str = CStr::from_ptr(c_str);
5548e920a95Sopenharmony_ci        c_str.to_string_lossy().to_string()
5558e920a95Sopenharmony_ci    }
5568e920a95Sopenharmony_ci}
5578e920a95Sopenharmony_ci
5588e920a95Sopenharmony_cifn cbyte_buffer_to_vec(data: *const u8, size: u32) -> Vec<u8> {
5598e920a95Sopenharmony_ci    unsafe {
5608e920a95Sopenharmony_ci        if data.is_null() {
5618e920a95Sopenharmony_ci            return Vec::new();
5628e920a95Sopenharmony_ci        }
5638e920a95Sopenharmony_ci        let data_slice = std::slice::from_raw_parts(data, size as usize);
5648e920a95Sopenharmony_ci        let mut result = Vec::with_capacity(size as usize);
5658e920a95Sopenharmony_ci        result.extend_from_slice(data_slice);
5668e920a95Sopenharmony_ci        result
5678e920a95Sopenharmony_ci    }
5688e920a95Sopenharmony_ci}
569