github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/tlsDialer.go (about)

     1  /*
     2   * Copyright (c) 2015, Psiphon Inc.
     3   * All rights reserved.
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  /*
    21  Copyright (c) 2012 The Go Authors. All rights reserved.
    22  
    23  Redistribution and use in source and binary forms, with or without
    24  modification, are permitted provided that the following conditions are
    25  met:
    26  
    27     * Redistributions of source code must retain the above copyright
    28  notice, this list of conditions and the following disclaimer.
    29     * Redistributions in binary form must reproduce the above
    30  copyright notice, this list of conditions and the following disclaimer
    31  in the documentation and/or other materials provided with the
    32  distribution.
    33     * Neither the name of Google Inc. nor the names of its
    34  contributors may be used to endorse or promote products derived from
    35  this software without specific prior written permission.
    36  
    37  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    38  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    39  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    40  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    41  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    42  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    43  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    44  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    45  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    46  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    47  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    48  */
    49  
    50  // Originally based on https://gopkg.in/getlantern/tlsdialer.v1.
    51  
    52  package psiphon
    53  
    54  import (
    55  	"bytes"
    56  	"context"
    57  	"crypto/sha256"
    58  	"crypto/x509"
    59  	"encoding/base64"
    60  	"encoding/hex"
    61  	std_errors "errors"
    62  	"io/ioutil"
    63  	"net"
    64  
    65  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common"
    66  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors"
    67  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/parameters"
    68  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/prng"
    69  	"github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/protocol"
    70  	tris "github.com/Psiphon-Labs/tls-tris"
    71  	utls "github.com/Psiphon-Labs/utls"
    72  )
    73  
    74  // CustomTLSConfig specifies the parameters for a CustomTLSDial, supporting
    75  // many TLS-related network obfuscation mechanisms.
    76  type CustomTLSConfig struct {
    77  
    78  	// Parameters is the active set of parameters.Parameters to use for the TLS
    79  	// dial. Must not be nil.
    80  	Parameters *parameters.Parameters
    81  
    82  	// Dial is the network connection dialer. TLS is layered on top of a new
    83  	// network connection created with dialer. Must not be nil.
    84  	Dial common.Dialer
    85  
    86  	// DialAddr overrides the "addr" input to Dial when specified
    87  	DialAddr string
    88  
    89  	// UseDialAddrSNI specifies whether to always use the dial "addr"
    90  	// host name in the SNI server_name field. When DialAddr is set,
    91  	// its host name is used.
    92  	UseDialAddrSNI bool
    93  
    94  	// SNIServerName specifies the value to set in the SNI
    95  	// server_name field. When blank, SNI is omitted. Note that
    96  	// underlying TLS code also automatically omits SNI when
    97  	// the server_name is an IP address.
    98  	// SNIServerName is ignored when UseDialAddrSNI is true.
    99  	SNIServerName string
   100  
   101  	// VerifyServerName specifies a domain name that must appear in the server
   102  	// certificate. When specified, certificate verification checks for
   103  	// VerifyServerName in the server certificate, in place of the dial or SNI
   104  	// hostname.
   105  	VerifyServerName string
   106  
   107  	// VerifyPins specifies one or more certificate pin values, one of which must
   108  	// appear in the verified server certificate chain. A pin value is the
   109  	// base64-encoded SHA2 digest of a certificate's public key. When specified,
   110  	// at least one pin must match at least one certificate in the chain, at any
   111  	// position; e.g., the root CA may be pinned, or the server certificate,
   112  	// etc.
   113  	VerifyPins []string
   114  
   115  	// VerifyLegacyCertificate is a special case self-signed server
   116  	// certificate case. Ignores IP SANs and basic constraints. No
   117  	// certificate chain. Just checks that the server presented the
   118  	// specified certificate.
   119  	//
   120  	// When VerifyLegacyCertificate is set, none of VerifyServerName, VerifyPins,
   121  	// SkipVerify may be set.
   122  	VerifyLegacyCertificate *x509.Certificate
   123  
   124  	// SkipVerify completely disables server certificate verification.
   125  	//
   126  	// When SkipVerify is set, none of VerifyServerName, VerifyPins,
   127  	// VerifyLegacyCertificate may be set.
   128  	SkipVerify bool
   129  
   130  	// TLSProfile specifies a particular indistinguishable TLS profile to use for
   131  	// the TLS dial. Setting TLSProfile allows the caller to pin the selection so
   132  	// all TLS connections in a certain context (e.g. a single meek connection)
   133  	// use a consistent value. The value should be selected by calling
   134  	// SelectTLSProfile, which will pick a value at random, subject to
   135  	// compatibility constraints.
   136  	//
   137  	// When TLSProfile is "", a profile is selected at random and
   138  	// DisableFrontingProviderTLSProfiles is ignored.
   139  	TLSProfile string
   140  
   141  	// NoDefaultTLSSessionID specifies whether to set a TLS session ID by
   142  	// default, for a new TLS connection that is not resuming a session.
   143  	// When nil, the parameter is set randomly.
   144  	NoDefaultTLSSessionID *bool
   145  
   146  	// RandomizedTLSProfileSeed specifies the PRNG seed to use when generating
   147  	// a randomized TLS ClientHello, which applies to TLS profiles where
   148  	// protocol.TLSProfileIsRandomized is true. The PRNG seed allows for
   149  	// optional replay of a particular randomized Client Hello.
   150  	RandomizedTLSProfileSeed *prng.Seed
   151  
   152  	// TLSPadding indicates whether to move or add a TLS padding extension to the
   153  	// front of the exension list and apply the specified padding length. Ignored
   154  	// when 0.
   155  	TLSPadding int
   156  
   157  	// TrustedCACertificatesFilename specifies a file containing trusted
   158  	// CA certs. See Config.TrustedCACertificatesFilename.
   159  	TrustedCACertificatesFilename string
   160  
   161  	// ObfuscatedSessionTicketKey enables obfuscated session tickets
   162  	// using the specified key.
   163  	ObfuscatedSessionTicketKey string
   164  
   165  	// PassthroughMessage, when specified, is a 32 byte value that is sent in the
   166  	// ClientHello random value field. The value should be generated using
   167  	// obfuscator.MakeTLSPassthroughMessage.
   168  	PassthroughMessage []byte
   169  
   170  	clientSessionCache utls.ClientSessionCache
   171  }
   172  
   173  // EnableClientSessionCache initializes a cache to use to persist session
   174  // tickets, enabling TLS session resumability across multiple
   175  // CustomTLSDial calls or dialers using the same CustomTLSConfig.
   176  func (config *CustomTLSConfig) EnableClientSessionCache() {
   177  	if config.clientSessionCache == nil {
   178  		config.clientSessionCache = utls.NewLRUClientSessionCache(0)
   179  	}
   180  }
   181  
   182  // NewCustomTLSDialer creates a new dialer based on CustomTLSDial.
   183  func NewCustomTLSDialer(config *CustomTLSConfig) common.Dialer {
   184  	return func(ctx context.Context, network, addr string) (net.Conn, error) {
   185  		return CustomTLSDial(ctx, network, addr, config)
   186  	}
   187  }
   188  
   189  // CustomTLSDial dials a new TLS connection using the parameters set in
   190  // CustomTLSConfig.
   191  //
   192  // The dial aborts if ctx becomes Done before the dial completes.
   193  func CustomTLSDial(
   194  	ctx context.Context,
   195  	network, addr string,
   196  	config *CustomTLSConfig) (net.Conn, error) {
   197  
   198  	if (config.SkipVerify &&
   199  		(config.VerifyLegacyCertificate != nil ||
   200  			len(config.VerifyServerName) > 0 ||
   201  			len(config.VerifyPins) > 0)) ||
   202  
   203  		(config.VerifyLegacyCertificate != nil &&
   204  			(config.SkipVerify ||
   205  				len(config.VerifyServerName) > 0 ||
   206  				len(config.VerifyPins) > 0)) {
   207  
   208  		return nil, errors.TraceNew("incompatible certification verification parameters")
   209  	}
   210  
   211  	p := config.Parameters.Get()
   212  
   213  	dialAddr := addr
   214  	if config.DialAddr != "" {
   215  		dialAddr = config.DialAddr
   216  	}
   217  
   218  	rawConn, err := config.Dial(ctx, network, dialAddr)
   219  	if err != nil {
   220  		return nil, errors.Trace(err)
   221  	}
   222  
   223  	hostname, _, err := net.SplitHostPort(dialAddr)
   224  	if err != nil {
   225  		rawConn.Close()
   226  		return nil, errors.Trace(err)
   227  	}
   228  
   229  	var tlsConfigRootCAs *x509.CertPool
   230  	if !config.SkipVerify &&
   231  		config.VerifyLegacyCertificate == nil &&
   232  		config.TrustedCACertificatesFilename != "" {
   233  
   234  		tlsConfigRootCAs = x509.NewCertPool()
   235  		certData, err := ioutil.ReadFile(config.TrustedCACertificatesFilename)
   236  		if err != nil {
   237  			return nil, errors.Trace(err)
   238  		}
   239  		tlsConfigRootCAs.AppendCertsFromPEM(certData)
   240  	}
   241  
   242  	// In some cases, config.SkipVerify is false, but
   243  	// utls.Config.InsecureSkipVerify will be set to true to disable verification
   244  	// in utls that will otherwise fail: when SNI is omitted, and when
   245  	// VerifyServerName differs from SNI. In these cases, the certificate chain
   246  	// is verified in VerifyPeerCertificate.
   247  
   248  	tlsConfigInsecureSkipVerify := false
   249  	tlsConfigServerName := ""
   250  	verifyServerName := hostname
   251  
   252  	if config.SkipVerify {
   253  		tlsConfigInsecureSkipVerify = true
   254  	}
   255  
   256  	if config.UseDialAddrSNI {
   257  
   258  		// Set SNI to match the dial hostname. This is the standard case.
   259  		tlsConfigServerName = hostname
   260  
   261  	} else if config.SNIServerName != "" {
   262  
   263  		// Set a custom SNI value. If this value doesn't match the server
   264  		// certificate, SkipVerify and/or VerifyServerName may need to be
   265  		// configured; but by itself this case doesn't necessarily require
   266  		// custom certificate verification.
   267  		tlsConfigServerName = config.SNIServerName
   268  
   269  	} else {
   270  
   271  		// Omit SNI. If SkipVerify is not set, this case requires custom certificate
   272  		// verification, which will check that the server certificate matches either
   273  		// the dial hostname or VerifyServerName, as if the SNI were set to one of
   274  		// those values.
   275  		tlsConfigInsecureSkipVerify = true
   276  	}
   277  
   278  	// When VerifyServerName does not match the SNI, custom certificate
   279  	// verification is necessary.
   280  	if config.VerifyServerName != "" && config.VerifyServerName != tlsConfigServerName {
   281  		verifyServerName = config.VerifyServerName
   282  		tlsConfigInsecureSkipVerify = true
   283  	}
   284  
   285  	// With the VerifyPeerCertificate callback, we perform any custom certificate
   286  	// verification at the same point in the TLS handshake as standard utls
   287  	// verification; and abort the handshake at the same point, if custom
   288  	// verification fails.
   289  	var tlsConfigVerifyPeerCertificate func([][]byte, [][]*x509.Certificate) error
   290  	if !config.SkipVerify {
   291  		tlsConfigVerifyPeerCertificate = func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
   292  
   293  			if config.VerifyLegacyCertificate != nil {
   294  				return verifyLegacyCertificate(
   295  					rawCerts, config.VerifyLegacyCertificate)
   296  			}
   297  
   298  			if tlsConfigInsecureSkipVerify {
   299  
   300  				// Limitation: this verification path does not set the utls.Conn's
   301  				// ConnectionState certificate information.
   302  
   303  				if len(verifiedChains) > 0 {
   304  					return errors.TraceNew("unexpected verified chains")
   305  				}
   306  				var err error
   307  				verifiedChains, err = verifyServerCertificate(
   308  					tlsConfigRootCAs, rawCerts, verifyServerName)
   309  				if err != nil {
   310  					return errors.Trace(err)
   311  				}
   312  			}
   313  
   314  			if len(config.VerifyPins) > 0 {
   315  				err := verifyCertificatePins(
   316  					config.VerifyPins, verifiedChains)
   317  				if err != nil {
   318  					return errors.Trace(err)
   319  				}
   320  			}
   321  
   322  			return nil
   323  		}
   324  	}
   325  
   326  	tlsConfig := &utls.Config{
   327  		RootCAs:               tlsConfigRootCAs,
   328  		InsecureSkipVerify:    tlsConfigInsecureSkipVerify,
   329  		ServerName:            tlsConfigServerName,
   330  		VerifyPeerCertificate: tlsConfigVerifyPeerCertificate,
   331  	}
   332  
   333  	selectedTLSProfile := config.TLSProfile
   334  
   335  	if selectedTLSProfile == "" {
   336  		selectedTLSProfile = SelectTLSProfile(false, false, "", p)
   337  	}
   338  
   339  	utlsClientHelloID, utlsClientHelloSpec, err := getUTLSClientHelloID(
   340  		p, selectedTLSProfile)
   341  	if err != nil {
   342  		return nil, errors.Trace(err)
   343  	}
   344  
   345  	var randomizedTLSProfileSeed *prng.Seed
   346  	isRandomized := protocol.TLSProfileIsRandomized(selectedTLSProfile)
   347  	if isRandomized {
   348  
   349  		randomizedTLSProfileSeed = config.RandomizedTLSProfileSeed
   350  
   351  		if randomizedTLSProfileSeed == nil {
   352  
   353  			randomizedTLSProfileSeed, err = prng.NewSeed()
   354  			if err != nil {
   355  				return nil, errors.Trace(err)
   356  			}
   357  		}
   358  
   359  		utlsClientHelloID.Seed = new(utls.PRNGSeed)
   360  		*utlsClientHelloID.Seed = [32]byte(*randomizedTLSProfileSeed)
   361  	}
   362  
   363  	// As noted here,
   364  	// https://gitlab.com/yawning/obfs4/commit/ca6765e3e3995144df2b1ca9f0e9d823a7f8a47c,
   365  	// the dynamic record sizing optimization in crypto/tls is not commonly
   366  	// implemented in browsers. Disable it for all utls parrots and select it
   367  	// randomly when using the randomized client hello.
   368  	if isRandomized {
   369  		PRNG, err := prng.NewPRNGWithSaltedSeed(randomizedTLSProfileSeed, "tls-dynamic-record-sizing")
   370  		if err != nil {
   371  			return nil, errors.Trace(err)
   372  		}
   373  		tlsConfig.DynamicRecordSizingDisabled = PRNG.FlipCoin()
   374  	} else {
   375  		tlsConfig.DynamicRecordSizingDisabled = true
   376  	}
   377  
   378  	conn := utls.UClient(rawConn, tlsConfig, utlsClientHelloID)
   379  
   380  	if utlsClientHelloSpec != nil {
   381  		err := conn.ApplyPreset(utlsClientHelloSpec)
   382  		if err != nil {
   383  			return nil, errors.Trace(err)
   384  		}
   385  	}
   386  
   387  	clientSessionCache := config.clientSessionCache
   388  	if clientSessionCache == nil {
   389  		clientSessionCache = utls.NewLRUClientSessionCache(0)
   390  	}
   391  
   392  	conn.SetSessionCache(clientSessionCache)
   393  
   394  	// TODO: can conn.SetClientRandom be made to take effect if called here? In
   395  	// testing, the random value appears to be overwritten. As is, the overhead
   396  	// of needRemarshal is now always required to handle
   397  	// config.PassthroughMessage.
   398  
   399  	// Build handshake state in advance to obtain the TLS version, which is used
   400  	// to determine whether the following customizations may be applied. Don't use
   401  	// getClientHelloVersion, since that may incur additional overhead.
   402  
   403  	err = conn.BuildHandshakeState()
   404  	if err != nil {
   405  		return nil, errors.Trace(err)
   406  	}
   407  
   408  	isTLS13 := false
   409  	for _, vers := range conn.HandshakeState.Hello.SupportedVersions {
   410  		if vers == utls.VersionTLS13 {
   411  			isTLS13 = true
   412  			break
   413  		}
   414  	}
   415  
   416  	// Add the obfuscated session ticket only when using TLS 1.2.
   417  	//
   418  	// Obfuscated session tickets are not currently supported in TLS 1.3, but we
   419  	// allow UNFRONTED-MEEK-SESSION-TICKET-OSSH to use TLS 1.3 profiles for
   420  	// additional diversity/capacity; TLS 1.3 encrypts the server certificate,
   421  	// so the desired obfuscated session tickets property of obfuscating server
   422  	// certificates is satisfied. We know that when the ClientHello offers TLS
   423  	// 1.3, the Psiphon server, in these direct protocol cases, will negotiate
   424  	// it.
   425  
   426  	if config.ObfuscatedSessionTicketKey != "" && !isTLS13 {
   427  
   428  		var obfuscatedSessionTicketKey [32]byte
   429  
   430  		key, err := hex.DecodeString(config.ObfuscatedSessionTicketKey)
   431  		if err == nil && len(key) != 32 {
   432  			err = std_errors.New("invalid obfuscated session key length")
   433  		}
   434  		if err != nil {
   435  			return nil, errors.Trace(err)
   436  		}
   437  		copy(obfuscatedSessionTicketKey[:], key)
   438  
   439  		obfuscatedSessionState, err := tris.NewObfuscatedClientSessionState(
   440  			obfuscatedSessionTicketKey)
   441  		if err != nil {
   442  			return nil, errors.Trace(err)
   443  		}
   444  
   445  		conn.SetSessionState(
   446  			utls.MakeClientSessionState(
   447  				obfuscatedSessionState.SessionTicket,
   448  				obfuscatedSessionState.Vers,
   449  				obfuscatedSessionState.CipherSuite,
   450  				obfuscatedSessionState.MasterSecret,
   451  				nil,
   452  				nil))
   453  
   454  		// Apply changes to utls
   455  		err = conn.BuildHandshakeState()
   456  		if err != nil {
   457  			return nil, errors.Trace(err)
   458  		}
   459  
   460  		// Ensure that TLS ClientHello has required session ticket extension and
   461  		// obfuscated session ticket cipher suite; the latter is required by
   462  		// utls/tls.Conn.loadSession. If these requirements are not met the
   463  		// obfuscation session ticket would be ignored, so fail.
   464  
   465  		if !tris.ContainsObfuscatedSessionTicketCipherSuite(
   466  			conn.HandshakeState.Hello.CipherSuites) {
   467  			return nil, errors.TraceNew(
   468  				"missing obfuscated session ticket cipher suite")
   469  		}
   470  
   471  		if len(conn.HandshakeState.Hello.SessionTicket) == 0 {
   472  			return nil, errors.TraceNew("missing session ticket extension")
   473  		}
   474  	}
   475  
   476  	// Perform at most one remarshal for the following ClientHello
   477  	// modifications.
   478  	needRemarshal := false
   479  
   480  	// Either pre-TLS 1.3 ClientHellos or any randomized ClientHello is a
   481  	// candidate for NoDefaultSessionID logic.
   482  	if len(conn.HandshakeState.Hello.SessionTicket) == 0 &&
   483  		(!isTLS13 || utlsClientHelloID.Client == "Randomized") {
   484  
   485  		var noDefaultSessionID bool
   486  		if config.NoDefaultTLSSessionID != nil {
   487  			noDefaultSessionID = *config.NoDefaultTLSSessionID
   488  		} else {
   489  			noDefaultSessionID = config.Parameters.Get().WeightedCoinFlip(
   490  				parameters.NoDefaultTLSSessionIDProbability)
   491  		}
   492  
   493  		if noDefaultSessionID {
   494  			conn.HandshakeState.Hello.SessionId = nil
   495  			needRemarshal = true
   496  		}
   497  	}
   498  
   499  	// utls doesn't omit the server_name extension when the ServerName value is
   500  	// empty or an IP address. To avoid a fingerprintable invalid/unusual
   501  	// server_name extension, remove it in these cases.
   502  	if tlsConfigServerName == "" || net.ParseIP(tlsConfigServerName) != nil {
   503  
   504  		// Assumes only one SNIExtension.
   505  		// TODO: use new UConn.RemoveSNIExtension function?
   506  		deleteIndex := -1
   507  		for index, extension := range conn.Extensions {
   508  			if _, ok := extension.(*utls.SNIExtension); ok {
   509  				deleteIndex = index
   510  				break
   511  			}
   512  		}
   513  		if deleteIndex != -1 {
   514  			conn.Extensions = append(
   515  				conn.Extensions[:deleteIndex], conn.Extensions[deleteIndex+1:]...)
   516  		}
   517  		needRemarshal = true
   518  	}
   519  
   520  	if config.TLSPadding > 0 {
   521  
   522  		tlsPadding := config.TLSPadding
   523  
   524  		// Maximum padding size per RFC 7685
   525  		if tlsPadding > 65535 {
   526  			tlsPadding = 65535
   527  		}
   528  
   529  		// Assumes only one PaddingExtension.
   530  		deleteIndex := -1
   531  		for index, extension := range conn.Extensions {
   532  			if _, ok := extension.(*utls.UtlsPaddingExtension); ok {
   533  				deleteIndex = index
   534  				break
   535  			}
   536  		}
   537  		if deleteIndex != -1 {
   538  			conn.Extensions = append(
   539  				conn.Extensions[:deleteIndex], conn.Extensions[deleteIndex+1:]...)
   540  		}
   541  
   542  		paddingExtension := &utls.UtlsPaddingExtension{
   543  			PaddingLen: tlsPadding,
   544  			WillPad:    true,
   545  		}
   546  		conn.Extensions = append([]utls.TLSExtension{paddingExtension}, conn.Extensions...)
   547  
   548  		needRemarshal = true
   549  
   550  	}
   551  
   552  	if config.PassthroughMessage != nil {
   553  		err := conn.SetClientRandom(config.PassthroughMessage)
   554  		if err != nil {
   555  			return nil, errors.Trace(err)
   556  		}
   557  
   558  		needRemarshal = true
   559  	}
   560  
   561  	if needRemarshal {
   562  		// Apply changes to utls
   563  		err = conn.MarshalClientHello()
   564  		if err != nil {
   565  			return nil, errors.Trace(err)
   566  		}
   567  	}
   568  
   569  	// Perform the TLS Handshake.
   570  
   571  	resultChannel := make(chan error)
   572  
   573  	go func() {
   574  		resultChannel <- conn.Handshake()
   575  	}()
   576  
   577  	select {
   578  	case err = <-resultChannel:
   579  	case <-ctx.Done():
   580  		err = ctx.Err()
   581  		// Interrupt the goroutine
   582  		rawConn.Close()
   583  		<-resultChannel
   584  	}
   585  
   586  	if err != nil {
   587  		rawConn.Close()
   588  		return nil, errors.Trace(err)
   589  	}
   590  
   591  	return conn, nil
   592  }
   593  
   594  func verifyLegacyCertificate(rawCerts [][]byte, expectedCertificate *x509.Certificate) error {
   595  	if len(rawCerts) < 1 {
   596  		return errors.TraceNew("missing certificate")
   597  	}
   598  	if !bytes.Equal(rawCerts[0], expectedCertificate.Raw) {
   599  		return errors.TraceNew("unexpected certificate")
   600  	}
   601  	return nil
   602  }
   603  
   604  func verifyServerCertificate(
   605  	rootCAs *x509.CertPool, rawCerts [][]byte, verifyServerName string) ([][]*x509.Certificate, error) {
   606  
   607  	// This duplicates the verification logic in utls (and standard crypto/tls).
   608  
   609  	certs := make([]*x509.Certificate, len(rawCerts))
   610  	for i, rawCert := range rawCerts {
   611  		cert, err := x509.ParseCertificate(rawCert)
   612  		if err != nil {
   613  			return nil, errors.Trace(err)
   614  		}
   615  		certs[i] = cert
   616  	}
   617  
   618  	opts := x509.VerifyOptions{
   619  		Roots:         rootCAs,
   620  		DNSName:       verifyServerName,
   621  		Intermediates: x509.NewCertPool(),
   622  	}
   623  
   624  	for i, cert := range certs {
   625  		if i == 0 {
   626  			continue
   627  		}
   628  		opts.Intermediates.AddCert(cert)
   629  	}
   630  
   631  	verifiedChains, err := certs[0].Verify(opts)
   632  	if err != nil {
   633  		return nil, errors.Trace(err)
   634  	}
   635  
   636  	return verifiedChains, nil
   637  }
   638  
   639  func verifyCertificatePins(pins []string, verifiedChains [][]*x509.Certificate) error {
   640  	for _, chain := range verifiedChains {
   641  		for _, cert := range chain {
   642  			publicKeyDigest := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
   643  			expectedPin := base64.StdEncoding.EncodeToString(publicKeyDigest[:])
   644  			if common.Contains(pins, expectedPin) {
   645  				// Return success on the first match of any certificate public key to any
   646  				// pin.
   647  				return nil
   648  			}
   649  		}
   650  	}
   651  	return errors.TraceNew("no pin found")
   652  }
   653  
   654  func IsTLSConnUsingHTTP2(conn net.Conn) bool {
   655  	if c, ok := conn.(*utls.UConn); ok {
   656  		state := c.ConnectionState()
   657  		return state.NegotiatedProtocolIsMutual &&
   658  			state.NegotiatedProtocol == "h2"
   659  	}
   660  	return false
   661  }
   662  
   663  // SelectTLSProfile picks a TLS profile at random from the available candidates.
   664  func SelectTLSProfile(
   665  	requireTLS12SessionTickets bool,
   666  	isFronted bool,
   667  	frontingProviderID string,
   668  	p parameters.ParametersAccessor) string {
   669  
   670  	// Two TLS profile lists are constructed, subject to limit constraints:
   671  	// stock, fixed parrots (non-randomized SupportedTLSProfiles) and custom
   672  	// parrots (CustomTLSProfileNames); and randomized. If one list is empty, the
   673  	// non-empty list is used. Otherwise SelectRandomizedTLSProfileProbability
   674  	// determines which list is used.
   675  	//
   676  	// Note that LimitTLSProfiles is not applied to CustomTLSProfiles; the
   677  	// presence of a candidate in CustomTLSProfiles is treated as explicit
   678  	// enabling.
   679  	//
   680  	// UseOnlyCustomTLSProfiles may be used to disable all stock TLS profiles and
   681  	// use only CustomTLSProfiles; UseOnlyCustomTLSProfiles is ignored if
   682  	// CustomTLSProfiles is empty.
   683  	//
   684  	// For fronted servers, DisableFrontingProviderTLSProfiles may be used
   685  	// to disable TLS profiles which are incompatible with the TLS stack used
   686  	// by the front. For example, if a utls parrot doesn't fully support all
   687  	// of the capabilities in the ClientHello. Unlike the LimitTLSProfiles case,
   688  	// DisableFrontingProviderTLSProfiles may disable CustomTLSProfiles.
   689  
   690  	limitTLSProfiles := p.TLSProfiles(parameters.LimitTLSProfiles)
   691  	var disableTLSProfiles protocol.TLSProfiles
   692  
   693  	if isFronted && frontingProviderID != "" {
   694  		disableTLSProfiles = p.LabeledTLSProfiles(
   695  			parameters.DisableFrontingProviderTLSProfiles, frontingProviderID)
   696  	}
   697  
   698  	randomizedTLSProfiles := make([]string, 0)
   699  	parrotTLSProfiles := make([]string, 0)
   700  
   701  	for _, tlsProfile := range p.CustomTLSProfileNames() {
   702  		if !common.Contains(disableTLSProfiles, tlsProfile) {
   703  			parrotTLSProfiles = append(parrotTLSProfiles, tlsProfile)
   704  		}
   705  	}
   706  
   707  	useOnlyCustomTLSProfiles := p.Bool(parameters.UseOnlyCustomTLSProfiles)
   708  	if useOnlyCustomTLSProfiles && len(parrotTLSProfiles) == 0 {
   709  		useOnlyCustomTLSProfiles = false
   710  	}
   711  
   712  	if !useOnlyCustomTLSProfiles {
   713  		for _, tlsProfile := range protocol.SupportedTLSProfiles {
   714  
   715  			if len(limitTLSProfiles) > 0 &&
   716  				!common.Contains(limitTLSProfiles, tlsProfile) {
   717  				continue
   718  			}
   719  
   720  			if common.Contains(disableTLSProfiles, tlsProfile) {
   721  				continue
   722  			}
   723  
   724  			// requireTLS12SessionTickets is specified for
   725  			// UNFRONTED-MEEK-SESSION-TICKET-OSSH, a protocol which depends on using
   726  			// obfuscated session tickets to ensure that the server doesn't send its
   727  			// certificate in the TLS handshake. TLS 1.2 profiles which omit session
   728  			// tickets should not be selected. As TLS 1.3 encrypts the server
   729  			// certificate message, there's no exclusion for TLS 1.3.
   730  
   731  			if requireTLS12SessionTickets &&
   732  				protocol.TLS12ProfileOmitsSessionTickets(tlsProfile) {
   733  				continue
   734  			}
   735  
   736  			if protocol.TLSProfileIsRandomized(tlsProfile) {
   737  				randomizedTLSProfiles = append(randomizedTLSProfiles, tlsProfile)
   738  			} else {
   739  				parrotTLSProfiles = append(parrotTLSProfiles, tlsProfile)
   740  			}
   741  		}
   742  	}
   743  
   744  	if len(randomizedTLSProfiles) > 0 &&
   745  		(len(parrotTLSProfiles) == 0 ||
   746  			p.WeightedCoinFlip(parameters.SelectRandomizedTLSProfileProbability)) {
   747  
   748  		return randomizedTLSProfiles[prng.Intn(len(randomizedTLSProfiles))]
   749  	}
   750  
   751  	if len(parrotTLSProfiles) == 0 {
   752  		return ""
   753  	}
   754  
   755  	return parrotTLSProfiles[prng.Intn(len(parrotTLSProfiles))]
   756  }
   757  
   758  func getUTLSClientHelloID(
   759  	p parameters.ParametersAccessor,
   760  	tlsProfile string) (utls.ClientHelloID, *utls.ClientHelloSpec, error) {
   761  
   762  	switch tlsProfile {
   763  	case protocol.TLS_PROFILE_IOS_111:
   764  		return utls.HelloIOS_11_1, nil, nil
   765  	case protocol.TLS_PROFILE_IOS_121:
   766  		return utls.HelloIOS_12_1, nil, nil
   767  	case protocol.TLS_PROFILE_IOS_13:
   768  		return utls.HelloIOS_13, nil, nil
   769  	case protocol.TLS_PROFILE_IOS_14:
   770  		return utls.HelloIOS_14, nil, nil
   771  	case protocol.TLS_PROFILE_CHROME_58:
   772  		return utls.HelloChrome_58, nil, nil
   773  	case protocol.TLS_PROFILE_CHROME_62:
   774  		return utls.HelloChrome_62, nil, nil
   775  	case protocol.TLS_PROFILE_CHROME_70:
   776  		return utls.HelloChrome_70, nil, nil
   777  	case protocol.TLS_PROFILE_CHROME_72:
   778  		return utls.HelloChrome_72, nil, nil
   779  	case protocol.TLS_PROFILE_CHROME_83:
   780  		return utls.HelloChrome_83, nil, nil
   781  	case protocol.TLS_PROFILE_CHROME_96:
   782  		return utls.HelloChrome_96, nil, nil
   783  	case protocol.TLS_PROFILE_CHROME_102:
   784  		return utls.HelloChrome_102, nil, nil
   785  	case protocol.TLS_PROFILE_FIREFOX_55:
   786  		return utls.HelloFirefox_55, nil, nil
   787  	case protocol.TLS_PROFILE_FIREFOX_56:
   788  		return utls.HelloFirefox_56, nil, nil
   789  	case protocol.TLS_PROFILE_FIREFOX_65:
   790  		return utls.HelloFirefox_65, nil, nil
   791  	case protocol.TLS_PROFILE_FIREFOX_99:
   792  		return utls.HelloFirefox_99, nil, nil
   793  	case protocol.TLS_PROFILE_FIREFOX_102:
   794  		return utls.HelloFirefox_102, nil, nil
   795  	case protocol.TLS_PROFILE_RANDOMIZED:
   796  		return utls.HelloRandomized, nil, nil
   797  	}
   798  
   799  	// utls.HelloCustom with a utls.ClientHelloSpec is used for
   800  	// CustomTLSProfiles.
   801  
   802  	customTLSProfile := p.CustomTLSProfile(tlsProfile)
   803  	if customTLSProfile == nil {
   804  		return utls.HelloCustom,
   805  			nil,
   806  			errors.Tracef("unknown TLS profile: %s", tlsProfile)
   807  	}
   808  
   809  	utlsClientHelloSpec, err := customTLSProfile.GetClientHelloSpec()
   810  	if err != nil {
   811  		return utls.ClientHelloID{}, nil, errors.Trace(err)
   812  	}
   813  
   814  	return utls.HelloCustom, utlsClientHelloSpec, nil
   815  }
   816  
   817  func getClientHelloVersion(
   818  	utlsClientHelloID utls.ClientHelloID,
   819  	utlsClientHelloSpec *utls.ClientHelloSpec) (string, error) {
   820  
   821  	switch utlsClientHelloID {
   822  
   823  	case utls.HelloIOS_11_1, utls.HelloIOS_12_1, utls.HelloChrome_58,
   824  		utls.HelloChrome_62, utls.HelloFirefox_55, utls.HelloFirefox_56:
   825  		return protocol.TLS_VERSION_12, nil
   826  
   827  	case utls.HelloChrome_70, utls.HelloChrome_72, utls.HelloChrome_83,
   828  		utls.HelloFirefox_65, utls.HelloGolang:
   829  		return protocol.TLS_VERSION_13, nil
   830  	}
   831  
   832  	// As utls.HelloRandomized/Custom may be either TLS 1.2 or TLS 1.3, we cannot
   833  	// perform a simple ClientHello ID check. BuildHandshakeState is run, which
   834  	// constructs the entire ClientHello.
   835  	//
   836  	// Assumes utlsClientHelloID.Seed has been set; otherwise the result is
   837  	// ephemeral.
   838  	//
   839  	// BenchmarkRandomizedGetClientHelloVersion indicates that this operation
   840  	// takes on the order of 0.05ms and allocates ~8KB for randomized client
   841  	// hellos.
   842  
   843  	conn := utls.UClient(
   844  		nil,
   845  		&utls.Config{InsecureSkipVerify: true},
   846  		utlsClientHelloID)
   847  
   848  	if utlsClientHelloSpec != nil {
   849  		err := conn.ApplyPreset(utlsClientHelloSpec)
   850  		if err != nil {
   851  			return "", errors.Trace(err)
   852  		}
   853  	}
   854  
   855  	err := conn.BuildHandshakeState()
   856  	if err != nil {
   857  		return "", errors.Trace(err)
   858  	}
   859  
   860  	for _, v := range conn.HandshakeState.Hello.SupportedVersions {
   861  		if v == utls.VersionTLS13 {
   862  			return protocol.TLS_VERSION_13, nil
   863  		}
   864  	}
   865  
   866  	return protocol.TLS_VERSION_12, nil
   867  }
   868  
   869  func init() {
   870  	// Favor compatibility over security. CustomTLSDial is used as an obfuscation
   871  	// layer; users of CustomTLSDial, including meek and remote server list
   872  	// downloads, don't depend on this TLS for its security properties.
   873  	utls.EnableWeakCiphers()
   874  }