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.

407 lines
14 KiB

  1. use std::ops::BitAnd;
  2. use std::convert::TryFrom;
  3. use libc::tm;
  4. use sequoia_openpgp as openpgp;
  5. use openpgp::KeyHandle;
  6. mod session;
  7. pub use session::Session;
  8. mod identity;
  9. pub use identity::{
  10. PepIdentityTemplate,
  11. PepIdentity,
  12. PepIdentityListItem,
  13. PepIdentityList,
  14. };
  15. mod stringlist;
  16. pub use stringlist::{
  17. StringListItem,
  18. StringList,
  19. StringListIterMut,
  20. StringListIter,
  21. };
  22. // Transforms an error from some error type to the pep::Error.
  23. macro_rules! wrap_err {
  24. ($e:expr, $err:ident, $msg:expr) => {
  25. $e.map_err(|err| {
  26. eprintln!("Error: {}: {}\n{:?}",
  27. err, $msg, backtrace::Backtrace::new());
  28. crate::pep::Error::$err(
  29. anyhow::Error::from(err).into(),
  30. String::from($msg))
  31. })
  32. }
  33. }
  34. // We use Error rather than anyhow's error so that we force the
  35. // function to convert the error into a form that we can easily pass
  36. // back to the engine.
  37. pub type Result<T> = std::result::Result<T, Error>;
  38. // The pEp engine's error type.
  39. pub type ErrorCode = i32;
  40. #[enumber::into]
  41. // XXX: This should be ErrorCode, but we can't use type aliases here :/.
  42. #[repr(i32)]
  43. #[non_exhaustive]
  44. #[derive(thiserror::Error, Debug)]
  45. #[allow(unused)]
  46. pub enum Error {
  47. #[error("Success")]
  48. StatusOk = 0,
  49. #[error("Initializing the crypto library failed: {0}")]
  50. InitCryptoLibInitFailed(String) = 0x0111,
  51. // PEP_INIT_CANNOT_LOAD_CRYPTO_LIB = 0x0110,
  52. // PEP_INIT_CRYPTO_LIB_INIT_FAILED = 0x0111,
  53. // PEP_INIT_NO_CRYPTO_HOME = 0x0112,
  54. // PEP_INIT_NETPGP_INIT_FAILED = 0x0113,
  55. // PEP_INIT_CANNOT_DETERMINE_CRYPTO_VERSION = 0x0114,
  56. // PEP_INIT_UNSUPPORTED_CRYPTO_VERSION = 0x0115,
  57. // PEP_INIT_CANNOT_CONFIG_CRYPTO_AGENT = 0x0116,
  58. //
  59. // PEP_INIT_SQLITE3_WITHOUT_MUTEX = 0x0120,
  60. #[error("Opening the database failed: {1}")]
  61. InitCannotOpenDB(#[source] anyhow::Error, String) = 0x0121,
  62. // PEP_INIT_CANNOT_OPEN_SYSTEM_DB = 0x0122,
  63. // PEP_INIT_DB_DOWNGRADE_VIOLATION = 0x0123,
  64. #[error("Database error: {1}")]
  65. UnknownDbError(#[source] anyhow::Error, String) = 0x01ff,
  66. #[error("Key {0} not present in database")]
  67. KeyNotFound(KeyHandle) = 0x0201,
  68. // PEP_KEY_HAS_AMBIG_NAME = 0x0202,
  69. #[error("Getting key: {1}")]
  70. GetKeyFailed(#[source] anyhow::Error, String) = 0x0203,
  71. // PEP_CANNOT_EXPORT_KEY = 0x0204,
  72. // PEP_CANNOT_EDIT_KEY = 0x0205,
  73. #[error("Key unsuitable: {0}")]
  74. KeyUnsuitable(#[source] anyhow::Error, String) = 0x0206,
  75. // PEP_MALFORMED_KEY_RESET_MSG = 0x0210,
  76. // PEP_KEY_NOT_RESET = 0x0211,
  77. #[error("Cannot delete key: {0}")]
  78. CannotDeleteKey(#[source] anyhow::Error, String) = 0x0212,
  79. #[error("Imported key")]
  80. KeyImported = 0x0220,
  81. #[error("No key imported")]
  82. NoKeyImported = 0x0221,
  83. // PEP_KEY_IMPORT_STATUS_UNKNOWN = 0x0222,
  84. #[error("Some keys imported")]
  85. SomeKeysImported = 0x0223,
  86. // PEP_CANNOT_FIND_IDENTITY = 0x0301,
  87. // PEP_CANNOT_SET_PERSON = 0x0381,
  88. // PEP_CANNOT_SET_PGP_KEYPAIR = 0x0382,
  89. // PEP_CANNOT_SET_IDENTITY = 0x0383,
  90. // PEP_CANNOT_SET_TRUST = 0x0384,
  91. // PEP_KEY_BLACKLISTED = 0x0385,
  92. // PEP_CANNOT_FIND_PERSON = 0x0386,
  93. // PEP_CANNOT_SET_PEP_VERSION = 0X0387,
  94. //
  95. // PEP_CANNOT_FIND_ALIAS = 0x0391,
  96. // PEP_CANNOT_SET_ALIAS = 0x0392,
  97. // PEP_NO_OWN_USERID_FOUND = 0x0393,
  98. //
  99. #[error("Message not encrypted and not verified")]
  100. Unencrypted = 0x0400,
  101. #[error("Message not encrypted, but verified")]
  102. Verified = 0x0401,
  103. #[error("Decrypted message")]
  104. Decrypted = 0x0402,
  105. #[error("Decrypted and verified message")]
  106. DecryptedAndVerified = 0x0403,
  107. #[error("Decrypted failed: wrong format")]
  108. DecryptWrongFormat = 0x0404,
  109. #[error("Decrypted failed: no key")]
  110. DecryptNoKey(#[source] anyhow::Error) = 0x0405,
  111. #[error("Decrypted failed: signature does not match")]
  112. DecryptSignatureDoesNotMatch = 0x0406,
  113. #[error("Verification failed: no key")]
  114. VerifyNoKey(#[source] anyhow::Error) = 0x0407,
  115. // PEP_VERIFIED_AND_TRUSTED = 0x0408,
  116. // PEP_CANNOT_REENCRYPT = 0x0409,
  117. #[error("Signer's key is revoked")]
  118. VerifySignerKeyRevoked = 0x040a,
  119. #[error("Cannot decrypt: {0}")]
  120. CannotDecryptUnknown(String) = 0x04ff,
  121. //
  122. //
  123. // PEP_TRUSTWORD_NOT_FOUND = 0x0501,
  124. // PEP_TRUSTWORDS_FPR_WRONG_LENGTH = 0x0502,
  125. // PEP_TRUSTWORDS_DUPLICATE_FPR = 0x0503,
  126. //
  127. #[error("Cannot create key")]
  128. CannotCreateKey(#[source] anyhow::Error, String) = 0x0601,
  129. // PEP_CANNOT_SEND_KEY = 0x0602,
  130. //
  131. // PEP_PHRASE_NOT_FOUND = 0x0701,
  132. //
  133. // PEP_SEND_FUNCTION_NOT_REGISTERED = 0x0801,
  134. // PEP_CONTRAINTS_VIOLATED = 0x0802,
  135. // PEP_CANNOT_ENCODE = 0x0803,
  136. //
  137. // PEP_SYNC_NO_NOTIFY_CALLBACK = 0x0901,
  138. // PEP_SYNC_ILLEGAL_MESSAGE = 0x0902,
  139. // PEP_SYNC_NO_INJECT_CALLBACK = 0x0903,
  140. // PEP_SYNC_NO_CHANNEL = 0x0904,
  141. // PEP_SYNC_CANNOT_ENCRYPT = 0x0905,
  142. // PEP_SYNC_NO_MESSAGE_SEND_CALLBACK = 0x0906,
  143. // PEP_SYNC_CANNOT_START = 0x0907,
  144. //
  145. // PEP_CANNOT_INCREASE_SEQUENCE = 0x0971,
  146. //
  147. // PEP_STATEMACHINE_ERROR = 0x0980,
  148. // PEP_NO_TRUST = 0x0981,
  149. // PEP_STATEMACHINE_INVALID_STATE = 0x0982,
  150. // PEP_STATEMACHINE_INVALID_EVENT = 0x0983,
  151. // PEP_STATEMACHINE_INVALID_CONDITION = 0x0984,
  152. // PEP_STATEMACHINE_INVALID_ACTION = 0x0985,
  153. // PEP_STATEMACHINE_INHIBITED_EVENT = 0x0986,
  154. // PEP_STATEMACHINE_CANNOT_SEND = 0x0987,
  155. //
  156. #[error("Passphrase required")]
  157. PassphraseRequired = 0x0a00,
  158. #[error("Bad passphrase")]
  159. WrongPassphrase(#[source] anyhow::Error, String) = 0x0a01,
  160. #[error("Passphrase required for new keys")]
  161. PassphraseForNewKeysRequired = 0x0a02,
  162. //
  163. // PEP_CANNOT_CREATE_GROUP = 0x0b00,
  164. // PEP_CANNOT_FIND_GROUP_ENTRY = 0x0b01,
  165. // PEP_GROUP_EXISTS = 0x0b02,
  166. // PEP_GROUP_NOT_FOUND = 0x0b03,
  167. // PEP_CANNOT_ENABLE_GROUP = 0x0b04,
  168. // PEP_CANNOT_DISABLE_GROUP = 0x0b05,
  169. // PEP_CANNOT_ADD_GROUP_MEMBER = 0x0b06,
  170. // PEP_CANNOT_DEACTIVATE_GROUP_MEMBER = 0x0b07,
  171. // PEP_NO_MEMBERSHIP_STATUS_FOUND = 0x0b08,
  172. // PEP_CANNOT_LEAVE_GROUP = 0x0b09,
  173. // PEP_CANNOT_JOIN_GROUP = 0x0b0a,
  174. // PEP_CANNOT_RETRIEVE_MEMBERSHIP_INFO = 0x0b0b,
  175. //
  176. // PEP_DISTRIBUTION_ILLEGAL_MESSAGE = 0x1002,
  177. // PEP_STORAGE_ILLEGAL_MESSAGE = 0x1102,
  178. //
  179. // PEP_COMMIT_FAILED = 0xff01,
  180. // PEP_MESSAGE_CONSUME = 0xff02,
  181. // PEP_MESSAGE_IGNORE = 0xff03,
  182. #[error("Invalid configuration: {0}")]
  183. CannotConfig(String) = 0xff04,
  184. //
  185. // PEP_RECORD_NOT_FOUND = -6,
  186. // PEP_CANNOT_CREATE_TEMP_FILE = -5,
  187. #[error("Illegal value: {0}")]
  188. IllegalValue(String) = -4,
  189. // PEP_BUFFER_TOO_SMALL = -3,
  190. #[error("Out of memory: {1} bytes for {0}")]
  191. OutOfMemory(String, usize) = -2,
  192. #[error("Unknown error: {1}")]
  193. UnknownError(#[source] anyhow::Error, String) = -1,
  194. // PEP_VERSION_MISMATCH = -7,
  195. }
  196. // See pEpEngine/src/timestamp.h
  197. //
  198. // https://gitea.pep.foundation/pEp.foundation/pEpEngine/src/branch/master/src/timestamp.h
  199. #[cfg(not(windows))]
  200. pub type Timestamp = tm;
  201. #[cfg(windows)]
  202. #[repr(C)]
  203. // for time values all functions are using POSIX struct tm
  204. pub struct Timestamp {
  205. tm_sec: c_int,
  206. tm_min: c_int,
  207. tm_hour: c_int,
  208. tm_mday: c_int,
  209. tm_mon: c_int,
  210. tm_year: c_int,
  211. tm_wday: c_int,
  212. tm_yday: c_int,
  213. tm_isdst: c_int,
  214. tm_gmtoff: c_long, // offset from GMT in seconds
  215. }
  216. // See pEpEngine/src/pEpEngine.h:PEP_comm_format.
  217. //
  218. // https://gitea.pep.foundation/pEp.foundation/pEpEngine/src/branch/master/src/pEpEngine.h#L697
  219. #[repr(C)]
  220. #[allow(unused)]
  221. #[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Debug)]
  222. pub enum PepCommType {
  223. Unknown = 0,
  224. // range 0x01 to 0x09: no encryption, 0x0a to 0x0e: nothing reasonable
  225. NoEncryption = 0x01, // generic
  226. NoEncryptedChannel = 0x02,
  227. KeyNotFound = 0x03,
  228. KeyExpired = 0x04,
  229. KeyRevoked = 0x05,
  230. KeyB0rken = 0x06,
  231. KeyExpiredButConfirmed = 0x07, // NOT with confirmed bit. Just retaining info here in case of renewal.
  232. MyKeyNotIncluded = 0x09,
  233. SecurityByObscurity = 0x0a,
  234. B0rkenCrypto = 0x0b,
  235. KeyTooShort = 0x0c,
  236. Compromised = 0x0e, // known compromised connection
  237. Mistrusted = 0x0f, // known mistrusted key
  238. // range 0x10 to 0x3f: unconfirmed encryption
  239. UnconfirmedEncryption = 0x10, // generic
  240. OpenPgpWeakUnconfirmed = 0x11, // RSA 1024 is weak
  241. ToBeChecked = 0x20, // generic
  242. SMimeUnconfirmed = 0x21,
  243. CmsUnconfirmed = 0x22,
  244. StrongButUnconfirmed = 0x30, // generic
  245. OpenPgpUnconfirmed = 0x38, // key at least 2048 bit RSA or EC
  246. OtrUnconfirmed = 0x3a,
  247. // range 0x40 to 0x7f: unconfirmed encryption and anonymization
  248. UnconfirmedEncAnon = 0x40, // generic
  249. PepUnconfirmed = 0x7f,
  250. Confirmed = 0x80, // this bit decides if trust is confirmed
  251. // range 0x81 to 0x8f: reserved
  252. // range 0x90 to 0xbf: confirmed encryption
  253. ConfirmedEncryption = 0x90, // generic
  254. OpenPgpWeak = 0x91, // RSA 1024 is weak (unused)
  255. ToBeCheckedConfirmed = 0xa0, // generic
  256. SMime = 0xa1,
  257. Cms = 0xa2,
  258. StrongEncryption = 0xb0, // generic
  259. OpenPgp = 0xb8, // key at least 2048 bit RSA or EC
  260. Otr = 0xba,
  261. // range 0xc0 to 0xff: confirmed encryption and anonymization
  262. ConfirmedEncAnon = 0xc0, // generic
  263. Pep = 0xff
  264. }
  265. // See pEpEngine/src/pEpEngine.h:PEP_enc_format.
  266. //
  267. // https://gitea.pep.foundation/pEp.foundation/pEpEngine/src/branch/master/src/pEpEngine.h#L179
  268. #[repr(C)]
  269. #[allow(unused)]
  270. pub enum PepEncFormat {
  271. None = 0, // message is not encrypted
  272. Pieces = 1, // inline PGP + PGP extensions, was removed
  273. // Inline = 1, // still there
  274. SMime = 2, // RFC5751
  275. PgpMime = 3, // RFC3156
  276. Pep = 4, // pEp encryption format
  277. PgpMimeOutlook1 = 5, // Message B0rken by Outlook type 1
  278. InlineEA = 6,
  279. Auto = 255 // figure out automatically where possible
  280. }
  281. // See pEpEngine/src/pEpEngine.h:identity_flags.
  282. //
  283. // https://gitea.pep.foundation/pEp.foundation/pEpEngine/src/branch/master/src/pEpEngine.h#L765
  284. #[repr(C)]
  285. #[allow(unused)]
  286. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
  287. pub enum PepIdentityFlags {
  288. // the first octet flags are app defined settings:
  289. // don't use this identity for sync
  290. NotForSync = 0x0001,
  291. // identity of list of persons
  292. List = 0x0002,
  293. // the second octet flags are calculated:
  294. // identity of a device group member
  295. DeviceGroup = 0x0100,
  296. // identity is associated with an org (i.e. NOT a private account
  297. // - could be company email)
  298. OrgIdent = 0x0200,
  299. // identity is a group identity (e.g. mailing list) - N.B. not
  300. // related to device group!
  301. GroupIdent = 0x0400,
  302. }
  303. impl BitAnd for PepIdentityFlags {
  304. type Output = usize;
  305. fn bitand(self, rhs: Self) -> Self::Output {
  306. (self as usize) & (rhs as usize)
  307. }
  308. }
  309. impl PepIdentityFlags {
  310. /// Returns whether the specified flag is set.
  311. pub fn is_set(&self, flag: PepIdentityFlags) -> bool {
  312. let flag = flag as usize;
  313. assert_eq!(flag.count_ones(), 1);
  314. ((*self as usize) & flag) != 0
  315. }
  316. }
  317. // See pEpEngine/src/pEpEngine.h:PEP_CIPHER_SUITE.
  318. //
  319. // https://gitea.pep.foundation/pEp.foundation/pEpEngine/src/branch/master/src/pEpEngine.h#L395
  320. #[repr(C)]
  321. #[allow(unused)]
  322. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
  323. pub enum PepCipherSuite {
  324. Default = 0,
  325. Cv25519 = 1,
  326. P256 = 2,
  327. P384 = 3,
  328. P521 = 4,
  329. Rsa2K = 5,
  330. Rsa3K = 6,
  331. Rsa4K = 7,
  332. Rsa8K = 8,
  333. }
  334. impl Default for PepCipherSuite {
  335. fn default() -> Self {
  336. PepCipherSuite::Default
  337. }
  338. }
  339. impl TryFrom<PepCipherSuite> for openpgp::cert::CipherSuite {
  340. type Error = Error;
  341. fn try_from(cs: PepCipherSuite) -> Result<openpgp::cert::CipherSuite> {
  342. use openpgp::cert::CipherSuite::*;
  343. match cs {
  344. PepCipherSuite::Default => Ok(RSA2k),
  345. PepCipherSuite::Cv25519 => Ok(Cv25519),
  346. PepCipherSuite::P256 => Ok(P256),
  347. PepCipherSuite::P384 => Ok(P384),
  348. PepCipherSuite::P521 => Ok(P521),
  349. PepCipherSuite::Rsa2K => Ok(RSA2k),
  350. PepCipherSuite::Rsa3K => Ok(RSA3k),
  351. PepCipherSuite::Rsa4K => Ok(RSA4k),
  352. _ => Err(Error::IllegalValue(
  353. format!("Unknown cipher suite: {}", cs as usize)))
  354. }
  355. }
  356. }