use std::ops::BitAnd;
use std::convert::TryFrom;
#[cfg(not(windows))]
use libc::tm;
use sequoia_openpgp as openpgp;
use openpgp::KeyHandle;
mod session;
pub use session::Session;
mod identity;
pub use identity::{
PepIdentityTemplate,
PepIdentity,
PepIdentityListItem,
PepIdentityList,
};
mod stringlist;
pub use stringlist::{
StringListItem,
StringList,
StringListIterMut,
StringListIter,
};
macro_rules! wrap_err {
($e:expr, $err:ident, $msg:expr) => {
$e.map_err(|err| {
eprintln!("Error: {}: {}\n{:?}",
err, $msg, backtrace::Backtrace::new());
crate::pep::Error::$err(
anyhow::Error::from(err).into(),
String::from($msg))
})
}
}
pub type Result<T> = std::result::Result<T, Error>;
pub type ErrorCode = i32;
#[enumber::into]
#[repr(i32)]
#[non_exhaustive]
#[derive(thiserror::Error, Debug)]
#[allow(unused)]
pub enum Error {
#[error("Success")]
StatusOk = 0,
#[error("Initializing the crypto library failed: {0}")]
InitCryptoLibInitFailed(String) = 0x0111,
#[error("Opening the database failed: {1}")]
InitCannotOpenDB(#[source] anyhow::Error, String) = 0x0121,
#[error("Database error: {1}")]
UnknownDbError(#[source] anyhow::Error, String) = 0x01ff,
#[error("Key {0} not present in database")]
KeyNotFound(KeyHandle) = 0x0201,
#[error("Getting key: {1}")]
GetKeyFailed(#[source] anyhow::Error, String) = 0x0203,
#[error("Key unsuitable: {0}")]
KeyUnsuitable(#[source] anyhow::Error, String) = 0x0206,
#[error("Cannot delete key: {0}")]
CannotDeleteKey(#[source] anyhow::Error, String) = 0x0212,
#[error("Imported key")]
KeyImported = 0x0220,
#[error("No key imported")]
NoKeyImported = 0x0221,
#[error("Some keys imported")]
SomeKeysImported = 0x0223,
#[error("Message not encrypted and not verified")]
Unencrypted = 0x0400,
#[error("Message not encrypted, but verified")]
Verified = 0x0401,
#[error("Decrypted message")]
Decrypted = 0x0402,
#[error("Decrypted and verified message")]
DecryptedAndVerified = 0x0403,
#[error("Decrypted failed: wrong format")]
DecryptWrongFormat = 0x0404,
#[error("Decrypted failed: no key")]
DecryptNoKey(#[source] anyhow::Error) = 0x0405,
#[error("Decrypted failed: signature does not match")]
DecryptSignatureDoesNotMatch = 0x0406,
#[error("Verification failed: no key")]
VerifyNoKey(#[source] anyhow::Error) = 0x0407,
#[error("Signer's key is revoked")]
VerifySignerKeyRevoked = 0x040a,
#[error("Cannot decrypt: {0}")]
CannotDecryptUnknown(String) = 0x04ff,
#[error("Cannot create key")]
CannotCreateKey(#[source] anyhow::Error, String) = 0x0601,
#[error("Passphrase required")]
PassphraseRequired = 0x0a00,
#[error("Bad passphrase")]
WrongPassphrase(#[source] anyhow::Error, String) = 0x0a01,
#[error("Passphrase required for new keys")]
PassphraseForNewKeysRequired = 0x0a02,
#[error("Invalid configuration: {0}")]
CannotConfig(String) = 0xff04,
#[error("Illegal value: {0}")]
IllegalValue(String) = -4,
#[error("Out of memory: {1} bytes for {0}")]
OutOfMemory(String, usize) = -2,
#[error("Unknown error: {1}")]
UnknownError(#[source] anyhow::Error, String) = -1,
}
#[cfg(not(windows))]
pub type Timestamp = tm;
#[cfg(windows)]
use libc::{c_int, c_long};
#[cfg(windows)]
#[repr(C)]
pub struct Timestamp {
pub tm_sec: c_int,
pub tm_min: c_int,
pub tm_hour: c_int,
pub tm_mday: c_int,
pub tm_mon: c_int,
pub tm_year: c_int,
pub tm_wday: c_int,
pub tm_yday: c_int,
pub tm_isdst: c_int,
pub tm_gmtoff: c_long, }
#[repr(C)]
#[allow(unused)]
#[derive(PartialOrd, Ord, PartialEq, Eq, Copy, Clone, Debug)]
pub enum PepCommType {
Unknown = 0,
NoEncryption = 0x01, NoEncryptedChannel = 0x02,
KeyNotFound = 0x03,
KeyExpired = 0x04,
KeyRevoked = 0x05,
KeyB0rken = 0x06,
KeyExpiredButConfirmed = 0x07, MyKeyNotIncluded = 0x09,
SecurityByObscurity = 0x0a,
B0rkenCrypto = 0x0b,
KeyTooShort = 0x0c,
Compromised = 0x0e, Mistrusted = 0x0f,
UnconfirmedEncryption = 0x10, OpenPgpWeakUnconfirmed = 0x11,
ToBeChecked = 0x20, SMimeUnconfirmed = 0x21,
CmsUnconfirmed = 0x22,
StrongButUnconfirmed = 0x30, OpenPgpUnconfirmed = 0x38, OtrUnconfirmed = 0x3a,
UnconfirmedEncAnon = 0x40, PepUnconfirmed = 0x7f,
Confirmed = 0x80,
ConfirmedEncryption = 0x90, OpenPgpWeak = 0x91,
ToBeCheckedConfirmed = 0xa0, SMime = 0xa1,
Cms = 0xa2,
StrongEncryption = 0xb0, OpenPgp = 0xb8, Otr = 0xba,
ConfirmedEncAnon = 0xc0, Pep = 0xff
}
#[repr(C)]
#[allow(unused)]
pub enum PepEncFormat {
None = 0, Pieces = 1, SMime = 2, PgpMime = 3, Pep = 4, PgpMimeOutlook1 = 5, InlineEA = 6,
Auto = 255 }
#[repr(C)]
#[allow(unused)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PepIdentityFlags {
NotForSync = 0x0001,
List = 0x0002,
DeviceGroup = 0x0100,
OrgIdent = 0x0200,
GroupIdent = 0x0400,
}
impl BitAnd for PepIdentityFlags {
type Output = usize;
fn bitand(self, rhs: Self) -> Self::Output {
(self as usize) & (rhs as usize)
}
}
impl PepIdentityFlags {
pub fn is_set(&self, flag: PepIdentityFlags) -> bool {
let flag = flag as usize;
assert_eq!(flag.count_ones(), 1);
((*self as usize) & flag) != 0
}
}
#[repr(C)]
#[allow(unused)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum PepCipherSuite {
Default = 0,
Cv25519 = 1,
P256 = 2,
P384 = 3,
P521 = 4,
Rsa2K = 5,
Rsa3K = 6,
Rsa4K = 7,
Rsa8K = 8,
}
impl Default for PepCipherSuite {
fn default() -> Self {
PepCipherSuite::Default
}
}
impl TryFrom<PepCipherSuite> for openpgp::cert::CipherSuite {
type Error = Error;
fn try_from(cs: PepCipherSuite) -> Result<openpgp::cert::CipherSuite> {
use openpgp::cert::CipherSuite::*;
match cs {
PepCipherSuite::Default => Ok(RSA2k),
PepCipherSuite::Cv25519 => Ok(Cv25519),
PepCipherSuite::P256 => Ok(P256),
PepCipherSuite::P384 => Ok(P384),
PepCipherSuite::P521 => Ok(P521),
PepCipherSuite::Rsa2K => Ok(RSA2k),
PepCipherSuite::Rsa3K => Ok(RSA3k),
PepCipherSuite::Rsa4K => Ok(RSA4k),
_ => Err(Error::IllegalValue(
format!("Unknown cipher suite: {}", cs as usize)))
}
}
}