use std::ffi::CString; use std::os::raw::c_char; use std::{ptr, slice}; use chksum::hash::{md5, sha1}; #[allow(clippy::let_and_return)] #[no_mangle] pub extern "C" fn chksum_hash_md5_new() -> *mut md5::State { let state = md5::State::new(); let state = Box::new(state); let state = Box::into_raw(state); state } #[no_mangle] pub unsafe extern "C" fn chksum_hash_md5_update(hash: *mut md5::State, data: *const u8, length: usize) -> usize { if data.is_null() || (length < md5::BLOCK_LENGTH_BYTES) { return 0; } match hash.as_mut() { Some(hash) => { for offset in 0..(length / md5::BLOCK_LENGTH_BYTES) { let block = data.add(offset); let block = slice::from_raw_parts(block, md5::BLOCK_LENGTH_BYTES); let block = [ u32::from_le_bytes([block[0x00], block[0x01], block[0x02], block[0x03]]), u32::from_le_bytes([block[0x04], block[0x05], block[0x06], block[0x07]]), u32::from_le_bytes([block[0x08], block[0x09], block[0x0A], block[0x0B]]), u32::from_le_bytes([block[0x0C], block[0x0D], block[0x0E], block[0x0F]]), u32::from_le_bytes([block[0x10], block[0x11], block[0x12], block[0x13]]), u32::from_le_bytes([block[0x14], block[0x15], block[0x16], block[0x17]]), u32::from_le_bytes([block[0x18], block[0x19], block[0x1A], block[0x1B]]), u32::from_le_bytes([block[0x1C], block[0x1D], block[0x1E], block[0x1F]]), u32::from_le_bytes([block[0x20], block[0x21], block[0x22], block[0x23]]), u32::from_le_bytes([block[0x24], block[0x25], block[0x26], block[0x27]]), u32::from_le_bytes([block[0x28], block[0x29], block[0x2A], block[0x2B]]), u32::from_le_bytes([block[0x2C], block[0x2D], block[0x2E], block[0x2F]]), u32::from_le_bytes([block[0x30], block[0x31], block[0x32], block[0x33]]), u32::from_le_bytes([block[0x34], block[0x35], block[0x36], block[0x37]]), u32::from_le_bytes([block[0x38], block[0x39], block[0x3A], block[0x3B]]), u32::from_le_bytes([block[0x3C], block[0x3D], block[0x3E], block[0x3F]]), ]; hash.update(block); } length - (length % md5::BLOCK_LENGTH_BYTES) }, None => 0, } } #[no_mangle] pub unsafe extern "C" fn chksum_hash_md5_digest(hash: *const md5::State) -> *mut u8 { match hash.as_ref() { Some(hash) => { let digest = hash.digest(); let digest: md5::Digest = digest.into(); let digest: [u8; md5::DIGEST_LENGTH_BYTES] = digest.into(); let digest = Box::new(digest); Box::into_raw(digest) as *mut u8 }, None => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn chksum_hash_md5_hexdigest(hash: *const md5::State) -> *mut c_char { match hash.as_ref() { Some(hash) => { let digest = hash.digest(); let digest: md5::Digest = digest.into(); let digest = format!("{digest:x}"); let digest = CString::new(digest).expect("CString::new failed"); digest.into_raw() }, None => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn chksum_hash_md5_drop(hash: *mut md5::State) { drop(Box::from_raw(hash)); } #[allow(clippy::let_and_return)] #[no_mangle] pub extern "C" fn chksum_hash_sha1_new() -> *mut sha1::State { let state = sha1::State::new(); let state = Box::new(state); let state = Box::into_raw(state); state } #[no_mangle] pub unsafe extern "C" fn chksum_hash_sha1_update(hash: *mut sha1::State, data: *const u8, length: usize) -> usize { if data.is_null() || (length < sha1::BLOCK_LENGTH_BYTES) { return 0; } match hash.as_mut() { Some(hash) => { for offset in 0..(length / sha1::BLOCK_LENGTH_BYTES) { let block = data.add(offset); let block = slice::from_raw_parts(block, sha1::BLOCK_LENGTH_BYTES); let block = [ u32::from_be_bytes([block[0x00], block[0x01], block[0x02], block[0x03]]), u32::from_be_bytes([block[0x04], block[0x05], block[0x06], block[0x07]]), u32::from_be_bytes([block[0x08], block[0x09], block[0x0A], block[0x0B]]), u32::from_be_bytes([block[0x0C], block[0x0D], block[0x0E], block[0x0F]]), u32::from_be_bytes([block[0x10], block[0x11], block[0x12], block[0x13]]), u32::from_be_bytes([block[0x14], block[0x15], block[0x16], block[0x17]]), u32::from_be_bytes([block[0x18], block[0x19], block[0x1A], block[0x1B]]), u32::from_be_bytes([block[0x1C], block[0x1D], block[0x1E], block[0x1F]]), u32::from_be_bytes([block[0x20], block[0x21], block[0x22], block[0x23]]), u32::from_be_bytes([block[0x24], block[0x25], block[0x26], block[0x27]]), u32::from_be_bytes([block[0x28], block[0x29], block[0x2A], block[0x2B]]), u32::from_be_bytes([block[0x2C], block[0x2D], block[0x2E], block[0x2F]]), u32::from_be_bytes([block[0x30], block[0x31], block[0x32], block[0x33]]), u32::from_be_bytes([block[0x34], block[0x35], block[0x36], block[0x37]]), u32::from_be_bytes([block[0x38], block[0x39], block[0x3A], block[0x3B]]), u32::from_be_bytes([block[0x3C], block[0x3D], block[0x3E], block[0x3F]]), ]; hash.update(block); } length - (length % sha1::BLOCK_LENGTH_BYTES) }, None => 0, } } #[no_mangle] pub unsafe extern "C" fn chksum_hash_sha1_digest(hash: *const sha1::State) -> *mut u8 { match hash.as_ref() { Some(hash) => { let digest = hash.digest(); let digest: sha1::Digest = digest.into(); let digest: [u8; sha1::DIGEST_LENGTH_BYTES] = digest.into(); let digest = Box::new(digest); Box::into_raw(digest) as *mut u8 }, None => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn chksum_hash_sha1_hexdigest(hash: *const sha1::State) -> *mut c_char { match hash.as_ref() { Some(hash) => { let digest = hash.digest(); let digest: sha1::Digest = digest.into(); let digest = format!("{digest:x}"); let digest = CString::new(digest).expect("CString::new failed"); digest.into_raw() }, None => ptr::null_mut(), } } #[no_mangle] pub unsafe extern "C" fn chksum_hash_sha1_drop(hash: *mut sha1::State) { drop(Box::from_raw(hash)); }