mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
refactor: reorg code and drop usage of libetpans base64 encoder
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
206
src/dc_key.rs
206
src/dc_key.rs
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user