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
5package tls
6
7import (
8	"crypto/hmac"
9	"crypto/sha512"
10	"fmt"
11)
12
13// Naming convention:
14// Unsupported things are prefixed with "Fake"
15// Things, supported by utls, but not crypto/tls' are prefixed with "utls"
16// Supported things, that have changed their ID are prefixed with "Old"
17// Supported but disabled things are prefixed with "Disabled". We will _enable_ them.
18const (
19	utlsExtensionPadding              uint16 = 21
20	utlsExtensionExtendedMasterSecret uint16 = 23 // https://tools.ietf.org/html/rfc7627
21
22	// extensions with 'fake' prefix break connection, if server echoes them back
23	fakeExtensionChannelID uint16 = 30032 // not IANA assigned
24
25	fakeCertCompressionAlgs uint16 = 0x001b
26	fakeRecordSizeLimit     uint16 = 0x001c
27)
28
29const (
30	OLD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256   = uint16(0xcc13)
31	OLD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = uint16(0xcc14)
32
33	DISABLED_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = uint16(0xc024)
34	DISABLED_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384   = uint16(0xc028)
35	DISABLED_TLS_RSA_WITH_AES_256_CBC_SHA256         = uint16(0x003d)
36
37	FAKE_OLD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = uint16(0xcc15) // we can try to craft these ciphersuites
38	FAKE_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256           = uint16(0x009e) // from existing pieces, if needed
39
40	FAKE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA  = uint16(0x0033)
41	FAKE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA  = uint16(0x0039)
42	FAKE_TLS_RSA_WITH_RC4_128_MD5          = uint16(0x0004)
43	FAKE_TLS_EMPTY_RENEGOTIATION_INFO_SCSV = uint16(0x00ff)
44)
45
46// newest signatures
47var (
48	FakePKCS1WithSHA224 SignatureScheme = 0x0301
49	FakeECDSAWithSHA224 SignatureScheme = 0x0303
50
51	// fakeEd25519 = SignatureAndHash{0x08, 0x07}
52	// fakeEd448 = SignatureAndHash{0x08, 0x08}
53)
54
55// fake curves(groups)
56var (
57	FakeFFDHE2048 = uint16(0x0100)
58	FakeFFDHE3072 = uint16(0x0101)
59)
60
61// https://tools.ietf.org/html/draft-ietf-tls-certificate-compression-04
62type CertCompressionAlgo uint16
63
64const (
65	CertCompressionZlib   CertCompressionAlgo = 0x0001
66	CertCompressionBrotli CertCompressionAlgo = 0x0002
67)
68
69const (
70	PskModePlain uint8 = pskModePlain
71	PskModeDHE   uint8 = pskModeDHE
72)
73
74type ClientHelloID struct {
75	Client string
76
77	// Version specifies version of a mimicked clients (e.g. browsers).
78	// Not used in randomized, custom handshake, and default Go.
79	Version string
80
81	// Seed is only used for randomized fingerprints to seed PRNG.
82	// Must not be modified once set.
83	Seed *PRNGSeed
84}
85
86func (p *ClientHelloID) Str() string {
87	return fmt.Sprintf("%s-%s", p.Client, p.Version)
88}
89
90func (p *ClientHelloID) IsSet() bool {
91	return (p.Client == "") && (p.Version == "")
92}
93
94const (
95	// clients
96	helloGolang           = "Golang"
97	helloRandomized       = "Randomized"
98	helloRandomizedALPN   = "Randomized-ALPN"
99	helloRandomizedNoALPN = "Randomized-NoALPN"
100	helloCustom           = "Custom"
101	helloFirefox          = "Firefox"
102	helloChrome           = "Chrome"
103	helloIOS              = "iOS"
104	helloAndroid          = "Android"
105
106	// versions
107	helloAutoVers = "0"
108)
109
110type ClientHelloSpec struct {
111	CipherSuites       []uint16       // nil => default
112	CompressionMethods []uint8        // nil => no compression
113	Extensions         []TLSExtension // nil => no extensions
114
115	TLSVersMin uint16 // [1.0-1.3] default: parse from .Extensions, if SupportedVersions ext is not present => 1.0
116	TLSVersMax uint16 // [1.2-1.3] default: parse from .Extensions, if SupportedVersions ext is not present => 1.2
117
118	// GreaseStyle: currently only random
119	// sessionID may or may not depend on ticket; nil => random
120	GetSessionID func(ticket []byte) [32]byte
121
122	// TLSFingerprintLink string // ?? link to tlsfingerprint.io for informational purposes
123}
124
125var (
126	// HelloGolang will use default "crypto/tls" handshake marshaling codepath, which WILL
127	// overwrite your changes to Hello(Config, Session are fine).
128	// You might want to call BuildHandshakeState() before applying any changes.
129	// UConn.Extensions will be completely ignored.
130	HelloGolang = ClientHelloID{helloGolang, helloAutoVers, nil}
131
132	// HelloCustom will prepare ClientHello with empty uconn.Extensions so you can fill it with
133	// TLSExtensions manually or use ApplyPreset function
134	HelloCustom = ClientHelloID{helloCustom, helloAutoVers, nil}
135
136	// HelloRandomized* randomly adds/reorders extensions, ciphersuites, etc.
137	HelloRandomized       = ClientHelloID{helloRandomized, helloAutoVers, nil}
138	HelloRandomizedALPN   = ClientHelloID{helloRandomizedALPN, helloAutoVers, nil}
139	HelloRandomizedNoALPN = ClientHelloID{helloRandomizedNoALPN, helloAutoVers, nil}
140
141	// The rest will will parrot given browser.
142	HelloFirefox_Auto = HelloFirefox_65
143	HelloFirefox_55   = ClientHelloID{helloFirefox, "55", nil}
144	HelloFirefox_56   = ClientHelloID{helloFirefox, "56", nil}
145	HelloFirefox_63   = ClientHelloID{helloFirefox, "63", nil}
146	HelloFirefox_65   = ClientHelloID{helloFirefox, "65", nil}
147
148	HelloChrome_Auto = HelloChrome_72
149	HelloChrome_58   = ClientHelloID{helloChrome, "58", nil}
150	HelloChrome_62   = ClientHelloID{helloChrome, "62", nil}
151	HelloChrome_70   = ClientHelloID{helloChrome, "70", nil}
152	HelloChrome_72   = ClientHelloID{helloChrome, "72", nil}
153
154	HelloIOS_Auto = HelloIOS_12_1
155	HelloIOS_11_1 = ClientHelloID{helloIOS, "111", nil} // legacy "111" means 11.1
156	HelloIOS_12_1 = ClientHelloID{helloIOS, "12.1", nil}
157)
158
159// based on spec's GreaseStyle, GREASE_PLACEHOLDER may be replaced by another GREASE value
160// https://tools.ietf.org/html/draft-ietf-tls-grease-01
161const GREASE_PLACEHOLDER = 0x0a0a
162
163// utlsMacSHA384 returns a SHA-384 based MAC. These are only supported in TLS 1.2
164// so the given version is ignored.
165func utlsMacSHA384(version uint16, key []byte) macFunction {
166	return tls10MAC{h: hmac.New(sha512.New384, key)}
167}
168
169var utlsSupportedCipherSuites []*cipherSuite
170
171func init() {
172	utlsSupportedCipherSuites = append(cipherSuites, []*cipherSuite{
173		{OLD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheRSAKA,
174			suiteECDHE | suiteTLS12 | suiteDefaultOff, nil, nil, aeadChaCha20Poly1305},
175		{OLD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheECDSAKA,
176			suiteECDHE | suiteECDSA | suiteTLS12 | suiteDefaultOff, nil, nil, aeadChaCha20Poly1305},
177	}...)
178}
179
180// EnableWeakCiphers allows utls connections to continue in some cases, when weak cipher was chosen.
181// This provides better compatibility with servers on the web, but weakens security. Feel free
182// to use this option if you establish additional secure connection inside of utls connection.
183// This option does not change the shape of parrots (i.e. same ciphers will be offered either way).
184// Must be called before establishing any connections.
185func EnableWeakCiphers() {
186	utlsSupportedCipherSuites = append(cipherSuites, []*cipherSuite{
187		{DISABLED_TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA,
188			suiteTLS12 | suiteDefaultOff, cipherAES, macSHA256, nil},
189
190		{DISABLED_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA,
191			suiteECDHE | suiteECDSA | suiteTLS12 | suiteDefaultOff | suiteSHA384, cipherAES, utlsMacSHA384, nil},
192		{DISABLED_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA,
193			suiteECDHE | suiteTLS12 | suiteDefaultOff | suiteSHA384, cipherAES, utlsMacSHA384, nil},
194	}...)
195}
196