]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
quic: v2 support per rfc 9369 9539/head
authorPhilippe Antoine <pantoine@oisf.net>
Wed, 27 Sep 2023 11:08:33 +0000 (13:08 +0200)
committerVictor Julien <victor@inliniac.net>
Tue, 3 Oct 2023 07:29:31 +0000 (09:29 +0200)
Ticket: #4968

rust/src/quic/crypto.rs
rust/src/quic/parser.rs

index 9b2857efef2467ff89b77501a466de4550aed602..d40e84527468c0deb9d7d64b028c2550994384e9 100644 (file)
@@ -32,10 +32,15 @@ pub const AES128_IV_LEN: usize = 12;
 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)));
     }
 
@@ -70,17 +75,27 @@ pub struct PacketKey {
 }
 
 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;
     }
 
@@ -111,10 +126,10 @@ pub struct DirectionalKeys {
 }
 
 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),
         }
     }
 }
@@ -163,6 +178,11 @@ pub fn quic_keys_initial(version: u32, client_dst_connection_id: &[u8]) -> Optio
             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;
         }
@@ -174,7 +194,7 @@ pub fn quic_keys_initial(version: u32, client_dst_connection_id: &[u8]) -> Optio
     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),
     });
 }
index 5d9d700080b042ee99b7e26b1f789ad121c6f8f5..126973633bac69b1ca0bf1208100dfaa0fc11518 100644 (file)
@@ -44,6 +44,7 @@ impl QuicVersion {
     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
@@ -61,6 +62,7 @@ impl From<QuicVersion> for String {
             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),
         }
     }
@@ -286,7 +288,18 @@ impl QuicHeader {
                             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,