diff --git a/Cargo.toml b/Cargo.toml index 4a38c8a..c4aab21 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2018" rand-8 = {package = "rand", version = "0.8.3"} rand-7 = {package = "rand", version = "0.7.3"} tokio = {version = "1", features = ["rt", "rt-multi-thread", "macros", "net", "io-util"]} +async-trait = "0.1.5" lazy_static = "1.4" socket2 = "0.4.0" rusqlite = {version = "0.25.1", features = ["bundled"]} diff --git a/src/frontend/index.css b/src/frontend/index.css index e071e65..22da76c 100644 --- a/src/frontend/index.css +++ b/src/frontend/index.css @@ -107,9 +107,12 @@ input[type="file"] { margin: auto; } .popup section { - font-weight: bold; display: block; margin-bottom: 20px; + border-top: 1px solid black; +} +.popup section:first-of-type { + border-top: unset; } .popup input { display: block; @@ -128,6 +131,62 @@ input[type="file"] { display: inline-block; vertical-align: middle; } +label { + cursor: pointer; +} +.switch_preference { + display: flex; + align-items: center; +} +.preference_description { + flex-grow: 1; + width: 0; /*fix unknown display bug of .switch*/ + margin-right: 20px; +} +.preference_description p:last-of-type { + font-size: .8em; +} +.switch { + position: relative; + display: inline-block; + width: 60px; + height: 34px; +} +.switch input { + opacity: 0; + width: 0; + height: 0; +} +.switch span { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: #ccc; + border-radius: 34px; + transition: .3s; +} +.switch span::before { + position: absolute; + content: ""; + height: 26px; + width: 26px; + left: 4px; + bottom: 4px; + background-color: white; + border-radius: 50%; + transition: .3s; +} +.switch input:checked + span { + background-color: var(--accent); +} +.switch input:focus + span { + box-shadow: 0 0 1px var(--accent); +} +.switch input:checked + span:before { + transform: translateX(26px); +} #session_info .name { display: flex; justify-content: center; @@ -158,8 +217,6 @@ input[type="file"] { } #right_panel { background-color: #15191E; - display: flex; - flex-direction: column; overflow: hidden; } #me { diff --git a/src/frontend/index.html b/src/frontend/index.html index 6b1b1db..ca6b87e 100644 --- a/src/frontend/index.html +++ b/src/frontend/index.html @@ -68,6 +68,7 @@ let identityFingerprint = "IDENTITY_FINGERPRINT"; let isIdentityProtected = IS_IDENTITY_PROTECTED; let websocketPort = WEBSOCKET_PORT; + let usePadding = PSEC_PADDING; diff --git a/src/frontend/index.js b/src/frontend/index.js index 39cdb41..4be2ab3 100644 --- a/src/frontend/index.js +++ b/src/frontend/index.js @@ -241,7 +241,9 @@ profile_div.onclick = function() { fingerprint.textContent = beautifyFingerprint(identityFingerprint); mainDiv.appendChild(fingerprint); let sectionName = document.createElement("section"); - sectionName.textContent = "Name:"; + let titleName = document.createElement("h3"); + titleName.textContent = "Name:"; + sectionName.appendChild(titleName); let inputName = document.createElement("input"); inputName.id = "new_name"; inputName.type = "text"; @@ -255,10 +257,16 @@ profile_div.onclick = function() { }; sectionName.appendChild(saveNameButton); mainDiv.appendChild(sectionName); + let sectionPadding = document.createElement("section"); + sectionPadding.appendChild(generateSwitchPreference("Use PSEC padding", "PSEC padding obfuscates the length of your messages but uses more network bandwidth.", usePadding, function(checked) { + socket.send("set_use_padding "+checked); + usePadding = checked; + })); + mainDiv.appendChild(sectionPadding); let sectionPassword = document.createElement("section"); - sectionPassword.textContent = "Change your password:"; - sectionPassword.style.paddingTop = "1em"; - sectionPassword.style.borderTop = "1px solid black"; + let titlePassword = document.createElement("h3"); + titlePassword.textContent = "Change your password:"; + sectionPassword.appendChild(titlePassword); if (isIdentityProtected) { let input_old_password = document.createElement("input"); input_old_password.type = "password"; @@ -313,8 +321,9 @@ profile_div.onclick = function() { sectionPassword.appendChild(changePasswordButton); mainDiv.appendChild(sectionPassword); let sectionDelete = document.createElement("section"); - sectionDelete.textContent = "Delete identity:"; - sectionDelete.style.paddingTop = "1em"; + let deleteTitle = document.createElement("h3"); + deleteTitle.textContent = "Delete identity:"; + sectionDelete.appendChild(deleteTitle); sectionDelete.style.borderTop = "1px solid red"; let p = document.createElement("p"); p.textContent = "Deleting your identity will delete all your conversations (messages and files), all your contacts, and your private key. You won't be able to be recognized by your contacts anymore."; @@ -879,6 +888,32 @@ function generatePopupWarningTitle() { h2.textContent = "Warning!"; return h2; } +function generateSwitchPreference(title, summary, checked, onSwitch) { + let label = document.createElement("label"); + label.classList.add("switch_preference"); + let divDesc = document.createElement("div"); + divDesc.classList.add("preference_description"); + let h3 = document.createElement("h3"); + h3.textContent = title; + divDesc.appendChild(h3); + let pSummary = document.createElement("p"); + pSummary.textContent = summary; + divDesc.appendChild(pSummary); + label.appendChild(divDesc); + let switchDiv = document.createElement("div"); + switchDiv.classList.add("switch"); + let input = document.createElement("input"); + input.type = "checkbox"; + input.checked = checked; + input.onchange = function() { + onSwitch(input.checked); + }; + switchDiv.appendChild(input); + let span = document.createElement("span"); + switchDiv.appendChild(span); + label.appendChild(switchDiv); + return label; +} function generateName(name) { let p = document.createElement("p"); if (typeof name == "undefined") { diff --git a/src/identity.rs b/src/identity.rs index 8cca8a1..4d60308 100644 --- a/src/identity.rs +++ b/src/identity.rs @@ -20,6 +20,7 @@ impl<'a> DBKeys { pub const KEYPAIR: &'a str = "keypair"; pub const SALT: &'a str = "salt"; pub const MASTER_KEY: &'a str = "master_key"; + pub const USE_PADDING: &'a str = "use_padding"; } fn bool_to_byte(b: bool) -> u8 { @@ -44,7 +45,8 @@ struct EncryptedIdentity { name: String, encrypted_keypair: Vec, salt: Vec, - encrypted_master_key: Vec + encrypted_master_key: Vec, + encrypted_use_padding: Vec, } pub struct Contact { @@ -59,6 +61,7 @@ pub struct Identity { pub name: String, keypair: Keypair, pub master_key: [u8; crypto::MASTER_KEY_LEN], + pub use_padding: bool, } impl Identity { @@ -329,6 +332,13 @@ impl Identity { result } + pub fn set_use_padding(&mut self, use_padding: bool) -> Result { + self.use_padding = use_padding; + let db = KeyValueTable::new(&get_database_path(), MAIN_TABLE)?; + let encrypted_use_padding = crypto::encrypt_data(&[bool_to_byte(use_padding)], &self.master_key).unwrap(); + db.update(DBKeys::USE_PADDING, &encrypted_use_padding) + } + pub fn zeroize(&mut self){ self.master_key.zeroize(); self.keypair.secret.zeroize(); @@ -340,11 +350,13 @@ impl Identity { let encrypted_keypair = db.get(DBKeys::KEYPAIR)?; let salt = db.get(DBKeys::SALT)?; let encrypted_master_key = db.get(DBKeys::MASTER_KEY)?; + let encrypted_use_padding = db.get(DBKeys::USE_PADDING)?; Ok(EncryptedIdentity { name: std::str::from_utf8(&name).unwrap().to_owned(), encrypted_keypair, salt, encrypted_master_key, + encrypted_use_padding, }) } @@ -370,11 +382,20 @@ impl Identity { }; match crypto::decrypt_data(&encrypted_identity.encrypted_keypair, &master_key) { Ok(keypair) => { - Ok(Identity{ - name: encrypted_identity.name, - keypair: Keypair::from_bytes(&keypair[..]).unwrap(), - master_key: master_key, - }) + match crypto::decrypt_data(&encrypted_identity.encrypted_use_padding, &master_key) { + Ok(use_padding) => { + Ok(Identity{ + name: encrypted_identity.name, + keypair: Keypair::from_bytes(&keypair[..]).unwrap(), + master_key, + use_padding: byte_to_bool(use_padding[0]).unwrap(), + }) + } + Err(e) => { + print_error!(e); + Err(String::from(DATABASE_CORRUPED_ERROR)) + } + } } Err(e) => { print_error!(e); @@ -412,10 +433,13 @@ impl Identity { salt }; db.set(DBKeys::SALT, &salt)?; + let encrypted_use_padding = crypto::encrypt_data(&[bool_to_byte(true)], &master_key).unwrap(); + db.set(DBKeys::USE_PADDING, &encrypted_use_padding)?; Ok(Identity { name: name.to_owned(), keypair, master_key, + use_padding: true, }) } @@ -470,6 +494,7 @@ impl Clone for Identity { name: self.name.clone(), keypair: Keypair::from_bytes(&self.keypair.to_bytes()).unwrap(), master_key: self.master_key, + use_padding: self.use_padding, } } } \ No newline at end of file diff --git a/src/key_value_table.rs b/src/key_value_table.rs index 510d1da..88c88c5 100644 --- a/src/key_value_table.rs +++ b/src/key_value_table.rs @@ -28,4 +28,7 @@ impl<'a> KeyValueTable<'a> { pub fn update(&self, key: &str, value: &[u8]) -> Result { self.db.execute(&format!("UPDATE {} SET value=? WHERE key=\"{}\"", self.table_name, key), params![value]) } + /*pub fn upsert(&self, key: &str, value: &[u8]) -> Result { + self.db.execute(&format!("INSERT INTO {} (key, value) VALUES(?1, ?2) ON CONFLICT(key) DO UPDATE SET value=?3", self.table_name), params![key, value, value]) + }*/ } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 35ef2f9..eccec77 100644 --- a/src/main.rs +++ b/src/main.rs @@ -91,7 +91,7 @@ fn load_msgs(session_manager: Arc, ui_connection: &mut UiConnect async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc>, worker_done: Arc>) { let session_manager = global_vars.read().unwrap().session_manager.clone(); - ui_connection.set_name(&session_manager.get_my_name()); + ui_connection.set_name(&session_manager.identity.read().unwrap().as_ref().unwrap().name); session_manager.list_contacts().into_iter().for_each(|contact|{ ui_connection.set_as_contact(contact.0, &contact.1, contact.2, &crypto::generate_fingerprint(&contact.3)); session_manager.last_loaded_msg_offsets.write().unwrap().insert(contact.0, 0); @@ -238,6 +238,12 @@ async fn websocket_worker(mut ui_connection: UiConnection, global_vars: Arc { + let use_padding: bool = args[1].parse().unwrap(); + if let Err(e) = session_manager.identity.write().unwrap().as_mut().unwrap().set_use_padding(use_padding) { + print_error!(e); + } + } "change_name" => { let new_name = &msg[args[0].len()+1..]; match session_manager.change_name(new_name.to_string()).await { @@ -316,7 +322,7 @@ fn handle_load_file(req: HttpRequest, file_info: web::Query) -> HttpRe match Uuid::from_str(&file_info.uuid) { Ok(uuid) => { let global_vars = req.app_data::>>>().unwrap(); - match global_vars.read().unwrap().session_manager.load_file(uuid) { + match global_vars.read().unwrap().session_manager.identity.read().unwrap().as_ref().unwrap().load_file(uuid) { Some(buffer) => { return HttpResponse::Ok().header("Content-Disposition", format!("attachment; filename=\"{}\"", escape_double_quote(html_escape::decode_html_entities(&file_info.file_name).to_string()))).content_type("application/octet-stream").body(buffer); } @@ -560,12 +566,15 @@ async fn handle_index(req: HttpRequest) -> HttpResponse { let html = fs::read_to_string("src/frontend/index.html").unwrap(); #[cfg(not(debug_assertions))] let html = include_str!(concat!(env!("OUT_DIR"), "/index.html")); + let public_key = global_vars_read.session_manager.identity.read().unwrap().as_ref().unwrap().get_public_key(); + let use_padding = global_vars_read.session_manager.identity.read().unwrap().as_ref().unwrap().use_padding.to_string(); HttpResponse::Ok().body( html .replace("AIRA_VERSION", env!("CARGO_PKG_VERSION")) - .replace("IDENTITY_FINGERPRINT", &crypto::generate_fingerprint(&global_vars_read.session_manager.get_my_public_key())) + .replace("IDENTITY_FINGERPRINT", &crypto::generate_fingerprint(&public_key)) .replace("WEBSOCKET_PORT", &global_vars_read.websocket_port.to_string()) .replace("IS_IDENTITY_PROTECTED", &Identity::is_protected().unwrap().to_string()) + .replace("PSEC_PADDING", &use_padding) ) } else { index_not_logged_in(global_vars) diff --git a/src/session_manager/mod.rs b/src/session_manager/mod.rs index 186c6cc..ee1a676 100644 --- a/src/session_manager/mod.rs +++ b/src/session_manager/mod.rs @@ -11,8 +11,7 @@ use uuid::Uuid; use platform_dirs::UserDirs; use crate::{constants, crypto, discovery, identity::{Contact, Identity}, print_error, utils::{get_unix_timestamp, get_not_used_path}}; use crate::ui_interface::UiConnection; - -use self::session::SessionWrite; +use self::session::{SessionWrite, PSECWriter}; #[derive(Display, Debug, PartialEq, Eq)] pub enum SessionError { @@ -67,7 +66,7 @@ pub struct SessionData { pub struct SessionManager { session_counter: RwLock, pub sessions: RwLock>, - identity: RwLock>, + pub identity: RwLock>, ui_connection: Mutex>, loaded_contacts: RwLock>, pub last_loaded_msg_offsets: RwLock>, @@ -89,6 +88,11 @@ impl SessionManager { } } + async fn encrypt_and_send(&self, writer: &mut T, buff: &[u8]) -> Result<(), SessionError> { + let use_padding = self.identity.read().unwrap().as_ref().unwrap().use_padding; + writer.encrypt_and_send(buff, use_padding).await + } + pub async fn connect_to(session_manager: Arc, ip: IpAddr) -> io::Result<()> { let stream = TcpStream::connect(SocketAddr::new(ip, constants::PORT)).await?; SessionManager::handle_new_session(session_manager, Session::new(stream), true); @@ -143,7 +147,7 @@ impl SessionManager { } async fn send_msg(&self, session_id: usize, session_write: &mut SessionWrite, buff: &[u8], is_sending: &mut bool, file_ack_sender: &mut Option>) -> Result<(), SessionError> { - session_write.encrypt_and_send(&buff).await?; + self.encrypt_and_send(session_write, &buff).await?; if buff[0] == protocol::Headers::ACCEPT_LARGE_FILES { self.sessions.write().unwrap().get_mut(&session_id).unwrap().files_download.as_mut().unwrap().accepted = true; } else if buff[0] == protocol::Headers::ABORT_FILES_TRANSFER { @@ -187,7 +191,7 @@ impl SessionManager { self.identity.read().unwrap().as_ref().and_then(|identity| Some(identity.name.clone())) }; if name.is_some() { //can be None if we log out just before locking the identity mutex - if let Err(e) = session_write.encrypt_and_send(&protocol::tell_name(&name.unwrap())).await { + if let Err(e) = self.encrypt_and_send(&mut session_write, &protocol::tell_name(&name.unwrap())).await { print_error!(e); break; } @@ -235,7 +239,7 @@ impl SessionManager { ui_connection.on_ask_large_files(&session_id, &files, download_location.to_str().unwrap()); }) } - } else if let Err(e) = session_write.encrypt_and_send(&[protocol::Headers::ABORT_FILES_TRANSFER]).await { + } else if let Err(e) = self.encrypt_and_send(&mut session_write, &[protocol::Headers::ABORT_FILES_TRANSFER]).await { print_error!(e); break; } @@ -282,7 +286,7 @@ impl SessionManager { local_file_handle = None; } } - if let Err(e) = session_write.encrypt_and_send(&[protocol::Headers::ACK_CHUNK]).await { + if let Err(e) = self.encrypt_and_send(&mut session_write, &[protocol::Headers::ACK_CHUNK]).await { print_error!(e); break; } @@ -297,7 +301,7 @@ impl SessionManager { if !is_success { self.sessions.write().unwrap().get_mut(&session_id).unwrap().files_download = None; local_file_handle = None; - if let Err(e) = session_write.encrypt_and_send(&[protocol::Headers::ABORT_FILES_TRANSFER]).await { + if let Err(e) = self.encrypt_and_send(&mut session_write, &[protocol::Headers::ABORT_FILES_TRANSFER]).await { print_error!(e); break; } @@ -395,11 +399,11 @@ impl SessionManager { } SessionCommand::EncryptFileChunk { plain_text } => { last_chunks_sizes.as_mut().unwrap().push(plain_text.len() as u32); - next_chunk = Some(session_write.encrypt(&plain_text)); + next_chunk = Some(session_write.encrypt(&plain_text, self.identity.read().unwrap().as_ref().unwrap().use_padding)); } SessionCommand::SendEncryptedFileChunk { ack_sender } => { if let Some(chunk) = next_chunk.as_ref() { - match session_write.socket_write(chunk).await { + match session_write.send(chunk).await { Ok(_) => { file_ack_sender = Some(ack_sender); //once the pre-encrypted chunk is sent, we can send the pending messages @@ -507,7 +511,7 @@ impl SessionManager { ui_connection.on_new_session(&session_id, &ip.to_string(), outgoing, &crypto::generate_fingerprint(&peer_public_key), ip, None); }); if !is_contact { - match session.encrypt_and_send(&protocol::ask_name()).await { + match session_manager.encrypt_and_send(&mut session, &protocol::ask_name()).await { Ok(_) => {} Err(e) => { print_error!(e); @@ -621,10 +625,6 @@ impl SessionManager { self.loaded_contacts.read().unwrap().contains_key(session_id) } - pub fn load_file(&self, uuid: Uuid) -> Option> { - self.identity.read().unwrap().as_ref().unwrap().load_file(uuid) - } - pub fn store_file(&self, session_id: &usize, data: &[u8]) -> Result { self.identity.read().unwrap().as_ref().unwrap().store_file(match self.loaded_contacts.read().unwrap().get(session_id) { Some(contact) => Some(contact.uuid), @@ -641,14 +641,6 @@ impl SessionManager { msgs } - pub fn get_my_public_key(&self) -> [u8; PUBLIC_KEY_LENGTH] { - self.identity.read().unwrap().as_ref().unwrap().get_public_key() - } - - pub fn get_my_name(&self) -> String { - self.identity.read().unwrap().as_ref().unwrap().name.clone() - } - #[allow(unused_must_use)] pub async fn change_name(&self, new_name: String) -> Result { let telling_name = protocol::tell_name(&new_name); diff --git a/src/session_manager/session.rs b/src/session_manager/session.rs index 26626bc..5e50c57 100644 --- a/src/session_manager/session.rs +++ b/src/session_manager/session.rs @@ -1,5 +1,6 @@ use std::{convert::TryInto, io::ErrorKind, net::IpAddr}; use tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::{TcpStream, tcp::{OwnedReadHalf, OwnedWriteHalf}}}; +use async_trait::async_trait; use ed25519_dalek; use ed25519_dalek::{ed25519::signature::Signature, Verifier, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH}; use x25519_dalek; @@ -16,7 +17,7 @@ const RANDOM_LEN: usize = 64; const MESSAGE_LEN_LEN: usize = 4; type MessageLenType = u32; -async fn socket_read(reader: &mut T, buff: &mut [u8]) -> Result { +async fn receive(reader: &mut T, buff: &mut [u8]) -> Result { match reader.read(buff).await { Ok(read) => { if read > 0 { @@ -37,7 +38,7 @@ async fn socket_read(reader: &mut T, buff: &mut [u8]) - } } -async fn socket_write(writer: &mut T, buff: &[u8]) -> Result<(), SessionError> { +async fn send(writer: &mut T, buff: &[u8]) -> Result<(), SessionError> { match writer.write_all(buff).await { Ok(_) => Ok(()), Err(e) => Err(match e.kind() { @@ -51,18 +52,22 @@ async fn socket_write(writer: &mut T, buff: &[u8]) -> } } -fn pad(plain_text: &[u8]) -> Vec { +fn pad(plain_text: &[u8], use_padding: bool) -> Vec { let encoded_msg_len = (plain_text.len() as MessageLenType).to_be_bytes(); let msg_len = plain_text.len()+encoded_msg_len.len(); - let mut len = 1000; - while len < msg_len { - len *= 2; - } let mut output = Vec::from(encoded_msg_len); - output.reserve(len); - output.extend(plain_text); - output.resize(len, 0); - OsRng.fill_bytes(&mut output[msg_len..]); + if use_padding { + let mut len = 1000; + while len < msg_len { + len *= 2; + } + output.reserve(len); + output.extend(plain_text); + output.resize(len, 0); + OsRng.fill_bytes(&mut output[msg_len..]); + } else { + output.extend(plain_text); + } output } @@ -71,8 +76,8 @@ fn unpad(input: Vec) -> Vec { Vec::from(&input[MESSAGE_LEN_LEN..MESSAGE_LEN_LEN+msg_len]) } -fn encrypt(local_cipher: &Aes128Gcm, local_iv: &[u8], local_counter: &mut usize, plain_text: &[u8]) -> Vec { - let padded_msg = pad(plain_text); +fn encrypt(local_cipher: &Aes128Gcm, local_iv: &[u8], local_counter: &mut usize, plain_text: &[u8], use_padding: bool) -> Vec { + let padded_msg = pad(plain_text, use_padding); let cipher_len = (padded_msg.len() as MessageLenType).to_be_bytes(); let payload = Payload { msg: &padded_msg, @@ -83,9 +88,16 @@ fn encrypt(local_cipher: &Aes128Gcm, local_iv: &[u8], local_counter: &mut usize, [&cipher_len, cipher_text.as_slice()].concat() } -pub async fn encrypt_and_send(writer: &mut T, local_cipher: &Aes128Gcm, local_iv: &[u8], local_counter: &mut usize, plain_text: &[u8]) -> Result<(), SessionError> { - let cipher_text = encrypt(local_cipher, local_iv, local_counter, plain_text); - socket_write(writer, &cipher_text).await +pub async fn encrypt_and_send(writer: &mut T, local_cipher: &Aes128Gcm, local_iv: &[u8], local_counter: &mut usize, plain_text: &[u8], use_padding: bool) -> Result<(), SessionError> { + let cipher_text = encrypt(local_cipher, local_iv, local_counter, plain_text, use_padding); + send(writer, &cipher_text).await +} + +#[async_trait] +pub trait PSECWriter { + async fn encrypt_and_send(&mut self, plain_text: &[u8], use_padding: bool) -> Result<(), SessionError>; + fn encrypt(&mut self, plain_text: &[u8], use_padding: bool) -> Vec; + async fn send(&mut self, cipher_text: &[u8]) -> Result<(), SessionError>; } pub struct SessionRead { @@ -96,19 +108,19 @@ pub struct SessionRead { } impl SessionRead { - async fn socket_read(&mut self, buff: &mut [u8]) -> Result { - socket_read(&mut self.read_half, buff).await + async fn receive(&mut self, buff: &mut [u8]) -> Result { + receive(&mut self.read_half, buff).await } pub async fn receive_and_decrypt(mut self) -> Result<(SessionRead, Vec), SessionError> { let mut message_len = [0; MESSAGE_LEN_LEN]; - self.socket_read(&mut message_len).await?; + self.receive(&mut message_len).await?; let recv_len = MessageLenType::from_be_bytes(message_len) as usize + AES_TAG_LEN; if recv_len <= Session::MAX_RECV_SIZE { let mut cipher_text = vec![0; recv_len]; let mut read = 0; while read < recv_len { - read += self.socket_read(&mut cipher_text[read..]).await?; + read += self.receive(&mut cipher_text[read..]).await?; } let peer_nonce = iv_to_nonce(&self.peer_iv, &mut self.peer_counter); let payload = Payload { @@ -133,15 +145,16 @@ pub struct SessionWrite { local_counter: usize, } -impl SessionWrite { - pub async fn encrypt_and_send(&mut self, plain_text: &[u8]) -> Result<(), SessionError> { - encrypt_and_send(&mut self.write_half, &self.local_cipher, &self.local_iv, &mut self.local_counter, plain_text).await +#[async_trait] +impl PSECWriter for SessionWrite { + async fn encrypt_and_send(&mut self, plain_text: &[u8], use_padding: bool) -> Result<(), SessionError> { + encrypt_and_send(&mut self.write_half, &self.local_cipher, &self.local_iv, &mut self.local_counter, plain_text, use_padding).await } - pub fn encrypt(&mut self, plain_text: &[u8]) -> Vec { - encrypt(&self.local_cipher, &self.local_iv, &mut self.local_counter, plain_text) + fn encrypt(&mut self, plain_text: &[u8], use_padding: bool) -> Vec { + encrypt(&self.local_cipher, &self.local_iv, &mut self.local_counter, plain_text, use_padding) } - pub async fn socket_write(&mut self, cipher_text: &[u8]) -> Result<(), SessionError> { - socket_write(&mut self.write_half, cipher_text).await + async fn send(&mut self, cipher_text: &[u8]) -> Result<(), SessionError> { + send(&mut self.write_half, cipher_text).await } } @@ -199,22 +212,22 @@ impl Session { self.stream.peer_addr().unwrap().ip() } - async fn socket_read(&mut self, buff: &mut [u8]) -> Result { - socket_read(&mut self.stream, buff).await + async fn receive(&mut self, buff: &mut [u8]) -> Result { + receive(&mut self.stream, buff).await } - pub async fn socket_write(&mut self, buff: &[u8]) -> Result<(), SessionError> { - socket_write(&mut self.stream, buff).await + pub async fn send(&mut self, buff: &[u8]) -> Result<(), SessionError> { + send(&mut self.stream, buff).await } async fn handshake_read(&mut self, buff: &mut [u8]) -> Result<(), SessionError> { - self.socket_read(buff).await?; + self.receive(buff).await?; self.handshake_recv_buff.extend(buff.as_ref()); Ok(()) } async fn handshake_write(&mut self, buff: &[u8]) -> Result<(), SessionError> { - self.socket_write(buff).await?; + self.send(buff).await?; self.handshake_sent_buff.extend(buff); Ok(()) } @@ -298,9 +311,9 @@ impl Session { let handshake_hash = self.hash_handshake(i_am_bob); //sending handshake finished let handshake_finished = compute_handshake_finished(handshake_keys.local_handshake_traffic_secret, handshake_hash); - self.socket_write(&handshake_finished).await?; + self.send(&handshake_finished).await?; let mut peer_handshake_finished = [0; HASH_OUTPUT_LEN]; - self.socket_read(&mut peer_handshake_finished).await?; + self.receive(&mut peer_handshake_finished).await?; if verify_handshake_finished(peer_handshake_finished, handshake_keys.peer_handshake_traffic_secret, handshake_hash) { //calc application keys let application_keys = ApplicationKeys::derive_keys(handshake_keys.handshake_secret, handshake_hash, i_am_bob); @@ -313,8 +326,19 @@ impl Session { } Err(SessionError::TransmissionCorrupted) } - - pub async fn encrypt_and_send(&mut self, plain_text: &[u8]) -> Result<(), SessionError> { - encrypt_and_send(&mut self.stream, self.local_cipher.as_ref().unwrap(), self.local_iv.as_ref().unwrap(), &mut self.local_counter, plain_text).await +} + +#[async_trait] +impl PSECWriter for Session { + async fn encrypt_and_send(&mut self, plain_text: &[u8], use_padding: bool) -> Result<(), SessionError> { + encrypt_and_send(&mut self.stream, self.local_cipher.as_ref().unwrap(), self.local_iv.as_ref().unwrap(), &mut self.local_counter, plain_text, use_padding).await + } + + fn encrypt(&mut self, plain_text: &[u8], use_padding: bool) -> Vec { + encrypt(self.local_cipher.as_ref().unwrap(), &self.local_iv.unwrap(), &mut self.local_counter, plain_text, use_padding) + } + + async fn send(&mut self, cipher_text: &[u8]) -> Result<(), SessionError> { + send(&mut self.stream, cipher_text).await } } \ No newline at end of file