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	"bytes"
9	"encoding/hex"
10	"fmt"
11	"io/ioutil"
12	"net"
13	"reflect"
14	"testing"
15)
16
17func assertEquality(t *testing.T, fieldName string, expected, actual interface{}) {
18	if kActual, ok := actual.(KeyShare); ok {
19		kExpected := expected.(KeyShare)
20		assertEquality(t, fieldName, kExpected.Group, kActual.Group)
21		return
22	}
23
24	if fieldName == "SupportedCurves" || fieldName == "KeyShares" {
25		cExpected := expected.(CurveID)
26		cActual := actual.(CurveID)
27		if isGREASEUint16(uint16(cExpected)) && isGREASEUint16(uint16(cActual)) {
28			return
29		}
30	}
31
32	if fieldName == "SupportedVersions" || fieldName == "CipherSuites" {
33		cExpected := expected.(uint16)
34		cActual := actual.(uint16)
35		if isGREASEUint16(cExpected) && isGREASEUint16(cActual) {
36			return
37		}
38	}
39
40	if expected != actual {
41		t.Errorf("%v fields not equal, expected: %v, got: %v", fieldName, expected, actual)
42	}
43}
44
45func compareClientHelloFields(t *testing.T, fieldName string, expected, actual *ClientHelloMsg) {
46	rExpected := reflect.ValueOf(expected)
47	if rExpected.Kind() != reflect.Ptr || rExpected.Elem().Kind() != reflect.Struct {
48		t.Errorf("Error using reflect to compare Hello fields")
49	}
50	rActual := reflect.ValueOf(actual)
51	if rActual.Kind() != reflect.Ptr || rActual.Elem().Kind() != reflect.Struct {
52		t.Errorf("Error using reflect to compare Hello fields")
53	}
54
55	rExpected = rExpected.Elem()
56	rActual = rActual.Elem()
57
58	fExpected := rExpected.FieldByName(fieldName)
59	fActual := rActual.FieldByName(fieldName)
60	if !(fExpected.IsValid() && fActual.IsValid()) {
61		t.Errorf("Error using reflect to lookup Hello field name: %v", fieldName)
62	}
63
64	if fExpected.Kind() == reflect.Slice {
65		sExpected := fExpected.Slice(0, fExpected.Len())
66		sActual := fActual.Slice(0, fActual.Len())
67
68		if sExpected.Len() != sActual.Len() {
69			t.Errorf("%v fields slice length not equal, expected: %v, got: %v", fieldName, fExpected, fActual)
70		}
71
72		for i := 0; i < sExpected.Len(); i++ {
73			assertEquality(t, fieldName, sExpected.Index(i).Interface(), sActual.Index(i).Interface())
74		}
75	} else {
76		assertEquality(t, fieldName, fExpected.Interface(), fActual.Interface())
77	}
78}
79
80func checkUTLSExtensionsEquality(t *testing.T, expected, actual TLSExtension) {
81	if expectedGrease, ok := expected.(*UtlsGREASEExtension); ok {
82		if actualGrease, ok := actual.(*UtlsGREASEExtension); ok {
83			if bytes.Equal(expectedGrease.Body, actualGrease.Body) {
84				return
85			}
86		}
87	}
88
89	if expected.Len() != actual.Len() {
90		t.Errorf("extension types length not equal\nexpected: %#v\ngot: %#v", expected, actual)
91	}
92
93	actualBytes, err := ioutil.ReadAll(actual)
94	if err != nil {
95		t.Errorf("got error: %v; expected to succeed", err)
96	}
97	expectedBytes, err := ioutil.ReadAll(expected)
98	if err != nil {
99		t.Errorf("got error: %v; expected to succeed", err)
100	}
101
102	logInequality := func() {
103		t.Errorf("extensions not equal\nexpected: %#v\nbytes:%#x\ngot: %#v\nbytes: %#x", expected, expectedBytes, actual, actualBytes)
104	}
105
106	if !bytes.Equal(expectedBytes, actualBytes) {
107		// handle all the cases where GREASE or other factors can cause byte unalignment
108
109		// at this point concrete types must match
110		expectedType := reflect.TypeOf(expected)
111		actualType := reflect.TypeOf(actual)
112		if expectedType != actualType {
113			t.Errorf("extensions not equal\nexpected: %#v\nbytes:%#x\ngot: %#v\nbytes: %#x", expected, expectedBytes, actual, actualBytes)
114			return
115		}
116
117		switch expectedExtension := expected.(type) {
118		case *SupportedCurvesExtension:
119			actualExtension := expected.(*SupportedCurvesExtension)
120			for i, expectedCurve := range expectedExtension.Curves {
121				actualCurve := actualExtension.Curves[i]
122				if expectedCurve == actualCurve {
123					continue
124				}
125				if isGREASEUint16(uint16(expectedCurve)) && isGREASEUint16(uint16(actualCurve)) {
126					continue
127				}
128				logInequality()
129				return
130			}
131		case *KeyShareExtension:
132			actualExtension := expected.(*KeyShareExtension)
133			for i, expectedKeyShare := range expectedExtension.KeyShares {
134				actualKeyShare := actualExtension.KeyShares[i]
135				// KeyShare data is unique per connection
136				if actualKeyShare.Group == expectedKeyShare.Group {
137					continue
138				}
139				if isGREASEUint16(uint16(expectedKeyShare.Group)) && isGREASEUint16(uint16(actualKeyShare.Group)) {
140					continue
141				}
142				logInequality()
143				return
144			}
145		case *SupportedVersionsExtension:
146			actualExtension := expected.(*SupportedVersionsExtension)
147			for i, expectedVersion := range expectedExtension.Versions {
148				actualVersion := actualExtension.Versions[i]
149				if isGREASEUint16(expectedVersion) && isGREASEUint16(actualVersion) || actualVersion == expectedVersion {
150					continue
151				}
152				logInequality()
153				return
154			}
155		default:
156			logInequality()
157			return
158		}
159	}
160}
161
162// Conn.vers is sometimes left to zero which is unacceptable to uTLS' SetTLSVers
163// https://github.com/refraction-networking/utls/blob/f7e7360167ed2903ef12898634512b66f8c3aad0/u_conn.go#L564-L566
164// https://github.com/refraction-networking/utls/blob/f7e7360167ed2903ef12898634512b66f8c3aad0/conn.go#L945-L948
165func createMinTLSVersion(vers uint16) uint16 {
166	if vers == 0 {
167		return VersionTLS10
168	}
169	return vers
170}
171
172// prependRecordHeader prepends a record header to a handshake messsage
173// if attempting to mimic an existing connection the minTLSVersion can be found
174// in the Conn.vers field
175func prependRecordHeader(hello []byte, minTLSVersion uint16) []byte {
176	l := len(hello)
177	if minTLSVersion == 0 {
178		minTLSVersion = VersionTLS10
179	}
180	header := []byte{
181		uint8(recordTypeHandshake),                                    // type
182		uint8(minTLSVersion >> 8 & 0xff), uint8(minTLSVersion & 0xff), // record version is the minimum supported
183		uint8(l >> 8 & 0xff), uint8(l & 0xff), // length
184	}
185	return append(header, hello...)
186}
187
188func checkUTLSFingerPrintClientHello(t *testing.T, clientHelloID ClientHelloID, serverName string) {
189	uconn := UClient(&net.TCPConn{}, &Config{ServerName: serverName}, clientHelloID)
190	if err := uconn.BuildHandshakeState(); err != nil {
191		t.Errorf("got error: %v; expected to succeed", err)
192	}
193
194	generatedUConn := UClient(&net.TCPConn{}, &Config{ServerName: "foobar"}, HelloCustom)
195	fingerprinter := &Fingerprinter{}
196	minTLSVers := createMinTLSVersion(uconn.vers)
197	generatedSpec, err := fingerprinter.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers))
198	if err != nil {
199		t.Errorf("got error: %v; expected to succeed", err)
200	}
201	if err := generatedUConn.ApplyPreset(generatedSpec); err != nil {
202		t.Errorf("got error: %v; expected to succeed", err)
203	}
204	if err := generatedUConn.BuildHandshakeState(); err != nil {
205		t.Errorf("got error: %v; expected to succeed", err)
206	}
207
208	if len(uconn.HandshakeState.Hello.Raw) != len(generatedUConn.HandshakeState.Hello.Raw) {
209		t.Errorf("UConn from fingerprint has %d length, should have %d", len(generatedUConn.HandshakeState.Hello.Raw), len(uconn.HandshakeState.Hello.Raw))
210	}
211
212	// We can't effectively check the extensions on randomized client hello ids
213	if !(clientHelloID == HelloRandomized || clientHelloID == HelloRandomizedALPN || clientHelloID == HelloRandomizedNoALPN) {
214		for i, originalExtension := range uconn.Extensions {
215			if _, ok := originalExtension.(*UtlsPaddingExtension); ok {
216				// We can't really compare padding extensions in this way
217				continue
218			}
219
220			generatedExtension := generatedUConn.Extensions[i]
221			checkUTLSExtensionsEquality(t, originalExtension, generatedExtension)
222		}
223	}
224
225	fieldsToTest := []string{
226		"Vers", "CipherSuites", "CompressionMethods", "NextProtoNeg", "ServerName", "OcspStapling", "Scts", "SupportedCurves",
227		"SupportedPoints", "TicketSupported", "SupportedSignatureAlgorithms", "SecureRenegotiation", "SecureRenegotiationSupported", "AlpnProtocols",
228		"SupportedSignatureAlgorithmsCert", "SupportedVersions", "KeyShares", "EarlyData", "PskModes", "PskIdentities", "PskBinders",
229	}
230
231	for _, field := range fieldsToTest {
232		compareClientHelloFields(t, field, uconn.HandshakeState.Hello, generatedUConn.HandshakeState.Hello)
233	}
234}
235
236func TestUTLSFingerprintClientHello(t *testing.T) {
237	clientHellosToTest := []ClientHelloID{
238		HelloChrome_58, HelloChrome_70, HelloChrome_83, HelloFirefox_55, HelloFirefox_63, HelloIOS_11_1, HelloIOS_12_1, HelloRandomized, HelloRandomizedALPN, HelloRandomizedNoALPN}
239
240	serverNames := []string{"foobar"}
241
242	for _, clientHello := range clientHellosToTest {
243		for _, serverName := range serverNames {
244			t.Logf("checking fingerprint generated client hello spec against %v and server name: %v", clientHello, serverName)
245			checkUTLSFingerPrintClientHello(t, clientHello, "foobar")
246		}
247	}
248}
249
250func TestUTLSFingerprintClientHelloBluntMimicry(t *testing.T) {
251	serverName := "foobar"
252	var extensionId uint16 = 0xfeed
253	extensionData := []byte("random data")
254
255	specWithGeneric, err := utlsIdToSpec(HelloChrome_Auto)
256	if err != nil {
257		t.Errorf("got error: %v; expected to succeed", err)
258	}
259	specWithGeneric.Extensions = append(specWithGeneric.Extensions, &GenericExtension{extensionId, extensionData})
260
261	uconn := UClient(&net.TCPConn{}, &Config{ServerName: serverName}, HelloCustom)
262
263	if err := uconn.ApplyPreset(&specWithGeneric); err != nil {
264		t.Errorf("got error: %v; expected to succeed", err)
265	}
266	if err := uconn.BuildHandshakeState(); err != nil {
267		t.Errorf("got error: %v; expected to succeed", err)
268	}
269
270	f := &Fingerprinter{}
271	minTLSVers := createMinTLSVersion(uconn.vers)
272	_, err = f.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers))
273	if err == nil {
274		t.Errorf("expected error generating spec from client hello with GenericExtension")
275	}
276
277	f = &Fingerprinter{AllowBluntMimicry: true}
278	generatedSpec, err := f.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers))
279	if err != nil {
280		t.Errorf("got error: %v; expected to succeed", err)
281	}
282
283	for _, ext := range generatedSpec.Extensions {
284		if genericExtension, ok := (ext).(*GenericExtension); ok {
285			if genericExtension.Id == extensionId && bytes.Equal(genericExtension.Data, extensionData) {
286				return
287			}
288		}
289	}
290	t.Errorf("generated ClientHelloSpec with BluntMimicry did not correctly carry over generic extension")
291}
292
293func TestUTLSFingerprintClientHelloAlwaysAddPadding(t *testing.T) {
294	serverName := "foobar"
295
296	specWithoutPadding, err := utlsIdToSpec(HelloIOS_12_1)
297	if err != nil {
298		t.Errorf("got error: %v; expected to succeed", err)
299	}
300	specWithPadding, err := utlsIdToSpec(HelloChrome_83)
301	if err != nil {
302		t.Errorf("got error: %v; expected to succeed", err)
303	}
304
305	uconnWithoutPadding := UClient(&net.TCPConn{}, &Config{ServerName: serverName}, HelloCustom)
306	uconnWithPadding := UClient(&net.TCPConn{}, &Config{ServerName: serverName}, HelloCustom)
307
308	if err := uconnWithoutPadding.ApplyPreset(&specWithoutPadding); err != nil {
309		t.Errorf("got error: %v; expected to succeed", err)
310	}
311	if err := uconnWithoutPadding.BuildHandshakeState(); err != nil {
312		t.Errorf("got error: %v; expected to succeed", err)
313	}
314
315	if err := uconnWithPadding.ApplyPreset(&specWithPadding); err != nil {
316		t.Errorf("got error: %v; expected to succeed", err)
317	}
318	if err := uconnWithPadding.BuildHandshakeState(); err != nil {
319		t.Errorf("got error: %v; expected to succeed", err)
320	}
321
322	f := &Fingerprinter{}
323	minTLSVersWithoutPadding := createMinTLSVersion(uconnWithoutPadding.vers)
324	fingerprintedWithoutPadding, err := f.FingerprintClientHello(prependRecordHeader(uconnWithoutPadding.HandshakeState.Hello.Raw, minTLSVersWithoutPadding))
325	if err != nil {
326		t.Errorf("got error: %v; expected to succeed", err)
327	}
328
329	for _, ext := range fingerprintedWithoutPadding.Extensions {
330		if _, ok := ext.(*UtlsPaddingExtension); ok {
331			t.Errorf("padding extension should not be present on fingerprinted ClientHelloSpec without AlwaysAddPadding set")
332			break
333		}
334	}
335
336	f = &Fingerprinter{AlwaysAddPadding: true}
337	generatedSpec, err := f.FingerprintClientHello(prependRecordHeader(uconnWithoutPadding.HandshakeState.Hello.Raw, minTLSVersWithoutPadding))
338	if err != nil {
339		t.Errorf("got error: %v; expected to succeed", err)
340	}
341
342	hasPadding := false
343	for _, ext := range generatedSpec.Extensions {
344		if _, ok := ext.(*UtlsPaddingExtension); ok {
345			hasPadding = true
346			break
347		}
348	}
349	if !hasPadding {
350		t.Errorf("expected padding extension on fingerprinted ClientHelloSpec with AlwaysAddPadding set")
351	}
352
353	f = &Fingerprinter{AlwaysAddPadding: true}
354	minTLSVersWithPadding := createMinTLSVersion(uconnWithPadding.vers)
355	generatedSpec, err = f.FingerprintClientHello(prependRecordHeader(uconnWithPadding.HandshakeState.Hello.Raw, minTLSVersWithPadding))
356	if err != nil {
357		t.Errorf("got error: %v; expected to succeed", err)
358	}
359
360	hasPadding = false
361	for _, ext := range generatedSpec.Extensions {
362		if _, ok := ext.(*UtlsPaddingExtension); ok {
363			if hasPadding {
364				t.Errorf("found double padding extension on fingerprinted ClientHelloSpec with AlwaysAddPadding set")
365			}
366
367			hasPadding = true
368		}
369	}
370	if !hasPadding {
371		t.Errorf("expected padding extension on fingerprinted ClientHelloSpec with AlwaysAddPadding set")
372	}
373}
374
375func TestUTLSFingerprintClientHelloKeepPSK(t *testing.T) {
376	// TLSv1.3 Record Layer: Handshake Protocol: Client Hello
377	//     Content Type: Handshake (22)
378	//     Version: TLS 1.0 (0x0301)
379	//     Length: 576
380	// Handshake Protocol: Client Hello
381	// 		Handshake Type: Client Hello (1)
382	// 		Length: 572
383	// 		Version: TLS 1.2 (0x0303)
384	// 		Random: 5cef5aa9122008e37f0f74d717cd4ae0f745daba4292e6fb…
385	// 		Session ID Length: 32
386	// 		Session ID: 8c4aa23444084eeb70097efe0b8f6e3a56c717abd67505c9…
387	// 		Cipher Suites Length: 32
388	// 		Cipher Suites (16 suites)
389	// 		Compression Methods Length: 1
390	// 		Compression Methods (1 method)
391	// 		Extensions Length: 467
392	// 		Extension: Reserved (GREASE) (len=0)
393	// 				Type: Reserved (GREASE) (14906)
394	// 				Length: 0
395	// 				Data: <MISSING>
396	// 		Extension: server_name (len=22)
397	// 				Type: server_name (0)
398	// 				Length: 22
399	// 				Server Name Indication extension
400	// 						Server Name list length: 20
401	// 						Server Name Type: host_name (0)
402	// 						Server Name length: 17
403	// 						Server Name: edgeapi.slack.com
404	// 		Extension: extended_master_secret (len=0)
405	// 				Type: extended_master_secret (23)
406	// 				Length: 0
407	// 		Extension: renegotiation_info (len=1)
408	// 				Type: renegotiation_info (65281)
409	// 				Length: 1
410	// 				Renegotiation Info extension
411	// 						Renegotiation info extension length: 0
412	// 		Extension: supported_groups (len=10)
413	// 				Type: supported_groups (10)
414	// 				Length: 10
415	// 				Supported Groups List Length: 8
416	// 				Supported Groups (4 groups)
417	// 						Supported Group: Reserved (GREASE) (0xdada)
418	// 						Supported Group: x25519 (0x001d)
419	// 						Supported Group: secp256r1 (0x0017)
420	// 						Supported Group: secp384r1 (0x0018)
421	// 		Extension: ec_point_formats (len=2)
422	// 				Type: ec_point_formats (11)
423	// 				Length: 2
424	// 				EC point formats Length: 1
425	// 				Elliptic curves point formats (1)
426	// 		Extension: session_ticket (len=0)
427	// 				Type: session_ticket (35)
428	// 				Length: 0
429	// 				Data (0 bytes)
430	// 		Extension: application_layer_protocol_negotiation (len=14)
431	// 				Type: application_layer_protocol_negotiation (16)
432	// 				Length: 14
433	// 				ALPN Extension Length: 12
434	// 				ALPN Protocol
435	// 						ALPN string length: 2
436	// 						ALPN Next Protocol: h2
437	// 						ALPN string length: 8
438	// 						ALPN Next Protocol: http/1.1
439	// 		Extension: status_request (len=5)
440	// 				Type: status_request (5)
441	// 				Length: 5
442	// 				Certificate Status Type: OCSP (1)
443	// 				Responder ID list Length: 0
444	// 				Request Extensions Length: 0
445	// 		Extension: signature_algorithms (len=18)
446	// 				Type: signature_algorithms (13)
447	// 				Length: 18
448	// 				Signature Hash Algorithms Length: 16
449	// 				Signature Hash Algorithms (8 algorithms)
450	// 		Extension: signed_certificate_timestamp (len=0)
451	// 				Type: signed_certificate_timestamp (18)
452	// 				Length: 0
453	// 		Extension: key_share (len=43)
454	// 				Type: key_share (51)
455	// 				Length: 43
456	// 				Key Share extension
457	// 						Client Key Share Length: 41
458	// 						Key Share Entry: Group: Reserved (GREASE), Key Exchange length: 1
459	// 								Group: Reserved (GREASE) (56026)
460	// 								Key Exchange Length: 1
461	// 								Key Exchange: 00
462	// 						Key Share Entry: Group: x25519, Key Exchange length: 32
463	// 								Group: x25519 (29)
464	// 								Key Exchange Length: 32
465	// 								Key Exchange: e35e636d4e2dcd5f39309170285dab92dbe81fefe4926826…
466	// 		Extension: psk_key_exchange_modes (len=2)
467	// 				Type: psk_key_exchange_modes (45)
468	// 				Length: 2
469	// 				PSK Key Exchange Modes Length: 1
470	// 				PSK Key Exchange Mode: PSK with (EC)DHE key establishment (psk_dhe_ke) (1)
471	// 		Extension: supported_versions (len=11)
472	// 				Type: supported_versions (43)
473	// 				Length: 11
474	// 				Supported Versions length: 10
475	// 				Supported Version: Unknown (0x2a2a)
476	// 				Supported Version: TLS 1.3 (0x0304)
477	// 				Supported Version: TLS 1.2 (0x0303)
478	// 				Supported Version: TLS 1.1 (0x0302)
479	// 				Supported Version: TLS 1.0 (0x0301)
480	// 		Extension: compress_certificate (len=3)
481	// 				Type: compress_certificate (27)
482	// 				Length: 3
483	// 				Algorithms Length: 2
484	// 				Algorithm: brotli (2)
485	// 		Extension: Reserved (GREASE) (len=1)
486	// 				Type: Reserved (GREASE) (19018)
487	// 				Length: 1
488	// 				Data: 00
489	// 		Extension: pre_shared_key (len=267)
490	// 				Type: pre_shared_key (41)
491	// 				Length: 267
492	// 				Pre-Shared Key extension
493
494	byteString := []byte("16030102400100023c03035cef5aa9122008e37f0f74d717cd4ae0f745daba4292e6fbca3cd5bf9123498f208c4aa23444084eeb70097efe0b8f6e3a56c717abd67505c950aab314de59bd8f00204a4a130113021303c02bc02fc02cc030cca9cca8c013c014009c009d002f0035010001d33a3a0000000000160014000011656467656170692e736c61636b2e636f6d00170000ff01000100000a000a0008dada001d00170018000b00020100002300000010000e000c02683208687474702f312e31000500050100000000000d0012001004030804040105030805050108060601001200000033002b0029dada000100001d0020e35e636d4e2dcd5f39309170285dab92dbe81fefe4926826cec1ef881321687e002d00020101002b000b0a2a2a0304030303020301001b00030200024a4a0001000029010b00e600e017fab59672c1966ae78fc4dacd7efb42e735de956e3f96d342bb8e63a5233ce21c92d6d75036601d74ccbc3ca0085f3ac2ebbd83da13501ac3c6d612bcb453fb206a39a8112d768bea1976d7c14e6de9aa0ee70ea732554d3c57d1a993f1044a46c1fb371811039ef30582cacf41bd497121d67793b8ee4df7a60d525f7df052fd66cda7f141bb553d9253816752d923ac7c71426179db4f26a7d42f0d65a2dd2dbaafb86fa17b2da23fd57c5064c76551cfda86304051231e4da9e697fedbcb5ae8cb2f6cb92f71164acf2edff5bccc1266cd648a53cc46262eabf40727bcb6958a3d1300212083e99d791672d39919dcb387f2fa7aeee938ec32ecf4b861306f7df4f9a8a746")
495
496	helloBytes := make([]byte, hex.DecodedLen(len(byteString)))
497	_, err := hex.Decode(helloBytes, byteString)
498	if err != nil {
499		t.Errorf("got error: %v; expected to succeed", err)
500		return
501	}
502
503	f := &Fingerprinter{}
504	_, err = f.FingerprintClientHello(helloBytes)
505	if err == nil {
506		t.Errorf("expected error generating spec from client hello with PSK")
507	}
508
509	f = &Fingerprinter{KeepPSK: true}
510	generatedSpec, err := f.FingerprintClientHello(helloBytes)
511	if err != nil {
512		t.Errorf("got error: %v; expected to succeed", err)
513		return
514	}
515
516	for _, ext := range generatedSpec.Extensions {
517		if genericExtension, ok := (ext).(*GenericExtension); ok {
518			if genericExtension.Id == extensionPreSharedKey {
519				return
520			}
521		}
522	}
523	t.Errorf("generated ClientHelloSpec with KeepPSK does not include preshared key extension")
524}
525
526func TestUTLSHandshakeClientFingerprintedSpecFromChrome_58(t *testing.T) {
527	helloID := HelloChrome_58
528	serverName := "foobar"
529	originalConfig := getUTLSTestConfig()
530	originalConfig.ServerName = serverName
531	uconn := UClient(&net.TCPConn{}, originalConfig, helloID)
532	if err := uconn.BuildHandshakeState(); err != nil {
533		t.Errorf("got error: %v; expected to succeed", err)
534	}
535
536	f := &Fingerprinter{}
537	minTLSVers := createMinTLSVersion(uconn.vers)
538	generatedSpec, err := f.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers))
539	if err != nil {
540		t.Errorf("got error: %v; expected to succeed", err)
541	}
542
543	hello := &helloSpec{
544		name: fmt.Sprintf("%v-fingerprinted", helloID.Str()),
545		spec: generatedSpec,
546	}
547
548	newConfig := getUTLSTestConfig()
549	newConfig.ServerName = serverName
550
551	opensslCipherName := "ECDHE-RSA-AES128-GCM-SHA256"
552	test := &clientTest{
553		name:   "UTLS-" + opensslCipherName + "-" + hello.helloName(),
554		args:   []string{"-cipher", opensslCipherName},
555		config: newConfig,
556	}
557
558	runUTLSClientTestTLS12(t, test, hello)
559}
560
561func TestUTLSHandshakeClientFingerprintedSpecFromChrome_70(t *testing.T) {
562	helloID := HelloChrome_70
563	serverName := "foobar"
564	originalConfig := getUTLSTestConfig()
565	originalConfig.ServerName = serverName
566
567	uconn := UClient(&net.TCPConn{}, originalConfig, helloID)
568	if err := uconn.BuildHandshakeState(); err != nil {
569		t.Errorf("got error: %v; expected to succeed", err)
570	}
571
572	f := &Fingerprinter{}
573	minTLSVers := createMinTLSVersion(uconn.vers)
574	generatedSpec, err := f.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers))
575	if err != nil {
576		t.Errorf("got error: %v; expected to succeed", err)
577	}
578
579	hello := &helloSpec{
580		name: fmt.Sprintf("%v-fingerprinted", helloID.Str()),
581		spec: generatedSpec,
582	}
583
584	newConfig := getUTLSTestConfig()
585	newConfig.ServerName = serverName
586
587	opensslCipherName := "TLS_AES_128_GCM_SHA256"
588	test := &clientTest{
589		name:   "UTLS-" + opensslCipherName + "-" + hello.helloName(),
590		args:   []string{"-ciphersuites", opensslCipherName},
591		config: newConfig,
592	}
593
594	runUTLSClientTestTLS13(t, test, hello)
595}
596
597func TestUTLSHandshakeClientFingerprintedSpecFromRaw(t *testing.T) {
598	// TLSv1.3 Record Layer: Handshake Protocol: Client Hello
599	//     Content Type: Handshake (22)
600	//     Version: TLS 1.0 (0x0301)
601	//     Length: 512
602	// Handshake Protocol: Client Hello
603	//     Handshake Type: Client Hello (1)
604	//     Length: 508
605	//     Version: TLS 1.2 (0x0303)
606	//     Random: 7fd76fa530c24816ea9e4a6cf2e939f2350b9486a7bac58e…
607	//     Session ID Length: 32
608	//     Session ID: d9b01fc4f4b6fe14fe9ce652442d66588d982cb25913d866…
609	//     Cipher Suites Length: 36
610	//     Cipher Suites (18 suites)
611	//         Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
612	//         Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
613	//         Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
614	//         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
615	//         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
616	//         Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
617	//         Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
618	//         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
619	//         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
620	//         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
621	//         Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
622	//         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
623	//         Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
624	//         Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
625	//         Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
626	//         Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
627	//         Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
628	//         Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
629	//     Compression Methods Length: 1
630	//     Compression Methods (1 method)
631	//     Extensions Length: 399
632	//     Extension: server_name (len=34)
633	//         Type: server_name (0)
634	//         Length: 34
635	//         Server Name Indication extension
636	//     Extension: extended_master_secret (len=0)
637	//         Type: extended_master_secret (23)
638	//         Length: 0
639	//     Extension: renegotiation_info (len=1)
640	//         Type: renegotiation_info (65281)
641	//         Length: 1
642	//         Renegotiation Info extension
643	//     Extension: supported_groups (len=14)
644	//         Type: supported_groups (10)
645	//         Length: 14
646	//         Supported Groups List Length: 12
647	//         Supported Groups (6 groups)
648	//     Extension: ec_point_formats (len=2)
649	//         Type: ec_point_formats (11)
650	//         Length: 2
651	//         EC point formats Length: 1
652	//         Elliptic curves point formats (1)
653	//     Extension: application_layer_protocol_negotiation (len=14)
654	//         Type: application_layer_protocol_negotiation (16)
655	//         Length: 14
656	//         ALPN Extension Length: 12
657	//         ALPN Protocol
658	//     Extension: status_request (len=5)
659	//         Type: status_request (5)
660	//         Length: 5
661	//         Certificate Status Type: OCSP (1)
662	//         Responder ID list Length: 0
663	//         Request Extensions Length: 0
664	//     Extension: key_share (len=107)
665	//         Type: key_share (51)
666	//         Length: 107
667	//         Key Share extension
668	//     Extension: supported_versions (len=5)
669	//         Type: supported_versions (43)
670	//         Length: 5
671	//         Supported Versions length: 4
672	//         Supported Version: TLS 1.3 (0x0304)
673	//         Supported Version: TLS 1.2 (0x0303)
674	//     Extension: signature_algorithms (len=24)
675	//         Type: signature_algorithms (13)
676	//         Length: 24
677	//         Signature Hash Algorithms Length: 22
678	//         Signature Hash Algorithms (11 algorithms)
679	//     Extension: record_size_limit (len=2)
680	//         Type: record_size_limit (28)
681	//         Length: 2
682	//         Record Size Limit: 16385
683	//     Extension: padding (len=143)
684	//         Type: padding (21)
685	//         Length: 143
686	//         Padding Data: 000000000000000000000000000000000000000000000000…
687	byteString := []byte("1603010200010001fc03037fd76fa530c24816ea9e4a6cf2e939f2350b9486a7bac58ece5753767fb6112420d9b01fc4f4b6fe14fe9ce652442d66588d982cb25913d866348bde54d3899abe0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f0035000a0100018f00000022002000001d70656f706c652d70612e636c69656e7473362e676f6f676c652e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b000201000010000e000c02683208687474702f312e310005000501000000000033006b0069001d002065e566ff33dfbeb012e3b13b87d75612bd0fbc3963673df90afed533dccc9b5400170041047fcc2666d04c31272a2e39905c771a89edf5a71dae301ec2fa0e7bc4d0e06580a0d36324e3dc4f29e200a8905badd11c00daf11588977bf501597dac5fdc55bf002b00050403040303000d0018001604030503060308040805080604010501060102030201001c000240010015008f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
688	helloBytes := make([]byte, hex.DecodedLen(len(byteString)))
689	_, err := hex.Decode(helloBytes, byteString)
690	if err != nil {
691		t.Errorf("got error: %v; expected to succeed", err)
692		return
693	}
694
695	f := &Fingerprinter{}
696	generatedSpec, err := f.FingerprintClientHello(helloBytes)
697	if err != nil {
698		t.Errorf("got error: %v; expected to succeed", err)
699	}
700
701	hello := &helloSpec{
702		name: "raw-capture-fingerprinted",
703		spec: generatedSpec,
704	}
705
706	config := getUTLSTestConfig()
707
708	opensslCipherName := "TLS_AES_128_GCM_SHA256"
709	test := &clientTest{
710		name:   "UTLS-" + opensslCipherName + "-" + hello.helloName(),
711		args:   []string{"-ciphersuites", opensslCipherName},
712		config: config,
713	}
714
715	runUTLSClientTestTLS13(t, test, hello)
716}
717