tests passing. static linking failing, not sure why

ffi
Avril 3 years ago
parent 65ad649519
commit e76499c166
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -24,8 +24,8 @@ fn build_cookie_wrapper(floc: impl AsRef<Path>)
.flag_if_supported("-flto") .flag_if_supported("-flto")
// Not sure if we want these two. We can check the codegen later. // Not sure if we want these two. We can check the codegen later.
.pic(false) //.pic(false)
.use_plt(false) //.use_plt(false)
.file(Path::new(FFI_SRC_DIR).join(floc)) .file(Path::new(FFI_SRC_DIR).join(floc))
.compile("cwrapper"); .compile("cwrapper");
@ -52,4 +52,6 @@ fn main() {
} }
build_cookie_wrapper("wrapper.c"); build_cookie_wrapper("wrapper.c");
//println!("cargo:rustc-link-lib={}", link);
} }

@ -36,6 +36,9 @@ typedef struct cc20_metadata {
typedef struct cc20_sink cc20_sink_t; typedef struct cc20_sink cc20_sink_t;
// Functions //
#define _cc20_OUT *restrict
cc20_result_t cc20_keygen(cc20_key_t* restrict key, cc20_result_t cc20_keygen(cc20_key_t* restrict key,
cc20_iv_t* restrict iv); cc20_iv_t* restrict iv);
@ -43,27 +46,31 @@ cc20_result_t cc20_gen_meta(FILE* file,
const cc20_key_t* key, const cc20_key_t* key,
const cc20_iv_t* iv, const cc20_iv_t* iv,
enum cc20_mode mode, enum cc20_mode mode,
struct cc20_metadata* restrict output); struct cc20_metadata _cc20_OUT output);
cc20_result_t cc20_gen_sink(const struct cc20_metadata* meta, cc20_sink_t* _cc20_OUT output);
cc20_sink_t* cc20_gen_sink(const struct cc20_metadata* meta);
cc20_sink_t* cc20_gen_sink_full(FILE* file, cc20_result_t cc20_gen_sink_full(FILE* file,
const cc20_key_t* key, const cc20_key_t* key,
const cc20_iv_t* iv, const cc20_iv_t* iv,
enum cc20_mode mode); enum cc20_mode mode,
cc20_sink_t* _cc20_OUT output);
FILE* cc20_wrap_full(FILE* file, cc20_result_t cc20_wrap_full(FILE* file,
const cc20_key_t* key, const cc20_key_t* key,
const cc20_iv_t* iv, const cc20_iv_t* iv,
enum cc20_mode mode); enum cc20_mode mode,
FILE* _cc20_OUT output);
FILE* cc20_gen(const struct cc20_metadata* meta); cc20_result_t cc20_gen(const struct cc20_metadata* meta,
FILE* _cc20_OUT output);
cc20_result_t cc20_close_sink(cc20_sink_t* sink, cc20_result_t cc20_close_sink(cc20_sink_t* sink,
struct cc20_metadata* restrict meta); struct cc20_metadata* restrict meta);
FILE* cc20_wrap_sink(cc20_sink_t* sink); FILE* cc20_wrap_sink(cc20_sink_t* sink);
size_t cc20_write(const void* ptr, size_t size, size_t nmemb, cc20_sink_t* restrict sink); cc20_result_t cc20_write(const void* ptr, size_t * restrict bytes, cc20_sink_t* restrict sink);
#endif /* _CC20_H */ #endif /* _CC20_H */

@ -61,25 +61,24 @@ pub use error::*;
}).unwrap_or(CErr::Panic) }).unwrap_or(CErr::Panic)
} }
#[no_mangle] pub unsafe extern "C" fn cc20_write(ptr: *const c_void, size: usize, nmemb: usize, sink: *mut CSink) -> usize #[no_mangle] pub unsafe extern "C" fn cc20_write(ptr: *const c_void, bytes: *mut usize, sink: *mut CSink) -> CErr
{ {
let mut output: usize = 0; no_unwind!({
let _er = no_unwind!(ref {
let sink = nullchk!(ref mut sink); let sink = nullchk!(ref mut sink);
let bytes = size * nmemb; let nbytes = nullchk!(move bytes);
let slice = if ptr.is_null() { let slice = if ptr.is_null() {
return CErr::NullPointer; return CErr::NullPointer;
} else { } else {
std::slice::from_raw_parts(ptr as *const u8, bytes) std::slice::from_raw_parts(ptr as *const u8, nbytes)
}; };
match sink.sink.write(&slice[..]) { match sink.sink.write(&slice[..]) {
Err(_) => return CErr::IO, Err(_) => return CErr::IO,
Ok(v) => output = v, Ok(v) => *bytes = v,
} }
CErr::Success CErr::Success
}).unwrap_or(CErr::Panic); })
//TODO: Write `er` into an error flag for `sink` (parallel to `ferror`/`feof`). .unwrap_or(CErr::Panic)
output
} }
#[no_mangle] pub unsafe extern "C" fn cc20_gen_meta(file: *mut libc::FILE, key: *const Key, iv: *const IV, mode: CMode, output: *mut CPassthrough) -> CErr #[no_mangle] pub unsafe extern "C" fn cc20_gen_meta(file: *mut libc::FILE, key: *const Key, iv: *const IV, mode: CMode, output: *mut CPassthrough) -> CErr
@ -111,10 +110,11 @@ pub use error::*;
} }
/// Create an encrypting `Sink` over a `FILE*` from this metadata struct. /// Create an encrypting `Sink` over a `FILE*` from this metadata struct.
#[no_mangle] pub unsafe extern "C" fn cc20_gen_sink(meta: *const CPassthrough) -> *mut CSink #[no_mangle] pub unsafe extern "C" fn cc20_gen_sink(meta: *const CPassthrough, output: *mut *mut CSink) -> CErr
{ {
no_unwind!({ no_unwind!({
let meta = nullchk!(ref meta); let meta = nullchk!(ref meta);
let output = nullchk!(ref mut output);
let sink = CSink { let sink = CSink {
sink: match meta.mode { sink: match meta.mode {
@ -122,42 +122,41 @@ pub use error::*;
CMode::Decrypt => Sink::decrypt(meta.clone(), meta.key, meta.iv).map_err(|_| CErr::SslError).unwrap(), CMode::Decrypt => Sink::decrypt(meta.clone(), meta.key, meta.iv).map_err(|_| CErr::SslError).unwrap(),
}, },
}; };
*output = interop::give(sink);
interop::give(sink) CErr::Success
}).unwrap_or(ptr::null_mut()) }).unwrap_or(CErr::Panic)
} }
/// Create an encrypting `Sink` over a `FILE*` with these options. /// Create an encrypting `Sink` over a `FILE*` with these options.
#[no_mangle] pub unsafe extern "C" fn cc20_gen_sink_full(file: *mut libc::FILE, key: *const Key, iv: *const IV, mode: CMode) -> *mut CSink #[no_mangle] pub unsafe extern "C" fn cc20_gen_sink_full(file: *mut libc::FILE, key: *const Key, iv: *const IV, mode: CMode, output: *mut *mut CSink) -> CErr
{ {
let meta = { let meta = {
// No need to `no_unwind` this, `cc20_gen_meta` already does it, and nothing else here can panic. // No need to `no_unwind` this, `cc20_gen_meta` already does it, and nothing else here can panic.
let mut meta: std::mem::MaybeUninit<CPassthrough> = std::mem::MaybeUninit::uninit(); let mut meta: std::mem::MaybeUninit<CPassthrough> = std::mem::MaybeUninit::uninit();
match cc20_gen_meta(file, key, iv, mode, &mut meta as *mut _ as *mut CPassthrough).into() { match cc20_gen_meta(file, key, iv, mode, &mut meta as *mut _ as *mut CPassthrough) {
0i32 => meta.assume_init(), CErr::Success => meta.assume_init(),
_ => return ptr::null_mut(), x => return x,
} }
}; };
cc20_gen_sink(&meta as *const _) cc20_gen_sink(&meta as *const _, output)
} }
#[no_mangle] pub unsafe extern "C" fn cc20_gen(meta: *const CPassthrough) -> *mut libc::FILE #[no_mangle] pub unsafe extern "C" fn cc20_gen(meta: *const CPassthrough, output: *mut *mut libc::FILE) -> CErr
{ {
let sink = cc20_gen_sink(meta); let mut sink: *mut CSink = ptr::null_mut();
if sink.is_null() { errchk!(cc20_gen_sink(meta, &mut sink as *mut *mut CSink));
return ptr::null_mut(); *output = cc20_wrap_sink(sink);
} CErr::Success
cc20_wrap_sink(sink)
} }
/// Create a wrapper `FILE*` that acts as a `Sink` when written to. /// Create a wrapper `FILE*` that acts as a `Sink` when written to.
#[no_mangle] pub unsafe extern "C" fn cc20_wrap_full(file: *mut libc::FILE, key: *const Key, iv: *const IV, mode: CMode) -> *mut libc::FILE #[no_mangle] pub unsafe extern "C" fn cc20_wrap_full(file: *mut libc::FILE, key: *const Key, iv: *const IV, mode: CMode, output: &mut *mut libc::FILE) -> CErr
{ {
// No need to `no_unwind` this, nothing here can panic. // No need to `no_unwind` this, nothing here can panic.
let csink = cc20_gen_sink_full(file, key, iv, mode); let mut csink: *mut CSink = ptr::null_mut();
if csink.is_null() { errchk!(cc20_gen_sink_full(file, key, iv, mode, &mut csink as *mut *mut CSink));
return ptr::null_mut(); *output = cc20_wrap_sink(csink);
} CErr::Success
cc20_wrap_sink(csink)
} }
/// Closes and frees the wrapper `sink`, and writes inner metadata struct to `meta`, if `file` is non-null. /// Closes and frees the wrapper `sink`, and writes inner metadata struct to `meta`, if `file` is non-null.
#[no_mangle] pub unsafe extern "C" fn cc20_close_sink(sink: *mut CSink, meta: *mut CPassthrough) -> CErr #[no_mangle] pub unsafe extern "C" fn cc20_close_sink(sink: *mut CSink, meta: *mut CPassthrough) -> CErr
@ -174,7 +173,9 @@ pub use error::*;
/// Convert a `Sink` into a `FILE*`. /// Convert a `Sink` into a `FILE*`.
#[no_mangle] pub unsafe extern "C" fn cc20_wrap_sink(sink: *mut CSink) -> *mut libc::FILE #[no_mangle] pub unsafe extern "C" fn cc20_wrap_sink(sink: *mut CSink) -> *mut libc::FILE
{ {
//todo!("Create a Custom Stream in `wrapper.c` that allows creating a FILE* object from `sink`.") if sink.is_null() {
return ptr::null_mut();
}
cookie::create(sink) cookie::create(sink)
} }

@ -2,6 +2,15 @@
use super::*; use super::*;
#[macro_export] macro_rules! errchk {
($expr:expr) => {
match CErr::from($expr) {
CErr::Success => (),
x => return x,
}
};
}
//TODO: Rework the error handling/reporting here. //TODO: Rework the error handling/reporting here.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Copy)]
#[repr(C)] #[repr(C)]

@ -18,8 +18,9 @@ static ssize_t cc20c_read(void* cookie, char* buffer, size_t size)
static ssize_t cc20c_write(void* cookie, const char* buffer, size_t size) static ssize_t cc20c_write(void* cookie, const char* buffer, size_t size)
{ {
register int c = cc20_write(buffer, 1, size, cookie); cc20_result_t res = cc20_write(buffer, &size, cookie);
return c < 0 ? 0 : c; IGNORE(res); // TODO: set an error flag `res` in `cookie` (i.e. `CSink`)
return (ssize_t) size;
} }
static int cc20c_seek(void* cookie, off64_t* pos, int w) static int cc20c_seek(void* cookie, off64_t* pos, int w)

@ -4,7 +4,9 @@
#include <cc20.h> #include <cc20.h>
#define TRY(expr) do { if(CC20_ERR(res = (expr))) fprintf(stderr, "cc20 error %d: " #expr "\n", (int)res); goto fail; } while(0) #define TRY(expr) do { if(CC20_ERR(res = (expr))) { fprintf(stderr, "cc20 error %d: " #expr "\n", (int)res); goto fail; } } while(0)
const char write_string[] = "Hello world?";
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -15,9 +17,11 @@ int main(int argc, char** argv)
if(!output) { perror("failed to open output"); return -1; } if(!output) { perror("failed to open output"); return -1; }
TRY(cc20_gen_meta(output, NULL, NULL, CC20_ENCRYPT, &meta)); TRY(cc20_gen_meta(output, NULL, NULL, CC20_ENCRYPT, &meta));
if(! (output = cc20_gen(&meta)) ) { perror("failed to open encrypted output"); fclose(meta.backing); return -1; } TRY(cc20_gen(&meta, &output));
printf("written %lu bytes\n", fwrite(write_string, 1, strlen(write_string), output));
fprintf(output, "Hello world!"); //fprintf(output, "Hello world!");
res = CC20_ERR_NONE; res = CC20_ERR_NONE;
fail: fail:

@ -1,5 +1,7 @@
#!/bin/bash #!/bin/bash
gcc test.c -Iinclude -Wall --std=gnu11 -pedantic -Wextra -O3 -o test-ffi -l:target/debug/libchacha20stream.so || exit gcc test.c -Iinclude -Wall --std=gnu11 -pedantic -Wextra -O3 -o test-ffi -l:target/release/libchacha20stream.so || exit
./test-ffi #-lssl -lcrypto -lpthread -ldl || exit
rm -f test-ffi valgrind ./test-ffi test-ffi-output
hexview test-ffi-output
rm -f test-ffi{,-output}

Loading…
Cancel
Save