diff --git a/Cargo.toml b/Cargo.toml index f5e5e2c..a0bf295 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ documentation = "https://docs.rs/valence/" license = "MIT" [workspace.dependencies] -aes = "0.7.5" +aes = "0.8.2" anyhow = "1.0.70" approx = "0.5.1" arrayvec = "0.7.2" @@ -26,7 +26,7 @@ bitfield-struct = "0.3.1" byteorder = "1.4.3" bytes = "1.2.1" cesu8 = "1.1.0" -cfb8 = "0.7.1" +cfb8 = "0.8.1" clap = { version = "4.0.30", features = ["derive"] } criterion = "0.4.0" directories = "5.0.0" diff --git a/crates/valence_core/src/packet/decode.rs b/crates/valence_core/src/packet/decode.rs index 174a845..d5203e0 100644 --- a/crates/valence_core/src/packet/decode.rs +++ b/crates/valence_core/src/packet/decode.rs @@ -1,5 +1,7 @@ #[cfg(feature = "encryption")] -use aes::cipher::{AsyncStreamCipher, NewCipher}; +use aes::cipher::generic_array::GenericArray; +#[cfg(feature = "encryption")] +use aes::cipher::{BlockDecryptMut, BlockSizeUser, KeyIvInit}; use anyhow::{bail, ensure}; use bytes::{Buf, BytesMut}; @@ -9,7 +11,7 @@ use crate::packet::{Packet, MAX_PACKET_SIZE}; /// The AES block cipher with a 128 bit key, using the CFB-8 mode of /// operation. #[cfg(feature = "encryption")] -type Cipher = cfb8::Cfb8; +type Cipher = cfb8::Decryptor; #[derive(Default)] pub struct PacketDecoder { @@ -128,20 +130,29 @@ impl PacketDecoder { pub fn enable_encryption(&mut self, key: &[u8; 16]) { assert!(self.cipher.is_none(), "encryption is already enabled"); - let mut cipher = Cipher::new(key.into(), key.into()); + let mut cipher = Cipher::new_from_slices(key, key).expect("invalid key"); // Don't forget to decrypt the data we already have. - cipher.decrypt(&mut self.buf); + Self::decrypt_bytes(&mut cipher, &mut self.buf); self.cipher = Some(cipher); } + /// Decrypts the provided byte slice in place using the cipher, without consuming the cipher. + #[cfg(feature = "encryption")] + fn decrypt_bytes(cipher: &mut Cipher, bytes: &mut [u8]) { + for chunk in bytes.chunks_mut(Cipher::block_size()) { + let gen_arr = GenericArray::from_mut_slice(chunk); + cipher.decrypt_block_mut(gen_arr); + } + } + pub fn queue_bytes(&mut self, mut bytes: BytesMut) { #![allow(unused_mut)] #[cfg(feature = "encryption")] if let Some(cipher) = &mut self.cipher { - cipher.decrypt(&mut bytes); + Self::decrypt_bytes(cipher, &mut bytes); } self.buf.unsplit(bytes); @@ -155,7 +166,8 @@ impl PacketDecoder { #[cfg(feature = "encryption")] if let Some(cipher) = &mut self.cipher { - cipher.decrypt(&mut self.buf[len..]); + let slice = &mut self.buf[len..]; + Self::decrypt_bytes(cipher, slice); } } diff --git a/crates/valence_core/src/packet/encode.rs b/crates/valence_core/src/packet/encode.rs index 62bc4a1..70e9417 100644 --- a/crates/valence_core/src/packet/encode.rs +++ b/crates/valence_core/src/packet/encode.rs @@ -1,5 +1,9 @@ use std::io::Write; +#[cfg(feature = "encryption")] +use aes::cipher::generic_array::GenericArray; +#[cfg(feature = "encryption")] +use aes::cipher::{BlockEncryptMut, BlockSizeUser, KeyIvInit}; use anyhow::ensure; use bytes::{BufMut, BytesMut}; use tracing::warn; @@ -10,7 +14,7 @@ use crate::packet::{Encode, Packet, MAX_PACKET_SIZE}; /// The AES block cipher with a 128 bit key, using the CFB-8 mode of /// operation. #[cfg(feature = "encryption")] -type Cipher = cfb8::Cfb8; +type Cipher = cfb8::Encryptor; #[derive(Default)] pub struct PacketEncoder { @@ -145,9 +149,10 @@ impl PacketEncoder { pub fn take(&mut self) -> BytesMut { #[cfg(feature = "encryption")] if let Some(cipher) = &mut self.cipher { - use aes::cipher::AsyncStreamCipher; - - cipher.encrypt(&mut self.buf); + for chunk in self.buf.chunks_mut(Cipher::block_size()) { + let gen_arr = GenericArray::from_mut_slice(chunk); + cipher.encrypt_block_mut(gen_arr); + } } self.buf.split() @@ -168,10 +173,8 @@ impl PacketEncoder { /// [taken]: Self::take #[cfg(feature = "encryption")] pub fn enable_encryption(&mut self, key: &[u8; 16]) { - use aes::cipher::NewCipher; - assert!(self.cipher.is_none(), "encryption is already enabled"); - self.cipher = Some(NewCipher::new(key.into(), key.into())); + self.cipher = Some(Cipher::new_from_slices(key, key).expect("invalid key")); } }