refactor: reorg code and drop usage of libetpans base64 encoder

This commit is contained in:
dignifiedquire
2019-04-29 14:54:55 +03:00
parent 83917ef93e
commit e43ddf0359
5 changed files with 95 additions and 173 deletions

View File

@@ -26,6 +26,7 @@ lettre = "0.9.0"
imap = "1.0.1"
# rental = "0.5.3"
mmime = { path = "../mmime" }
base64 = "0.10.1"
[dev-dependencies]
tempfile = "3.0.7"

View File

@@ -261,12 +261,8 @@ pub unsafe fn dc_aheader_render(mut aheader: *const dc_aheader_t) -> *mut libc::
// TODO replace 78 with enum /rtn
/* adds a whitespace every 78 characters, this allows libEtPan to wrap the lines according to RFC 5322
(which may insert a linebreak before every whitespace) */
keybase64_wrapped = dc_key_render_base64(
(*aheader).public_key,
78,
b" \x00" as *const u8 as *const libc::c_char,
0,
);
keybase64_wrapped = dc_key_render_base64((*aheader).public_key, 78);
if !keybase64_wrapped.is_null() {
/*no checksum*/
dc_strbuilder_cat(&mut ret, keybase64_wrapped);

View File

@@ -315,9 +315,9 @@ pub unsafe extern "C" fn dc_render_setup_file(
let mut payload_key_asc: *mut libc::c_char = dc_key_render_asc(
curr_private_key,
if 0 != e2ee_enabled {
b"Autocrypt-Prefer-Encrypt: mutual\r\n\x00" as *const u8 as *const libc::c_char
Some(("Autocrypt-Prefer-Encrypt", "mutual"))
} else {
0 as *const libc::c_char
None
},
);
if !payload_key_asc.is_null() {

View File

@@ -1,3 +1,12 @@
use std::collections::BTreeMap;
use std::ffi::CString;
use std::io::Cursor;
use std::slice;
use libc;
use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey};
use pgp::ser::Serialize;
use crate::dc_context::dc_context_t;
use crate::dc_log::*;
use crate::dc_pgp::*;
@@ -6,9 +15,7 @@ use crate::dc_strbuilder::*;
use crate::dc_tools::*;
use crate::types::*;
use crate::x::*;
/* *
* Library-internal.
*/
#[derive(Copy, Clone)]
#[repr(C)]
pub struct dc_key_t {
@@ -287,141 +294,78 @@ pub unsafe fn dc_key_load_self_private(
}
/* the result must be freed */
pub unsafe fn dc_render_base64(
mut buf: *const libc::c_void,
mut buf_bytes: size_t,
mut break_every: libc::c_int,
mut break_chars: *const libc::c_char,
mut add_checksum: libc::c_int,
) -> *mut libc::c_char {
let mut ret: *mut libc::c_char = 0 as *mut libc::c_char;
if !(buf == 0 as *mut libc::c_void || buf_bytes <= 0) {
ret = encode_base64(buf as *const libc::c_char, buf_bytes as libc::c_int);
if !ret.is_null() {
if break_every > 0i32 {
let mut temp: *mut libc::c_char = ret;
ret = dc_insert_breaks(temp, break_every, break_chars);
free(temp as *mut libc::c_void);
}
if add_checksum == 2i32 {
let mut checksum: libc::c_long = crc_octets(buf as *const libc::c_uchar, buf_bytes);
let mut c: [uint8_t; 3] = [0; 3];
c[0usize] = (checksum >> 16i32 & 0xffi32 as libc::c_long) as uint8_t;
c[1usize] = (checksum >> 8i32 & 0xffi32 as libc::c_long) as uint8_t;
c[2usize] = (checksum & 0xffi32 as libc::c_long) as uint8_t;
let mut c64: *mut libc::c_char =
encode_base64(c.as_mut_ptr() as *const libc::c_char, 3i32);
let mut temp_0: *mut libc::c_char = ret;
ret = dc_mprintf(
b"%s%s=%s\x00" as *const u8 as *const libc::c_char,
temp_0,
break_chars,
c64,
);
free(temp_0 as *mut libc::c_void);
free(c64 as *mut libc::c_void);
}
}
}
ret
}
/*******************************************************************************
* Render keys
******************************************************************************/
unsafe fn crc_octets(mut octets: *const libc::c_uchar, mut len: size_t) -> libc::c_long {
let mut crc: libc::c_long = 0xb704ce;
loop {
let fresh0 = len;
len = len.wrapping_sub(1);
if !(0 != fresh0) {
break;
}
let fresh1 = octets;
octets = octets.offset(1);
crc ^= ((*fresh1 as libc::c_int) << 16i32) as libc::c_long;
let mut i: libc::c_int = 0i32;
while i < 8i32 {
crc <<= 1i32;
if 0 != crc & 0x1000000 as libc::c_long {
crc ^= 0x1864cfb
}
i += 1
}
}
crc & 0xffffff
}
/* the result must be freed */
pub unsafe fn dc_key_render_base64(
mut key: *const dc_key_t,
mut break_every: libc::c_int,
mut break_chars: *const libc::c_char,
mut add_checksum: libc::c_int,
) -> *mut libc::c_char {
pub fn dc_key_render_base64(key: *const dc_key_t, break_every: usize) -> *mut libc::c_char {
if key.is_null() {
return 0 as *mut libc::c_char;
return std::ptr::null_mut();
}
dc_render_base64(
(*key).binary,
(*key).bytes as size_t,
break_every,
break_chars,
add_checksum,
)
let key = unsafe { *key };
let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) };
assert_eq!(bytes.len(), key.bytes as usize);
let buf = if key.type_0 == 0 {
// public key
let skey = SignedPublicKey::from_bytes(Cursor::new(bytes)).expect("invalid pub key");
skey.to_bytes().expect("failed to serialize key")
} else {
// secret key
let skey = SignedSecretKey::from_bytes(Cursor::new(bytes)).expect("invalid sec key");
skey.to_bytes().expect("failed to serialize key")
};
let encoded = base64::encode(&buf);
let res = encoded
.as_bytes()
.chunks(break_every)
.fold(String::new(), |mut res, buf| {
// safe because we are using a base64 encoded string
res += unsafe { std::str::from_utf8_unchecked(buf) };
res += " ";
res
});
let res_c = CString::new(res.trim()).unwrap();
// need to use strdup to allocate the result with malloc
// so it can be `free`d later.
unsafe { libc::strdup(res_c.as_ptr()) }
}
/* each header line must be terminated by \r\n, the result must be freed */
pub unsafe fn dc_key_render_asc(
mut key: *const dc_key_t,
mut add_header_lines: *const libc::c_char,
) -> *mut libc::c_char {
/* see RFC 4880, 6.2. Forming ASCII Armor, https://tools.ietf.org/html/rfc4880#section-6.2 */
let mut base64: *mut libc::c_char = 0 as *mut libc::c_char;
let mut ret: *mut libc::c_char = 0 as *mut libc::c_char;
if !key.is_null() {
base64 = dc_key_render_base64(
key,
76i32,
b"\r\n\x00" as *const u8 as *const libc::c_char,
2i32,
);
if !base64.is_null() {
/*checksum in new line*/
/* RFC: The encoded output stream must be represented in lines of no more than 76 characters each. */
ret =
dc_mprintf(b"-----BEGIN PGP %s KEY BLOCK-----\r\n%s\r\n%s\r\n-----END PGP %s KEY BLOCK-----\r\n\x00"
as *const u8 as *const libc::c_char,
if (*key).type_0 == 0i32 {
b"PUBLIC\x00" as *const u8 as
*const libc::c_char
} else {
b"PRIVATE\x00" as *const u8 as
*const libc::c_char
},
if !add_header_lines.is_null() {
add_header_lines
} else {
b"\x00" as *const u8 as *const libc::c_char
}, base64,
if (*key).type_0 == 0i32 {
b"PUBLIC\x00" as *const u8 as
*const libc::c_char
} else {
b"PRIVATE\x00" as *const u8 as
*const libc::c_char
})
}
/// each header line must be terminated by `\r\n`, the result must be freed.
pub fn dc_key_render_asc(key: *const dc_key_t, header: Option<(&str, &str)>) -> *mut libc::c_char {
if key.is_null() {
return std::ptr::null_mut();
}
free(base64 as *mut libc::c_void);
ret
let key = unsafe { *key };
let headers = header.map(|(key, value)| {
let mut m = BTreeMap::new();
m.insert(key.to_string(), value.to_string());
m
});
let bytes = unsafe { slice::from_raw_parts(key.binary as *const u8, key.bytes as usize) };
let buf = if key.type_0 == 0 {
// public key
let skey = SignedPublicKey::from_bytes(Cursor::new(bytes)).expect("invalid key");
skey.to_armored_string(headers.as_ref())
.expect("failed to serialize key")
} else {
// secret key
let skey = SignedSecretKey::from_bytes(Cursor::new(bytes)).expect("invalid key");
skey.to_armored_string(headers.as_ref())
.expect("failed to serialize key")
};
let buf_c = CString::new(buf).unwrap();
// need to use strdup to allocate the result with malloc
// so it can be `free`d later.
unsafe { libc::strdup(buf_c.as_ptr()) }
}
// TODO should return bool /rtn
pub unsafe fn dc_key_render_asc_to_file(
mut key: *const dc_key_t,
mut file: *const libc::c_char,
@@ -429,8 +373,10 @@ pub unsafe fn dc_key_render_asc_to_file(
) -> libc::c_int {
let mut success: libc::c_int = 0i32;
let mut file_content: *mut libc::c_char = 0 as *mut libc::c_char;
if !(key.is_null() || file.is_null()) {
file_content = dc_key_render_asc(key, 0 as *const libc::c_char);
file_content = dc_key_render_asc(key, None);
if !file_content.is_null() {
if 0 == dc_write_file(
context,

View File

@@ -3173,11 +3173,8 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) {
let ah: *mut dc_aheader_t = dc_aheader_new();
let rendered: *mut libc::c_char;
let mut ah_ok: libc::c_int;
ah_ok = dc_aheader_set_from_string(
ah,
b"addr=a@b.example.org; prefer-encrypt=mutual; keydata=RGVsdGEgQ2hhdA==\x00" as *const u8
as *const libc::c_char,
);
let fixed_header = b"addr=a@b.example.org; prefer-encrypt=mutual; keydata= xsBNBFzG3j0BCAC6iNhT8zydvCXi8LI/gFnkadMbfmSE/rTJskRRra/utGbLyDta/yTrJgWL7O3y/g 4HdDW/dN2z26Y6W13IMzx9gLInn1KQZChtqWAcr/ReUucXcymwcfg1mdkBGk3TSLeLihN6CJx8Wsv8 ig+kgAzte4f5rqEEAJVQ9WZHuti7UiYs6oRzqTo06CRe9owVXxzdMf0VDQtf7ZFm9dpzKKbhH7Lu88 80iiotQ9/yRCkDGp9fNThsrLdZiK6OIAcIBAqi2rI89aS1dAmnRbktQieCx5izzyYkR1KvVL3gTTll HOzfKVEC2asmtWu2e4se/+O4WMIS1eGrn7GeWVb0Vwc5ABEBAAHNETxhQEBiLmV4YW1wbGUuZGU+ws CJBBABCAAzAhkBBQJcxt5FAhsDBAsJCAcGFQgJCgsCAxYCARYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiML938H/18F+3Wf9/JaAy/8hCO1v4S2PVBhxaKCokaNFtkfaMRne2l087LscCFPiF Nyb4mv6Z3YeK8Xpxlp2sI0ecvdiqLUOGfnxS6tQrj+83EjtIrZ/hXOk1h121QFWH9Zg2VNHtODXjAg dLDC0NWUrclR0ZOqEDQHeo0ibTILdokVfXFN25wakPmGaYJP2y729cb1ve7RzvIvwn+Dddfxo3ao72 rBfLi7l4NQ4S0KsY4cw+/6l5bRCKYCP77wZtvCwUvfVVosLdT43agtSiBI49+ayqvZ8OCvSJa61i+v 81brTiEy9GBod4eAp45Ibsuemkw+gon4ZOvUXHTjwFB+h63MrozOwE0EXMbePQEIAL/vauf1zK8JgC u3V+G+SOX0iWw5xUlCPX+ERpBbWfwu3uAqn4wYXD3JDE/fVAF668xiV4eTPtlSUd5h0mn+G7uXMMOt kb+20SoEt50f8zw8TrL9t+ZsV11GKZWJpCar5AhXWsn6EEi8I2hLL5vn55ZZmHuGgN4jjmkRl3ToKC LhaXwTBjCJem7N5EH7F75wErEITa55v4Lb4Nfca7vnvtYrI1OA446xa8gHra0SINelTD09/JM/Fw4s WVPBaRZmJK/Tnu79N23No9XBUubmFPv1pNexZsQclicnTpt/BEWhiun7d6lfGB63K1aoHRTR1pcrWv BuALuuz0gqar2zlI0AEQEAAcLAdgQYAQgAIAUCXMbeRQIbDBYhBI4xxYKBgH3ANh5cufaKrc9mtiML AAoJEPaKrc9mtiMLKSEIAIyLCRO2OyZ0IYRvRPpMn4p7E+7Pfcz/0mSkOy+1hshgJnqivXurm8zwGr wdMqeV4eslKR9H1RUdWGUQJNbtwmmjrt5DHpIhYHl5t3FpCBaGbV20Omo00Q38lBl9MtrmZkZw+ktE k6X+0xCKssMF+2MADkSOIufbR5HrDVB89VZOHCO9DeXvCUUAw2hyJiL/LHmLzJ40zYoTmb+F//f0k0 j+tRdbkefyRoCmwG7YGiT+2hnCdgcezswnzah5J3ZKlrg7jOGo1LxtbvNUzxNBbC6S/aNgwm6qxo7x egRhmEl5uZ16zwyj4qz+xkjGy25Of5mWfUDoNw7OT7sjUbHOOMc=";
ah_ok = dc_aheader_set_from_string(ah, fixed_header as *const u8 as *const libc::c_char);
if 0 != !(ah_ok == 1i32) as libc::c_int as libc::c_long {
__assert_rtn(
(*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00"))
@@ -3204,21 +3201,9 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) {
);
} else {
};
if 0 != !((*(*ah).public_key).bytes == 10i32
&& strncmp(
(*(*ah).public_key).binary as *mut libc::c_char,
b"Delta Chat\x00" as *const u8 as *const libc::c_char,
10,
) == 0i32) as libc::c_int as libc::c_long
{
__assert_rtn((*::std::mem::transmute::<&[u8; 17],
&[libc::c_char; 17]>(b"stress_functions\x00")).as_ptr(),
b"../cmdline/stress.c\x00" as *const u8 as
*const libc::c_char, 771i32,
b"ah->public_key->bytes==10 && strncmp((char*)ah->public_key->binary, \"Delta Chat\", 10)==0\x00"
as *const u8 as *const libc::c_char);
} else {
};
assert_eq!((*(*ah).public_key).bytes, 1212);
if 0 != !((*ah).prefer_encrypt == 1i32) as libc::c_int as libc::c_long {
__assert_rtn(
(*::std::mem::transmute::<&[u8; 17], &[libc::c_char; 17]>(b"stress_functions\x00"))
@@ -3229,22 +3214,15 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) {
);
} else {
};
rendered = dc_aheader_render(ah);
if 0 != !(!rendered.is_null()
&& strcmp(
rendered,
b"addr=a@b.example.org; prefer-encrypt=mutual; keydata= RGVsdGEgQ2hhdA==\x00"
as *const u8 as *const libc::c_char,
) == 0i32) as libc::c_int as libc::c_long
{
__assert_rtn((*::std::mem::transmute::<&[u8; 17],
&[libc::c_char; 17]>(b"stress_functions\x00")).as_ptr(),
b"../cmdline/stress.c\x00" as *const u8 as
*const libc::c_char, 775i32,
b"rendered && strcmp(rendered, \"addr=a@b.example.org; prefer-encrypt=mutual; keydata= RGVsdGEgQ2hhdA==\")==0\x00"
as *const u8 as *const libc::c_char);
} else {
};
assert!(!rendered.is_null());
assert_eq!(
std::ffi::CStr::from_ptr(rendered).to_str().unwrap(),
std::str::from_utf8(fixed_header).unwrap()
);
ah_ok =
dc_aheader_set_from_string(ah,
b" _foo; __FOO=BAR ;;; addr = a@b.example.org ;\r\n prefer-encrypt = mutual ; keydata = RG VsdGEgQ\r\n2hhdA==\x00"
@@ -3275,6 +3253,7 @@ unsafe extern "C" fn stress_functions(context: &dc_context_t) {
);
} else {
};
if 0 != !((*(*ah).public_key).bytes == 10i32
&& strncmp(
(*(*ah).public_key).binary as *mut libc::c_char,