github.com/tumi8/quic-go@v0.37.4-tum/fuzzing/tokens/fuzz.go (about)

     1  package tokens
     2  
     3  import (
     4  	"encoding/binary"
     5  	"math/rand"
     6  	"net"
     7  	"time"
     8  
     9  	"github.com/tumi8/quic-go/noninternal/handshake"
    10  	"github.com/tumi8/quic-go/noninternal/protocol"
    11  )
    12  
    13  func Fuzz(data []byte) int {
    14  	if len(data) < 8 {
    15  		return -1
    16  	}
    17  	seed := binary.BigEndian.Uint64(data[:8])
    18  	data = data[8:]
    19  	tg, err := handshake.NewTokenGenerator(rand.New(rand.NewSource(int64(seed))))
    20  	if err != nil {
    21  		panic(err)
    22  	}
    23  	if len(data) < 1 {
    24  		return -1
    25  	}
    26  	s := data[0] % 3
    27  	data = data[1:]
    28  	switch s {
    29  	case 0:
    30  		tg.DecodeToken(data)
    31  		return 1
    32  	case 1:
    33  		return newToken(tg, data)
    34  	case 2:
    35  		return newRetryToken(tg, data)
    36  	}
    37  	return -1
    38  }
    39  
    40  func newToken(tg *handshake.TokenGenerator, data []byte) int {
    41  	if len(data) < 1 {
    42  		return -1
    43  	}
    44  	usesUDPAddr := data[0]%2 == 0
    45  	data = data[1:]
    46  	if len(data) != 18 {
    47  		return -1
    48  	}
    49  	var addr net.Addr
    50  	if usesUDPAddr {
    51  		addr = &net.UDPAddr{
    52  			Port: int(binary.BigEndian.Uint16(data[:2])),
    53  			IP:   net.IP(data[2:]),
    54  		}
    55  	} else {
    56  		addr = &net.TCPAddr{
    57  			Port: int(binary.BigEndian.Uint16(data[:2])),
    58  			IP:   net.IP(data[2:]),
    59  		}
    60  	}
    61  	start := time.Now()
    62  	encrypted, err := tg.NewToken(addr)
    63  	if err != nil {
    64  		panic(err)
    65  	}
    66  	token, err := tg.DecodeToken(encrypted)
    67  	if err != nil {
    68  		panic(err)
    69  	}
    70  	if token.IsRetryToken {
    71  		panic("didn't encode a Retry token")
    72  	}
    73  	if token.SentTime.Before(start) || token.SentTime.After(time.Now()) {
    74  		panic("incorrect send time")
    75  	}
    76  	if token.OriginalDestConnectionID.Len() > 0 || token.RetrySrcConnectionID.Len() > 0 {
    77  		panic("didn't expect connection IDs")
    78  	}
    79  	return 1
    80  }
    81  
    82  func newRetryToken(tg *handshake.TokenGenerator, data []byte) int {
    83  	if len(data) < 2 {
    84  		return -1
    85  	}
    86  	origDestConnIDLen := int(data[0] % 21)
    87  	retrySrcConnIDLen := int(data[1] % 21)
    88  	data = data[2:]
    89  	if len(data) < origDestConnIDLen {
    90  		return -1
    91  	}
    92  	origDestConnID := protocol.ParseConnectionID(data[:origDestConnIDLen])
    93  	data = data[origDestConnIDLen:]
    94  	if len(data) < retrySrcConnIDLen {
    95  		return -1
    96  	}
    97  	retrySrcConnID := protocol.ParseConnectionID(data[:retrySrcConnIDLen])
    98  	data = data[retrySrcConnIDLen:]
    99  
   100  	if len(data) < 1 {
   101  		return -1
   102  	}
   103  	usesUDPAddr := data[0]%2 == 0
   104  	data = data[1:]
   105  	if len(data) != 18 {
   106  		return -1
   107  	}
   108  	start := time.Now()
   109  	var addr net.Addr
   110  	if usesUDPAddr {
   111  		addr = &net.UDPAddr{
   112  			Port: int(binary.BigEndian.Uint16(data[:2])),
   113  			IP:   net.IP(data[2:]),
   114  		}
   115  	} else {
   116  		addr = &net.TCPAddr{
   117  			Port: int(binary.BigEndian.Uint16(data[:2])),
   118  			IP:   net.IP(data[2:]),
   119  		}
   120  	}
   121  	encrypted, err := tg.NewRetryToken(addr, origDestConnID, retrySrcConnID)
   122  	if err != nil {
   123  		panic(err)
   124  	}
   125  	token, err := tg.DecodeToken(encrypted)
   126  	if err != nil {
   127  		panic(err)
   128  	}
   129  	if !token.IsRetryToken {
   130  		panic("expected a Retry token")
   131  	}
   132  	if token.SentTime.Before(start) || token.SentTime.After(time.Now()) {
   133  		panic("incorrect send time")
   134  	}
   135  	if token.OriginalDestConnectionID != origDestConnID {
   136  		panic("orig dest conn ID doesn't match")
   137  	}
   138  	if token.RetrySrcConnectionID != retrySrcConnID {
   139  		panic("retry src conn ID doesn't match")
   140  	}
   141  	return 1
   142  }