use std::fmt::Display;
use std::ops::Index;
use std::ops::IndexMut;
use std::ops::RangeInclusive;
use std::time;
use ring::aead;
use crate::Error;
use crate::Result;
use crate::crypto;
use crate::rand;
use crate::ranges;
use crate::stream;
const FORM_BIT: u8 = 0x80;
const FIXED_BIT: u8 = 0x40;
const KEY_PHASE_BIT: u8 = 0x04;
const TYPE_MASK: u8 = 0x30;
const PKT_NUM_MASK: u8 = 0x03;
pub const MAX_CID_LEN: u8 = 20;
pub const MAX_PKT_NUM_LEN: usize = 4;
const SAMPLE_LEN: usize = 16;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub enum Epoch {
Initial = 0,
Handshake = 1,
Application = 2,
}
static EPOCHS: [Epoch; 3] =
[Epoch::Initial, Epoch::Handshake, Epoch::Application];
impl Epoch {
pub fn epochs(range: RangeInclusive<Epoch>) -> &'static [Epoch] {
&EPOCHS[*range.start() as usize..=*range.end() as usize]
}
pub const fn count() -> usize {
3
}
}
impl Display for Epoch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", usize::from(*self))
}
}
impl From<Epoch> for usize {
fn from(e: Epoch) -> Self {
e as usize
}
}
impl<T> Index<Epoch> for [T]
where
T: Sized,
{
type Output = T;
fn index(&self, index: Epoch) -> &Self::Output {
self.index(usize::from(index))
}
}
impl<T> IndexMut<Epoch> for [T]
where
T: Sized,
{
fn index_mut(&mut self, index: Epoch) -> &mut Self::Output {
self.index_mut(usize::from(index))
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Type {
Initial,
Retry,
Handshake,
ZeroRTT,
VersionNegotiation,
Short,
}
impl Type {
pub(crate) fn from_epoch(e: Epoch) -> Type {
match e {
Epoch::Initial => Type::Initial,
Epoch::Handshake => Type::Handshake,
Epoch::Application => Type::Short,
}
}
pub(crate) fn to_epoch(self) -> Result<Epoch> {
match self {
Type::Initial => Ok(Epoch::Initial),
Type::ZeroRTT => Ok(Epoch::Application),
Type::Handshake => Ok(Epoch::Handshake),
Type::Short => Ok(Epoch::Application),
_ => Err(Error::InvalidPacket),
}
}
#[cfg(feature = "qlog")]
pub(crate) fn to_qlog(self) -> qlog::events::quic::PacketType {
match self {
Type::Initial => qlog::events::quic::PacketType::Initial,
Type::Retry => qlog::events::quic::PacketType::Retry,
Type::Handshake => qlog::events::quic::PacketType::Handshake,
Type::ZeroRTT => qlog::events::quic::PacketType::ZeroRtt,
Type::VersionNegotiation =>
qlog::events::quic::PacketType::VersionNegotiation,
Type::Short => qlog::events::quic::PacketType::OneRtt,
}
}
}
pub struct ConnectionId<'a>(ConnectionIdInner<'a>);
enum ConnectionIdInner<'a> {
Vec(Vec<u8>),
Ref(&'a [u8]),
}
impl<'a> ConnectionId<'a> {
#[inline]
pub const fn from_vec(cid: Vec<u8>) -> Self {
Self(ConnectionIdInner::Vec(cid))
}
#[inline]
pub const fn from_ref(cid: &'a [u8]) -> Self {
Self(ConnectionIdInner::Ref(cid))
}
#[inline]
pub fn into_owned(self) -> ConnectionId<'static> {
ConnectionId::from_vec(self.into())
}
}
impl Default for ConnectionId<'_> {
#[inline]
fn default() -> Self {
Self::from_vec(Vec::new())
}
}
impl From<Vec<u8>> for ConnectionId<'_> {
#[inline]
fn from(v: Vec<u8>) -> Self {
Self::from_vec(v)
}
}
impl From<ConnectionId<'_>> for Vec<u8> {
#[inline]
fn from(id: ConnectionId<'_>) -> Self {
match id.0 {
ConnectionIdInner::Vec(cid) => cid,
ConnectionIdInner::Ref(cid) => cid.to_vec(),
}
}
}
impl PartialEq for ConnectionId<'_> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.as_ref() == other.as_ref()
}
}
impl Eq for ConnectionId<'_> {}
impl AsRef<[u8]> for ConnectionId<'_> {
#[inline]
fn as_ref(&self) -> &[u8] {
match &self.0 {
ConnectionIdInner::Vec(v) => v.as_ref(),
ConnectionIdInner::Ref(v) => v,
}
}
}
impl std::hash::Hash for ConnectionId<'_> {
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_ref().hash(state);
}
}
impl std::ops::Deref for ConnectionId<'_> {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
match &self.0 {
ConnectionIdInner::Vec(v) => v.as_ref(),
ConnectionIdInner::Ref(v) => v,
}
}
}
impl Clone for ConnectionId<'_> {
#[inline]
fn clone(&self) -> Self {
Self::from_vec(self.as_ref().to_vec())
}
}
impl std::fmt::Debug for ConnectionId<'_> {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for c in self.as_ref() {
write!(f, "{c:02x}")?;
}
Ok(())
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct Header<'a> {
pub ty: Type,
pub version: u32,
pub dcid: ConnectionId<'a>,
pub scid: ConnectionId<'a>,
pub(crate) pkt_num: u64,
pub(crate) pkt_num_len: usize,
pub token: Option<Vec<u8>>,
pub versions: Option<Vec<u32>>,
pub(crate) key_phase: bool,
}
impl<'a> Header<'a> {
#[inline]
pub fn from_slice<'b>(
buf: &'b mut [u8], dcid_len: usize,
) -> Result<Header<'a>> {
let mut b = octets::OctetsMut::with_slice(buf);
Header::from_bytes(&mut b, dcid_len)
}
pub(crate) fn from_bytes<'b>(
b: &'b mut octets::OctetsMut, dcid_len: usize,
) -> Result<Header<'a>> {
let first = b.get_u8()?;
if !Header::is_long(first) {
let dcid = b.get_bytes(dcid_len)?;
return Ok(Header {
ty: Type::Short,
version: 0,
dcid: dcid.to_vec().into(),
scid: ConnectionId::default(),
pkt_num: 0,
pkt_num_len: 0,
token: None,
versions: None,
key_phase: false,
});
}
let version = b.get_u32()?;
let ty = if version == 0 {
Type::VersionNegotiation
} else {
match (first & TYPE_MASK) >> 4 {
0x00 => Type::Initial,
0x01 => Type::ZeroRTT,
0x02 => Type::Handshake,
0x03 => Type::Retry,
_ => return Err(Error::InvalidPacket),
}
};
let dcid_len = b.get_u8()?;
if crate::version_is_supported(version) && dcid_len > MAX_CID_LEN {
return Err(Error::InvalidPacket);
}
let dcid = b.get_bytes(dcid_len as usize)?.to_vec();
let scid_len = b.get_u8()?;
if crate::version_is_supported(version) && scid_len > MAX_CID_LEN {
return Err(Error::InvalidPacket);
}
let scid = b.get_bytes(scid_len as usize)?.to_vec();
let mut token: Option<Vec<u8>> = None;
let mut versions: Option<Vec<u32>> = None;
match ty {
Type::Initial => {
token = Some(b.get_bytes_with_varint_length()?.to_vec());
},
Type::Retry => {
if b.cap() < aead::AES_128_GCM.tag_len() {
return Err(Error::InvalidPacket);
}
let token_len = b.cap() - aead::AES_128_GCM.tag_len();
token = Some(b.get_bytes(token_len)?.to_vec());
},
Type::VersionNegotiation => {
let mut list: Vec<u32> = Vec::new();
while b.cap() > 0 {
let version = b.get_u32()?;
list.push(version);
}
versions = Some(list);
},
_ => (),
};
Ok(Header {
ty,
version,
dcid: dcid.into(),
scid: scid.into(),
pkt_num: 0,
pkt_num_len: 0,
token,
versions,
key_phase: false,
})
}
pub(crate) fn to_bytes(&self, out: &mut octets::OctetsMut) -> Result<()> {
let mut first = 0;
first |= self.pkt_num_len.saturating_sub(1) as u8;
if self.ty == Type::Short {
first &= !FORM_BIT;
first |= FIXED_BIT;
if self.key_phase {
first |= KEY_PHASE_BIT;
} else {
first &= !KEY_PHASE_BIT;
}
out.put_u8(first)?;
out.put_bytes(&self.dcid)?;
return Ok(());
}
let ty: u8 = match self.ty {
Type::Initial => 0x00,
Type::ZeroRTT => 0x01,
Type::Handshake => 0x02,
Type::Retry => 0x03,
_ => return Err(Error::InvalidPacket),
};
first |= FORM_BIT | FIXED_BIT | (ty << 4);
out.put_u8(first)?;
out.put_u32(self.version)?;
out.put_u8(self.dcid.len() as u8)?;
out.put_bytes(&self.dcid)?;
out.put_u8(self.scid.len() as u8)?;
out.put_bytes(&self.scid)?;
match self.ty {
Type::Initial => {
match self.token {
Some(ref v) => {
out.put_varint(v.len() as u64)?;
out.put_bytes(v)?;
},
None => {
out.put_varint(0)?;
},
}
},
Type::Retry => {
out.put_bytes(self.token.as_ref().unwrap())?;
},
_ => (),
}
Ok(())
}
fn is_long(b: u8) -> bool {
b & FORM_BIT != 0
}
}
impl std::fmt::Debug for Header<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self.ty)?;
if self.ty != Type::Short {
write!(f, " version={:x}", self.version)?;
}
write!(f, " dcid={:?}", self.dcid)?;
if self.ty != Type::Short {
write!(f, " scid={:?}", self.scid)?;
}
if let Some(ref token) = self.token {
write!(f, " token=")?;
for b in token {
write!(f, "{b:02x}")?;
}
}
if let Some(ref versions) = self.versions {
write!(f, " versions={versions:x?}")?;
}
if self.ty == Type::Short {
write!(f, " key_phase={}", self.key_phase)?;
}
Ok(())
}
}
pub fn pkt_num_len(pn: u64, largest_acked: u64) -> usize {
let num_unacked: u64 = pn.saturating_sub(largest_acked) + 1;
let min_bits = u64::BITS - num_unacked.leading_zeros();
((min_bits + 7) / 8) as usize
}
pub fn decrypt_hdr(
b: &mut octets::OctetsMut, hdr: &mut Header, aead: &crypto::Open,
) -> Result<()> {
let mut first = {
let (first_buf, _) = b.split_at(1)?;
first_buf.as_ref()[0]
};
let mut pn_and_sample = b.peek_bytes_mut(MAX_PKT_NUM_LEN + SAMPLE_LEN)?;
let (mut ciphertext, sample) = pn_and_sample.split_at(MAX_PKT_NUM_LEN)?;
let ciphertext = ciphertext.as_mut();
let mask = aead.new_mask(sample.as_ref())?;
if Header::is_long(first) {
first ^= mask[0] & 0x0f;
} else {
first ^= mask[0] & 0x1f;
}
let pn_len = usize::from((first & PKT_NUM_MASK) + 1);
let ciphertext = &mut ciphertext[..pn_len];
for i in 0..pn_len {
ciphertext[i] ^= mask[i + 1];
}
let pn = match pn_len {
1 => u64::from(b.get_u8()?),
2 => u64::from(b.get_u16()?),
3 => u64::from(b.get_u24()?),
4 => u64::from(b.get_u32()?),
_ => return Err(Error::InvalidPacket),
};
let (mut first_buf, _) = b.split_at(1)?;
first_buf.as_mut()[0] = first;
hdr.pkt_num = pn;
hdr.pkt_num_len = pn_len;
if hdr.ty == Type::Short {
hdr.key_phase = (first & KEY_PHASE_BIT) != 0;
}
Ok(())
}
pub fn decode_pkt_num(largest_pn: u64, truncated_pn: u64, pn_len: usize) -> u64 {
let pn_nbits = pn_len * 8;
let expected_pn = largest_pn + 1;
let pn_win = 1 << pn_nbits;
let pn_hwin = pn_win / 2;
let pn_mask = pn_win - 1;
let candidate_pn = (expected_pn & !pn_mask) | truncated_pn;
if candidate_pn + pn_hwin <= expected_pn && candidate_pn < (1 << 62) - pn_win
{
return candidate_pn + pn_win;
}
if candidate_pn > expected_pn + pn_hwin && candidate_pn >= pn_win {
return candidate_pn - pn_win;
}
candidate_pn
}
pub fn decrypt_pkt<'a>(
b: &'a mut octets::OctetsMut, pn: u64, pn_len: usize, payload_len: usize,
aead: &crypto::Open,
) -> Result<octets::Octets<'a>> {
let payload_offset = b.off();
let (header, mut payload) = b.split_at(payload_offset)?;
let payload_len = payload_len
.checked_sub(pn_len)
.ok_or(Error::InvalidPacket)?;
let mut ciphertext = payload.peek_bytes_mut(payload_len)?;
let payload_len =
aead.open_with_u64_counter(pn, header.as_ref(), ciphertext.as_mut())?;
Ok(b.get_bytes(payload_len)?)
}
pub fn encrypt_hdr(
b: &mut octets::OctetsMut, pn_len: usize, payload: &[u8], aead: &crypto::Seal,
) -> Result<()> {
let sample = &payload
[MAX_PKT_NUM_LEN - pn_len..SAMPLE_LEN + (MAX_PKT_NUM_LEN - pn_len)];
let mask = aead.new_mask(sample)?;
let (mut first, mut rest) = b.split_at(1)?;
let first = first.as_mut();
if Header::is_long(first[0]) {
first[0] ^= mask[0] & 0x0f;
} else {
first[0] ^= mask[0] & 0x1f;
}
let pn_buf = rest.slice_last(pn_len)?;
for i in 0..pn_len {
pn_buf[i] ^= mask[i + 1];
}
Ok(())
}
pub fn encrypt_pkt(
b: &mut octets::OctetsMut, pn: u64, pn_len: usize, payload_len: usize,
payload_offset: usize, extra_in: Option<&[u8]>, aead: &crypto::Seal,
) -> Result<usize> {
let (mut header, mut payload) = b.split_at(payload_offset)?;
let ciphertext_len = aead.seal_with_u64_counter(
pn,
header.as_ref(),
payload.as_mut(),
payload_len,
extra_in,
)?;
encrypt_hdr(&mut header, pn_len, payload.as_ref(), aead)?;
Ok(payload_offset + ciphertext_len)
}
pub fn encode_pkt_num(
pn: u64, pn_len: usize, b: &mut octets::OctetsMut,
) -> Result<()> {
match pn_len {
1 => b.put_u8(pn as u8)?,
2 => b.put_u16(pn as u16)?,
3 => b.put_u24(pn as u32)?,
4 => b.put_u32(pn as u32)?,
_ => return Err(Error::InvalidPacket),
};
Ok(())
}
pub fn negotiate_version(
scid: &[u8], dcid: &[u8], out: &mut [u8],
) -> Result<usize> {
let mut b = octets::OctetsMut::with_slice(out);
let first = rand::rand_u8() | FORM_BIT;
b.put_u8(first)?;
b.put_u32(0)?;
b.put_u8(scid.len() as u8)?;
b.put_bytes(scid)?;
b.put_u8(dcid.len() as u8)?;
b.put_bytes(dcid)?;
b.put_u32(crate::PROTOCOL_VERSION_V1)?;
Ok(b.off())
}
pub fn retry(
scid: &[u8], dcid: &[u8], new_scid: &[u8], token: &[u8], version: u32,
out: &mut [u8],
) -> Result<usize> {
let mut b = octets::OctetsMut::with_slice(out);
if !crate::version_is_supported(version) {
return Err(Error::UnknownVersion);
}
let hdr = Header {
ty: Type::Retry,
version,
dcid: ConnectionId::from_ref(scid),
scid: ConnectionId::from_ref(new_scid),
pkt_num: 0,
pkt_num_len: 0,
token: Some(token.to_vec()),
versions: None,
key_phase: false,
};
hdr.to_bytes(&mut b)?;
let tag = compute_retry_integrity_tag(&b, dcid, version)?;
b.put_bytes(tag.as_ref())?;
Ok(b.off())
}
pub fn verify_retry_integrity(
b: &octets::OctetsMut, odcid: &[u8], version: u32,
) -> Result<()> {
let tag = compute_retry_integrity_tag(b, odcid, version)?;
ring::constant_time::verify_slices_are_equal(
&b.as_ref()[..aead::AES_128_GCM.tag_len()],
tag.as_ref(),
)
.map_err(|_| Error::CryptoFail)?;
Ok(())
}
fn compute_retry_integrity_tag(
b: &octets::OctetsMut, odcid: &[u8], version: u32,
) -> Result<aead::Tag> {
const RETRY_INTEGRITY_KEY_V1: [u8; 16] = [
0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a, 0x1d, 0x76, 0x6b, 0x54,
0xe3, 0x68, 0xc8, 0x4e,
];
const RETRY_INTEGRITY_NONCE_V1: [u8; aead::NONCE_LEN] = [
0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb,
];
let (key, nonce) = match version {
crate::PROTOCOL_VERSION_V1 =>
(&RETRY_INTEGRITY_KEY_V1, RETRY_INTEGRITY_NONCE_V1),
_ => (&RETRY_INTEGRITY_KEY_V1, RETRY_INTEGRITY_NONCE_V1),
};
let hdr_len = b.off();
let mut pseudo = vec![0; 1 + odcid.len() + hdr_len];
let mut pb = octets::OctetsMut::with_slice(&mut pseudo);
pb.put_u8(odcid.len() as u8)?;
pb.put_bytes(odcid)?;
pb.put_bytes(&b.buf()[..hdr_len])?;
let key = aead::LessSafeKey::new(
aead::UnboundKey::new(&aead::AES_128_GCM, key)
.map_err(|_| Error::CryptoFail)?,
);
let nonce = aead::Nonce::assume_unique_for_key(nonce);
let aad = aead::Aad::from(&pseudo);
key.seal_in_place_separate_tag(nonce, aad, &mut [])
.map_err(|_| Error::CryptoFail)
}
pub struct KeyUpdate {
pub crypto_open: crypto::Open,
pub pn_on_update: u64,
pub update_acked: bool,
pub timer: time::Instant,
}
pub struct PktNumSpace {
pub largest_rx_pkt_num: u64,
pub largest_rx_pkt_time: time::Instant,
pub largest_rx_non_probing_pkt_num: u64,
pub next_pkt_num: u64,
pub recv_pkt_need_ack: ranges::RangeSet,
pub recv_pkt_num: PktNumWindow,
pub ack_elicited: bool,
pub key_update: Option<KeyUpdate>,
pub crypto_open: Option<crypto::Open>,
pub crypto_seal: Option<crypto::Seal>,
pub crypto_0rtt_open: Option<crypto::Open>,
pub crypto_stream: stream::Stream,
}
impl PktNumSpace {
pub fn new() -> PktNumSpace {
PktNumSpace {
largest_rx_pkt_num: 0,
largest_rx_pkt_time: time::Instant::now(),
largest_rx_non_probing_pkt_num: 0,
next_pkt_num: 0,
recv_pkt_need_ack: ranges::RangeSet::new(crate::MAX_ACK_RANGES),
recv_pkt_num: PktNumWindow::default(),
ack_elicited: false,
key_update: None,
crypto_open: None,
crypto_seal: None,
crypto_0rtt_open: None,
crypto_stream: stream::Stream::new(
0, u64::MAX,
u64::MAX,
true,
true,
stream::MAX_STREAM_WINDOW,
),
}
}
pub fn clear(&mut self) {
self.crypto_stream = stream::Stream::new(
0, u64::MAX,
u64::MAX,
true,
true,
stream::MAX_STREAM_WINDOW,
);
self.ack_elicited = false;
}
pub fn crypto_overhead(&self) -> Option<usize> {
Some(self.crypto_seal.as_ref()?.alg().tag_len())
}
pub fn ready(&self) -> bool {
self.crypto_stream.is_flushable() || self.ack_elicited
}
pub fn has_keys(&self) -> bool {
self.crypto_open.is_some() && self.crypto_seal.is_some()
}
}
#[derive(Clone, Copy, Default)]
pub struct PktNumWindow {
lower: u64,
window: u128,
}
impl PktNumWindow {
pub fn insert(&mut self, seq: u64) {
if seq < self.lower {
return;
}
if seq > self.upper() {
let diff = seq - self.upper();
self.lower += diff;
self.window = self.window.checked_shl(diff as u32).unwrap_or(0);
}
let mask = 1_u128 << (self.upper() - seq);
self.window |= mask;
}
pub fn contains(&mut self, seq: u64) -> bool {
if seq > self.upper() {
return false;
}
if seq < self.lower {
return true;
}
let mask = 1_u128 << (self.upper() - seq);
self.window & mask != 0
}
fn upper(&self) -> u64 {
self.lower
.saturating_add(std::mem::size_of::<u128>() as u64 * 8) -
1
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn retry() {
let hdr = Header {
ty: Type::Retry,
version: 0xafafafaf,
dcid: vec![0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba]
.into(),
scid: vec![0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb].into(),
pkt_num: 0,
pkt_num_len: 0,
token: Some(vec![0xba; 24]),
versions: None,
key_phase: false,
};
let mut d = [0; 63];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
b.put_bytes(&[0xba; 16]).unwrap();
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 9).unwrap(), hdr);
}
#[test]
fn initial() {
let hdr = Header {
ty: Type::Initial,
version: 0xafafafaf,
dcid: vec![0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba]
.into(),
scid: vec![0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb].into(),
pkt_num: 0,
pkt_num_len: 0,
token: Some(vec![0x05, 0x06, 0x07, 0x08]),
versions: None,
key_phase: false,
};
let mut d = [0; 50];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 9).unwrap(), hdr);
}
#[test]
fn initial_v1_dcid_too_long() {
let hdr = Header {
ty: Type::Initial,
version: crate::PROTOCOL_VERSION,
dcid: vec![
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
]
.into(),
scid: vec![0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb].into(),
pkt_num: 0,
pkt_num_len: 0,
token: Some(vec![0x05, 0x06, 0x07, 0x08]),
versions: None,
key_phase: false,
};
let mut d = [0; 50];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 21), Err(Error::InvalidPacket));
}
#[test]
fn initial_v1_scid_too_long() {
let hdr = Header {
ty: Type::Initial,
version: crate::PROTOCOL_VERSION,
dcid: vec![0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba]
.into(),
scid: vec![
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
]
.into(),
pkt_num: 0,
pkt_num_len: 0,
token: Some(vec![0x05, 0x06, 0x07, 0x08]),
versions: None,
key_phase: false,
};
let mut d = [0; 50];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 9), Err(Error::InvalidPacket));
}
#[test]
fn initial_non_v1_scid_long() {
let hdr = Header {
ty: Type::Initial,
version: 0xafafafaf,
dcid: vec![0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba]
.into(),
scid: vec![
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
]
.into(),
pkt_num: 0,
pkt_num_len: 0,
token: Some(vec![0x05, 0x06, 0x07, 0x08]),
versions: None,
key_phase: false,
};
let mut d = [0; 50];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 9).unwrap(), hdr);
}
#[test]
fn handshake() {
let hdr = Header {
ty: Type::Handshake,
version: 0xafafafaf,
dcid: vec![0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba]
.into(),
scid: vec![0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb].into(),
pkt_num: 0,
pkt_num_len: 0,
token: None,
versions: None,
key_phase: false,
};
let mut d = [0; 50];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 9).unwrap(), hdr);
}
#[test]
fn application() {
let hdr = Header {
ty: Type::Short,
version: 0,
dcid: vec![0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba]
.into(),
scid: ConnectionId::default(),
pkt_num: 0,
pkt_num_len: 0,
token: None,
versions: None,
key_phase: false,
};
let mut d = [0; 50];
let mut b = octets::OctetsMut::with_slice(&mut d);
assert!(hdr.to_bytes(&mut b).is_ok());
let mut b = octets::OctetsMut::with_slice(&mut d);
assert_eq!(Header::from_bytes(&mut b, 9).unwrap(), hdr);
}
#[test]
fn pkt_num_encode_decode() {
let num_len = pkt_num_len(0, 0);
assert_eq!(num_len, 1);
let pn = decode_pkt_num(0xa82f30ea, 0x9b32, 2);
assert_eq!(pn, 0xa82f9b32);
let mut d = [0; 10];
let mut b = octets::OctetsMut::with_slice(&mut d);
let num_len = pkt_num_len(0xac5c02, 0xabe8b3);
assert_eq!(num_len, 2);
encode_pkt_num(0xac5c02, num_len, &mut b).unwrap();
let mut b = octets::OctetsMut::with_slice(&mut d);
let hdr_num = u64::from(b.get_u16().unwrap());
let pn = decode_pkt_num(0xac5c01, hdr_num, num_len);
assert_eq!(pn, 0xac5c02);
let num_len = pkt_num_len(0xace9fe, 0xabe8b3);
assert_eq!(num_len, 3);
let mut b = octets::OctetsMut::with_slice(&mut d);
encode_pkt_num(0xace9fe, num_len, &mut b).unwrap();
let mut b = octets::OctetsMut::with_slice(&mut d);
let hdr_num = u64::from(b.get_u24().unwrap());
let pn = decode_pkt_num(0xace9fa, hdr_num, num_len);
assert_eq!(pn, 0xace9fe);
}
#[test]
fn pkt_num_window() {
let mut win = PktNumWindow::default();
assert_eq!(win.lower, 0);
assert!(!win.contains(0));
assert!(!win.contains(1));
win.insert(0);
assert_eq!(win.lower, 0);
assert!(win.contains(0));
assert!(!win.contains(1));
win.insert(1);
assert_eq!(win.lower, 0);
assert!(win.contains(0));
assert!(win.contains(1));
win.insert(3);
assert_eq!(win.lower, 0);
assert!(win.contains(0));
assert!(win.contains(1));
assert!(!win.contains(2));
assert!(win.contains(3));
win.insert(10);
assert_eq!(win.lower, 0);
assert!(win.contains(0));
assert!(win.contains(1));
assert!(!win.contains(2));
assert!(win.contains(3));
assert!(!win.contains(4));
assert!(!win.contains(5));
assert!(!win.contains(6));
assert!(!win.contains(7));
assert!(!win.contains(8));
assert!(!win.contains(9));
assert!(win.contains(10));
win.insert(132);
assert_eq!(win.lower, 5);
assert!(win.contains(0));
assert!(win.contains(1));
assert!(win.contains(2));
assert!(win.contains(3));
assert!(win.contains(4));
assert!(!win.contains(5));
assert!(!win.contains(6));
assert!(!win.contains(7));
assert!(!win.contains(8));
assert!(!win.contains(9));
assert!(win.contains(10));
assert!(!win.contains(128));
assert!(!win.contains(130));
assert!(!win.contains(131));
assert!(win.contains(132));
win.insert(1024);
assert_eq!(win.lower, 897);
assert!(win.contains(0));
assert!(win.contains(1));
assert!(win.contains(2));
assert!(win.contains(3));
assert!(win.contains(4));
assert!(win.contains(5));
assert!(win.contains(6));
assert!(win.contains(7));
assert!(win.contains(8));
assert!(win.contains(9));
assert!(win.contains(10));
assert!(win.contains(128));
assert!(win.contains(130));
assert!(win.contains(132));
assert!(win.contains(896));
assert!(!win.contains(897));
assert!(!win.contains(1022));
assert!(!win.contains(1023));
assert!(win.contains(1024));
assert!(!win.contains(1025));
assert!(!win.contains(1026));
win.insert(u64::MAX - 1);
assert!(win.contains(0));
assert!(win.contains(1));
assert!(win.contains(2));
assert!(win.contains(3));
assert!(win.contains(4));
assert!(win.contains(5));
assert!(win.contains(6));
assert!(win.contains(7));
assert!(win.contains(8));
assert!(win.contains(9));
assert!(win.contains(10));
assert!(win.contains(128));
assert!(win.contains(130));
assert!(win.contains(132));
assert!(win.contains(896));
assert!(win.contains(897));
assert!(win.contains(1022));
assert!(win.contains(1023));
assert!(win.contains(1024));
assert!(win.contains(1025));
assert!(win.contains(1026));
assert!(!win.contains(u64::MAX - 2));
assert!(win.contains(u64::MAX - 1));
}
fn assert_decrypt_initial_pkt(
pkt: &mut [u8], dcid: &[u8], is_server: bool, expected_frames: &[u8],
expected_pn: u64, expected_pn_len: usize,
) {
let mut b = octets::OctetsMut::with_slice(pkt);
let mut hdr = Header::from_bytes(&mut b, 0).unwrap();
assert_eq!(hdr.ty, Type::Initial);
let payload_len = b.get_varint().unwrap() as usize;
let (aead, _) =
crypto::derive_initial_key_material(dcid, hdr.version, is_server)
.unwrap();
decrypt_hdr(&mut b, &mut hdr, &aead).unwrap();
assert_eq!(hdr.pkt_num_len, expected_pn_len);
let pn = decode_pkt_num(0, hdr.pkt_num, hdr.pkt_num_len);
assert_eq!(pn, expected_pn);
let payload =
decrypt_pkt(&mut b, pn, hdr.pkt_num_len, payload_len, &aead).unwrap();
let payload = payload.as_ref();
assert_eq!(&payload[..expected_frames.len()], expected_frames);
}
#[test]
fn decrypt_client_initial_v1() {
let mut pkt = [
0xc0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x83, 0x94, 0xc8, 0xf0, 0x3e,
0x51, 0x57, 0x08, 0x00, 0x00, 0x44, 0x9e, 0x7b, 0x9a, 0xec, 0x34,
0xd1, 0xb1, 0xc9, 0x8d, 0xd7, 0x68, 0x9f, 0xb8, 0xec, 0x11, 0xd2,
0x42, 0xb1, 0x23, 0xdc, 0x9b, 0xd8, 0xba, 0xb9, 0x36, 0xb4, 0x7d,
0x92, 0xec, 0x35, 0x6c, 0x0b, 0xab, 0x7d, 0xf5, 0x97, 0x6d, 0x27,
0xcd, 0x44, 0x9f, 0x63, 0x30, 0x00, 0x99, 0xf3, 0x99, 0x1c, 0x26,
0x0e, 0xc4, 0xc6, 0x0d, 0x17, 0xb3, 0x1f, 0x84, 0x29, 0x15, 0x7b,
0xb3, 0x5a, 0x12, 0x82, 0xa6, 0x43, 0xa8, 0xd2, 0x26, 0x2c, 0xad,
0x67, 0x50, 0x0c, 0xad, 0xb8, 0xe7, 0x37, 0x8c, 0x8e, 0xb7, 0x53,
0x9e, 0xc4, 0xd4, 0x90, 0x5f, 0xed, 0x1b, 0xee, 0x1f, 0xc8, 0xaa,
0xfb, 0xa1, 0x7c, 0x75, 0x0e, 0x2c, 0x7a, 0xce, 0x01, 0xe6, 0x00,
0x5f, 0x80, 0xfc, 0xb7, 0xdf, 0x62, 0x12, 0x30, 0xc8, 0x37, 0x11,
0xb3, 0x93, 0x43, 0xfa, 0x02, 0x8c, 0xea, 0x7f, 0x7f, 0xb5, 0xff,
0x89, 0xea, 0xc2, 0x30, 0x82, 0x49, 0xa0, 0x22, 0x52, 0x15, 0x5e,
0x23, 0x47, 0xb6, 0x3d, 0x58, 0xc5, 0x45, 0x7a, 0xfd, 0x84, 0xd0,
0x5d, 0xff, 0xfd, 0xb2, 0x03, 0x92, 0x84, 0x4a, 0xe8, 0x12, 0x15,
0x46, 0x82, 0xe9, 0xcf, 0x01, 0x2f, 0x90, 0x21, 0xa6, 0xf0, 0xbe,
0x17, 0xdd, 0xd0, 0xc2, 0x08, 0x4d, 0xce, 0x25, 0xff, 0x9b, 0x06,
0xcd, 0xe5, 0x35, 0xd0, 0xf9, 0x20, 0xa2, 0xdb, 0x1b, 0xf3, 0x62,
0xc2, 0x3e, 0x59, 0x6d, 0xee, 0x38, 0xf5, 0xa6, 0xcf, 0x39, 0x48,
0x83, 0x8a, 0x3a, 0xec, 0x4e, 0x15, 0xda, 0xf8, 0x50, 0x0a, 0x6e,
0xf6, 0x9e, 0xc4, 0xe3, 0xfe, 0xb6, 0xb1, 0xd9, 0x8e, 0x61, 0x0a,
0xc8, 0xb7, 0xec, 0x3f, 0xaf, 0x6a, 0xd7, 0x60, 0xb7, 0xba, 0xd1,
0xdb, 0x4b, 0xa3, 0x48, 0x5e, 0x8a, 0x94, 0xdc, 0x25, 0x0a, 0xe3,
0xfd, 0xb4, 0x1e, 0xd1, 0x5f, 0xb6, 0xa8, 0xe5, 0xeb, 0xa0, 0xfc,
0x3d, 0xd6, 0x0b, 0xc8, 0xe3, 0x0c, 0x5c, 0x42, 0x87, 0xe5, 0x38,
0x05, 0xdb, 0x05, 0x9a, 0xe0, 0x64, 0x8d, 0xb2, 0xf6, 0x42, 0x64,
0xed, 0x5e, 0x39, 0xbe, 0x2e, 0x20, 0xd8, 0x2d, 0xf5, 0x66, 0xda,
0x8d, 0xd5, 0x99, 0x8c, 0xca, 0xbd, 0xae, 0x05, 0x30, 0x60, 0xae,
0x6c, 0x7b, 0x43, 0x78, 0xe8, 0x46, 0xd2, 0x9f, 0x37, 0xed, 0x7b,
0x4e, 0xa9, 0xec, 0x5d, 0x82, 0xe7, 0x96, 0x1b, 0x7f, 0x25, 0xa9,
0x32, 0x38, 0x51, 0xf6, 0x81, 0xd5, 0x82, 0x36, 0x3a, 0xa5, 0xf8,
0x99, 0x37, 0xf5, 0xa6, 0x72, 0x58, 0xbf, 0x63, 0xad, 0x6f, 0x1a,
0x0b, 0x1d, 0x96, 0xdb, 0xd4, 0xfa, 0xdd, 0xfc, 0xef, 0xc5, 0x26,
0x6b, 0xa6, 0x61, 0x17, 0x22, 0x39, 0x5c, 0x90, 0x65, 0x56, 0xbe,
0x52, 0xaf, 0xe3, 0xf5, 0x65, 0x63, 0x6a, 0xd1, 0xb1, 0x7d, 0x50,
0x8b, 0x73, 0xd8, 0x74, 0x3e, 0xeb, 0x52, 0x4b, 0xe2, 0x2b, 0x3d,
0xcb, 0xc2, 0xc7, 0x46, 0x8d, 0x54, 0x11, 0x9c, 0x74, 0x68, 0x44,
0x9a, 0x13, 0xd8, 0xe3, 0xb9, 0x58, 0x11, 0xa1, 0x98, 0xf3, 0x49,
0x1d, 0xe3, 0xe7, 0xfe, 0x94, 0x2b, 0x33, 0x04, 0x07, 0xab, 0xf8,
0x2a, 0x4e, 0xd7, 0xc1, 0xb3, 0x11, 0x66, 0x3a, 0xc6, 0x98, 0x90,
0xf4, 0x15, 0x70, 0x15, 0x85, 0x3d, 0x91, 0xe9, 0x23, 0x03, 0x7c,
0x22, 0x7a, 0x33, 0xcd, 0xd5, 0xec, 0x28, 0x1c, 0xa3, 0xf7, 0x9c,
0x44, 0x54, 0x6b, 0x9d, 0x90, 0xca, 0x00, 0xf0, 0x64, 0xc9, 0x9e,
0x3d, 0xd9, 0x79, 0x11, 0xd3, 0x9f, 0xe9, 0xc5, 0xd0, 0xb2, 0x3a,
0x22, 0x9a, 0x23, 0x4c, 0xb3, 0x61, 0x86, 0xc4, 0x81, 0x9e, 0x8b,
0x9c, 0x59, 0x27, 0x72, 0x66, 0x32, 0x29, 0x1d, 0x6a, 0x41, 0x82,
0x11, 0xcc, 0x29, 0x62, 0xe2, 0x0f, 0xe4, 0x7f, 0xeb, 0x3e, 0xdf,
0x33, 0x0f, 0x2c, 0x60, 0x3a, 0x9d, 0x48, 0xc0, 0xfc, 0xb5, 0x69,
0x9d, 0xbf, 0xe5, 0x89, 0x64, 0x25, 0xc5, 0xba, 0xc4, 0xae, 0xe8,
0x2e, 0x57, 0xa8, 0x5a, 0xaf, 0x4e, 0x25, 0x13, 0xe4, 0xf0, 0x57,
0x96, 0xb0, 0x7b, 0xa2, 0xee, 0x47, 0xd8, 0x05, 0x06, 0xf8, 0xd2,
0xc2, 0x5e, 0x50, 0xfd, 0x14, 0xde, 0x71, 0xe6, 0xc4, 0x18, 0x55,
0x93, 0x02, 0xf9, 0x39, 0xb0, 0xe1, 0xab, 0xd5, 0x76, 0xf2, 0x79,
0xc4, 0xb2, 0xe0, 0xfe, 0xb8, 0x5c, 0x1f, 0x28, 0xff, 0x18, 0xf5,
0x88, 0x91, 0xff, 0xef, 0x13, 0x2e, 0xef, 0x2f, 0xa0, 0x93, 0x46,
0xae, 0xe3, 0x3c, 0x28, 0xeb, 0x13, 0x0f, 0xf2, 0x8f, 0x5b, 0x76,
0x69, 0x53, 0x33, 0x41, 0x13, 0x21, 0x19, 0x96, 0xd2, 0x00, 0x11,
0xa1, 0x98, 0xe3, 0xfc, 0x43, 0x3f, 0x9f, 0x25, 0x41, 0x01, 0x0a,
0xe1, 0x7c, 0x1b, 0xf2, 0x02, 0x58, 0x0f, 0x60, 0x47, 0x47, 0x2f,
0xb3, 0x68, 0x57, 0xfe, 0x84, 0x3b, 0x19, 0xf5, 0x98, 0x40, 0x09,
0xdd, 0xc3, 0x24, 0x04, 0x4e, 0x84, 0x7a, 0x4f, 0x4a, 0x0a, 0xb3,
0x4f, 0x71, 0x95, 0x95, 0xde, 0x37, 0x25, 0x2d, 0x62, 0x35, 0x36,
0x5e, 0x9b, 0x84, 0x39, 0x2b, 0x06, 0x10, 0x85, 0x34, 0x9d, 0x73,
0x20, 0x3a, 0x4a, 0x13, 0xe9, 0x6f, 0x54, 0x32, 0xec, 0x0f, 0xd4,
0xa1, 0xee, 0x65, 0xac, 0xcd, 0xd5, 0xe3, 0x90, 0x4d, 0xf5, 0x4c,
0x1d, 0xa5, 0x10, 0xb0, 0xff, 0x20, 0xdc, 0xc0, 0xc7, 0x7f, 0xcb,
0x2c, 0x0e, 0x0e, 0xb6, 0x05, 0xcb, 0x05, 0x04, 0xdb, 0x87, 0x63,
0x2c, 0xf3, 0xd8, 0xb4, 0xda, 0xe6, 0xe7, 0x05, 0x76, 0x9d, 0x1d,
0xe3, 0x54, 0x27, 0x01, 0x23, 0xcb, 0x11, 0x45, 0x0e, 0xfc, 0x60,
0xac, 0x47, 0x68, 0x3d, 0x7b, 0x8d, 0x0f, 0x81, 0x13, 0x65, 0x56,
0x5f, 0xd9, 0x8c, 0x4c, 0x8e, 0xb9, 0x36, 0xbc, 0xab, 0x8d, 0x06,
0x9f, 0xc3, 0x3b, 0xd8, 0x01, 0xb0, 0x3a, 0xde, 0xa2, 0xe1, 0xfb,
0xc5, 0xaa, 0x46, 0x3d, 0x08, 0xca, 0x19, 0x89, 0x6d, 0x2b, 0xf5,
0x9a, 0x07, 0x1b, 0x85, 0x1e, 0x6c, 0x23, 0x90, 0x52, 0x17, 0x2f,
0x29, 0x6b, 0xfb, 0x5e, 0x72, 0x40, 0x47, 0x90, 0xa2, 0x18, 0x10,
0x14, 0xf3, 0xb9, 0x4a, 0x4e, 0x97, 0xd1, 0x17, 0xb4, 0x38, 0x13,
0x03, 0x68, 0xcc, 0x39, 0xdb, 0xb2, 0xd1, 0x98, 0x06, 0x5a, 0xe3,
0x98, 0x65, 0x47, 0x92, 0x6c, 0xd2, 0x16, 0x2f, 0x40, 0xa2, 0x9f,
0x0c, 0x3c, 0x87, 0x45, 0xc0, 0xf5, 0x0f, 0xba, 0x38, 0x52, 0xe5,
0x66, 0xd4, 0x45, 0x75, 0xc2, 0x9d, 0x39, 0xa0, 0x3f, 0x0c, 0xda,
0x72, 0x19, 0x84, 0xb6, 0xf4, 0x40, 0x59, 0x1f, 0x35, 0x5e, 0x12,
0xd4, 0x39, 0xff, 0x15, 0x0a, 0xab, 0x76, 0x13, 0x49, 0x9d, 0xbd,
0x49, 0xad, 0xab, 0xc8, 0x67, 0x6e, 0xef, 0x02, 0x3b, 0x15, 0xb6,
0x5b, 0xfc, 0x5c, 0xa0, 0x69, 0x48, 0x10, 0x9f, 0x23, 0xf3, 0x50,
0xdb, 0x82, 0x12, 0x35, 0x35, 0xeb, 0x8a, 0x74, 0x33, 0xbd, 0xab,
0xcb, 0x90, 0x92, 0x71, 0xa6, 0xec, 0xbc, 0xb5, 0x8b, 0x93, 0x6a,
0x88, 0xcd, 0x4e, 0x8f, 0x2e, 0x6f, 0xf5, 0x80, 0x01, 0x75, 0xf1,
0x13, 0x25, 0x3d, 0x8f, 0xa9, 0xca, 0x88, 0x85, 0xc2, 0xf5, 0x52,
0xe6, 0x57, 0xdc, 0x60, 0x3f, 0x25, 0x2e, 0x1a, 0x8e, 0x30, 0x8f,
0x76, 0xf0, 0xbe, 0x79, 0xe2, 0xfb, 0x8f, 0x5d, 0x5f, 0xbb, 0xe2,
0xe3, 0x0e, 0xca, 0xdd, 0x22, 0x07, 0x23, 0xc8, 0xc0, 0xae, 0xa8,
0x07, 0x8c, 0xdf, 0xcb, 0x38, 0x68, 0x26, 0x3f, 0xf8, 0xf0, 0x94,
0x00, 0x54, 0xda, 0x48, 0x78, 0x18, 0x93, 0xa7, 0xe4, 0x9a, 0xd5,
0xaf, 0xf4, 0xaf, 0x30, 0x0c, 0xd8, 0x04, 0xa6, 0xb6, 0x27, 0x9a,
0xb3, 0xff, 0x3a, 0xfb, 0x64, 0x49, 0x1c, 0x85, 0x19, 0x4a, 0xab,
0x76, 0x0d, 0x58, 0xa6, 0x06, 0x65, 0x4f, 0x9f, 0x44, 0x00, 0xe8,
0xb3, 0x85, 0x91, 0x35, 0x6f, 0xbf, 0x64, 0x25, 0xac, 0xa2, 0x6d,
0xc8, 0x52, 0x44, 0x25, 0x9f, 0xf2, 0xb1, 0x9c, 0x41, 0xb9, 0xf9,
0x6f, 0x3c, 0xa9, 0xec, 0x1d, 0xde, 0x43, 0x4d, 0xa7, 0xd2, 0xd3,
0x92, 0xb9, 0x05, 0xdd, 0xf3, 0xd1, 0xf9, 0xaf, 0x93, 0xd1, 0xaf,
0x59, 0x50, 0xbd, 0x49, 0x3f, 0x5a, 0xa7, 0x31, 0xb4, 0x05, 0x6d,
0xf3, 0x1b, 0xd2, 0x67, 0xb6, 0xb9, 0x0a, 0x07, 0x98, 0x31, 0xaa,
0xf5, 0x79, 0xbe, 0x0a, 0x39, 0x01, 0x31, 0x37, 0xaa, 0xc6, 0xd4,
0x04, 0xf5, 0x18, 0xcf, 0xd4, 0x68, 0x40, 0x64, 0x7e, 0x78, 0xbf,
0xe7, 0x06, 0xca, 0x4c, 0xf5, 0xe9, 0xc5, 0x45, 0x3e, 0x9f, 0x7c,
0xfd, 0x2b, 0x8b, 0x4c, 0x8d, 0x16, 0x9a, 0x44, 0xe5, 0x5c, 0x88,
0xd4, 0xa9, 0xa7, 0xf9, 0x47, 0x42, 0x41, 0x10, 0x92, 0xab, 0xbd,
0xf8, 0xb8, 0x89, 0xe5, 0xc1, 0x99, 0xd0, 0x96, 0xe3, 0xf2, 0x47,
0x88,
];
let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
let frames = [
0x06, 0x00, 0x40, 0xf1, 0x01, 0x00, 0x00, 0xed, 0x03, 0x03, 0xeb,
0xf8, 0xfa, 0x56, 0xf1, 0x29, 0x39, 0xb9, 0x58, 0x4a, 0x38, 0x96,
0x47, 0x2e, 0xc4, 0x0b, 0xb8, 0x63, 0xcf, 0xd3, 0xe8, 0x68, 0x04,
0xfe, 0x3a, 0x47, 0xf0, 0x6a, 0x2b, 0x69, 0x48, 0x4c, 0x00, 0x00,
0x04, 0x13, 0x01, 0x13, 0x02, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00,
0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0xff, 0x01, 0x00, 0x01,
0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17,
0x00, 0x18, 0x00, 0x10, 0x00, 0x07, 0x00, 0x05, 0x04, 0x61, 0x6c,
0x70, 0x6e, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x93,
0x70, 0xb2, 0xc9, 0xca, 0xa4, 0x7f, 0xba, 0xba, 0xf4, 0x55, 0x9f,
0xed, 0xba, 0x75, 0x3d, 0xe1, 0x71, 0xfa, 0x71, 0xf5, 0x0f, 0x1c,
0xe1, 0x5d, 0x43, 0xe9, 0x94, 0xec, 0x74, 0xd7, 0x48, 0x00, 0x2b,
0x00, 0x03, 0x02, 0x03, 0x04, 0x00, 0x0d, 0x00, 0x10, 0x00, 0x0e,
0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08,
0x05, 0x08, 0x06, 0x00, 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x1c,
0x00, 0x02, 0x40, 0x01, 0xff, 0xa5, 0x00, 0x32, 0x04, 0x08, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x04, 0x80, 0x00,
0xff, 0xff, 0x07, 0x04, 0x80, 0x00, 0xff, 0xff, 0x08, 0x01, 0x10,
0x01, 0x04, 0x80, 0x00, 0x75, 0x30, 0x09, 0x01, 0x10, 0x0f, 0x08,
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0x06, 0x04, 0x80,
0x00, 0xff, 0xff,
];
assert_decrypt_initial_pkt(&mut pkt, &dcid, true, &frames, 2, 4);
}
#[test]
fn decrypt_server_initial_v1() {
let mut pkt = [
0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50,
0x2a, 0x42, 0x62, 0xb5, 0x00, 0x40, 0x75, 0xc0, 0xd9, 0x5a, 0x48,
0x2c, 0xd0, 0x99, 0x1c, 0xd2, 0x5b, 0x0a, 0xac, 0x40, 0x6a, 0x58,
0x16, 0xb6, 0x39, 0x41, 0x00, 0xf3, 0x7a, 0x1c, 0x69, 0x79, 0x75,
0x54, 0x78, 0x0b, 0xb3, 0x8c, 0xc5, 0xa9, 0x9f, 0x5e, 0xde, 0x4c,
0xf7, 0x3c, 0x3e, 0xc2, 0x49, 0x3a, 0x18, 0x39, 0xb3, 0xdb, 0xcb,
0xa3, 0xf6, 0xea, 0x46, 0xc5, 0xb7, 0x68, 0x4d, 0xf3, 0x54, 0x8e,
0x7d, 0xde, 0xb9, 0xc3, 0xbf, 0x9c, 0x73, 0xcc, 0x3f, 0x3b, 0xde,
0xd7, 0x4b, 0x56, 0x2b, 0xfb, 0x19, 0xfb, 0x84, 0x02, 0x2f, 0x8e,
0xf4, 0xcd, 0xd9, 0x37, 0x95, 0xd7, 0x7d, 0x06, 0xed, 0xbb, 0x7a,
0xaf, 0x2f, 0x58, 0x89, 0x18, 0x50, 0xab, 0xbd, 0xca, 0x3d, 0x20,
0x39, 0x8c, 0x27, 0x64, 0x56, 0xcb, 0xc4, 0x21, 0x58, 0x40, 0x7d,
0xd0, 0x74, 0xee,
];
let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
let frames = [
0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x5a, 0x02, 0x00,
0x00, 0x56, 0x03, 0x03, 0xee, 0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1,
0xd1, 0x63, 0x2e, 0x96, 0x67, 0x78, 0x25, 0xdd, 0xf7, 0x39, 0x88,
0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, 0x6d, 0xc5, 0x43, 0x0b, 0x9a,
0x04, 0x5a, 0x12, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33,
0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x9d, 0x3c, 0x94, 0x0d, 0x89,
0x69, 0x0b, 0x84, 0xd0, 0x8a, 0x60, 0x99, 0x3c, 0x14, 0x4e, 0xca,
0x68, 0x4d, 0x10, 0x81, 0x28, 0x7c, 0x83, 0x4d, 0x53, 0x11, 0xbc,
0xf3, 0x2b, 0xb9, 0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
];
assert_decrypt_initial_pkt(&mut pkt, &dcid, false, &frames, 1, 2);
}
#[test]
fn decrypt_chacha20() {
let secret = [
0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42,
0x27, 0x48, 0xad, 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0,
0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3, 0x0f, 0x21, 0x63, 0x2b,
];
let mut pkt = [
0x4c, 0xfe, 0x41, 0x89, 0x65, 0x5e, 0x5c, 0xd5, 0x5c, 0x41, 0xf6,
0x90, 0x80, 0x57, 0x5d, 0x79, 0x99, 0xc2, 0x5a, 0x5b, 0xfb,
];
let mut b = octets::OctetsMut::with_slice(&mut pkt);
let alg = crypto::Algorithm::ChaCha20_Poly1305;
let aead = crypto::Open::from_secret(alg, &secret).unwrap();
let mut hdr = Header::from_bytes(&mut b, 0).unwrap();
assert_eq!(hdr.ty, Type::Short);
let payload_len = b.cap();
decrypt_hdr(&mut b, &mut hdr, &aead).unwrap();
assert_eq!(hdr.pkt_num_len, 3);
let pn = decode_pkt_num(654_360_564, hdr.pkt_num, hdr.pkt_num_len);
assert_eq!(pn, 654_360_564);
let payload =
decrypt_pkt(&mut b, pn, hdr.pkt_num_len, payload_len, &aead).unwrap();
let payload = payload.as_ref();
assert_eq!(&payload, &[0x01]);
}
fn assert_encrypt_initial_pkt(
header: &mut [u8], dcid: &[u8], frames: &[u8], pn: u64, pn_len: usize,
is_server: bool, expected_pkt: &[u8],
) {
let mut b = octets::OctetsMut::with_slice(header);
let hdr = Header::from_bytes(&mut b, 0).unwrap();
assert_eq!(hdr.ty, Type::Initial);
let mut out = vec![0; expected_pkt.len()];
let mut b = octets::OctetsMut::with_slice(&mut out);
b.put_bytes(header).unwrap();
let (_, aead) =
crypto::derive_initial_key_material(dcid, hdr.version, is_server)
.unwrap();
let payload_len = frames.len();
let payload_offset = b.off();
b.put_bytes(frames).unwrap();
let written = encrypt_pkt(
&mut b,
pn,
pn_len,
payload_len,
payload_offset,
None,
&aead,
)
.unwrap();
assert_eq!(written, expected_pkt.len());
assert_eq!(&out[..written], expected_pkt);
}
#[test]
fn encrypt_client_initial_v1() {
let mut header = [
0xc3, 0x00, 0x00, 0x00, 0x01, 0x08, 0x83, 0x94, 0xc8, 0xf0, 0x3e,
0x51, 0x57, 0x08, 0x00, 0x00, 0x44, 0x9e, 0x00, 0x00, 0x00, 0x02,
];
let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
let frames = [
0x06, 0x00, 0x40, 0xf1, 0x01, 0x00, 0x00, 0xed, 0x03, 0x03, 0xeb,
0xf8, 0xfa, 0x56, 0xf1, 0x29, 0x39, 0xb9, 0x58, 0x4a, 0x38, 0x96,
0x47, 0x2e, 0xc4, 0x0b, 0xb8, 0x63, 0xcf, 0xd3, 0xe8, 0x68, 0x04,
0xfe, 0x3a, 0x47, 0xf0, 0x6a, 0x2b, 0x69, 0x48, 0x4c, 0x00, 0x00,
0x04, 0x13, 0x01, 0x13, 0x02, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00,
0x00, 0x10, 0x00, 0x0e, 0x00, 0x00, 0x0b, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0xff, 0x01, 0x00, 0x01,
0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17,
0x00, 0x18, 0x00, 0x10, 0x00, 0x07, 0x00, 0x05, 0x04, 0x61, 0x6c,
0x70, 0x6e, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x93,
0x70, 0xb2, 0xc9, 0xca, 0xa4, 0x7f, 0xba, 0xba, 0xf4, 0x55, 0x9f,
0xed, 0xba, 0x75, 0x3d, 0xe1, 0x71, 0xfa, 0x71, 0xf5, 0x0f, 0x1c,
0xe1, 0x5d, 0x43, 0xe9, 0x94, 0xec, 0x74, 0xd7, 0x48, 0x00, 0x2b,
0x00, 0x03, 0x02, 0x03, 0x04, 0x00, 0x0d, 0x00, 0x10, 0x00, 0x0e,
0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08,
0x05, 0x08, 0x06, 0x00, 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x1c,
0x00, 0x02, 0x40, 0x01, 0xff, 0xa5, 0x00, 0x32, 0x04, 0x08, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x05, 0x04, 0x80, 0x00,
0xff, 0xff, 0x07, 0x04, 0x80, 0x00, 0xff, 0xff, 0x08, 0x01, 0x10,
0x01, 0x04, 0x80, 0x00, 0x75, 0x30, 0x09, 0x01, 0x10, 0x0f, 0x08,
0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08, 0x06, 0x04, 0x80,
0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
];
let pkt = [
0xc0, 0x00, 0x00, 0x00, 0x01, 0x08, 0x83, 0x94, 0xc8, 0xf0, 0x3e,
0x51, 0x57, 0x08, 0x00, 0x00, 0x44, 0x9e, 0x7b, 0x9a, 0xec, 0x34,
0xd1, 0xb1, 0xc9, 0x8d, 0xd7, 0x68, 0x9f, 0xb8, 0xec, 0x11, 0xd2,
0x42, 0xb1, 0x23, 0xdc, 0x9b, 0xd8, 0xba, 0xb9, 0x36, 0xb4, 0x7d,
0x92, 0xec, 0x35, 0x6c, 0x0b, 0xab, 0x7d, 0xf5, 0x97, 0x6d, 0x27,
0xcd, 0x44, 0x9f, 0x63, 0x30, 0x00, 0x99, 0xf3, 0x99, 0x1c, 0x26,
0x0e, 0xc4, 0xc6, 0x0d, 0x17, 0xb3, 0x1f, 0x84, 0x29, 0x15, 0x7b,
0xb3, 0x5a, 0x12, 0x82, 0xa6, 0x43, 0xa8, 0xd2, 0x26, 0x2c, 0xad,
0x67, 0x50, 0x0c, 0xad, 0xb8, 0xe7, 0x37, 0x8c, 0x8e, 0xb7, 0x53,
0x9e, 0xc4, 0xd4, 0x90, 0x5f, 0xed, 0x1b, 0xee, 0x1f, 0xc8, 0xaa,
0xfb, 0xa1, 0x7c, 0x75, 0x0e, 0x2c, 0x7a, 0xce, 0x01, 0xe6, 0x00,
0x5f, 0x80, 0xfc, 0xb7, 0xdf, 0x62, 0x12, 0x30, 0xc8, 0x37, 0x11,
0xb3, 0x93, 0x43, 0xfa, 0x02, 0x8c, 0xea, 0x7f, 0x7f, 0xb5, 0xff,
0x89, 0xea, 0xc2, 0x30, 0x82, 0x49, 0xa0, 0x22, 0x52, 0x15, 0x5e,
0x23, 0x47, 0xb6, 0x3d, 0x58, 0xc5, 0x45, 0x7a, 0xfd, 0x84, 0xd0,
0x5d, 0xff, 0xfd, 0xb2, 0x03, 0x92, 0x84, 0x4a, 0xe8, 0x12, 0x15,
0x46, 0x82, 0xe9, 0xcf, 0x01, 0x2f, 0x90, 0x21, 0xa6, 0xf0, 0xbe,
0x17, 0xdd, 0xd0, 0xc2, 0x08, 0x4d, 0xce, 0x25, 0xff, 0x9b, 0x06,
0xcd, 0xe5, 0x35, 0xd0, 0xf9, 0x20, 0xa2, 0xdb, 0x1b, 0xf3, 0x62,
0xc2, 0x3e, 0x59, 0x6d, 0xee, 0x38, 0xf5, 0xa6, 0xcf, 0x39, 0x48,
0x83, 0x8a, 0x3a, 0xec, 0x4e, 0x15, 0xda, 0xf8, 0x50, 0x0a, 0x6e,
0xf6, 0x9e, 0xc4, 0xe3, 0xfe, 0xb6, 0xb1, 0xd9, 0x8e, 0x61, 0x0a,
0xc8, 0xb7, 0xec, 0x3f, 0xaf, 0x6a, 0xd7, 0x60, 0xb7, 0xba, 0xd1,
0xdb, 0x4b, 0xa3, 0x48, 0x5e, 0x8a, 0x94, 0xdc, 0x25, 0x0a, 0xe3,
0xfd, 0xb4, 0x1e, 0xd1, 0x5f, 0xb6, 0xa8, 0xe5, 0xeb, 0xa0, 0xfc,
0x3d, 0xd6, 0x0b, 0xc8, 0xe3, 0x0c, 0x5c, 0x42, 0x87, 0xe5, 0x38,
0x05, 0xdb, 0x05, 0x9a, 0xe0, 0x64, 0x8d, 0xb2, 0xf6, 0x42, 0x64,
0xed, 0x5e, 0x39, 0xbe, 0x2e, 0x20, 0xd8, 0x2d, 0xf5, 0x66, 0xda,
0x8d, 0xd5, 0x99, 0x8c, 0xca, 0xbd, 0xae, 0x05, 0x30, 0x60, 0xae,
0x6c, 0x7b, 0x43, 0x78, 0xe8, 0x46, 0xd2, 0x9f, 0x37, 0xed, 0x7b,
0x4e, 0xa9, 0xec, 0x5d, 0x82, 0xe7, 0x96, 0x1b, 0x7f, 0x25, 0xa9,
0x32, 0x38, 0x51, 0xf6, 0x81, 0xd5, 0x82, 0x36, 0x3a, 0xa5, 0xf8,
0x99, 0x37, 0xf5, 0xa6, 0x72, 0x58, 0xbf, 0x63, 0xad, 0x6f, 0x1a,
0x0b, 0x1d, 0x96, 0xdb, 0xd4, 0xfa, 0xdd, 0xfc, 0xef, 0xc5, 0x26,
0x6b, 0xa6, 0x61, 0x17, 0x22, 0x39, 0x5c, 0x90, 0x65, 0x56, 0xbe,
0x52, 0xaf, 0xe3, 0xf5, 0x65, 0x63, 0x6a, 0xd1, 0xb1, 0x7d, 0x50,
0x8b, 0x73, 0xd8, 0x74, 0x3e, 0xeb, 0x52, 0x4b, 0xe2, 0x2b, 0x3d,
0xcb, 0xc2, 0xc7, 0x46, 0x8d, 0x54, 0x11, 0x9c, 0x74, 0x68, 0x44,
0x9a, 0x13, 0xd8, 0xe3, 0xb9, 0x58, 0x11, 0xa1, 0x98, 0xf3, 0x49,
0x1d, 0xe3, 0xe7, 0xfe, 0x94, 0x2b, 0x33, 0x04, 0x07, 0xab, 0xf8,
0x2a, 0x4e, 0xd7, 0xc1, 0xb3, 0x11, 0x66, 0x3a, 0xc6, 0x98, 0x90,
0xf4, 0x15, 0x70, 0x15, 0x85, 0x3d, 0x91, 0xe9, 0x23, 0x03, 0x7c,
0x22, 0x7a, 0x33, 0xcd, 0xd5, 0xec, 0x28, 0x1c, 0xa3, 0xf7, 0x9c,
0x44, 0x54, 0x6b, 0x9d, 0x90, 0xca, 0x00, 0xf0, 0x64, 0xc9, 0x9e,
0x3d, 0xd9, 0x79, 0x11, 0xd3, 0x9f, 0xe9, 0xc5, 0xd0, 0xb2, 0x3a,
0x22, 0x9a, 0x23, 0x4c, 0xb3, 0x61, 0x86, 0xc4, 0x81, 0x9e, 0x8b,
0x9c, 0x59, 0x27, 0x72, 0x66, 0x32, 0x29, 0x1d, 0x6a, 0x41, 0x82,
0x11, 0xcc, 0x29, 0x62, 0xe2, 0x0f, 0xe4, 0x7f, 0xeb, 0x3e, 0xdf,
0x33, 0x0f, 0x2c, 0x60, 0x3a, 0x9d, 0x48, 0xc0, 0xfc, 0xb5, 0x69,
0x9d, 0xbf, 0xe5, 0x89, 0x64, 0x25, 0xc5, 0xba, 0xc4, 0xae, 0xe8,
0x2e, 0x57, 0xa8, 0x5a, 0xaf, 0x4e, 0x25, 0x13, 0xe4, 0xf0, 0x57,
0x96, 0xb0, 0x7b, 0xa2, 0xee, 0x47, 0xd8, 0x05, 0x06, 0xf8, 0xd2,
0xc2, 0x5e, 0x50, 0xfd, 0x14, 0xde, 0x71, 0xe6, 0xc4, 0x18, 0x55,
0x93, 0x02, 0xf9, 0x39, 0xb0, 0xe1, 0xab, 0xd5, 0x76, 0xf2, 0x79,
0xc4, 0xb2, 0xe0, 0xfe, 0xb8, 0x5c, 0x1f, 0x28, 0xff, 0x18, 0xf5,
0x88, 0x91, 0xff, 0xef, 0x13, 0x2e, 0xef, 0x2f, 0xa0, 0x93, 0x46,
0xae, 0xe3, 0x3c, 0x28, 0xeb, 0x13, 0x0f, 0xf2, 0x8f, 0x5b, 0x76,
0x69, 0x53, 0x33, 0x41, 0x13, 0x21, 0x19, 0x96, 0xd2, 0x00, 0x11,
0xa1, 0x98, 0xe3, 0xfc, 0x43, 0x3f, 0x9f, 0x25, 0x41, 0x01, 0x0a,
0xe1, 0x7c, 0x1b, 0xf2, 0x02, 0x58, 0x0f, 0x60, 0x47, 0x47, 0x2f,
0xb3, 0x68, 0x57, 0xfe, 0x84, 0x3b, 0x19, 0xf5, 0x98, 0x40, 0x09,
0xdd, 0xc3, 0x24, 0x04, 0x4e, 0x84, 0x7a, 0x4f, 0x4a, 0x0a, 0xb3,
0x4f, 0x71, 0x95, 0x95, 0xde, 0x37, 0x25, 0x2d, 0x62, 0x35, 0x36,
0x5e, 0x9b, 0x84, 0x39, 0x2b, 0x06, 0x10, 0x85, 0x34, 0x9d, 0x73,
0x20, 0x3a, 0x4a, 0x13, 0xe9, 0x6f, 0x54, 0x32, 0xec, 0x0f, 0xd4,
0xa1, 0xee, 0x65, 0xac, 0xcd, 0xd5, 0xe3, 0x90, 0x4d, 0xf5, 0x4c,
0x1d, 0xa5, 0x10, 0xb0, 0xff, 0x20, 0xdc, 0xc0, 0xc7, 0x7f, 0xcb,
0x2c, 0x0e, 0x0e, 0xb6, 0x05, 0xcb, 0x05, 0x04, 0xdb, 0x87, 0x63,
0x2c, 0xf3, 0xd8, 0xb4, 0xda, 0xe6, 0xe7, 0x05, 0x76, 0x9d, 0x1d,
0xe3, 0x54, 0x27, 0x01, 0x23, 0xcb, 0x11, 0x45, 0x0e, 0xfc, 0x60,
0xac, 0x47, 0x68, 0x3d, 0x7b, 0x8d, 0x0f, 0x81, 0x13, 0x65, 0x56,
0x5f, 0xd9, 0x8c, 0x4c, 0x8e, 0xb9, 0x36, 0xbc, 0xab, 0x8d, 0x06,
0x9f, 0xc3, 0x3b, 0xd8, 0x01, 0xb0, 0x3a, 0xde, 0xa2, 0xe1, 0xfb,
0xc5, 0xaa, 0x46, 0x3d, 0x08, 0xca, 0x19, 0x89, 0x6d, 0x2b, 0xf5,
0x9a, 0x07, 0x1b, 0x85, 0x1e, 0x6c, 0x23, 0x90, 0x52, 0x17, 0x2f,
0x29, 0x6b, 0xfb, 0x5e, 0x72, 0x40, 0x47, 0x90, 0xa2, 0x18, 0x10,
0x14, 0xf3, 0xb9, 0x4a, 0x4e, 0x97, 0xd1, 0x17, 0xb4, 0x38, 0x13,
0x03, 0x68, 0xcc, 0x39, 0xdb, 0xb2, 0xd1, 0x98, 0x06, 0x5a, 0xe3,
0x98, 0x65, 0x47, 0x92, 0x6c, 0xd2, 0x16, 0x2f, 0x40, 0xa2, 0x9f,
0x0c, 0x3c, 0x87, 0x45, 0xc0, 0xf5, 0x0f, 0xba, 0x38, 0x52, 0xe5,
0x66, 0xd4, 0x45, 0x75, 0xc2, 0x9d, 0x39, 0xa0, 0x3f, 0x0c, 0xda,
0x72, 0x19, 0x84, 0xb6, 0xf4, 0x40, 0x59, 0x1f, 0x35, 0x5e, 0x12,
0xd4, 0x39, 0xff, 0x15, 0x0a, 0xab, 0x76, 0x13, 0x49, 0x9d, 0xbd,
0x49, 0xad, 0xab, 0xc8, 0x67, 0x6e, 0xef, 0x02, 0x3b, 0x15, 0xb6,
0x5b, 0xfc, 0x5c, 0xa0, 0x69, 0x48, 0x10, 0x9f, 0x23, 0xf3, 0x50,
0xdb, 0x82, 0x12, 0x35, 0x35, 0xeb, 0x8a, 0x74, 0x33, 0xbd, 0xab,
0xcb, 0x90, 0x92, 0x71, 0xa6, 0xec, 0xbc, 0xb5, 0x8b, 0x93, 0x6a,
0x88, 0xcd, 0x4e, 0x8f, 0x2e, 0x6f, 0xf5, 0x80, 0x01, 0x75, 0xf1,
0x13, 0x25, 0x3d, 0x8f, 0xa9, 0xca, 0x88, 0x85, 0xc2, 0xf5, 0x52,
0xe6, 0x57, 0xdc, 0x60, 0x3f, 0x25, 0x2e, 0x1a, 0x8e, 0x30, 0x8f,
0x76, 0xf0, 0xbe, 0x79, 0xe2, 0xfb, 0x8f, 0x5d, 0x5f, 0xbb, 0xe2,
0xe3, 0x0e, 0xca, 0xdd, 0x22, 0x07, 0x23, 0xc8, 0xc0, 0xae, 0xa8,
0x07, 0x8c, 0xdf, 0xcb, 0x38, 0x68, 0x26, 0x3f, 0xf8, 0xf0, 0x94,
0x00, 0x54, 0xda, 0x48, 0x78, 0x18, 0x93, 0xa7, 0xe4, 0x9a, 0xd5,
0xaf, 0xf4, 0xaf, 0x30, 0x0c, 0xd8, 0x04, 0xa6, 0xb6, 0x27, 0x9a,
0xb3, 0xff, 0x3a, 0xfb, 0x64, 0x49, 0x1c, 0x85, 0x19, 0x4a, 0xab,
0x76, 0x0d, 0x58, 0xa6, 0x06, 0x65, 0x4f, 0x9f, 0x44, 0x00, 0xe8,
0xb3, 0x85, 0x91, 0x35, 0x6f, 0xbf, 0x64, 0x25, 0xac, 0xa2, 0x6d,
0xc8, 0x52, 0x44, 0x25, 0x9f, 0xf2, 0xb1, 0x9c, 0x41, 0xb9, 0xf9,
0x6f, 0x3c, 0xa9, 0xec, 0x1d, 0xde, 0x43, 0x4d, 0xa7, 0xd2, 0xd3,
0x92, 0xb9, 0x05, 0xdd, 0xf3, 0xd1, 0xf9, 0xaf, 0x93, 0xd1, 0xaf,
0x59, 0x50, 0xbd, 0x49, 0x3f, 0x5a, 0xa7, 0x31, 0xb4, 0x05, 0x6d,
0xf3, 0x1b, 0xd2, 0x67, 0xb6, 0xb9, 0x0a, 0x07, 0x98, 0x31, 0xaa,
0xf5, 0x79, 0xbe, 0x0a, 0x39, 0x01, 0x31, 0x37, 0xaa, 0xc6, 0xd4,
0x04, 0xf5, 0x18, 0xcf, 0xd4, 0x68, 0x40, 0x64, 0x7e, 0x78, 0xbf,
0xe7, 0x06, 0xca, 0x4c, 0xf5, 0xe9, 0xc5, 0x45, 0x3e, 0x9f, 0x7c,
0xfd, 0x2b, 0x8b, 0x4c, 0x8d, 0x16, 0x9a, 0x44, 0xe5, 0x5c, 0x88,
0xd4, 0xa9, 0xa7, 0xf9, 0x47, 0x42, 0x41, 0x10, 0x92, 0xab, 0xbd,
0xf8, 0xb8, 0x89, 0xe5, 0xc1, 0x99, 0xd0, 0x96, 0xe3, 0xf2, 0x47,
0x88,
];
assert_encrypt_initial_pkt(
&mut header,
&dcid,
&frames,
2,
4,
false,
&pkt,
);
}
#[test]
fn encrypt_server_initial_v1() {
let mut header = [
0xc1, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50,
0x2a, 0x42, 0x62, 0xb5, 0x00, 0x40, 0x75, 0x00, 0x01,
];
let dcid = [0x83, 0x94, 0xc8, 0xf0, 0x3e, 0x51, 0x57, 0x08];
let frames = [
0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x40, 0x5a, 0x02, 0x00,
0x00, 0x56, 0x03, 0x03, 0xee, 0xfc, 0xe7, 0xf7, 0xb3, 0x7b, 0xa1,
0xd1, 0x63, 0x2e, 0x96, 0x67, 0x78, 0x25, 0xdd, 0xf7, 0x39, 0x88,
0xcf, 0xc7, 0x98, 0x25, 0xdf, 0x56, 0x6d, 0xc5, 0x43, 0x0b, 0x9a,
0x04, 0x5a, 0x12, 0x00, 0x13, 0x01, 0x00, 0x00, 0x2e, 0x00, 0x33,
0x00, 0x24, 0x00, 0x1d, 0x00, 0x20, 0x9d, 0x3c, 0x94, 0x0d, 0x89,
0x69, 0x0b, 0x84, 0xd0, 0x8a, 0x60, 0x99, 0x3c, 0x14, 0x4e, 0xca,
0x68, 0x4d, 0x10, 0x81, 0x28, 0x7c, 0x83, 0x4d, 0x53, 0x11, 0xbc,
0xf3, 0x2b, 0xb9, 0xda, 0x1a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
];
let pkt = [
0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50,
0x2a, 0x42, 0x62, 0xb5, 0x00, 0x40, 0x75, 0xc0, 0xd9, 0x5a, 0x48,
0x2c, 0xd0, 0x99, 0x1c, 0xd2, 0x5b, 0x0a, 0xac, 0x40, 0x6a, 0x58,
0x16, 0xb6, 0x39, 0x41, 0x00, 0xf3, 0x7a, 0x1c, 0x69, 0x79, 0x75,
0x54, 0x78, 0x0b, 0xb3, 0x8c, 0xc5, 0xa9, 0x9f, 0x5e, 0xde, 0x4c,
0xf7, 0x3c, 0x3e, 0xc2, 0x49, 0x3a, 0x18, 0x39, 0xb3, 0xdb, 0xcb,
0xa3, 0xf6, 0xea, 0x46, 0xc5, 0xb7, 0x68, 0x4d, 0xf3, 0x54, 0x8e,
0x7d, 0xde, 0xb9, 0xc3, 0xbf, 0x9c, 0x73, 0xcc, 0x3f, 0x3b, 0xde,
0xd7, 0x4b, 0x56, 0x2b, 0xfb, 0x19, 0xfb, 0x84, 0x02, 0x2f, 0x8e,
0xf4, 0xcd, 0xd9, 0x37, 0x95, 0xd7, 0x7d, 0x06, 0xed, 0xbb, 0x7a,
0xaf, 0x2f, 0x58, 0x89, 0x18, 0x50, 0xab, 0xbd, 0xca, 0x3d, 0x20,
0x39, 0x8c, 0x27, 0x64, 0x56, 0xcb, 0xc4, 0x21, 0x58, 0x40, 0x7d,
0xd0, 0x74, 0xee,
];
assert_encrypt_initial_pkt(&mut header, &dcid, &frames, 1, 2, true, &pkt);
}
#[test]
fn encrypt_chacha20() {
let secret = [
0x9a, 0xc3, 0x12, 0xa7, 0xf8, 0x77, 0x46, 0x8e, 0xbe, 0x69, 0x42,
0x27, 0x48, 0xad, 0x00, 0xa1, 0x54, 0x43, 0xf1, 0x82, 0x03, 0xa0,
0x7d, 0x60, 0x60, 0xf6, 0x88, 0xf3, 0x0f, 0x21, 0x63, 0x2b,
];
let mut header = [0x42, 0x00, 0xbf, 0xf4];
let expected_pkt = [
0x4c, 0xfe, 0x41, 0x89, 0x65, 0x5e, 0x5c, 0xd5, 0x5c, 0x41, 0xf6,
0x90, 0x80, 0x57, 0x5d, 0x79, 0x99, 0xc2, 0x5a, 0x5b, 0xfb,
];
let mut b = octets::OctetsMut::with_slice(&mut header);
let hdr = Header::from_bytes(&mut b, 0).unwrap();
assert_eq!(hdr.ty, Type::Short);
let mut out = vec![0; expected_pkt.len()];
let mut b = octets::OctetsMut::with_slice(&mut out);
b.put_bytes(&header).unwrap();
let alg = crypto::Algorithm::ChaCha20_Poly1305;
let aead = crypto::Seal::from_secret(alg, &secret).unwrap();
let pn = 654_360_564;
let pn_len = 3;
let frames = [0x01];
let payload_len = frames.len();
let payload_offset = b.off();
b.put_bytes(&frames).unwrap();
let written = encrypt_pkt(
&mut b,
pn,
pn_len,
payload_len,
payload_offset,
None,
&aead,
)
.unwrap();
assert_eq!(written, expected_pkt.len());
assert_eq!(&out[..written], &expected_pkt[..]);
}
#[test]
fn decrypt_pkt_underflow() {
let mut buf = [0; 65535];
let mut b = octets::OctetsMut::with_slice(&mut buf);
let hdr = Header {
ty: Type::Initial,
version: crate::PROTOCOL_VERSION,
dcid: ConnectionId::default(),
scid: ConnectionId::default(),
pkt_num: 0,
pkt_num_len: 0,
token: None,
versions: None,
key_phase: false,
};
hdr.to_bytes(&mut b).unwrap();
b.put_bytes(&[0; 50]).unwrap();
let payload_len = b.get_varint().unwrap() as usize;
let (aead, _) =
crypto::derive_initial_key_material(b"", hdr.version, true).unwrap();
assert_eq!(
decrypt_pkt(&mut b, 0, 1, payload_len, &aead),
Err(Error::InvalidPacket)
);
}
#[test]
fn decrypt_pkt_too_small() {
let mut buf = [0; 65535];
let mut b = octets::OctetsMut::with_slice(&mut buf);
let hdr = Header {
ty: Type::Initial,
version: crate::PROTOCOL_VERSION,
dcid: ConnectionId::default(),
scid: ConnectionId::default(),
pkt_num: 0,
pkt_num_len: 0,
token: None,
versions: None,
key_phase: false,
};
hdr.to_bytes(&mut b).unwrap();
b.put_bytes(&[0; 1]).unwrap();
let payload_len = 1;
let (aead, _) =
crypto::derive_initial_key_material(b"", hdr.version, true).unwrap();
assert_eq!(
decrypt_pkt(&mut b, 0, 1, payload_len, &aead),
Err(Error::CryptoFail)
);
}
}