A backend for the p≡p Engine built on Sequoia.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

222 lines
6.0 KiB

12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
  1. use std::ptr;
  2. use std::ffi::CStr;
  3. use std::convert::TryInto;
  4. use libc::c_char;
  5. use sequoia_openpgp as openpgp;
  6. use openpgp::crypto::Password;
  7. use crate::Error;
  8. use crate::Keystore;
  9. use crate::PepCipherSuite;
  10. use crate::Result;
  11. use crate::{Malloc, Free};
  12. const MAGIC: u64 = 0xE3F3_05AD_48EE_0DF5;
  13. pub struct State {
  14. ks: Keystore,
  15. malloc: Malloc,
  16. free: Free,
  17. magic: u64,
  18. }
  19. impl State {
  20. /// Converts the raw pointer to a Rust reference.
  21. ///
  22. /// This does *not* take ownership of the object.
  23. ///
  24. /// Sanity checks the data structure.
  25. pub fn as_mut(ptr: *mut Self) -> &'static mut Self {
  26. let s = unsafe { ptr.as_mut() }.expect("NULL pointer");
  27. assert_eq!(s.magic, MAGIC, "magic");
  28. s
  29. }
  30. /// Converts a raw pointer back into a Rust object.
  31. ///
  32. /// Takes ownership of the object.
  33. pub fn to_rust(ptr: *mut Self) -> Box<Self> {
  34. assert!(! ptr.is_null());
  35. let s = unsafe { Box::from_raw(ptr) };
  36. assert_eq!(s.magic, MAGIC, "magic");
  37. s
  38. }
  39. /// Converts the Rust object to a raw pointer.
  40. ///
  41. /// Transfers ownership to the caller.
  42. pub fn to_c(self) -> *mut Self {
  43. Box::into_raw(Box::new(self))
  44. }
  45. }
  46. #[repr(C)]
  47. pub struct Session {
  48. pub version: *const u8,
  49. pub state: *mut State,
  50. pub curr_passphrase: *const c_char,
  51. pub new_key_pass_enabled: bool,
  52. pub generation_passphrase: *const c_char,
  53. pub cipher_suite: PepCipherSuite,
  54. }
  55. impl Session {
  56. /// Returns a new session.
  57. ///
  58. /// This is normally initialized by the engine, but we need this
  59. /// for testing.
  60. #[cfg(test)]
  61. pub fn new() -> *mut Session {
  62. Box::into_raw(Box::new(Session {
  63. version: ptr::null(),
  64. state: Box::into_raw(Box::new(State {
  65. ks: Keystore::init_in_memory().unwrap(),
  66. malloc: libc::malloc,
  67. free: libc::free,
  68. magic: MAGIC,
  69. })),
  70. curr_passphrase: ptr::null(),
  71. new_key_pass_enabled: false,
  72. generation_passphrase: ptr::null(),
  73. cipher_suite: PepCipherSuite::Default,
  74. }))
  75. }
  76. pub fn init(&mut self,
  77. ks: Keystore,
  78. malloc: Malloc,
  79. free: Free)
  80. {
  81. assert!(self.state.is_null());
  82. self.state = Box::into_raw(Box::new(State {
  83. ks: ks,
  84. malloc: malloc,
  85. free: free,
  86. magic: MAGIC,
  87. }));
  88. }
  89. pub fn deinit(&mut self) {
  90. let _ = State::to_rust(self.state);
  91. self.state = ptr::null_mut();
  92. }
  93. /// Converts the raw pointer to a Rust reference.
  94. ///
  95. /// This does not take ownership of the object.
  96. pub fn as_mut(ptr: *mut Self) -> &'static mut Self {
  97. unsafe { ptr.as_mut() }.expect("NULL pointer")
  98. }
  99. /// Returns a reference to the keystore.
  100. ///
  101. /// This panics if the keystore has not yet been set (see
  102. /// [`Session::set_keystore`].
  103. pub fn keystore(&mut self) -> &mut Keystore {
  104. &mut State::as_mut(self.state).ks
  105. }
  106. /// Returns the application's malloc routine.
  107. pub fn malloc(&self) -> Malloc {
  108. State::as_mut(self.state).malloc
  109. }
  110. /// Returns the application's free routine.
  111. pub fn free(&self) -> Free {
  112. State::as_mut(self.state).free
  113. }
  114. /// Returns the value of curr_passphrase.
  115. pub fn curr_passphrase(&self) -> Option<Password> {
  116. unsafe {
  117. self.curr_passphrase.as_ref().and_then(|ptr| {
  118. let bytes = CStr::from_ptr(ptr).to_bytes();
  119. // A zero-length password is not a password.
  120. if bytes.len() == 0 {
  121. None
  122. } else {
  123. Some(Password::from(bytes))
  124. }
  125. })
  126. }
  127. }
  128. /// Returns the value of new_key_pass_enabled.
  129. pub fn new_key_pass_enabled(&self) -> bool {
  130. self.new_key_pass_enabled
  131. }
  132. /// Returns the value of generation_passphrase.
  133. pub fn generation_passphrase(&self) -> Option<Password> {
  134. unsafe {
  135. self.generation_passphrase.as_ref().and_then(|ptr| {
  136. let bytes = CStr::from_ptr(ptr).to_bytes();
  137. // A zero-length password is not a password.
  138. if bytes.len() == 0 {
  139. None
  140. } else {
  141. Some(Password::from(bytes))
  142. }
  143. })
  144. }
  145. }
  146. /// Returns the value of cipher_suite.
  147. pub fn cipher_suite(&self) -> PepCipherSuite {
  148. self.cipher_suite
  149. }
  150. /// Sets the value of cipher suite.
  151. ///
  152. /// If suite is known and supported, this function returns
  153. /// success. If suite is not known or not supported, then this
  154. /// sets the cipher suite to the default!
  155. pub fn set_cipher_suite(&mut self, suite: PepCipherSuite) -> Result<()> {
  156. let sq_suite: Result<openpgp::cert::CipherSuite> = suite.try_into();
  157. match sq_suite {
  158. Ok(_) => {
  159. self.cipher_suite = suite;
  160. Ok(())
  161. }
  162. Err(_err) => {
  163. self.cipher_suite = PepCipherSuite::Rsa2K;
  164. Err(Error::CannotConfig("cipher suite".into()))
  165. }
  166. }
  167. }
  168. }
  169. #[cfg(test)]
  170. mod tests {
  171. use super::*;
  172. // Make sure the pointer is cleared when the state is dropped.
  173. #[test]
  174. fn state() {
  175. let session = Session::new();
  176. {
  177. let session: &mut Session = Session::as_mut(session);
  178. let ks = session.keystore() as *mut _;
  179. let ks2 = session.keystore() as *mut _;
  180. assert!(ptr::eq(ks, ks2));
  181. session.deinit();
  182. // If the state pointer is non-NULL, this will panic.
  183. session.init(Keystore::init_in_memory().unwrap(),
  184. libc::malloc, libc::free);
  185. let ks = session.keystore() as *mut _;
  186. let ks2 = session.keystore() as *mut _;
  187. assert!(ptr::eq(ks, ks2));
  188. session.deinit();
  189. }
  190. unsafe { Box::from_raw(session) };
  191. }
  192. }