1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
use bytes::BytesMut; use chacha20poly1305::{ aead::{AeadInPlace, NewAead}, ChaCha8Poly1305, Key, Nonce, Tag, }; use quinn_proto::crypto::{CryptoError, HeaderKey, KeyPair, PacketKey}; pub const HEADER_KEYPAIR: KeyPair<PlaintextHeaderKey> = KeyPair { local: PlaintextHeaderKey, remote: PlaintextHeaderKey, }; #[derive(Clone)] pub struct ChaCha8PacketKey(ChaCha8Poly1305); impl ChaCha8PacketKey { pub fn new(key: [u8; 32]) -> Self { let key = Key::from(key); Self(ChaCha8Poly1305::new(&key)) } } impl PacketKey for ChaCha8PacketKey { fn encrypt(&self, packet: u64, buf: &mut [u8], header_len: usize) { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&packet.to_le_bytes()); let nonce = Nonce::from(nonce); let (header, payload) = buf.split_at_mut(header_len); let (content, auth) = payload.split_at_mut(payload.len() - self.tag_len()); let tag = self .0 .encrypt_in_place_detached(&nonce, header, content) .unwrap(); auth.copy_from_slice(&tag); } fn decrypt( &self, packet: u64, header: &[u8], payload: &mut BytesMut, ) -> Result<(), CryptoError> { let mut nonce = [0; 12]; nonce[4..].copy_from_slice(&packet.to_le_bytes()); let nonce = Nonce::from(nonce); let len = payload.len() - self.tag_len(); let (content, tag) = payload.split_at_mut(len); let tag = Tag::from_slice(tag); self.0 .decrypt_in_place_detached(&nonce, header, content, tag) .map_err(|_| CryptoError)?; payload.truncate(len); Ok(()) } fn tag_len(&self) -> usize { 16 } fn confidentiality_limit(&self) -> u64 { u64::MAX } fn integrity_limit(&self) -> u64 { u64::MAX } } pub struct PlaintextHeaderKey; impl HeaderKey for PlaintextHeaderKey { fn decrypt(&self, _pn_offset: usize, _packet: &mut [u8]) {} fn encrypt(&self, _pn_offset: usize, _packet: &mut [u8]) {} fn sample_size(&self) -> usize { 0 } }