mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 20:27:35 +03:00
add a fuzz target for the token generator
This commit is contained in:
parent
556bf18dbf
commit
8b96db3a84
1 changed files with 161 additions and 0 deletions
161
fuzzing/tokens/fuzz.go
Normal file
161
fuzzing/tokens/fuzz.go
Normal file
|
@ -0,0 +1,161 @@
|
|||
package tokens
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/handshake"
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
||||
func Fuzz(data []byte) int {
|
||||
if len(data) < 8 {
|
||||
return -1
|
||||
}
|
||||
seed := binary.BigEndian.Uint64(data[:8])
|
||||
data = data[8:]
|
||||
tg, err := handshake.NewTokenGenerator(rand.New(rand.NewSource(int64(seed))))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if len(data) < 1 {
|
||||
return -1
|
||||
}
|
||||
s := data[0] % 3
|
||||
data = data[1:]
|
||||
switch s {
|
||||
case 0:
|
||||
tg.DecodeToken(data)
|
||||
return 1
|
||||
case 1:
|
||||
return newToken(tg, data)
|
||||
case 2:
|
||||
return newRetryToken(tg, data)
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func newToken(tg *handshake.TokenGenerator, data []byte) int {
|
||||
if len(data) < 1 {
|
||||
return -1
|
||||
}
|
||||
usesUDPAddr := data[0]%2 == 0
|
||||
data = data[1:]
|
||||
if len(data) != 18 {
|
||||
return -1
|
||||
}
|
||||
var addr net.Addr
|
||||
if usesUDPAddr {
|
||||
addr = &net.UDPAddr{
|
||||
Port: int(binary.BigEndian.Uint16(data[:2])),
|
||||
IP: net.IP(data[2:]),
|
||||
}
|
||||
} else {
|
||||
addr = &net.TCPAddr{
|
||||
Port: int(binary.BigEndian.Uint16(data[:2])),
|
||||
IP: net.IP(data[2:]),
|
||||
}
|
||||
}
|
||||
start := time.Now()
|
||||
encrypted, err := tg.NewToken(addr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
token, err := tg.DecodeToken(encrypted)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if token.IsRetryToken {
|
||||
panic("didn't encode a Retry token")
|
||||
}
|
||||
if token.SentTime.Before(start) || token.SentTime.After(time.Now()) {
|
||||
panic("incorrect send time")
|
||||
}
|
||||
if token.OriginalDestConnectionID != nil || token.RetrySrcConnectionID != nil {
|
||||
panic("didn't expect connection IDs")
|
||||
}
|
||||
checkAddr(token.RemoteAddr, addr)
|
||||
return 1
|
||||
}
|
||||
|
||||
func newRetryToken(tg *handshake.TokenGenerator, data []byte) int {
|
||||
if len(data) < 2 {
|
||||
return -1
|
||||
}
|
||||
origDestConnIDLen := int(data[0] % 21)
|
||||
retrySrcConnIDLen := int(data[1] % 21)
|
||||
data = data[2:]
|
||||
if len(data) < origDestConnIDLen {
|
||||
return -1
|
||||
}
|
||||
origDestConnID := protocol.ConnectionID(data[:origDestConnIDLen])
|
||||
data = data[origDestConnIDLen:]
|
||||
if len(data) < retrySrcConnIDLen {
|
||||
return -1
|
||||
}
|
||||
retrySrcConnID := protocol.ConnectionID(data[:retrySrcConnIDLen])
|
||||
data = data[retrySrcConnIDLen:]
|
||||
|
||||
if len(data) < 1 {
|
||||
return -1
|
||||
}
|
||||
usesUDPAddr := data[0]%2 == 0
|
||||
data = data[1:]
|
||||
if len(data) != 18 {
|
||||
return -1
|
||||
}
|
||||
start := time.Now()
|
||||
var addr net.Addr
|
||||
if usesUDPAddr {
|
||||
addr = &net.UDPAddr{
|
||||
Port: int(binary.BigEndian.Uint16(data[:2])),
|
||||
IP: net.IP(data[2:]),
|
||||
}
|
||||
} else {
|
||||
addr = &net.TCPAddr{
|
||||
Port: int(binary.BigEndian.Uint16(data[:2])),
|
||||
IP: net.IP(data[2:]),
|
||||
}
|
||||
}
|
||||
encrypted, err := tg.NewRetryToken(addr, origDestConnID, retrySrcConnID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
token, err := tg.DecodeToken(encrypted)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !token.IsRetryToken {
|
||||
panic("expected a Retry token")
|
||||
}
|
||||
if token.SentTime.Before(start) || token.SentTime.After(time.Now()) {
|
||||
panic("incorrect send time")
|
||||
}
|
||||
if !token.OriginalDestConnectionID.Equal(origDestConnID) {
|
||||
panic("orig dest conn ID doesn't match")
|
||||
}
|
||||
if !token.RetrySrcConnectionID.Equal(retrySrcConnID) {
|
||||
panic("retry src conn ID doesn't match")
|
||||
}
|
||||
checkAddr(token.RemoteAddr, addr)
|
||||
return 1
|
||||
}
|
||||
|
||||
func checkAddr(tokenAddr string, addr net.Addr) {
|
||||
if udpAddr, ok := addr.(*net.UDPAddr); ok {
|
||||
// For UDP addresses, we encode only the IP (not the port).
|
||||
if ip := udpAddr.IP.String(); tokenAddr != ip {
|
||||
fmt.Printf("%s vs %s", tokenAddr, ip)
|
||||
panic("wrong remote address for a net.UDPAddr")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if tokenAddr != addr.String() {
|
||||
fmt.Printf("%s vs %s", tokenAddr, addr.String())
|
||||
panic("wrong remote address")
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue