diff --git a/src/keystore.rs b/src/keystore.rs index 90d4f3f3443ca2b91b886a056f030a262b970aab..95b931f6319ef209f3958c70cf03467e6b6705ee 100644 --- a/src/keystore.rs +++ b/src/keystore.rs @@ -35,8 +35,6 @@ use crate::constants::{ }; use crate::pep::PepIdentityTemplate; -const MAGIC: u64 = 0xE3F3_05AD_48EE_0DF5; - // Pick the fastest hash function from the SHA2 family for the // architecture's word size. On 64-bit architectures, SHA512 is // almost twice as fast, but on 32-bit ones, SHA256 is faster. @@ -52,7 +50,6 @@ const CERT_CACHE_ENTRIES: usize = 32; type CertCache = LruCache, Cert>; pub struct Keystore { - magic: u64, conn: rusqlite::Connection, // The certificate cache. // @@ -97,36 +94,6 @@ macro_rules! sql_stmt { } impl Keystore { - /// Converts the raw pointer to a Rust reference. - /// - /// This does *not* take ownership of the object. - /// - /// Sanity checks the data structure. - pub fn as_mut(ptr: *mut Self) -> &'static mut Self { - let ks = unsafe { ptr.as_mut() }.expect("NULL pointer"); - assert_eq!(ks.magic, MAGIC, "magic"); - - ks - } - - /// Converts a raw pointer back into a Rust object. - /// - /// Takes ownership of the object. - pub fn to_rust(ptr: *mut Self) -> Box { - assert!(! ptr.is_null()); - let ks = unsafe { Box::from_raw(ptr) }; - assert_eq!(ks.magic, MAGIC, "magic"); - - ks - } - - /// Converts the Rust object to a raw pointer. - /// - /// Transfers ownership to the caller. - pub fn to_c(self) -> *mut Self { - Box::into_raw(Box::new(self)) - } - // Compares two User IDs. // // Extracts the email address or URI stored in each User ID and @@ -271,7 +238,6 @@ impl Keystore { keys_db.display()))?; Ok(Keystore { - magic: MAGIC, conn, cert_cache: LruCache::new(CERT_CACHE_ENTRIES), }) diff --git a/src/lib.rs b/src/lib.rs index 98ac6d75c55d109b48c54c190561d84041c25992..cb857ab7b77c1c3cf64e5b275ad79b1f548f030b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -229,7 +229,7 @@ ffi!(fn pgp_init_(session: *mut Session, _in_first: bool, assert!(session_size as usize >= size_of::()); assert_eq!(session_cookie_offset as usize, - offset_of!(Session, ks)); + offset_of!(Session, state)); assert_eq!(session_curr_passphrase_offset as usize, offset_of!(Session, curr_passphrase)); assert_eq!(session_new_key_pass_enable as usize, @@ -273,14 +273,14 @@ ffi!(fn pgp_init_(session: *mut Session, _in_first: bool, }; let ks = keystore::Keystore::init(Path::new(per_user_directory))?; - session.set_keystore(ks); + session.init(ks); Ok(()) }); // void pgp_release(PEP_SESSION session, bool out_last) ffi!(fn pgp_release(session: *mut Session, _out_last: bool) -> Result<()> { - Session::as_mut(session).drop_keystore(); + Session::as_mut(session).deinit(); Ok(()) }); diff --git a/src/pep/session.rs b/src/pep/session.rs index fde7926c32df1ca3ef0be2b917a4230ed18c559a..971e4ac1b73682f06bb10dd991e1d67366c39d51 100644 --- a/src/pep/session.rs +++ b/src/pep/session.rs @@ -12,10 +12,49 @@ use crate::Keystore; use crate::PepCipherSuite; use crate::Result; +const MAGIC: u64 = 0xE3F3_05AD_48EE_0DF5; + +pub struct State { + ks: Keystore, + magic: u64, +} + +impl State { + /// Converts the raw pointer to a Rust reference. + /// + /// This does *not* take ownership of the object. + /// + /// Sanity checks the data structure. + pub fn as_mut(ptr: *mut Self) -> &'static mut Self { + let s = unsafe { ptr.as_mut() }.expect("NULL pointer"); + assert_eq!(s.magic, MAGIC, "magic"); + + s + } + + /// Converts a raw pointer back into a Rust object. + /// + /// Takes ownership of the object. + pub fn to_rust(ptr: *mut Self) -> Box { + assert!(! ptr.is_null()); + let s = unsafe { Box::from_raw(ptr) }; + assert_eq!(s.magic, MAGIC, "magic"); + + s + } + + /// Converts the Rust object to a raw pointer. + /// + /// Transfers ownership to the caller. + pub fn to_c(self) -> *mut Self { + Box::into_raw(Box::new(self)) + } +} + #[repr(C)] pub struct Session { pub version: *const u8, - pub ks: *mut Keystore, + pub state: *mut State, pub curr_passphrase: *const c_char, pub new_key_pass_enabled: bool, pub generation_passphrase: *const c_char, @@ -31,7 +70,10 @@ impl Session { pub fn new() -> *mut Session { Box::into_raw(Box::new(Session { version: ptr::null(), - ks: ptr::null_mut(), + state: Box::into_raw(Box::new(State { + ks: Keystore::init_in_memory().unwrap(), + magic: MAGIC, + })), curr_passphrase: ptr::null(), new_key_pass_enabled: false, generation_passphrase: ptr::null(), @@ -39,6 +81,22 @@ impl Session { })) } + pub fn init(&mut self, + ks: Keystore) + { + assert!(self.state.is_null()); + + self.state = Box::into_raw(Box::new(State { + ks: ks, + magic: MAGIC, + })); + } + + pub fn deinit(&mut self) { + let _ = State::to_rust(self.state); + self.state = ptr::null_mut(); + } + /// Converts the raw pointer to a Rust reference. /// /// This does not take ownership of the object. @@ -51,26 +109,7 @@ impl Session { /// This panics if the keystore has not yet been set (see /// [`Session::set_keystore`]. pub fn keystore(&mut self) -> &mut Keystore { - Keystore::as_mut(self.ks) - } - - /// Sets the keystore. - /// - /// This panics if a keystore has already been set. - /// - /// The keystore can be dropped using [`Session::drop_keystore`]. - pub fn set_keystore(&mut self, ks: Keystore) { - assert!(self.ks.is_null()); - self.ks = ks.to_c(); - } - - /// Drops the keystore. - /// - /// This panics if a keystore has already been set. - pub fn drop_keystore(&mut self) { - let _ = Keystore::to_rust(self.ks); - // Reset the pointer. - self.ks = ptr::null_mut() as *mut _; + &mut State::as_mut(self.state).ks } /// Returns the value of curr_passphrase. @@ -137,26 +176,25 @@ impl Session { mod tests { use super::*; - // Make sure the pointer is cleared when the key store is dropped. + // Make sure the pointer is cleared when the state is dropped. #[test] - fn keystore() { + fn state() { let session = Session::new(); { let session: &mut Session = Session::as_mut(session); - session.set_keystore(Keystore::init_in_memory().unwrap()); let ks = session.keystore() as *mut _; let ks2 = session.keystore() as *mut _; assert!(ptr::eq(ks, ks2)); - session.drop_keystore(); + session.deinit(); - // If the keystore pointer is non-NULL, this will panic. - session.set_keystore(Keystore::init_in_memory().unwrap()); + // If the state pointer is non-NULL, this will panic. + session.init(Keystore::init_in_memory().unwrap()); let ks = session.keystore() as *mut _; let ks2 = session.keystore() as *mut _; assert!(ptr::eq(ks, ks2)); - session.drop_keystore(); + session.deinit(); } unsafe { Box::from_raw(session) };