extern crate libc; extern crate libpasta; extern crate rpassword; use libc::{c_char, c_uchar, c_uint}; use rpassword::prompt_password_stdout; use std::ffi::{CStr, CString}; macro_rules! ffi_ref { ($name:ident) => ( { assert!(!$name.is_null()); &*$name } ); } macro_rules! ffi_string { ($name:ident) => ( { assert!(!$name.is_null()); CStr::from_ptr($name).to_str().unwrap() } ) } #[no_mangle] pub extern fn read_password(prompt: *const c_char) -> *mut c_char { let prompt = unsafe { ffi_string!(prompt) }; let password = prompt_password_stdout(prompt).unwrap(); CString::new(password).unwrap().into_raw() } // Required to free memory properly #[no_mangle] pub extern fn free_string(s: *mut c_char) { unsafe { if s.is_null() { return } CString::from_raw(s) }; } #[no_mangle] pub extern fn hash_password(password: *const c_char) -> *mut c_char { let password = unsafe { ffi_string!(password) }; let output = libpasta::hash_password(password); CString::new(output).unwrap().into_raw() } #[no_mangle] pub extern "C" fn config_hash_password(config: *const Config, password: *const c_char) -> *mut c_char { let config = unsafe { ffi_ref!(config) }; let password = unsafe { ffi_string!(password) }; let output = config.hash_password(password); CString::new(output).unwrap().into_raw() } #[no_mangle] pub extern "C" fn verify_password(hash: *const c_char, password: *const c_char) -> bool { let hash = unsafe { ffi_string!(hash) }; let password = unsafe { ffi_string!(password) }; libpasta::verify_password(hash, password) } #[no_mangle] pub extern "C" fn config_verify_password(config: *const Config, hash: *const c_char, password: *const c_char) -> bool { let config = unsafe { ffi_ref!(config) }; let hash = unsafe { ffi_string!(hash) }; let password = unsafe { ffi_string!(password) }; config.verify_password(hash, password) } #[no_mangle] pub extern "C" fn verify_password_update_hash_in_place(hash: *const c_char, password: *const c_char, new_hash: *mut *mut c_char) -> bool { let mut hash = unsafe { ffi_string!(hash).to_owned() }; let password = unsafe { ffi_string!(password) }; let res = libpasta::verify_password_update_hash(&mut hash, password); unsafe { *new_hash = CString::new(hash).unwrap().into_raw(); } res } #[no_mangle] pub extern "C" fn config_verify_password_update_hash(config: *const Config, hash: *const c_char, password: *const c_char, new_hash: *mut *mut c_char) -> bool { let config = unsafe { ffi_ref!(config) }; let mut hash = unsafe { ffi_string!(hash).to_owned() }; let password = unsafe { ffi_string!(password) }; let res = config.verify_password_update_hash(&mut hash, password); unsafe { *new_hash = CString::new(hash).unwrap().into_raw(); } res } // use libpasta::primitives::Primitive; use libpasta::primitives::*; use libpasta::config::Config; #[no_mangle] pub extern "C" fn migrate_hash(hash: *const c_char) -> *mut c_char { let mut hash = unsafe { ffi_string!(hash).to_owned() }; libpasta::migrate_hash(&mut hash); CString::new(hash).unwrap().into_raw() } #[no_mangle] pub extern "C" fn config_migrate_hash(config: *const Config, hash: *const c_char) -> *mut c_char { let config = unsafe { ffi_ref!(config) }; let mut hash = unsafe { ffi_string!(hash).to_owned() }; config.migrate_hash(&mut hash); CString::new(hash).unwrap().into_raw() } #[no_mangle] pub extern "C" fn config_with_primitive(prim: *const Primitive) -> *mut Config { let prim = unsafe { ffi_ref!(prim) }; Box::into_raw(Box::new(Config::with_primitive(prim.clone()))) } #[no_mangle] pub extern "C" fn default_argon2i() -> *mut Primitive { Box::into_raw(Box::new(Argon2::default())) } #[no_mangle] pub extern "C" fn default_bcrypt() -> *mut Primitive { Box::into_raw(Box::new(Bcrypt::default())) } #[no_mangle] pub extern "C" fn default_pbkdf2i() -> *mut Primitive { Box::into_raw(Box::new(Pbkdf2::default())) } #[no_mangle] pub extern "C" fn default_scrypt() -> *mut Primitive { Box::into_raw(Box::new(Scrypt::default())) } #[no_mangle] pub extern "C" fn new_argon2i(passes: c_uint, lanes: c_uint, kib: c_uint) -> *mut Primitive { Box::into_raw(Box::new(Argon2::new(passes, lanes, kib))) } #[no_mangle] pub extern "C" fn new_bcrypt(cost: c_uint) -> *mut Primitive { Box::into_raw(Box::new(Bcrypt::new(cost))) } #[no_mangle] pub extern "C" fn new_scrypt(log_n: c_uchar, r: c_uint, p: c_uint) -> *mut Primitive { Box::into_raw(Box::new(Scrypt::new(log_n, r, p))) } #[no_mangle] pub extern "C" fn free_Primitive(prim: *mut Primitive) { let _prim = unsafe { ffi_ref!(prim) }; } #[no_mangle] pub extern "C" fn free_Config(config: *mut Config) { let _config = unsafe { ffi_ref!(config) }; }