github.com/Carcraftz/utls@v0.0.0-20220413235215-6b7c52fd78b6/u_parrots.go (about)

     1  // Copyright 2017 Google Inc. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tls
     6  
     7  import (
     8  	"crypto/sha256"
     9  	"encoding/binary"
    10  	"errors"
    11  	"fmt"
    12  	"io"
    13  	"sort"
    14  	"strconv"
    15  )
    16  
    17  func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
    18  	switch id {
    19  	case HelloChrome_58, HelloChrome_62:
    20  		return ClientHelloSpec{
    21  			TLSVersMax: VersionTLS12,
    22  			TLSVersMin: VersionTLS10,
    23  			CipherSuites: []uint16{
    24  				GREASE_PLACEHOLDER,
    25  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    26  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    27  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
    28  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
    29  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
    30  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
    31  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
    32  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
    33  				TLS_RSA_WITH_AES_128_GCM_SHA256,
    34  				TLS_RSA_WITH_AES_256_GCM_SHA384,
    35  				TLS_RSA_WITH_AES_128_CBC_SHA,
    36  				TLS_RSA_WITH_AES_256_CBC_SHA,
    37  				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
    38  			},
    39  			CompressionMethods: []byte{compressionNone},
    40  			Extensions: []TLSExtension{
    41  				&UtlsGREASEExtension{},
    42  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
    43  				&SNIExtension{},
    44  				&UtlsExtendedMasterSecretExtension{},
    45  				&SessionTicketExtension{},
    46  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
    47  					ECDSAWithP256AndSHA256,
    48  					PSSWithSHA256,
    49  					PKCS1WithSHA256,
    50  					ECDSAWithP384AndSHA384,
    51  					PSSWithSHA384,
    52  					PKCS1WithSHA384,
    53  					PSSWithSHA512,
    54  					PKCS1WithSHA512,
    55  					PKCS1WithSHA1},
    56  				},
    57  				&StatusRequestExtension{},
    58  				&SCTExtension{},
    59  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
    60  				&FakeChannelIDExtension{},
    61  				&SupportedPointsExtension{SupportedPoints: []byte{pointFormatUncompressed}},
    62  				&SupportedCurvesExtension{[]CurveID{CurveID(GREASE_PLACEHOLDER),
    63  					X25519, CurveP256, CurveP384}},
    64  				&UtlsGREASEExtension{},
    65  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
    66  			},
    67  			GetSessionID: sha256.Sum256,
    68  		}, nil
    69  	case HelloChrome_70:
    70  		return ClientHelloSpec{
    71  			TLSVersMin: VersionTLS10,
    72  			TLSVersMax: VersionTLS13,
    73  			CipherSuites: []uint16{
    74  				GREASE_PLACEHOLDER,
    75  				TLS_AES_128_GCM_SHA256,
    76  				TLS_AES_256_GCM_SHA384,
    77  				TLS_CHACHA20_POLY1305_SHA256,
    78  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
    79  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
    80  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
    81  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
    82  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
    83  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
    84  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
    85  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
    86  				TLS_RSA_WITH_AES_128_GCM_SHA256,
    87  				TLS_RSA_WITH_AES_256_GCM_SHA384,
    88  				TLS_RSA_WITH_AES_128_CBC_SHA,
    89  				TLS_RSA_WITH_AES_256_CBC_SHA,
    90  				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
    91  			},
    92  			CompressionMethods: []byte{
    93  				compressionNone,
    94  			},
    95  			Extensions: []TLSExtension{
    96  				&UtlsGREASEExtension{},
    97  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
    98  				&SNIExtension{},
    99  				&UtlsExtendedMasterSecretExtension{},
   100  				&SessionTicketExtension{},
   101  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   102  					ECDSAWithP256AndSHA256,
   103  					PSSWithSHA256,
   104  					PKCS1WithSHA256,
   105  					ECDSAWithP384AndSHA384,
   106  					PSSWithSHA384,
   107  					PKCS1WithSHA384,
   108  					PSSWithSHA512,
   109  					PKCS1WithSHA512,
   110  					PKCS1WithSHA1,
   111  				}},
   112  				&StatusRequestExtension{},
   113  				&SCTExtension{},
   114  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
   115  				&FakeChannelIDExtension{},
   116  				&SupportedPointsExtension{SupportedPoints: []byte{
   117  					pointFormatUncompressed,
   118  				}},
   119  				&KeyShareExtension{[]KeyShare{
   120  					{Group: CurveID(GREASE_PLACEHOLDER), Data: []byte{0}},
   121  					{Group: X25519},
   122  				}},
   123  				&PSKKeyExchangeModesExtension{[]uint8{pskModeDHE}},
   124  				&SupportedVersionsExtension{[]uint16{
   125  					GREASE_PLACEHOLDER,
   126  					VersionTLS13,
   127  					VersionTLS12,
   128  					VersionTLS11,
   129  					VersionTLS10}},
   130  				&SupportedCurvesExtension{[]CurveID{
   131  					CurveID(GREASE_PLACEHOLDER),
   132  					X25519,
   133  					CurveP256,
   134  					CurveP384,
   135  				}},
   136  				&CompressCertificateExtension{
   137  					Algorithms: []CertCompressionAlgo{CertCompressionBrotli},
   138  				},
   139  				&UtlsGREASEExtension{},
   140  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
   141  			},
   142  		}, nil
   143  	case HelloChrome_72:
   144  		return ClientHelloSpec{
   145  			CipherSuites: []uint16{
   146  				GREASE_PLACEHOLDER,
   147  				TLS_AES_128_GCM_SHA256,
   148  				TLS_AES_256_GCM_SHA384,
   149  				TLS_CHACHA20_POLY1305_SHA256,
   150  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   151  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   152  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   153  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   154  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   155  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   156  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   157  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   158  				TLS_RSA_WITH_AES_128_GCM_SHA256,
   159  				TLS_RSA_WITH_AES_256_GCM_SHA384,
   160  				TLS_RSA_WITH_AES_128_CBC_SHA,
   161  				TLS_RSA_WITH_AES_256_CBC_SHA,
   162  				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
   163  			},
   164  			CompressionMethods: []byte{
   165  				0x00, // compressionNone
   166  			},
   167  			Extensions: []TLSExtension{
   168  				&UtlsGREASEExtension{},
   169  				&SNIExtension{},
   170  				&UtlsExtendedMasterSecretExtension{},
   171  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   172  				&SupportedCurvesExtension{[]CurveID{
   173  					CurveID(GREASE_PLACEHOLDER),
   174  					X25519,
   175  					CurveP256,
   176  					CurveP384,
   177  				}},
   178  				&SupportedPointsExtension{SupportedPoints: []byte{
   179  					0x00, // pointFormatUncompressed
   180  				}},
   181  				&SessionTicketExtension{},
   182  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
   183  				&StatusRequestExtension{},
   184  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   185  					ECDSAWithP256AndSHA256,
   186  					PSSWithSHA256,
   187  					PKCS1WithSHA256,
   188  					ECDSAWithP384AndSHA384,
   189  					PSSWithSHA384,
   190  					PKCS1WithSHA384,
   191  					PSSWithSHA512,
   192  					PKCS1WithSHA512,
   193  					PKCS1WithSHA1,
   194  				}},
   195  				&SCTExtension{},
   196  				&KeyShareExtension{[]KeyShare{
   197  					{Group: CurveID(GREASE_PLACEHOLDER), Data: []byte{0}},
   198  					{Group: X25519},
   199  				}},
   200  				&PSKKeyExchangeModesExtension{[]uint8{
   201  					PskModeDHE,
   202  				}},
   203  				&SupportedVersionsExtension{[]uint16{
   204  					GREASE_PLACEHOLDER,
   205  					VersionTLS13,
   206  					VersionTLS12,
   207  					VersionTLS11,
   208  					VersionTLS10,
   209  				}},
   210  				&CompressCertificateExtension{
   211  					Algorithms: []CertCompressionAlgo{CertCompressionBrotli},
   212  				},
   213  				&UtlsGREASEExtension{},
   214  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
   215  			},
   216  		}, nil
   217  	case HelloChrome_83:
   218  		return ClientHelloSpec{
   219  			CipherSuites: []uint16{
   220  				GREASE_PLACEHOLDER,
   221  				TLS_AES_128_GCM_SHA256,
   222  				TLS_AES_256_GCM_SHA384,
   223  				TLS_CHACHA20_POLY1305_SHA256,
   224  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   225  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   226  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   227  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   228  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   229  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   230  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   231  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   232  				TLS_RSA_WITH_AES_128_GCM_SHA256,
   233  				TLS_RSA_WITH_AES_256_GCM_SHA384,
   234  				TLS_RSA_WITH_AES_128_CBC_SHA,
   235  				TLS_RSA_WITH_AES_256_CBC_SHA,
   236  			},
   237  			CompressionMethods: []byte{
   238  				0x00, // compressionNone
   239  			},
   240  			Extensions: []TLSExtension{
   241  				&UtlsGREASEExtension{},
   242  				&SNIExtension{},
   243  				&UtlsExtendedMasterSecretExtension{},
   244  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   245  				&SupportedCurvesExtension{[]CurveID{
   246  					CurveID(GREASE_PLACEHOLDER),
   247  					X25519,
   248  					CurveP256,
   249  					CurveP384,
   250  				}},
   251  				&SupportedPointsExtension{SupportedPoints: []byte{
   252  					0x00, // pointFormatUncompressed
   253  				}},
   254  				&SessionTicketExtension{},
   255  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
   256  				&StatusRequestExtension{},
   257  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   258  					ECDSAWithP256AndSHA256,
   259  					PSSWithSHA256,
   260  					PKCS1WithSHA256,
   261  					ECDSAWithP384AndSHA384,
   262  					PSSWithSHA384,
   263  					PKCS1WithSHA384,
   264  					PSSWithSHA512,
   265  					PKCS1WithSHA512,
   266  				}},
   267  				&SCTExtension{},
   268  				&KeyShareExtension{[]KeyShare{
   269  					{Group: CurveID(GREASE_PLACEHOLDER), Data: []byte{0}},
   270  					{Group: X25519},
   271  				}},
   272  				&PSKKeyExchangeModesExtension{[]uint8{
   273  					PskModeDHE,
   274  				}},
   275  				&SupportedVersionsExtension{[]uint16{
   276  					GREASE_PLACEHOLDER,
   277  					VersionTLS13,
   278  					VersionTLS12,
   279  					VersionTLS11,
   280  					VersionTLS10,
   281  				}},
   282  				&CompressCertificateExtension{[]CertCompressionAlgo{
   283  					CertCompressionBrotli,
   284  				}},
   285  				&UtlsGREASEExtension{},
   286  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
   287  			},
   288  		}, nil
   289  	case HelloChrome_100:
   290  		return ClientHelloSpec{
   291  			CipherSuites: []uint16{
   292  				GREASE_PLACEHOLDER,
   293  				TLS_AES_128_GCM_SHA256,
   294  				TLS_AES_256_GCM_SHA384,
   295  				TLS_CHACHA20_POLY1305_SHA256,
   296  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   297  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   298  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   299  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   300  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   301  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   302  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   303  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   304  				TLS_RSA_WITH_AES_128_GCM_SHA256,
   305  				TLS_RSA_WITH_AES_256_GCM_SHA384,
   306  				TLS_RSA_WITH_AES_128_CBC_SHA,
   307  				TLS_RSA_WITH_AES_256_CBC_SHA,
   308  			},
   309  			CompressionMethods: []uint8{
   310  				0x00,
   311  			},
   312  			Extensions: []TLSExtension{
   313  				&UtlsGREASEExtension{},
   314  				&SNIExtension{},
   315  				&UtlsExtendedMasterSecretExtension{},
   316  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   317  				&SupportedCurvesExtension{[]CurveID{
   318  					CurveID(GREASE_PLACEHOLDER),
   319  					X25519,
   320  					CurveP256,
   321  					CurveP384,
   322  				}},
   323  				&SupportedPointsExtension{SupportedPoints: []byte{
   324  					0x00, // pointFormatUncompressed
   325  				}},
   326  				&SessionTicketExtension{},
   327  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
   328  				&StatusRequestExtension{},
   329  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   330  					ECDSAWithP256AndSHA256,
   331  					PSSWithSHA256,
   332  					PKCS1WithSHA256,
   333  					ECDSAWithP384AndSHA384,
   334  					PSSWithSHA384,
   335  					PKCS1WithSHA384,
   336  					PSSWithSHA512,
   337  					PKCS1WithSHA512,
   338  				}},
   339  				&SCTExtension{},
   340  				&KeyShareExtension{[]KeyShare{
   341  					{Group: CurveID(GREASE_PLACEHOLDER), Data: []byte{0}},
   342  					{Group: X25519},
   343  				}},
   344  				&PSKKeyExchangeModesExtension{[]uint8{
   345  					PskModeDHE,
   346  				}},
   347  				&SupportedVersionsExtension{[]uint16{
   348  					GREASE_PLACEHOLDER,
   349  					VersionTLS13,
   350  					VersionTLS12,
   351  				}},
   352  				&CompressCertificateExtension{[]CertCompressionAlgo{
   353  					CertCompressionBrotli,
   354  				}},
   355  				&GenericExtension{Id: 0x4469}, // WARNING: UNKNOWN EXTENSION, USE AT YOUR OWN RISK
   356  				&UtlsGREASEExtension{},
   357  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
   358  			},
   359  		}, nil
   360  	case HelloFirefox_55, HelloFirefox_56:
   361  		return ClientHelloSpec{
   362  			TLSVersMax: VersionTLS12,
   363  			TLSVersMin: VersionTLS10,
   364  			CipherSuites: []uint16{
   365  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   366  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   367  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   368  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   369  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   370  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   371  				TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   372  				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   373  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   374  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   375  				FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
   376  				FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
   377  				TLS_RSA_WITH_AES_128_CBC_SHA,
   378  				TLS_RSA_WITH_AES_256_CBC_SHA,
   379  				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
   380  			},
   381  			CompressionMethods: []byte{compressionNone},
   382  			Extensions: []TLSExtension{
   383  				&SNIExtension{},
   384  				&UtlsExtendedMasterSecretExtension{},
   385  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   386  				&SupportedCurvesExtension{[]CurveID{X25519, CurveP256, CurveP384, CurveP521}},
   387  				&SupportedPointsExtension{SupportedPoints: []byte{pointFormatUncompressed}},
   388  				&SessionTicketExtension{},
   389  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
   390  				&StatusRequestExtension{},
   391  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   392  					ECDSAWithP256AndSHA256,
   393  					ECDSAWithP384AndSHA384,
   394  					ECDSAWithP521AndSHA512,
   395  					PSSWithSHA256,
   396  					PSSWithSHA384,
   397  					PSSWithSHA512,
   398  					PKCS1WithSHA256,
   399  					PKCS1WithSHA384,
   400  					PKCS1WithSHA512,
   401  					ECDSAWithSHA1,
   402  					PKCS1WithSHA1},
   403  				},
   404  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
   405  			},
   406  			GetSessionID: nil,
   407  		}, nil
   408  	case HelloFirefox_63, HelloFirefox_65:
   409  		return ClientHelloSpec{
   410  			TLSVersMin: VersionTLS10,
   411  			TLSVersMax: VersionTLS13,
   412  			CipherSuites: []uint16{
   413  				TLS_AES_128_GCM_SHA256,
   414  				TLS_CHACHA20_POLY1305_SHA256,
   415  				TLS_AES_256_GCM_SHA384,
   416  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   417  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   418  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   419  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   420  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   421  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   422  				TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   423  				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   424  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   425  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   426  				FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
   427  				FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
   428  				TLS_RSA_WITH_AES_128_CBC_SHA,
   429  				TLS_RSA_WITH_AES_256_CBC_SHA,
   430  				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
   431  			},
   432  			CompressionMethods: []byte{
   433  				compressionNone,
   434  			},
   435  			Extensions: []TLSExtension{
   436  				&SNIExtension{},
   437  				&UtlsExtendedMasterSecretExtension{},
   438  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   439  				&SupportedCurvesExtension{[]CurveID{
   440  					X25519,
   441  					CurveP256,
   442  					CurveP384,
   443  					CurveP521,
   444  					CurveID(FakeFFDHE2048),
   445  					CurveID(FakeFFDHE3072),
   446  				}},
   447  				&SupportedPointsExtension{SupportedPoints: []byte{
   448  					pointFormatUncompressed,
   449  				}},
   450  				&SessionTicketExtension{},
   451  				&ALPNExtension{AlpnProtocols: []string{"h2", "http/1.1"}},
   452  				&StatusRequestExtension{},
   453  				&KeyShareExtension{[]KeyShare{
   454  					{Group: X25519},
   455  					{Group: CurveP256},
   456  				}},
   457  				&SupportedVersionsExtension{[]uint16{
   458  					VersionTLS13,
   459  					VersionTLS12,
   460  					VersionTLS11,
   461  					VersionTLS10}},
   462  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   463  					ECDSAWithP256AndSHA256,
   464  					ECDSAWithP384AndSHA384,
   465  					ECDSAWithP521AndSHA512,
   466  					PSSWithSHA256,
   467  					PSSWithSHA384,
   468  					PSSWithSHA512,
   469  					PKCS1WithSHA256,
   470  					PKCS1WithSHA384,
   471  					PKCS1WithSHA512,
   472  					ECDSAWithSHA1,
   473  					PKCS1WithSHA1,
   474  				}},
   475  				&PSKKeyExchangeModesExtension{[]uint8{pskModeDHE}},
   476  				&FakeRecordSizeLimitExtension{0x4001},
   477  				&UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle},
   478  			}}, nil
   479  	case HelloIOS_11_1:
   480  		return ClientHelloSpec{
   481  			TLSVersMax: VersionTLS12,
   482  			TLSVersMin: VersionTLS10,
   483  			CipherSuites: []uint16{
   484  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   485  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   486  				DISABLED_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
   487  				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
   488  				TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   489  				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   490  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   491  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   492  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   493  				DISABLED_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
   494  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
   495  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   496  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   497  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   498  				TLS_RSA_WITH_AES_256_GCM_SHA384,
   499  				TLS_RSA_WITH_AES_128_GCM_SHA256,
   500  				DISABLED_TLS_RSA_WITH_AES_256_CBC_SHA256,
   501  				TLS_RSA_WITH_AES_128_CBC_SHA256,
   502  				TLS_RSA_WITH_AES_256_CBC_SHA,
   503  				TLS_RSA_WITH_AES_128_CBC_SHA,
   504  			},
   505  			CompressionMethods: []byte{
   506  				compressionNone,
   507  			},
   508  			Extensions: []TLSExtension{
   509  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   510  				&SNIExtension{},
   511  				&UtlsExtendedMasterSecretExtension{},
   512  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   513  					ECDSAWithP256AndSHA256,
   514  					PSSWithSHA256,
   515  					PKCS1WithSHA256,
   516  					ECDSAWithP384AndSHA384,
   517  					PSSWithSHA384,
   518  					PKCS1WithSHA384,
   519  					PSSWithSHA512,
   520  					PKCS1WithSHA512,
   521  					PKCS1WithSHA1,
   522  				}},
   523  				&StatusRequestExtension{},
   524  				&NPNExtension{},
   525  				&SCTExtension{},
   526  				&ALPNExtension{AlpnProtocols: []string{"h2", "h2-16", "h2-15", "h2-14", "spdy/3.1", "spdy/3", "http/1.1"}},
   527  				&SupportedPointsExtension{SupportedPoints: []byte{
   528  					pointFormatUncompressed,
   529  				}},
   530  				&SupportedCurvesExtension{Curves: []CurveID{
   531  					X25519,
   532  					CurveP256,
   533  					CurveP384,
   534  					CurveP521,
   535  				}},
   536  			},
   537  		}, nil
   538  	case HelloIOS_12_1:
   539  		return ClientHelloSpec{
   540  			CipherSuites: []uint16{
   541  				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
   542  				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   543  				DISABLED_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
   544  				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
   545  				TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
   546  				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
   547  				TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,
   548  				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   549  				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   550  				DISABLED_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
   551  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
   552  				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
   553  				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
   554  				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,
   555  				TLS_RSA_WITH_AES_256_GCM_SHA384,
   556  				TLS_RSA_WITH_AES_128_GCM_SHA256,
   557  				DISABLED_TLS_RSA_WITH_AES_256_CBC_SHA256,
   558  				TLS_RSA_WITH_AES_128_CBC_SHA256,
   559  				TLS_RSA_WITH_AES_256_CBC_SHA,
   560  				TLS_RSA_WITH_AES_128_CBC_SHA,
   561  				0xc008,
   562  				TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
   563  				TLS_RSA_WITH_3DES_EDE_CBC_SHA,
   564  			},
   565  			CompressionMethods: []byte{
   566  				compressionNone,
   567  			},
   568  			Extensions: []TLSExtension{
   569  				&RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient},
   570  				&SNIExtension{},
   571  				&UtlsExtendedMasterSecretExtension{},
   572  				&SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: []SignatureScheme{
   573  					ECDSAWithP256AndSHA256,
   574  					PSSWithSHA256,
   575  					PKCS1WithSHA256,
   576  					ECDSAWithP384AndSHA384,
   577  					ECDSAWithSHA1,
   578  					PSSWithSHA384,
   579  					PSSWithSHA384,
   580  					PKCS1WithSHA384,
   581  					PSSWithSHA512,
   582  					PKCS1WithSHA512,
   583  					PKCS1WithSHA1,
   584  				}},
   585  				&StatusRequestExtension{},
   586  				&NPNExtension{},
   587  				&SCTExtension{},
   588  				&ALPNExtension{AlpnProtocols: []string{"h2", "h2-16", "h2-15", "h2-14", "spdy/3.1", "spdy/3", "http/1.1"}},
   589  				&SupportedPointsExtension{SupportedPoints: []byte{
   590  					pointFormatUncompressed,
   591  				}},
   592  				&SupportedCurvesExtension{[]CurveID{
   593  					X25519,
   594  					CurveP256,
   595  					CurveP384,
   596  					CurveP521,
   597  				}},
   598  			},
   599  		}, nil
   600  	default:
   601  		return ClientHelloSpec{}, errors.New("ClientHello ID " + id.Str() + " is unknown")
   602  	}
   603  }
   604  
   605  func (uconn *UConn) applyPresetByID(id ClientHelloID) (err error) {
   606  	var spec ClientHelloSpec
   607  	uconn.ClientHelloID = id
   608  	// choose/generate the spec
   609  	switch id.Client {
   610  	case helloRandomized, helloRandomizedNoALPN, helloRandomizedALPN:
   611  		spec, err = uconn.generateRandomizedSpec()
   612  		if err != nil {
   613  			return err
   614  		}
   615  	case helloCustom:
   616  		return nil
   617  
   618  	default:
   619  		spec, err = utlsIdToSpec(id)
   620  		if err != nil {
   621  			return err
   622  		}
   623  	}
   624  
   625  	return uconn.ApplyPreset(&spec)
   626  }
   627  
   628  // ApplyPreset should only be used in conjunction with HelloCustom to apply custom specs.
   629  // Fields of TLSExtensions that are slices/pointers are shared across different connections with
   630  // same ClientHelloSpec. It is advised to use different specs and avoid any shared state.
   631  func (uconn *UConn) ApplyPreset(p *ClientHelloSpec) error {
   632  	var err error
   633  
   634  	err = uconn.SetTLSVers(p.TLSVersMin, p.TLSVersMax, p.Extensions)
   635  	if err != nil {
   636  		return err
   637  	}
   638  
   639  	privateHello, ecdheParams, err := uconn.makeClientHello()
   640  	if err != nil {
   641  		return err
   642  	}
   643  	uconn.HandshakeState.Hello = privateHello.getPublicPtr()
   644  	uconn.HandshakeState.State13.EcdheParams = ecdheParamMapToPublic(ecdheParams)
   645  	hello := uconn.HandshakeState.Hello
   646  	session := uconn.HandshakeState.Session
   647  
   648  	switch len(hello.Random) {
   649  	case 0:
   650  		hello.Random = make([]byte, 32)
   651  		_, err := io.ReadFull(uconn.config.rand(), hello.Random)
   652  		if err != nil {
   653  			return errors.New("tls: short read from Rand: " + err.Error())
   654  		}
   655  	case 32:
   656  	// carry on
   657  	default:
   658  		return errors.New("ClientHello expected length: 32 bytes. Got: " +
   659  			strconv.Itoa(len(hello.Random)) + " bytes")
   660  	}
   661  	if len(hello.CipherSuites) == 0 {
   662  		hello.CipherSuites = defaultCipherSuites()
   663  	}
   664  	if len(hello.CompressionMethods) == 0 {
   665  		hello.CompressionMethods = []uint8{compressionNone}
   666  	}
   667  
   668  	// Currently, GREASE is assumed to come from BoringSSL
   669  	grease_bytes := make([]byte, 2*ssl_grease_last_index)
   670  	grease_extensions_seen := 0
   671  	_, err = io.ReadFull(uconn.config.rand(), grease_bytes)
   672  	if err != nil {
   673  		return errors.New("tls: short read from Rand: " + err.Error())
   674  	}
   675  	for i := range uconn.greaseSeed {
   676  		uconn.greaseSeed[i] = binary.LittleEndian.Uint16(grease_bytes[2*i : 2*i+2])
   677  	}
   678  	if uconn.greaseSeed[ssl_grease_extension1] == uconn.greaseSeed[ssl_grease_extension2] {
   679  		uconn.greaseSeed[ssl_grease_extension2] ^= 0x1010
   680  	}
   681  
   682  	hello.CipherSuites = make([]uint16, len(p.CipherSuites))
   683  	copy(hello.CipherSuites, p.CipherSuites)
   684  	for i := range hello.CipherSuites {
   685  		if hello.CipherSuites[i] == GREASE_PLACEHOLDER {
   686  			hello.CipherSuites[i] = GetBoringGREASEValue(uconn.greaseSeed, ssl_grease_cipher)
   687  		}
   688  	}
   689  	uconn.GetSessionID = p.GetSessionID
   690  	uconn.Extensions = make([]TLSExtension, len(p.Extensions))
   691  	copy(uconn.Extensions, p.Extensions)
   692  
   693  	// reGrease, and point things to each other
   694  	for _, e := range uconn.Extensions {
   695  		switch ext := e.(type) {
   696  		case *SNIExtension:
   697  			if ext.ServerName == "" {
   698  				ext.ServerName = uconn.config.ServerName
   699  			}
   700  		case *UtlsGREASEExtension:
   701  			switch grease_extensions_seen {
   702  			case 0:
   703  				ext.Value = GetBoringGREASEValue(uconn.greaseSeed, ssl_grease_extension1)
   704  			case 1:
   705  				ext.Value = GetBoringGREASEValue(uconn.greaseSeed, ssl_grease_extension2)
   706  				ext.Body = []byte{0}
   707  			default:
   708  				return errors.New("at most 2 grease extensions are supported")
   709  			}
   710  			grease_extensions_seen += 1
   711  		case *SessionTicketExtension:
   712  			if session == nil && uconn.config.ClientSessionCache != nil {
   713  				cacheKey := clientSessionCacheKey(uconn.RemoteAddr(), uconn.config)
   714  				session, _ = uconn.config.ClientSessionCache.Get(cacheKey)
   715  				// TODO: use uconn.loadSession(hello.getPrivateObj()) to support TLS 1.3 PSK-style resumption
   716  			}
   717  			err := uconn.SetSessionState(session)
   718  			if err != nil {
   719  				return err
   720  			}
   721  		case *SupportedCurvesExtension:
   722  			for i := range ext.Curves {
   723  				if ext.Curves[i] == GREASE_PLACEHOLDER {
   724  					ext.Curves[i] = CurveID(GetBoringGREASEValue(uconn.greaseSeed, ssl_grease_group))
   725  				}
   726  			}
   727  		case *KeyShareExtension:
   728  			for i := range ext.KeyShares {
   729  				curveID := ext.KeyShares[i].Group
   730  				if curveID == GREASE_PLACEHOLDER {
   731  					ext.KeyShares[i].Group = CurveID(GetBoringGREASEValue(uconn.greaseSeed, ssl_grease_group))
   732  					continue
   733  				}
   734  				if len(ext.KeyShares[i].Data) > 1 {
   735  					continue
   736  				}
   737  
   738  				var params ecdheParameters
   739  				switch utlsSupportedGroups[curveID] {
   740  				case true:
   741  					var ok bool
   742  					params, ok = uconn.HandshakeState.State13.EcdheParams[curveID]
   743  					if !ok {
   744  						// Should never happen.
   745  						return fmt.Errorf("BUG: unsupported Curve in KeyShareExtension: %v.", curveID)
   746  					}
   747  				case false:
   748  					var err error
   749  					params, err = generateECDHEParameters(uconn.config.rand(), curveID)
   750  					if err != nil {
   751  						return fmt.Errorf("unsupported Curve in KeyShareExtension: %v."+
   752  							"To mimic it, fill the Data(key) field manually.", curveID)
   753  					}
   754  				}
   755  
   756  				ext.KeyShares[i].Data = params.PublicKey()
   757  			}
   758  		case *SupportedVersionsExtension:
   759  			for i := range ext.Versions {
   760  				if ext.Versions[i] == GREASE_PLACEHOLDER {
   761  					ext.Versions[i] = GetBoringGREASEValue(uconn.greaseSeed, ssl_grease_version)
   762  				}
   763  			}
   764  		case *CompressCertificateExtension:
   765  			uconn.HandshakeState.State13.CertCompAlgs = ext.Algorithms
   766  		}
   767  	}
   768  	return nil
   769  }
   770  
   771  func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) {
   772  	p := ClientHelloSpec{}
   773  
   774  	if uconn.ClientHelloID.Seed == nil {
   775  		seed, err := NewPRNGSeed()
   776  		if err != nil {
   777  			return p, err
   778  		}
   779  		uconn.ClientHelloID.Seed = seed
   780  	}
   781  
   782  	r, err := newPRNGWithSeed(uconn.ClientHelloID.Seed)
   783  	if err != nil {
   784  		return p, err
   785  	}
   786  
   787  	id := uconn.ClientHelloID
   788  
   789  	var WithALPN bool
   790  	switch id.Client {
   791  	case helloRandomizedALPN:
   792  		WithALPN = true
   793  	case helloRandomizedNoALPN:
   794  		WithALPN = false
   795  	case helloRandomized:
   796  		if r.FlipWeightedCoin(0.7) {
   797  			WithALPN = true
   798  		} else {
   799  			WithALPN = false
   800  		}
   801  	default:
   802  		return p, fmt.Errorf("using non-randomized ClientHelloID %v to generate randomized spec", id.Client)
   803  	}
   804  
   805  	p.CipherSuites = make([]uint16, len(defaultCipherSuites()))
   806  	copy(p.CipherSuites, defaultCipherSuites())
   807  	shuffledSuites, err := shuffledCiphers(r)
   808  	if err != nil {
   809  		return p, err
   810  	}
   811  
   812  	if r.FlipWeightedCoin(0.4) {
   813  		p.TLSVersMin = VersionTLS10
   814  		p.TLSVersMax = VersionTLS13
   815  		tls13ciphers := make([]uint16, len(defaultCipherSuitesTLS13()))
   816  		copy(tls13ciphers, defaultCipherSuitesTLS13())
   817  		r.rand.Shuffle(len(tls13ciphers), func(i, j int) {
   818  			tls13ciphers[i], tls13ciphers[j] = tls13ciphers[j], tls13ciphers[i]
   819  		})
   820  		// appending TLS 1.3 ciphers before TLS 1.2, since that's what popular implementations do
   821  		shuffledSuites = append(tls13ciphers, shuffledSuites...)
   822  
   823  		// TLS 1.3 forbids RC4 in any configurations
   824  		shuffledSuites = removeRC4Ciphers(shuffledSuites)
   825  	} else {
   826  		p.TLSVersMin = VersionTLS10
   827  		p.TLSVersMax = VersionTLS12
   828  	}
   829  
   830  	p.CipherSuites = removeRandomCiphers(r, shuffledSuites, 0.4)
   831  
   832  	sni := SNIExtension{uconn.config.ServerName}
   833  	sessionTicket := SessionTicketExtension{Session: uconn.HandshakeState.Session}
   834  
   835  	sigAndHashAlgos := []SignatureScheme{
   836  		ECDSAWithP256AndSHA256,
   837  		PKCS1WithSHA256,
   838  		ECDSAWithP384AndSHA384,
   839  		PKCS1WithSHA384,
   840  		PKCS1WithSHA1,
   841  		PKCS1WithSHA512,
   842  	}
   843  
   844  	if r.FlipWeightedCoin(0.63) {
   845  		sigAndHashAlgos = append(sigAndHashAlgos, ECDSAWithSHA1)
   846  	}
   847  	if r.FlipWeightedCoin(0.59) {
   848  		sigAndHashAlgos = append(sigAndHashAlgos, ECDSAWithP521AndSHA512)
   849  	}
   850  	if r.FlipWeightedCoin(0.51) || p.TLSVersMax == VersionTLS13 {
   851  		// https://tools.ietf.org/html/rfc8446 says "...RSASSA-PSS (which is mandatory in TLS 1.3)..."
   852  		sigAndHashAlgos = append(sigAndHashAlgos, PSSWithSHA256)
   853  		if r.FlipWeightedCoin(0.9) {
   854  			// these usually go together
   855  			sigAndHashAlgos = append(sigAndHashAlgos, PSSWithSHA384)
   856  			sigAndHashAlgos = append(sigAndHashAlgos, PSSWithSHA512)
   857  		}
   858  	}
   859  
   860  	r.rand.Shuffle(len(sigAndHashAlgos), func(i, j int) {
   861  		sigAndHashAlgos[i], sigAndHashAlgos[j] = sigAndHashAlgos[j], sigAndHashAlgos[i]
   862  	})
   863  	sigAndHash := SignatureAlgorithmsExtension{SupportedSignatureAlgorithms: sigAndHashAlgos}
   864  
   865  	status := StatusRequestExtension{}
   866  	sct := SCTExtension{}
   867  	ems := UtlsExtendedMasterSecretExtension{}
   868  	points := SupportedPointsExtension{SupportedPoints: []byte{pointFormatUncompressed}}
   869  
   870  	curveIDs := []CurveID{}
   871  	if r.FlipWeightedCoin(0.71) || p.TLSVersMax == VersionTLS13 {
   872  		curveIDs = append(curveIDs, X25519)
   873  	}
   874  	curveIDs = append(curveIDs, CurveP256, CurveP384)
   875  	if r.FlipWeightedCoin(0.46) {
   876  		curveIDs = append(curveIDs, CurveP521)
   877  	}
   878  
   879  	curves := SupportedCurvesExtension{curveIDs}
   880  
   881  	padding := UtlsPaddingExtension{GetPaddingLen: BoringPaddingStyle}
   882  	reneg := RenegotiationInfoExtension{Renegotiation: RenegotiateOnceAsClient}
   883  
   884  	p.Extensions = []TLSExtension{
   885  		&sni,
   886  		&sessionTicket,
   887  		&sigAndHash,
   888  		&points,
   889  		&curves,
   890  	}
   891  
   892  	if WithALPN {
   893  		if len(uconn.config.NextProtos) == 0 {
   894  			// if user didn't specify alpn yet, choose something popular
   895  			uconn.config.NextProtos = []string{"h2", "http/1.1"}
   896  		}
   897  		alpn := ALPNExtension{AlpnProtocols: uconn.config.NextProtos}
   898  		p.Extensions = append(p.Extensions, &alpn)
   899  	}
   900  
   901  	if r.FlipWeightedCoin(0.62) || p.TLSVersMax == VersionTLS13 {
   902  		// always include for TLS 1.3, since TLS 1.3 ClientHellos are often over 256 bytes
   903  		// and that's when padding is required to work around buggy middleboxes
   904  		p.Extensions = append(p.Extensions, &padding)
   905  	}
   906  	if r.FlipWeightedCoin(0.74) {
   907  		p.Extensions = append(p.Extensions, &status)
   908  	}
   909  	if r.FlipWeightedCoin(0.46) {
   910  		p.Extensions = append(p.Extensions, &sct)
   911  	}
   912  	if r.FlipWeightedCoin(0.75) {
   913  		p.Extensions = append(p.Extensions, &reneg)
   914  	}
   915  	if r.FlipWeightedCoin(0.77) {
   916  		p.Extensions = append(p.Extensions, &ems)
   917  	}
   918  	if p.TLSVersMax == VersionTLS13 {
   919  		ks := KeyShareExtension{[]KeyShare{
   920  			{Group: X25519}, // the key for the group will be generated later
   921  		}}
   922  		if r.FlipWeightedCoin(0.25) {
   923  			ks.KeyShares = append(ks.KeyShares, KeyShare{Group: CurveP256})
   924  		}
   925  		pskExchangeModes := PSKKeyExchangeModesExtension{[]uint8{pskModeDHE}}
   926  		supportedVersionsExt := SupportedVersionsExtension{
   927  			Versions: makeSupportedVersions(p.TLSVersMin, p.TLSVersMax),
   928  		}
   929  		p.Extensions = append(p.Extensions, &ks, &pskExchangeModes, &supportedVersionsExt)
   930  	}
   931  	r.rand.Shuffle(len(p.Extensions), func(i, j int) {
   932  		p.Extensions[i], p.Extensions[j] = p.Extensions[j], p.Extensions[i]
   933  	})
   934  
   935  	return p, nil
   936  }
   937  
   938  func removeRandomCiphers(r *prng, s []uint16, maxRemovalProbability float64) []uint16 {
   939  	// removes elements in place
   940  	// probability to remove increases for further elements
   941  	// never remove first cipher
   942  	if len(s) <= 1 {
   943  		return s
   944  	}
   945  
   946  	// remove random elements
   947  	floatLen := float64(len(s))
   948  	sliceLen := len(s)
   949  	for i := 1; i < sliceLen; i++ {
   950  		if r.FlipWeightedCoin(maxRemovalProbability * float64(i) / floatLen) {
   951  			s = append(s[:i], s[i+1:]...)
   952  			sliceLen--
   953  			i--
   954  		}
   955  	}
   956  	return s[:sliceLen]
   957  }
   958  
   959  func shuffledCiphers(r *prng) ([]uint16, error) {
   960  	ciphers := make(sortableCiphers, len(cipherSuites))
   961  	perm := r.Perm(len(cipherSuites))
   962  	for i, suite := range cipherSuites {
   963  		ciphers[i] = sortableCipher{suite: suite.id,
   964  			isObsolete: ((suite.flags & suiteTLS12) == 0),
   965  			randomTag:  perm[i]}
   966  	}
   967  	sort.Sort(ciphers)
   968  	return ciphers.GetCiphers(), nil
   969  }
   970  
   971  type sortableCipher struct {
   972  	isObsolete bool
   973  	randomTag  int
   974  	suite      uint16
   975  }
   976  
   977  type sortableCiphers []sortableCipher
   978  
   979  func (ciphers sortableCiphers) Len() int {
   980  	return len(ciphers)
   981  }
   982  
   983  func (ciphers sortableCiphers) Less(i, j int) bool {
   984  	if ciphers[i].isObsolete && !ciphers[j].isObsolete {
   985  		return false
   986  	}
   987  	if ciphers[j].isObsolete && !ciphers[i].isObsolete {
   988  		return true
   989  	}
   990  	return ciphers[i].randomTag < ciphers[j].randomTag
   991  }
   992  
   993  func (ciphers sortableCiphers) Swap(i, j int) {
   994  	ciphers[i], ciphers[j] = ciphers[j], ciphers[i]
   995  }
   996  
   997  func (ciphers sortableCiphers) GetCiphers() []uint16 {
   998  	cipherIDs := make([]uint16, len(ciphers))
   999  	for i := range ciphers {
  1000  		cipherIDs[i] = ciphers[i].suite
  1001  	}
  1002  	return cipherIDs
  1003  }
  1004  
  1005  func removeRC4Ciphers(s []uint16) []uint16 {
  1006  	// removes elements in place
  1007  	sliceLen := len(s)
  1008  	for i := 0; i < sliceLen; i++ {
  1009  		cipher := s[i]
  1010  		if cipher == TLS_ECDHE_ECDSA_WITH_RC4_128_SHA ||
  1011  			cipher == TLS_ECDHE_RSA_WITH_RC4_128_SHA ||
  1012  			cipher == TLS_RSA_WITH_RC4_128_SHA {
  1013  			s = append(s[:i], s[i+1:]...)
  1014  			sliceLen--
  1015  			i--
  1016  		}
  1017  	}
  1018  	return s[:sliceLen]
  1019  }