diff --git a/keystore2/Android.bp b/keystore2/Android.bp index 0069f958..64636ac7 100644 --- a/keystore2/Android.bp +++ b/keystore2/Android.bp @@ -46,7 +46,6 @@ rust_defaults { "libkeystore2_crypto_rust", "libkeystore2_km_compat", "libkeystore2_selinux", - "libkeystore2_system_property-rust", "libkeystore2_vintf_rust", "liblazy_static", "liblibc", @@ -55,6 +54,7 @@ rust_defaults { "liblog_rust", "librand", "librusqlite", + "libsystem_properties-rust", "libthiserror", ], shared_libs: [ diff --git a/keystore2/src/metrics_store.rs b/keystore2/src/metrics_store.rs index 32067b95..9f535d5c 100644 --- a/keystore2/src/metrics_store.rs +++ b/keystore2/src/metrics_store.rs @@ -45,11 +45,11 @@ use android_security_metrics::aidl::android::security::metrics::{ Storage::Storage as MetricsStorage, }; use anyhow::{Context, Result}; -use keystore2_system_property::{write, PropertyWatcher, PropertyWatcherError}; use lazy_static::lazy_static; use std::collections::HashMap; use std::sync::Mutex; use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use system_properties::{write, PropertyWatcher, PropertyWatcherError}; // Note: Crash events are recorded at keystore restarts, based on the assumption that keystore only // gets restarted after a crash, during a boot cycle. diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs index e02d9bcf..fbb03601 100644 --- a/keystore2/src/super_key.rs +++ b/keystore2/src/super_key.rs @@ -46,13 +46,13 @@ use keystore2_crypto::{ aes_gcm_decrypt, aes_gcm_encrypt, generate_aes256_key, generate_salt, Password, ZVec, AES_256_KEY_LENGTH, }; -use keystore2_system_property::PropertyWatcher; use std::{ collections::HashMap, sync::Arc, sync::{Mutex, Weak}, }; use std::{convert::TryFrom, ops::Deref}; +use system_properties::PropertyWatcher; const MAX_MAX_BOOT_LEVEL: usize = 1_000_000_000; /// Allow up to 15 seconds between the user unlocking using a biometric, and the auth diff --git a/keystore2/system_property/Android.bp b/keystore2/system_property/Android.bp deleted file mode 100644 index 773804d9..00000000 --- a/keystore2/system_property/Android.bp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2021, The Android Open Source Project -// -// 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. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "system_security_license" - // to get the below license kinds: - // SPDX-license-identifier-Apache-2.0 - default_applicable_licenses: ["system_security_license"], -} - -rust_bindgen { - name: "libkeystore2_system_property_bindgen", - wrapper_src: "system_property_bindgen.hpp", - crate_name: "keystore2_system_property_bindgen", - source_stem: "bindings", - - bindgen_flags: [ - "--size_t-is-usize", - "--allowlist-function=__system_property_find", - "--allowlist-function=__system_property_read_callback", - "--allowlist-function=__system_property_set", - "--allowlist-function=__system_property_wait", - ], -} - -rust_library { - name: "libkeystore2_system_property-rust", - crate_name: "keystore2_system_property", - srcs: [ - "lib.rs", - ], - rustlibs: [ - "libanyhow", - "libkeystore2_system_property_bindgen", - "libthiserror", - ], - shared_libs: [ - "libbase", - ], -} diff --git a/keystore2/system_property/lib.rs b/keystore2/system_property/lib.rs deleted file mode 100644 index b993c879..00000000 --- a/keystore2/system_property/lib.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2021, The Android Open Source Project -// -// 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. - -//! This crate provides the PropertyWatcher type, which watches for changes -//! in Android system properties. - -use anyhow::{anyhow, Context, Result as AnyhowResult}; -use keystore2_system_property_bindgen::prop_info as PropInfo; -use std::os::raw::c_char; -use std::ptr::null; -use std::{ - ffi::{c_void, CStr, CString}, - str::Utf8Error, -}; -use thiserror::Error; - -/// Errors this crate can generate -#[derive(Error, Debug)] -pub enum PropertyWatcherError { - /// We can't watch for a property whose name contains a NUL character. - #[error("Cannot convert name to C string")] - BadNameError(#[from] std::ffi::NulError), - /// We can only watch for properties that exist when the watcher is created. - #[error("System property is absent")] - SystemPropertyAbsent, - /// __system_property_wait timed out despite being given no timeout. - #[error("Wait failed")] - WaitFailed, - /// read callback was not called - #[error("__system_property_read_callback did not call callback")] - ReadCallbackNotCalled, - /// read callback gave us a NULL pointer - #[error("__system_property_read_callback gave us a NULL pointer instead of a string")] - MissingCString, - /// read callback gave us a bad C string - #[error("__system_property_read_callback gave us a non-UTF8 C string")] - BadCString(#[from] Utf8Error), - /// read callback returned an error - #[error("Callback failed")] - CallbackError(#[from] anyhow::Error), - /// Failure in setting the system property - #[error("__system_property_set failed.")] - SetPropertyFailed, -} - -/// Result type specific for this crate. -pub type Result = std::result::Result; - -/// PropertyWatcher takes the name of an Android system property such -/// as `keystore.boot_level`; it can report the current value of this -/// property, or wait for it to change. -pub struct PropertyWatcher { - prop_name: CString, - prop_info: *const PropInfo, - serial: keystore2_system_property_bindgen::__uint32_t, -} - -impl PropertyWatcher { - /// Create a PropertyWatcher for the named system property. - pub fn new(name: &str) -> Result { - Ok(Self { prop_name: CString::new(name)?, prop_info: null(), serial: 0 }) - } - - // Lazy-initializing accessor for self.prop_info. - fn get_prop_info(&mut self) -> Option<*const PropInfo> { - if self.prop_info.is_null() { - // Unsafe required for FFI call. Input and output are both const. - // The returned pointer is valid for the lifetime of the program. - self.prop_info = unsafe { - keystore2_system_property_bindgen::__system_property_find(self.prop_name.as_ptr()) - }; - } - if self.prop_info.is_null() { - None - } else { - Some(self.prop_info) - } - } - - fn read_raw(prop_info: *const PropInfo, mut f: impl FnOnce(Option<&CStr>, Option<&CStr>)) { - // Unsafe function converts values passed to us by - // __system_property_read_callback to Rust form - // and pass them to inner callback. - unsafe extern "C" fn callback( - res_p: *mut c_void, - name: *const c_char, - value: *const c_char, - _: keystore2_system_property_bindgen::__uint32_t, - ) { - let name = if name.is_null() { None } else { Some(CStr::from_ptr(name)) }; - let value = if value.is_null() { None } else { Some(CStr::from_ptr(value)) }; - let f = &mut *res_p.cast::<&mut dyn FnMut(Option<&CStr>, Option<&CStr>)>(); - f(name, value); - } - - let mut f: &mut dyn FnOnce(Option<&CStr>, Option<&CStr>) = &mut f; - - // Unsafe block for FFI call. We convert the FnOnce - // to a void pointer, and unwrap it in our callback. - unsafe { - keystore2_system_property_bindgen::__system_property_read_callback( - prop_info, - Some(callback), - &mut f as *mut _ as *mut c_void, - ) - } - } - - /// Call the passed function, passing it the name and current value - /// of this system property. See documentation for - /// `__system_property_read_callback` for details. - /// Returns an error if the property is empty or doesn't exist. - pub fn read(&mut self, f: F) -> Result - where - F: FnOnce(&str, &str) -> anyhow::Result, - { - let prop_info = self.get_prop_info().ok_or(PropertyWatcherError::SystemPropertyAbsent)?; - let mut result = Err(PropertyWatcherError::ReadCallbackNotCalled); - Self::read_raw(prop_info, |name, value| { - // use a wrapping closure as an erzatz try block. - result = (|| { - let name = name.ok_or(PropertyWatcherError::MissingCString)?.to_str()?; - let value = value.ok_or(PropertyWatcherError::MissingCString)?.to_str()?; - f(name, value).map_err(PropertyWatcherError::CallbackError) - })() - }); - result - } - - // Waits for the property that self is watching to be created. Returns immediately if the - // property already exists. - fn wait_for_property_creation(&mut self) -> Result<()> { - let mut global_serial = 0; - loop { - match self.get_prop_info() { - Some(_) => return Ok(()), - None => { - // Unsafe call for FFI. The function modifies only global_serial, and has - // no side-effects. - if !unsafe { - // Wait for a global serial number change, then try again. On success, - // the function will update global_serial with the last version seen. - keystore2_system_property_bindgen::__system_property_wait( - null(), - global_serial, - &mut global_serial, - null(), - ) - } { - return Err(PropertyWatcherError::WaitFailed); - } - } - } - } - } - - /// Wait for the system property to change. This - /// records the serial number of the last change, so - /// race conditions are avoided. - pub fn wait(&mut self) -> Result<()> { - // If the property is null, then wait for it to be created. Subsequent waits will - // skip this step and wait for our specific property to change. - if self.prop_info.is_null() { - return self.wait_for_property_creation(); - } - - let mut new_serial = self.serial; - // Unsafe block to call __system_property_wait. - // All arguments are private to PropertyWatcher so we - // can be confident they are valid. - if !unsafe { - keystore2_system_property_bindgen::__system_property_wait( - self.prop_info, - self.serial, - &mut new_serial, - null(), - ) - } { - return Err(PropertyWatcherError::WaitFailed); - } - self.serial = new_serial; - Ok(()) - } -} - -/// Writes a system property. -pub fn write(name: &str, value: &str) -> AnyhowResult<()> { - if - // Unsafe required for FFI call. Input and output are both const and valid strings. - unsafe { - // If successful, __system_property_set returns 0, otherwise, returns -1. - keystore2_system_property_bindgen::__system_property_set( - CString::new(name) - .context("In keystore2::system_property::write: Construction CString from name.")? - .as_ptr(), - CString::new(value) - .context("In keystore2::system_property::write: Constructing CString from value.")? - .as_ptr(), - ) - } == 0 - { - Ok(()) - } else { - Err(anyhow!(PropertyWatcherError::SetPropertyFailed)) - } -} diff --git a/keystore2/system_property/system_property_bindgen.hpp b/keystore2/system_property/system_property_bindgen.hpp deleted file mode 100644 index e3c1ade0..00000000 --- a/keystore2/system_property/system_property_bindgen.hpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * 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. - */ -#pragma once - -#include "sys/system_properties.h"