diff --git a/src/aes.rs b/src/aes.rs index 0d83d1a..1760da3 100644 --- a/src/aes.rs +++ b/src/aes.rs @@ -2,12 +2,18 @@ use aes_gcm::{ aead::{generic_array::GenericArray, AeadMut, OsRng}, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, }; +use rand::RngCore; use rand_07::AsByteSliceMut; use std::ffi::{c_char, c_uchar, CStr, CString}; -use x25519_dalek::x25519; use crate::x25519; +#[repr(C)] +pub struct AesNonce { + pub nonce: *mut c_uchar, + pub length: usize +} + #[repr(C)] pub struct AesBytesEncrypt { pub ciphertext: *mut c_uchar, @@ -23,7 +29,8 @@ pub struct AesBytesDecrypt { #[repr(C)] pub struct AesNonceAndKeyFromX25519DiffieHellman { pub aes_key_ptr: *mut c_char, - pub aes_nonce_ptr: *mut c_char, + pub aes_nonce_ptr: *mut c_uchar, + pub aes_nonce_ptr_length: usize } #[no_mangle] @@ -35,13 +42,17 @@ pub extern "C" fn aes_256_key_and_nonce_from_x25519_diffie_hellman_shared_secret unsafe { std::slice::from_raw_parts(shared_secret, shared_secret_length) }; let aes_key = Key::::from_slice(&shared_secret_slice); - let mut aes_nonce: [u8; 8] = Default::default(); - aes_nonce.copy_from_slice(&shared_secret_slice[..8]); - + let mut aes_nonce = Vec::with_capacity(12); + aes_nonce.resize(12, 0); + aes_nonce.copy_from_slice(&shared_secret_slice[..12]); + let capacity = aes_nonce.capacity(); + aes_nonce.reserve_exact(capacity); let result = AesNonceAndKeyFromX25519DiffieHellman { aes_key_ptr: CString::new(base64::encode(aes_key)).unwrap().into_raw(), - aes_nonce_ptr: CString::new(base64::encode(aes_nonce)).unwrap().into_raw(), + aes_nonce_ptr: aes_nonce.as_mut_ptr(), + aes_nonce_ptr_length: aes_nonce.len() }; + std::mem::forget(aes_nonce); result } @@ -87,8 +98,7 @@ pub fn aes_256_key_and_nonce_from_x25519_diffie_hellman_shared_secret_test() { bob_shared_secret.shared_secret_length, ); - let alice_aes_nonce_cstr = unsafe { CString::from_raw(alice_aes.aes_nonce_ptr) }; - let alice_aes_nonce_ptr = alice_aes_nonce_cstr.as_bytes_with_nul().as_ptr() as *const c_char; + let alice_public_key_cstr = unsafe { CString::from_raw(alice_aes.aes_key_ptr) }; let alice_public_key_ptr = alice_public_key_cstr.as_bytes_with_nul().as_ptr() as *const c_char; @@ -96,15 +106,15 @@ pub fn aes_256_key_and_nonce_from_x25519_diffie_hellman_shared_secret_test() { let password = "DontUseThisPassword"; let password_cstr = password.as_bytes(); let password_ptr = password.as_ptr(); - let cipher_text_result = aes_256_encrypt_bytes_with_key(alice_aes_nonce_ptr, alice_public_key_ptr, password_ptr, password_cstr.len()); - let plain_text_result = aes_256_decrypt_bytes_with_key(bob_aes.aes_nonce_ptr, bob_aes.aes_key_ptr, cipher_text_result.ciphertext, cipher_text_result.length); + let cipher_text_result = aes_256_encrypt_bytes_with_key(alice_aes.aes_nonce_ptr, alice_aes.aes_nonce_ptr_length, alice_public_key_ptr, password_ptr, password_cstr.len()); + let plain_text_result = aes_256_decrypt_bytes_with_key(bob_aes.aes_nonce_ptr, bob_aes.aes_nonce_ptr_length, bob_aes.aes_key_ptr, cipher_text_result.ciphertext, cipher_text_result.length); let plain_text_result_slice: &[u8] = unsafe { - std::slice::from_raw_parts( - plain_text_result.plaintext, - plain_text_result.length, - ) - }; - assert_eq!(password_cstr, plain_text_result_slice); + std::slice::from_raw_parts( + plain_text_result.plaintext, + plain_text_result.length, + ) + }; + assert_eq!(password_cstr, plain_text_result_slice); } #[no_mangle] @@ -118,13 +128,17 @@ pub extern "C" fn aes_128_key_and_nonce_from_x25519_diffie_hellman_shared_secret let mut shorted_shared_secret: [u8; 16] = Default::default(); shorted_shared_secret.copy_from_slice(&shared_secret_slice[..16]); let aes_key = Key::::from_slice(&shorted_shared_secret); - let mut aes_nonce: [u8; 8] = Default::default(); - aes_nonce.copy_from_slice(&shared_secret_slice[..8]); - + let mut aes_nonce = Vec::with_capacity(12); + aes_nonce.resize(12, 0); + aes_nonce.copy_from_slice(&shared_secret_slice[..12]); + let capacity = aes_nonce.capacity(); + aes_nonce.reserve_exact(capacity); let result = AesNonceAndKeyFromX25519DiffieHellman { aes_key_ptr: CString::new(base64::encode(aes_key)).unwrap().into_raw(), - aes_nonce_ptr: CString::new(base64::encode(aes_nonce)).unwrap().into_raw(), + aes_nonce_ptr: aes_nonce.as_mut_ptr(), + aes_nonce_ptr_length: aes_nonce.len() }; + std::mem::forget(aes_nonce); result } @@ -170,8 +184,6 @@ pub fn aes_128_key_and_nonce_from_x25519_diffie_hellman_shared_secret_test() { bob_shared_secret.shared_secret_length, ); - let alice_aes_nonce_cstr = unsafe { CString::from_raw(alice_aes.aes_nonce_ptr) }; - let alice_aes_nonce_ptr = alice_aes_nonce_cstr.as_bytes_with_nul().as_ptr() as *const c_char; let alice_public_key_cstr = unsafe { CString::from_raw(alice_aes.aes_key_ptr) }; let alice_public_key_ptr = alice_public_key_cstr.as_bytes_with_nul().as_ptr() as *const c_char; @@ -179,8 +191,8 @@ pub fn aes_128_key_and_nonce_from_x25519_diffie_hellman_shared_secret_test() { let password = "DontUseThisPassword"; let password_cstr = password.as_bytes(); let password_ptr = password.as_ptr(); - let cipher_text_result = aes_128_encrypt_bytes_with_key(alice_aes_nonce_ptr, alice_public_key_ptr, password_ptr, password_cstr.len()); - let plain_text_result = aes_128_decrypt_bytes_with_key(bob_aes.aes_nonce_ptr, bob_aes.aes_key_ptr, cipher_text_result.ciphertext, cipher_text_result.length); + let cipher_text_result = aes_128_encrypt_bytes_with_key(alice_aes.aes_nonce_ptr, alice_aes.aes_nonce_ptr_length, alice_public_key_ptr, password_ptr, password_cstr.len()); + let plain_text_result = aes_128_decrypt_bytes_with_key(bob_aes.aes_nonce_ptr, bob_aes.aes_nonce_ptr_length, bob_aes.aes_key_ptr, cipher_text_result.ciphertext, cipher_text_result.length); let plain_text_result_slice: &[u8] = unsafe { std::slice::from_raw_parts( plain_text_result.plaintext, @@ -190,6 +202,22 @@ pub fn aes_128_key_and_nonce_from_x25519_diffie_hellman_shared_secret_test() { assert_eq!(password_cstr, plain_text_result_slice); } +#[no_mangle] +pub extern "C" fn aes_nonce() -> AesNonce { + let mut rng = &mut OsRng; + let mut random_bytes = Vec::with_capacity(12); + random_bytes.resize(12, 0); + rng.fill_bytes(&mut random_bytes); + let capacity = random_bytes.capacity(); + random_bytes.reserve_exact(capacity); + let result = AesNonce { + nonce: random_bytes.as_mut_ptr(), + length: random_bytes.len() + }; + std::mem::forget(random_bytes); + result +} + #[no_mangle] pub extern "C" fn aes_256_key() -> *mut c_char { return CString::new(base64::encode(Aes256Gcm::generate_key(&mut OsRng))) @@ -206,19 +234,13 @@ pub extern "C" fn aes_128_key() -> *mut c_char { #[no_mangle] pub extern "C" fn aes_128_encrypt_bytes_with_key( - nonce_key: *const c_char, + nonce_key: *const c_uchar, + nonce_key_length: usize, key: *const c_char, to_encrypt: *const c_uchar, to_encrypt_length: usize, ) -> AesBytesEncrypt { - let nonce_string_key = unsafe { - assert!(!nonce_key.is_null()); - CStr::from_ptr(nonce_key) - } - .to_str() - .unwrap() - .as_bytes(); - + let nonce_slice = unsafe { std::slice::from_raw_parts(nonce_key, nonce_key_length) }; let key_string = unsafe { assert!(!key.is_null()); CStr::from_ptr(key) @@ -230,7 +252,7 @@ pub extern "C" fn aes_128_encrypt_bytes_with_key( let mut decoded_string_key = base64::decode(key_string).unwrap(); let key = GenericArray::from_slice(decoded_string_key.as_byte_slice_mut()); let mut cipher = Aes128Gcm::new(&key); - let nonce = Nonce::from_slice(nonce_string_key); // 96-bits; unique per message + let nonce = Nonce::from_slice(nonce_slice); // 96-bits; unique per message let mut ciphertext: Vec = cipher.encrypt(nonce, to_encrypt_slice.as_ref()).unwrap(); let capacity = ciphertext.capacity(); ciphertext.reserve_exact(capacity); @@ -244,19 +266,13 @@ pub extern "C" fn aes_128_encrypt_bytes_with_key( #[no_mangle] pub extern "C" fn aes_256_encrypt_bytes_with_key( - nonce_key: *const c_char, + nonce_key: *const c_uchar, + nonce_key_length: usize, key: *const c_char, to_decrypt: *const c_uchar, to_decrypt_length: usize, ) -> AesBytesEncrypt { - let nonce_string_key = unsafe { - assert!(!nonce_key.is_null()); - CStr::from_ptr(nonce_key) - } - .to_str() - .unwrap() - .as_bytes(); - + let nonce_slice = unsafe { std::slice::from_raw_parts(nonce_key, nonce_key_length) }; let key_string = unsafe { assert!(!key.is_null()); CStr::from_ptr(key) @@ -267,7 +283,7 @@ pub extern "C" fn aes_256_encrypt_bytes_with_key( let mut decoded_string_key = base64::decode(key_string).unwrap(); let key = GenericArray::from_slice(decoded_string_key.as_byte_slice_mut()); let mut cipher = Aes256Gcm::new(&key); - let nonce = Nonce::from_slice(nonce_string_key); // 96-bits; unique per message + let nonce = Nonce::from_slice(nonce_slice); // 96-bits; unique per message let mut ciphertext = cipher.encrypt(nonce, to_decrypt_slice).unwrap(); let capacity = ciphertext.capacity(); ciphertext.reserve_exact(capacity); @@ -281,19 +297,13 @@ pub extern "C" fn aes_256_encrypt_bytes_with_key( #[no_mangle] pub extern "C" fn aes_128_decrypt_bytes_with_key( - nonce_key: *const c_char, + nonce_key: *const c_uchar, + nonce_key_length: usize, key: *const c_char, to_decrypt: *const c_uchar, to_decrypt_length: usize, ) -> AesBytesDecrypt { - let nonce_string_key = unsafe { - assert!(!nonce_key.is_null()); - CStr::from_ptr(nonce_key) - } - .to_str() - .unwrap() - .as_bytes(); - + let nonce_slice = unsafe { std::slice::from_raw_parts(nonce_key, nonce_key_length) }; let key_string = unsafe { assert!(!key.is_null()); CStr::from_ptr(key) @@ -304,7 +314,7 @@ pub extern "C" fn aes_128_decrypt_bytes_with_key( let mut decoded_string_key = base64::decode(key_string).unwrap(); let key = GenericArray::from_slice(decoded_string_key.as_byte_slice_mut()); let mut cipher = Aes128Gcm::new(&key); - let nonce = Nonce::from_slice(nonce_string_key); // 96-bits; unique per message + let nonce = Nonce::from_slice(nonce_slice); // 96-bits; unique per message let mut plaintext = cipher.decrypt(nonce, to_decrypt_slice).unwrap(); let capacity = plaintext.capacity(); plaintext.reserve_exact(capacity); @@ -318,19 +328,13 @@ pub extern "C" fn aes_128_decrypt_bytes_with_key( #[no_mangle] pub extern "C" fn aes_256_decrypt_bytes_with_key( - nonce_key: *const c_char, + nonce_key: *const c_uchar, + nonce_key_length: usize, key: *const c_char, to_decrypt: *const c_uchar, to_decrypt_length: usize, ) -> AesBytesDecrypt { - let nonce_string_key = unsafe { - assert!(!nonce_key.is_null()); - CStr::from_ptr(nonce_key) - } - .to_str() - .unwrap() - .as_bytes(); - + let nonce_slice = unsafe { std::slice::from_raw_parts(nonce_key, nonce_key_length) }; let key_string = unsafe { assert!(!key.is_null()); CStr::from_ptr(key) @@ -341,7 +345,7 @@ pub extern "C" fn aes_256_decrypt_bytes_with_key( let mut decoded_string_key = base64::decode(key_string).unwrap(); let key = GenericArray::from_slice(decoded_string_key.as_byte_slice_mut()); let mut cipher = Aes256Gcm::new(&key); - let nonce = Nonce::from_slice(nonce_string_key); // 96-bits; unique per message + let nonce = Nonce::from_slice(nonce_slice); // 96-bits; unique per message let mut plaintext = cipher.decrypt(nonce, to_decrypt_slice).unwrap(); let capacity = plaintext.capacity(); plaintext.reserve_exact(capacity);