package handshake import ( "crypto/tls" "net" "time" "github.com/marten-seemann/qtls" ) type conn struct { remoteAddr net.Addr } func newConn(remote net.Addr) net.Conn { return &conn{remoteAddr: remote} } var _ net.Conn = &conn{} func (c *conn) Read([]byte) (int, error) { return 0, nil } func (c *conn) Write([]byte) (int, error) { return 0, nil } func (c *conn) Close() error { return nil } func (c *conn) RemoteAddr() net.Addr { return c.remoteAddr } func (c *conn) LocalAddr() net.Addr { return nil } func (c *conn) SetReadDeadline(time.Time) error { return nil } func (c *conn) SetWriteDeadline(time.Time) error { return nil } func (c *conn) SetDeadline(time.Time) error { return nil } func tlsConfigToQtlsConfig( c *tls.Config, recordLayer qtls.RecordLayer, extHandler tlsExtensionHandler, getDataForSessionState func() []byte, setDataFromSessionState func([]byte), accept0RTT func([]byte) bool, rejected0RTT func(), enable0RTT bool, ) *qtls.Config { if c == nil { c = &tls.Config{} } // Clone the config first. This executes the tls.Config.serverInit(). // This sets the SessionTicketKey, if the user didn't supply one. c = c.Clone() // QUIC requires TLS 1.3 or newer minVersion := c.MinVersion if minVersion < qtls.VersionTLS13 { minVersion = qtls.VersionTLS13 } maxVersion := c.MaxVersion if maxVersion < qtls.VersionTLS13 { maxVersion = qtls.VersionTLS13 } var getConfigForClient func(ch *tls.ClientHelloInfo) (*qtls.Config, error) if c.GetConfigForClient != nil { getConfigForClient = func(ch *tls.ClientHelloInfo) (*qtls.Config, error) { tlsConf, err := c.GetConfigForClient(ch) if err != nil { return nil, err } if tlsConf == nil { return nil, nil } return tlsConfigToQtlsConfig(tlsConf, recordLayer, extHandler, getDataForSessionState, setDataFromSessionState, accept0RTT, rejected0RTT, enable0RTT), nil } } var csc qtls.ClientSessionCache if c.ClientSessionCache != nil { csc = newClientSessionCache(c.ClientSessionCache, getDataForSessionState, setDataFromSessionState) } conf := &qtls.Config{ Rand: c.Rand, Time: c.Time, Certificates: c.Certificates, NameToCertificate: c.NameToCertificate, GetCertificate: c.GetCertificate, GetClientCertificate: c.GetClientCertificate, GetConfigForClient: getConfigForClient, VerifyPeerCertificate: c.VerifyPeerCertificate, RootCAs: c.RootCAs, NextProtos: c.NextProtos, EnforceNextProtoSelection: true, ServerName: c.ServerName, ClientAuth: c.ClientAuth, ClientCAs: c.ClientCAs, InsecureSkipVerify: c.InsecureSkipVerify, CipherSuites: c.CipherSuites, PreferServerCipherSuites: c.PreferServerCipherSuites, SessionTicketsDisabled: c.SessionTicketsDisabled, SessionTicketKey: c.SessionTicketKey, ClientSessionCache: csc, MinVersion: minVersion, MaxVersion: maxVersion, CurvePreferences: c.CurvePreferences, DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled, // no need to copy Renegotiation, it's not supported by TLS 1.3 KeyLogWriter: c.KeyLogWriter, AlternativeRecordLayer: recordLayer, GetExtensions: extHandler.GetExtensions, ReceivedExtensions: extHandler.ReceivedExtensions, Accept0RTT: accept0RTT, Rejected0RTT: rejected0RTT, } if enable0RTT { conf.Enable0RTT = true conf.MaxEarlyData = 0xffffffff } return conf } func cipherSuiteName(id uint16) string { switch id { case qtls.TLS_AES_128_GCM_SHA256: return "TLS_AES_128_GCM_SHA256" case qtls.TLS_CHACHA20_POLY1305_SHA256: return "TLS_CHACHA20_POLY1305_SHA256" case qtls.TLS_AES_256_GCM_SHA384: return "TLS_AES_256_GCM_SHA384" default: return "unknown cipher suite" } }