refactor: use strum on EncryptionAlgorithm, use Xor as default when AesGcm not available (#1923)

This commit is contained in:
Luna Yao
2026-03-25 11:42:34 +01:00
committed by GitHub
parent 1d89ddbb16
commit e2684a93de
14 changed files with 642 additions and 856 deletions
+41 -48
View File
@@ -1,10 +1,8 @@
use aes_gcm::aead::consts::{U12, U16};
use aes_gcm::aead::generic_array::GenericArray;
use aes_gcm::{AeadCore, AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit, Nonce, Tag};
use aes_gcm::{AeadCore, AeadInPlace, Aes128Gcm, Aes256Gcm, Key, KeyInit};
use rand::rngs::OsRng;
use zerocopy::{AsBytes, FromBytes};
use crate::tunnel::packet_def::{AesGcmTail, ZCPacket, AES_GCM_ENCRYPTION_RESERVED};
use crate::tunnel::packet_def::{StandardAeadTail, ZCPacket};
use super::{Encryptor, Error};
@@ -42,27 +40,28 @@ impl Encryptor for AesGcmCipher {
}
let payload_len = zc_packet.payload().len();
if payload_len < AES_GCM_ENCRYPTION_RESERVED {
if payload_len < StandardAeadTail::SIZE {
return Err(Error::PacketTooShort(zc_packet.payload().len()));
}
let text_len = payload_len - AES_GCM_ENCRYPTION_RESERVED;
let text_len = payload_len - StandardAeadTail::SIZE;
let aes_tail = AesGcmTail::ref_from_suffix(zc_packet.payload())
let aes_tail = StandardAeadTail::ref_from_suffix(zc_packet.payload())
.unwrap()
.clone();
let nonce: &GenericArray<u8, U12> = Nonce::from_slice(&aes_tail.nonce);
let tag: GenericArray<u8, U16> = Tag::clone_from_slice(aes_tail.tag.as_slice());
let nonce = aes_tail.nonce.into();
let tag = aes_tail.tag.into();
let rs = match &self.cipher {
AesGcmEnum::AES128GCM(aes_gcm) => aes_gcm.decrypt_in_place_detached(
nonce,
&nonce,
&[],
&mut zc_packet.mut_payload()[..text_len],
&tag,
),
AesGcmEnum::AES256GCM(aes_gcm) => aes_gcm.decrypt_in_place_detached(
nonce,
&nonce,
&[],
&mut zc_packet.mut_payload()[..text_len],
&tag,
@@ -79,7 +78,7 @@ impl Encryptor for AesGcmCipher {
let old_len = zc_packet.buf_len();
zc_packet
.mut_inner()
.truncate(old_len - AES_GCM_ENCRYPTION_RESERVED);
.truncate(old_len - StandardAeadTail::SIZE);
Ok(())
}
@@ -98,43 +97,40 @@ impl Encryptor for AesGcmCipher {
return Ok(());
}
let mut tail = AesGcmTail::default();
if let Some(nonce) = nonce {
if nonce.len() != tail.nonce.len() {
return Err(Error::EncryptionFailed);
}
tail.nonce.copy_from_slice(nonce);
}
let rs = match &self.cipher {
let nonce = nonce
.map(|n| {
<[u8; StandardAeadTail::NONCE_SIZE]>::try_from(n)
.map(Into::into)
.map_err(|_| Error::EncryptionFailed)
})
.transpose()?;
let (tag, nonce) = match &self.cipher {
AesGcmEnum::AES128GCM(aes_gcm) => {
if nonce.is_none() {
let nonce = Aes128Gcm::generate_nonce(&mut OsRng);
tail.nonce.copy_from_slice(nonce.as_slice());
}
let nonce = Nonce::from_slice(&tail.nonce);
aes_gcm.encrypt_in_place_detached(nonce, &[], zc_packet.mut_payload())
let nonce = nonce.unwrap_or_else(|| Aes128Gcm::generate_nonce(&mut OsRng));
(
aes_gcm.encrypt_in_place_detached(&nonce, &[], zc_packet.mut_payload()),
nonce,
)
}
AesGcmEnum::AES256GCM(aes_gcm) => {
if nonce.is_none() {
let nonce = Aes256Gcm::generate_nonce(&mut OsRng);
tail.nonce.copy_from_slice(nonce.as_slice());
}
let nonce = Nonce::from_slice(&tail.nonce);
aes_gcm.encrypt_in_place_detached(nonce, &[], zc_packet.mut_payload())
let nonce = nonce.unwrap_or_else(|| Aes256Gcm::generate_nonce(&mut OsRng));
(
aes_gcm.encrypt_in_place_detached(&nonce, &[], zc_packet.mut_payload()),
nonce,
)
}
};
match rs {
Ok(tag) => {
tail.tag.copy_from_slice(tag.as_slice());
let tail = StandardAeadTail {
tag: tag.map_err(|_| Error::EncryptionFailed)?.into(),
nonce: nonce.into(),
};
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
Ok(())
}
Err(_) => Err(Error::EncryptionFailed),
}
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
Ok(())
}
}
@@ -142,7 +138,7 @@ impl Encryptor for AesGcmCipher {
mod tests {
use crate::{
peers::encrypt::{aes_gcm::AesGcmCipher, Encryptor},
tunnel::packet_def::{AesGcmTail, ZCPacket, AES_GCM_ENCRYPTION_RESERVED},
tunnel::packet_def::{StandardAeadTail, ZCPacket},
};
use zerocopy::FromBytes;
@@ -154,10 +150,7 @@ mod tests {
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
cipher.encrypt(&mut packet).unwrap();
assert_eq!(
packet.payload().len(),
text.len() + AES_GCM_ENCRYPTION_RESERVED
);
assert_eq!(packet.payload().len(), text.len() + StandardAeadTail::SIZE);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
cipher.decrypt(&mut packet).unwrap();
@@ -186,7 +179,7 @@ mod tests {
assert_eq!(packet1.payload(), packet2.payload());
let tail = AesGcmTail::ref_from_suffix(packet1.payload()).unwrap();
let tail = StandardAeadTail::ref_from_suffix(packet1.payload()).unwrap();
assert_eq!(tail.nonce, nonce);
cipher.decrypt(&mut packet1).unwrap();
+50 -54
View File
@@ -1,23 +1,20 @@
use std::sync::Arc;
use crate::{
common::{config::EncryptionAlgorithm, log},
tunnel::packet_def::ZCPacket,
};
use cfg_if::cfg_if;
use std::sync::Arc;
#[cfg(feature = "wireguard")]
pub mod ring_aes_gcm;
#[cfg(feature = "wireguard")]
pub mod ring_chacha20;
pub mod ring;
#[cfg(feature = "aes-gcm")]
pub mod aes_gcm;
#[cfg(feature = "openssl-crypto")]
pub mod openssl_cipher;
pub mod openssl;
pub mod xor_cipher;
pub mod xor;
#[derive(thiserror::Error, Debug)]
pub enum Error {
@@ -32,6 +29,7 @@ pub enum Error {
}
pub trait Encryptor: Send + Sync + 'static {
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error>;
fn encrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error>;
fn encrypt_with_nonce(
&self,
@@ -40,16 +38,11 @@ pub trait Encryptor: Send + Sync + 'static {
) -> Result<(), Error> {
self.encrypt(zc_packet)
}
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error>;
}
pub struct NullCipher;
impl Encryptor for NullCipher {
fn encrypt(&self, _zc_packet: &mut ZCPacket) -> Result<(), Error> {
Ok(())
}
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if pm_header.is_encrypted() {
@@ -58,6 +51,10 @@ impl Encryptor for NullCipher {
Ok(())
}
}
fn encrypt(&self, _zc_packet: &mut ZCPacket) -> Result<(), Error> {
Ok(())
}
}
/// Create an encryptor based on the algorithm name
@@ -69,60 +66,59 @@ pub fn create_encryptor(
let algorithm = match EncryptionAlgorithm::try_from(algorithm) {
Ok(algorithm) => algorithm,
Err(_) => {
let default = EncryptionAlgorithm::default();
log::warn!(
"Unknown encryption algorithm: {}, falling back to default AES-GCM",
algorithm
"Unknown encryption algorithm: {}, falling back to default {}",
algorithm,
default
);
EncryptionAlgorithm::AesGcm
default
}
};
match algorithm {
EncryptionAlgorithm::Xor => Arc::new(xor::XorCipher::new(&key_128)),
#[cfg(any(feature = "aes-gcm", feature = "wireguard", feature = "openssl-crypto"))]
EncryptionAlgorithm::AesGcm => {
#[cfg(feature = "wireguard")]
{
Arc::new(ring_aes_gcm::AesGcmCipher::new_128(key_128))
}
#[cfg(all(feature = "aes-gcm", not(feature = "wireguard")))]
{
Arc::new(aes_gcm::AesGcmCipher::new_128(key_128))
}
#[cfg(all(not(feature = "wireguard"), not(feature = "aes-gcm")))]
{
compile_error!(
"wireguard or aes-gcm feature must be enabled for default encryption"
);
cfg_if! {
if #[cfg(feature = "openssl-crypto")] {
Arc::new(openssl::OpenSslCipher::new_aes128_gcm(key_128))
} else if #[cfg(feature = "wireguard")] {
Arc::new(ring::RingCipher::new_aes128_gcm(key_128))
} else if #[cfg(feature = "aes-gcm")] {
Arc::new(aes_gcm::AesGcmCipher::new_128(key_128))
} else {
compile_error!("unreachable!");
}
}
}
#[cfg(any(feature = "aes-gcm", feature = "wireguard", feature = "openssl-crypto"))]
EncryptionAlgorithm::Aes256Gcm => {
#[cfg(feature = "wireguard")]
{
Arc::new(ring_aes_gcm::AesGcmCipher::new_256(key_256))
}
#[cfg(all(feature = "aes-gcm", not(feature = "wireguard")))]
{
Arc::new(aes_gcm::AesGcmCipher::new_256(key_256))
cfg_if! {
if #[cfg(feature = "openssl-crypto")] {
Arc::new(openssl::OpenSslCipher::new_aes256_gcm(key_256))
} else if #[cfg(feature = "wireguard")] {
Arc::new(ring::RingCipher::new_aes256_gcm(key_256))
} else if #[cfg(feature = "aes-gcm")] {
Arc::new(aes_gcm::AesGcmCipher::new_256(key_256))
} else {
compile_error!("unreachable!");
}
}
}
EncryptionAlgorithm::Xor => Arc::new(xor_cipher::XorCipher::new(&key_128)),
#[cfg(feature = "wireguard")]
EncryptionAlgorithm::ChaCha20 => Arc::new(ring_chacha20::RingChaCha20Cipher::new(key_256)),
#[cfg(feature = "openssl-crypto")]
EncryptionAlgorithm::OpensslAesGcm => {
Arc::new(openssl_cipher::OpenSslCipher::new_aes128_gcm(key_128))
}
#[cfg(feature = "openssl-crypto")]
EncryptionAlgorithm::OpensslAes256Gcm => {
Arc::new(openssl_cipher::OpenSslCipher::new_aes256_gcm(key_256))
}
#[cfg(feature = "openssl-crypto")]
EncryptionAlgorithm::OpensslChacha20 => {
Arc::new(openssl_cipher::OpenSslCipher::new_chacha20(key_256))
#[cfg(any(feature = "wireguard", feature = "openssl-crypto"))]
EncryptionAlgorithm::ChaCha20 => {
cfg_if! {
if #[cfg(feature = "openssl-crypto")] {
Arc::new(openssl::OpenSslCipher::new_chacha20(key_256))
} else if #[cfg(feature = "wireguard")] {
Arc::new(ring::RingCipher::new_chacha20(key_256))
} else {
compile_error!("unreachable!");
}
}
}
}
}
+201
View File
@@ -0,0 +1,201 @@
use crate::tunnel::packet_def::{StandardAeadTail, ZCPacket};
use openssl::symm::{Cipher, Crypter, Mode};
use rand::RngCore;
use zerocopy::{AsBytes, FromBytes, FromZeroes};
use crate::peers::encrypt::{Encryptor, Error};
#[derive(Clone)]
pub struct OpenSslCipher {
pub(crate) cipher: OpenSslEnum,
}
#[derive(Clone, Copy)]
pub enum OpenSslEnum {
Aes128Gcm([u8; 16]),
Aes256Gcm([u8; 32]),
ChaCha20([u8; 32]),
}
impl OpenSslCipher {
pub fn new_aes128_gcm(key: [u8; 16]) -> Self {
Self {
cipher: OpenSslEnum::Aes128Gcm(key),
}
}
pub fn new_aes256_gcm(key: [u8; 32]) -> Self {
Self {
cipher: OpenSslEnum::Aes256Gcm(key),
}
}
pub fn new_chacha20(key: [u8; 32]) -> Self {
Self {
cipher: OpenSslEnum::ChaCha20(key),
}
}
fn get_cipher_and_key(&self) -> (Cipher, &[u8]) {
match &self.cipher {
OpenSslEnum::Aes128Gcm(key) => (Cipher::aes_128_gcm(), key.as_slice()),
OpenSslEnum::Aes256Gcm(key) => (Cipher::aes_256_gcm(), key.as_slice()),
OpenSslEnum::ChaCha20(key) => (Cipher::chacha20_poly1305(), key.as_slice()),
}
}
}
impl Encryptor for OpenSslCipher {
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if !pm_header.is_encrypted() {
return Ok(());
}
let payload = zc_packet.payload();
let len = payload.len();
if len < StandardAeadTail::SIZE {
return Err(Error::PacketTooShort(len));
}
let (cipher, key) = self.get_cipher_and_key();
// 提取 nonce/IV 和 tag
let tail = StandardAeadTail::ref_from_suffix(payload).unwrap();
let mut decrypter = Crypter::new(cipher, Mode::Decrypt, key, Some(&tail.nonce))
.map_err(|_| Error::DecryptionFailed)?;
decrypter
.set_tag(&tail.tag)
.map_err(|_| Error::DecryptionFailed)?;
let text_len = len - StandardAeadTail::SIZE;
let mut output = vec![0u8; text_len + cipher.block_size()];
let mut count = decrypter
.update(&payload[..text_len], &mut output)
.map_err(|_| Error::DecryptionFailed)?;
count += decrypter
.finalize(&mut output[count..])
.map_err(|_| Error::DecryptionFailed)?;
// 更新数据包
zc_packet.mut_payload()[..count].copy_from_slice(&output[..count]);
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(false);
let len = zc_packet.buf_len() - (len - count);
zc_packet.mut_inner().truncate(len);
Ok(())
}
fn encrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
self.encrypt_with_nonce(zc_packet, None)
}
fn encrypt_with_nonce(
&self,
zc_packet: &mut ZCPacket,
nonce: Option<&[u8]>,
) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if pm_header.is_encrypted() {
tracing::warn!(?zc_packet, "packet is already encrypted");
return Ok(());
}
let (cipher, key) = self.get_cipher_and_key();
let mut tail = StandardAeadTail::new_zeroed();
if let Some(nonce) = nonce {
if nonce.len() != StandardAeadTail::NONCE_SIZE {
return Err(Error::EncryptionFailed);
}
tail.nonce.copy_from_slice(nonce);
} else {
rand::thread_rng().fill_bytes(&mut tail.nonce);
}
let mut encrypter = Crypter::new(cipher, Mode::Encrypt, key, Some(&tail.nonce))
.map_err(|_| Error::EncryptionFailed)?;
let payload_len = zc_packet.payload().len();
let mut output = vec![0u8; payload_len + cipher.block_size()];
let mut count = encrypter
.update(zc_packet.payload(), &mut output)
.map_err(|_| Error::EncryptionFailed)?;
count += encrypter
.finalize(&mut output[count..])
.map_err(|_| Error::EncryptionFailed)?;
// 更新数据包内容
zc_packet.mut_payload()[..count].copy_from_slice(&output[..count]);
encrypter
.get_tag(&mut tail.tag)
.map_err(|_| Error::EncryptionFailed)?;
// 添加 nonce/IV & tag 的结构
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn run_cipher_test_with_nonce(cipher: OpenSslCipher) {
let text = b"Hello, World! This is a standardized test message.";
let nonce: [u8; 12] = [101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112];
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet, Some(&nonce))
.unwrap();
let payload = packet.payload();
let len = payload.len();
assert!(len > text.len() + StandardAeadTail::SIZE - 1);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
let tail = StandardAeadTail::ref_from_suffix(payload).unwrap().clone();
assert_eq!(tail.nonce, nonce);
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
#[test]
fn test_openssl_aes128_gcm() {
let key = [1u8; 16];
let cipher = OpenSslCipher::new_aes128_gcm(key);
run_cipher_test_with_nonce(cipher);
}
#[test]
fn test_openssl_aes256_gcm() {
let key = [2u8; 32];
let cipher = OpenSslCipher::new_aes256_gcm(key);
run_cipher_test_with_nonce(cipher);
}
#[test]
fn test_openssl_chacha20() {
let key = [3u8; 32];
let cipher = OpenSslCipher::new_chacha20(key);
run_cipher_test_with_nonce(cipher);
}
}
@@ -1,288 +0,0 @@
use openssl::symm::{Cipher, Crypter, Mode};
use rand::RngCore;
use zerocopy::{AsBytes, FromBytes, FromZeroes};
use crate::tunnel::packet_def::ZCPacket;
use crate::peers::encrypt::{Encryptor, Error};
// OpenSSL 加密尾部结构
#[repr(C, packed)]
#[derive(AsBytes, FromBytes, FromZeroes, Clone, Debug, Default)]
pub struct OpenSslTail {
pub nonce: [u8; 16], // 使用 16 字节的 nonce/IV
}
pub const OPENSSL_ENCRYPTION_RESERVED: usize = std::mem::size_of::<OpenSslTail>();
#[derive(Clone)]
pub struct OpenSslCipher {
pub(crate) cipher: OpenSslEnum,
}
pub enum OpenSslEnum {
Aes128Gcm([u8; 16]),
Aes256Gcm([u8; 32]),
Chacha20([u8; 32]),
}
impl Clone for OpenSslEnum {
fn clone(&self) -> Self {
match &self {
OpenSslEnum::Aes128Gcm(key) => OpenSslEnum::Aes128Gcm(*key),
OpenSslEnum::Aes256Gcm(key) => OpenSslEnum::Aes256Gcm(*key),
OpenSslEnum::Chacha20(key) => OpenSslEnum::Chacha20(*key),
}
}
}
impl OpenSslCipher {
pub fn new_aes128_gcm(key: [u8; 16]) -> Self {
Self {
cipher: OpenSslEnum::Aes128Gcm(key),
}
}
pub fn new_aes256_gcm(key: [u8; 32]) -> Self {
Self {
cipher: OpenSslEnum::Aes256Gcm(key),
}
}
pub fn new_chacha20(key: [u8; 32]) -> Self {
Self {
cipher: OpenSslEnum::Chacha20(key),
}
}
fn get_cipher_and_key(&self) -> (Cipher, &[u8]) {
match &self.cipher {
OpenSslEnum::Aes128Gcm(key) => (Cipher::aes_128_gcm(), key.as_slice()),
OpenSslEnum::Aes256Gcm(key) => (Cipher::aes_256_gcm(), key.as_slice()),
OpenSslEnum::Chacha20(key) => (Cipher::chacha20_poly1305(), key.as_slice()),
}
}
fn is_aead_cipher(&self) -> bool {
matches!(
self.cipher,
OpenSslEnum::Aes128Gcm(_) | OpenSslEnum::Aes256Gcm(_) | OpenSslEnum::Chacha20(_)
)
}
fn get_nonce_size(&self) -> usize {
match &self.cipher {
OpenSslEnum::Aes128Gcm(_) | OpenSslEnum::Aes256Gcm(_) | OpenSslEnum::Chacha20(_) => 12, // GCM and ChaCha20-Poly1305 use 12-byte nonce
}
}
}
impl Encryptor for OpenSslCipher {
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if !pm_header.is_encrypted() {
return Ok(());
}
let payload_len = zc_packet.payload().len();
if payload_len < OPENSSL_ENCRYPTION_RESERVED {
return Err(Error::PacketTooShort(zc_packet.payload().len()));
}
let (cipher, key) = self.get_cipher_and_key();
let is_aead = self.is_aead_cipher();
let nonce_size = self.get_nonce_size();
// 提取 nonce/IV
let openssl_tail = OpenSslTail::ref_from_suffix(zc_packet.payload())
.unwrap()
.clone();
let text_len = if is_aead {
payload_len - OPENSSL_ENCRYPTION_RESERVED - 16 // AEAD 需要减去 tag 长度
} else {
payload_len - OPENSSL_ENCRYPTION_RESERVED
};
let mut decrypter = Crypter::new(
cipher,
Mode::Decrypt,
key,
Some(&openssl_tail.nonce[..nonce_size]),
)
.map_err(|_| Error::DecryptionFailed)?;
if is_aead {
// 对于 AEAD 模式,需要设置 tag
let tag_start = text_len;
let tag = &zc_packet.payload()[tag_start..tag_start + 16];
decrypter
.set_tag(tag)
.map_err(|_| Error::DecryptionFailed)?;
}
let mut output = vec![0u8; text_len + cipher.block_size()];
let mut count = decrypter
.update(&zc_packet.payload()[..text_len], &mut output)
.map_err(|_| Error::DecryptionFailed)?;
count += decrypter
.finalize(&mut output[count..])
.map_err(|_| Error::DecryptionFailed)?;
// 更新数据包
zc_packet.mut_payload()[..count].copy_from_slice(&output[..count]);
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(false);
let old_len = zc_packet.buf_len();
let new_len = old_len - (payload_len - count);
zc_packet.mut_inner().truncate(new_len);
Ok(())
}
fn encrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
self.encrypt_with_nonce(zc_packet, None)
}
fn encrypt_with_nonce(
&self,
zc_packet: &mut ZCPacket,
nonce: Option<&[u8]>,
) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if pm_header.is_encrypted() {
tracing::warn!(?zc_packet, "packet is already encrypted");
return Ok(());
}
let (cipher, key) = self.get_cipher_and_key();
let is_aead = self.is_aead_cipher();
let nonce_size = self.get_nonce_size();
let mut tail = OpenSslTail::default();
if let Some(nonce) = nonce {
if nonce.len() != nonce_size {
return Err(Error::EncryptionFailed);
}
tail.nonce[..nonce_size].copy_from_slice(nonce);
} else {
rand::thread_rng().fill_bytes(&mut tail.nonce[..nonce_size]);
}
let mut encrypter =
Crypter::new(cipher, Mode::Encrypt, key, Some(&tail.nonce[..nonce_size]))
.map_err(|_| Error::EncryptionFailed)?;
let payload_len = zc_packet.payload().len();
let mut output = vec![0u8; payload_len + cipher.block_size()];
let mut count = encrypter
.update(zc_packet.payload(), &mut output)
.map_err(|_| Error::EncryptionFailed)?;
count += encrypter
.finalize(&mut output[count..])
.map_err(|_| Error::EncryptionFailed)?;
// 更新数据包内容
zc_packet.mut_payload()[..count].copy_from_slice(&output[..count]);
// 对于 AEAD 模式,添加 tag
if is_aead {
let mut tag = vec![0u8; 16]; // GCM 标签通常是 16 字节
encrypter
.get_tag(&mut tag)
.map_err(|_| Error::EncryptionFailed)?;
zc_packet.mut_inner().extend_from_slice(&tag);
}
// 添加 nonce/IV
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::{
peers::encrypt::{openssl_cipher::OpenSslCipher, Encryptor},
tunnel::packet_def::ZCPacket,
};
use zerocopy::FromBytes;
use super::OPENSSL_ENCRYPTION_RESERVED;
#[test]
fn test_openssl_aes128_gcm() {
let key = [0u8; 16];
let cipher = OpenSslCipher::new_aes128_gcm(key);
let text = b"Hello, World! This is a test message for OpenSSL AES-128-GCM.";
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
// 加密
cipher.encrypt(&mut packet).unwrap();
assert!(packet.payload().len() > text.len() + OPENSSL_ENCRYPTION_RESERVED);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
// 解密
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
#[test]
fn test_openssl_aes128_gcm_with_nonce() {
let key = [7u8; 16];
let cipher = OpenSslCipher::new_aes128_gcm(key);
let text = b"Hello";
let nonce = [3u8; 12];
let mut packet1 = ZCPacket::new_with_payload(text);
packet1.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet1, Some(&nonce))
.unwrap();
let mut packet2 = ZCPacket::new_with_payload(text);
packet2.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet2, Some(&nonce))
.unwrap();
assert_eq!(packet1.payload(), packet2.payload());
assert!(packet1.payload().len() > text.len() + OPENSSL_ENCRYPTION_RESERVED);
let tail = super::OpenSslTail::ref_from_suffix(packet1.payload())
.unwrap()
.clone();
assert_eq!(&tail.nonce[..nonce.len()], nonce);
cipher.decrypt(&mut packet1).unwrap();
assert_eq!(packet1.payload(), text);
}
#[test]
fn test_openssl_chacha20() {
let key = [0u8; 32];
let cipher = OpenSslCipher::new_chacha20(key);
let text = b"Hello, World! This is a test message for OpenSSL ChaCha20.";
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
// 加密
cipher.encrypt(&mut packet).unwrap();
assert!(packet.payload().len() > text.len());
assert!(packet.peer_manager_header().unwrap().is_encrypted());
// 解密
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
}
+252
View File
@@ -0,0 +1,252 @@
use rand::RngCore;
use ring::aead::{self};
use ring::aead::{LessSafeKey, UnboundKey};
use zerocopy::{AsBytes, FromBytes, FromZeroes};
use crate::tunnel::packet_def::{StandardAeadTail, ZCPacket};
use super::{Encryptor, Error};
#[derive(Clone)]
pub struct RingCipher {
pub(crate) cipher: RingEnum,
}
pub enum RingEnum {
Aes128Gcm(LessSafeKey, [u8; 16]),
Aes256Gcm(LessSafeKey, [u8; 32]),
ChaCha20(LessSafeKey, [u8; 32]),
}
impl RingEnum {
fn get_cipher(&self) -> &LessSafeKey {
match &self {
RingEnum::Aes128Gcm(cipher, _) => cipher,
RingEnum::Aes256Gcm(cipher, _) => cipher,
RingEnum::ChaCha20(cipher, _) => cipher,
}
}
}
impl Clone for RingEnum {
fn clone(&self) -> Self {
match &self {
RingEnum::Aes128Gcm(_, key) => {
let c =
LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
RingEnum::Aes128Gcm(c, *key)
}
RingEnum::Aes256Gcm(_, key) => {
let c =
LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
RingEnum::Aes256Gcm(c, *key)
}
RingEnum::ChaCha20(_, key) => {
let c = LessSafeKey::new(
UnboundKey::new(&aead::CHACHA20_POLY1305, key.as_slice()).unwrap(),
);
RingEnum::ChaCha20(c, *key)
}
}
}
}
impl RingCipher {
pub fn new_aes128_gcm(key: [u8; 16]) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key).unwrap());
Self {
cipher: RingEnum::Aes128Gcm(cipher, key),
}
}
pub fn new_aes256_gcm(key: [u8; 32]) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
Self {
cipher: RingEnum::Aes256Gcm(cipher, key),
}
}
pub fn new_chacha20(key: [u8; 32]) -> Self {
let unbound_key = UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
let cipher = LessSafeKey::new(unbound_key);
Self {
cipher: RingEnum::ChaCha20(cipher, key),
}
}
}
impl Encryptor for RingCipher {
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if !pm_header.is_encrypted() {
return Ok(());
}
let payload_len = zc_packet.payload().len();
if payload_len < StandardAeadTail::SIZE {
return Err(Error::PacketTooShort(zc_packet.payload().len()));
}
let text_and_tag_len = payload_len - StandardAeadTail::SIZE + StandardAeadTail::TAG_SIZE;
let aes_tail = StandardAeadTail::ref_from_suffix(zc_packet.payload()).unwrap();
let nonce = aead::Nonce::assume_unique_for_key(aes_tail.nonce);
self.cipher
.get_cipher()
.open_in_place(
nonce,
aead::Aad::empty(),
&mut zc_packet.mut_payload()[..text_and_tag_len],
)
.map_err(|_| Error::DecryptionFailed)?;
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(false);
let old_len = zc_packet.buf_len();
zc_packet
.mut_inner()
.truncate(old_len - StandardAeadTail::SIZE);
Ok(())
}
fn encrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
self.encrypt_with_nonce(zc_packet, None)
}
fn encrypt_with_nonce(
&self,
zc_packet: &mut ZCPacket,
nonce: Option<&[u8]>,
) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if pm_header.is_encrypted() {
tracing::warn!(?zc_packet, "packet is already encrypted");
return Ok(());
}
let mut tail = StandardAeadTail::new_zeroed();
match nonce {
Some(n) => tail.nonce = n.try_into().map_err(|_| Error::EncryptionFailed)?,
None => rand::thread_rng().fill_bytes(&mut tail.nonce),
}
let nonce = aead::Nonce::assume_unique_for_key(tail.nonce);
let tag = self
.cipher
.get_cipher()
.seal_in_place_separate_tag(nonce, aead::Aad::empty(), zc_packet.mut_payload())
.map_err(|_| Error::EncryptionFailed)?;
let tag = tag.as_ref();
if tag.len() != StandardAeadTail::TAG_SIZE {
return Err(Error::InvalidTag(tag.to_vec()));
}
tail.tag.copy_from_slice(tag);
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::{
peers::encrypt::{ring::RingCipher, Encryptor},
tunnel::packet_def::{StandardAeadTail, ZCPacket},
};
use zerocopy::FromBytes;
#[test]
fn test_aes_gcm_cipher() {
let key = [0u8; 16];
let cipher = RingCipher::new_aes128_gcm(key);
let text = b"1234567";
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
cipher.encrypt(&mut packet).unwrap();
assert_eq!(packet.payload().len(), text.len() + StandardAeadTail::SIZE);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
#[test]
fn test_aes_gcm_cipher_with_nonce() {
let key = [7u8; 16];
let cipher = RingCipher::new_aes128_gcm(key);
let text = b"Hello";
let nonce = [3u8; 12];
let mut packet1 = ZCPacket::new_with_payload(text);
packet1.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet1, Some(&nonce))
.unwrap();
let mut packet2 = ZCPacket::new_with_payload(text);
packet2.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet2, Some(&nonce))
.unwrap();
assert_eq!(packet1.payload(), packet2.payload());
let tail = StandardAeadTail::ref_from_suffix(packet1.payload()).unwrap();
assert_eq!(tail.nonce, nonce);
cipher.decrypt(&mut packet1).unwrap();
assert_eq!(packet1.payload(), text);
}
#[test]
fn test_ring_chacha20_cipher() {
let key = [0u8; 32];
let cipher = RingCipher::new_chacha20(key);
let text = b"Hello, World! This is a test message for Ring ChaCha20-Poly1305.";
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
cipher.encrypt(&mut packet).unwrap();
assert_eq!(packet.payload().len(), text.len() + StandardAeadTail::SIZE);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
#[test]
fn test_ring_chacha20_cipher_with_nonce() {
let key = [9u8; 32];
let cipher = RingCipher::new_chacha20(key);
let text = b"Hello";
let nonce = [5u8; 12];
let mut packet1 = ZCPacket::new_with_payload(text);
packet1.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet1, Some(&nonce))
.unwrap();
let mut packet2 = ZCPacket::new_with_payload(text);
packet2.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet2, Some(&nonce))
.unwrap();
assert_eq!(packet1.payload(), packet2.payload());
let tail = StandardAeadTail::ref_from_suffix(packet1.payload()).unwrap();
assert_eq!(tail.nonce, nonce);
cipher.decrypt(&mut packet1).unwrap();
assert_eq!(packet1.payload(), text);
assert!(!packet1.peer_manager_header().unwrap().is_encrypted());
}
}
-205
View File
@@ -1,205 +0,0 @@
use rand::RngCore;
use ring::aead::{self};
use ring::aead::{LessSafeKey, UnboundKey};
use zerocopy::{AsBytes, FromBytes};
use crate::tunnel::packet_def::{AesGcmTail, ZCPacket, AES_GCM_ENCRYPTION_RESERVED};
use super::{Encryptor, Error};
#[derive(Clone)]
pub struct AesGcmCipher {
pub(crate) cipher: AesGcmEnum,
}
pub enum AesGcmEnum {
AesGCM128(LessSafeKey, [u8; 16]),
AesGCM256(LessSafeKey, [u8; 32]),
}
impl Clone for AesGcmEnum {
fn clone(&self) -> Self {
match &self {
AesGcmEnum::AesGCM128(_, key) => {
let c =
LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, key.as_slice()).unwrap());
AesGcmEnum::AesGCM128(c, *key)
}
AesGcmEnum::AesGCM256(_, key) => {
let c =
LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, key.as_slice()).unwrap());
AesGcmEnum::AesGCM256(c, *key)
}
}
}
}
impl AesGcmCipher {
pub fn new_128(key: [u8; 16]) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_128_GCM, &key).unwrap());
Self {
cipher: AesGcmEnum::AesGCM128(cipher, key),
}
}
pub fn new_256(key: [u8; 32]) -> Self {
let cipher = LessSafeKey::new(UnboundKey::new(&aead::AES_256_GCM, &key).unwrap());
Self {
cipher: AesGcmEnum::AesGCM256(cipher, key),
}
}
}
impl Encryptor for AesGcmCipher {
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if !pm_header.is_encrypted() {
return Ok(());
}
let payload_len = zc_packet.payload().len();
if payload_len < AES_GCM_ENCRYPTION_RESERVED {
return Err(Error::PacketTooShort(zc_packet.payload().len()));
}
let text_and_tag_len = payload_len - AES_GCM_ENCRYPTION_RESERVED + 16;
let aes_tail = AesGcmTail::ref_from_suffix(zc_packet.payload()).unwrap();
let nonce = aead::Nonce::assume_unique_for_key(aes_tail.nonce);
let rs = match &self.cipher {
AesGcmEnum::AesGCM128(cipher, _) => cipher.open_in_place(
nonce,
aead::Aad::empty(),
&mut zc_packet.mut_payload()[..text_and_tag_len],
),
AesGcmEnum::AesGCM256(cipher, _) => cipher.open_in_place(
nonce,
aead::Aad::empty(),
&mut zc_packet.mut_payload()[..text_and_tag_len],
),
};
if rs.is_err() {
return Err(Error::DecryptionFailed);
}
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(false);
let old_len = zc_packet.buf_len();
zc_packet
.mut_inner()
.truncate(old_len - AES_GCM_ENCRYPTION_RESERVED);
Ok(())
}
fn encrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
self.encrypt_with_nonce(zc_packet, None)
}
fn encrypt_with_nonce(
&self,
zc_packet: &mut ZCPacket,
nonce: Option<&[u8]>,
) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if pm_header.is_encrypted() {
tracing::warn!(?zc_packet, "packet is already encrypted");
return Ok(());
}
let mut tail = AesGcmTail::default();
if let Some(nonce) = nonce {
if nonce.len() != tail.nonce.len() {
return Err(Error::EncryptionFailed);
}
tail.nonce.copy_from_slice(nonce);
} else {
rand::thread_rng().fill_bytes(&mut tail.nonce);
}
let nonce = aead::Nonce::assume_unique_for_key(tail.nonce);
let rs = match &self.cipher {
AesGcmEnum::AesGCM128(cipher, _) => cipher.seal_in_place_separate_tag(
nonce,
aead::Aad::empty(),
zc_packet.mut_payload(),
),
AesGcmEnum::AesGCM256(cipher, _) => cipher.seal_in_place_separate_tag(
nonce,
aead::Aad::empty(),
zc_packet.mut_payload(),
),
};
match rs {
Ok(tag) => {
let tag = tag.as_ref();
if tag.len() != 16 {
return Err(Error::InvalidTag(tag.to_vec()));
}
tail.tag.copy_from_slice(tag);
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
Ok(())
}
Err(_) => Err(Error::EncryptionFailed),
}
}
}
#[cfg(test)]
mod tests {
use crate::{
peers::encrypt::{ring_aes_gcm::AesGcmCipher, Encryptor},
tunnel::packet_def::{AesGcmTail, ZCPacket, AES_GCM_ENCRYPTION_RESERVED},
};
use zerocopy::FromBytes;
#[test]
fn test_aes_gcm_cipher() {
let key = [0u8; 16];
let cipher = AesGcmCipher::new_128(key);
let text = b"1234567";
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
cipher.encrypt(&mut packet).unwrap();
assert_eq!(
packet.payload().len(),
text.len() + AES_GCM_ENCRYPTION_RESERVED
);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
#[test]
fn test_aes_gcm_cipher_with_nonce() {
let key = [7u8; 16];
let cipher = AesGcmCipher::new_128(key);
let text = b"Hello";
let nonce = [3u8; 12];
let mut packet1 = ZCPacket::new_with_payload(text);
packet1.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet1, Some(&nonce))
.unwrap();
let mut packet2 = ZCPacket::new_with_payload(text);
packet2.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet2, Some(&nonce))
.unwrap();
assert_eq!(packet1.payload(), packet2.payload());
let tail = AesGcmTail::ref_from_suffix(packet1.payload()).unwrap();
assert_eq!(tail.nonce, nonce);
cipher.decrypt(&mut packet1).unwrap();
assert_eq!(packet1.payload(), text);
}
}
-170
View File
@@ -1,170 +0,0 @@
use rand::RngCore;
use ring::aead::{self, Aad, LessSafeKey, Nonce, UnboundKey};
use zerocopy::{AsBytes, FromBytes, FromZeroes};
use super::{Encryptor, Error};
use crate::tunnel::packet_def::ZCPacket;
#[repr(C, packed)]
#[derive(AsBytes, FromBytes, FromZeroes, Clone, Debug, Default)]
pub struct ChaCha20Poly1305Tail {
pub tag: [u8; 16],
pub nonce: [u8; 12],
}
pub const CHACHA20_POLY1305_ENCRYPTION_RESERVED: usize =
std::mem::size_of::<ChaCha20Poly1305Tail>();
#[derive(Clone)]
pub struct RingChaCha20Cipher {
cipher: LessSafeKey,
key: [u8; 32],
}
impl RingChaCha20Cipher {
pub fn new(key: [u8; 32]) -> Self {
let unbound_key = UnboundKey::new(&aead::CHACHA20_POLY1305, &key).unwrap();
let cipher = LessSafeKey::new(unbound_key);
Self { cipher, key }
}
}
impl Encryptor for RingChaCha20Cipher {
fn decrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if !pm_header.is_encrypted() {
return Ok(());
}
let payload_len = zc_packet.payload().len();
if payload_len < CHACHA20_POLY1305_ENCRYPTION_RESERVED {
return Err(Error::PacketTooShort(zc_packet.payload().len()));
}
let text_and_tag_len = payload_len - CHACHA20_POLY1305_ENCRYPTION_RESERVED + 16;
let chacha20_tail = ChaCha20Poly1305Tail::ref_from_suffix(zc_packet.payload()).unwrap();
let nonce = Nonce::assume_unique_for_key(chacha20_tail.nonce);
let rs = self.cipher.open_in_place(
nonce,
Aad::empty(),
&mut zc_packet.mut_payload()[..text_and_tag_len],
);
if rs.is_err() {
return Err(Error::DecryptionFailed);
}
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(false);
let old_len = zc_packet.buf_len();
zc_packet
.mut_inner()
.truncate(old_len - CHACHA20_POLY1305_ENCRYPTION_RESERVED);
Ok(())
}
fn encrypt(&self, zc_packet: &mut ZCPacket) -> Result<(), Error> {
self.encrypt_with_nonce(zc_packet, None)
}
fn encrypt_with_nonce(
&self,
zc_packet: &mut ZCPacket,
nonce: Option<&[u8]>,
) -> Result<(), Error> {
let pm_header = zc_packet.peer_manager_header().unwrap();
if pm_header.is_encrypted() {
tracing::warn!(?zc_packet, "packet is already encrypted");
return Ok(());
}
let mut tail = ChaCha20Poly1305Tail::default();
if let Some(nonce) = nonce {
if nonce.len() != tail.nonce.len() {
return Err(Error::EncryptionFailed);
}
tail.nonce.copy_from_slice(nonce);
} else {
rand::thread_rng().fill_bytes(&mut tail.nonce);
}
let nonce = Nonce::assume_unique_for_key(tail.nonce);
let rs =
self.cipher
.seal_in_place_separate_tag(nonce, Aad::empty(), zc_packet.mut_payload());
match rs {
Ok(tag) => {
tail.tag.copy_from_slice(tag.as_ref());
let pm_header = zc_packet.mut_peer_manager_header().unwrap();
pm_header.set_encrypted(true);
zc_packet.mut_inner().extend_from_slice(tail.as_bytes());
Ok(())
}
Err(_) => Err(Error::EncryptionFailed),
}
}
}
#[cfg(test)]
mod tests {
use crate::{
peers::encrypt::{ring_chacha20::RingChaCha20Cipher, Encryptor},
tunnel::packet_def::ZCPacket,
};
use zerocopy::FromBytes;
use super::CHACHA20_POLY1305_ENCRYPTION_RESERVED;
#[test]
fn test_ring_chacha20_cipher() {
let key = [0u8; 32];
let cipher = RingChaCha20Cipher::new(key);
let text = b"Hello, World! This is a test message for Ring ChaCha20-Poly1305.";
let mut packet = ZCPacket::new_with_payload(text);
packet.fill_peer_manager_hdr(0, 0, 0);
cipher.encrypt(&mut packet).unwrap();
assert_eq!(
packet.payload().len(),
text.len() + CHACHA20_POLY1305_ENCRYPTION_RESERVED
);
assert!(packet.peer_manager_header().unwrap().is_encrypted());
cipher.decrypt(&mut packet).unwrap();
assert_eq!(packet.payload(), text);
assert!(!packet.peer_manager_header().unwrap().is_encrypted());
}
#[test]
fn test_ring_chacha20_cipher_with_nonce() {
let key = [9u8; 32];
let cipher = RingChaCha20Cipher::new(key);
let text = b"Hello";
let nonce = [5u8; 12];
let mut packet1 = ZCPacket::new_with_payload(text);
packet1.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet1, Some(&nonce))
.unwrap();
let mut packet2 = ZCPacket::new_with_payload(text);
packet2.fill_peer_manager_hdr(0, 0, 0);
cipher
.encrypt_with_nonce(&mut packet2, Some(&nonce))
.unwrap();
assert_eq!(packet1.payload(), packet2.payload());
let tail = super::ChaCha20Poly1305Tail::ref_from_suffix(packet1.payload()).unwrap();
assert_eq!(tail.nonce, nonce);
cipher.decrypt(&mut packet1).unwrap();
assert_eq!(packet1.payload(), text);
assert!(!packet1.peer_manager_header().unwrap().is_encrypted());
}
}
@@ -61,7 +61,7 @@ impl Encryptor for XorCipher {
#[cfg(test)]
mod tests {
use crate::{
peers::encrypt::{xor_cipher::XorCipher, Encryptor},
peers::encrypt::{xor::XorCipher, Encryptor},
tunnel::packet_def::ZCPacket,
};
+8 -14
View File
@@ -8,17 +8,17 @@ use std::{
use atomic_shim::AtomicU64;
use crate::{
common::PeerId,
peers::encrypt::{create_encryptor, Encryptor},
tunnel::packet_def::{StandardAeadTail, ZCPacket},
};
use anyhow::anyhow;
use dashmap::DashMap;
use hmac::{Hmac, Mac as _};
use rand::RngCore as _;
use sha2::Sha256;
use crate::{
common::PeerId,
peers::encrypt::{create_encryptor, Encryptor},
tunnel::packet_def::{AesGcmTail, ZCPacket},
};
use zerocopy::FromBytes;
type HmacSha256 = Hmac<Sha256>;
pub struct UpsertResponderSessionReturn {
@@ -733,14 +733,8 @@ impl PeerSession {
}
fn parse_tail(payload: &[u8]) -> Option<[u8; 12]> {
if payload.len() < std::mem::size_of::<AesGcmTail>() {
return None;
}
let tail_off = payload.len() - std::mem::size_of::<AesGcmTail>();
let tail = &payload[tail_off..];
let mut nonce = [0u8; 12];
nonce.copy_from_slice(&tail[16..]);
Some(nonce)
let tail = StandardAeadTail::ref_from_suffix(payload)?;
Some(tail.nonce)
}
fn evict_old_rx_slots(rx: &mut [[EpochRxSlot; 2]; 2], now_ms: u64) {