mirror of
https://gitee.com/openharmony/security_code_signature
synced 2025-02-17 04:39:23 +00:00
feat:新增设备id校验
Signed-off-by: yeyuning <yeyuning2@huawei.com> Change-Id: I4571d8c50220e24820f6e93a24f80fb240cce515
This commit is contained in:
parent
a249b48754
commit
c9cfa8cdef
@ -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}
|
||||
__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}
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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<const uint8_t *>(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<const uint8_t *>(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<const uint8_t *>(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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
],
|
||||
);
|
||||
}
|
@ -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<u8>) -> Result<(),
|
||||
file.read_to_end(buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
/// find file
|
||||
/// find file
|
||||
pub fn file_exists(file_path: &str) -> bool {
|
||||
Path::new(file_path).exists()
|
||||
}
|
||||
|
@ -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<dyn Error>> {
|
||||
let pkcs7 = Pkcs7::from_der(profile_data)?;
|
||||
let stack_of_certs = Stack::<X509>::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<String, String> {
|
||||
let mut udid: Vec<u8> = 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<dyn Error>> {
|
||||
let stack_of_certs = Stack::<X509>::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<String> {
|
||||
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(())
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <parameters.h>
|
||||
#include <parameter.h>
|
||||
#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);
|
||||
}
|
@ -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",
|
||||
|
@ -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");
|
||||
|
@ -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() {};
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user