From c9cfa8cdef8baaa6916b5e125cd67c10961311c6 Mon Sep 17 00:00:00 2001 From: yeyuning Date: Tue, 14 Nov 2023 21:39:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=96=B0=E5=A2=9E=E8=AE=BE=E5=A4=87id?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yeyuning Change-Id: I4571d8c50220e24820f6e93a24f80fb240cce515 --- hisysevent.yaml | 16 +- .../code_sign_utils/include/code_sign_utils.h | 2 + .../code_sign_utils/src/code_sign_utils.cpp | 44 ++-- services/key_enable/BUILD.gn | 2 + services/key_enable/include/rust_interface.h | 4 +- services/key_enable/key_enable.cfg | 6 +- services/key_enable/src/cert_path_utils.rs | 3 +- services/key_enable/src/cs_hisysevent.rs | 7 +- services/key_enable/src/file_utils.rs | 41 +++- services/key_enable/src/profile_utils.rs | 205 +++++++++++++----- services/key_enable/utils/include/cert_path.h | 2 + services/key_enable/utils/src/cert_path.cpp | 6 + test/unittest/BUILD.gn | 2 + test/unittest/code_sign_utils_test.cpp | 13 +- test/unittest/enable_verity_test.cpp | 1 - utils/include/cs_hisysevent.h | 13 ++ 16 files changed, 282 insertions(+), 85 deletions(-) diff --git a/hisysevent.yaml b/hisysevent.yaml index 6c60af2..015ed8b 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -59,6 +59,18 @@ CS_SA_INVALID_CALLER: INTERFACE: {type: STRING, desc: 'interface type, Cert or Sign'} TOKEN_ID : {type: UINT32, desc: token id of invalid caller} +CS_PARSE_CODE_SIG: + __BASE: {type: FAULT, level: CRITICAL, desc: parse code sig failed} + FILE_INFO: {type: STRING, desc: info of hap file} + ERR_TYPE : {type: UINT32, desc: parse cide sig error type} + +CS_INVALID_OWNER: + __BASE: {type: SECURITY, level: CRITICAL, desc: invalid owner} + FILE_INFO: {type: STRING, desc: info of hap file} + OWNER_ID: {type: STRING, desc: owner id of the hap file} + PARSED_OWNER_ID: {type: STRING, desc: owner id in the signature} + CS_ERR_PROFILE: - __BASE: {type: FAULT, level: CRITICAL, desc: parsing local profile failure event} - PROFILE_PATH: {type: STRING, desc: profile path at local sotrage} \ No newline at end of file + __BASE: {type: SECURITY, level: CRITICAL, desc: parsing local profile failure event} + PROFILE_INFO: {type: STRING, desc: profile path at local sotrage} + ERR_TYPE: {type: INT32, desc: profile parse error type} \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h index 1fa5e67..627d173 100644 --- a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h @@ -108,6 +108,8 @@ private: static int32_t IsFsVerityEnabled(int fd); static int32_t EnableCodeSignForFile(const std::string &path, const struct code_sign_enable_arg &arg); static void ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg); + static int32_t CheckOwnerId(const std::string &path, const std::string &ownerId, + const uint8_t *sigPtr, uint32_t sigSize); }; } } diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp index efdc273..ff847ce 100644 --- a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp @@ -227,6 +227,29 @@ void CodeSignUtils::ShowCodeSignInfo(const std::string &path, const struct code_ rootHashPtr[0], rootHashPtr[1], rootHashPtr[2], rootHashPtr[32], rootHashPtr[63]); // 2, 32, 63 data index } +int32_t CodeSignUtils::CheckOwnerId(const std::string &path, const std::string &ownerId, + const uint8_t *sigPtr, uint32_t sigSize) +{ + if (ownerId.empty()) { + return CS_SUCCESS; + } + + int32_t ret; + ByteBuffer sigBuffer; + sigBuffer.CopyFrom(reinterpret_cast(sigPtr), sigSize); + std::string retId; + ret = SignerInfo::ParseOwnerIdFromSignature(sigBuffer, retId); + if (ret != CS_SUCCESS) { + ReportInvalidOwner(path, ownerId, "invalid"); + LOG_ERROR(LABEL, "get ownerId from signature failed, ret %{public}d", ret); + } else if (retId != ownerId) { + ret = CS_ERR_INVALID_OWNER_ID; + ReportInvalidOwner(path, ownerId, retId); + LOG_ERROR(LABEL, "invalid ownerId retId %{public}s ownerId %{public}s", retId.c_str(), ownerId.c_str()); + } + return ret; +} + int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(std::string ownerId, const std::string &path, const EntryMap &entryPathMap, FileType type) { @@ -249,9 +272,11 @@ int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(std::string ownerId, con CodeSignBlock codeSignBlock; ret = codeSignBlock.ParseCodeSignBlock(realPath, entryPathMap, type); if (ret != CS_SUCCESS) { + if (ret != CS_CODE_SIGN_NOT_EXISTS) { + ReportParseCodeSig(realPath, ret); + } return ret; } - do { std::string targetFile; struct code_sign_enable_arg arg = {0}; @@ -263,23 +288,12 @@ int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(std::string ownerId, con return ret; } - if (!ownerId.empty()) { - ByteBuffer sigBuffer; - sigBuffer.CopyFrom(reinterpret_cast(arg.sig_ptr), arg.sig_size); - std::string retId; - ret = SignerInfo::ParseOwnerIdFromSignature(sigBuffer, retId); - if (ret != CS_SUCCESS) { - LOG_ERROR(LABEL, "get ownerId from signature failed, ret %{public}d", ret); - break; - } else if (retId != ownerId) { - ret = CS_ERR_INVALID_OWNER_ID; - LOG_ERROR(LABEL, "invalid ownerId retId %{public}s ownerId %{public}s", retId.c_str(), ownerId.c_str()); - break; - } + ret = CheckOwnerId(path, ownerId, reinterpret_cast(arg.sig_ptr), arg.sig_size); + if (ret != CS_SUCCESS) { + break; } ShowCodeSignInfo(targetFile, arg); - if (!CheckFilePathValid(targetFile, Constants::ENABLE_APP_BASE_PATH)) { return CS_ERR_TARGET_FILE_PATH; } diff --git a/services/key_enable/BUILD.gn b/services/key_enable/BUILD.gn index d6656db..f1e309e 100644 --- a/services/key_enable/BUILD.gn +++ b/services/key_enable/BUILD.gn @@ -17,8 +17,10 @@ import("../../code_signature.gni") common_deps = [ "${rust_openssl_dir}/openssl:lib", "utils:libkey_enable_utils", + "//third_party/rust/crates/cxx:lib", ] common_external_deps = [ + "c_utils:utils_rust", "hilog:hilog_rust", "hisysevent:hisysevent_rust", "ylong_json:lib", diff --git a/services/key_enable/include/rust_interface.h b/services/key_enable/include/rust_interface.h index 8fc0201..921b30e 100644 --- a/services/key_enable/include/rust_interface.h +++ b/services/key_enable/include/rust_interface.h @@ -21,8 +21,8 @@ #ifdef __cplusplus extern "C" { #endif - int32_t EnableKeyInProfileByRust(const char* bundle_name, const uint8_t* profile, uint32_t profile_size); - int32_t RemoveKeyInProfileByRust(const char* bundle_name); + int32_t EnableKeyInProfileByRust(const char* bundleName, const uint8_t* profile, uint32_t profileSize); + int32_t RemoveKeyInProfileByRust(const char* bundleName); #ifdef __cplusplus } #endif diff --git a/services/key_enable/key_enable.cfg b/services/key_enable/key_enable.cfg index 5db47ac..5e6f25b 100644 --- a/services/key_enable/key_enable.cfg +++ b/services/key_enable/key_enable.cfg @@ -3,9 +3,9 @@ "name" : "post-fs-data", "cmds" : [ "write /proc/sys/fs/verity/require_signatures 1", - "mkdir /data/service/el0/profiles 0644 installs installs", - "mkdir /data/service/el0/profiles/developer 0644 installs installs", - "mkdir /data/service/el0/profiles/debug 0644 installs installs" + "mkdir /data/service/el0/profiles 0655 installs installs", + "mkdir /data/service/el0/profiles/developer 0655 installs installs", + "mkdir /data/service/el0/profiles/debug 0655 installs installs" ] } ], diff --git a/services/key_enable/src/cert_path_utils.rs b/services/key_enable/src/cert_path_utils.rs index 011c5bb..82d2ae0 100644 --- a/services/key_enable/src/cert_path_utils.rs +++ b/services/key_enable/src/cert_path_utils.rs @@ -14,7 +14,7 @@ */ use super::cs_hisysevent; use super::profile_utils::IsDeveloperModeOn; -use hilog_rust::{error, hilog, HiLogLabel, LogType}; +use hilog_rust::{error, hilog, info, HiLogLabel, LogType}; use std::ffi::{c_char, CString}; use ylong_json::JsonValue; @@ -400,6 +400,7 @@ where __reserved: [0; 32], }; let ret = operation(&cert_path_info); + info!(LOG_LABEL, "ioctl return:{}", @public(ret)); if ret < 0 { cs_hisysevent::report_add_key_err(op_name, ret); return Err(CertPathError::CertPathOperationError); diff --git a/services/key_enable/src/cs_hisysevent.rs b/services/key_enable/src/cs_hisysevent.rs index 92718be..ef6861b 100644 --- a/services/key_enable/src/cs_hisysevent.rs +++ b/services/key_enable/src/cs_hisysevent.rs @@ -29,13 +29,14 @@ pub fn report_add_key_err(cert_type: &str, errcode: i32) { } /// report parse local profile err by hisysevent -pub fn report_parse_profile_err(profile_path: &str) { +pub fn report_parse_profile_err(profile_path: &str, errcode: i32) { hisysevent::write( "CODE_SIGN", - "CSS_ERR_PROFILE", - EventType::Fault, + "CS_ERR_PROFILE", + EventType::Security, &[ hisysevent::build_str_param!("STRING_SINGLE", profile_path), + hisysevent::build_number_param!("INT32_SINGLE", errcode), ], ); } \ No newline at end of file diff --git a/services/key_enable/src/file_utils.rs b/services/key_enable/src/file_utils.rs index ae7ae84..d73b0c6 100644 --- a/services/key_enable/src/file_utils.rs +++ b/services/key_enable/src/file_utils.rs @@ -12,9 +12,46 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -use std::fs::{remove_dir_all , create_dir_all, File}; +use std::fs::{create_dir_all, remove_dir_all, File}; use std::io::{Read, Write}; use std::path::Path; +use cxx::let_cxx_string; +use utils_rust::directory_ex; +// rw-r--r-- +const PROFILE_FILE_MODE: u32 = 0o644; +// rw-r-xr-x +const PROFILE_PATH_MODE: u32 = 0o655; +/// code sign file error +pub enum CodeSignFileError { + /// change file mode error + ChangeFileModError, + /// change path mode error + ChangePathModError, + } +/// change default mode of file +pub fn change_default_mode_file(path_file: &str) -> Result<(), CodeSignFileError> { + let_cxx_string!(dirpath = path_file); + let mode = PROFILE_FILE_MODE; + let ret = directory_ex::ffi::ChangeModeFile(&dirpath, &mode); + if !ret { + return Err(CodeSignFileError::ChangeFileModError); + } + Ok(()) +} +/// change default mode of directory +pub fn change_default_mode_directory(path_file: &str) -> Result<(), CodeSignFileError> { + let_cxx_string!(dirpath = path_file); + let mode = PROFILE_PATH_MODE; + let ret = directory_ex::ffi::ChangeModeDirectory(&dirpath, &mode); + if !ret { + return Err(CodeSignFileError::ChangePathModError); + } + Ok(()) +} +/// format storage file path +pub fn fmt_store_path(prefix: &str, tail: &str) -> String { + format!("{}/{}", prefix, tail) +} /// create file path with path name pub fn create_file_path(path_name: &str) -> Result<(), std::io::Error> { let path = Path::new(path_name); @@ -33,7 +70,7 @@ pub fn load_bytes_from_file(filename: &str, buffer: &mut Vec) -> Result<(), file.read_to_end(buffer)?; Ok(()) } -/// find file +/// find file pub fn file_exists(file_path: &str) -> bool { Path::new(file_path).exists() } diff --git a/services/key_enable/src/profile_utils.rs b/services/key_enable/src/profile_utils.rs index 9ac3a80..22ff761 100644 --- a/services/key_enable/src/profile_utils.rs +++ b/services/key_enable/src/profile_utils.rs @@ -15,14 +15,15 @@ use super::cert_chain_utils::PemCollection; use super::cert_path_utils::{ - add_cert_path_info, remove_cert_path_info, DebugCertPathType, ReleaseCertPathType, - TrustCertPath, + add_cert_path_info, remove_cert_path_info, + DebugCertPathType, ReleaseCertPathType, TrustCertPath, }; use super::cs_hisysevent::report_parse_profile_err; use super::file_utils::{ - create_file_path, delete_file_path, file_exists, load_bytes_from_file, write_bytes_to_file, + create_file_path, delete_file_path, file_exists, fmt_store_path, + load_bytes_from_file, write_bytes_to_file, change_default_mode_file, change_default_mode_directory }; -use hilog_rust::{error, hilog, HiLogLabel, LogType}; +use hilog_rust::{error, info, hilog, HiLogLabel, LogType}; use openssl::pkcs7::{Pkcs7, Pkcs7Flags}; use openssl::stack::Stack; use openssl::x509::store::{X509Store, X509StoreBuilder}; @@ -43,22 +44,34 @@ const PROFILE_STORE_PREFIX: &str = "/data/service/el0/profiles/developer"; const DEBUG_PROFILE_STORE_PREFIX: &str = "/data/service/el0/profiles/debug"; const PROFILE_STORE_TAIL: &str = "profile.p7b"; const PROFILE_TYPE_KEY: &str = "type"; +const PROFILE_DEVICE_ID_TYPE_KEY: &str = "device-id-type"; +const PROFILE_DEBUG_INFO_KEY: &str = "debug-info"; +const PROFILE_DEVICE_IDS_KEY: &str = "device-ids"; const PROFILE_BUNDLE_INFO_KEY: &str = "bundle-info"; const PROFILE_BUNDLE_INFO_RELEASE_KEY: &str = "distribution-certificate"; const PROFILE_BUNDLE_INFO_DEBUG_KEY: &str = "development-certificate"; const DEFAULT_MAX_CERT_PATH_LEN: u32 = 3; const PROFILE_RELEASE_TYPE: &str = "release"; const PROFILE_DEBUG_TYPE: &str = "debug"; - /// profile error pub enum ProfileError { /// add cert path error AddCertPathError, } +/// profile error report to hisysevent +pub enum HisyseventProfileError { + /// release platform code + VerifySigner = 1, + /// release authed code + ParsePkcs7 = 2, + /// release developer code + AddCertPath = 3, +} extern "C" { /// if developer state on return true pub fn IsDeveloperModeOn() -> bool; + fn CodeSignGetUdid(udid: *mut u8) -> i32; } #[no_mangle] @@ -84,36 +97,24 @@ pub extern "C" fn RemoveKeyInProfileByRust(bundle_name: *const c_char) -> i32 { } fn parse_pkcs7_data( - profile_data: &[u8], + pkcs7: &Pkcs7, root_store: &X509Store, - profile_signer: &[(&String, &String)], - verify: bool, + flags: Pkcs7Flags, ) -> Result<(String, String, u32), Box> { - let pkcs7 = Pkcs7::from_der(profile_data)?; let stack_of_certs = Stack::::new()?; - let flags = if verify { - let signers_result = pkcs7.signers(&stack_of_certs, Pkcs7Flags::empty())?; - for signer in signers_result { - let subject_name = format_x509name_to_string(signer.subject_name()); - let issuer_name = format_x509name_to_string(signer.issuer_name()); - if !profile_signer.contains(&(&subject_name, &issuer_name)) { - return Err("Verification failed.".into()); - } - } - Pkcs7Flags::empty() - } else { - Pkcs7Flags::NOVERIFY - }; - let mut profile = Vec::new(); if pkcs7.verify(&stack_of_certs, root_store, None, Some(&mut profile), flags).is_err() { error!(LOG_LABEL, "pkcs7 verify failed."); return Err("pkcs7 verify failed.".into()); } - let profile_json = JsonValue::from_text(profile)?; let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str(); + + if bundle_type == PROFILE_DEBUG_TYPE && verify_udid(&profile_json).is_err() { + error!(LOG_LABEL, "udid verify failed."); + return Err("Invalid udid .".into()); + } let profile_type = match bundle_type { PROFILE_DEBUG_TYPE => DebugCertPathType::Developer as u32, PROFILE_RELEASE_TYPE => ReleaseCertPathType::Developer as u32, @@ -126,7 +127,8 @@ fn parse_pkcs7_data( PROFILE_DEBUG_TYPE => { profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_DEBUG_KEY].try_as_string()? } - PROFILE_RELEASE_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_BUNDLE_INFO_RELEASE_KEY] + PROFILE_RELEASE_TYPE => profile_json[PROFILE_BUNDLE_INFO_KEY] + [PROFILE_BUNDLE_INFO_RELEASE_KEY] .try_as_string()?, _ => { error!(LOG_LABEL, "pkcs7 verify failed."); @@ -140,6 +142,40 @@ fn parse_pkcs7_data( Ok((subject, issuer, profile_type)) } +fn get_udid() -> Result { + let mut udid: Vec = vec![0; 128]; + let result = unsafe { CodeSignGetUdid(udid.as_mut_ptr()) }; + + if result != 0 { + return Err("Failed to get UDID".to_string()); + } + + if let Some(first_zero_index) = udid.iter().position(|&x| x == 0) { + udid.truncate(first_zero_index); + } + + match String::from_utf8(udid) { + Ok(s) => Ok(s), + Err(_) => Err("UDID is not valid UTF-8".to_string()), + } +} + +fn verify_signers( + pkcs7: &Pkcs7, + profile_signer: &[(&String, &String)], +) -> Result<(), Box> { + let stack_of_certs = Stack::::new()?; + let signers_result = pkcs7.signers(&stack_of_certs, Pkcs7Flags::empty())?; + for signer in signers_result { + let subject_name = format_x509name_to_string(signer.subject_name()); + let issuer_name = format_x509name_to_string(signer.issuer_name()); + if !profile_signer.contains(&(&subject_name, &issuer_name)) { + return Err("Verification failed.".into()); + } + } + Ok(()) +} + fn format_x509name_to_string(name: &X509NameRef) -> String { let mut parts = Vec::new(); @@ -166,7 +202,7 @@ fn get_profile_paths(is_debug: bool) -> Vec { if let Ok(entries) = read_dir(profile_paths) { for entry in entries.filter_map(Result::ok) { let path = entry.path(); - let filename = format!("{}/{}", path.to_string_lossy(), PROFILE_STORE_TAIL); + let filename = fmt_store_path(&path.to_string_lossy(), PROFILE_STORE_TAIL); if file_exists(&filename) { paths.push(filename); } @@ -181,21 +217,17 @@ pub fn add_profile_cert_path( cert_paths: &TrustCertPath, ) -> Result<(), ProfileError> { let x509_store = root_cert.to_x509_store().unwrap(); - if process_profile_paths(false, &x509_store, cert_paths.get_profile_info().as_slice()).is_err() { + if process_profile(false, &x509_store, cert_paths.get_profile_info().as_slice()).is_err() { return Err(ProfileError::AddCertPathError); } if unsafe { IsDeveloperModeOn() } - && process_profile_paths( - true, - &x509_store, - cert_paths.get_debug_profile_info().as_slice(), - ).is_err() { + && process_profile(true, &x509_store, cert_paths.get_debug_profile_info().as_slice()).is_err() { return Err(ProfileError::AddCertPathError); } Ok(()) } -fn process_profile_paths( +fn process_profile( is_debug: bool, x509_store: &X509Store, profile_info: &[(&String, &String)], @@ -204,29 +236,69 @@ fn process_profile_paths( for path in profiles_paths { let mut pkcs7_data = Vec::new(); if load_bytes_from_file(&path, &mut pkcs7_data).is_err() { + info!(LOG_LABEL, "load profile failed {}!", @public(path)); + continue; + } + info!(LOG_LABEL, "load profile success {}!", @public(path)); + let pkcs7 = match Pkcs7::from_der(&pkcs7_data) { + Ok(pk7) => pk7, + Err(_) => { + error!(LOG_LABEL, "load profile to pkcs7 obj failed {}!", @public(path)); + continue; + } + }; + if verify_signers(&pkcs7, profile_info).is_err() { + error!(LOG_LABEL, "Invalid signer profile file {}", @public(path)); + report_parse_profile_err(&path, HisyseventProfileError::VerifySigner as i32); continue; } let (subject, issuer, profile_type) = - match parse_pkcs7_data(&pkcs7_data, x509_store, profile_info, true) { + match parse_pkcs7_data(&pkcs7, x509_store, Pkcs7Flags::empty()) { Ok(tuple) => tuple, Err(_) => { - error!(LOG_LABEL, "Failed to parse profile file {}", path); - report_parse_profile_err(&path); + error!(LOG_LABEL, "Failed to parse profile file {}", @public(path)); + report_parse_profile_err(&path, HisyseventProfileError::ParsePkcs7 as i32); continue; } }; if add_cert_path_info(&subject, &issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!( LOG_LABEL, - "Failed to add profile cert path info into ioctl for {}", path + "Failed to add profile cert path info into ioctl for {}", @public(path) ); - report_parse_profile_err(&path); + report_parse_profile_err(&path, HisyseventProfileError::AddCertPath as i32); continue; } } Ok(()) } +fn verify_udid(profile_json: &JsonValue) -> Result<(), String> { + let device_udid = get_udid()?; + let device_id_type = &profile_json[PROFILE_DEBUG_INFO_KEY][PROFILE_DEVICE_ID_TYPE_KEY]; + + if let JsonValue::String(id_type) = device_id_type { + if id_type != "udid" { + return Err("Invalid device ID type".to_string()); + } + } else { + return Err("Device ID type is not a string".to_string()); + } + match &profile_json[PROFILE_DEBUG_INFO_KEY][PROFILE_DEVICE_IDS_KEY] { + JsonValue::Array(arr) => { + if arr.iter().any(|item| match item { + JsonValue::String(s) => s == &device_udid, + _ => false, + }) { + Ok(()) + } else { + Err("UDID not found in the list".to_string()) + } + } + _ => Err("Device IDs are not in an array format".to_string()), + } +} + fn enable_key_in_profile_internal( bundle_name: *const c_char, profile: *const u8, @@ -238,7 +310,6 @@ fn enable_key_in_profile_internal( return Err(()); } let profile_data = cbyte_buffer_to_vec(profile, profile_size); - let signer_info: &[(&String, &String)] = &[]; let store = match X509StoreBuilder::new() { Ok(store) => store.build(), Err(_) => { @@ -246,8 +317,15 @@ fn enable_key_in_profile_internal( return Err(()); } }; + let pkcs7 = match Pkcs7::from_der(&profile_data) { + Ok(pk7) => pk7, + Err(_) => { + error!(LOG_LABEL, "load profile to pkcs7 obj failed "); + return Err(()); + } + }; let (subject, issuer, profile_type) = - match parse_pkcs7_data(&profile_data, &store, signer_info, false) { + match parse_pkcs7_data(&pkcs7, &store, Pkcs7Flags::NOVERIFY) { Ok(tuple) => tuple, Err(_) => { error!(LOG_LABEL, "parse pkcs7 data error"); @@ -256,31 +334,39 @@ fn enable_key_in_profile_internal( }; let bundle_path = match profile_type { value if value == DebugCertPathType::Developer as u32 => { - format!("{}/{}", DEBUG_PROFILE_STORE_PREFIX, _bundle_name) + fmt_store_path(DEBUG_PROFILE_STORE_PREFIX, &_bundle_name) } value if value == ReleaseCertPathType::Developer as u32 => { - format!("{}/{}", PROFILE_STORE_PREFIX, _bundle_name) + fmt_store_path(PROFILE_STORE_PREFIX, &_bundle_name) } _ => { error!(LOG_LABEL, "invalid profile type"); return Err(()); } }; + info!(LOG_LABEL, "create bundle_path path {}!", @public(bundle_path)); if !file_exists(&bundle_path) && create_file_path(&bundle_path).is_err() { - error!(LOG_LABEL, "create bundle_path path {} failed!", bundle_path); + error!(LOG_LABEL, "create bundle_path path {} failed!", @public(bundle_path)); return Err(()); } - - let filename = format!("{}/{}", bundle_path, PROFILE_STORE_TAIL); + if change_default_mode_directory(&bundle_path).is_err() { + error!(LOG_LABEL, "change bundle_path mode error!"); + return Err(()); + } + let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL); if write_bytes_to_file(&filename, &profile_data).is_err() { error!(LOG_LABEL, "dump profile data error!"); return Err(()); } - + if change_default_mode_file(&filename).is_err() { + error!(LOG_LABEL, "change profile mode error!"); + return Err(()); + } if add_cert_path_info(&subject, &issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!(LOG_LABEL, "add profile data error!"); return Err(()); } + info!(LOG_LABEL, "finish add cert path in ioctl!"); Ok(()) } @@ -291,8 +377,8 @@ fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> return Err(()); } - let debug_bundle_path = format!("{}/{}", DEBUG_PROFILE_STORE_PREFIX, _bundle_name); - let release_bundle_path = format!("{}/{}", PROFILE_STORE_PREFIX, _bundle_name); + let debug_bundle_path = fmt_store_path(DEBUG_PROFILE_STORE_PREFIX, &_bundle_name); + let release_bundle_path = fmt_store_path(PROFILE_STORE_PREFIX, &_bundle_name); let bundle_path = if file_exists(&debug_bundle_path) { debug_bundle_path @@ -302,14 +388,13 @@ fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> error!(LOG_LABEL, "bundle path does not exists!"); return Err(()); }; - let filename = format!("{}/{}", bundle_path, PROFILE_STORE_TAIL); + let filename = fmt_store_path(&bundle_path, PROFILE_STORE_TAIL); let mut profile_data = Vec::new(); if load_bytes_from_file(&filename, &mut profile_data).is_err() { error!(LOG_LABEL, "load profile data error!"); return Err(()); } - let signer_info: &[(&String, &String)] = &[]; let store = match X509StoreBuilder::new() { Ok(store) => store.build(), Err(_) => { @@ -317,9 +402,15 @@ fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> return Err(()); } }; - + let pkcs7 = match Pkcs7::from_der(&profile_data) { + Ok(pk7) => pk7, + Err(_) => { + error!(LOG_LABEL, "load profile to pkcs7 obj failed"); + return Err(()); + } + }; let (subject, issuer, profile_type) = - match parse_pkcs7_data(&profile_data, &store, signer_info, false) { + match parse_pkcs7_data(&pkcs7, &store, Pkcs7Flags::NOVERIFY) { Ok(tuple) => tuple, Err(_) => { error!(LOG_LABEL, "parse pkcs7 data error"); @@ -330,12 +421,16 @@ fn remove_key_in_profile_internal(bundle_name: *const c_char) -> Result<(), ()> error!(LOG_LABEL, "remove profile data error!"); return Err(()); } - if unsafe { IsDeveloperModeOn() } - && profile_type != DebugCertPathType::Developer as u32 - && remove_cert_path_info(&subject, &issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { + info!(LOG_LABEL, "remove bundle_path path {}!", @public(bundle_path)); + if unsafe { !IsDeveloperModeOn() } && profile_type == DebugCertPathType::Developer as u32 { + info!(LOG_LABEL, "not remove profile_type:{} when development off", @public(profile_type)); + return Ok(()); + } + if remove_cert_path_info(&subject, &issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!(LOG_LABEL, "remove profile data error!"); return Err(()); } + info!(LOG_LABEL, "finish remove cert path in ioctl!"); Ok(()) } diff --git a/services/key_enable/utils/include/cert_path.h b/services/key_enable/utils/include/cert_path.h index f5e6af7..7f4dd02 100644 --- a/services/key_enable/utils/include/cert_path.h +++ b/services/key_enable/utils/include/cert_path.h @@ -20,6 +20,7 @@ #define CERT_DEVICE_PATH "/dev/code_sign" #define CERT_IOCTL_MAGIC_NUMBER 'k' +#define UDID_SIZE 65 struct CertPathInfo { uint32_t signing_length; @@ -39,6 +40,7 @@ extern "C" { int AddCertPath(const CertPathInfo &info); int RemoveCertPath(const CertPathInfo &info); bool IsDeveloperModeOn(); + int CodeSignGetUdid(char *udid); #ifdef __cplusplus } #endif diff --git a/services/key_enable/utils/src/cert_path.cpp b/services/key_enable/utils/src/cert_path.cpp index 41a81d9..2de5bd6 100644 --- a/services/key_enable/utils/src/cert_path.cpp +++ b/services/key_enable/utils/src/cert_path.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "log.h" #include "errcode.h" #include "cert_path.h" @@ -64,3 +65,8 @@ bool IsDeveloperModeOn() } return ret; } + +int CodeSignGetUdid(char *udid) +{ + return GetDevUdid(udid, UDID_SIZE); +} \ No newline at end of file diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index dfb207c..0b533d3 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -161,8 +161,10 @@ ohos_rust_static_library("rust_key_enable_lib") { deps = [ "${code_signature_root_dir}/services/key_enable/utils:libkey_enable_utils", "${rust_openssl_dir}/openssl:lib", + "//third_party/rust/crates/cxx:lib", ] external_deps = [ + "c_utils:utils_rust", "hilog:hilog_rust", "hisysevent:hisysevent_rust", "ylong_json:lib", diff --git a/test/unittest/code_sign_utils_test.cpp b/test/unittest/code_sign_utils_test.cpp index b5ead8e..7075069 100644 --- a/test/unittest/code_sign_utils_test.cpp +++ b/test/unittest/code_sign_utils_test.cpp @@ -442,8 +442,19 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0016, TestSize.Level0) { std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap"; EntryMap entryMap; + std::string profileEnablePath = PROFILE_BASE_PATH + "/demo_cert/pkcs7/verify_test_profile.p7b"; + ByteBuffer buffer; + bool flag = ReadSignatureFromFile(profileEnablePath, buffer); + EXPECT_EQ(flag, true); - int32_t ret = CodeSignUtils::EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF); + string bundlName = "CodeSignUtilsTest"; + int32_t ret = CodeSignUtils::EnableKeyInProfile(bundlName, buffer); + EXPECT_EQ(ret, CS_SUCCESS); + + ret = CodeSignUtils::EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + ret = CodeSignUtils::RemoveKeyInProfile(bundlName); EXPECT_EQ(ret, CS_SUCCESS); std::string filePath1("libs/arm64-v8a/libc++_shared.so"); diff --git a/test/unittest/enable_verity_test.cpp b/test/unittest/enable_verity_test.cpp index d04d7e3..1f09d69 100644 --- a/test/unittest/enable_verity_test.cpp +++ b/test/unittest/enable_verity_test.cpp @@ -80,7 +80,6 @@ public: static void TearDownTestCase() { SaveStringToFile(XPM_DEBUG_FS_MODE_PATH, PERMISSIVE_MODE); - SaveStringToFile(SELINUX_MODE_PATH, ENFORCE_MODE); }; void SetUp() {}; void TearDown() {}; diff --git a/utils/include/cs_hisysevent.h b/utils/include/cs_hisysevent.h index c4b2228..f8da38b 100644 --- a/utils/include/cs_hisysevent.h +++ b/utils/include/cs_hisysevent.h @@ -41,6 +41,19 @@ inline void ReportInvalidCaller(const std::string &interfaceType, uint32_t token HiviewDFX::HiSysEvent::EventType::SECURITY, "INTERFACE", interfaceType, "TOKEN_ID", tokenId); } +inline void ReportParseCodeSig(const std::string &fileInfo, uint32_t errCode) +{ + HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::CODE_SIGN, "CS_PARSE_CODE_SIG", + HiviewDFX::HiSysEvent::EventType::FAULT, + "FILE_INFO", fileInfo, "ERR_TYPE", errCode); +} +inline void ReportInvalidOwner(const std::string &fileInfo, const std::string &ownerID, + const std::string &parsedOwnerID) +{ + HiSysEventWrite(HiviewDFX::HiSysEvent::Domain::CODE_SIGN, "CS_INVALID_OWNER", + HiviewDFX::HiSysEvent::EventType::SECURITY, + "FILE_INFO", fileInfo, "OWNER_ID", ownerID, "PARSED_OWNER_ID", parsedOwnerID); +} } } } -- Gitee