This commit is contained in:
dignifiedquire
2019-09-22 22:31:26 +02:00
parent 77a7efc920
commit 8cf571c78a
8 changed files with 193 additions and 412 deletions

20
Cargo.lock generated
View File

@@ -301,7 +301,7 @@ dependencies = [
[[package]]
name = "circular"
version = "0.2.0"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -507,7 +507,7 @@ dependencies = [
"num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"pgp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pgp 0.2.2",
"pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"pretty_env_logger 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -860,6 +860,11 @@ name = "hex"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hex"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hostname"
version = "0.1.5"
@@ -1556,8 +1561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "pgp"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
version = "0.2.2"
dependencies = [
"aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1570,7 +1574,7 @@ dependencies = [
"cast5 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"cfb-mode 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
"circular 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"circular 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"crc24 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
"des 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1580,7 +1584,7 @@ dependencies = [
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"md-5 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2887,7 +2891,7 @@ dependencies = [
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
"checksum charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4f426e64df1c3de26cbf44593c6ffff5dbfd43bbf9de0d075058558126b3fc73"
"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
"checksum circular 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82945ea9ff134eba321833377d0c485f5c6fb4c8e26cfec199174e2970d5385a"
"checksum circular 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0fc239e0f6cb375d2402d48afb92f76f5404fd1df208a41930ec81eda078bea"
"checksum clear_on_drop 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "97276801e127ffb46b66ce23f35cc96bd454fa311294bced4bbace7baa8b1d17"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum constant_time_eq 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "995a44c877f9212528ccc74b21a232f66ad69001e40ede5bcee2ac9ef2657120"
@@ -2946,6 +2950,7 @@ dependencies = [
"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
"checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e"
"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e"
"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4"
"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
@@ -3019,7 +3024,6 @@ dependencies = [
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum pgp 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bb80b37b7debf9a98dc0caca3ed40ddf1d383691208763d0458df0b91521020f"
"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea"
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427"

View File

@@ -10,7 +10,7 @@ deltachat_derive = { path = "./deltachat_derive" }
mmime = { version = "0.1.2", path = "./mmime" }
libc = "0.2.51"
pgp = { version = "0.2", default-features = false }
pgp = { path = "../../rpgp/rpgp", default-features = false }
hex = "0.3.2"
sha2 = "0.8.0"
rand = "0.6.5"

View File

@@ -593,6 +593,25 @@ pub fn dc_read_file<P: AsRef<std::path::Path>>(
}
}
pub fn dc_open_file<P: AsRef<std::path::Path>>(
context: &Context,
path: P,
) -> Result<std::fs::File, Error> {
let path_abs = dc_get_abs_path(context, &path);
match fs::File::open(&path_abs) {
Ok(bytes) => Ok(bytes),
Err(err) => {
warn!(
context,
"Cannot read \"{}\" or file is empty.",
path.as_ref().display()
);
Err(err.into())
}
}
}
pub(crate) fn dc_get_next_backup_path(
folder: impl AsRef<Path>,
backup_time: i64,
@@ -612,6 +631,26 @@ pub(crate) fn dc_get_next_backup_path(
}
bail!("could not create backup file, disk full?");
}
pub(crate) fn dc_get_fine_path_filename(
context: &Context,
folder: impl AsRef<Path>,
backup_time: i64,
) -> Result<PathBuf, Error> {
let folder = PathBuf::from(folder.as_ref());
let stem = chrono::NaiveDateTime::from_timestamp(backup_time, 0)
.format("delta-chat-%Y-%m-%d")
.to_string();
// 64 backup files per day should be enough for everyone
for i in 0..64 {
let mut path = folder.clone();
path.push(format!("{}-{}.bak", stem, i));
if !path.exists() {
return Ok(path);
}
}
bail!("could not create backup file, disk full?");
}
pub(crate) fn dc_is_blobdir_path(context: &Context, path: impl AsRef<str>) -> bool {
context

View File

@@ -70,12 +70,6 @@ impl From<std::str::Utf8Error> for Error {
}
}
impl From<std::string::FromUtf8Error> for Error {
fn from(err: std::string::FromUtf8Error) -> Error {
Error::FromUtf8(err)
}
}
impl From<image_meta::ImageError> for Error {
fn from(err: image_meta::ImageError) -> Error {
Error::Image(err)
@@ -94,6 +88,12 @@ impl From<pgp::errors::Error> for Error {
}
}
impl From<std::string::FromUtf8Error> for Error {
fn from(err: std::string::FromUtf8Error) -> Error {
Error::FromUtf8(err)
}
}
#[macro_export]
macro_rules! bail {
($e:expr) => {

View File

@@ -1,7 +1,5 @@
use core::cmp::{max, min};
use std::ffi::CString;
use std::path::{Path, PathBuf};
use std::ptr;
use num_traits::FromPrimitive;
use rand::{thread_rng, Rng};
@@ -241,18 +239,12 @@ pub fn continue_key_transfer(context: &Context, msg_id: u32, setup_code: &str) -
);
if let Some(filename) = msg.get_file(context) {
if let Ok(ref mut buf) = dc_read_file(context, filename) {
let sc = normalize_setup_code(setup_code);
if let Ok(armored_key) = decrypt_setup_file(context, sc, buf) {
set_self_key(context, &armored_key, true, true)?;
} else {
bail!("Bad setup code.")
}
let file = dc_open_file(context, filename)?;
let sc = normalize_setup_code(setup_code);
let armored_key = decrypt_setup_file(context, &sc, file)?;
set_self_key(context, &armored_key, true, true)?;
Ok(())
} else {
bail!("Cannot read Autocrypt Setup Message file.");
}
Ok(())
} else {
bail!("Message is no Autocrypt Setup Message.");
}
@@ -326,53 +318,15 @@ fn set_self_key(
Ok(())
}
fn decrypt_setup_file(
_context: &Context,
passphrase: impl AsRef<str>,
filecontent: &mut [u8],
fn decrypt_setup_file<T: std::io::Read + std::io::Seek>(
context: &Context,
passphrase: &str,
file: T,
) -> Result<String> {
let mut fc_headerline = String::default();
let mut fc_base64: *const libc::c_char = ptr::null();
let plain_bytes = dc_pgp_symm_decrypt(passphrase, file)?;
let plain_text = std::string::String::from_utf8(plain_bytes)?;
let split_result = unsafe {
dc_split_armored_data(
filecontent.as_mut_ptr().cast(),
&mut fc_headerline,
ptr::null_mut(),
ptr::null_mut(),
&mut fc_base64,
)
};
if !split_result || fc_headerline != "-----BEGIN PGP MESSAGE-----" || fc_base64.is_null() {
bail!("Invalid armored data");
}
// convert base64 to binary
let base64_encoded =
unsafe { std::slice::from_raw_parts(fc_base64 as *const u8, libc::strlen(fc_base64)) };
let data = base64_decode(&base64_encoded)?;
// decrypt symmetrically
let payload = dc_pgp_symm_decrypt(passphrase.as_ref(), &data)?;
let payload_str = String::from_utf8(payload)?;
Ok(payload_str)
}
/// Decode the base64 encoded slice. Handles line breaks.
fn base64_decode(input: &[u8]) -> Result<Vec<u8>> {
use std::io::Read;
let c = std::io::Cursor::new(input);
let lr = pgp::line_reader::LineReader::new(c);
let br = pgp::base64_reader::Base64Reader::new(lr);
let mut reader = pgp::base64_decoder::Base64Decoder::new(br);
let mut data = Vec::new();
reader.read_to_end(&mut data)?;
Ok(data)
Ok(plain_text)
}
pub fn normalize_setup_code(s: &str) -> String {
@@ -663,40 +617,17 @@ fn import_self_keys(context: &Context, dir: impl AsRef<Path>) -> Result<()> {
continue;
}
}
let ccontent = if let Ok(content) = dc_read_file(context, &path_plus_name) {
key = String::from_utf8_lossy(&content).to_string();
CString::new(content).unwrap_or_default()
} else {
continue;
};
/* only import if we have a private key */
let mut buf2_headerline = String::default();
let split_res: bool;
unsafe {
let buf2 = dc_strdup(ccontent.as_ptr());
split_res = dc_split_armored_data(
buf2,
&mut buf2_headerline,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
);
libc::free(buf2 as *mut libc::c_void);
match dc_read_file(context, &path_plus_name) {
Ok(buf) => {
let armored = std::string::String::from_utf8_lossy(&buf);
if let Err(err) = set_self_key(context, &armored, set_default, false) {
error!(context, "set_self_key: {}", err);
continue;
}
}
Err(_) => continue,
}
if split_res
&& buf2_headerline.contains("-----BEGIN PGP PUBLIC KEY BLOCK-----")
&& !key.contains("-----BEGIN PGP PRIVATE KEY BLOCK")
{
info!(context, "ignoring public key file '{}", name_f);
// it's fine: DC exports public with private
continue;
}
if let Err(err) = set_self_key(context, &key, set_default, false) {
error!(context, "set_self_key: {}", err);
continue;
}
imported_cnt += 1
imported_cnt += 1;
}
ensure!(
imported_cnt > 0,
@@ -784,6 +715,7 @@ mod tests {
use super::*;
use crate::test_utils::*;
use pgp::armor::BlockType;
#[test]
fn test_render_setup_file() {
@@ -866,50 +798,26 @@ mod tests {
let ctx = dummy_context();
let context = &ctx.ctx;
let mut headerline = String::default();
let mut setupcodebegin = ptr::null();
let mut preferencrypt = ptr::null();
let buf_1 = S_EM_SETUPFILE.as_bytes().to_vec();
let (typ, headers, base64) = split_armored_data(&buf_1).unwrap();
assert_eq!(typ, BlockType::Message);
assert!(S_EM_SETUPCODE.starts_with(headers.get(HEADER_SETUPCODE).unwrap()));
assert!(headers.get(HEADER_AUTOCRYPT).is_none());
unsafe {
let buf_1 = S_EM_SETUPFILE.strdup();
let res = dc_split_armored_data(
buf_1,
&mut headerline,
&mut setupcodebegin,
&mut preferencrypt,
ptr::null_mut(),
);
libc::free(buf_1 as *mut libc::c_void);
assert!(res);
}
assert_eq!(headerline, "-----BEGIN PGP MESSAGE-----");
assert!(!setupcodebegin.is_null());
// TODO: verify that this is the right check
assert!(S_EM_SETUPCODE.starts_with(as_str(setupcodebegin)));
assert!(preferencrypt.is_null());
assert!(!base64.is_empty());
let mut setup_file = S_EM_SETUPFILE.to_string();
let decrypted = unsafe {
decrypt_setup_file(context, S_EM_SETUPCODE, setup_file.as_bytes_mut()).unwrap()
};
let decrypted = decrypt_setup_file(
context,
S_EM_SETUPCODE,
std::io::Cursor::new(setup_file.as_bytes()),
)
.unwrap();
unsafe {
let buf1 = decrypted.strdup();
assert!(dc_split_armored_data(
buf1,
&mut headerline,
&mut setupcodebegin,
&mut preferencrypt,
ptr::null_mut(),
));
libc::free(buf1 as *mut libc::c_void);
}
let (typ, headers, base64) = split_armored_data(&buf_1).unwrap();
assert_eq!(headerline, "-----BEGIN PGP PRIVATE KEY BLOCK-----");
assert!(setupcodebegin.is_null());
assert!(!preferencrypt.is_null());
assert_eq!(as_str(preferencrypt), "mutual",);
assert_eq!(typ, BlockType::PrivateKey);
assert_eq!(headers.get(HEADER_AUTOCRYPT), Some(&"mutual".to_string()));
assert!(headers.get(HEADER_SETUPCODE).is_none());
}
}

View File

@@ -1,5 +1,4 @@
use std::path::{Path, PathBuf};
use std::ptr;
use deltachat_derive::{FromSql, ToSql};
@@ -107,6 +106,7 @@ impl Message {
msg.hidden = row.get(18)?;
msg.location_id = row.get(19)?;
msg.chat_blocked = row.get::<_, Option<Blocked>>(20)?.unwrap_or_default();
Ok(msg)
})
}
@@ -339,23 +339,10 @@ impl Message {
}
if let Some(filename) = self.get_file(context) {
if let Ok(mut buf) = dc_read_file(context, filename) {
unsafe {
// just a pointer inside buf, MUST NOT be free()'d
let mut buf_headerline = String::default();
// just a pointer inside buf, MUST NOT be free()'d
let mut buf_setupcodebegin = ptr::null();
if dc_split_armored_data(
buf.as_mut_ptr().cast(),
&mut buf_headerline,
&mut buf_setupcodebegin,
ptr::null_mut(),
ptr::null_mut(),
) && buf_headerline == "-----BEGIN PGP MESSAGE-----"
&& !buf_setupcodebegin.is_null()
{
return Some(to_string_lossy(buf_setupcodebegin));
if let Ok(ref buf) = dc_read_file(context, filename) {
if let Ok((typ, headers, _)) = split_armored_data(buf) {
if typ == pgp::armor::BlockType::Message {
return headers.get(crate::pgp::HEADER_SETUPCODE).cloned();
}
}
}

View File

@@ -1,9 +1,8 @@
use std::collections::HashSet;
use std::collections::{BTreeMap, HashSet};
use std::convert::TryInto;
use std::io::Cursor;
use std::ptr;
use libc::{strchr, strlen, strncmp, strspn, strstr};
use pgp::armor::BlockType;
use pgp::composed::{
Deserializable, KeyType as PgpKeyType, Message, SecretKeyParamsBuilder, SignedPublicKey,
SignedSecretKey, SubkeyParamsBuilder,
@@ -12,122 +11,39 @@ use pgp::crypto::{HashAlgorithm, SymmetricKeyAlgorithm};
use pgp::types::{CompressionAlgorithm, KeyTrait, SecretKeyTrait, StringToKey};
use rand::thread_rng;
use crate::dc_tools::*;
use crate::error::Error;
use crate::key::*;
use crate::keyring::*;
pub unsafe fn dc_split_armored_data(
buf: *mut libc::c_char,
ret_headerline: *mut String,
ret_setupcodebegin: *mut *const libc::c_char,
ret_preferencrypt: *mut *const libc::c_char,
ret_base64: *mut *const libc::c_char,
) -> bool {
let mut success = false;
let mut line_chars: libc::size_t = 0;
let mut line: *mut libc::c_char = buf;
let mut p1: *mut libc::c_char = buf;
let mut p2: *mut libc::c_char;
let mut headerline: *mut libc::c_char = ptr::null_mut();
let mut base64: *mut libc::c_char = ptr::null_mut();
if !ret_setupcodebegin.is_null() {
*ret_setupcodebegin = ptr::null_mut();
}
if !ret_preferencrypt.is_null() {
*ret_preferencrypt = ptr::null();
}
if !ret_base64.is_null() {
*ret_base64 = ptr::null();
}
if !buf.is_null() {
dc_remove_cr_chars(buf);
while 0 != *p1 {
if i32::from(*p1) == '\n' as i32 {
*line.offset(line_chars as isize) = 0i32 as libc::c_char;
if headerline.is_null() {
dc_trim(line);
if strncmp(
line,
b"-----BEGIN \x00" as *const u8 as *const libc::c_char,
1,
) == 0i32
&& strncmp(
&mut *line.offset(strlen(line).wrapping_sub(5) as isize),
b"-----\x00" as *const u8 as *const libc::c_char,
5,
) == 0i32
{
headerline = line;
*ret_headerline = as_str(headerline).to_string();
}
} else if strspn(line, b"\t\r\n \x00" as *const u8 as *const libc::c_char)
== strlen(line)
{
base64 = p1.offset(1isize);
break;
} else {
p2 = strchr(line, ':' as i32);
if p2.is_null() {
*line.add(line_chars) = '\n' as i32 as libc::c_char;
base64 = line;
break;
} else {
*p2 = 0i32 as libc::c_char;
dc_trim(line);
if strcasecmp(
line,
b"Passphrase-Begin\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
p2 = p2.offset(1isize);
dc_trim(p2);
if !ret_setupcodebegin.is_null() {
*ret_setupcodebegin = p2
}
} else if strcasecmp(
line,
b"Autocrypt-Prefer-Encrypt\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
p2 = p2.offset(1isize);
dc_trim(p2);
if !ret_preferencrypt.is_null() {
*ret_preferencrypt = p2
}
}
}
}
p1 = p1.offset(1isize);
line = p1;
line_chars = 0;
} else {
p1 = p1.offset(1isize);
line_chars = line_chars.wrapping_add(1)
}
}
if !(headerline.is_null() || base64.is_null()) {
/* now, line points to beginning of base64 data, search end */
/*the trailing space makes sure, this is not a normal base64 sequence*/
p1 = strstr(base64, b"-----END \x00" as *const u8 as *const libc::c_char);
if !(p1.is_null()
|| strncmp(
p1.offset(9isize),
headerline.offset(11isize),
strlen(headerline.offset(11isize)),
) != 0i32)
{
*p1 = 0i32 as libc::c_char;
dc_trim(base64);
if !ret_base64.is_null() {
*ret_base64 = base64
}
success = true;
}
}
}
pub const HEADER_AUTOCRYPT: &str = "autocrypt-prefer-encrypt";
pub const HEADER_SETUPCODE: &str = "passphrase-begin";
success
/// Split data from PGP Armored Data as defined in https://tools.ietf.org/html/rfc4880#section-6.2.
///
/// Returns (type, headers, base64 encoded body).
pub fn split_armored_data(
buf: &[u8],
) -> Result<(BlockType, BTreeMap<String, String>, Vec<u8>), Error> {
use std::io::Read;
let cursor = Cursor::new(buf);
let mut dearmor = pgp::armor::Dearmor::new(cursor);
let mut bytes = Vec::with_capacity(buf.len());
dearmor.read_to_end(&mut bytes)?;
ensure!(dearmor.typ.is_some(), "Failed to parse type");
let typ = dearmor.typ.unwrap();
// normalize headers
let headers = dearmor
.headers
.into_iter()
.map(|(key, value)| (key.to_lowercase(), value))
.collect();
Ok((typ, headers, bytes))
}
/// Create a new key pair.
@@ -281,8 +197,11 @@ pub fn dc_pgp_symm_encrypt(passphrase: &str, plain: &[u8]) -> Result<String, Err
}
/// Symmetric decryption.
pub fn dc_pgp_symm_decrypt(passphrase: &str, ctext: &[u8]) -> Result<Vec<u8>, Error> {
let enc_msg = Message::from_bytes(Cursor::new(ctext))?;
pub fn dc_pgp_symm_decrypt<T: std::io::Read + std::io::Seek>(
passphrase: &str,
ctext: T,
) -> Result<Vec<u8>, Error> {
let (enc_msg, _) = Message::from_armor_single(ctext)?;
let decryptor = enc_msg.decrypt_with_password(|| passphrase.into())?;
let msgs = decryptor.collect::<Result<Vec<_>, _>>()?;
@@ -293,3 +212,59 @@ pub fn dc_pgp_symm_decrypt(passphrase: &str, ctext: &[u8]) -> Result<Vec<u8>, Er
None => bail!("Decrypted message is empty"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_split_armored_data() {
let (typ, _headers, base64) = split_armored_data(
b"-----BEGIN PGP MESSAGE-----\nNoVal:\n\naGVsbG8gd29ybGQ=\n-----END PGP MESSAGE----",
)
.unwrap();
assert_eq!(typ, BlockType::Message);
assert!(!base64.is_empty());
assert_eq!(
std::string::String::from_utf8(base64).unwrap(),
"hello world"
);
let (typ, _headers, base64) =
split_armored_data(b"-----BEGIN PGP MESSAGE-----\n\ndat1\n-----END PGP MESSAGE-----\n-----BEGIN PGP MESSAGE-----\n\ndat2\n-----END PGP MESSAGE-----")
.unwrap();
assert_eq!(typ, BlockType::Message);
assert!(!base64.is_empty());
let (typ, _headers, base64) = split_armored_data(
b"foo \n -----BEGIN PGP MESSAGE----- \n base64-123 \n -----END PGP MESSAGE-----",
)
.unwrap();
assert_eq!(typ, BlockType::Message);
assert!(!base64.is_empty());
assert!(split_armored_data(b"foo-----BEGIN PGP MESSAGE-----",).is_err());
let (typ, headers, base64) = split_armored_data(
b"foo \n -----BEGIN PGP MESSAGE-----\n Passphrase-BeGIN : 23 \n \n base64-567 \r\n abc \n -----END PGP MESSAGE-----\n\n\n",
)
.unwrap();
assert_eq!(typ, BlockType::Message);
assert!(!base64.is_empty());
assert_eq!(headers.get(HEADER_SETUPCODE), Some(&"23".to_string()));
let (typ, headers, base64) = split_armored_data(
b"-----BEGIN PGP PRIVATE KEY BLOCK-----\n Autocrypt-Prefer-Encrypt : mutual \n\nbase64\n-----END PGP PRIVATE KEY BLOCK-----"
)
.unwrap();
assert_eq!(typ, BlockType::PrivateKey);
assert!(!base64.is_empty());
assert_eq!(headers.get(HEADER_AUTOCRYPT), Some(&"mutual".to_string()));
}
}

View File

@@ -1,18 +1,15 @@
//! Stress some functions for testing; if used as a lib, this file is obsolete.
use std::collections::HashSet;
use std::ptr;
use deltachat::chat::{self, Chat};
use deltachat::config;
use deltachat::contact::*;
use deltachat::context::*;
use deltachat::dc_tools::*;
use deltachat::keyring::*;
use deltachat::oauth2::*;
use deltachat::pgp::*;
use deltachat::Event;
use libc::{free, strcmp, strdup};
use tempfile::{tempdir, TempDir};
/* some data used for testing
@@ -50,135 +47,6 @@ unsafe fn stress_functions(context: &Context) {
assert!(res.contains(" configured_send_port "));
assert!(res.contains(" configured_server_flags "));
let mut buf_0: *mut libc::c_char;
let mut headerline = String::default();
let mut setupcodebegin: *const libc::c_char = ptr::null();
let mut preferencrypt: *const libc::c_char = ptr::null();
let mut base64: *const libc::c_char = ptr::null();
buf_0 = strdup(
b"-----BEGIN PGP MESSAGE-----\nNoVal:\n\ndata\n-----END PGP MESSAGE-----\x00" as *const u8
as *const libc::c_char,
);
let ok = dc_split_armored_data(
buf_0,
&mut headerline,
&mut setupcodebegin,
ptr::null_mut(),
&mut base64,
);
assert!(ok);
assert!(!headerline.is_empty());
assert_eq!(headerline, "-----BEGIN PGP MESSAGE-----");
assert!(!base64.is_null());
assert_eq!(as_str(base64 as *const libc::c_char), "data",);
free(buf_0 as *mut libc::c_void);
buf_0 =
strdup(b"-----BEGIN PGP MESSAGE-----\n\ndat1\n-----END PGP MESSAGE-----\n-----BEGIN PGP MESSAGE-----\n\ndat2\n-----END PGP MESSAGE-----\x00"
as *const u8 as *const libc::c_char);
let ok = dc_split_armored_data(
buf_0,
&mut headerline,
&mut setupcodebegin,
ptr::null_mut(),
&mut base64,
);
assert!(ok);
assert_eq!(headerline, "-----BEGIN PGP MESSAGE-----");
assert!(!base64.is_null());
assert_eq!(as_str(base64 as *const libc::c_char), "dat1",);
free(buf_0 as *mut libc::c_void);
buf_0 = strdup(
b"foo \n -----BEGIN PGP MESSAGE----- \n base64-123 \n -----END PGP MESSAGE-----\x00"
as *const u8 as *const libc::c_char,
);
let ok = dc_split_armored_data(
buf_0,
&mut headerline,
&mut setupcodebegin,
ptr::null_mut(),
&mut base64,
);
assert!(ok);
assert_eq!(headerline, "-----BEGIN PGP MESSAGE-----");
assert!(setupcodebegin.is_null());
assert!(!base64.is_null());
assert_eq!(as_str(base64 as *const libc::c_char), "base64-123",);
free(buf_0 as *mut libc::c_void);
buf_0 = strdup(b"foo-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char);
let ok = dc_split_armored_data(
buf_0,
&mut headerline,
&mut setupcodebegin,
ptr::null_mut(),
&mut base64,
);
assert!(!ok);
free(buf_0 as *mut libc::c_void);
buf_0 =
strdup(b"foo \n -----BEGIN PGP MESSAGE-----\n Passphrase-BeGIN : 23 \n \n base64-567 \r\n abc \n -----END PGP MESSAGE-----\n\n\n\x00"
as *const u8 as *const libc::c_char);
let ok = dc_split_armored_data(
buf_0,
&mut headerline,
&mut setupcodebegin,
ptr::null_mut(),
&mut base64,
);
assert!(ok);
assert_eq!(headerline, "-----BEGIN PGP MESSAGE-----");
assert!(!setupcodebegin.is_null());
assert_eq!(
strcmp(
setupcodebegin,
b"23\x00" as *const u8 as *const libc::c_char,
),
0
);
assert!(!base64.is_null());
assert_eq!(as_str(base64 as *const libc::c_char), "base64-567 \n abc",);
free(buf_0 as *mut libc::c_void);
buf_0 =
strdup(b"-----BEGIN PGP PRIVATE KEY BLOCK-----\n Autocrypt-Prefer-Encrypt : mutual \n\nbase64\n-----END PGP PRIVATE KEY BLOCK-----\x00"
as *const u8 as *const libc::c_char);
let ok = dc_split_armored_data(
buf_0,
&mut headerline,
ptr::null_mut(),
&mut preferencrypt,
&mut base64,
);
assert!(ok);
assert_eq!(headerline, "-----BEGIN PGP PRIVATE KEY BLOCK-----");
assert!(!preferencrypt.is_null());
assert_eq!(
strcmp(
preferencrypt,
b"mutual\x00" as *const u8 as *const libc::c_char,
),
0
);
assert!(!base64.is_null());
assert_eq!(as_str(base64 as *const libc::c_char), "base64",);
free(buf_0 as *mut libc::c_void);
// Cant check, no configured context
// assert!(dc_is_configured(context) != 0, "Missing configured context");