pub struct HeaderProtectionKey(Aes128);
impl HeaderProtectionKey {
- fn new(secret: &[u8]) -> Self {
+ fn new(secret: &[u8], version: u32) -> Self {
let hk = Hkdf::<Sha256>::from_prk(secret).unwrap();
let mut secret = [0u8; AES128_KEY_LEN];
- hkdf_expand_label(&hk, b"quic hp", &mut secret, AES128_KEY_LEN as u16);
+ let quichp = if version == 0x6b3343cf {
+ b"quicv2 hp" as &[u8]
+ } else {
+ b"quic hp" as &[u8]
+ };
+ hkdf_expand_label(&hk, quichp, &mut secret, AES128_KEY_LEN as u16);
return Self(Aes128::new(GenericArray::from_slice(&secret)));
}
}
impl PacketKey {
- fn new(secret: &[u8]) -> Self {
+ fn new(secret: &[u8], version: u32) -> Self {
let hk = Hkdf::<Sha256>::from_prk(secret).unwrap();
let mut secret = [0u8; AES128_KEY_LEN];
- hkdf_expand_label(&hk, b"quic key", &mut secret, AES128_KEY_LEN as u16);
+ let quickey = if version == 0x6b3343cf {
+ b"quicv2 key" as &[u8]
+ } else {
+ b"quic key" as &[u8]
+ };
+ hkdf_expand_label(&hk, quickey, &mut secret, AES128_KEY_LEN as u16);
let key = Aes128Gcm::new(GenericArray::from_slice(&secret));
let mut r = PacketKey {
key,
iv: [0u8; AES128_IV_LEN],
};
- hkdf_expand_label(&hk, b"quic iv", &mut r.iv, AES128_IV_LEN as u16);
+ let quiciv = if version == 0x6b3343cf {
+ b"quicv2 iv" as &[u8]
+ } else {
+ b"quic iv" as &[u8]
+ };
+ hkdf_expand_label(&hk, quiciv, &mut r.iv, AES128_IV_LEN as u16);
return r;
}
}
impl DirectionalKeys {
- fn new(secret: &[u8]) -> Self {
+ fn new(secret: &[u8], version: u32) -> Self {
Self {
- header: HeaderProtectionKey::new(secret),
- packet: PacketKey::new(secret),
+ header: HeaderProtectionKey::new(secret, version),
+ packet: PacketKey::new(secret, version),
}
}
}
0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17, 0x9a, 0xe6, 0xa4, 0xc8,
0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a,
],
+ 0x6b3343cf => &[
+ // https://www.rfc-editor.org/rfc/rfc9369.html#section-3.3.1
+ 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93, 0x81, 0xbe, 0x6e, 0x26,
+ 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9,
+ ],
_ => {
return None;
}
hkdf_expand_label(&hk, b"server in", &mut server_secret, 32);
return Some(QuicKeys {
- local: DirectionalKeys::new(&server_secret),
- remote: DirectionalKeys::new(&client_secret),
+ local: DirectionalKeys::new(&server_secret, version),
+ remote: DirectionalKeys::new(&client_secret, version),
});
}
pub const Q044: QuicVersion = QuicVersion(0x51303434);
pub const Q045: QuicVersion = QuicVersion(0x51303435);
pub const Q046: QuicVersion = QuicVersion(0x51303436);
+ pub const V2: QuicVersion = QuicVersion(0x6b3343cf);
fn is_gquic(&self) -> bool {
*self == QuicVersion::Q043
QuicVersion(0x51303434) => "Q044".to_string(),
QuicVersion(0x51303435) => "Q045".to_string(),
QuicVersion(0x51303436) => "Q046".to_string(),
+ QuicVersion(0x6b3343cf) => "v2".to_string(),
QuicVersion(x) => format!("{:x}", x),
}
}
return Err(nom7::Err::Error(QuicError::InvalidPacket));
}
}
+ } else if version == QuicVersion::V2 {
+ match (first & 0x30) >> 4 {
+ 0x01 => QuicType::Initial,
+ 0x02 => QuicType::ZeroRTT,
+ 0x03 => QuicType::Handshake,
+ 0x00 => QuicType::Retry,
+ _ => {
+ return Err(nom7::Err::Error(QuicError::InvalidPacket));
+ }
+ }
} else {
+ // consider as Quic version 1 (and latest drafts)
match (first & 0x30) >> 4 {
0x00 => QuicType::Initial,
0x01 => QuicType::ZeroRTT,