diff --git a/services/key_enable/src/cert_path_utils.rs b/services/key_enable/src/cert_path_utils.rs index 6841b15aede75b6334bb4ab6945d2c198ccd5370..ff73a24955136594ec08b1578dffec26fc573a47 100644 --- a/services/key_enable/src/cert_path_utils.rs +++ b/services/key_enable/src/cert_path_utils.rs @@ -34,6 +34,7 @@ const TYPE_KEY: &str = "type"; const SUBJECT_KEY: &str = "subject"; const ISSUER_KEY: &str = "issuer"; const MAX_CERT_PATH: &str = "max-certs-path"; +const EMPTY_APP_ID: &str = ""; const COMMON_NAME_CHAR_LIMIT: usize = 7; /// profile cert path error pub enum CertPathError { @@ -323,6 +324,7 @@ impl CertPath { subject, issuer, self.cert_path_type, + EMPTY_APP_ID.to_string(), self.max_certs_path, )?; Ok(()) @@ -344,7 +346,11 @@ pub struct CertPathInfo { pub path_len: u32, /// path type pub path_type: u32, - __reserved: [u8; 32], + /// app id + pub app_id: u64, + /// app id length + pub app_id_length: u32, + __reserved: [u8; 20], } fn fabricate_name(subject: &str) -> String { @@ -419,6 +425,7 @@ fn cert_path_operation( subject: String, issuer: String, cert_path_type: u32, + app_id: String, path_length: u32, operation: F, op_name: &str, @@ -429,9 +436,13 @@ where return Err(CertPathError::CertPathOperationError); } + if !app_id.is_empty() { + info!(LOG_LABEL, "sending APP_ID '{}' through ioctl", @public(app_id)); + } let subject_cstring = CString::new(subject).expect("convert to subject_cstring error!"); - let issuer_cstring = CString::new(issuer).expect("convert to cstring error!"); + let issuer_cstring = CString::new(issuer).expect("convert to issuer_cstring error!"); let converted_cert_type = convert_cert_type(cert_path_type); + let app_id_cstring = CString::new(app_id).expect("convert to app_id_cstring error!"); // invalid cert type, skip adding if converted_cert_type == 0u32 { @@ -445,7 +456,9 @@ where issuer: issuer_cstring.as_ptr() as u64, path_len: path_length, path_type: converted_cert_type, - __reserved: [0; 32], + app_id: app_id_cstring.as_ptr() as u64, + app_id_length: app_id_cstring.as_bytes().len() as u32, + __reserved: [0; 20], }; let ret = operation(&cert_path_info); info!(LOG_LABEL, "ioctl return:{}", @public(ret)); @@ -460,12 +473,14 @@ pub fn add_cert_path_info( subject: String, issuer: String, cert_path_type: u32, + app_id: String, path_length: u32, ) -> Result<(), CertPathError> { cert_path_operation( subject, issuer, cert_path_type, + app_id, path_length, |info| unsafe { AddCertPath(info) }, "add cert_path", @@ -477,12 +492,14 @@ pub fn remove_cert_path_info( subject: String, issuer: String, cert_path_type: u32, + app_id: String, path_length: u32, ) -> Result<(), CertPathError> { cert_path_operation( subject, issuer, cert_path_type, + app_id, path_length, |info| unsafe { RemoveCertPath(info) }, "remove cert_path", diff --git a/services/key_enable/src/profile_utils.rs b/services/key_enable/src/profile_utils.rs index 711c0c378c82eafb0c3d5081b587d65685726493..40a63e1786b060fa52af25e78121bf2da80009b0 100644 --- a/services/key_enable/src/profile_utils.rs +++ b/services/key_enable/src/profile_utils.rs @@ -56,6 +56,7 @@ 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 PROFILE_APP_DISTRIBUTION_TYPE_KEY: &str = "app-distribution-type"; +const PROFILE_APP_IDENTIFIER_KEY: &str = "app-identifier"; const APP_DISTRIBUTION_TYPE_INTERNALTESTING: &str = "internaltesting"; const APP_DISTRIBUTION_TYPE_ENTERPRISE: &str = "enterprise"; const APP_DISTRIBUTION_TYPE_ENTERPRISE_NORMAL: &str = "enterprise_normal"; @@ -63,6 +64,7 @@ const APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM: &str = "enterprise_mdm"; const DEFAULT_MAX_CERT_PATH_LEN: u32 = 3; const PROFILE_RELEASE_TYPE: &str = "release"; const PROFILE_DEBUG_TYPE: &str = "debug"; +const EMPTY_APP_ID: &str = ""; /// profile error pub enum ProfileError { @@ -113,7 +115,7 @@ fn parse_pkcs7_data( root_store: &X509Store, flags: Pkcs7Flags, check_udid: bool, -) -> Result<(String, String, u32), Box> { +) -> Result<(String, String, u32, String), Box> { let profile = verify_pkcs7_signature(pkcs7, root_store, flags)?; let profile_json = parse_and_validate_profile(profile, check_udid)?; get_cert_details(&profile_json) @@ -175,13 +177,17 @@ fn parse_and_validate_profile( Ok(profile_json) } -fn get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32), Box> { +fn get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32, String), Box> { let bundle_type = profile_json[PROFILE_TYPE_KEY].try_as_string()?.as_str(); let profile_type = match bundle_type { PROFILE_DEBUG_TYPE => DebugCertPathType::Developer as u32, PROFILE_RELEASE_TYPE => ReleaseCertPathType::Developer as u32, _ => return Err("Invalid bundle type.".into()), }; + let app_id = match profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_APP_IDENTIFIER_KEY] { + JsonValue::Null => EMPTY_APP_ID.to_string(), + _ => profile_json[PROFILE_BUNDLE_INFO_KEY][PROFILE_APP_IDENTIFIER_KEY].try_as_string()?.to_string(), + }; let signed_cert = match bundle_type { 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].try_as_string()?, @@ -190,7 +196,7 @@ fn get_cert_details(profile_json: &JsonValue) -> Result<(String, String, u32), B let signed_pem = X509::from_pem(signed_cert.as_bytes())?; let subject = format_x509_fabricate_name(signed_pem.subject_name()); let issuer = format_x509_fabricate_name(signed_pem.issuer_name()); - Ok((subject, issuer, profile_type)) + Ok((subject, issuer, profile_type, app_id)) } lazy_static! { @@ -342,7 +348,7 @@ fn process_profile( continue; } let check_udid = unsafe { !IsRdDevice() }; - let (subject, issuer, profile_type) = + let (subject, issuer, profile_type, app_id) = match parse_pkcs7_data(&pkcs7, x509_store, Pkcs7Flags::empty(), check_udid) { Ok(tuple) => tuple, Err(e) => { @@ -352,7 +358,7 @@ fn process_profile( continue; } }; - if add_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { + if add_cert_path_info(subject, issuer, profile_type, app_id, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!( LOG_LABEL, "Failed to add profile cert path info into ioctl for {}", @public(path) @@ -405,7 +411,7 @@ fn validate_and_convert_inputs( Ok((_bundle_name, profile_data)) } -fn process_data(profile_data: &[u8]) -> Result<(String, String, u32), ()> { +fn process_data(profile_data: &[u8]) -> Result<(String, String, u32, String), ()> { let store = match X509StoreBuilder::new() { Ok(store) => store.build(), Err(_) => { @@ -453,7 +459,7 @@ fn enable_key_in_profile_internal( profile_size: u32, ) -> Result<(), ()> { let (_bundle_name, profile_data) = validate_and_convert_inputs(bundle_name, profile, profile_size)?; - let (subject, issuer, profile_type) = process_data(&profile_data)?; + let (subject, issuer, profile_type, app_id) = process_data(&profile_data)?; let bundle_path = create_bundle_path(&_bundle_name, profile_type)?; info!(LOG_LABEL, "create bundle_path path {}!", @public(bundle_path)); if !file_exists(&bundle_path) && create_file_path(&bundle_path).is_err() { @@ -473,7 +479,7 @@ fn enable_key_in_profile_internal( 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() { + if add_cert_path_info(subject, issuer, profile_type, app_id, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!(LOG_LABEL, "add profile data error!"); return Err(()); } @@ -498,7 +504,7 @@ fn process_remove_bundle( return Err(()); } - let (subject, issuer, profile_type) = process_data(&profile_data)?; + let (subject, issuer, profile_type, app_id) = process_data(&profile_data)?; if delete_file_path(&bundle_path).is_err() { error!(LOG_LABEL, "remove profile data error!"); return Err(()); @@ -506,7 +512,7 @@ fn process_remove_bundle( info!(LOG_LABEL, "remove bundle_path path {}!", @public(bundle_path)); - if remove_cert_path_info(subject, issuer, profile_type, DEFAULT_MAX_CERT_PATH_LEN).is_err() { + if remove_cert_path_info(subject, issuer, profile_type, app_id, DEFAULT_MAX_CERT_PATH_LEN).is_err() { error!(LOG_LABEL, "remove profile data error!"); return Err(()); } diff --git a/services/key_enable/utils/include/cert_path.h b/services/key_enable/utils/include/cert_path.h index 114ad30ed2578b582a1262bbe80b97b896bbbf59..a277dcad4757e9a8ad99d3dcbaa3568ec3435a6d 100644 --- a/services/key_enable/utils/include/cert_path.h +++ b/services/key_enable/utils/include/cert_path.h @@ -33,7 +33,9 @@ struct CertPathInfo { uint64_t issuer; uint32_t path_len; uint32_t path_type; - uint8_t __reserved[32]; + uint64_t app_id; + uint32_t app_id_length; + uint8_t __reserved[20]; }; #define ADD_CERT_PATH_CMD _IOW(CERT_IOCTL_MAGIC_NUMBER, 1, CertPathInfo) diff --git a/test/unittest/add_cert_path_test.cpp b/test/unittest/add_cert_path_test.cpp index c010ecaab47501bfffb3164e25a27fe19cf64014..409c9a5308d27627e8e0b615df66b686ab86ca52 100644 --- a/test/unittest/add_cert_path_test.cpp +++ b/test/unittest/add_cert_path_test.cpp @@ -42,6 +42,8 @@ static const string TEST_ISSUER = "OpenHarmony Application CA"; static const string KEY_ENABLE_CTX = "u:r:key_enable:s0"; static const string FAKE_SUBJECT = "Fake subject"; static const string FAKE_ISSUER = "Fake issuer"; +static const string TEST_APP_ID = "6918688064123613841"; +static const string EMPTY_APP_ID = ""; static const string SUBJECT_AS_SYSTEM_TYPE = "System subject"; static const string ISSUER_AS_SYSTEM_TYPE = "System issuer"; @@ -55,14 +57,16 @@ public: void TearDown() {}; }; -static CertPathInfo MakeCertPathInfo(const char *signing, const char *issuer, +static CertPathInfo MakeCertPathInfo(const char *signing, const char *issuer, const char *app_id, uint32_t max_cert_chain, uint32_t cert_path_type) { CertPathInfo arg = { 0 }; arg.signing = reinterpret_cast(signing); arg.issuer = reinterpret_cast(issuer); + arg.app_id = reinterpret_cast(app_id); arg.signing_length = strlen(signing); arg.issuer_length = strlen(issuer); + arg.app_id_length = strlen(app_id); arg.path_len = max_cert_chain; arg.path_type = cert_path_type; return arg; @@ -76,7 +80,7 @@ static CertPathInfo MakeCertPathInfo(const char *signing, const char *issuer, */ HWTEST_F(AddCertPathTest, AddCertPathTest_0001, TestSize.Level0) { - CertPathInfo certPathInfo = MakeCertPathInfo(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), + CertPathInfo certPathInfo = MakeCertPathInfo(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), EMPTY_APP_ID.c_str(), GREATER_THAN_MAX_CERT_CHAIN, CERT_PATH_TYPE); EXPECT_NE(AddCertPath(certPathInfo), 0); } @@ -89,7 +93,7 @@ HWTEST_F(AddCertPathTest, AddCertPathTest_0001, TestSize.Level0) */ HWTEST_F(AddCertPathTest, AddCertPathTest_0002, TestSize.Level0) { - CertPathInfo certPathInfo = MakeCertPathInfo(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), + CertPathInfo certPathInfo = MakeCertPathInfo(TEST_SUBJECT.c_str(), TEST_ISSUER.c_str(), EMPTY_APP_ID.c_str(), LESS_THAN_MIN_CERT_CHAIN, CERT_PATH_TYPE); EXPECT_NE(AddCertPath(certPathInfo), 0); } @@ -103,12 +107,14 @@ HWTEST_F(AddCertPathTest, AddCertPathTest_0002, TestSize.Level0) HWTEST_F(AddCertPathTest, AddCertPathTest_0003, TestSize.Level0) { // type = developer in release - CertPathInfo certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), MAX_CERT_CHAIN, 0x3); + CertPathInfo certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), + EMPTY_APP_ID.c_str(), MAX_CERT_CHAIN, 0x3); EXPECT_EQ(AddCertPath(certPathInfo), 0); EXPECT_EQ(RemoveCertPath(certPathInfo), 0); // type = developer in debug - certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), MAX_CERT_CHAIN, 0x103); + certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), + EMPTY_APP_ID.c_str(), MAX_CERT_CHAIN, 0x103); EXPECT_EQ(AddCertPath(certPathInfo), 0); EXPECT_EQ(RemoveCertPath(certPathInfo), 0); @@ -126,10 +132,34 @@ HWTEST_F(AddCertPathTest, AddCertPathTest_0004, TestSize.Level0) { // release CertPathInfo certPathInfo = MakeCertPathInfo(SUBJECT_AS_SYSTEM_TYPE.c_str(), - ISSUER_AS_SYSTEM_TYPE.c_str(), MAX_CERT_CHAIN, 1); + ISSUER_AS_SYSTEM_TYPE.c_str(), EMPTY_APP_ID.c_str(), MAX_CERT_CHAIN, 1); // cannot add except key_enable EXPECT_NE(AddCertPath(certPathInfo), 0); } + +/** + * @tc.name: AddCertPathTest_0005 + * @tc.desc: add enterprise cert path success + * @tc.type: Func + * @tc.require: + */ +HWTEST_F(AddCertPathTest, AddCertPathTest_0005, TestSize.Level0) +{ + // type = developer in release + CertPathInfo certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), + TEST_APP_ID.c_str(), MAX_CERT_CHAIN, 0x3); + EXPECT_EQ(AddCertPath(certPathInfo), 0); + EXPECT_EQ(RemoveCertPath(certPathInfo), 0); + + // type = developer in debug + certPathInfo = MakeCertPathInfo(FAKE_SUBJECT.c_str(), FAKE_ISSUER.c_str(), + TEST_APP_ID.c_str(), MAX_CERT_CHAIN, 0x103); + EXPECT_EQ(AddCertPath(certPathInfo), 0); + EXPECT_EQ(RemoveCertPath(certPathInfo), 0); + + // remove unexists + EXPECT_NE(RemoveCertPath(certPathInfo), 0); +} } // namespace CodeSign } // namespace Security } // namespace OHOS \ No newline at end of file