Skip to content

Commit 874abdc

Browse files
authored
QUIC: fix small bugs in size calculation (#4685)
1 parent d63f54e commit 874abdc

3 files changed

Lines changed: 104 additions & 11 deletions

File tree

scapy/layers/quic.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
MultipleTypeField,
3636
ShortField,
3737
StrLenField,
38+
ThreeBytesField,
3839
)
3940

4041
# Typing imports
@@ -80,9 +81,9 @@ def addfield(self, pkt: Packet, s: bytes, val: Optional[int]):
8081
elif val < 0x4000:
8182
return s + struct.pack("!H", val | 0x4000)
8283
elif val < 0x40000000:
83-
return s + struct.pack("!I", val | 0x40000000)
84+
return s + struct.pack("!I", val | 0x80000000)
8485
else:
85-
return s + struct.pack("!Q", val | 0x4000000000000000)
86+
return s + struct.pack("!Q", val | 0xC000000000000000)
8687

8788
def getfield(self, pkt: Packet, s: bytes) -> Tuple[bytes, int]:
8889
length = (s[0] & 0xC0) >> 6
@@ -185,7 +186,7 @@ class QUIC_Version(QUIC):
185186
IntField("Version", 0),
186187
FieldLenField("DstConnIDLen", None, length_of="DstConnID", fmt="B"),
187188
StrLenField("DstConnID", "", length_from=lambda pkt: pkt.DstConnIDLen),
188-
FieldLenField("SrcConnIDLen", None, length_of="DstConnID", fmt="B"),
189+
FieldLenField("SrcConnIDLen", None, length_of="SrcConnID", fmt="B"),
189190
StrLenField("SrcConnID", "", length_from=lambda pkt: pkt.SrcConnIDLen),
190191
FieldListField("SupportedVersions", [], IntField("", 0)),
191192
]
@@ -195,9 +196,34 @@ class QUIC_Version(QUIC):
195196

196197
QuicPacketNumberField = lambda name, default: MultipleTypeField(
197198
[
198-
(ByteField(name, default), lambda pkt: pkt.PacketNumberLen == 0),
199-
(ShortField(name, default), lambda pkt: pkt.PacketNumberLen == 1),
200-
(IntField(name, default), lambda pkt: pkt.PacketNumberLen == 2),
199+
(
200+
ByteField(name, default),
201+
(
202+
lambda pkt: pkt.PacketNumberLen == 0,
203+
lambda _, val: val < 0x100,
204+
),
205+
),
206+
(
207+
ShortField(name, default),
208+
(
209+
lambda pkt: pkt.PacketNumberLen == 1,
210+
lambda _, val: val < 0x10000,
211+
),
212+
),
213+
(
214+
ThreeBytesField(name, default),
215+
(
216+
lambda pkt: pkt.PacketNumberLen == 2,
217+
lambda _, val: val < 0x1000000,
218+
),
219+
),
220+
(
221+
IntField(name, default),
222+
(
223+
lambda pkt: pkt.PacketNumberLen == 3,
224+
lambda _, val: val < 0x100000000,
225+
),
226+
),
201227
],
202228
ByteField(name, default),
203229
)
@@ -213,7 +239,7 @@ def i2m(self, pkt, x):
213239
return 0
214240
elif PacketNumber < 0x10000:
215241
return 1
216-
elif PacketNumber < 0x100000000:
242+
elif PacketNumber < 0x1000000:
217243
return 2
218244
else:
219245
return 3

test/scapy/layers/quic.uts

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,76 @@ assert pkt.DstConnID == b"c_cid"
4242
assert pkt.SrcConnID == b"s_cid"
4343
assert pkt.PacketNumber == 1
4444

45-
= QUIC - Build Client Initial Packet
45+
= QUIC - QuicPacketNumberField / QuicPacketNumberBitFieldLenField - variable lengths
4646

4747
from scapy.layers.quic import *
4848

49-
pkt = QUIC_Initial(PacketNumberLen=3, DstConnID=b'p\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR', SrcConnID=b'\xf7\x10Q', PacketNumber=116)
50-
assert bytes(pkt) == b'\xc3\x00\x00\x00\x01\x0fp\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR\x0f\xf7\x10Q\x00\x00t'
49+
pkt = QUIC_Initial(DstConnID=b'p\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR', SrcConnID=b'\xf7\x10Q', PacketNumber=0xFF)
50+
assert bytes(pkt) == b'\xc0\x00\x00\x00\x01\x0fp\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR\x03\xf7\x10Q\x00\x00\xff'
51+
pkt = QUIC_Initial(bytes(pkt))
52+
assert pkt.DstConnIDLen == 15
53+
assert pkt.SrcConnIDLen == 3
54+
assert pkt.PacketNumberLen == 0
55+
assert pkt.PacketNumber == 0xFF
56+
57+
pkt = QUIC_Initial(DstConnID=b'p\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR', SrcConnID=b'\xf7\x10Q', PacketNumber=0xFFFF)
58+
assert bytes(pkt) == b'\xc1\x00\x00\x00\x01\x0fp\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR\x03\xf7\x10Q\x00\x00\xff\xff'
59+
pkt = QUIC_Initial(bytes(pkt))
60+
assert pkt.PacketNumberLen == 1
61+
assert pkt.PacketNumber == 0xFFFF
62+
63+
pkt = QUIC_Initial(DstConnID=b'p\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR', SrcConnID=b'\xf7\x10Q', PacketNumber=0xFFFFFF)
64+
assert bytes(pkt) == b'\xc2\x00\x00\x00\x01\x0fp\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR\x03\xf7\x10Q\x00\x00\xff\xff\xff'
65+
pkt = QUIC_Initial(bytes(pkt))
66+
assert pkt.PacketNumberLen == 2
67+
assert pkt.PacketNumber == 0xFFFFFF
68+
69+
pkt = QUIC_Initial(DstConnID=b'p\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR', SrcConnID=b'\xf7\x10Q', PacketNumber=0xFFFFFFFF)
70+
assert bytes(pkt) == b'\xc3\x00\x00\x00\x01\x0fp\xa2\x8e@\x96\xc5}\xd0\xff\xb6\xc3\xd8\x1b\xcaR\x03\xf7\x10Q\x00\x00\xff\xff\xff\xff'
71+
pkt = QUIC_Initial(bytes(pkt))
72+
assert pkt.PacketNumberLen == 3
73+
assert pkt.PacketNumber == 0xFFFFFFFF
74+
75+
= QUIC - QuicPacketNumberField / QuicPacketNumberBitFieldLenField - Out of range
76+
77+
import struct
78+
from scapy.layers.quic import *
79+
80+
try:
81+
pkt = QUIC_Initial(PacketNumber=0xFFFFFFFFFF)
82+
bytes(pkt)
83+
assert False, "QUIC Packet Number length should fail"
84+
except struct.error:
85+
pass
86+
87+
= QUIC - QuicVarIntField - variable lengths
88+
89+
from scapy.layers.quic import *
90+
91+
pkt = QUIC_Initial(Length=1)
92+
assert bytes(pkt) == b'\xc0\x00\x00\x00\x01\x00\x00\x00\x01\x00'
93+
assert QUIC_Initial(bytes(pkt)).Length == 1
94+
95+
pkt = QUIC_Initial(Length=1 << 9)
96+
assert bytes(pkt) == b'\xc0\x00\x00\x00\x01\x00\x00\x00B\x00\x00'
97+
assert QUIC_Initial(bytes(pkt)).Length == 1 << 9
98+
99+
pkt = QUIC_Initial(Length=1 << 17)
100+
assert bytes(pkt) == b'\xc0\x00\x00\x00\x01\x00\x00\x00\x80\x02\x00\x00\x00'
101+
assert QUIC_Initial(bytes(pkt)).Length == 1 << 17
102+
103+
pkt = QUIC_Initial(Length=4611686018427387903)
104+
assert bytes(pkt) == b'\xc0\x00\x00\x00\x01\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00'
105+
assert QUIC_Initial(bytes(pkt)).Length == 4611686018427387903
106+
107+
= QUIC - QuicVarIntField - Out of range
108+
109+
import struct
110+
from scapy.layers.quic import *
111+
112+
try:
113+
pkt = QUIC_Initial(Length=0xFFFFFFFFFFFFFFFF)
114+
bytes(pkt)
115+
assert False, "QUIC Variable length should fail"
116+
except struct.error:
117+
pass

test/scapy/layers/tls/tls13.uts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ tp = TLS_Ext_QUICTransportParameters(params=[
12811281
actual = tp.build()
12821282

12831283
# the expected data is extracted from the ClientHello above
1284-
expect = bytes.fromhex("0039004601015388030145460401409896800501400f42400601400f42400701400f424008014064090140640a01030b01190c000f142173071905d778f98e367b8ad8eeb526484e8f5d")
1284+
expect = bytes.fromhex("0039004601015388030145460401809896800501800f42400601800f42400701800f424008014064090140640a01030b01190c000f142173071905d778f98e367b8ad8eeb526484e8f5d")
12851285

12861286
assert actual == expect
12871287

0 commit comments

Comments
 (0)