diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3fbf678..f880c5c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,9 +81,6 @@ jobs: runs-on: ubuntu-latest needs: - build-boringssl - permissions: - id-token: write - attestations: write strategy: matrix: build-type: [debug, release] diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml index 091e84e..d33a383 100644 --- a/.github/workflows/update-changelog.yml +++ b/.github/workflows/update-changelog.yml @@ -35,7 +35,7 @@ jobs: echo "$RELEASE_BODY" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - ASSET_URL=$(echo "$ASSETS_JSON" | jq -r '.[] | select(.name | contains("release")) | .browser_download_url' | head -n1) + ASSET_URL=$(echo "$ASSETS_JSON" | jq -r '.[] | select(.name | endswith("release.zip")) | .browser_download_url' | head -n1) if [ -z "$ASSET_URL" ]; then echo "::error::No release zip found in assets! Names:" diff --git a/Cargo.toml b/Cargo.toml index 99ff138..481a807 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "OhMyKeymint" -version = "0.1.2" +version = "0.1.1" edition = "2021" license = "AGPL-3.0-or-later" @@ -10,23 +10,23 @@ path = "src/main.rs" [dependencies] jni = "0.21.1" -syscalls = "0.7.0" +syscalls = "0.6.15" kmr-derive = { path = "derive" } kmr-common = { path = "common" } kmr-crypto-boring = { path = "boringssl" } kmr-ta = { path = "ta" } kmr-wire = { path = "wire" } -libc = "0.2.180" +libc = "0.2.176" prost = "0.14.1" prost-types = "0.14.1" hex = "0.4.3" log4rs = "1.4.0" -log = "0.4.29" -rsbinder = { version = "0.5.0", features = ["android_12_plus"] } -rusqlite = { version = "0.38.0", features = ["bundled"] } +log = "0.4.28" +rsbinder = { version = "0.4.2", features = ["android_12_plus"] } +rusqlite = { version = "0.37.0", features = ["bundled"] } anyhow = "1.0.100" async-trait = "0.1.89" -tokio = { version = "1.49.0", features = ["macros", "libc"] } +tokio = { version = "1.47.1", features = ["macros", "libc"] } lazy_static = "1.5.0" thiserror = "2.0.17" serde = "1.0.228" @@ -34,7 +34,7 @@ x509-cert = "0.2.5" watchdog_rs = "*" nix = { version = "0.30.1", features = ["mman"] } rsproperties = { version = "0.2.2", features = ["builder"] } -libsqlite3-sys = "0.36.0" +libsqlite3-sys = "0.35.0" rand = "0.9.2" der = "0.7.10" toml = "0.9.8" @@ -48,8 +48,6 @@ rsproperties-service = "*" android_logger = "0.15.1" multi_log = "0.1.2" -[profile.dev] -incremental = true [profile.release] opt-level = 'z' # Optimize for size @@ -58,7 +56,6 @@ codegen-units = 1 # Reduce number of codegen units to increase optimizations panic = 'abort' # Abort on panic strip = true # Strip symbols from binary* debuginfo = 0 # Disable debug info -incremental = true [workspace] members = [ @@ -70,7 +67,6 @@ members = [ "wire", "watchdog", "rsproperties-service", - "injector", ] [patch.crates-io] @@ -81,9 +77,8 @@ kmr-ta = { path = "ta" } kmr-tests = { path = "tests" } kmr-wire = { path = "wire" } watchdog_rs = { path = "watchdog" } -injector = { path = "injector" } rsproperties-service = { path = "rsproperties-service" } [build-dependencies] prost-build = "0.14.1" -rsbinder-aidl = "0.5.0" +rsbinder-aidl = "0.4.3" diff --git a/README.md b/README.md index 9cfee8a..b91a710 100644 --- a/README.md +++ b/README.md @@ -3,61 +3,7 @@ Custom keystore implementation for Android Keystore Spoofer > [!WARNING] -> The program is still in its early stages of development. -> -> No ANY guarantees are made regarding performance or stability. - -# What is this? - -This is a complete implementation of the Keystore, implementing features not implemented in the Tricky Store. -You can think of it as DLC for the game. It can work without it, but it's usually better to have it. - -In the future, we will gradually move away from the Tricky Store as a backend. - -# Install and configure - -1. Install the [qwq233's Tricky Store](https://github.com/qwq233/TrickyStore) (My fork). - -2. Install this module. - -3. Configure (if you need) - -Configuration file is located at `/data/misc/keystore/omk/config.toml` - -```toml -[main] -# We can only use Tricky Store as backend at this point. -backend = "TrickyStore" - -# The following values ​​are used to generate the seed for device encryption -# and verification. Please be sure to save the following values. If you lose -# them for some reason, please clear the module database (/data/misc/keystore/omk/data/) -# DO NOT MODIFY ANY VALUE BELOW IF YOU DO NOT UNDERSTAND WHAT ARE YOU DOING -[crypto] -root_kek_seed = "4b61c4b3bdf72bb700c351e020270846fb67ba3885e5fb67547e626af5cc1a7f" -kak_seed = "d6fa5bb024540928a7d554ab5831a0553dd2f688f5d6cb3cb1645be2ff49e357" - -[trust] -os_version = 15 -security_patch = "2025-05-01" -vb_key = "b114f5162ca0e4b4fc0544a218953caba54f3102f5f3a9346e220c770890b93b" -vb_hash = "2b38cf298eb4ca0d2dbaab32721dea2bb297b42652f4fff9180c48e7ac4da887" -verified_boot_state = true -device_locked = true - -[device] -brand = "Google" -device = "generic" -product = "generic" -manufacturer = "Google" -model = "generic" -serial = "ABC12345678ABC" -meid = "1234567890" -imei = "1234567890" -imei2 = "1234567890" -``` - -4. Enjoy +> This is a toy project. No ANY guarantees are made regarding performance or stability. # License diff --git a/boringssl/Cargo.toml b/boringssl/Cargo.toml index fe3c62c..1b0b65c 100644 --- a/boringssl/Cargo.toml +++ b/boringssl/Cargo.toml @@ -9,14 +9,14 @@ edition = "2021" license = "Apache-2.0" [dependencies] -foreign-types = "0.3.1" +foreign-types = "0.5.0" kmr-common = "*" kmr-wire = "*" libc = "^0.2.112" log = "^0.4" anyhow = "*" thiserror = "*" -nix = { version = "*", features = ["mman"] } +nix = "*" [target.'cfg(target_os = "linux")'.dependencies] openssl = "^0.10.36" diff --git a/boringssl/src/ec.rs b/boringssl/src/ec.rs index c963373..00a3054 100644 --- a/boringssl/src/ec.rs +++ b/boringssl/src/ec.rs @@ -33,37 +33,16 @@ use openssl::hash::MessageDigest; use Box; use Vec; -#[cfg(target_os = "android")] +#[cfg(soong)] fn private_key_from_der_for_group( der: &[u8], group: &openssl::ec::EcGroupRef, ) -> Result, openssl::error::ErrorStack> { // This method is an Android modification to the rust-openssl crate. - ossl_private_key_from_der_for_group(der, group) -} - -#[cfg(target_os = "android")] -fn ossl_private_key_from_der_for_group( - der: &[u8], - group: &openssl::ec::EcGroupRef, -) -> Result, openssl::error::ErrorStack> { - use foreign_types::ForeignTypeRef; - - unsafe { - let mut cbs = ffi::CBS { - data: der.as_ptr(), - len: der.len(), - }; - - crate::ocvt_p(ffi::EC_KEY_parse_private_key( - &mut cbs as *mut ffi::CBS, - group.as_ptr(), - )) - .map(|p| openssl::ec::EcKey::from_ptr(p)) - } + openssl::ec::EcKey::private_key_from_der_for_group(der, group) } -#[cfg(not(target_os = "android"))] +#[cfg(not(soong))] fn private_key_from_der_for_group( der: &[u8], _group: &openssl::ec::EcGroupRef, diff --git a/boringssl/src/km.rs b/boringssl/src/km.rs index a5f180d..8ad73de 100644 --- a/boringssl/src/km.rs +++ b/boringssl/src/km.rs @@ -62,7 +62,7 @@ pub fn generate_random_data(size: usize) -> Result, Error> { #[allow(non_snake_case)] fn randomBytes(buf: *mut u8, len: usize) -> bool { - let mut rng = crate::rng::BoringRng; + let mut rng = crate::rng::BoringRng::default(); rng.fill_bytes(unsafe { std::slice::from_raw_parts_mut(buf, len) }); true } @@ -370,7 +370,10 @@ pub fn hkdf_expand(out_len: usize, prk: &[u8], info: &[u8]) -> Result bool { let digest = MessageDigest::sha256(); - openssl::pkcs5::pbkdf2_hmac(prk, info, 1, digest, out_key).is_ok() + match openssl::pkcs5::pbkdf2_hmac(prk, info, 1, digest, out_key) { + Ok(_) => true, + Err(_) => false, + } } /// A wrapper around the boringssl EC_KEY type that frees it on drop. diff --git a/boringssl/src/lib.rs b/boringssl/src/lib.rs index b174794..556dbef 100644 --- a/boringssl/src/lib.rs +++ b/boringssl/src/lib.rs @@ -153,15 +153,6 @@ fn cvt_p(r: *mut T) -> Result<*mut T, Error> { } } -#[inline] -fn ocvt_p(r: *mut T) -> Result<*mut T, openssl::error::ErrorStack> { - if r.is_null() { - Err(openssl::error::ErrorStack::get()) - } else { - Ok(r) - } -} - #[inline] fn cvt(r: libc::c_int) -> Result { if r <= 0 { diff --git a/build.rs b/build.rs index 8855b18..30e9570 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,6 @@ use std::{fs, path::PathBuf, vec}; fn main() { - println!("cargo:rustc-link-lib=c++"); - println!("cargo:rerun-if-changed=aidl"); println!("cargo:rerun-if-changed=src/proto"); println!("cargo:rerun-if-changed=build.rs"); @@ -31,7 +29,6 @@ fn main() { .output(PathBuf::from("aidl.rs")); let dirs = vec![ - "aidl/android/content/pm", "aidl/android/system/keystore2", "aidl/android/hardware/security/keymint", "aidl/android/security/metrics", @@ -69,7 +66,6 @@ fn main() { .replace("HardwareAuthenticatorType.", "super::super::super::hardware::security::keymint::HardwareAuthenticatorType::HardwareAuthenticatorType::") .replace("r#authenticatorType: super::Digest::Digest::NONE,", "r#authenticatorType: super::HardwareAuthenticatorType::HardwareAuthenticatorType::NONE,") .replace("r#authenticatorType: super::KeyPermission::KeyPermission::NONE,", "r#authenticatorType: super::HardwareAuthenticatorType::HardwareAuthenticatorType::NONE,") - .replace("r#authenticatorType: super::PaddingMode::PaddingMode::NONE,", "r#authenticatorType: super::HardwareAuthenticatorType::HardwareAuthenticatorType::NONE,") .replace("r#operation: rsbinder::Strong,", "r#operation: Option>,"); println!("Patched AIDL content:\n{}", generated_path.display()); diff --git a/common/Cargo.toml b/common/Cargo.toml index 71175e1..822b523 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -9,10 +9,10 @@ edition = "2021" license = "Apache-2.0" [dependencies] -cddl-cat = { version = "^0.7.0", optional = true } +cddl-cat = { version = "^0.6.1", optional = true } ciborium = { version = "^0.2.0", default-features = false } ciborium-io = "^0.2.0" -coset = "0.4.0" +coset = "0.3.3" der = { version = "^0.7.2", features = ["alloc", "derive"] } enumn = "0.1.4" kmr-derive = "*" diff --git a/common/src/crypto/hmac.rs b/common/src/crypto/hmac.rs index 7ef4b9c..699f5a9 100644 --- a/common/src/crypto/hmac.rs +++ b/common/src/crypto/hmac.rs @@ -32,7 +32,7 @@ pub const MAX_KEY_SIZE_BITS: usize = 1024; pub struct Key(pub Vec); fn valid_size(key_size: KeySizeInBits, max_size_bits: usize) -> Result<(), Error> { - if !key_size.0.is_multiple_of(8) { + if key_size.0 % 8 != 0 { Err(km_err!( UnsupportedKeySize, "key size {} bits not a multiple of 8", diff --git a/common/src/keyblob.rs b/common/src/keyblob.rs index c8ee21d..600b036 100644 --- a/common/src/keyblob.rs +++ b/common/src/keyblob.rs @@ -187,7 +187,7 @@ pub struct SecureDeletionData { } /// Indication of what kind of key operation requires a secure deletion slot. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Clone, Copy, PartialEq, Eq)] pub enum SlotPurpose { /// Secure deletion slot needed for key generation. KeyGeneration, diff --git a/common/src/tag.rs b/common/src/tag.rs index 471a573..96033ea 100644 --- a/common/src/tag.rs +++ b/common/src/tag.rs @@ -108,32 +108,6 @@ macro_rules! get_opt_tag_value { } } -#[macro_export] -macro_rules! modify_tag_value { - { $params:expr, $variant:ident, $new_value:expr } => { - modify_tag_value!($params, $variant, $new_value, InvalidTag) - }; - { $params:expr, $variant:ident, $new_value:expr, $dup_error:ident } => { - { - let mut found = false; - for param in $params.iter_mut() { - if let kmr_wire::keymint::KeyParam::$variant(v) = param { - if (found) { - return Err($crate::km_err!(InvalidTag, "duplicate tag {}", stringify!($variant))); - } - *v = $new_value; - found = true; - } - } - if found { - Ok(()) - } else { - Err($crate::km_err!(InvalidTag, "missing tag {}", stringify!($variant))) - } - } - }; -} - /// Macro to retrieve a `bool` tag value, returning `false` if the tag is absent #[macro_export] macro_rules! get_bool_tag_value { @@ -200,7 +174,7 @@ pub fn transcribe_tags( for param in src { let tag = param.tag(); dup_checker.add(tag)?; - if tags.contains(&tag) { + if tags.iter().any(|t| *t == tag) { dest.try_push(param.clone())?; } } @@ -807,7 +781,9 @@ fn check_aes_import_params( /// Check the parameter validity for an AES key that is about to be generated or imported. fn check_aes_params(params: &[KeyParam]) -> Result<(), Error> { - let gcm_support = params.contains(&KeyParam::BlockMode(BlockMode::Gcm)); + let gcm_support = params + .iter() + .any(|p| *p == KeyParam::BlockMode(BlockMode::Gcm)); if gcm_support { let min_mac_len = get_tag_value!(params, MinMacLength, ErrorCode::MissingMinMacLength)?; if (min_mac_len % 8 != 0) || !(96..=128).contains(&min_mac_len) { diff --git a/injector/Cargo.toml b/injector/Cargo.toml deleted file mode 100644 index a2ccaec..0000000 --- a/injector/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "injector" -version = "0.1.0" -edition = "2021" -license = "AGPL-3.0-or-later" - -[[bin]] -name = "inject" -path = "src/main.rs" - -[dependencies] -libc = "0.2.177" -log = "0.4.28" -log4rs = "1.4.0" -nix = { version = "0.30.1", features = ["dir", "fs", "ptrace", "signal"] } -lsplt-rs = "2.1.5" -anyhow = "1.0.100" - -[target.'cfg(target_os = "android")'.dependencies] -android_logger = "0.15.1" -multi_log = "0.1.2" diff --git a/injector/src/logging.rs b/injector/src/logging.rs deleted file mode 100644 index 0caf184..0000000 --- a/injector/src/logging.rs +++ /dev/null @@ -1,45 +0,0 @@ -use log::LevelFilter; -use log4rs::append::console::ConsoleAppender; -use log4rs::config::{Appender, Config, Root}; -use log4rs::encode::pattern::PatternEncoder; - -const PATTERN: &str = "{d(%Y-%m-%d %H:%M:%S %Z)(utc)} [{h({l})}] {M} - {m}{n}"; - -#[cfg(not(target_os = "android"))] -pub fn init_logger() { - let stdout = ConsoleAppender::builder() - .encoder(Box::new(PatternEncoder::new(PATTERN))) - .build(); - let root = Root::builder().appender("stdout").build(LevelFilter::Debug); - let config = Config::builder() - .appender(Appender::builder().build("stdout", Box::new(stdout))) - .build(root) - .unwrap(); - log4rs::init_config(config).unwrap(); -} - -#[cfg(target_os = "android")] -pub fn init_logger() { - let config = android_logger::Config::default() - .with_max_level(LevelFilter::Debug) - .with_tag("OhMyKeymint"); - - let android_logger = android_logger::AndroidLogger::new(config); - - let stdout = ConsoleAppender::builder() - .encoder(Box::new(PatternEncoder::new(PATTERN))) - .build(); - let root = Root::builder().appender("stdout").build(LevelFilter::Debug); - let config = Config::builder() - .appender(Appender::builder().build("stdout", Box::new(stdout))) - .build(root) - .unwrap(); - - let log4rs = log4rs::Logger::new(config); - - multi_log::MultiLogger::init( - vec![Box::new(android_logger), Box::new(log4rs)], - log::Level::Debug, - ) - .unwrap(); -} diff --git a/injector/src/main.rs b/injector/src/main.rs deleted file mode 100644 index 98aa067..0000000 --- a/injector/src/main.rs +++ /dev/null @@ -1,388 +0,0 @@ -use std::ffi::c_void; - -use anyhow::{bail, Context, Result}; -use log::{debug, error}; -use nix::{sys::signal::Signal, unistd::Pid}; - -use crate::sys::wait_pid; - -pub mod logging; -pub mod sys; -pub mod utils; - -fn main() { - logging::init_logger(); - let (pid, _) = utils::find_process_by_name("keystore2").unwrap(); - let pid = Pid::from_raw(pid); - inject_library(pid, entry).unwrap(); -} - -fn inject_library(pid: Pid, entry: extern "C" fn(*const c_void) -> bool) -> Result<()> { - let self_path = - std::fs::read_link("/proc/self/exe").context("Failed to read link /proc/self/exe")?; - - nix::sys::ptrace::attach(pid)?; - debug!("Attached to process {}", pid); - - if let Err(e) = wait_pid(pid, Signal::SIGSTOP) { - bail!("Failed to wait for process {} to stop: {}", pid, e); - } - - let mut regs = sys::get_regs(pid)?; - let backup_regs = regs; - - let local_maps = lsplt_rs::MapInfo::scan("self"); - let remote_maps = lsplt_rs::MapInfo::scan(pid.as_raw().to_string().as_str()); - - // Helper closure to resolve function address - let resolve = |lib: &str, name: &str| -> Result { - utils::resolve_func_addr(&local_maps, &remote_maps, lib, name) - .or_else(|_| utils::resolve_func_addr(&local_maps, &remote_maps, "libc.so", name)) - // Fallback to libc for newer android - }; - - // Helper to push data to remote stack and update regs SP - let mut push_to_remote_stack = |data: &[u8]| -> Result { - let sp = { - #[cfg(target_arch = "x86_64")] - { - regs.rsp as usize - } - #[cfg(target_arch = "x86")] - { - regs.esp as usize - } - #[cfg(target_arch = "aarch64")] - { - regs.sp as usize - } - #[cfg(target_arch = "arm")] - { - regs.uregs[13] as usize - } - }; - // sys::push_stack returns the NEW stack pointer address - let new_sp = sys::push_stack(pid, sp, data, false)?; - - // Update local regs copy - #[cfg(target_arch = "x86_64")] - { - regs.rsp = new_sp as u64; - } - #[cfg(target_arch = "x86")] - { - regs.esp = new_sp as u32; - } - #[cfg(target_arch = "aarch64")] - { - regs.sp = new_sp as u64; - } - #[cfg(target_arch = "arm")] - { - regs.uregs[13] = new_sp as u32; - } - - // Commit SP change to remote process so subsequent remote_call works correctly - sys::set_regs(pid, ®s)?; - Ok(new_sp) - }; - - let libc_return_addr = utils::resolve_return_addr(&remote_maps, "libc.so")?; - debug!("Resolved libc return address: 0x{:x}", libc_return_addr); - - let close_addr = resolve("libc.so", "close")?; - let socket_addr = resolve("libc.so", "socket")?; - let bind_addr = resolve("libc.so", "bind")?; - let recvmsg_addr = resolve("libc.so", "recvmsg")?; - let errno_addr = resolve("libc.so", "__errno").ok(); - let strlen_addr = resolve("libc.so", "strlen").ok(); - - let dlopen_addr = resolve("libdl.so", "dlopen")?; - let dlerror_addr = resolve("libdl.so", "dlerror").ok(); - - let get_remote_errno = || -> Result { - if let Some(addr) = errno_addr { - let ptr = sys::remote_call(pid, addr, libc_return_addr, &[])?; - let mut buf = [0u8; 4]; - sys::read_stack(pid, ptr, &mut buf)?; - Ok(i32::from_ne_bytes(buf)) - } else { - Ok(0) - } - }; - - let close_remote = |fd: i32| -> Result<()> { - let args = vec![fd as usize]; - if sys::remote_call(pid, close_addr, libc_return_addr, &args)? != 0 { - error!("Remote close failed for fd {}", fd); - } - Ok(()) - }; - - // Prepare FD Passing - utils::set_sockcreate_con("u:object_r:system_file:s0")?; - - // Create local socket - let local_socket = - unsafe { libc::socket(libc::AF_UNIX, libc::SOCK_DGRAM | libc::SOCK_CLOEXEC, 0) }; - if local_socket == -1 { - bail!( - "Failed to create local socket: {}", - std::io::Error::last_os_error() - ); - } - // Ensure local socket is closed when we drop/exit - let _local_sock_guard = { - // Simple scope guard to close fd - struct FdGuard(i32); - impl Drop for FdGuard { - fn drop(&mut self) { - unsafe { - libc::close(self.0); - } - } - } - FdGuard(local_socket) - }; - // Set SELinux context for the file - utils::set_file_con(&self_path, "u:object_r:system_file:s0")?; - - let local_lib_file = std::fs::OpenOptions::new() - .read(true) - .open(&self_path) - .context("Failed to open self executable")?; - use std::os::unix::io::AsRawFd; - let local_lib_fd = local_lib_file.as_raw_fd(); - - let args = vec![ - libc::AF_UNIX as usize, - (libc::SOCK_DGRAM | libc::SOCK_CLOEXEC) as usize, - 0, - ]; - let remote_fd = sys::remote_call(pid, socket_addr, libc_return_addr, &args)? as i32; - if remote_fd == -1 { - let err = get_remote_errno()?; - bail!("Failed to create remote socket. Remote errno: {}", err); - } - - // generate magic socket name - let mut magic_bytes = Vec::with_capacity(16); - let time = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH)? - .subsec_nanos(); - for i in 0..16 { - magic_bytes.push(b'a' + ((time.wrapping_add(i) % 26) as u8)); // a-z - } - - // Construct sockaddr_un - // Layout: family (u16) + path (108 bytes) - // Using explicit bytes to ensure layout matches C struct exactly without imports - let mut addr_bytes = vec![0u8; std::mem::size_of::()]; - // Set family AF_UNIX - let family = (libc::AF_UNIX as u16).to_ne_bytes(); - addr_bytes[0] = family[0]; - addr_bytes[1] = family[1]; - // Set abstract path (starts with \0, then magic) - // sun_path offset is 2 - addr_bytes[2] = 0; - for (i, b) in magic_bytes.iter().enumerate() { - if 3 + i < addr_bytes.len() { - addr_bytes[3 + i] = *b; - } - } - let addr_len = 2 + 1 + magic_bytes.len(); // family + null + magic - - debug!( - "Generated magic socket: @{}", - String::from_utf8_lossy(&magic_bytes) - ); - - let remote_addr_ptr = push_to_remote_stack(&addr_bytes)?; - - let args = vec![remote_fd as usize, remote_addr_ptr, addr_len]; - let bind_res = sys::remote_call(pid, bind_addr, libc_return_addr, &args)?; - if (bind_res as isize) == -1 { - let err = get_remote_errno()?; - close_remote(remote_fd)?; - bail!("Failed to bind remote socket. Remote errno: {}", err); - } - - // CMSG buffer - let cmsg_space = - unsafe { libc::CMSG_SPACE(std::mem::size_of::() as u32) as usize }; - let cmsg_buf = vec![0u8; cmsg_space]; - let remote_cmsg_ptr = push_to_remote_stack(&cmsg_buf)?; - - let mut msg: libc::msghdr = unsafe { std::mem::zeroed() }; - msg.msg_control = remote_cmsg_ptr as *mut c_void; - msg.msg_controllen = cmsg_space; - - let msg_bytes = unsafe { - std::slice::from_raw_parts( - &msg as *const _ as *const u8, - std::mem::size_of::(), - ) - }; - let remote_msg_ptr = push_to_remote_stack(msg_bytes)?; - - // 6b. Sendmsg (Local) -> Send the FD - // Construct local address to send TO - let mut local_dest_addr: libc::sockaddr_un = unsafe { std::mem::zeroed() }; - local_dest_addr.sun_family = libc::AF_UNIX as u16; - local_dest_addr.sun_path[0] = 0; // Abstract - for (i, b) in magic_bytes.iter().enumerate() { - local_dest_addr.sun_path[1 + i] = *b; - } - - // Construct Control Message - // Requires explicit CMSG construction - let mut local_cmsg_buf = vec![0u8; cmsg_space]; - let mut local_iov = libc::iovec { - iov_base: std::ptr::null_mut(), - iov_len: 0, - }; // Send 0 bytes of real data - - let mut local_hdr: libc::msghdr = unsafe { std::mem::zeroed() }; - local_hdr.msg_name = &mut local_dest_addr as *mut _ as *mut c_void; - local_hdr.msg_namelen = addr_len as u32; - local_hdr.msg_iov = &mut local_iov; - local_hdr.msg_iovlen = 1; - local_hdr.msg_control = local_cmsg_buf.as_mut_ptr() as *mut c_void; - local_hdr.msg_controllen = cmsg_space; - - unsafe { - let cmsg = libc::CMSG_FIRSTHDR(&local_hdr); - (*cmsg).cmsg_level = libc::SOL_SOCKET; - (*cmsg).cmsg_type = libc::SCM_RIGHTS; - (*cmsg).cmsg_len = libc::CMSG_LEN(std::mem::size_of::() as u32) as usize; - *(libc::CMSG_DATA(cmsg) as *mut libc::c_int) = local_lib_fd; - // Update controllen to actual length used - local_hdr.msg_controllen = (*cmsg).cmsg_len; - } - - let send_res = unsafe { libc::sendmsg(local_socket, &local_hdr, 0) }; - if send_res == -1 { - close_remote(remote_fd)?; - bail!( - "Failed to send FD locally: {}", - std::io::Error::last_os_error() - ); - } - debug!("Sent FD {} to remote abstract socket", local_lib_fd); - - let args = vec![ - remote_fd as usize, - remote_msg_ptr, - libc::MSG_WAITALL as usize, - ]; - let recv_res = sys::remote_call(pid, recvmsg_addr, libc_return_addr, &args)? as isize; - - if recv_res == -1 { - let err = get_remote_errno()?; - close_remote(remote_fd)?; - bail!("Remote recvmsg failed. Errno: {}", err); - } - - // Retrieve Received FD from Remote Memory - let mut remote_cmsg_data = vec![0u8; cmsg_space]; - sys::read_stack(pid, remote_cmsg_ptr, &mut remote_cmsg_data)?; - - let cmsg_hdr_len = unsafe { libc::CMSG_LEN(0) } as usize; - let remote_lib_fd_bytes = &remote_cmsg_data[cmsg_hdr_len..cmsg_hdr_len + 4]; - let remote_lib_fd = i32::from_ne_bytes(remote_lib_fd_bytes.try_into().unwrap()); - - debug!("Remote received FD: {}", remote_lib_fd); - - close_remote(remote_fd)?; - - let info_size = 64; // Safe upper bound - let mut info_bytes = vec![0u8; info_size]; - - let flags: u64 = 0x10; - info_bytes[0..8].copy_from_slice(&flags.to_ne_bytes()); - - // library_fd offset - // 64-bit: 0(u64), 8(ptr), 16(u64), 24(int), 28(int library_fd) - // 32-bit: 0(u64), 8(ptr), 12(u32), 16(int), 20(int library_fd) - let fd_offset = if std::mem::size_of::() == 8 { - 28 - } else { - 20 - }; - info_bytes[fd_offset..fd_offset + 4].copy_from_slice(&remote_lib_fd.to_ne_bytes()); - - let remote_info_ptr = push_to_remote_stack(&info_bytes)?; - - // Push library path string - let lib_path_str = self_path.to_string_lossy(); - let lib_path_c = std::ffi::CString::new(lib_path_str.as_bytes())?; - let remote_path_ptr = push_to_remote_stack(lib_path_c.as_bytes_with_nul())?; - - // Call dlopen - // args: filename, flags (RTLD_NOW=2), extinfo - let args = vec![remote_path_ptr, libc::RTLD_NOW as usize, remote_info_ptr]; - let handle = sys::remote_call(pid, dlopen_addr, libc_return_addr, &args)?; - - debug!("Remote dlopen handle: 0x{:x}", handle); - - if handle == 0 { - // Read dlerror - if let (Some(err_fn), Some(str_fn)) = (dlerror_addr, strlen_addr) { - let err_ptr = sys::remote_call(pid, err_fn, libc_return_addr, &[])?; - if err_ptr != 0 { - let len = sys::remote_call(pid, str_fn, libc_return_addr, &[err_ptr])?; - if len > 0 && len < 1024 { - let mut err_buf = vec![0u8; len]; - sys::read_stack(pid, err_ptr, &mut err_buf)?; - error!("dlopen failed: {}", String::from_utf8_lossy(&err_buf)); - } - } - } - // Close the leaked lib_fd in remote - close_remote(remote_lib_fd)?; - bail!("Remote dlopen failed"); - } - - close_remote(remote_lib_fd)?; - - // a - let local_entry_addr = entry as usize; - let local_base = utils::resolve_base_addr( - &local_maps, - &self_path.file_name().unwrap().to_string_lossy(), - )?; - let offset = local_entry_addr - local_base; - debug!( - "Local Entry: 0x{:x}, Local Base: 0x{:x}, Offset: 0x{:x}", - local_entry_addr, local_base, offset - ); - - let remote_maps = lsplt_rs::MapInfo::scan(pid.as_raw().to_string().as_str()); // Refresh remote maps - let remote_base = utils::resolve_base_addr( - &remote_maps, - &self_path.file_name().unwrap().to_string_lossy(), - )?; - - let injector_entry = remote_base + offset; - debug!("Found 'entry' at: 0x{:x}", injector_entry); - - if injector_entry == 0 { - bail!("Failed to find 'entry' symbol in injected library"); - } - - let args = vec![handle]; - sys::remote_call(pid, injector_entry, libc_return_addr, &args)?; - - // Cleanup - debug!("Restore context and detach"); - sys::set_regs(pid, &backup_regs)?; - nix::sys::ptrace::detach(pid, None)?; - - Ok(()) -} - -#[no_mangle] -#[allow(unused)] -pub extern "C" fn entry(handle: *const c_void) -> bool { - true -} diff --git a/injector/src/sys.rs b/injector/src/sys.rs deleted file mode 100644 index af14ce1..0000000 --- a/injector/src/sys.rs +++ /dev/null @@ -1,508 +0,0 @@ -use std::os::unix::fs::FileExt as _; -use std::path::PathBuf; - -use std::ffi::c_void; - -use anyhow::{anyhow, bail, Context, Result}; -use libc::iovec; -use log::{debug, error, trace}; -use nix::sys::signal::Signal; -use nix::{ - sys::wait::{WaitPidFlag, WaitStatus}, - unistd::Pid, -}; - -#[cfg(any( - target_arch = "aarch64", - target_arch = "arm", - target_arch = "x86_64", - target_arch = "x86" -))] -pub type Regs = libc::user_regs_struct; - -pub const NT_PRSTATUS: std::ffi::c_int = 1; - -pub fn align_stack(regs: &mut Regs, preserve: usize) { - #[cfg(target_arch = "x86_64")] - { - regs.rsp = (regs.rsp.wrapping_sub(preserve as u64)) & !0xf; - } - #[cfg(target_arch = "x86")] - { - regs.esp = (regs.esp.wrapping_sub(preserve as u32)) & !0xf; - } - #[cfg(target_arch = "aarch64")] - { - regs.sp = (regs.sp.wrapping_sub(preserve as u64)) & !0xf; - } - #[cfg(target_arch = "arm")] - { - regs.uregs[13] = (regs.uregs[13].wrapping_sub(preserve as u32)) & !0xf; - } -} - -pub fn wait_pid(pid: Pid, target: Signal) -> Result<()> { - loop { - match nix::sys::wait::waitpid(pid, Some(WaitPidFlag::empty()))? { - WaitStatus::Stopped(_, sig) => { - if sig == target { - return Ok(()); - } - if sig == Signal::SIGTRAP { - continue; - } - bail!("Process {} stopped with signal {}", pid, sig.as_str()); - } - WaitStatus::Signaled(_, sig, _) => { - bail!("Process {} terminated with signal {}", pid, sig.as_str()); - } - WaitStatus::Exited(_, code) => { - bail!("Process {} exited with code {}", pid, code); - } - _ => continue, - } - } -} - -pub fn get_regs(pid: Pid) -> Result { - let mut regs: Regs = unsafe { std::mem::zeroed() }; - - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - let result = unsafe { - libc::ptrace( - libc::PTRACE_GETREGS, - pid.as_raw(), - 0, - &mut regs as *mut _ as *mut c_void, - ) - }; - - if result == -1 { - bail!( - "ptrace(PTRACE_GETREGS) failed: {}", - std::io::Error::last_os_error() - ); - } - } - - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] - { - let mut iov = libc::iovec { - iov_base: &mut regs as *mut _ as *mut c_void, - iov_len: std::mem::size_of::(), - }; - - let result = unsafe { - libc::ptrace( - libc::PTRACE_GETREGSET, - pid.as_raw(), - NT_PRSTATUS as *mut c_void, - &mut iov as *mut _ as *mut c_void, - ) - }; - - if result == -1 { - bail!( - "ptrace(PTRACE_GETREGS) failed: {}", - std::io::Error::last_os_error() - ); - } - } - - Ok(regs) -} - -pub fn set_regs(pid: Pid, regs: &Regs) -> Result<()> { - #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] - { - let result = unsafe { - libc::ptrace( - libc::PTRACE_SETREGS, - pid.as_raw(), - 0, - regs as *const _ as *mut c_void, - ) - }; - - if result == -1 { - bail!( - "ptrace(PTRACE_SETREGS) failed: {}", - std::io::Error::last_os_error() - ); - } - } - - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] - { - let mut iov = libc::iovec { - iov_base: regs as *const _ as *mut c_void, - iov_len: std::mem::size_of::(), - }; - - let result = unsafe { - libc::ptrace( - libc::PTRACE_SETREGSET, - pid.as_raw(), - NT_PRSTATUS as *mut c_void, - &mut iov as *mut _ as *mut c_void, - ) - }; - - if result == -1 { - bail!( - "ptrace(PTRACE_SETREGS) failed: {}", - std::io::Error::last_os_error() - ); - } - } - - Ok(()) -} - -pub fn read_stack(pid: Pid, remote_addr: usize, buf: &mut [u8]) -> Result { - let local = iovec { - iov_base: buf.as_mut_ptr() as *mut c_void, - iov_len: buf.len(), - }; - - let remote = iovec { - iov_base: remote_addr as *mut c_void, - iov_len: buf.len(), - }; - - let result = unsafe { - libc::process_vm_readv( - pid.as_raw(), - &local as *const iovec, - 1, - &remote as *const iovec, - 1, - 0, - ) - }; - - if result == -1 { - bail!( - "process_vm_readv failed: {}", - std::io::Error::last_os_error() - ); - } else if result != buf.len() as isize { - bail!( - "process_vm_readv read incomplete data: {}/{} bytes", - result, - buf.len() - ) - } else { - Ok(result as usize) - } -} - -pub fn push_stack(pid: Pid, remote_addr: usize, data: &[u8], use_proc_mem: bool) -> Result { - let new_addr = remote_addr - .checked_sub(data.len()) - .ok_or_else(|| anyhow!("Stack overflow when pushing data"))?; - - if use_proc_mem { - let mem_path = PathBuf::from(format!("/proc/{}/mem", pid.as_raw())); - let mem_file = std::fs::OpenOptions::new() - .write(true) - .open(&mem_path) - .context(format!("Failed to open {}", mem_path.display()))?; - - mem_file - .write_at(data, new_addr as u64) - .context(format!("Failed to write to address 0x{:x}", new_addr))?; - - Ok(new_addr) - } else { - let local = iovec { - iov_base: data.as_ptr() as *mut c_void, - iov_len: data.len(), - }; - - let remote = iovec { - iov_base: new_addr as *mut c_void, - iov_len: data.len(), - }; - - let result = unsafe { - libc::process_vm_writev( - pid.as_raw(), - &local as *const iovec, - 1, - &remote as *const iovec, - 1, - 0, - ) - }; - - if result == -1 { - error!( - "process_vm_writev failed: {}", - std::io::Error::last_os_error() - ); - Err(anyhow!( - "process_vm_writev failed: {}", - std::io::Error::last_os_error() - )) - } else if result != data.len() as isize { - Err(anyhow!( - "process_vm_writev wrote incomplete data: {}/{} bytes", - result, - data.len() - )) - } else { - Ok(new_addr) - } - } -} - -pub fn setup_remote_call( - pid: Pid, - regs: &mut Regs, - func_addr: usize, - return_addr: usize, - args: &[usize], -) -> Result<()> { - align_stack(regs, 0); - trace!( - "Setting up remote call: func_addr=0x{:x}, return_addr=0x{:x}, regs=0{:?}, args={:?}", - func_addr, - return_addr, - regs, - args - ); - - #[cfg(target_arch = "x86_64")] - { - let mut sp = regs.rsp as usize; - - // set up arguments in registers - if args.len() > 0 { - regs.rdi = args[0] as u64; - } - if args.len() > 1 { - regs.rsi = args[1] as u64; - } - if args.len() > 2 { - regs.rdx = args[2] as u64; - } - if args.len() > 3 { - regs.rcx = args[3] as u64; - } - if args.len() > 4 { - regs.r8 = args[4] as u64; - } - if args.len() > 5 { - regs.r9 = args[5] as u64; - } - - if args.len() > 6 { - for i in (6..args.len()).rev() { - let arg_bytes = args[i].to_ne_bytes(); - sp = push_stack(pid, sp, &arg_bytes, false)?; - } - } - - let ret_bytes = return_addr.to_ne_bytes(); - sp = push_stack(pid, sp, &ret_bytes, false)?; - regs.rsp = sp as u64; - regs.rip = func_addr as u64; - } - - #[cfg(target_arch = "x86")] - { - let mut sp = regs.esp as usize; - - for i in (0..args.len()).rev() { - let arg_bytes = (args[i] as u32).to_ne_bytes(); - sp = push_stack(pid, sp, &arg_bytes, false)?; - } - - let ret_bytes = (return_addr as u32).to_ne_bytes(); - sp = push_stack(pid, sp, &ret_bytes, false)?; - - regs.esp = sp as u32; - regs.eip = func_addr as u32; - } - - #[cfg(target_arch = "aarch64")] - { - const ARG_REG_COUNT: usize = 8; - let mut sp = regs.sp as usize; - - // set up arguments in registers - for i in 0..args.len().min(ARG_REG_COUNT) { - regs.regs[i] = args[i] as u64; - } - // jump to stack for additional arguments - if args.len() > ARG_REG_COUNT { - // ensure 16-byte alignment - let size = (args.len() - ARG_REG_COUNT) * std::mem::size_of::(); - let target_sp = sp.wrapping_sub(size) & !0xf; - sp = target_sp + size; - - for i in (ARG_REG_COUNT..args.len()).rev() { - sp = push_stack(pid, sp, &args[i].to_ne_bytes(), false)?; - } - } - // set link register to dummy return address - regs.regs[30] = return_addr as u64; - // set program counter to function address - regs.pc = func_addr as u64; - // ensure proper instruction set state - regs.sp = sp as u64; - } - - #[cfg(target_arch = "arm")] - { - const REG_ARGS_COUNT: usize = 4; - let mut sp = regs.uregs[13] as usize; // SP - - if args.len() > REG_ARGS_COUNT { - let stack_args_len = (args.len() - REG_ARGS_COUNT) * 4; - let target_sp = (sp - stack_args_len) & !0x7; - sp = target_sp + stack_args_len; - - for i in (REG_ARGS_COUNT..args.len()).rev() { - let arg_bytes = (args[i] as u32).to_ne_bytes(); - sp = push_stack(pid, sp, &arg_bytes, false)?; - } - } - - for i in 0..std::cmp::min(args.len(), REG_ARGS_COUNT) { - regs.uregs[i] = args[i] as u32; - } - - regs.uregs[14] = return_addr as u32; // LR - regs.uregs[13] = sp as u32; // SP - - if (func_addr & 1) != 0 { - regs.uregs[15] = (func_addr & !1) as u32; // PC - regs.uregs[16] |= 0x20; // Set CPSR T bit (bit 5) - } else { - regs.uregs[15] = func_addr as u32; // PC - regs.uregs[16] &= !0x20; // Clear T bit - } - } - - set_regs(pid, regs)?; - if unsafe { libc::ptrace(libc::PTRACE_CONT, pid.as_raw(), 0, 0) } != 0 { - bail!( - "ptrace(PTRACE_CONT) failed: {}", - std::io::Error::last_os_error() - ); - } - - Ok(()) -} - -fn wait_remote_call(pid: Pid, return_addr: usize) -> Result { - wait_pid(pid, Signal::SIGSEGV)?; - let regs = get_regs(pid)?; - - #[cfg(target_arch = "x86_64")] - { - if regs.rip != (return_addr as u64) { - error!( - "Unexpected RIP after remote call: expected 0x{:x}, got 0x{:x}", - return_addr, regs.rip - ); - match nix::sys::ptrace::getsiginfo(pid) { - Ok(info) => { - error!("Signal info: {:?}", info); - } - Err(e) => { - error!("Failed to get signal info: {}", e); - } - } - bail!("Remote call did not reach expected function address"); - } - - Ok(regs.rax as usize) - } - #[cfg(target_arch = "x86")] - { - if regs.eip != (return_addr as u32) { - error!( - "Unexpected EIP after remote call: expected 0x{:x}, got 0x{:x}", - return_addr, regs.eip - ); - match nix::sys::ptrace::getsiginfo(pid) { - Ok(info) => { - error!("Signal info: {:?}", info); - } - Err(e) => { - error!("Failed to get signal info: {}", e); - } - } - bail!("Remote call did not reach expected function address"); - } - - Ok(regs.eax as usize) - } - - #[cfg(target_arch = "aarch64")] - { - if regs.pc != (return_addr as u64) { - error!( - "Unexpected PC after remote call: expected 0x{:x}, got 0x{:x}", - return_addr, regs.pc - ); - match nix::sys::ptrace::getsiginfo(pid) { - Ok(info) => { - error!("Signal info: {:?}", info); - } - Err(e) => { - error!("Failed to get signal info: {}", e); - } - } - bail!("Remote call did not reach expected function address"); - } - - Ok(regs.regs[0] as usize) - } - #[cfg(target_arch = "arm")] - { - if regs.uregs[15] != (return_addr as u32) { - error!( - "Unexpected PC after remote call: expected 0x{:x}, got 0x{:x}", - return_addr, regs.uregs[15] - ); - match nix::sys::ptrace::getsiginfo(pid) { - Ok(info) => { - error!("Signal info: {:?}", info); - } - Err(e) => { - error!("Failed to get signal info: {}", e); - } - } - bail!("Remote call did not reach expected function address"); - } - - Ok(regs.uregs[0] as usize) - } -} - -pub fn remote_call( - pid: Pid, - func_addr: usize, - return_addr: usize, - args: &[usize], -) -> Result { - debug!( - "Performing remote call to 0x{:x} with return address 0x{:x} and args {:?}", - func_addr, return_addr, args - ); - let original_regs = get_regs(pid).context("Failed to backup registers.")?; - let mut regs = original_regs; - - setup_remote_call(pid, &mut regs, func_addr, return_addr, args)?; - let ret = wait_remote_call(pid, return_addr)?; - - // restore original registers - set_regs(pid, &original_regs).context("Failed to restore registers.")?; - - Ok(ret) -} diff --git a/injector/src/utils.rs b/injector/src/utils.rs deleted file mode 100644 index 1549599..0000000 --- a/injector/src/utils.rs +++ /dev/null @@ -1,192 +0,0 @@ -use std::os::unix::ffi::OsStrExt; -use std::{ffi::CString, path::PathBuf}; - -use std::ffi::{c_void, CStr}; - -use anyhow::{anyhow, Context, Result}; -use log::{debug, error}; -use lsplt_rs::MapInfo; -use nix::{ - dir::{Dir, Type}, - fcntl::OFlag, - sys::stat::Mode, -}; - -// SELinux stuff -pub fn set_sockcreate_con(context: &str) -> Result<()> { - let context = CString::new(context).context("Invalid context string")?; - let context = context.as_bytes_with_nul(); - if let Err(e) = std::fs::write("/proc/thread-self/attr/sockcreate", context) { - error!("Failed to set sockcreate context: {}", e); - - let tid = unsafe { libc::gettid() as usize }; - std::fs::write(format!("/proc/{}/attr/sockcreate", tid), context) - .context("Failed to set sockcreate context via /proc/[tid]/attr/sockcreate")?; - } - - Ok(()) -} - -pub fn set_file_con(path: &PathBuf, context: &str) -> Result<()> { - const XATTR_NAME_SELINUX: &CStr = c"security.selinux"; - - let path = - CString::new(path.as_os_str().as_bytes()).context("Invalid file path for setxattr")?; - let context = CString::new(context).context("Invalid context string")?; - let size = context.as_bytes_with_nul().len(); - - let result = unsafe { - libc::setxattr( - path.as_ptr(), - XATTR_NAME_SELINUX.as_ptr(), - context.as_ptr() as *const c_void, - size, - 0, - ) - }; - - if result != 0 { - Err(anyhow!( - "Failed to set file context: {}", - std::io::Error::last_os_error() - )) - } else { - Ok(()) - } -} - -// Hook stuff -pub fn resolve_base_addr(info: &[MapInfo], lib_name: &str) -> Result { - for map in info { - if let Some(path) = &map.pathname { - if map.offset == 0 && path.as_str().ends_with(lib_name) { - debug!( - "Found library '{}' at base address: 0x{:x}", - lib_name, map.start - ); - return Ok(map.start); - } - } - } - Err(anyhow!("Library '{}' not found in process maps", lib_name)) -} - -pub fn resolve_return_addr(info: &[MapInfo], lib_name: &str) -> Result { - for map in info { - if let Some(path) = &map.pathname { - if (map.perms & libc::PROT_EXEC as u8) == 0 && path.as_str().ends_with(lib_name) { - let data_addr = map.start + map.offset; - debug!( - "Found data seg in library '{}' at address: 0x{:x}", - lib_name, data_addr - ); - return Ok(data_addr); - } - } - } - Err(anyhow!("Not found in library '{}'", lib_name)) -} - -pub fn resolve_func_addr( - local: &[MapInfo], - remote: &[MapInfo], - lib_name: &str, - name: &str, -) -> Result { - let lib = unsafe { - let lib = CString::new(lib_name).map_err(|_| anyhow!("Invalid library name"))?; - libc::dlopen(lib.as_ptr(), libc::RTLD_NOW) - }; - if lib.is_null() { - return Err(anyhow!( - "Failed to open library '{}': {}", - lib_name, - std::io::Error::last_os_error() - )); - } - - let symbol = unsafe { - let name = CString::new(name).map_err(|_| anyhow!("Invalid function name"))?; - libc::dlsym(lib, name.as_ptr()) - }; - if symbol.is_null() { - return Err(anyhow!( - "Failed to find symbol '{}' in library '{}': {}", - name, - lib_name, - std::io::Error::last_os_error() - )); - } - - unsafe { - libc::dlclose(lib); - } - - let local_addr = resolve_base_addr(local, lib_name) - .context(format!("failed to find local base for module {}", lib_name))?; - let remote_addr = resolve_base_addr(remote, lib_name).context(format!( - "failed to find remote base for module {}", - lib_name - ))?; - - let offset = (symbol as usize) - .checked_sub(local_addr) - .ok_or_else(|| anyhow!("Invalid symbol address"))?; - let remote_func_addr = remote_addr - .checked_add(offset) - .ok_or_else(|| anyhow!("Address overflow"))?; - - debug!( - "Resolved function '{}' address: 0x{:x}", - name, remote_func_addr - ); - Ok(remote_func_addr) -} - -pub fn find_process_by_name(target_name: &str) -> Result<(i32, PathBuf)> { - let mut proc_dir = Dir::open("/proc", OFlag::O_RDONLY | OFlag::O_DIRECTORY, Mode::empty())?; - - for entry_result in proc_dir.iter() { - let entry = match entry_result { - Ok(entry) => entry, - Err(_) => continue, - }; - - if entry.file_type() != Some(Type::Directory) { - continue; - } - - let file_name = entry.file_name(); - - let pid_str = file_name.to_str().unwrap(); - if !pid_str.chars().all(char::is_numeric) { - continue; - } - - let path = PathBuf::from("/proc").join(pid_str); - - let comm_path = path.join("exe"); - let target = match std::fs::read_link(comm_path) { - Ok(name) => name, - Err(_) => continue, - }; - let file_name = match target.file_name().and_then(std::ffi::OsStr::to_str) { - Some(name) => name, - None => continue, - }; - if file_name.trim() != target_name { - continue; - } - - let pid = pid_str.parse::().unwrap(); - debug!("Found target executable: {:?} (PID {})", target, pid); - - return Ok((pid, target)); - } - - Err(std::io::Error::new( - std::io::ErrorKind::NotFound, - format!("Process '{}' not found", target_name), - )) - .context("") -} diff --git a/src/att_mgr.rs b/src/att_mgr.rs index 2e4a316..757dd74 100644 --- a/src/att_mgr.rs +++ b/src/att_mgr.rs @@ -8,24 +8,21 @@ pub struct AttestationIdMgr; impl RetrieveAttestationIds for AttestationIdMgr { fn get(&self) -> Result { - let info = { - let config = CONFIG - .read() - .map_err(|_| km_err!(UnknownError, "config lock poisoned"))?; - AttestationIdInfo { - brand: config.device.brand.clone().into_bytes(), - device: config.device.device.clone().into_bytes(), - product: config.device.product.clone().into_bytes(), - serial: config.device.serial.clone().into_bytes(), - imei: config.device.imei.clone().into_bytes(), - imei2: config.device.imei2.clone().into_bytes(), - meid: config.device.meid.clone().into_bytes(), - manufacturer: config.device.manufacturer.clone().into_bytes(), - model: config.device.model.clone().into_bytes(), - } - }; + let config = CONFIG + .read() + .map_err(|_| km_err!(UnknownError, "config lock poisoned"))?; - Ok(info) + Ok(AttestationIdInfo { + brand: config.device.brand.clone().into_bytes(), + device: config.device.device.clone().into_bytes(), + product: config.device.product.clone().into_bytes(), + serial: config.device.serial.clone().into_bytes(), + imei: config.device.imei.clone().into_bytes(), + imei2: config.device.imei2.clone().into_bytes(), + meid: config.device.meid.clone().into_bytes(), + manufacturer: config.device.manufacturer.clone().into_bytes(), + model: config.device.model.clone().into_bytes(), + }) } fn destroy_all(&mut self) -> Result<(), kmr_common::Error> { diff --git a/src/config.rs b/src/config.rs index 0ea0fe6..20801f0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,7 +11,7 @@ lazy_static::lazy_static! { } #[cfg(target_os = "android")] -const CONFIG_PATH: &str = "/data/misc/keystore/omk/config.toml"; +const CONFIG_PATH: &str = "/data/adb/omk/config.toml"; #[cfg(not(target_os = "android"))] const CONFIG_PATH: &str = "./omk/config.toml"; diff --git a/src/global.rs b/src/global.rs index 82c9f83..e54f477 100644 --- a/src/global.rs +++ b/src/global.rs @@ -11,18 +11,14 @@ use crate::{ android::hardware::security::secureclock::ISecureClock::ISecureClock, err, keymaster::{ - apex::ApexModuleInfo, async_task::AsyncTask, db::KeymasterDb, enforcements::Enforcements, - gc::Gc, keymint_device::get_keymint_wrapper, super_key::SuperKeyManager, + async_task::AsyncTask, db::KeymasterDb, enforcements::Enforcements, gc::Gc, + keymint_device::get_keymint_wrapper, super_key::SuperKeyManager, }, watchdog as wd, }; static DB_INIT: Once = Once::new(); -lazy_static::lazy_static! { - pub static ref APEX_MODULE_HASH: anyhow::Result> = crate::plat::utils::get_apex_module_info(); -} - /// A single on-demand worker thread that handles deferred tasks with two different /// priorities. pub static ASYNC_TASK: LazyLock> = LazyLock::new(Default::default); diff --git a/src/keymaster/apex.rs b/src/keymaster/apex.rs index 8119736..a9b0f5a 100644 --- a/src/keymaster/apex.rs +++ b/src/keymaster/apex.rs @@ -5,7 +5,7 @@ use der::{ DerOrd, Encode, Sequence, }; -#[derive(Sequence, Debug, Clone)] +#[derive(Sequence, Debug)] pub struct ApexModuleInfo { pub package_name: OctetString, pub version_code: u64, @@ -23,6 +23,6 @@ impl DerOrd for ApexModuleInfo { } } -pub fn encode_module_info(module_info: &Vec) -> Result, der::Error> { - SetOfVec::::from_iter(module_info.iter().cloned())?.to_der() +pub fn encode_module_info(module_info: Vec) -> Result, der::Error> { + SetOfVec::::from_iter(module_info.into_iter())?.to_der() } diff --git a/src/keymaster/db.rs b/src/keymaster/db.rs index 6a7e93c..3f38278 100644 --- a/src/keymaster/db.rs +++ b/src/keymaster/db.rs @@ -31,9 +31,9 @@ use TransactionBehavior::Immediate; const DB_ROOT_PATH: &str = "./omk/data"; #[cfg(target_os = "android")] -const DB_ROOT_PATH: &str = "/data/misc/keystore/omk/data"; +const DB_ROOT_PATH: &str = "/data/adb/omk/data"; -const PERSISTENT_DB_FILENAME: &str = "keymaster.db"; +const PERSISTENT_DB_FILENAME: &'static str = "keymaster.db"; const DB_BUSY_RETRY_INTERVAL: Duration = Duration::from_micros(500); @@ -1735,13 +1735,11 @@ impl KeymasterDb { AND state = ? AND key_type = ?;", params![domain.0 as u32, namespace, KeyLifeCycle::Live, key_type], - |row| row.get::<_, i32>(0), + |row| row.get(0), ) .context(err!("Failed to count number of keys.")) .no_gc() })?; - let num_keys = - usize::try_from(num_keys).context(err!("Failed to convert key count to usize."))?; Ok(num_keys) } diff --git a/src/keymaster/enforcements.rs b/src/keymaster/enforcements.rs index d73fb87..a36c233 100644 --- a/src/keymaster/enforcements.rs +++ b/src/keymaster/enforcements.rs @@ -789,7 +789,7 @@ impl Enforcements { let result = Self::find_auth_token(|auth_token_entry: &AuthTokenEntry| { let token_valid = now_in_millis .checked_sub(&auth_token_entry.time_received()) - .is_some_and(|token_age_in_millis| { + .map_or(false, |token_age_in_millis| { auth_token_max_age_millis > token_age_in_millis.milliseconds() }); token_valid && auth_token_entry.satisfies(&sids, auth_type) diff --git a/src/keymaster/keymint_device.rs b/src/keymaster/keymint_device.rs index 12eea14..a4eaeb8 100644 --- a/src/keymaster/keymint_device.rs +++ b/src/keymaster/keymint_device.rs @@ -93,13 +93,17 @@ impl KeyMintDevice { /// Get a [`KeyMintDevice`] for the given [`SecurityLevel`] pub fn get(security_level: SecurityLevel) -> Result { + let km_dev = KeyMintWrapper::new(security_level) + .expect(err!("Failed to init strongbox wrapper").as_str()); + let hw_info = km_dev.get_hardware_info().unwrap(); + let km_uuid = RwLock::new(Uuid::from(security_level)); let wrapper: KeyMintWrapper = KeyMintWrapper::new(security_level).unwrap(); Ok(KeyMintDevice { km_dev: wrapper, - version: 400, + version: hw_info.version_number, km_uuid, - security_level, + security_level: get_keymaster_security_level(hw_info.security_level)?, }) } @@ -171,7 +175,7 @@ impl KeyMintDevice { &BlobInfo::new(&creation_result.keyBlob, &blob_metadata), &CertificateInfo::new(None, None), &key_metadata, - &self.km_uuid.read().unwrap(), + &*self.km_uuid.read().unwrap(), ) .context(err!("store_new_key failed"))?; Ok(()) @@ -303,7 +307,7 @@ impl KeyMintDevice { F: Fn(&[u8]) -> Result, { let (f_result, upgraded_blob) = crate::keymaster::utils::upgrade_keyblob_if_required_with( - self.security_level, + self.security_level.clone(), self.version(), &key_blob, &[], @@ -407,16 +411,21 @@ impl IKeyMintDevice for KeyMintWrapper { }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result: InternalBeginResult = match result.rsp.unwrap() { PerformOpRsp::DeviceBegin(rsp) => rsp.ret, - _ => unreachable!("Unexpected response type"), + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }; let operation = crate::keymaster::keymint_operation::KeyMintOperation::new( - self.security_level, + self.security_level.clone(), result.challenge, km_params, result.op_handle, @@ -438,8 +447,10 @@ impl IKeyMintDevice for KeyMintWrapper { crate::android::hardware::security::keymint::KeyMintHardwareInfo::KeyMintHardwareInfo, Status, > { - let hardware_info: keymint::KeyMintHardwareInfo = - self.keymint.lock().unwrap().get_hardware_info().unwrap(); + let hardware_info: keymint::KeyMintHardwareInfo = self.keymint + .lock().unwrap() + .get_hardware_info() + .unwrap(); let resp = crate::android::hardware::security::keymint::KeyMintHardwareInfo::KeyMintHardwareInfo { @@ -449,7 +460,12 @@ impl IKeyMintDevice for KeyMintWrapper { SecurityLevel::TRUSTED_ENVIRONMENT } kmr_wire::keymint::SecurityLevel::Strongbox => SecurityLevel::STRONGBOX, - kmr_wire::keymint::SecurityLevel::Keystore => SecurityLevel::KEYSTORE, + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }, versionNumber: hardware_info.version_number, keyMintName: hardware_info.key_mint_name, @@ -511,13 +527,19 @@ impl IKeyMintDevice for KeyMintWrapper { key_params: key_parameters, attestation_key, }); - let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + let result = self.keymint.lock().unwrap() + .process_req(req); + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { PerformOpRsp::DeviceGenerateKey(rsp) => rsp.ret, - _ => unreachable!("Unexpected response type"), + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }; let resp = key_creation_result_to_aidl(result)?; @@ -571,12 +593,17 @@ impl IKeyMintDevice for KeyMintWrapper { attestation_key, }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { PerformOpRsp::DeviceImportKey(rsp) => rsp.ret, - _ => unreachable!("Unexpected response type"), + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }; let resp = key_creation_result_to_aidl(result)?; @@ -614,7 +641,7 @@ impl IKeyMintDevice for KeyMintWrapper { }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } @@ -650,7 +677,7 @@ impl IKeyMintDevice for KeyMintWrapper { let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { @@ -734,12 +761,17 @@ impl IKeyMintDevice for KeyMintWrapper { }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { PerformOpRsp::DeviceConvertStorageKeyToEphemeral(rsp) => rsp.ret, - _ => unreachable!("Unexpected response type"), + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }; Result::Ok(result) @@ -760,19 +792,24 @@ impl IKeyMintDevice for KeyMintWrapper { }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { PerformOpRsp::DeviceGetKeyCharacteristics(rsp) => rsp.ret, - _ => unreachable!("Unexpected response type"), + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }; let result: Result, rsbinder::Status> = result.iter().map(|kc| { let params: Result, rsbinder::Status> = kc.authorizations.iter().map(|p| { key_param_to_aidl(p.clone()) .map_err(|_| Error::Km(ErrorCode::INVALID_ARGUMENT)) - .map_err(map_ks_error) + .map_err(|e| map_ks_error(e)) }).collect(); let params = params?; @@ -784,7 +821,12 @@ impl IKeyMintDevice for KeyMintWrapper { SecurityLevel::TRUSTED_ENVIRONMENT } kmr_wire::keymint::SecurityLevel::Strongbox => SecurityLevel::STRONGBOX, - kmr_wire::keymint::SecurityLevel::Keystore => SecurityLevel::KEYSTORE, + _ => { + return Err(rsbinder::Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }, }) @@ -798,7 +840,7 @@ impl IKeyMintDevice for KeyMintWrapper { let req = PerformOpReq::GetRootOfTrustChallenge(GetRootOfTrustChallengeRequest {}); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { @@ -821,12 +863,17 @@ impl IKeyMintDevice for KeyMintWrapper { let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Status::new_service_specific_error(result.error_code, None)); } let result = match result.rsp.unwrap() { PerformOpRsp::GetRootOfTrust(rsp) => rsp.ret, - _ => unreachable!("Unexpected response type"), + _ => { + return Err(Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }; Result::Ok(result) @@ -873,21 +920,19 @@ impl IKeyMintDevice for KeyMintWrapper { impl KeyMintWrapper { pub fn new(security_level: SecurityLevel) -> Result { Ok(KeyMintWrapper { - security_level, + security_level: security_level.clone(), keymint: Mutex::new(init_keymint_ta(security_level)?), }) } pub fn reset_keymint_ta(&self) -> Result<()> { let mut keymint = self.keymint.lock().unwrap(); - *keymint = init_keymint_ta(self.security_level)?; + *keymint = init_keymint_ta(self.security_level.clone())?; Ok(()) } pub fn get_hardware_info(&self) -> Result { - self.keymint - .lock() - .unwrap() + self.keymint.lock().unwrap() .get_hardware_info() .map_err(|_| Error::Km(ErrorCode::UNKNOWN_ERROR)) } @@ -908,22 +953,26 @@ impl KeyMintWrapper { } else { None }; - let timestamp_token = timestamp_token.map(|tt| kmr_wire::secureclock::TimeStampToken { - challenge: tt.challenge, - timestamp: kmr_wire::secureclock::Timestamp { - milliseconds: tt.timestamp.milliSeconds, - }, - mac: tt.mac.clone(), - }); + let timestamp_token = if let Some(tt) = timestamp_token { + Some(kmr_wire::secureclock::TimeStampToken { + challenge: tt.challenge, + timestamp: kmr_wire::secureclock::Timestamp { + milliseconds: tt.timestamp.milliSeconds, + }, + mac: tt.mac.clone(), + }) + } else { + None + }; let req = PerformOpReq::OperationUpdateAad(UpdateAadRequest { op_handle, input: input.to_vec(), auth_token: hardware_auth_token, - timestamp_token, + timestamp_token: timestamp_token, }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Error::Binder( ExceptionCode::ServiceSpecific, result.error_code, @@ -953,22 +1002,26 @@ impl KeyMintWrapper { } else { None }; - let timestamp_token = timestamp_token.map(|tt| kmr_wire::secureclock::TimeStampToken { - challenge: tt.challenge, - timestamp: kmr_wire::secureclock::Timestamp { - milliseconds: tt.timestamp.milliSeconds, - }, - mac: tt.mac.clone(), - }); + let timestamp_token = if let Some(tt) = timestamp_token { + Some(kmr_wire::secureclock::TimeStampToken { + challenge: tt.challenge, + timestamp: kmr_wire::secureclock::Timestamp { + milliseconds: tt.timestamp.milliSeconds, + }, + mac: tt.mac.clone(), + }) + } else { + None + }; let req = PerformOpReq::OperationUpdate(UpdateRequest { op_handle, input: input.to_vec(), auth_token: hardware_auth_token, - timestamp_token, + timestamp_token: timestamp_token, }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Error::Binder( ExceptionCode::ServiceSpecific, result.error_code, @@ -1000,27 +1053,31 @@ impl KeyMintWrapper { } else { None }; - let timestamp_token = timestamp_token.map(|tt| kmr_wire::secureclock::TimeStampToken { - challenge: tt.challenge, - timestamp: kmr_wire::secureclock::Timestamp { - milliseconds: tt.timestamp.milliSeconds, - }, - mac: tt.mac.clone(), - }); + let timestamp_token = if let Some(tt) = timestamp_token { + Some(kmr_wire::secureclock::TimeStampToken { + challenge: tt.challenge, + timestamp: kmr_wire::secureclock::Timestamp { + milliseconds: tt.timestamp.milliSeconds, + }, + mac: tt.mac.clone(), + }) + } else { + None + }; let input = input.map(|i| i.to_vec()); let signature = signature.map(|s| s.to_vec()); let confirmation_token = confirmation_token.map(|c| c.to_vec()); let req = PerformOpReq::OperationFinish(FinishRequest { op_handle, - input, - signature, + input: input, + signature: signature, auth_token: hardware_auth_token, - timestamp_token, - confirmation_token, + timestamp_token: timestamp_token, + confirmation_token: confirmation_token, }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Error::Binder( ExceptionCode::ServiceSpecific, result.error_code, @@ -1037,7 +1094,7 @@ impl KeyMintWrapper { pub fn op_abort(&self, op_handle: i64) -> Result<(), Error> { let req = PerformOpReq::OperationAbort(AbortRequest { op_handle }); let result = self.keymint.lock().unwrap().process_req(req); - if result.rsp.is_none() { + if let None = result.rsp { return Err(Error::Binder( ExceptionCode::ServiceSpecific, result.error_code, @@ -1142,9 +1199,9 @@ fn init_keymint_ta(security_level: SecurityLevel) -> Result { sha256: Box::new(kmr_crypto_boring::sha256::BoringSha256), }; - let keys: Box = Box::new(soft::Keys::new( - config.crypto.root_kek_seed, - config.crypto.kak_seed, + let keys: Box = Box::new(soft::Keys::new( + config.crypto.root_kek_seed.clone(), + config.crypto.kak_seed.clone(), )); let rpc: Box = Box::new(soft::RpcArtifacts::new( soft::Derive::default(), @@ -1201,7 +1258,7 @@ fn init_keymint_ta(security_level: SecurityLevel) -> Result { let req = PerformOpReq::SetHalInfo(kmr_wire::SetHalInfoRequest { os_version: config.trust.os_version as u32, os_patchlevel, - vendor_patchlevel: boot_patchlevel, + vendor_patchlevel: os_patchlevel, }); let resp = ta.process_req(req); if resp.error_code != 0 { @@ -1210,9 +1267,7 @@ fn init_keymint_ta(security_level: SecurityLevel) -> Result { let module_hash = crate::global::ENCODED_MODULE_INFO.get_or_try_init(|| -> Result, anyhow::Error> { - let apex_info = crate::global::APEX_MODULE_HASH - .as_ref() - .map_err(|_| anyhow::anyhow!("Failed to get APEX module info."))?; + let apex_info = crate::plat::utils::get_apex_module_info()?; let encoding = encode_module_info(apex_info) .map_err(|_| anyhow::anyhow!("Failed to encode module info."))?; diff --git a/src/keymaster/keymint_operation.rs b/src/keymaster/keymint_operation.rs index b3bbfd4..20557e9 100644 --- a/src/keymaster/keymint_operation.rs +++ b/src/keymaster/keymint_operation.rs @@ -49,7 +49,7 @@ impl IKeyMintOperation for KeyMintOperation { get_keymint_wrapper(self.security_level) .unwrap() .op_update_aad(self.op_handle, input, authToken, timeStampToken) - .map_err(map_ks_error)?; + .map_err(|e| map_ks_error(e))?; Ok(()) } @@ -64,8 +64,8 @@ impl IKeyMintOperation for KeyMintOperation { get_keymint_wrapper(self.security_level) .unwrap() .op_update(self.op_handle, input, authToken, timeStampToken) - .map_err(map_ks_error) - .map(|rsp: Vec| rsp.to_vec()) + .map_err(|e| map_ks_error(e)) + .and_then(|rsp: Vec| Ok(rsp.to_vec())) } fn r#finish( @@ -88,14 +88,14 @@ impl IKeyMintOperation for KeyMintOperation { timestampToken, confirmationToken, ) - .map_err(map_ks_error) - .map(|rsp: Vec| rsp.to_vec()) + .map_err(|e| map_ks_error(e)) + .and_then(|rsp: Vec| Ok(rsp.to_vec())) } fn r#abort(&self) -> rsbinder::status::Result<()> { get_keymint_wrapper(self.security_level) .unwrap() .op_abort(self.op_handle) - .map_err(map_ks_error) + .map_err(|e| map_ks_error(e)) } } diff --git a/src/keymaster/security_level.rs b/src/keymaster/security_level.rs index c52a3cb..36eb93b 100644 --- a/src/keymaster/security_level.rs +++ b/src/keymaster/security_level.rs @@ -19,14 +19,14 @@ use crate::{ err, global::{DB, ENFORCEMENTS, SUPER_KEY, UNDEFINED_NOT_AFTER}, keymaster::{ - attestation_key_utils::{get_attest_key_info, AttestationKeyInfo}, + attestation_key_utils::{AttestationKeyInfo, get_attest_key_info}, db::{ BlobInfo, BlobMetaData, BlobMetaEntry, CertificateInfo, DateTime, KeyEntry, KeyEntryLoadBits, KeyIdGuard, KeyMetaData, KeyMetaEntry, KeyType, SubComponentType, Uuid, }, - error::{into_logged_binder, map_binder_status, KsError}, - keymint_device::KeyMintWrapper, + error::{KsError, into_logged_binder, map_binder_status}, + keymint_device::{KeyMintWrapper}, metrics_store::log_key_creation_event_stats, operation::{KeystoreOperation, LoggingInfo, OperationDb}, super_key::{KeyBlob, SuperKeyManager}, @@ -60,8 +60,8 @@ pub struct KeystoreSecurityLevel { impl KeystoreSecurityLevel { pub fn new(security_level: SecurityLevel, km_uuid: Uuid) -> Result { let km_wrapper = KeyMintWrapper::new(security_level) - .expect(err!("Failed to init strongbox wrapper").as_str()); - + .expect(err!("Failed to init strongbox wrapper").as_str()); + let hw_info = km_wrapper .get_hardware_info() .context(err!("Failed to get hardware info."))?; @@ -142,25 +142,25 @@ impl KeystoreSecurityLevel { let creation_datetime = SystemTime::now(); // Add CREATION_DATETIME only if the backend version Keymint V1 (100) or newer. - // if self.hw_info.version_number >= 100 { - result.push(KeyParameter { - tag: Tag::CREATION_DATETIME, - value: KeyParameterValue::DateTime( - creation_datetime - .duration_since(SystemTime::UNIX_EPOCH) - .context(err!( - "KeystoreSecurityLevel::add_required_parameters: \ + if self.hw_info.version_number >= 100 { + result.push(KeyParameter { + tag: Tag::CREATION_DATETIME, + value: KeyParameterValue::DateTime( + creation_datetime + .duration_since(SystemTime::UNIX_EPOCH) + .context(err!( + "KeystoreSecurityLevel::add_required_parameters: \ Failed to get epoch time." - ))? - .as_millis() - .try_into() - .context(err!( - "KeystoreSecurityLevel::add_required_parameters: \ + ))? + .as_millis() + .try_into() + .context(err!( + "KeystoreSecurityLevel::add_required_parameters: \ Failed to convert epoch time." - ))?, - ), - }); - // } + ))?, + ), + }); + } // If there is an attestation challenge we need to get an application id. if params.iter().any(|kp| kp.tag == Tag::ATTESTATION_CHALLENGE) { @@ -466,8 +466,7 @@ impl KeystoreSecurityLevel { ), 5000, // Generate can take a little longer. ); - let result = self - .get_keymint_wrapper() + let result = self.get_keymint_wrapper() .generateKey(¶ms, attest_key.as_ref()); map_binder_status(result) }, @@ -486,7 +485,8 @@ impl KeystoreSecurityLevel { ), 5000, // Generate can take a little longer. ); - self.get_keymint_wrapper().generateKey(¶ms, None) + self.get_keymint_wrapper() + .generateKey(¶ms, None) } .context(err!( "While generating without a provided \ @@ -1005,8 +1005,9 @@ impl IKeystoreSecurityLevel for KeystoreSecurityLevel { forced: bool, ) -> Result { let _wp = self.watch("IKeystoreSecurityLevel::createOperation"); - self.create_operation(None, key, operation_parameters, forced) - .map_err(into_logged_binder) + Ok(self + .create_operation(None, key, operation_parameters, forced) + .map_err(into_logged_binder)?) } fn generateKey( @@ -1096,8 +1097,9 @@ impl IOhMySecurityLevel for KeystoreSecurityLevel { forced: bool, ) -> Result { let _wp = self.watch("IOhMySecurityLevel::createOperation"); - self.create_operation(ctx, key, operation_parameters, forced) - .map_err(into_logged_binder) + Ok(self + .create_operation(ctx, key, operation_parameters, forced) + .map_err(into_logged_binder)?) } fn generateKey( diff --git a/src/keymaster/service.rs b/src/keymaster/service.rs index 1dd2a39..7980f12 100644 --- a/src/keymaster/service.rs +++ b/src/keymaster/service.rs @@ -468,9 +468,7 @@ impl KeystoreService { Tag::MODULE_HASH => { let info = ENCODED_MODULE_INFO.get_or_try_init(|| -> Result, anyhow::Error> { - let apex_info = crate::global::APEX_MODULE_HASH - .as_ref() - .map_err(|_| anyhow::anyhow!("Failed to get APEX module info."))?; + let apex_info = crate::plat::utils::get_apex_module_info()?; let encoding = encode_module_info(apex_info) .map_err(|_| anyhow::anyhow!("Failed to encode module info."))?; @@ -790,15 +788,9 @@ impl IOhMyKsService for KeystoreService { .unwrap_or(()); // reset KeyMintTa - get_keymint_wrapper(SecurityLevel::TRUSTED_ENVIRONMENT) - .unwrap() - .reset_keymint_ta() - .unwrap(); + get_keymint_wrapper(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap().reset_keymint_ta().unwrap(); - get_keymint_wrapper(SecurityLevel::STRONGBOX) - .unwrap() - .reset_keymint_ta() - .unwrap(); + get_keymint_wrapper(SecurityLevel::STRONGBOX).unwrap().reset_keymint_ta().unwrap(); Result::Ok(()) } diff --git a/src/keymaster/super_key.rs b/src/keymaster/super_key.rs index 9b9c0a7..b74b576 100644 --- a/src/keymaster/super_key.rs +++ b/src/keymaster/super_key.rs @@ -364,10 +364,9 @@ impl SuperKeyManager { } pub fn level_accessible(&self, boot_level: i32) -> bool { - self.data - .boot_level_key_cache - .as_ref() - .is_some_and(|c| c.lock().unwrap().level_accessible(boot_level as usize)) + self.data.boot_level_key_cache.as_ref().map_or(false, |c| { + c.lock().unwrap().level_accessible(boot_level as usize) + }) } pub fn forget_all_keys_for_user(&mut self, user: UserId) { diff --git a/src/keymaster/utils.rs b/src/keymaster/utils.rs index 0993490..e942ab1 100644 --- a/src/keymaster/utils.rs +++ b/src/keymaster/utils.rs @@ -6,9 +6,9 @@ use crate::{ }, consts, err, keymaster::{ - error::{map_ks_error, KsError as Error}, + error::{KsError as Error, map_ks_error}, key_parameter::KeyParameter, - keymint_device::{get_keymint_wrapper, KeyMintDevice}, + keymint_device::{KeyMintDevice, get_keymint_wrapper}, }, watchdog, }; @@ -20,7 +20,7 @@ use kmr_wire::{ }; pub fn log_params(params: &[KmKeyParameter]) -> Vec { - params.to_vec() + params.iter().cloned().collect::>() } /// Converts a set of key characteristics as returned from KeyMint into the internal @@ -623,7 +623,7 @@ pub fn key_creation_result_to_aidl( let params: Result, rsbinder::Status> = kc.authorizations.iter().map(|p| { key_param_to_aidl(p.clone()) .map_err(|_| Error::Km(ErrorCode::INVALID_ARGUMENT)) - .map_err(map_ks_error) + .map_err(|e| map_ks_error(e)) }).collect(); let params = params?; @@ -635,7 +635,12 @@ pub fn key_creation_result_to_aidl( SecurityLevel::TRUSTED_ENVIRONMENT } kmr_wire::keymint::SecurityLevel::Strongbox => SecurityLevel::STRONGBOX, - kmr_wire::keymint::SecurityLevel::Keystore => SecurityLevel::KEYSTORE, + _ => { + return Err(rsbinder::Status::new_service_specific_error( + ErrorCode::UNKNOWN_ERROR.0, + None, + )) + } }, }) diff --git a/src/keymint/clock.rs b/src/keymint/clock.rs index f9faccf..1d4af52 100644 --- a/src/keymint/clock.rs +++ b/src/keymint/clock.rs @@ -43,6 +43,6 @@ impl crypto::MonotonicClock for StdClock { warn!("failed to get time!"); return crypto::MillisecondsSinceEpoch(0); } - crypto::MillisecondsSinceEpoch((time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000)) + crypto::MillisecondsSinceEpoch(((time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000)).into()) } } diff --git a/src/keymint/sdd.rs b/src/keymint/sdd.rs index 65af5a3..b8607ac 100644 --- a/src/keymint/sdd.rs +++ b/src/keymint/sdd.rs @@ -31,7 +31,7 @@ use std::path; const SECURE_DELETION_DATA_FILE: &str = "./omk/data/keymint.dat"; #[cfg(target_os = "android")] -const SECURE_DELETION_DATA_FILE: &str = "/data/misc/keystore/omk/data/keymint.dat"; +const SECURE_DELETION_DATA_FILE: &str = "/data/adb/omk/data/keymint.dat"; fn read_sdd_file() -> Result { let f = fs::File::open(SECURE_DELETION_DATA_FILE).map_err(|e| { diff --git a/src/logging.rs b/src/logging.rs index 0caf184..212caab 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -37,9 +37,5 @@ pub fn init_logger() { let log4rs = log4rs::Logger::new(config); - multi_log::MultiLogger::init( - vec![Box::new(android_logger), Box::new(log4rs)], - log::Level::Debug, - ) - .unwrap(); + multi_log::MultiLogger::init(vec![Box::new(android_logger), Box::new(log4rs)], log::Level::Debug).unwrap(); } diff --git a/src/main.rs b/src/main.rs index 29604ef..c033269 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use std::panic; -use log::{debug, error, info}; +use log::{debug, error}; use rsbinder::hub; use crate::{ @@ -36,53 +36,42 @@ const TAG: &str = "OhMyKeymint"; fn main() { logging::init_logger(); - info!("Hello, OhMyKeymint!"); - info!("Reading config"); + debug!("Hello, OhMyKeymint!"); + debug!("Reading config"); let config = CONFIG.read().unwrap(); - info!("Initial process state"); + debug!("Initial process state"); rsbinder::ProcessState::init_default(); - // We can no longer retrieve APEX module info after dropping privileges. - debug!("Retrieving APEX module hash with root privileges"); - if let Err(e) = global::APEX_MODULE_HASH.as_ref() { - error!("Failed to retrieve APEX module info: {:?}", e); - } - - unsafe { - info!("Setting UID to KEYSTORE_UID (1017)"); - libc::setuid(1017); // KEYSTORE_UID - } - // Redirect panic messages to logcat. panic::set_hook(Box::new(|panic_info| { error!("{}", panic_info); })); - info!("Starting thread pool"); + debug!("Starting thread pool"); rsbinder::ProcessState::start_thread_pool(); match config.main.backend { Backend::OMK => { - info!("Using OhMyKeymint backend"); - info!("Creating keystore service"); + debug!("Using OhMyKeymint backend"); + debug!("Creating keystore service"); let dev = KeystoreService::new_native_binder().unwrap(); let service = BnKeystoreService::new_binder(dev); - info!("Adding keystore service to hub"); + debug!("Adding keystore service to hub"); hub::add_service("keystore3", service.as_binder()).unwrap(); } Backend::TrickyStore => { - info!("Using TrickyStore backend"); - info!("Creating keystore service"); + debug!("Using TrickyStore backend"); + debug!("Creating keystore service"); let dev = KeystoreService::new_native_binder().unwrap(); - info!("Adding OMK service to hub"); + debug!("Adding OMK service to hub"); let service = BnOhMyKsService::new_binder(dev); hub::add_service("omk", service.as_binder()).unwrap(); } } - info!("Joining thread pool"); + debug!("Joining thread pool"); rsbinder::ProcessState::join_thread_pool().unwrap(); } diff --git a/src/plat/property_watcher.rs b/src/plat/property_watcher.rs index 6ff9a7d..657778a 100644 --- a/src/plat/property_watcher.rs +++ b/src/plat/property_watcher.rs @@ -1,3 +1,6 @@ +use log::info; +use rsproperties::PropertyConfig; + #[cfg(not(target_os = "android"))] use rsproperties_service; @@ -30,7 +33,7 @@ impl PropertyWatcher { pub fn read(&self) -> Result { rsproperties::system_properties() - .get_with_result(self.name.as_str()) + .get_with_result(&self.name.as_str()) .context(anyhow!("Property '{}' not found", self.name)) } @@ -39,7 +42,7 @@ impl PropertyWatcher { F: FnMut(&str) -> Result, { rsproperties::system_properties() - .get_with_result(self.name.as_str()) + .get_with_result(&self.name.as_str()) .context(anyhow!("Property '{}' not found", self.name)) .and_then(|value| f(value.as_str())) } diff --git a/src/plat/utils.rs b/src/plat/utils.rs index 36cb82c..220139a 100644 --- a/src/plat/utils.rs +++ b/src/plat/utils.rs @@ -106,14 +106,14 @@ pub fn get_aaid(uid: u32) -> anyhow::Result> { let current_uid = unsafe { libc::getuid() }; let current_euid = unsafe { libc::geteuid() }; debug!("Current UID: {}, EUID: {}", current_uid, current_euid); - // unsafe { - // libc::seteuid(1017); // KEYSTORE_UID - // } - - // unsafe { - // libc::seteuid(current_euid); - // } - pm.getKeyAttestationApplicationId(uid as i32) + unsafe { + libc::seteuid(1017); // KEYSTORE_UID + } + let result = pm.getKeyAttestationApplicationId(uid as i32); + unsafe { + libc::seteuid(current_euid); + } + result }; if let Result::Ok(application_id) = result { break application_id; @@ -153,7 +153,7 @@ fn encode_application_id( .hash(sig.data.as_slice()) .map_err(|e| anyhow::anyhow!("Failed to hash signature: {:?}", e))?; - let octet_string = x509_cert::der::asn1::OctetString::new(result)?; + let octet_string = x509_cert::der::asn1::OctetString::new(&result)?; let result = signature_digests.insert_ordered(octet_string).map_err(|e| { anyhow::anyhow!(err!("Failed to encode AttestationApplicationId: {:?}", e)) @@ -177,7 +177,7 @@ fn encode_application_id( let result = super::aaid::AttestationApplicationId { package_info_records: package_info_set, - signature_digests, + signature_digests: signature_digests, }; result @@ -187,11 +187,9 @@ fn encode_application_id( pub fn get_apex_module_info() -> anyhow::Result> { let apex = get_apex()?; - let result: Vec = - apex.getActivePackages().map_err(|e| { - log::error!("Failed to get active packages: {:?}", e); - anyhow::anyhow!(err!("getActivePackages failed: {:?}", e)) - })?; + let result: Vec = apex + .getAllPackages() + .map_err(|e| anyhow::anyhow!(err!("getAllPackages failed: {:?}", e)))?; let result: Vec = result .iter() diff --git a/src/utils.rs b/src/utils.rs index 96c7abf..f277ca7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -9,7 +9,7 @@ pub fn get_current_time_in_milliseconds() -> i64 { // SAFETY: The pointer is valid because it comes from a reference, and clock_gettime doesn't // retain it beyond the call. unsafe { libc::clock_gettime(libc::CLOCK_BOOTTIME, &mut current_time) }; - current_time.tv_sec * 1000 + (current_time.tv_nsec / 1_000_000) + current_time.tv_sec as i64 * 1000 + (current_time.tv_nsec as i64 / 1_000_000) } pub trait ParcelExt { diff --git a/ta/Cargo.toml b/ta/Cargo.toml index e1ccb10..a05ccf9 100644 --- a/ta/Cargo.toml +++ b/ta/Cargo.toml @@ -17,7 +17,7 @@ downgrade = [] [dependencies] ciborium = { version = "^0.2.0", default-features = false } ciborium-io = "^0.2.0" -coset = "0.4.0" +coset = "0.3.3" der = { version = "^0.7.8", features = ["alloc", "derive"] } flagset = "0.4.3" kmr-common = "*" diff --git a/ta/src/cert.rs b/ta/src/cert.rs index b566d60..52e5efb 100644 --- a/ta/src/cert.rs +++ b/ta/src/cert.rs @@ -28,7 +28,7 @@ use kmr_common::crypto::KeyMaterial; use kmr_common::{ crypto, der_err, get_tag_value, km_err, tag, try_to_vec, vec_try_with_capacity, Error, }; -use kmr_common::{get_bool_tag_value, get_opt_tag_value, modify_tag_value, FallibleAllocExt}; +use kmr_common::{get_bool_tag_value, get_opt_tag_value, FallibleAllocExt}; use kmr_wire::{ keymint, keymint::{ @@ -445,12 +445,10 @@ macro_rules! check_attestation_id { match $mustmatch { None => return Err(km_err!(CannotAttestIds, "no attestation IDs provisioned")), - Some(want) => if val != want.as_slice() { - let result = modify_tag_value!($params, $variant, want.to_vec()); - if result.is_err() { - return Err(result.unwrap_err()); - } - log::info!("attestation ID mismatch for {}, reseting to {:?}", stringify!($variant), want); + Some(want) => if val != want { + return Err(km_err!(CannotAttestIds, + "attestation ID mismatch for {}", + stringify!($variant))) } } } @@ -469,50 +467,48 @@ impl<'a> AuthorizationList<'a> { app_id: Option<&'a [u8]>, additional_attestation_info: &'a [KeyParam], ) -> Result { - let mut keygen_params = keygen_params.to_vec(); - check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdBrand, attestation_ids.map(|v| &v.brand) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdDevice, attestation_ids.map(|v| &v.device) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdProduct, attestation_ids.map(|v| &v.product) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdSerial, attestation_ids.map(|v| &v.serial) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdImei, attestation_ids.map(|v| &v.imei) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdSecondImei, attestation_ids.map(|v| &v.imei2) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdMeid, attestation_ids.map(|v| &v.meid) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdManufacturer, attestation_ids.map(|v| &v.manufacturer) ); check_attestation_id!( - &mut keygen_params, + keygen_params, AttestationIdModel, attestation_ids.map(|v| &v.model) ); @@ -1375,7 +1371,7 @@ struct RootOfTrust<'a> { } impl<'a> From<&'a keymint::BootInfo> for RootOfTrust<'a> { - fn from(info: &keymint::BootInfo) -> RootOfTrust<'_> { + fn from(info: &keymint::BootInfo) -> RootOfTrust { let verified_boot_key: &[u8] = if info.verified_boot_key.is_empty() { // If an empty verified boot key was passed by the boot loader, set the verified boot // key in the attestation to all zeroes. diff --git a/ta/src/clock.rs b/ta/src/clock.rs index b8945d5..906be9b 100644 --- a/ta/src/clock.rs +++ b/ta/src/clock.rs @@ -17,6 +17,7 @@ use core::mem::size_of; use kmr_common::{km_err, vec_try_with_capacity, Error}; use kmr_wire::secureclock::{TimeStampToken, TIME_STAMP_MAC_LABEL}; +use Vec; impl crate::KeyMintTa { pub(crate) fn generate_timestamp(&self, challenge: i64) -> Result { diff --git a/ta/src/keys.rs b/ta/src/keys.rs index adc8e2b..862e622 100644 --- a/ta/src/keys.rs +++ b/ta/src/keys.rs @@ -30,7 +30,7 @@ use kmr_wire::{ }, *, }; -use log::{debug, error, warn}; +use log::{error, warn}; use spki::SubjectPublicKeyInfoOwned; use std::collections::btree_map::Entry; use x509_cert::ext::pkix::KeyUsages; @@ -399,14 +399,6 @@ impl crate::KeyMintTa { key_material: KeyMaterial, purpose: keyblob::SlotPurpose, ) -> Result { - debug!( - "finish_keyblob_creation: params {:?} attestKey {:?}", - params, attestation_key - ); - debug!("key characteristics: {:?}", chars); - debug!("key material: {:?}", key_material); - debug!("keyblob purpose: {:?}", purpose); - let keyblob = keyblob::PlaintextKeyBlob { // Don't include any `SecurityLevel::Keystore` characteristics in the set that is bound // to the key. diff --git a/ta/src/lib.rs b/ta/src/lib.rs index 08e1098..dd25e43 100644 --- a/ta/src/lib.rs +++ b/ta/src/lib.rs @@ -196,7 +196,7 @@ pub fn split_rsp(mut rsp_data: &[u8], max_size: usize) -> Result>, E // Need to allocate one byte for the more_msg_signal. let allowed_msg_length = max_size - 1; let mut num_of_splits = rsp_data.len() / allowed_msg_length; - if !rsp_data.len().is_multiple_of(allowed_msg_length) { + if rsp_data.len() % allowed_msg_length > 0 { num_of_splits += 1; } let mut split_rsp = vec_try_with_capacity!(num_of_splits)?; diff --git a/template/AOSP.Apache-license-2.0.txt b/template/AOSP.Apache-license-2.0.txt deleted file mode 100644 index d645695..0000000 --- a/template/AOSP.Apache-license-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/template/LICENSE.1 b/template/LICENSE.1 deleted file mode 120000 index 7eabdb1..0000000 --- a/template/LICENSE.1 +++ /dev/null @@ -1 +0,0 @@ -../LICENSE.md \ No newline at end of file diff --git a/template/LICENSE.2 b/template/LICENSE.2 deleted file mode 120000 index 8945da6..0000000 --- a/template/LICENSE.2 +++ /dev/null @@ -1 +0,0 @@ -../LICENSE-2 \ No newline at end of file diff --git a/template/README.md b/template/README.md deleted file mode 120000 index 32d46ee..0000000 --- a/template/README.md +++ /dev/null @@ -1 +0,0 @@ -../README.md \ No newline at end of file diff --git a/template/customize.sh b/template/customize.sh index 263862a..684cca5 100644 --- a/template/customize.sh +++ b/template/customize.sh @@ -1,9 +1,10 @@ # shellcheck disable=SC2034 SKIPUNZIP=1 -SONAME="Oh My Keymint" -SUPPORTED_ABIS="arm64" -MIN_SDK=29 +DEBUG=@DEBUG@ +SONAME=@SONAME@ +SUPPORTED_ABIS="@SUPPORTED_ABIS@" +MIN_SDK=@MIN_SDK@ if [ "$BOOTMODE" ] && [ "$KSU" ]; then ui_print "- Installing from KernelSU app" @@ -71,10 +72,10 @@ chmod 755 "$MODPATH/daemon" # if [ "$ARCH" = "x64" ]; then # ui_print "- Extracting x64 libraries" -# extract "$ZIPFILE" "libs/x86_64/keymint" "$MODPATH" true +# extract "$ZIPFILE" "lib/x86_64/keymint" "$MODPATH" true # else ui_print "- Extracting arm64 libraries" - extract "$ZIPFILE" "libs/arm64-v8a/keymint" "$MODPATH" true + extract "$ZIPFILE" "lib/arm64-v8a/keymint" "$MODPATH" true # fi chmod 755 "$MODPATH/keymint" diff --git a/template/daemon b/template/daemon index d7716c3..a09d291 100644 --- a/template/daemon +++ b/template/daemon @@ -1,7 +1,5 @@ #!/system/bin/sh -export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/vendor/lib64/:/system/lib64/:/apex/com.android.runtime/lib64/bionic/" - if [ -f "/data/adb/omk/keymint" ]; then chmod 0755 "/data/adb/omk/keymint" exec "/data/adb/omk/keymint" "$@" diff --git a/template/sepolicy.rule b/template/sepolicy.rule index ee37842..c1d02a4 100644 --- a/template/sepolicy.rule +++ b/template/sepolicy.rule @@ -1,9 +1,4 @@ allow keystore system_file unix_dgram_socket * allow system_file keystore unix_dgram_socket * allow keystore system_file file * - -allow keystore adb_data_file unix_dgram_socket * -allow adb_data_file keystore unix_dgram_socket * -allow keystore adb_data_file file * - allow crash_dump keystore process * diff --git a/template/service.sh b/template/service.sh index c5983f9..9acbb09 100644 --- a/template/service.sh +++ b/template/service.sh @@ -1,3 +1,5 @@ +DEBUG=@DEBUG@ + MODDIR=${0%/*} cd $MODDIR diff --git a/wire/Cargo.toml b/wire/Cargo.toml index 1adc4f3..ce3d1e7 100644 --- a/wire/Cargo.toml +++ b/wire/Cargo.toml @@ -20,7 +20,7 @@ hal_v2 = [] [dependencies] ciborium = { version = "^0.2.2", default-features = false } ciborium-io = "^0.2.0" -coset = "0.4.0" +coset = "0.3.3" enumn = "0.1.4" kmr-derive = "*" log = "^0.4"