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  }