github.com/3andne/restls-client-go@v0.1.6/u_fingerprinter_test.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 "bytes" 9 "encoding/hex" 10 "fmt" 11 "io/ioutil" 12 "net" 13 "reflect" 14 "testing" 15 ) 16 17 func 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 45 func compareClientHelloFields(t *testing.T, fieldName string, expected, actual *PubClientHelloMsg) { 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 80 func 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 165 func 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 175 func 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 188 func 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 236 func 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 250 func 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 293 func 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 375 func 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 generatedSpec, err := f.FingerprintClientHello(helloBytes) 505 if err != nil { 506 t.Errorf("got error: %v; expected to succeed", err) 507 return 508 } 509 510 for _, ext := range generatedSpec.Extensions { 511 if _, ok := (ext).(*FakePreSharedKeyExtension); ok { 512 return 513 } 514 } 515 t.Errorf("generated ClientHelloSpec with KeepPSK does not include preshared key extension") 516 } 517 518 func TestUTLSHandshakeClientFingerprintedSpecFromChrome_58(t *testing.T) { 519 helloID := HelloChrome_58 520 serverName := "foobar" 521 originalConfig := getUTLSTestConfig() 522 originalConfig.ServerName = serverName 523 uconn := UClient(&net.TCPConn{}, originalConfig, helloID) 524 if err := uconn.BuildHandshakeState(); err != nil { 525 t.Errorf("got error: %v; expected to succeed", err) 526 } 527 528 f := &Fingerprinter{} 529 minTLSVers := createMinTLSVersion(uconn.vers) 530 generatedSpec, err := f.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers)) 531 if err != nil { 532 t.Errorf("got error: %v; expected to succeed", err) 533 } 534 535 hello := &helloSpec{ 536 name: fmt.Sprintf("%v-fingerprinted", helloID.Str()), 537 spec: generatedSpec, 538 } 539 540 newConfig := getUTLSTestConfig() 541 newConfig.ServerName = serverName 542 543 opensslCipherName := "ECDHE-RSA-AES128-GCM-SHA256" 544 test := &clientTest{ 545 name: "UTLS-" + opensslCipherName + "-" + hello.helloName(), 546 args: []string{"-cipher", opensslCipherName}, 547 config: newConfig, 548 } 549 550 runUTLSClientTestTLS12(t, test, hello) 551 } 552 553 func TestUTLSHandshakeClientFingerprintedSpecFromChrome_70(t *testing.T) { 554 helloID := HelloChrome_70 555 serverName := "foobar" 556 originalConfig := getUTLSTestConfig() 557 originalConfig.ServerName = serverName 558 559 uconn := UClient(&net.TCPConn{}, originalConfig, helloID) 560 if err := uconn.BuildHandshakeState(); err != nil { 561 t.Errorf("got error: %v; expected to succeed", err) 562 } 563 564 f := &Fingerprinter{} 565 minTLSVers := createMinTLSVersion(uconn.vers) 566 generatedSpec, err := f.FingerprintClientHello(prependRecordHeader(uconn.HandshakeState.Hello.Raw, minTLSVers)) 567 if err != nil { 568 t.Errorf("got error: %v; expected to succeed", err) 569 } 570 571 hello := &helloSpec{ 572 name: fmt.Sprintf("%v-fingerprinted", helloID.Str()), 573 spec: generatedSpec, 574 } 575 576 newConfig := getUTLSTestConfig() 577 newConfig.ServerName = serverName 578 579 opensslCipherName := "TLS_AES_128_GCM_SHA256" 580 test := &clientTest{ 581 name: "UTLS-" + opensslCipherName + "-" + hello.helloName(), 582 args: []string{"-ciphersuites", opensslCipherName}, 583 config: newConfig, 584 } 585 586 runUTLSClientTestTLS13(t, test, hello) 587 } 588 589 func TestUTLSHandshakeClientFingerprintedSpecFromRaw(t *testing.T) { 590 // TLSv1.3 Record Layer: Handshake Protocol: Client Hello 591 // Content Type: Handshake (22) 592 // Version: TLS 1.0 (0x0301) 593 // Length: 512 594 // Handshake Protocol: Client Hello 595 // Handshake Type: Client Hello (1) 596 // Length: 508 597 // Version: TLS 1.2 (0x0303) 598 // Random: 7fd76fa530c24816ea9e4a6cf2e939f2350b9486a7bac58e… 599 // Session ID Length: 32 600 // Session ID: d9b01fc4f4b6fe14fe9ce652442d66588d982cb25913d866… 601 // Cipher Suites Length: 36 602 // Cipher Suites (18 suites) 603 // Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301) 604 // Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303) 605 // Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302) 606 // Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) 607 // Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) 608 // Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9) 609 // Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8) 610 // Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) 611 // Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) 612 // Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a) 613 // Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009) 614 // Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013) 615 // Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014) 616 // Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c) 617 // Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d) 618 // Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f) 619 // Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035) 620 // Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a) 621 // Compression Methods Length: 1 622 // Compression Methods (1 method) 623 // Extensions Length: 399 624 // Extension: server_name (len=34) 625 // Type: server_name (0) 626 // Length: 34 627 // Server Name Indication extension 628 // Extension: extended_master_secret (len=0) 629 // Type: extended_master_secret (23) 630 // Length: 0 631 // Extension: renegotiation_info (len=1) 632 // Type: renegotiation_info (65281) 633 // Length: 1 634 // Renegotiation Info extension 635 // Extension: supported_groups (len=14) 636 // Type: supported_groups (10) 637 // Length: 14 638 // Supported Groups List Length: 12 639 // Supported Groups (6 groups) 640 // Extension: ec_point_formats (len=2) 641 // Type: ec_point_formats (11) 642 // Length: 2 643 // EC point formats Length: 1 644 // Elliptic curves point formats (1) 645 // Extension: application_layer_protocol_negotiation (len=14) 646 // Type: application_layer_protocol_negotiation (16) 647 // Length: 14 648 // ALPN Extension Length: 12 649 // ALPN Protocol 650 // Extension: status_request (len=5) 651 // Type: status_request (5) 652 // Length: 5 653 // Certificate Status Type: OCSP (1) 654 // Responder ID list Length: 0 655 // Request Extensions Length: 0 656 // Extension: key_share (len=107) 657 // Type: key_share (51) 658 // Length: 107 659 // Key Share extension 660 // Extension: supported_versions (len=5) 661 // Type: supported_versions (43) 662 // Length: 5 663 // Supported Versions length: 4 664 // Supported Version: TLS 1.3 (0x0304) 665 // Supported Version: TLS 1.2 (0x0303) 666 // Extension: signature_algorithms (len=24) 667 // Type: signature_algorithms (13) 668 // Length: 24 669 // Signature Hash Algorithms Length: 22 670 // Signature Hash Algorithms (11 algorithms) 671 // Extension: record_size_limit (len=2) 672 // Type: record_size_limit (28) 673 // Length: 2 674 // Record Size Limit: 16385 675 // Extension: padding (len=143) 676 // Type: padding (21) 677 // Length: 143 678 // Padding Data: 000000000000000000000000000000000000000000000000… 679 byteString := []byte("1603010200010001fc03037fd76fa530c24816ea9e4a6cf2e939f2350b9486a7bac58ece5753767fb6112420d9b01fc4f4b6fe14fe9ce652442d66588d982cb25913d866348bde54d3899abe0024130113031302c02bc02fcca9cca8c02cc030c00ac009c013c014009c009d002f0035000a0100018f00000022002000001d70656f706c652d70612e636c69656e7473362e676f6f676c652e636f6d00170000ff01000100000a000e000c001d00170018001901000101000b000201000010000e000c02683208687474702f312e310005000501000000000033006b0069001d002065e566ff33dfbeb012e3b13b87d75612bd0fbc3963673df90afed533dccc9b5400170041047fcc2666d04c31272a2e39905c771a89edf5a71dae301ec2fa0e7bc4d0e06580a0d36324e3dc4f29e200a8905badd11c00daf11588977bf501597dac5fdc55bf002b00050403040303000d0018001604030503060308040805080604010501060102030201001c000240010015008f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") 680 helloBytes := make([]byte, hex.DecodedLen(len(byteString))) 681 _, err := hex.Decode(helloBytes, byteString) 682 if err != nil { 683 t.Errorf("got error: %v; expected to succeed", err) 684 return 685 } 686 687 f := &Fingerprinter{} 688 generatedSpec, err := f.FingerprintClientHello(helloBytes) 689 if err != nil { 690 t.Errorf("got error: %v; expected to succeed", err) 691 } 692 693 hello := &helloSpec{ 694 name: "raw-capture-fingerprinted", 695 spec: generatedSpec, 696 } 697 698 config := getUTLSTestConfig() 699 700 opensslCipherName := "TLS_AES_128_GCM_SHA256" 701 test := &clientTest{ 702 name: "UTLS-" + opensslCipherName + "-" + hello.helloName(), 703 args: []string{"-ciphersuites", opensslCipherName}, 704 config: config, 705 } 706 707 runUTLSClientTestTLS13(t, test, hello) 708 } 709 710 // FingerprintClientHello should work when the dump contains the client's greeting and subsequent frames. 711 // Lack of subsequent frames should not lead to inoperability of FingerprintClientHello. 712 func TestFingerprintDumpLargerThanExtensions(t *testing.T) { 713 // Dump of curl/7.74.0 with some test request https://tlsfingerprint.io/id/37695dd988f0c8b8 714 dump := "1603010200010001fc03032e763fe74cd8472de77d17eef1cf4cb9b18d0163196a69337d0d7c6c844a1b71202aef889ccf5bdef725185b7c0cc51a100311c7c3992b1d206beaef121a111cc5003e130213031301c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff010001750000000e000c0000096c6f63616c686f7374000b000403000102000a000c000a001d0017001e00190018337400000010000e000c02683208687474702f312e31001600000017000000310000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602002b00050403040303002d00020101003300260024001d00204f21193633f4a0c751143f0084941995cc6fb7cb87545f56f07877c99615f074001500be000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001403030001011703030045f621cd4a3c52c89e0d94c6f6a79d5863274af09696811cb73c433aa05ea5bb7a266cbc11cdbd18a553c9b4ba02c202ec709faabfdd9e9b76c1b2162dd8296cdbc9e6451742170303005ff37ae5fd6c2f240472c6248abb2a82dd2e634d4da4f67d0db94cf56eebe7e9e3766f6458f87c82bdd70a4d75e0f904c368a7c57beba6d76ea9d3f6d06e26cdf1dcb4c6fa2067f269268e91e94ade464efdb2e5f5cf2f7930faeb6f2a4a3bc2" 715 // shortDump := "1603010200010001fc03032e763fe74cd8472de77d17eef1cf4cb9b18d0163196a69337d0d7c6c844a1b71202aef889ccf5bdef725185b7c0cc51a100311c7c3992b1d206beaef121a111cc5003e130213031301c02cc030009fcca9cca8ccaac02bc02f009ec024c028006bc023c0270067c00ac0140039c009c0130033009d009c003d003c0035002f00ff010001750000000e000c0000096c6f63616c686f7374000b000403000102000a000c000a001d0017001e00190018337400000010000e000c02683208687474702f312e31001600000017000000310000000d002a0028040305030603080708080809080a080b080408050806040105010601030303010302040205020602002b00050403040303002d00020101003300260024001d00204f21193633f4a0c751143f0084941995cc6fb7cb87545f56f07877c99615f074001500be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 716 helloBytes, err := hex.DecodeString(dump) 717 if err != nil { 718 t.Error(err) 719 return 720 } 721 f := &Fingerprinter{ 722 AllowBluntMimicry: true, 723 } 724 clientHelloSpec, err := f.FingerprintClientHello(helloBytes) 725 if err != nil { 726 t.Errorf("got error: %v; expected to succeed", err) 727 } 728 if clientHelloSpec == nil { 729 t.Error("clientHelloSpec cannot be nil") 730 } 731 }