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