github.com/3andne/restls-client-go@v0.1.6/u_quic_transport_parameters.go (about) 1 package tls 2 3 import ( 4 "crypto/rand" 5 "encoding/binary" 6 "math" 7 "math/big" 8 9 "github.com/3andne/restls-client-go/quicvarint" 10 ) 11 12 const ( 13 // RFC IDs 14 max_idle_timeout uint64 = 0x1 15 max_udp_payload_size uint64 = 0x3 16 initial_max_data uint64 = 0x4 17 initial_max_stream_data_bidi_local uint64 = 0x5 18 initial_max_stream_data_bidi_remote uint64 = 0x6 19 initial_max_stream_data_uni uint64 = 0x7 20 initial_max_streams_bidi uint64 = 0x8 21 initial_max_streams_uni uint64 = 0x9 22 max_ack_delay uint64 = 0xb 23 disable_active_migration uint64 = 0xc 24 active_connection_id_limit uint64 = 0xe 25 initial_source_connection_id uint64 = 0xf 26 version_information uint64 = 0x11 // RFC 9368 27 padding uint64 = 0x15 28 max_datagram_frame_size uint64 = 0x20 // RFC 9221 29 grease_quic_bit uint64 = 0x2ab2 30 31 // Legacy IDs from draft 32 version_information_legacy uint64 = 0xff73db // draft-ietf-quic-version-negotiation-13 and early 33 ) 34 35 type TransportParameters []TransportParameter 36 37 func (tps TransportParameters) Marshal() []byte { 38 var b []byte 39 for _, tp := range tps { 40 b = quicvarint.Append(b, tp.ID()) 41 b = quicvarint.Append(b, uint64(len(tp.Value()))) 42 b = append(b, tp.Value()...) 43 } 44 return b 45 } 46 47 // TransportParameter represents a QUIC transport parameter. 48 // 49 // Caller will write the following to the wire: 50 // 51 // var b []byte 52 // b = quicvarint.Append(b, ID()) 53 // b = quicvarint.Append(b, len(Value())) 54 // b = append(b, Value()) 55 // 56 // Therefore Value() should return the exact bytes to be written to the wire AFTER the length field, 57 // i.e., the bytes MAY be a Variable Length Integer per RFC depending on the type of the transport 58 // parameter, but MUST NOT including the length field unless the parameter is defined so. 59 type TransportParameter interface { 60 ID() uint64 61 Value() []byte 62 } 63 64 type GREASETransportParameter struct { 65 IdOverride uint64 // if set to a valid GREASE ID, use this instead of randomly generated one. 66 Length uint16 // if len(ValueOverride) == 0, will generate random data of this size. 67 ValueOverride []byte // if len(ValueOverride) > 0, use this instead of random bytes. 68 } 69 70 const ( 71 GREASE_MAX_MULTIPLIER = (0x3FFFFFFFFFFFFFFF - 27) / 31 72 ) 73 74 // IsGREASEID returns true if id is a valid GREASE ID for 75 // transport parameters. 76 func (GREASETransportParameter) IsGREASEID(id uint64) bool { 77 return id >= 27 && (id-27)%31 == 0 78 } 79 80 // GetGREASEID returns a random valid GREASE ID for transport parameters. 81 func (GREASETransportParameter) GetGREASEID() uint64 { 82 max := big.NewInt(GREASE_MAX_MULTIPLIER) 83 84 randMultiply, err := rand.Int(rand.Reader, max) 85 if err != nil { 86 return 27 87 } 88 89 return 27 + randMultiply.Uint64()*31 90 } 91 92 func (g *GREASETransportParameter) ID() uint64 { 93 if !g.IsGREASEID(g.IdOverride) { 94 g.IdOverride = g.GetGREASEID() 95 } 96 return g.IdOverride 97 } 98 99 func (g *GREASETransportParameter) Value() []byte { 100 if len(g.ValueOverride) == 0 { 101 g.ValueOverride = make([]byte, g.Length) 102 rand.Read(g.ValueOverride) 103 } 104 return g.ValueOverride 105 } 106 107 type MaxIdleTimeout uint64 // in milliseconds 108 109 func (MaxIdleTimeout) ID() uint64 { 110 return max_idle_timeout 111 } 112 113 func (m MaxIdleTimeout) Value() []byte { 114 return quicvarint.Append([]byte{}, uint64(m)) 115 } 116 117 type MaxUDPPayloadSize uint64 118 119 func (MaxUDPPayloadSize) ID() uint64 { 120 return max_udp_payload_size 121 } 122 123 func (m MaxUDPPayloadSize) Value() []byte { 124 return quicvarint.Append([]byte{}, uint64(m)) 125 } 126 127 type InitialMaxData uint64 128 129 func (InitialMaxData) ID() uint64 { 130 return initial_max_data 131 } 132 133 func (i InitialMaxData) Value() []byte { 134 return quicvarint.Append([]byte{}, uint64(i)) 135 } 136 137 type InitialMaxStreamDataBidiLocal uint64 138 139 func (InitialMaxStreamDataBidiLocal) ID() uint64 { 140 return initial_max_stream_data_bidi_local 141 } 142 143 func (i InitialMaxStreamDataBidiLocal) Value() []byte { 144 return quicvarint.Append([]byte{}, uint64(i)) 145 } 146 147 type InitialMaxStreamDataBidiRemote uint64 148 149 func (InitialMaxStreamDataBidiRemote) ID() uint64 { 150 return initial_max_stream_data_bidi_remote 151 } 152 153 func (i InitialMaxStreamDataBidiRemote) Value() []byte { 154 return quicvarint.Append([]byte{}, uint64(i)) 155 } 156 157 type InitialMaxStreamDataUni uint64 158 159 func (InitialMaxStreamDataUni) ID() uint64 { 160 return initial_max_stream_data_uni 161 } 162 163 func (i InitialMaxStreamDataUni) Value() []byte { 164 return quicvarint.Append([]byte{}, uint64(i)) 165 } 166 167 type InitialMaxStreamsBidi uint64 168 169 func (InitialMaxStreamsBidi) ID() uint64 { 170 return initial_max_streams_bidi 171 } 172 173 func (i InitialMaxStreamsBidi) Value() []byte { 174 return quicvarint.Append([]byte{}, uint64(i)) 175 } 176 177 type InitialMaxStreamsUni uint64 178 179 func (InitialMaxStreamsUni) ID() uint64 { 180 return initial_max_streams_uni 181 } 182 183 func (i InitialMaxStreamsUni) Value() []byte { 184 return quicvarint.Append([]byte{}, uint64(i)) 185 } 186 187 type MaxAckDelay uint64 188 189 func (MaxAckDelay) ID() uint64 { 190 return max_ack_delay 191 } 192 193 func (m MaxAckDelay) Value() []byte { 194 return quicvarint.Append([]byte{}, uint64(m)) 195 } 196 197 type DisableActiveMigration struct{} 198 199 func (*DisableActiveMigration) ID() uint64 { 200 return disable_active_migration 201 } 202 203 // Its Value MUST ALWAYS be empty. 204 func (*DisableActiveMigration) Value() []byte { 205 return []byte{} 206 } 207 208 type ActiveConnectionIDLimit uint64 209 210 func (ActiveConnectionIDLimit) ID() uint64 { 211 return active_connection_id_limit 212 } 213 214 func (a ActiveConnectionIDLimit) Value() []byte { 215 return quicvarint.Append([]byte{}, uint64(a)) 216 } 217 218 type InitialSourceConnectionID []byte // if empty, will be set to the Connection ID used for the Initial packet. 219 220 func (InitialSourceConnectionID) ID() uint64 { 221 return initial_source_connection_id 222 } 223 224 func (i InitialSourceConnectionID) Value() []byte { 225 return []byte(i) 226 } 227 228 type VersionInformation struct { 229 ChoosenVersion uint32 230 AvailableVersions []uint32 // Also known as "Other Versions" in early drafts. 231 232 LegacyID bool // If true, use the legacy-assigned ID (0xff73db) instead of the RFC-assigned one (0x11). 233 } 234 235 const ( 236 VERSION_NEGOTIATION uint32 = 0x00000000 // rfc9000 237 VERSION_1 uint32 = 0x00000001 // rfc9000 238 VERSION_2 uint32 = 0x6b3343cf // rfc9369 239 240 VERSION_GREASE uint32 = 0x0a0a0a0a // -> 0x?a?a?a?a 241 ) 242 243 func (v *VersionInformation) ID() uint64 { 244 if v.LegacyID { 245 return version_information_legacy 246 } 247 return version_information 248 } 249 250 func (v *VersionInformation) Value() []byte { 251 var b []byte 252 b = binary.BigEndian.AppendUint32(b, v.ChoosenVersion) 253 for _, version := range v.AvailableVersions { 254 if version != VERSION_GREASE { 255 b = binary.BigEndian.AppendUint32(b, version) 256 } else { 257 b = binary.BigEndian.AppendUint32(b, v.GetGREASEVersion()) 258 } 259 } 260 return b 261 } 262 263 func (*VersionInformation) GetGREASEVersion() uint32 { 264 // get a random uint32 265 max := big.NewInt(math.MaxUint32) 266 randVal, err := rand.Int(rand.Reader, max) 267 if err != nil { 268 return VERSION_GREASE 269 } 270 271 return uint32(randVal.Uint64()&math.MaxUint32) | 0x0a0a0a0a // all GREASE versions are in 0x?a?a?a?a 272 } 273 274 type PaddingTransportParameter []byte 275 276 func (PaddingTransportParameter) ID() uint64 { 277 return padding 278 } 279 280 func (p PaddingTransportParameter) Value() []byte { 281 return p 282 } 283 284 type MaxDatagramFrameSize uint64 285 286 func (MaxDatagramFrameSize) ID() uint64 { 287 return max_datagram_frame_size 288 } 289 290 func (m MaxDatagramFrameSize) Value() []byte { 291 return quicvarint.Append([]byte{}, uint64(m)) 292 } 293 294 type GREASEQUICBit struct{} 295 296 func (*GREASEQUICBit) ID() uint64 { 297 return grease_quic_bit 298 } 299 300 // Its Value MUST ALWAYS be empty. 301 func (*GREASEQUICBit) Value() []byte { 302 return []byte{} 303 } 304 305 type FakeQUICTransportParameter struct { 306 Id uint64 307 Val []byte 308 } 309 310 func (f *FakeQUICTransportParameter) ID() uint64 { 311 if f.Id == 0 { 312 panic("it is not allowed to use a FakeQUICTransportParameter without setting the ID") 313 } 314 return f.Id 315 } 316 317 func (f *FakeQUICTransportParameter) Value() []byte { 318 return f.Val 319 }